diff options
Diffstat (limited to 'drivers/gles3/storage/texture_storage.cpp')
| -rw-r--r-- | drivers/gles3/storage/texture_storage.cpp | 62 | 
1 files changed, 60 insertions, 2 deletions
diff --git a/drivers/gles3/storage/texture_storage.cpp b/drivers/gles3/storage/texture_storage.cpp index 524ff14cc9..076225adf4 100644 --- a/drivers/gles3/storage/texture_storage.cpp +++ b/drivers/gles3/storage/texture_storage.cpp @@ -790,6 +790,7 @@ Ref<Image> TextureStorage::texture_2d_get(RID p_texture) const {  #ifdef GLES_OVER_GL  	// OpenGL 3.3 supports glGetTexImage which is faster and simpler than glReadPixels. +	// It also allows for reading compressed textures, mipmaps, and more formats.  	Vector<uint8_t> data;  	int data_size = Image::get_image_data_size(texture->alloc_width, texture->alloc_height, texture->real_format, texture->mipmaps > 1); @@ -826,8 +827,65 @@ Ref<Image> TextureStorage::texture_2d_get(RID p_texture) const {  		image->convert(texture->format);  	}  #else -	// Support for Web and Mobile will come later. -	Ref<Image> image; + +	Vector<uint8_t> data; + +	// On web and mobile we always read an RGBA8 image with no mipmaps. +	int data_size = Image::get_image_data_size(texture->alloc_width, texture->alloc_height, Image::FORMAT_RGBA8, false); + +	data.resize(data_size * 2); //add some memory at the end, just in case for buggy drivers +	uint8_t *w = data.ptrw(); + +	GLuint temp_framebuffer; +	glGenFramebuffers(1, &temp_framebuffer); + +	GLuint temp_color_texture; +	glGenTextures(1, &temp_color_texture); + +	glBindFramebuffer(GL_FRAMEBUFFER, temp_framebuffer); + +	glBindTexture(GL_TEXTURE_2D, temp_color_texture); +	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture->alloc_width, texture->alloc_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + +	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); +	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); +	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, temp_color_texture, 0); + +	glDepthMask(GL_FALSE); +	glDisable(GL_DEPTH_TEST); +	glDisable(GL_CULL_FACE); +	glDisable(GL_BLEND); +	glDepthFunc(GL_LEQUAL); +	glColorMask(1, 1, 1, 1); +	glActiveTexture(GL_TEXTURE0); +	glBindTexture(GL_TEXTURE_2D, texture->tex_id); + +	glViewport(0, 0, texture->alloc_width, texture->alloc_height); +	glClearColor(0.0, 0.0, 0.0, 0.0); +	glClear(GL_COLOR_BUFFER_BIT); + +	CopyEffects::get_singleton()->copy_to_rect(Rect2i(0, 0, 1.0, 1.0)); + +	glReadPixels(0, 0, texture->alloc_width, texture->alloc_height, GL_RGBA, GL_UNSIGNED_BYTE, &w[0]); + +	glBindFramebuffer(GL_FRAMEBUFFER, 0); +	glDeleteTextures(1, &temp_color_texture); +	glDeleteFramebuffers(1, &temp_framebuffer); + +	data.resize(data_size); + +	ERR_FAIL_COND_V(data.size() == 0, Ref<Image>()); +	Ref<Image> image = Image::create_from_data(texture->width, texture->height, false, Image::FORMAT_RGBA8, data); +	ERR_FAIL_COND_V(image->is_empty(), Ref<Image>()); + +	if (texture->format != Image::FORMAT_RGBA8) { +		image->convert(texture->format); +	} + +	if (texture->mipmaps > 1) { +		image->generate_mipmaps(); +	} +  #endif  #ifdef TOOLS_ENABLED  |