Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1915)

Unified Diff: gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.cc

Issue 2776083002: enable fallback path (Closed)
Patch Set: use stream read Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.cc
diff --git a/gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.cc b/gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.cc
index 338772a23351f630855dd291b39525b7f0656d9b..16c54dd99d1c9f4f16e123aacdb2672a4048d44f 100644
--- a/gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.cc
+++ b/gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.cc
@@ -617,6 +617,180 @@ void DoCopyTexSubImage2D(const gpu::gles2::GLES2Decoder* decoder,
decoder->RestoreFramebufferBindings();
}
+// Convert RGBA/UNSIGNED_BYTE source to RGB/UNSIGNED_BYTE destination.
+void convertToRGB(const uint8_t* source,
+ uint8_t* destination,
+ unsigned pixelsPerRow) {
+ for (unsigned i = 0; i < pixelsPerRow; ++i) {
+ destination[0] = source[0];
+ destination[1] = source[1];
+ destination[2] = source[2];
+ source += 4;
+ destination += 3;
+ }
+}
+
+// Convert RGBA/UNSIGNED_BYTE source to RGB/FLOAT destination.
+void convertToRGBFloat(const uint8_t* source,
+ float* destination,
+ unsigned pixelsPerRow) {
+ const float scaleFactor = 1.0f / 255.0f;
+ for (unsigned i = 0; i < pixelsPerRow; ++i) {
+ destination[0] = source[0] * scaleFactor;
+ destination[1] = source[1] * scaleFactor;
+ destination[2] = source[2] * scaleFactor;
+ source += 4;
+ destination += 3;
+ }
+}
+
+// Prepare the image data to be uploaded to a texture in pixel unpack buffer.
+void prepareUnpackBuffer(GLuint buffer[2],
+ bool is_es,
+ GLenum format,
+ GLenum type,
+ GLsizei width,
+ GLsizei height) {
+ uint32_t pixel_num = width * height;
+ glBindBuffer(GL_PIXEL_PACK_BUFFER, buffer[0]);
+
+ // Result of glReadPixels with format == GL_RGB and type == GL_UNSIGNED_BYTE
+ // from read framebuffer in RGBA fromat is not correct on desktop core
+ // profile on both Linux Mesa and Linux NVIDIA. This may be a driver bug.
+ bool is_rgb_unsigned_byte = format == GL_RGB && type == GL_UNSIGNED_BYTE;
+ if ((!is_es && !is_rgb_unsigned_byte) ||
+ (format == GL_RGBA && type == GL_UNSIGNED_BYTE)) {
+ uint32_t bytes_per_group =
+ gpu::gles2::GLES2Util::ComputeImageGroupSize(format, type);
+ glBufferData(GL_PIXEL_PACK_BUFFER, pixel_num * bytes_per_group, 0,
+ GL_STATIC_READ);
+ glReadPixels(0, 0, width, height, format, type, 0);
+ glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer[0]);
+ return;
+ }
+
+ uint32_t bytes_per_group =
+ gpu::gles2::GLES2Util::ComputeImageGroupSize(GL_RGBA, GL_UNSIGNED_BYTE);
+ uint32_t buf_size = pixel_num * bytes_per_group;
+
+ if (format == GL_RGB && type == GL_FLOAT) {
+ glBufferData(GL_PIXEL_PACK_BUFFER, buf_size, 0, GL_STREAM_READ);
+ glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, 0);
+
+ glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
+ std::unique_ptr<uint8_t[]> pixels(new uint8_t[width * height * 4]);
+ glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels.get());
+
+ glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer[1]);
+ bytes_per_group =
+ gpu::gles2::GLES2Util::ComputeImageGroupSize(format, type);
+ buf_size = pixel_num * bytes_per_group;
+ /*
+ glBufferData(GL_PIXEL_UNPACK_BUFFER, buf_size, 0, GL_STATIC_DRAW);
+ void* data =
+ glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, buf_size, GL_MAP_WRITE_BIT);
+ convertToRGBFloat((uint8_t*)pixels, (float*)data, pixel_num);
+ glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
+ glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
+ */
+
+ std::unique_ptr<float[]> data(new float[width * height * 3]);
+ convertToRGBFloat(pixels.get(), data.get(), pixel_num);
+ glBufferData(GL_PIXEL_UNPACK_BUFFER, buf_size, data.get(), GL_STATIC_DRAW);
+ return;
+ }
+
+ if (format == GL_RGB && type == GL_UNSIGNED_BYTE) {
+ glBufferData(GL_PIXEL_PACK_BUFFER, buf_size, 0, GL_DYNAMIC_DRAW);
+ glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, 0);
+ void* pixels = glMapBufferRange(GL_PIXEL_PACK_BUFFER, 0, buf_size,
+ GL_MAP_READ_BIT | GL_MAP_WRITE_BIT);
+ void* data = pixels;
+ convertToRGB((uint8_t*)pixels, (uint8_t*)data, pixel_num);
+ glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
+ glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer[0]);
+ return;
+ }
+
+ NOTREACHED();
+}
+
+void DoReadbackAndTexImage(bool is_tex_image,
+ const gpu::gles2::GLES2Decoder* decoder,
+ GLenum source_target,
+ GLuint source_id,
+ GLint source_level,
+ GLenum dest_target,
+ GLuint dest_id,
+ GLint dest_level,
+ GLenum dest_internal_format,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLuint framebuffer) {
+ DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), source_target);
+ GLenum dest_binding_target =
+ gpu::gles2::GLES2Util::GLFaceTargetToTextureTarget(dest_target);
+ DCHECK(dest_binding_target == GL_TEXTURE_2D ||
+ dest_binding_target == GL_TEXTURE_CUBE_MAP);
+ DCHECK(source_level == 0 || decoder->GetFeatureInfo()->IsES3Capable());
+ if (BindFramebufferTexture2D(source_target, source_id, source_level,
+ framebuffer)) {
+ glBindTexture(dest_binding_target, dest_id);
+ glTexParameterf(dest_binding_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameterf(dest_binding_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexParameteri(dest_binding_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(dest_binding_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+
+ GLenum format = GL_RGBA;
+ GLenum type = GL_UNSIGNED_BYTE;
+ switch (dest_internal_format) {
+ case GL_RGB9_E5:
+ format = GL_RGB;
+ type = GL_FLOAT;
+ break;
+ case GL_SRGB_EXT:
+ case GL_SRGB8:
+ format = GL_RGB;
+ break;
+ case GL_RGB5_A1:
+ case GL_SRGB_ALPHA_EXT:
+ case GL_SRGB8_ALPHA8:
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+
+ // TODO(qiankun.miao@intel.com): PIXEL_PACK_BUFFER and PIXEL_UNPACK_BUFFER
+ // are not supported in ES2.
+ bool is_es = decoder->GetFeatureInfo()->gl_version_info().is_es;
+ DCHECK(!is_es || decoder->GetFeatureInfo()->gl_version_info().is_es3);
+
+ uint32_t buffer_num = is_es && format == GL_RGB && type == GL_FLOAT ? 2 : 1;
+ GLuint buffer[2];
+ glGenBuffersARB(buffer_num, buffer);
+ prepareUnpackBuffer(buffer, is_es, format, type, width, height);
+
+ if (is_tex_image) {
+ glTexImage2D(dest_target, dest_level, dest_internal_format, width, height,
+ 0, format, type, 0);
+ } else {
+ glTexSubImage2D(dest_target, dest_level, xoffset, yoffset, width, height,
+ format, type, 0);
+ }
+ glDeleteBuffersARB(buffer_num, buffer);
+ }
+
+ decoder->RestoreTextureState(source_id);
+ decoder->RestoreTextureState(dest_id);
+ decoder->RestoreTextureUnitBindings(0);
+ decoder->RestoreActiveTexture();
+ decoder->RestoreFramebufferBindings();
+ decoder->RestoreBufferBindings();
+}
+
} // namespace
namespace gpu {
@@ -735,9 +909,11 @@ void CopyTextureCHROMIUMResourceManager::DoCopyTexture(
GLint original_dest_level = dest_level;
GLenum original_dest_target = dest_target;
GLenum original_internal_format = dest_internal_format;
- if (method == DRAW_AND_COPY) {
+ if (method == DRAW_AND_COPY || method == DRAW_AND_READBACK) {
GLenum adjusted_internal_format =
- getIntermediateFormat(dest_internal_format);
+ method == DRAW_AND_READBACK
+ ? GL_RGBA
+ : getIntermediateFormat(dest_internal_format);
dest_target = GL_TEXTURE_2D;
glGenTextures(1, &intermediate_texture);
glBindTexture(dest_target, intermediate_texture);
@@ -758,11 +934,18 @@ void CopyTextureCHROMIUMResourceManager::DoCopyTexture(
dest_target, dest_texture, dest_level, dest_internal_format, width,
height, flip_y, premultiply_alpha, unpremultiply_alpha, kIdentityMatrix);
- if (method == DRAW_AND_COPY) {
+ if (method == DRAW_AND_COPY || method == DRAW_AND_READBACK) {
source_level = 0;
- DoCopyTexImage2D(decoder, dest_target, intermediate_texture, source_level,
- original_dest_target, dest_id, original_dest_level,
- original_internal_format, width, height, framebuffer_);
+ if (method == DRAW_AND_COPY) {
+ DoCopyTexImage2D(decoder, dest_target, intermediate_texture, source_level,
+ original_dest_target, dest_id, original_dest_level,
+ original_internal_format, width, height, framebuffer_);
+ } else if (method == DRAW_AND_READBACK) {
+ DoReadbackAndTexImage(true, decoder, dest_target, intermediate_texture,
+ source_level, original_dest_target, dest_id,
+ original_dest_level, original_internal_format, 0, 0,
+ width, height, framebuffer_);
+ }
glDeleteTextures(1, &intermediate_texture);
}
}
@@ -805,9 +988,12 @@ void CopyTextureCHROMIUMResourceManager::DoCopySubTexture(
GLint original_dest_level = dest_level;
GLenum original_dest_target = dest_target;
GLuint intermediate_texture = 0;
- if (method == DRAW_AND_COPY) {
+ GLenum original_internal_format = dest_internal_format;
+ if (method == DRAW_AND_COPY || method == DRAW_AND_READBACK) {
GLenum adjusted_internal_format =
- getIntermediateFormat(dest_internal_format);
+ method == DRAW_AND_READBACK
+ ? GL_RGBA
+ : getIntermediateFormat(dest_internal_format);
dest_target = GL_TEXTURE_2D;
glGenTextures(1, &intermediate_texture);
glBindTexture(dest_target, intermediate_texture);
@@ -834,12 +1020,19 @@ void CopyTextureCHROMIUMResourceManager::DoCopySubTexture(
source_height, flip_y, premultiply_alpha, unpremultiply_alpha,
kIdentityMatrix);
- if (method == DRAW_AND_COPY) {
+ if (method == DRAW_AND_COPY || method == DRAW_AND_READBACK) {
source_level = 0;
- DoCopyTexSubImage2D(decoder, dest_target, intermediate_texture,
- source_level, original_dest_target, dest_id,
- original_dest_level, xoffset, yoffset, 0, 0, width,
- height, framebuffer_);
+ if (method == DRAW_AND_COPY) {
+ DoCopyTexSubImage2D(decoder, dest_target, intermediate_texture,
+ source_level, original_dest_target, dest_id,
+ original_dest_level, xoffset, yoffset, 0, 0, width,
+ height, framebuffer_);
+ } else if (method == DRAW_AND_READBACK) {
+ DoReadbackAndTexImage(false, decoder, dest_target, intermediate_texture,
+ source_level, original_dest_target, dest_id,
+ original_dest_level, original_internal_format,
+ xoffset, yoffset, width, height, framebuffer_);
+ }
glDeleteTextures(1, &intermediate_texture);
}
}
« no previous file with comments | « gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h ('k') | gpu/command_buffer/service/gles2_cmd_decoder.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698