Diff
Modified: trunk/Source/WebCore/ChangeLog (146693 => 146694)
--- trunk/Source/WebCore/ChangeLog 2013-03-23 00:44:31 UTC (rev 146693)
+++ trunk/Source/WebCore/ChangeLog 2013-03-23 00:45:21 UTC (rev 146694)
@@ -1,3 +1,38 @@
+2013-03-19 Zhenyao Mo <z...@google.com>
+
+ Check WEBGL_draw_buffers requirements before exposing the extension
+ https://bugs.webkit.org/show_bug.cgi?id=112359
+
+ Reviewed by Kenneth Russell.
+
+ * html/canvas/EXTDrawBuffers.cpp:
+ (WebCore::EXTDrawBuffers::supported): call satisfies*().
+ (WebCore::EXTDrawBuffers::drawBuffersEXT):
+ (WebCore):
+ (WebCore::EXTDrawBuffers::satisfiesWebGLRequirements): check WebGL requirements.
+ * html/canvas/EXTDrawBuffers.h:
+ (EXTDrawBuffers):
+ * html/canvas/WebGLFramebuffer.cpp:
+ (WebCore::WebGLFramebuffer::getDrawBuffer):
+ (WebCore):
+ * html/canvas/WebGLFramebuffer.h:
+ (WebGLFramebuffer):
+ * html/canvas/WebGLRenderingContext.cpp:
+ (WebCore):
+ (WebCore::WebGLRenderingContext::initializeNewContext):
+ (WebCore::WebGLRenderingContext::getExtension):
+ (WebCore::WebGLRenderingContext::getParameter):
+ (WebCore::WebGLRenderingContext::getSupportedExtensions):
+ (WebCore::WebGLRenderingContext::validateFramebufferFuncParameters):
+ (WebCore::WebGLRenderingContext::getMaxDrawBuffers):
+ (WebCore::WebGLRenderingContext::getMaxColorAttachments):
+ (WebCore::WebGLRenderingContext::setBackDrawBuffer):
+ (WebCore::WebGLRenderingContext::restoreCurrentFramebuffer):
+ (WebCore::WebGLRenderingContext::restoreCurrentTexture2D):
+ (WebCore::WebGLRenderingContext::supportsDrawBuffers): a cached version of EXTDrawBuffers::supports()
+ * html/canvas/WebGLRenderingContext.h:
+ (WebGLRenderingContext):
+
2013-03-22 Roger Fong <roger_f...@apple.com>
Unreviewed. Fix AppleWin port following https://bugs.webkit.org/show_bug.cgi?id=113100.
Modified: trunk/Source/WebCore/html/canvas/EXTDrawBuffers.cpp (146693 => 146694)
--- trunk/Source/WebCore/html/canvas/EXTDrawBuffers.cpp 2013-03-23 00:44:31 UTC (rev 146693)
+++ trunk/Source/WebCore/html/canvas/EXTDrawBuffers.cpp 2013-03-23 00:45:21 UTC (rev 146694)
@@ -60,7 +60,8 @@
return false;
#endif
Extensions3D* extensions = context->graphicsContext3D()->getExtensions();
- return extensions->supports("GL_EXT_draw_buffers");
+ return (extensions->supports("GL_EXT_draw_buffers")
+ && satisfiesWebGLRequirements(context));
}
void EXTDrawBuffers::drawBuffersEXT(const Vector<GC3Denum>& buffers)
@@ -81,6 +82,7 @@
// Because the backbuffer is simulated on all current WebKit ports, we need to change BACK to COLOR_ATTACHMENT0.
GC3Denum value = (bufs[0] == GraphicsContext3D::BACK) ? GraphicsContext3D::COLOR_ATTACHMENT0 : GraphicsContext3D::NONE;
m_context->graphicsContext3D()->getExtensions()->drawBuffersEXT(1, &value);
+ m_context->setBackDrawBuffer(bufs[0]);
} else {
if (n > m_context->getMaxDrawBuffers()) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "drawBuffersEXT", "more than max draw buffers");
@@ -96,6 +98,90 @@
}
}
+// static
+bool EXTDrawBuffers::satisfiesWebGLRequirements(WebGLRenderingContext* webglContext)
+{
+ GraphicsContext3D* context = webglContext->graphicsContext3D();
+
+ // This is called after we make sure GL_EXT_draw_buffers is supported.
+ GC3Dint maxDrawBuffers = 0;
+ GC3Dint maxColorAttachments = 0;
+ context->getIntegerv(Extensions3D::MAX_DRAW_BUFFERS_EXT, &maxDrawBuffers);
+ context->getIntegerv(Extensions3D::MAX_COLOR_ATTACHMENTS_EXT, &maxColorAttachments);
+ if (maxDrawBuffers < 4 || maxColorAttachments < 4)
+ return false;
+
+ Platform3DObject fbo = context->createFramebuffer();
+ context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, fbo);
+
+#if PLATFORM(CHROMIUM)
+ const unsigned char* buffer = 0; // Chromium doesn't allow init data for depth/stencil tetxures.
+#else
+ const unsigned char buffer[4] = { 0, 0, 0, 0 }; // textures are required to be initialized for other ports.
+#endif
+ bool supportsDepth = (context->getExtensions()->supports("GL_CHROMIUM_depth_texture")
+ || context->getExtensions()->supports("GL_OES_depth_texture")
+ || context->getExtensions()->supports("GL_ARB_depth_texture"));
+ bool supportsDepthStencil = (context->getExtensions()->supports("GL_EXT_packed_depth_stencil")
+ || context->getExtensions()->supports("GL_OES_packed_depth_stencil"));
+ Platform3DObject depthStencil = 0;
+ if (supportsDepthStencil) {
+ depthStencil = context->createTexture();
+ context->bindTexture(GraphicsContext3D::TEXTURE_2D, depthStencil);
+ context->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::DEPTH_STENCIL, 1, 1, 0, GraphicsContext3D::DEPTH_STENCIL, GraphicsContext3D::UNSIGNED_INT_24_8, buffer);
+ }
+ Platform3DObject depth = 0;
+ if (supportsDepth) {
+ depth = context->createTexture();
+ context->bindTexture(GraphicsContext3D::TEXTURE_2D, depth);
+ context->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::DEPTH_COMPONENT, 1, 1, 0, GraphicsContext3D::DEPTH_COMPONENT, GraphicsContext3D::UNSIGNED_INT, buffer);
+ }
+
+ Vector<Platform3DObject> colors;
+ bool ok = true;
+ GC3Dint maxAllowedBuffers = std::min(maxDrawBuffers, maxColorAttachments);
+ for (GC3Dint i = 0; i < maxAllowedBuffers; ++i) {
+ Platform3DObject color = context->createTexture();
+ colors.append(color);
+ context->bindTexture(GraphicsContext3D::TEXTURE_2D, color);
+ context->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, 1, 1, 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, buffer);
+ context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0 + i, GraphicsContext3D::TEXTURE_2D, color, 0);
+ if (context->checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER) != GraphicsContext3D::FRAMEBUFFER_COMPLETE) {
+ ok = false;
+ break;
+ }
+ if (supportsDepth) {
+ context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::DEPTH_ATTACHMENT, GraphicsContext3D::TEXTURE_2D, depth, 0);
+ if (context->checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER) != GraphicsContext3D::FRAMEBUFFER_COMPLETE) {
+ ok = false;
+ break;
+ }
+ context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::DEPTH_ATTACHMENT, GraphicsContext3D::TEXTURE_2D, 0, 0);
+ }
+ if (supportsDepthStencil) {
+ context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::DEPTH_ATTACHMENT, GraphicsContext3D::TEXTURE_2D, depthStencil, 0);
+ context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::STENCIL_ATTACHMENT, GraphicsContext3D::TEXTURE_2D, depthStencil, 0);
+ if (context->checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER) != GraphicsContext3D::FRAMEBUFFER_COMPLETE) {
+ ok = false;
+ break;
+ }
+ context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::DEPTH_ATTACHMENT, GraphicsContext3D::TEXTURE_2D, 0, 0);
+ context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::STENCIL_ATTACHMENT, GraphicsContext3D::TEXTURE_2D, 0, 0);
+ }
+ }
+
+ webglContext->restoreCurrentFramebuffer();
+ context->deleteFramebuffer(fbo);
+ webglContext->restoreCurrentTexture2D();
+ if (supportsDepth)
+ context->deleteTexture(depth);
+ if (supportsDepthStencil)
+ context->deleteTexture(depthStencil);
+ for (size_t i = 0; i < colors.size(); ++i)
+ context->deleteTexture(colors[i]);
+ return ok;
+}
+
} // namespace WebCore
#endif // ENABLE(WEBGL)
Modified: trunk/Source/WebCore/html/canvas/EXTDrawBuffers.h (146693 => 146694)
--- trunk/Source/WebCore/html/canvas/EXTDrawBuffers.h 2013-03-23 00:44:31 UTC (rev 146693)
+++ trunk/Source/WebCore/html/canvas/EXTDrawBuffers.h 2013-03-23 00:45:21 UTC (rev 146694)
@@ -44,6 +44,8 @@
private:
EXTDrawBuffers(WebGLRenderingContext*);
+
+ static bool satisfiesWebGLRequirements(WebGLRenderingContext*);
};
} // namespace WebCore
Modified: trunk/Source/WebCore/html/canvas/WebGLFramebuffer.cpp (146693 => 146694)
--- trunk/Source/WebCore/html/canvas/WebGLFramebuffer.cpp 2013-03-23 00:44:31 UTC (rev 146693)
+++ trunk/Source/WebCore/html/canvas/WebGLFramebuffer.cpp 2013-03-23 00:45:21 UTC (rev 146694)
@@ -624,6 +624,17 @@
}
}
+GC3Denum WebGLFramebuffer::getDrawBuffer(GC3Denum drawBuffer)
+{
+ int index = static_cast<int>(drawBuffer - Extensions3D::DRAW_BUFFER0_EXT);
+ ASSERT(index >= 0);
+ if (index < static_cast<int>(m_drawBuffers.size()))
+ return m_drawBuffers[index];
+ if (drawBuffer == Extensions3D::DRAW_BUFFER0_EXT)
+ return GraphicsContext3D::COLOR_ATTACHMENT0;
+ return GraphicsContext3D::NONE;
}
+}
+
#endif // ENABLE(WEBGL)
Modified: trunk/Source/WebCore/html/canvas/WebGLFramebuffer.h (146693 => 146694)
--- trunk/Source/WebCore/html/canvas/WebGLFramebuffer.h 2013-03-23 00:44:31 UTC (rev 146693)
+++ trunk/Source/WebCore/html/canvas/WebGLFramebuffer.h 2013-03-23 00:45:21 UTC (rev 146694)
@@ -98,6 +98,8 @@
// Wrapper for drawBuffersEXT/drawBuffersARB to work around a driver bug.
void drawBuffers(const Vector<GC3Denum>& bufs);
+ GC3Denum getDrawBuffer(GC3Denum);
+
protected:
WebGLFramebuffer(WebGLRenderingContext*);
Modified: trunk/Source/WebCore/html/canvas/WebGLRenderingContext.cpp (146693 => 146694)
--- trunk/Source/WebCore/html/canvas/WebGLRenderingContext.cpp 2013-03-23 00:44:31 UTC (rev 146693)
+++ trunk/Source/WebCore/html/canvas/WebGLRenderingContext.cpp 2013-03-23 00:45:21 UTC (rev 146694)
@@ -550,6 +550,10 @@
m_maxDrawBuffers = 0;
m_maxColorAttachments = 0;
+ m_backDrawBuffer = GraphicsContext3D::BACK;
+ m_drawBuffersWebGLRequirementsChecked = false;
+ m_drawBuffersSupported = false;
+
m_defaultVertexArrayObject = WebGLVertexArrayObjectOES::create(this, WebGLVertexArrayObjectOES::VaoTypeDefault);
addContextObject(m_defaultVertexArrayObject.get());
m_boundVertexArrayObject = m_defaultVertexArrayObject;
@@ -2455,7 +2459,7 @@
}
return m_webglDepthTexture.get();
}
- if (equalIgnoringCase(name, "EXT_draw_buffers") && EXTDrawBuffers::supported(this)) {
+ if (equalIgnoringCase(name, "EXT_draw_buffers") && supportsDrawBuffers()) {
if (!m_extDrawBuffers) {
m_context->getExtensions()->ensureEnabled("GL_EXT_draw_buffers");
m_extDrawBuffers = EXTDrawBuffers::create(this);
@@ -2755,41 +2759,17 @@
return WebGLGetInfo(getMaxDrawBuffers());
synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name, EXT_draw_buffers not enabled");
return WebGLGetInfo();
- case Extensions3D::DRAW_BUFFER0_EXT: // DRAW_BUFFER0_EXT is special as the backbuffer is simulated.
- if (m_extDrawBuffers) {
- GC3Dint value = 0;
- m_context->getIntegerv(pname, &value);
- if (!m_framebufferBinding && value != GraphicsContext3D::NONE)
- value = GraphicsContext3D::BACK;
+ default:
+ if (m_extDrawBuffers
+ && pname >= Extensions3D::DRAW_BUFFER0_EXT
+ && pname < static_cast<GC3Denum>(Extensions3D::DRAW_BUFFER0_EXT + getMaxDrawBuffers())) {
+ GC3Dint value = GraphicsContext3D::NONE;
+ if (m_framebufferBinding)
+ value = m_framebufferBinding->getDrawBuffer(pname);
+ else // emulated backbuffer
+ value = m_backDrawBuffer;
return WebGLGetInfo(value);
}
- synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name, EXT_draw_buffers not enabled");
- return WebGLGetInfo();
- case Extensions3D::DRAW_BUFFER1_EXT:
- case Extensions3D::DRAW_BUFFER2_EXT:
- case Extensions3D::DRAW_BUFFER3_EXT:
- case Extensions3D::DRAW_BUFFER4_EXT:
- case Extensions3D::DRAW_BUFFER5_EXT:
- case Extensions3D::DRAW_BUFFER6_EXT:
- case Extensions3D::DRAW_BUFFER7_EXT:
- case Extensions3D::DRAW_BUFFER8_EXT:
- case Extensions3D::DRAW_BUFFER9_EXT:
- case Extensions3D::DRAW_BUFFER10_EXT:
- case Extensions3D::DRAW_BUFFER11_EXT:
- case Extensions3D::DRAW_BUFFER12_EXT:
- case Extensions3D::DRAW_BUFFER13_EXT:
- case Extensions3D::DRAW_BUFFER14_EXT:
- case Extensions3D::DRAW_BUFFER15_EXT: // EXT_draw_buffers END
- if (m_extDrawBuffers) {
- if (static_cast<GC3Denum>(Extensions3D::DRAW_BUFFER0_EXT + getMaxDrawBuffers()) <= pname) {
- synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter, exceeds MAX_COLOR_ATTACHMENTS_EXT");
- return WebGLGetInfo();
- }
- return getIntParameter(pname);
- }
- synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name, EXT_draw_buffers not enabled");
- return WebGLGetInfo();
- default:
synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name");
return WebGLGetInfo();
}
@@ -2995,7 +2975,7 @@
result.append("WEBKIT_WEBGL_compressed_texture_s3tc");
if (WebGLDepthTexture::supported(graphicsContext3D()))
result.append("WEBKIT_WEBGL_depth_texture");
- if (EXTDrawBuffers::supported(this))
+ if (supportsDrawBuffers())
result.append("EXT_draw_buffers");
if (allowPrivilegedExtensions()) {
@@ -5548,32 +5528,11 @@
case GraphicsContext3D::STENCIL_ATTACHMENT:
case GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT:
break;
- case Extensions3D::COLOR_ATTACHMENT1_EXT: // EXT_draw_buffers BEGIN
- case Extensions3D::COLOR_ATTACHMENT2_EXT:
- case Extensions3D::COLOR_ATTACHMENT3_EXT:
- case Extensions3D::COLOR_ATTACHMENT4_EXT:
- case Extensions3D::COLOR_ATTACHMENT5_EXT:
- case Extensions3D::COLOR_ATTACHMENT6_EXT:
- case Extensions3D::COLOR_ATTACHMENT7_EXT:
- case Extensions3D::COLOR_ATTACHMENT8_EXT:
- case Extensions3D::COLOR_ATTACHMENT9_EXT:
- case Extensions3D::COLOR_ATTACHMENT10_EXT:
- case Extensions3D::COLOR_ATTACHMENT11_EXT:
- case Extensions3D::COLOR_ATTACHMENT12_EXT:
- case Extensions3D::COLOR_ATTACHMENT13_EXT:
- case Extensions3D::COLOR_ATTACHMENT14_EXT:
- case Extensions3D::COLOR_ATTACHMENT15_EXT: // EXT_draw_buffers END
- // COLOR_ATTACHMENT0_EXT is equal to COLOR_ATTACHMENT0.
- if (!m_extDrawBuffers) {
- synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid attachment, EXT_draw_buffers not enabled");
- return false;
- }
- if (static_cast<GC3Denum>(Extensions3D::COLOR_ATTACHMENT0_EXT + getMaxColorAttachments()) <= attachment) {
- synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid attachment, exceeds MAX_DRAW_BUFFERS_EXT");
- return false;
- }
- break;
default:
+ if (m_extDrawBuffers
+ && attachment > GraphicsContext3D::COLOR_ATTACHMENT0
+ && attachment < static_cast<GC3Denum>(GraphicsContext3D::COLOR_ATTACHMENT0 + getMaxColorAttachments()))
+ break;
synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid attachment");
return false;
}
@@ -6092,18 +6051,51 @@
GC3Dint WebGLRenderingContext::getMaxDrawBuffers()
{
- if (!m_maxDrawBuffers && EXTDrawBuffers::supported(this))
+ if (!supportsDrawBuffers())
+ return 0;
+ if (!m_maxDrawBuffers)
m_context->getIntegerv(Extensions3D::MAX_DRAW_BUFFERS_EXT, &m_maxDrawBuffers);
- return m_maxDrawBuffers;
+ if (!m_maxColorAttachments)
+ m_context->getIntegerv(Extensions3D::MAX_COLOR_ATTACHMENTS_EXT, &m_maxColorAttachments);
+ // WEBGL_draw_buffers requires MAX_COLOR_ATTACHMENTS >= MAX_DRAW_BUFFERS.
+ return std::min(m_maxDrawBuffers, m_maxColorAttachments);
}
GC3Dint WebGLRenderingContext::getMaxColorAttachments()
{
- if (!m_maxColorAttachments && EXTDrawBuffers::supported(this))
+ if (!supportsDrawBuffers())
+ return 0;
+ if (!m_maxColorAttachments)
m_context->getIntegerv(Extensions3D::MAX_COLOR_ATTACHMENTS_EXT, &m_maxColorAttachments);
return m_maxColorAttachments;
}
+void WebGLRenderingContext::setBackDrawBuffer(GC3Denum buf)
+{
+ m_backDrawBuffer = buf;
+}
+
+void WebGLRenderingContext::restoreCurrentFramebuffer()
+{
+ ExceptionCode ec;
+ bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_framebufferBinding.get(), ec);
+}
+
+void WebGLRenderingContext::restoreCurrentTexture2D()
+{
+ ExceptionCode ec;
+ bindTexture(GraphicsContext3D::TEXTURE_2D, m_textureUnits[m_activeTextureUnit].m_texture2DBinding.get(), ec);
+}
+
+bool WebGLRenderingContext::supportsDrawBuffers()
+{
+ if (!m_drawBuffersWebGLRequirementsChecked) {
+ m_drawBuffersWebGLRequirementsChecked = true;
+ m_drawBuffersSupported = EXTDrawBuffers::supported(this);
+ }
+ return m_drawBuffersSupported;
+}
+
} // namespace WebCore
#endif // ENABLE(WEBGL)
Modified: trunk/Source/WebCore/html/canvas/WebGLRenderingContext.h (146693 => 146694)
--- trunk/Source/WebCore/html/canvas/WebGLRenderingContext.h 2013-03-23 00:44:31 UTC (rev 146693)
+++ trunk/Source/WebCore/html/canvas/WebGLRenderingContext.h 2013-03-23 00:45:21 UTC (rev 146694)
@@ -483,6 +483,9 @@
GC3Dint m_maxDrawBuffers;
GC3Dint m_maxColorAttachments;
+ GC3Denum m_backDrawBuffer;
+ bool m_drawBuffersWebGLRequirementsChecked;
+ bool m_drawBuffersSupported;
GC3Dint m_packAlignment;
GC3Dint m_unpackAlignment;
@@ -748,6 +751,14 @@
GC3Dint getMaxDrawBuffers();
GC3Dint getMaxColorAttachments();
+ void setBackDrawBuffer(GC3Denum);
+
+ void restoreCurrentFramebuffer();
+ void restoreCurrentTexture2D();
+
+ // Check if EXT_draw_buffers extension is supported and if it satisfies the WebGL requirements.
+ bool supportsDrawBuffers();
+
friend class WebGLStateRestorer;
};