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

Unified Diff: third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.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: Full client side implementation of GL_RGB emulation. 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/modules/webgl/WebGLRenderingContextBase.cpp
diff --git a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp
index 896cafbed0f06dc47f17a0427f55ca4d418d40ef..339225c1fd6872d5b62f74c5e1f445be1ec9348f 100644
--- a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp
+++ b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp
@@ -103,6 +103,8 @@
#include "wtf/text/StringBuilder.h"
#include "wtf/text/StringUTF8Adaptor.h"
+#include <memory>
+
namespace blink {
namespace {
@@ -125,6 +127,24 @@ WebGLRenderingContextBaseMap& forciblyEvictedContexts()
return forciblyEvictedContexts;
}
+class ScopedRGBEmulationColorMask {
+public:
+ ScopedRGBEmulationColorMask(gpu::gles2::GLES2Interface* contextGL, GLboolean* colorMask)
+ : m_contextGL(contextGL)
+ {
+ memcpy(m_colorMask, colorMask, 4 * sizeof(GLboolean));
+ m_contextGL->ColorMask(m_colorMask[0], m_colorMask[1], m_colorMask[2], false);
+ }
+ ~ScopedRGBEmulationColorMask()
+ {
+ m_contextGL->ColorMask(m_colorMask[0], m_colorMask[1], m_colorMask[2], m_colorMask[3]);
+ }
+
+private:
+ gpu::gles2::GLES2Interface* m_contextGL;
+ GLboolean m_colorMask[4];
+};
+
} // namespace
void WebGLRenderingContextBase::forciblyLoseOldestContext(const String& reason)
@@ -1166,7 +1186,7 @@ WebGLRenderingContextBase::HowToClear WebGLRenderingContextBase::clearIfComposit
} else {
contextGL()->ClearColor(0, 0, 0, 0);
}
- contextGL()->ColorMask(true, true, true, true);
+ contextGL()->ColorMask(true, true, true, !drawingBuffer()->requiresRGBEmulation());
GLbitfield clearMask = GL_COLOR_BUFFER_BIT;
if (contextAttributes.get().depth()) {
if (!combinedClear || !m_depthMask || !(mask & GL_DEPTH_BUFFER_BIT))
@@ -1210,6 +1230,16 @@ void WebGLRenderingContextBase::restoreStateAfterClear()
contextGL()->DepthMask(m_depthMask);
}
+void WebGLRenderingContextBase::moveGLErrorsToInternalQueue()
+{
+ DCHECK(!isContextLost());
+ GLenum error = GL_NO_ERROR;
+ while ((error = contextGL()->GetError()) != GL_NO_ERROR) {
+ if (!m_syntheticErrors.contains(error))
+ m_syntheticErrors.append(error);
+ }
+}
+
void WebGLRenderingContextBase::markLayerComposited()
{
if (!isContextLost())
@@ -1696,6 +1726,11 @@ void WebGLRenderingContextBase::clear(GLbitfield mask)
synthesizeGLError(GL_INVALID_FRAMEBUFFER_OPERATION, "clear", reason);
return;
}
+
+ std::unique_ptr<ScopedRGBEmulationColorMask> scopedColorMask;
+ if (m_drawingBuffer->requiresRGBEmulation())
+ scopedColorMask.reset(new ScopedRGBEmulationColorMask(contextGL(), m_colorMask));
+
if (clearIfComposited(mask) != CombinedClear) {
// If clearing the default back buffer's depth buffer, also clear the stencil buffer, if one
// was allocated implicitly. This avoids performance problems on some GPUs.
@@ -1766,12 +1801,23 @@ void WebGLRenderingContextBase::compressedTexImage2D(GLenum target, GLint level,
{
if (isContextLost())
return;
- if (!validateTexture2DBinding("compressedTexImage2D", target))
+ WebGLTexture* texture = validateTexture2DBinding("compressedTexImage2D", target);
+ if (!texture)
return;
if (!validateCompressedTexFormat("compressedTexImage2D", internalformat))
return;
+
+ moveGLErrorsToInternalQueue();
contextGL()->CompressedTexImage2D(target, level, internalformat, width, height,
border, data->byteLength(), data->baseAddress());
+
+ GLenum error = contextGL()->GetError();
+ if (error == GL_NO_ERROR) {
+ texture->setColorFormat(internalformat);
+ } else {
+ if (!m_syntheticErrors.contains(error))
+ m_syntheticErrors.append(error);
+ }
}
void WebGLRenderingContextBase::compressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, DOMArrayBufferView* data)
@@ -1817,26 +1863,61 @@ void WebGLRenderingContextBase::copyTexImage2D(GLenum target, GLint level, GLenu
{
if (isContextLost())
return;
- if (!validateTexture2DBinding("copyTexImage2D", target))
+ WebGLTexture* texture = validateTexture2DBinding("copyTexImage2D", target);
+ if (!texture)
return;
if (!validateCopyTexFormat("copyTexImage2D", internalformat))
return;
if (!validateSettableTexFormat("copyTexImage2D", internalformat))
return;
+
+ // If RGB emulation is required, then the destination format should not have
+ // an alpha channel.
+ if (drawingBuffer()->requiresRGBEmulation()) {
+ uint32_t channelsExist = WebGLImageConversion::getChannelBitsByFormat(GL_RGB);
+ uint32_t channelsNeeded = WebGLImageConversion::getChannelBitsByFormat(internalformat);
+ if ((channelsNeeded & channelsExist) != channelsNeeded) {
+ synthesizeGLError(GL_INVALID_OPERATION, "copyTexImage2D", "incompatible format");
+ return;
+ }
+ }
+
WebGLFramebuffer* readFramebufferBinding = nullptr;
if (!validateReadBufferAndGetInfo("copyTexImage2D", readFramebufferBinding))
return;
clearIfComposited();
ScopedDrawingBufferBinder binder(drawingBuffer(), readFramebufferBinding);
+ moveGLErrorsToInternalQueue();
contextGL()->CopyTexImage2D(target, level, internalformat, x, y, width, height, border);
+
+ GLenum error = contextGL()->GetError();
+ if (error == GL_NO_ERROR) {
+ texture->setColorFormat(internalformat);
+ } else {
+ if (!m_syntheticErrors.contains(error))
+ m_syntheticErrors.append(error);
+ }
}
void WebGLRenderingContextBase::copyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height)
{
if (isContextLost())
return;
- if (!validateTexture2DBinding("copyTexSubImage2D", target))
+ WebGLTexture* texture = validateTexture2DBinding("copyTexSubImage2D", target);
+ if (!texture)
return;
+
+ // If RGB emulation is required, then the destination format should not have
+ // an alpha channel.
+ if (drawingBuffer()->requiresRGBEmulation()) {
+ uint32_t channelsExist = WebGLImageConversion::getChannelBitsByFormat(GL_RGB);
+ uint32_t channelsNeeded = WebGLImageConversion::getChannelBitsByFormat(texture->getColorFormat());
+ if ((channelsNeeded & channelsExist) != channelsNeeded) {
+ synthesizeGLError(GL_INVALID_OPERATION, "copyTexSubImage2D", "incompatible format");
+ return;
+ }
+ }
+
WebGLFramebuffer* readFramebufferBinding = nullptr;
if (!validateReadBufferAndGetInfo("copyTexSubImage2D", readFramebufferBinding))
return;
@@ -2116,6 +2197,9 @@ void WebGLRenderingContextBase::drawArrays(GLenum mode, GLint first, GLsizei cou
if (!validateDrawArrays("drawArrays"))
return;
+ std::unique_ptr<ScopedRGBEmulationColorMask> scopedColorMask;
+ if (m_drawingBuffer->requiresRGBEmulation())
+ scopedColorMask.reset(new ScopedRGBEmulationColorMask(contextGL(), m_colorMask));
clearIfComposited();
contextGL()->DrawArrays(mode, first, count);
markContextChanged(CanvasChanged);
@@ -2131,6 +2215,9 @@ void WebGLRenderingContextBase::drawElements(GLenum mode, GLsizei count, GLenum
return;
}
+ std::unique_ptr<ScopedRGBEmulationColorMask> scopedColorMask;
+ if (m_drawingBuffer->requiresRGBEmulation())
+ scopedColorMask.reset(new ScopedRGBEmulationColorMask(contextGL(), m_colorMask));
clearIfComposited();
contextGL()->DrawElements(mode, count, type, reinterpret_cast<void*>(static_cast<intptr_t>(offset)));
markContextChanged(CanvasChanged);
@@ -2141,6 +2228,9 @@ void WebGLRenderingContextBase::drawArraysInstancedANGLE(GLenum mode, GLint firs
if (!validateDrawArrays("drawArraysInstancedANGLE"))
return;
+ std::unique_ptr<ScopedRGBEmulationColorMask> scopedColorMask;
+ if (m_drawingBuffer->requiresRGBEmulation())
+ scopedColorMask.reset(new ScopedRGBEmulationColorMask(contextGL(), m_colorMask));
clearIfComposited();
contextGL()->DrawArraysInstancedANGLE(mode, first, count, primcount);
markContextChanged(CanvasChanged);
@@ -2151,6 +2241,9 @@ void WebGLRenderingContextBase::drawElementsInstancedANGLE(GLenum mode, GLsizei
if (!validateDrawElements("drawElementsInstancedANGLE", type, offset))
return;
+ std::unique_ptr<ScopedRGBEmulationColorMask> scopedColorMask;
+ if (m_drawingBuffer->requiresRGBEmulation())
+ scopedColorMask.reset(new ScopedRGBEmulationColorMask(contextGL(), m_colorMask));
clearIfComposited();
contextGL()->DrawElementsInstancedANGLE(mode, count, type, reinterpret_cast<void*>(static_cast<intptr_t>(offset)), primcount);
markContextChanged(CanvasChanged);
@@ -2582,6 +2675,8 @@ ScriptValue WebGLRenderingContextBase::getParameter(ScriptState* scriptState, GL
case GL_ALIASED_POINT_SIZE_RANGE:
return getWebGLFloatArrayParameter(scriptState, pname);
case GL_ALPHA_BITS:
+ if (m_drawingBuffer->requiresRGBEmulation())
+ return WebGLAny(scriptState, 0);
return getIntParameter(scriptState, pname);
case GL_ARRAY_BUFFER_BINDING:
return WebGLAny(scriptState, m_boundArrayBuffer.get());
@@ -3906,8 +4001,20 @@ GLenum WebGLRenderingContextBase::convertTexInternalFormat(GLenum internalformat
void WebGLRenderingContextBase::texImage2DBase(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void* pixels)
{
+ moveGLErrorsToInternalQueue();
+
// All calling functions check isContextLost, so a duplicate check is not needed here.
contextGL()->TexImage2D(target, level, convertTexInternalFormat(internalformat, type), width, height, border, format, type, pixels);
+
+ GLenum error = contextGL()->GetError();
Ken Russell (switch to Gerrit) 2016/04/06 00:02:53 Sorry, but this synchronous GetError call will kil
+ if (error == GL_NO_ERROR) {
+ WebGLTexture* texture = validateTexture2DBinding("texImage2DBase", target);
+ if (texture)
+ texture->setColorFormat(format);
+ } else {
+ if (!m_syntheticErrors.contains(error))
+ m_syntheticErrors.append(error);
+ }
}
void WebGLRenderingContextBase::texImage2DImpl(GLenum target, GLint level, GLint internalformat, GLenum format, GLenum type, Image* image, WebGLImageConversion::ImageHtmlDomSource domSource, bool flipY, bool premultiplyAlpha)

Powered by Google App Engine
This is Rietveld 408576698