summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/html/canvas/WebGLFramebuffer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/html/canvas/WebGLFramebuffer.cpp')
-rw-r--r--Source/WebCore/html/canvas/WebGLFramebuffer.cpp210
1 files changed, 176 insertions, 34 deletions
diff --git a/Source/WebCore/html/canvas/WebGLFramebuffer.cpp b/Source/WebCore/html/canvas/WebGLFramebuffer.cpp
index 4b721eb..3c1c718 100644
--- a/Source/WebCore/html/canvas/WebGLFramebuffer.cpp
+++ b/Source/WebCore/html/canvas/WebGLFramebuffer.cpp
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2012 Sony Mobile Communications AB
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -35,12 +36,47 @@ namespace WebCore {
namespace {
- // This function is only for depth/stencil/depth_stencil attachment.
- // Currently we assume these attachments are all renderbuffers.
- GC3Denum getInternalFormat(WebGLObject* buffer)
+ bool isAttachmentComplete(WebGLObject* attachedObject, GC3Denum attachment)
{
- ASSERT(buffer && buffer->isRenderbuffer());
- return (reinterpret_cast<WebGLRenderbuffer*>(buffer))->getInternalFormat();
+ ASSERT(attachedObject && attachedObject->object());
+ ASSERT(attachedObject->isRenderbuffer());
+ WebGLRenderbuffer* buffer = reinterpret_cast<WebGLRenderbuffer*>(attachedObject);
+ switch (attachment) {
+ case GraphicsContext3D::DEPTH_ATTACHMENT:
+ if (buffer->getInternalFormat() != GraphicsContext3D::DEPTH_COMPONENT16)
+ return false;
+ break;
+ case GraphicsContext3D::STENCIL_ATTACHMENT:
+ if (buffer->getInternalFormat() != GraphicsContext3D::STENCIL_INDEX8)
+ return false;
+ break;
+ case GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT:
+ if (buffer->getInternalFormat() != GraphicsContext3D::DEPTH_STENCIL)
+ return false;
+ break;
+ default:
+ ASSERT_NOT_REACHED();
+ return false;
+ }
+ if (!buffer->getWidth() || !buffer->getHeight())
+ return false;
+ return true;
+ }
+
+ GC3Dsizei getImageWidth(WebGLObject* attachedObject)
+ {
+ ASSERT(attachedObject && attachedObject->object());
+ ASSERT(attachedObject->isRenderbuffer());
+ WebGLRenderbuffer* buffer = reinterpret_cast<WebGLRenderbuffer*>(attachedObject);
+ return buffer->getWidth();
+ }
+
+ GC3Dsizei getImageHeight(WebGLObject* attachedObject)
+ {
+ ASSERT(attachedObject && attachedObject->object());
+ ASSERT(attachedObject->isRenderbuffer());
+ WebGLRenderbuffer* buffer = reinterpret_cast<WebGLRenderbuffer*>(attachedObject);
+ return buffer->getHeight();
}
bool isUninitialized(WebGLObject* attachedObject)
@@ -82,10 +118,12 @@ WebGLFramebuffer::WebGLFramebuffer(WebGLRenderingContext* ctx)
setObject(context()->graphicsContext3D()->createFramebuffer());
}
-void WebGLFramebuffer::setAttachment(GC3Denum attachment, GC3Denum texTarget, WebGLTexture* texture, GC3Dint level)
+void WebGLFramebuffer::setAttachmentForBoundFramebuffer(GC3Denum attachment, GC3Denum texTarget, WebGLTexture* texture, GC3Dint level)
{
+ ASSERT(isBound());
if (!object())
return;
+ removeAttachmentFromBoundFramebuffer(attachment);
if (texture && !texture->object())
texture = 0;
switch (attachment) {
@@ -106,14 +144,19 @@ void WebGLFramebuffer::setAttachment(GC3Denum attachment, GC3Denum texTarget, We
m_depthStencilAttachment = texture;
break;
default:
- return;
+ ASSERT_NOT_REACHED();
+ break;
}
+ if (texture)
+ texture->onAttached();
}
-void WebGLFramebuffer::setAttachment(GC3Denum attachment, WebGLRenderbuffer* renderbuffer)
+void WebGLFramebuffer::setAttachmentForBoundFramebuffer(GC3Denum attachment, WebGLRenderbuffer* renderbuffer)
{
+ ASSERT(isBound());
if (!object())
return;
+ removeAttachmentFromBoundFramebuffer(attachment);
if (renderbuffer && !renderbuffer->object())
renderbuffer = 0;
switch (attachment) {
@@ -130,8 +173,11 @@ void WebGLFramebuffer::setAttachment(GC3Denum attachment, WebGLRenderbuffer* ren
m_depthStencilAttachment = renderbuffer;
break;
default:
- return;
+ ASSERT_NOT_REACHED();
+ break;
}
+ if (renderbuffer)
+ renderbuffer->onAttached();
}
WebGLObject* WebGLFramebuffer::getAttachment(GC3Denum attachment) const
@@ -148,24 +194,78 @@ WebGLObject* WebGLFramebuffer::getAttachment(GC3Denum attachment) const
case GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT:
return m_depthStencilAttachment.get();
default:
+ ASSERT_NOT_REACHED();
return 0;
}
}
-void WebGLFramebuffer::removeAttachment(WebGLObject* attachment)
+void WebGLFramebuffer::removeAttachmentFromBoundFramebuffer(GC3Denum attachment)
{
+ ASSERT(isBound());
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
+
+ switch (attachment) {
+ case GraphicsContext3D::COLOR_ATTACHMENT0:
+ if (m_colorAttachment) {
+ m_colorAttachment->onDetached();
+ m_colorAttachment = 0;
+ m_texTarget = 0;
+ m_texLevel = -1;
+ }
+ break;
+ case GraphicsContext3D::DEPTH_ATTACHMENT:
+ if (m_depthAttachment) {
+ m_depthAttachment->onDetached();
+ m_depthAttachment = 0;
+ }
+ break;
+ case GraphicsContext3D::STENCIL_ATTACHMENT:
+ if (m_stencilAttachment) {
+ m_stencilAttachment->onDetached();
+ m_stencilAttachment = 0;
+ }
+ break;
+ case GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT:
+ if (m_depthStencilAttachment) {
+ m_depthStencilAttachment->onDetached();
+ m_depthStencilAttachment = 0;
+ }
+ break;
+ default:
+ ASSERT_NOT_REACHED();
+ break;
+ }
+}
+
+void WebGLFramebuffer::removeAttachmentFromBoundFramebuffer(WebGLObject* attachment)
+{
+ ASSERT(isBound());
+ if (!object())
+ return;
+ if (!attachment)
return;
+ GraphicsContext3D* gc3d = context()->graphicsContext3D();
+ if (attachment == m_colorAttachment.get()) {
+ if (attachment->isRenderbuffer())
+ gc3d->framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::RENDERBUFFER, 0);
+ else
+ gc3d->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, m_texTarget, 0, m_texLevel);
+ removeAttachmentFromBoundFramebuffer(GraphicsContext3D::COLOR_ATTACHMENT0);
+ }
+ if (attachment == m_depthAttachment.get()) {
+ gc3d->framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::DEPTH_ATTACHMENT, GraphicsContext3D::RENDERBUFFER, 0);
+ removeAttachmentFromBoundFramebuffer(GraphicsContext3D::DEPTH_ATTACHMENT);
+ }
+ if (attachment == m_stencilAttachment.get()) {
+ gc3d->framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::STENCIL_ATTACHMENT, GraphicsContext3D::RENDERBUFFER, 0);
+ removeAttachmentFromBoundFramebuffer(GraphicsContext3D::STENCIL_ATTACHMENT);
+ }
+ if (attachment == m_depthStencilAttachment.get()) {
+ gc3d->framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::DEPTH_ATTACHMENT, GraphicsContext3D::RENDERBUFFER, 0);
+ gc3d->framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::STENCIL_ATTACHMENT, GraphicsContext3D::RENDERBUFFER, 0);
+ removeAttachmentFromBoundFramebuffer(GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT);
+ }
}
GC3Dsizei WebGLFramebuffer::getWidth() const
@@ -213,34 +313,67 @@ GC3Denum WebGLFramebuffer::getColorBufferFormat() const
return 0;
}
-bool WebGLFramebuffer::isIncomplete(bool checkInternalFormat) const
+GC3Denum WebGLFramebuffer::checkStatus() const
{
unsigned int count = 0;
+ GC3Dsizei width = 0, height = 0;
if (isDepthAttached()) {
- if (checkInternalFormat && getInternalFormat(m_depthAttachment.get()) != GraphicsContext3D::DEPTH_COMPONENT16)
- return true;
+ if (!isAttachmentComplete(m_depthAttachment.get(), GraphicsContext3D::DEPTH_ATTACHMENT))
+ return GraphicsContext3D::FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+ width = getImageWidth(m_depthAttachment.get());
+ height = getImageHeight(m_depthAttachment.get());
count++;
}
if (isStencilAttached()) {
- if (checkInternalFormat && getInternalFormat(m_stencilAttachment.get()) != GraphicsContext3D::STENCIL_INDEX8)
- return true;
+ if (!isAttachmentComplete(m_stencilAttachment.get(), GraphicsContext3D::STENCIL_ATTACHMENT))
+ return GraphicsContext3D::FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+ if (!count) {
+ width = getImageWidth(m_stencilAttachment.get());
+ height = getImageHeight(m_stencilAttachment.get());
+ } else {
+ if (width != getImageWidth(m_stencilAttachment.get()) || height != getImageHeight(m_stencilAttachment.get()))
+ return GraphicsContext3D::FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
+ }
count++;
}
if (isDepthStencilAttached()) {
- if (checkInternalFormat && getInternalFormat(m_depthStencilAttachment.get()) != GraphicsContext3D::DEPTH_STENCIL)
- return true;
+ if (!isAttachmentComplete(m_depthStencilAttachment.get(), GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT))
+ return GraphicsContext3D::FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
if (!isValid(m_depthStencilAttachment.get()))
- return true;
+ return GraphicsContext3D::FRAMEBUFFER_UNSUPPORTED;
+ if (!count) {
+ width = getImageWidth(m_depthStencilAttachment.get());
+ height = getImageHeight(m_depthStencilAttachment.get());
+ } else {
+ if (width != getImageWidth(m_depthStencilAttachment.get()) || height != getImageHeight(m_depthStencilAttachment.get()))
+ return GraphicsContext3D::FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
+ }
count++;
}
+ // WebGL specific: no conflicting DEPTH/STENCIL/DEPTH_STENCIL attachments.
if (count > 1)
- return true;
- return false;
+ return GraphicsContext3D::FRAMEBUFFER_UNSUPPORTED;
+ if (isColorAttached()) {
+ // FIXME: if color buffer is texture, is ALPHA, LUMINANCE or LUMINANCE_ALPHA valid?
+ if (!getColorBufferFormat())
+ return GraphicsContext3D::FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+ if (!count) {
+ if (!getWidth() || !getHeight())
+ return GraphicsContext3D::FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+ } else {
+ if (width != getWidth() || height != getHeight())
+ return GraphicsContext3D::FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
+ }
+ } else {
+ if (!count)
+ return GraphicsContext3D::FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
+ }
+ return GraphicsContext3D::FRAMEBUFFER_COMPLETE;
}
bool WebGLFramebuffer::onAccess(bool needToInitializeRenderbuffers)
{
- if (isIncomplete(true))
+ if (checkStatus() != GraphicsContext3D::FRAMEBUFFER_COMPLETE)
return false;
if (needToInitializeRenderbuffers)
return initializeRenderbuffers();
@@ -249,11 +382,15 @@ bool WebGLFramebuffer::onAccess(bool needToInitializeRenderbuffers)
void WebGLFramebuffer::deleteObjectImpl(Platform3DObject object)
{
+ if (m_colorAttachment)
+ m_colorAttachment->onDetached();
+ if (m_depthAttachment)
+ m_depthAttachment->onDetached();
+ if (m_stencilAttachment)
+ m_stencilAttachment->onDetached();
+ if (m_depthStencilAttachment)
+ m_depthStencilAttachment->onDetached();
context()->graphicsContext3D()->deleteFramebuffer(object);
- m_colorAttachment = 0;
- m_depthAttachment = 0;
- m_stencilAttachment = 0;
- m_depthStencilAttachment = 0;
}
bool WebGLFramebuffer::initializeRenderbuffers()
@@ -352,6 +489,11 @@ bool WebGLFramebuffer::initializeRenderbuffers()
return true;
}
+bool WebGLFramebuffer::isBound() const
+{
+ return (context()->m_framebufferBinding.get() == this);
+}
+
}
#endif // ENABLE(WEBGL)