summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/html/canvas/WebGLFramebuffer.cpp
diff options
context:
space:
mode:
authorSteve Block <steveblock@google.com>2011-05-06 11:45:16 +0100
committerSteve Block <steveblock@google.com>2011-05-12 13:44:10 +0100
commitcad810f21b803229eb11403f9209855525a25d57 (patch)
tree29a6fd0279be608e0fe9ffe9841f722f0f4e4269 /Source/WebCore/html/canvas/WebGLFramebuffer.cpp
parent121b0cf4517156d0ac5111caf9830c51b69bae8f (diff)
downloadexternal_webkit-cad810f21b803229eb11403f9209855525a25d57.zip
external_webkit-cad810f21b803229eb11403f9209855525a25d57.tar.gz
external_webkit-cad810f21b803229eb11403f9209855525a25d57.tar.bz2
Merge WebKit at r75315: Initial merge by git.
Change-Id: I570314b346ce101c935ed22a626b48c2af266b84
Diffstat (limited to 'Source/WebCore/html/canvas/WebGLFramebuffer.cpp')
-rw-r--r--Source/WebCore/html/canvas/WebGLFramebuffer.cpp357
1 files changed, 357 insertions, 0 deletions
diff --git a/Source/WebCore/html/canvas/WebGLFramebuffer.cpp b/Source/WebCore/html/canvas/WebGLFramebuffer.cpp
new file mode 100644
index 0000000..a1c3a9a
--- /dev/null
+++ b/Source/WebCore/html/canvas/WebGLFramebuffer.cpp
@@ -0,0 +1,357 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(3D_CANVAS)
+
+#include "WebGLFramebuffer.h"
+
+#include "WebGLRenderingContext.h"
+
+namespace WebCore {
+
+namespace {
+
+ // This function is only for depth/stencil/depth_stencil attachment.
+ // Currently we assume these attachments are all renderbuffers.
+ unsigned long getInternalFormat(WebGLObject* buffer)
+ {
+ ASSERT(buffer && buffer->isRenderbuffer());
+ return (reinterpret_cast<WebGLRenderbuffer*>(buffer))->getInternalFormat();
+ }
+
+ bool isUninitialized(WebGLObject* attachedObject)
+ {
+ if (attachedObject && attachedObject->object() && attachedObject->isRenderbuffer()
+ && !(reinterpret_cast<WebGLRenderbuffer*>(attachedObject))->isInitialized())
+ return true;
+ return false;
+ }
+
+ void setInitialized(WebGLObject* attachedObject)
+ {
+ if (attachedObject && attachedObject->object() && attachedObject->isRenderbuffer())
+ (reinterpret_cast<WebGLRenderbuffer*>(attachedObject))->setInitialized();
+ }
+
+ bool isValid(WebGLObject* attachedObject)
+ {
+ if (attachedObject && attachedObject->object() && attachedObject->isRenderbuffer()) {
+ if (!(reinterpret_cast<WebGLRenderbuffer*>(attachedObject))->isValid())
+ return false;
+ }
+ return true;
+ }
+
+} // anonymous namespace
+
+PassRefPtr<WebGLFramebuffer> WebGLFramebuffer::create(WebGLRenderingContext* ctx)
+{
+ return adoptRef(new WebGLFramebuffer(ctx));
+}
+
+WebGLFramebuffer::WebGLFramebuffer(WebGLRenderingContext* ctx)
+ : WebGLObject(ctx)
+ , m_hasEverBeenBound(false)
+ , m_texTarget(0)
+ , m_texLevel(-1)
+{
+ setObject(context()->graphicsContext3D()->createFramebuffer());
+}
+
+void WebGLFramebuffer::setAttachment(unsigned long attachment, unsigned long texTarget, WebGLTexture* texture, int level)
+{
+ if (!object())
+ return;
+ if (texture && !texture->object())
+ texture = 0;
+ switch (attachment) {
+ case GraphicsContext3D::COLOR_ATTACHMENT0:
+ m_colorAttachment = texture;
+ if (texture) {
+ m_texTarget = texTarget;
+ m_texLevel = level;
+ }
+ break;
+ case GraphicsContext3D::DEPTH_ATTACHMENT:
+ m_depthAttachment = texture;
+ break;
+ case GraphicsContext3D::STENCIL_ATTACHMENT:
+ m_stencilAttachment = texture;
+ break;
+ case GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT:
+ m_depthStencilAttachment = texture;
+ break;
+ default:
+ return;
+ }
+}
+
+void WebGLFramebuffer::setAttachment(unsigned long attachment, WebGLRenderbuffer* renderbuffer)
+{
+ if (!object())
+ return;
+ if (renderbuffer && !renderbuffer->object())
+ renderbuffer = 0;
+ switch (attachment) {
+ case GraphicsContext3D::COLOR_ATTACHMENT0:
+ m_colorAttachment = renderbuffer;
+ break;
+ case GraphicsContext3D::DEPTH_ATTACHMENT:
+ m_depthAttachment = renderbuffer;
+ break;
+ case GraphicsContext3D::STENCIL_ATTACHMENT:
+ m_stencilAttachment = renderbuffer;
+ break;
+ case GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT:
+ m_depthStencilAttachment = renderbuffer;
+ break;
+ default:
+ return;
+ }
+}
+
+WebGLObject* WebGLFramebuffer::getAttachment(unsigned long attachment) const
+{
+ if (!object())
+ return 0;
+ switch (attachment) {
+ case GraphicsContext3D::COLOR_ATTACHMENT0:
+ return m_colorAttachment.get();
+ case GraphicsContext3D::DEPTH_ATTACHMENT:
+ return m_depthAttachment.get();
+ case GraphicsContext3D::STENCIL_ATTACHMENT:
+ return m_stencilAttachment.get();
+ case GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT:
+ return m_depthStencilAttachment.get();
+ default:
+ return 0;
+ }
+}
+
+void WebGLFramebuffer::removeAttachment(WebGLObject* attachment)
+{
+ if (!object())
+ return;
+ if (attachment == m_colorAttachment.get())
+ m_colorAttachment = 0;
+ else if (attachment == m_depthAttachment.get())
+ m_depthAttachment = 0;
+ else if (attachment == m_stencilAttachment.get())
+ m_stencilAttachment = 0;
+ else if (attachment == m_depthStencilAttachment.get())
+ m_depthStencilAttachment = 0;
+ else
+ return;
+}
+
+int WebGLFramebuffer::getWidth() const
+{
+ if (!object() || !isColorAttached())
+ return 0;
+ if (m_colorAttachment->isRenderbuffer())
+ return (reinterpret_cast<WebGLRenderbuffer*>(m_colorAttachment.get()))->getWidth();
+ if (m_colorAttachment->isTexture())
+ return (reinterpret_cast<WebGLTexture*>(m_colorAttachment.get()))->getWidth(m_texTarget, m_texLevel);
+ ASSERT_NOT_REACHED();
+ return 0;
+}
+
+int WebGLFramebuffer::getHeight() const
+{
+ if (!object() || !isColorAttached())
+ return 0;
+ if (m_colorAttachment->isRenderbuffer())
+ return (reinterpret_cast<WebGLRenderbuffer*>(m_colorAttachment.get()))->getHeight();
+ if (m_colorAttachment->isTexture())
+ return (reinterpret_cast<WebGLTexture*>(m_colorAttachment.get()))->getHeight(m_texTarget, m_texLevel);
+ ASSERT_NOT_REACHED();
+ return 0;
+}
+
+unsigned long WebGLFramebuffer::getColorBufferFormat() const
+{
+ if (!object() || !isColorAttached())
+ return 0;
+ if (m_colorAttachment->isRenderbuffer()) {
+ unsigned long format = (reinterpret_cast<WebGLRenderbuffer*>(m_colorAttachment.get()))->getInternalFormat();
+ switch (format) {
+ case GraphicsContext3D::RGBA4:
+ case GraphicsContext3D::RGB5_A1:
+ return GraphicsContext3D::RGBA;
+ case GraphicsContext3D::RGB565:
+ return GraphicsContext3D::RGB;
+ }
+ return 0;
+ }
+ if (m_colorAttachment->isTexture())
+ return (reinterpret_cast<WebGLTexture*>(m_colorAttachment.get()))->getInternalFormat(m_texTarget, m_texLevel);
+ ASSERT_NOT_REACHED();
+ return 0;
+}
+
+bool WebGLFramebuffer::isIncomplete(bool checkInternalFormat) const
+{
+ unsigned int count = 0;
+ if (isDepthAttached()) {
+ if (checkInternalFormat && getInternalFormat(m_depthAttachment.get()) != GraphicsContext3D::DEPTH_COMPONENT16)
+ return true;
+ count++;
+ }
+ if (isStencilAttached()) {
+ if (checkInternalFormat && getInternalFormat(m_stencilAttachment.get()) != GraphicsContext3D::STENCIL_INDEX8)
+ return true;
+ count++;
+ }
+ if (isDepthStencilAttached()) {
+ if (checkInternalFormat && getInternalFormat(m_depthStencilAttachment.get()) != GraphicsContext3D::DEPTH_STENCIL)
+ return true;
+ if (!isValid(m_depthStencilAttachment.get()))
+ return true;
+ count++;
+ }
+ if (count > 1)
+ return true;
+ return false;
+}
+
+bool WebGLFramebuffer::onAccess(bool needToInitializeRenderbuffers)
+{
+ if (isIncomplete(true))
+ return false;
+ if (needToInitializeRenderbuffers)
+ return initializeRenderbuffers();
+ return true;
+}
+
+void WebGLFramebuffer::deleteObjectImpl(Platform3DObject object)
+{
+ context()->graphicsContext3D()->deleteFramebuffer(object);
+ m_colorAttachment = 0;
+ m_depthAttachment = 0;
+ m_stencilAttachment = 0;
+ m_depthStencilAttachment = 0;
+}
+
+bool WebGLFramebuffer::initializeRenderbuffers()
+{
+ ASSERT(object());
+ bool initColor = false, initDepth = false, initStencil = false;
+ unsigned long mask = 0;
+ if (isUninitialized(m_colorAttachment.get())) {
+ initColor = true;
+ mask |= GraphicsContext3D::COLOR_BUFFER_BIT;
+ }
+ if (isUninitialized(m_depthAttachment.get())) {
+ initDepth = true;
+ mask |= GraphicsContext3D::DEPTH_BUFFER_BIT;
+ }
+ if (isUninitialized(m_stencilAttachment.get())) {
+ initStencil = true;
+ mask |= GraphicsContext3D::STENCIL_BUFFER_BIT;
+ }
+ if (isUninitialized(m_depthStencilAttachment.get())) {
+ initDepth = true;
+ initStencil = true;
+ mask |= (GraphicsContext3D::DEPTH_BUFFER_BIT | GraphicsContext3D::STENCIL_BUFFER_BIT);
+ }
+ if (!initColor && !initDepth && !initStencil)
+ return true;
+
+ // We only clear un-initialized renderbuffers when they are ready to be
+ // read, i.e., when the framebuffer is complete.
+ GraphicsContext3D* g3d = context()->graphicsContext3D();
+ if (g3d->checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER) != GraphicsContext3D::FRAMEBUFFER_COMPLETE)
+ return false;
+
+ float colorClearValue[] = {0, 0, 0, 0}, depthClearValue = 0;
+ int stencilClearValue = 0;
+ unsigned char colorMask[] = {0, 0, 0, 0}, depthMask = 0;
+ unsigned int stencilMask = 0xffffffff;
+ bool isScissorEnabled = false;
+ bool isDitherEnabled = false;
+ if (initColor) {
+ g3d->getFloatv(GraphicsContext3D::COLOR_CLEAR_VALUE, colorClearValue);
+ g3d->getBooleanv(GraphicsContext3D::COLOR_WRITEMASK, colorMask);
+ g3d->clearColor(0, 0, 0, 0);
+ g3d->colorMask(true, true, true, true);
+ }
+ if (initDepth) {
+ g3d->getFloatv(GraphicsContext3D::DEPTH_CLEAR_VALUE, &depthClearValue);
+ g3d->getBooleanv(GraphicsContext3D::DEPTH_WRITEMASK, &depthMask);
+ g3d->clearDepth(0);
+ g3d->depthMask(true);
+ }
+ if (initStencil) {
+ g3d->getIntegerv(GraphicsContext3D::STENCIL_CLEAR_VALUE, &stencilClearValue);
+ g3d->getIntegerv(GraphicsContext3D::STENCIL_WRITEMASK, reinterpret_cast<int*>(&stencilMask));
+ g3d->clearStencil(0);
+ g3d->stencilMask(0xffffffff);
+ }
+ isScissorEnabled = g3d->isEnabled(GraphicsContext3D::SCISSOR_TEST);
+ g3d->disable(GraphicsContext3D::SCISSOR_TEST);
+ isDitherEnabled = g3d->isEnabled(GraphicsContext3D::DITHER);
+ g3d->disable(GraphicsContext3D::DITHER);
+
+ g3d->clear(mask);
+
+ if (initColor) {
+ g3d->clearColor(colorClearValue[0], colorClearValue[1], colorClearValue[2], colorClearValue[3]);
+ g3d->colorMask(colorMask[0], colorMask[1], colorMask[2], colorMask[3]);
+ }
+ if (initDepth) {
+ g3d->clearDepth(depthClearValue);
+ g3d->depthMask(depthMask);
+ }
+ if (initStencil) {
+ g3d->clearStencil(stencilClearValue);
+ g3d->stencilMask(stencilMask);
+ }
+ if (isScissorEnabled)
+ g3d->enable(GraphicsContext3D::SCISSOR_TEST);
+ else
+ g3d->disable(GraphicsContext3D::SCISSOR_TEST);
+ if (isDitherEnabled)
+ g3d->enable(GraphicsContext3D::DITHER);
+ else
+ g3d->disable(GraphicsContext3D::DITHER);
+
+ if (initColor)
+ setInitialized(m_colorAttachment.get());
+ if (initDepth && initStencil && m_depthStencilAttachment)
+ setInitialized(m_depthStencilAttachment.get());
+ else {
+ if (initDepth)
+ setInitialized(m_depthAttachment.get());
+ if (initStencil)
+ setInitialized(m_stencilAttachment.get());
+ }
+ return true;
+}
+
+}
+
+#endif // ENABLE(3D_CANVAS)