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 82f55a9e8de826c01a1d1b75256d58fe05b013e0..e99b32a278616bb210fc8f28f7a07bd3106f34ee 100644 |
| --- a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp |
| +++ b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp |
| @@ -31,6 +31,7 @@ |
| #include "platform/graphics/gpu/DrawingBuffer.h" |
| #include "gpu/command_buffer/client/gles2_interface.h" |
| +#include "gpu/command_buffer/common/capabilities.h" |
| #include "platform/RuntimeEnabledFeatures.h" |
| #include "platform/TraceEvent.h" |
| #include "platform/graphics/GraphicsLayer.h" |
| @@ -135,6 +136,7 @@ DrawingBuffer::DrawingBuffer( |
| , m_texture2DBinding(0) |
| , m_drawFramebufferBinding(0) |
| , m_readFramebufferBinding(0) |
| + , m_renderbufferBinding(0) |
| , m_activeTextureUnit(GL_TEXTURE0) |
| , m_contextProvider(std::move(contextProvider)) |
| , m_context(m_contextProvider->context3d()) |
| @@ -148,6 +150,8 @@ DrawingBuffer::DrawingBuffer( |
| , m_fbo(0) |
| , m_depthStencilBuffer(0) |
| , m_multisampleFBO(0) |
| + , m_multisampleIntermediateFBO(0) |
| + , m_multisampleIntermediateRenderbuffer(0) |
| , m_multisampleColorBuffer(0) |
| , m_contentsChanged(true) |
| , m_contentsChangeCommitted(false) |
| @@ -225,6 +229,15 @@ void DrawingBuffer::setFilterQuality(SkFilterQuality filterQuality) |
| } |
| } |
| +bool DrawingBuffer::requiresRGBEmulation() |
| +{ |
| + // When an explicit resolve is required, clients draw into a render buffer |
| + // which is never backed by an IOSurface. |
| + if (m_antiAliasingMode == MSAAExplicitResolve) |
| + return false; |
| + return !m_drawFramebufferBinding && !m_wantAlphaChannel && m_colorBuffer.imageId && contextProvider()->getCapabilities().chromium_image_rgb_emulation; |
| +} |
| + |
| void DrawingBuffer::freeRecycledMailboxes() |
| { |
| if (m_recycledMailboxQueue.isEmpty()) |
| @@ -343,9 +356,23 @@ DrawingBuffer::TextureParameters DrawingBuffer::chromiumImageTextureParameters() |
| // on OSX. |
| TextureParameters parameters; |
| parameters.target = GC3D_TEXTURE_RECTANGLE_ARB; |
| - parameters.internalColorFormat = GL_RGBA; |
| - parameters.internalRenderbufferFormat = GL_RGBA8_OES; |
| - parameters.colorFormat = GL_RGBA; |
| + |
| + if (m_wantAlphaChannel) { |
| + parameters.creationInternalColorFormat = GL_RGBA; |
| + parameters.internalColorFormat = GL_RGBA; |
| + parameters.internalRenderbufferFormat = GL_RGBA8_OES; |
| + } else if (contextProvider()->getCapabilities().chromium_image_rgb_emulation) { |
| + parameters.creationInternalColorFormat = GL_RGB; |
| + parameters.internalColorFormat = GL_RGBA; |
| + parameters.internalRenderbufferFormat = GL_RGB8_OES; |
| + } else { |
| + parameters.creationInternalColorFormat = GL_RGB; |
| + parameters.internalColorFormat = GL_RGB; |
| + parameters.internalRenderbufferFormat = GL_RGB8_OES; |
| + } |
| + |
| + // Unused. |
|
Ken Russell (switch to Gerrit)
2016/04/29 09:33:09
Unused when CHROMIUM_image is being used, right? D
erikchen
2016/05/03 22:58:07
Correct. I updated the comment. Fallback textures
|
| + parameters.colorFormat = 0; |
| return parameters; |
| #else |
| return defaultTextureParameters(); |
| @@ -358,10 +385,12 @@ DrawingBuffer::TextureParameters DrawingBuffer::defaultTextureParameters() |
| parameters.target = GL_TEXTURE_2D; |
| if (m_wantAlphaChannel) { |
| parameters.internalColorFormat = GL_RGBA; |
| + parameters.creationInternalColorFormat = GL_RGBA; |
| parameters.colorFormat = GL_RGBA; |
| parameters.internalRenderbufferFormat = GL_RGBA8_OES; |
| } else { |
| parameters.internalColorFormat = GL_RGB; |
| + parameters.creationInternalColorFormat = GL_RGB; |
| parameters.colorFormat = GL_RGB; |
| parameters.internalRenderbufferFormat = GL_RGB8_OES; |
| } |
| @@ -586,6 +615,12 @@ void DrawingBuffer::beginDestruction() |
| if (m_multisampleColorBuffer) |
| m_gl->DeleteRenderbuffers(1, &m_multisampleColorBuffer); |
| + if (m_multisampleIntermediateFBO) |
| + m_gl->DeleteFramebuffers(1, &m_multisampleIntermediateFBO); |
| + |
| + if (m_multisampleIntermediateRenderbuffer) |
| + m_gl->DeleteRenderbuffers(1, &m_multisampleIntermediateRenderbuffer); |
| + |
| if (m_depthStencilBuffer) |
| m_gl->DeleteRenderbuffers(1, &m_depthStencilBuffer); |
| @@ -749,7 +784,7 @@ bool DrawingBuffer::reset(const IntSize& newSize, bool wantDepthOrStencilBuffer) |
| m_gl->Disable(GL_SCISSOR_TEST); |
| m_gl->ClearColor(0, 0, 0, 0); |
| - m_gl->ColorMask(true, true, true, true); |
| + m_gl->ColorMask(true, true, true, !requiresRGBEmulation()); |
| GLbitfield clearMask = GL_COLOR_BUFFER_BIT; |
| if (!!m_depthStencilBuffer) { |
| @@ -764,6 +799,7 @@ bool DrawingBuffer::reset(const IntSize& newSize, bool wantDepthOrStencilBuffer) |
| } |
| clearFramebuffers(clearMask); |
| + m_gl->ColorMask(true, true, true, true); |
|
Ken Russell (switch to Gerrit)
2016/04/29 09:33:09
Were callers relying on this to set the color mask
erikchen
2016/05/03 22:58:07
No. I removed this call.
|
| return true; |
| } |
| @@ -779,7 +815,36 @@ void DrawingBuffer::commit() |
| int width = m_size.width(); |
| int height = m_size.height(); |
| // Use NEAREST, because there is no scale performed during the blit. |
| - m_gl->BlitFramebufferCHROMIUM(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_NEAREST); |
| + GLuint filter = GL_NEAREST; |
| + |
| + // If the destination has a different color format than the source, then |
| + // first resolve to an intermediary renderbuffer with the same color |
| + // format. |
| + // If this extra blit proves to be a performance problem, it can be |
| + // bypassed on most GPUs by performing client side GL_RGBA emulation on |
| + // the source renderbuffer. |
| + // https://bugs.chromium.org/p/chromium/issues/detail?id=595948#c30 |
| + if (m_colorBuffer.parameters.internalColorFormat == GL_RGBA && m_colorBuffer.parameters.internalRenderbufferFormat == GL_RGB8_OES) { |
| + if (!m_multisampleIntermediateFBO) { |
| + DCHECK(!m_multisampleIntermediateRenderbuffer); |
|
Zhenyao Mo
2016/04/29 22:54:16
These two names are misleading. The intermediate
erikchen
2016/05/03 22:58:08
Done.
|
| + m_gl->GenRenderbuffers(1, &m_multisampleIntermediateRenderbuffer); |
| + m_gl->BindRenderbuffer(GL_RENDERBUFFER, m_multisampleIntermediateRenderbuffer); |
|
Ken Russell (switch to Gerrit)
2016/04/29 09:33:09
Is resizing of m_multisampleIntermediateRenderbuff
erikchen
2016/05/03 22:58:07
No, it wasn't. I added a test:
https://codereview.
|
| + m_gl->RenderbufferStorage(GL_RENDERBUFFER, GL_RGB8, width, height); |
| + |
| + m_gl->GenFramebuffers(1, &m_multisampleIntermediateFBO); |
| + m_gl->BindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, m_multisampleIntermediateFBO); |
| + m_gl->FramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER_ANGLE, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_multisampleIntermediateRenderbuffer); |
| + m_gl->BindRenderbuffer(GL_RENDERBUFFER, m_renderbufferBinding); |
| + } |
| + |
| + m_gl->BindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, m_multisampleIntermediateFBO); |
| + m_gl->BlitFramebufferCHROMIUM(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, filter); |
| + |
| + m_gl->BindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, m_multisampleIntermediateFBO); |
| + m_gl->BindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, m_fbo); |
| + } |
| + |
| + m_gl->BlitFramebufferCHROMIUM(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, filter); |
| if (m_scissorEnabled) |
| m_gl->Enable(GL_SCISSOR_TEST); |
| @@ -933,21 +998,32 @@ void DrawingBuffer::deleteChromiumImageForTexture(TextureInfo* info) |
| } |
| } |
| -DrawingBuffer::TextureInfo DrawingBuffer::createTextureAndAllocateMemory(const IntSize& size) |
| +void DrawingBuffer::clearChromiumImageIfNecessary(const TextureInfo& info) |
| { |
| - // TODO(erikchen): Add support for a CHROMIUM_image back buffer whose |
| - // behavior mimics a texture with internal format GL_RGB. |
| - // https://crbug.com/581777. |
| - if (!m_wantAlphaChannel) |
| - return createDefaultTextureAndAllocateMemory(size); |
| + if (m_wantAlphaChannel) |
|
Zhenyao Mo
2016/04/29 22:54:15
You can also return early if we don't need to emul
erikchen
2016/05/03 22:58:07
Done.
|
| + return; |
| + |
| + GLuint fbo = 0; |
| + m_gl->GenFramebuffers(1, &fbo); |
| + m_gl->BindFramebuffer(GL_FRAMEBUFFER, fbo); |
| + m_gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, info.parameters.target, info.textureId, 0); |
| + m_gl->ClearColor(0, 0, 0, 1); |
| + m_gl->ColorMask(false, false, false, true); |
|
Ken Russell (switch to Gerrit)
2016/04/29 09:33:09
Is it deliberate that only the alpha channel is be
erikchen
2016/05/03 22:58:07
Yes. I updated the name of this method to be clear
|
| + m_gl->Clear(GL_COLOR_BUFFER_BIT); |
| + m_gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, info.parameters.target, 0, 0); |
| + m_gl->DeleteFramebuffers(1, &fbo); |
| + restoreFramebufferBindings(); |
|
Zhenyao Mo
2016/04/29 22:54:16
Should we also restore clear color and clear mask
erikchen
2016/05/03 22:58:07
Yes. Done.
|
| +} |
| +DrawingBuffer::TextureInfo DrawingBuffer::createTextureAndAllocateMemory(const IntSize& size) |
| +{ |
| if (!RuntimeEnabledFeatures::webGLImageChromiumEnabled()) |
| return createDefaultTextureAndAllocateMemory(size); |
| // First, try to allocate a CHROMIUM_image. This always has the potential to |
| // fail. |
| TextureParameters parameters = chromiumImageTextureParameters(); |
| - GLuint imageId = m_gl->CreateGpuMemoryBufferImageCHROMIUM(size.width(), size.height(), parameters.internalColorFormat, GC3D_SCANOUT_CHROMIUM); |
| + GLuint imageId = m_gl->CreateGpuMemoryBufferImageCHROMIUM(size.width(), size.height(), parameters.creationInternalColorFormat, GC3D_SCANOUT_CHROMIUM); |
| if (!imageId) |
| return createDefaultTextureAndAllocateMemory(size); |
| @@ -958,6 +1034,7 @@ DrawingBuffer::TextureInfo DrawingBuffer::createTextureAndAllocateMemory(const I |
| info.textureId = textureId; |
| info.imageId = imageId; |
| info.parameters = parameters; |
| + clearChromiumImageIfNecessary(info); |
| return info; |
| } |
| @@ -965,7 +1042,7 @@ DrawingBuffer::TextureInfo DrawingBuffer::createDefaultTextureAndAllocateMemory( |
| { |
| TextureParameters parameters = defaultTextureParameters(); |
| GLuint textureId = createColorTexture(parameters); |
| - texImage2DResourceSafe(parameters.target, 0, parameters.internalColorFormat, size.width(), size.height(), 0, parameters.colorFormat, GL_UNSIGNED_BYTE); |
| + texImage2DResourceSafe(parameters.target, 0, parameters.creationInternalColorFormat, size.width(), size.height(), 0, parameters.colorFormat, GL_UNSIGNED_BYTE); |
| DrawingBuffer::TextureInfo info; |
| info.textureId = textureId; |
| @@ -978,10 +1055,11 @@ void DrawingBuffer::resizeTextureMemory(TextureInfo* info, const IntSize& size) |
| ASSERT(info->textureId); |
| if (info->imageId) { |
| deleteChromiumImageForTexture(info); |
| - info->imageId = m_gl->CreateGpuMemoryBufferImageCHROMIUM(size.width(), size.height(), info->parameters.internalColorFormat, GC3D_SCANOUT_CHROMIUM); |
| + info->imageId = m_gl->CreateGpuMemoryBufferImageCHROMIUM(size.width(), size.height(), info->parameters.creationInternalColorFormat, GC3D_SCANOUT_CHROMIUM); |
| if (info->imageId) { |
| m_gl->BindTexture(info->parameters.target, info->textureId); |
| m_gl->BindTexImage2DCHROMIUM(info->parameters.target, info->imageId); |
| + clearChromiumImageIfNecessary(*info); |
| return; |
| } |
| @@ -992,7 +1070,7 @@ void DrawingBuffer::resizeTextureMemory(TextureInfo* info, const IntSize& size) |
| } |
| m_gl->BindTexture(info->parameters.target, info->textureId); |
| - texImage2DResourceSafe(info->parameters.target, 0, info->parameters.internalColorFormat, size.width(), size.height(), 0, info->parameters.colorFormat, GL_UNSIGNED_BYTE); |
| + texImage2DResourceSafe(info->parameters.target, 0, info->parameters.creationInternalColorFormat, size.width(), size.height(), 0, info->parameters.colorFormat, GL_UNSIGNED_BYTE); |
| } |
| void DrawingBuffer::attachColorBufferToCurrentFBO() |