Chromium Code Reviews| Index: third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp |
| diff --git a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp |
| index 7a26d0f0102499c20e5b3afe6f6e882fb03cdeeb..2d4c5d9ea62ff2e97c70cafe19dd7d25efc0d9a3 100644 |
| --- a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp |
| +++ b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp |
| @@ -589,6 +589,19 @@ DrawingBuffer::CreateOrRecycleColorBuffer() { |
| return CreateColorBuffer(size_); |
| } |
| +DrawingBuffer::ScopedRGBEmulationForBlitFramebuffer:: |
| + ScopedRGBEmulationForBlitFramebuffer(DrawingBuffer* drawing_buffer) |
| + : drawing_buffer_(drawing_buffer) { |
| + doing_work_ = drawing_buffer->SetupRGBEmulationForBlitFramebuffer(); |
| +} |
| + |
| +DrawingBuffer::ScopedRGBEmulationForBlitFramebuffer:: |
| + ~ScopedRGBEmulationForBlitFramebuffer() { |
| + if (doing_work_) { |
| + drawing_buffer_->CleanupRGBEmulationForBlitFramebuffer(); |
| + } |
| +} |
| + |
| DrawingBuffer::ColorBuffer::ColorBuffer( |
| DrawingBuffer* drawing_buffer, |
| const ColorBufferParameters& parameters, |
| @@ -612,6 +625,10 @@ DrawingBuffer::ColorBuffer::~ColorBuffer() { |
| if (image_id) { |
| gl->BindTexture(parameters.target, texture_id); |
| gl->ReleaseTexImage2DCHROMIUM(parameters.target, image_id); |
| + if (rgb_workaround_texture_id) { |
| + gl->BindTexture(parameters.target, rgb_workaround_texture_id); |
| + gl->ReleaseTexImage2DCHROMIUM(parameters.target, image_id); |
| + } |
| gl->DestroyImageCHROMIUM(image_id); |
| switch (parameters.target) { |
| case GL_TEXTURE_2D: |
| @@ -631,6 +648,7 @@ DrawingBuffer::ColorBuffer::~ColorBuffer() { |
| gpu_memory_buffer.reset(); |
| } |
| gl->DeleteTextures(1, &texture_id); |
| + gl->DeleteTextures(1, &rgb_workaround_texture_id); |
| } |
| bool DrawingBuffer::Initialize(const IntSize& size, bool use_multisampling) { |
| @@ -1271,6 +1289,78 @@ GLenum DrawingBuffer::GetMultisampledRenderbufferFormat() { |
| return GL_RGB8_OES; |
| } |
| +bool DrawingBuffer::SetupRGBEmulationForBlitFramebuffer() { |
| + // We only need to do this work if: |
| + // - The user has selected alpha:false and antialias:false |
| + // - We are using CHROMIUM_image with RGB emulation |
| + // macOS is the only platform on which this is necessary. |
| + |
| + if (want_alpha_channel_ || anti_aliasing_mode_ != kNone) |
| + return false; |
| + |
| + if (!(ShouldUseChromiumImage() && |
| + ContextProvider()->GetCapabilities().chromium_image_rgb_emulation)) |
| + return false; |
| + |
| + if (!back_color_buffer_) |
| + return false; |
| + |
| + // If for some reason the back buffer doesn't have a CHROMIUM_image, |
| + // don't proceed with this workaround. |
| + if (!back_color_buffer_->image_id) |
| + return false; |
| + |
| + // Before allowing the BlitFramebuffer call to go through, it's necessary |
| + // to swap out the RGBA texture that's bound to the CHROMIUM_image |
| + // instance with an RGB texture. BlitFramebuffer requires the internal |
| + // formats of the source and destination to match when doing a |
| + // multisample resolve, and the best way to achieve this without adding |
| + // more full-screen blits is to hook up a true RGB texture to the |
| + // underlying IOSurface. Unfortunately, on macOS, this rendering path |
| + // destroys the alpha channel and requires a fixup afterward, which is |
| + // why it isn't used all the time. |
| + |
| + GLuint rgb_texture = back_color_buffer_->rgb_workaround_texture_id; |
| + GLenum target = GC3D_TEXTURE_RECTANGLE_ARB; |
| + if (!rgb_texture) { |
| + gl_->GenTextures(1, &rgb_texture); |
| + gl_->BindTexture(target, rgb_texture); |
| + gl_->TexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |
| + gl_->TexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
| + gl_->TexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
| + gl_->TexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
| + |
| + // Bind this texture to the CHROMIUM_image instance that the color |
| + // buffer owns. This is an expensive operation, so it's important that |
| + // the result be cached. |
| + gl_->BindTexImage2DWithInternalformatCHROMIUM(target, GL_RGB, |
| + back_color_buffer_->image_id); |
| + back_color_buffer_->rgb_workaround_texture_id = rgb_texture; |
| + } |
| + |
| + gl_->FramebufferTexture2D(GL_DRAW_FRAMEBUFFER_ANGLE, GL_COLOR_ATTACHMENT0, |
| + target, rgb_texture, 0); |
| + return true; |
| +} |
| + |
| +void DrawingBuffer::CleanupRGBEmulationForBlitFramebuffer() { |
| + // This will only be called if SetupRGBEmulationForBlitFramebuffer was. |
| + // Put the framebuffer back the way it was, and clear the alpha channel. |
| + DCHECK(back_color_buffer_); |
| + DCHECK(back_color_buffer_->image_id); |
| + GLenum target = GC3D_TEXTURE_RECTANGLE_ARB; |
| + gl_->FramebufferTexture2D(GL_DRAW_FRAMEBUFFER_ANGLE, GL_COLOR_ATTACHMENT0, |
| + target, back_color_buffer_->texture_id, 0); |
|
Zhenyao Mo
2017/04/19 23:07:34
Please make sure this was bound before SetupRGBEmu
Ken Russell (switch to Gerrit)
2017/04/20 01:49:18
Confirmed that it is, in AttachColorBufferToReadFr
|
| + // Clear the alpha channel. |
| + gl_->ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE); |
| + gl_->Disable(GL_SCISSOR_TEST); |
| + gl_->ClearColor(0, 0, 0, 1); |
| + gl_->Clear(GL_COLOR_BUFFER_BIT); |
| + DCHECK(client_); |
| + client_->DrawingBufferClientRestoreScissorTest(); |
| + client_->DrawingBufferClientRestoreMaskAndClearValues(); |
| +} |
| + |
| DrawingBuffer::ScopedStateRestorer::ScopedStateRestorer( |
| DrawingBuffer* drawing_buffer) |
| : drawing_buffer_(drawing_buffer) { |