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

Unified Diff: third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp

Issue 1856933002: WebGL GL_RGB emulation to support IOSurfaces on Mac. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Clean up. Created 4 years, 8 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: 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()

Powered by Google App Engine
This is Rietveld 408576698