Chromium Code Reviews| Index: content/common/gpu/client/gl_helper.cc |
| diff --git a/content/common/gpu/client/gl_helper.cc b/content/common/gpu/client/gl_helper.cc |
| index dfdeff072ae45c02ff4b535a53611c12c7dd3a01..64446a69cf1eeab7f34e56c35c57643043d9a8fe 100644 |
| --- a/content/common/gpu/client/gl_helper.cc |
| +++ b/content/common/gpu/client/gl_helper.cc |
| @@ -141,7 +141,7 @@ class GLHelper::CopyTextureToImpl |
| const gfx::Rect& src_subrect, |
| const gfx::Size& dst_size, |
| unsigned char* out, |
| - const SkColorType color_type, |
| + const SkColorType out_color_type, |
| const base::Callback<void(bool)>& callback, |
| GLHelper::ScalerQuality quality); |
| @@ -319,6 +319,23 @@ class GLHelper::CopyTextureToImpl |
| SkColorType color_type, |
| GLHelper::ScalerQuality quality); |
| + // Converts each four consecutive pixels of the source texture into one pixel |
| + // in the result texture with each pixel channel representing the grayscale |
| + // color of one of the four original pixels: |
| + // R1B1G1A1 R2B2G2A2 R3B3G3A3 R4G4B4A4 -> X1X2X3X4 |
| + // The resulting texture is still an RGBA texture (which is ~4 times narrower |
| + // than the original). If rendered directly, it wouldn't show anything useful, |
| + // but the data in it can be used to construct a grayscale image. |
| + // |encoded_texture_size| is the exact size of the resulting RGBA texture. It |
| + // is equal to src_size.width()/4 rounded upwards. Some channels in the last |
| + // pixel ((-src_size.width()) % 4) to be exact) are padding and don't contain |
| + // useful data. |
| + GLuint EncodeTextureAsGrayscale(GLuint src_texture, |
| + const gfx::Size& src_size, |
| + gfx::Size* const encoded_texture_size, |
| + bool vertically_flip_texture, |
| + bool swizzle); |
| + |
| static void nullcallback(bool success) {} |
| void ReadbackDone(Request *request, int bytes_per_pixel); |
| void FinishRequest(Request* request, bool result); |
| @@ -327,6 +344,7 @@ class GLHelper::CopyTextureToImpl |
| static const float kRGBtoYColorWeights[]; |
| static const float kRGBtoUColorWeights[]; |
| static const float kRGBtoVColorWeights[]; |
| + static const float kRGBtoGrayscaleColorWeights[]; |
| GLES2Interface* gl_; |
| gpu::ContextSupport* context_support_; |
| @@ -407,6 +425,45 @@ GLuint GLHelper::CopyTextureToImpl::ScaleTexture( |
| return dst_texture; |
| } |
| +GLuint GLHelper::CopyTextureToImpl::EncodeTextureAsGrayscale( |
| + GLuint src_texture, |
| + const gfx::Size& src_size, |
| + gfx::Size* const encoded_texture_size, |
| + bool vertically_flip_texture, |
| + bool swizzle) { |
| + LOG(ERROR) << "GLHelper::CopyTextureToImpl::EncodeTextureAsGrayscale"; |
| + |
| + GLuint dst_texture = 0u; |
| + gl_->GenTextures(1, &dst_texture); |
| + // The size of the encoded texture. |
| + *encoded_texture_size = |
| + gfx::Size((src_size.width() + 3) / 4, src_size.height()); |
| + { |
| + ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, dst_texture); |
| + gl_->TexImage2D(GL_TEXTURE_2D, |
| + 0, |
| + GL_BGRA_EXT, |
| + encoded_texture_size->width(), |
| + encoded_texture_size->height(), |
| + 0, |
| + GL_BGRA_EXT, |
|
no sievers
2014/07/18 19:27:13
Is it more straightforward to use GL_RGBA here if
mfomitchev
2014/08/12 21:52:04
I am getting the same result regardless of whether
|
| + GL_UNSIGNED_BYTE, |
| + NULL); |
| + } |
| + |
| + helper_->InitScalerImpl(); |
| + scoped_ptr<ScalerInterface> grayscale_scaler( |
| + helper_->scaler_impl_.get()->CreatePlanarScaler( |
| + src_size, |
| + gfx::Rect(0, 0, (src_size.width() + 3) & ~3, src_size.height()), |
| + *encoded_texture_size, |
| + vertically_flip_texture, |
| + (swizzle == kSwizzleBGRA), |
|
no sievers
2014/07/18 19:27:12
Here you are comparing a bool to an enum. Did you
mfomitchev
2014/08/12 21:52:04
Just using the bool swizzle that's passed in now.
|
| + kRGBtoGrayscaleColorWeights)); |
| + grayscale_scaler->Scale(src_texture, dst_texture); |
| + return dst_texture; |
| +} |
| + |
| void GLHelper::CopyTextureToImpl::ReadbackAsync( |
| const gfx::Size& dst_size, |
| int32 bytes_per_row, |
| @@ -442,6 +499,7 @@ void GLHelper::CopyTextureToImpl::ReadbackAsync( |
| NOTREACHED(); |
| break; |
| } |
| + |
| gl_->GenBuffers(1, &request->buffer); |
| gl_->BindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, request->buffer); |
| gl_->BufferData(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, |
| @@ -452,13 +510,8 @@ void GLHelper::CopyTextureToImpl::ReadbackAsync( |
| request->query = 0u; |
| gl_->GenQueriesEXT(1, &request->query); |
| gl_->BeginQueryEXT(GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM, request->query); |
| - gl_->ReadPixels(0, |
| - 0, |
| - dst_size.width(), |
| - dst_size.height(), |
| - format, |
| - type, |
| - NULL); |
| + gl_->ReadPixels( |
| + 0, 0, dst_size.width(), dst_size.height(), format, type, NULL); |
| gl_->EndQueryEXT(GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM); |
| gl_->BindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, 0); |
| context_support_->SignalQuery( |
| @@ -466,32 +519,66 @@ void GLHelper::CopyTextureToImpl::ReadbackAsync( |
| base::Bind(&CopyTextureToImpl::ReadbackDone, AsWeakPtr(), |
| request, bytes_per_pixel)); |
| } |
| + |
| void GLHelper::CopyTextureToImpl::CropScaleReadbackAndCleanTexture( |
| GLuint src_texture, |
| const gfx::Size& src_size, |
| const gfx::Rect& src_subrect, |
| const gfx::Size& dst_size, |
| unsigned char* out, |
| - const SkColorType color_type, |
| + const SkColorType out_color_type, |
| const base::Callback<void(bool)>& callback, |
| GLHelper::ScalerQuality quality) { |
| - if (!IsReadbackConfigSupported(color_type)) { |
| + if (out_color_type != kAlpha_8_SkColorType && |
| + !IsReadbackConfigSupported(out_color_type)) { |
| callback.Run(false); |
| return; |
| } |
| - GLuint texture = ScaleTexture(src_texture, |
| - src_size, |
| - src_subrect, |
| - dst_size, |
| - true, |
| + |
| + GLuint texture = src_texture; |
| + bool swizzle = |
| #if (SK_R32_SHIFT == 16) && !SK_B32_SHIFT |
| - true, |
| + true; |
| #else |
| - false, |
| + false; |
| #endif |
| - color_type, |
| - quality); |
| - DCHECK(texture); |
| + |
| + // Scale texture if needed |
| + // Optimization: SCALER_QUALITY_FAST is just a single bilinear pass, which we |
| + // can do just as well in EncodeTextureAsGrayscale if we need to output A8 |
| + // color type, so let's skip the actual scaling in that case. |
| + bool scale_texture = out_color_type != kAlpha_8_SkColorType || |
| + quality != GLHelper::SCALER_QUALITY_FAST; |
| + if (scale_texture) { |
| + LOG(ERROR) << "+++ Scaling texture"; |
| + texture = |
| + ScaleTexture(src_texture, |
| + src_size, |
| + src_subrect, |
| + dst_size, |
| + true, |
| + out_color_type == kAlpha_8_SkColorType ? false : swizzle, |
| + out_color_type == kAlpha_8_SkColorType ? kN32_SkColorType |
| + : out_color_type, |
| + quality); |
| + DCHECK(texture); |
| + } |
| + |
| + // Encode texture to grayscale if needed |
| + gfx::Size readback_texture_size = dst_size; |
| + |
| + if (out_color_type == kAlpha_8_SkColorType) { |
| + texture = EncodeTextureAsGrayscale( |
| + texture, |
| + dst_size, |
| + &readback_texture_size, |
| + !scale_texture, // Do the vertical flip here if we haven't already |
| + // done it in the scale step. |
| + swizzle); |
| + DCHECK(texture); |
| + } |
| + |
| + // Readback the pixels of the resulting texture |
| ScopedFramebuffer dst_framebuffer(gl_); |
| ScopedFramebufferBinder<GL_FRAMEBUFFER> framebuffer_binder(gl_, |
| dst_framebuffer); |
| @@ -502,23 +589,30 @@ void GLHelper::CopyTextureToImpl::CropScaleReadbackAndCleanTexture( |
| texture, |
| 0); |
| int bytes_per_pixel = 4; |
| - switch (color_type) { |
| + ReadbackSwizzle readback_swizzle = kSwizzleNone; |
| + SkColorType readback_color_type = out_color_type; |
| + switch (out_color_type) { |
| case kN32_SkColorType: |
| // Do nothing params already set. |
| break; |
| case kRGB_565_SkColorType: |
| bytes_per_pixel = 2; |
| break; |
| + case kAlpha_8_SkColorType: |
| + bytes_per_pixel = 1; |
| + readback_swizzle = kSwizzleBGRA; |
| + readback_color_type = kN32_SkColorType; |
| + break; |
| default: |
| NOTREACHED(); |
| break; |
| } |
| - ReadbackAsync(dst_size, |
| + ReadbackAsync(readback_texture_size, |
| dst_size.width() * bytes_per_pixel, |
| dst_size.width() * bytes_per_pixel, |
| out, |
| - color_type, |
| - kSwizzleNone, |
| + readback_color_type, |
| + readback_swizzle, |
| callback); |
| gl_->DeleteTextures(1, &texture); |
| } |
| @@ -682,19 +776,18 @@ void GLHelper::CropScaleReadbackAndCleanTexture( |
| const gfx::Rect& src_subrect, |
| const gfx::Size& dst_size, |
| unsigned char* out, |
| - const SkColorType color_type, |
| + const SkColorType out_color_type, |
| const base::Callback<void(bool)>& callback, |
| GLHelper::ScalerQuality quality) { |
| InitCopyTextToImpl(); |
| - copy_texture_to_impl_->CropScaleReadbackAndCleanTexture( |
| - src_texture, |
| - src_size, |
| - src_subrect, |
| - dst_size, |
| - out, |
| - color_type, |
| - callback, |
| - quality); |
| + copy_texture_to_impl_->CropScaleReadbackAndCleanTexture(src_texture, |
| + src_size, |
| + src_subrect, |
| + dst_size, |
| + out, |
| + out_color_type, |
| + callback, |
| + quality); |
| } |
| void GLHelper::CropScaleReadbackAndCleanMailbox( |
| @@ -704,15 +797,18 @@ void GLHelper::CropScaleReadbackAndCleanMailbox( |
| const gfx::Rect& src_subrect, |
| const gfx::Size& dst_size, |
| unsigned char* out, |
| - const SkColorType color_type, |
| + const SkColorType out_color_type, |
| const base::Callback<void(bool)>& callback, |
| GLHelper::ScalerQuality quality) { |
| GLuint mailbox_texture = ConsumeMailboxToTexture(src_mailbox, sync_point); |
| - CropScaleReadbackAndCleanTexture( |
| - mailbox_texture, src_size, src_subrect, dst_size, out, |
| - color_type, |
| - callback, |
| - quality); |
| + CropScaleReadbackAndCleanTexture(mailbox_texture, |
| + src_size, |
| + src_subrect, |
| + dst_size, |
| + out, |
| + out_color_type, |
| + callback, |
| + quality); |
| gl_->DeleteTextures(1, &mailbox_texture); |
| } |
| @@ -928,6 +1024,8 @@ const float GLHelper::CopyTextureToImpl::kRGBtoUColorWeights[] = { |
| -0.148f, -0.291f, 0.439f, 0.5f}; |
| const float GLHelper::CopyTextureToImpl::kRGBtoVColorWeights[] = { |
| 0.439f, -0.368f, -0.071f, 0.5f}; |
| +const float GLHelper::CopyTextureToImpl::kRGBtoGrayscaleColorWeights[] = { |
| + 0.213f, 0.715f, 0.072f, 0.0f}; |
| // YUV readback constructors. Initiates the main scaler pipeline and |
| // one planar scaler for each of the Y, U and V planes. |