| 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 155558732ef1c1bfd811b51a7aaa3b5d72de3334..d4f384554dc9c51736d3c58b20f7f35ee702cc70 100644
|
| --- a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp
|
| +++ b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp
|
| @@ -576,6 +576,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,
|
| @@ -599,6 +612,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:
|
| @@ -618,6 +635,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) {
|
| @@ -1258,6 +1276,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);
|
| + // 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) {
|
|
|