WebCore/html/canvas/WebGLFramebuffer.cpp
changeset 0 4f2f89ce4247
equal deleted inserted replaced
-1:000000000000 0:4f2f89ce4247
       
     1 /*
       
     2  * Copyright (C) 2009 Apple Inc. All rights reserved.
       
     3  *
       
     4  * Redistribution and use in source and binary forms, with or without
       
     5  * modification, are permitted provided that the following conditions
       
     6  * are met:
       
     7  * 1. Redistributions of source code must retain the above copyright
       
     8  *    notice, this list of conditions and the following disclaimer.
       
     9  * 2. Redistributions in binary form must reproduce the above copyright
       
    10  *    notice, this list of conditions and the following disclaimer in the
       
    11  *    documentation and/or other materials provided with the distribution.
       
    12  *
       
    13  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
       
    14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
       
    15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
       
    16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
       
    17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
       
    18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
       
    19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
       
    20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
       
    21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
       
    22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
       
    23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
       
    24  */
       
    25 
       
    26 #include "config.h"
       
    27 
       
    28 #if ENABLE(3D_CANVAS)
       
    29 
       
    30 #include "WebGLFramebuffer.h"
       
    31 #include "WebGLRenderingContext.h"
       
    32 
       
    33 namespace WebCore {
       
    34     
       
    35 PassRefPtr<WebGLFramebuffer> WebGLFramebuffer::create(WebGLRenderingContext* ctx)
       
    36 {
       
    37     return adoptRef(new WebGLFramebuffer(ctx));
       
    38 }
       
    39 
       
    40 WebGLFramebuffer::WebGLFramebuffer(WebGLRenderingContext* ctx)
       
    41     : CanvasObject(ctx)
       
    42     , m_colorAttachment(0)
       
    43     , m_depthAttachment(0)
       
    44     , m_stencilAttachment(0)
       
    45     , m_depthStencilAttachment(0)
       
    46 {
       
    47     setObject(context()->graphicsContext3D()->createFramebuffer());
       
    48 }
       
    49 
       
    50 void WebGLFramebuffer::setAttachment(unsigned long attachment, CanvasObject* attachedObject)
       
    51 {
       
    52     if (!object())
       
    53         return;
       
    54     if (attachedObject && !attachedObject->object())
       
    55         attachedObject = 0;
       
    56     switch (attachment) {
       
    57     case GraphicsContext3D::COLOR_ATTACHMENT0:
       
    58         m_colorAttachment = attachedObject;
       
    59         break;
       
    60     case GraphicsContext3D::DEPTH_ATTACHMENT:
       
    61         m_depthAttachment = attachedObject;
       
    62         break;
       
    63     case GraphicsContext3D::STENCIL_ATTACHMENT:
       
    64         m_stencilAttachment = attachedObject;
       
    65         break;
       
    66     case GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT:
       
    67         m_depthStencilAttachment = attachedObject;
       
    68         break;
       
    69     default:
       
    70         return;
       
    71     }
       
    72     initializeRenderbuffers();
       
    73 }
       
    74 
       
    75 void WebGLFramebuffer::onBind()
       
    76 {
       
    77     initializeRenderbuffers();
       
    78 }
       
    79 
       
    80 void WebGLFramebuffer::onAttachedObjectChange(CanvasObject* object)
       
    81 {
       
    82     // Currently object == 0 is not considered, but this might change if the
       
    83     // lifespan of CanvasObject changes.
       
    84     if (object
       
    85         && (object == m_colorAttachment || object == m_depthAttachment
       
    86             || object == m_stencilAttachment || object == m_depthStencilAttachment))
       
    87         initializeRenderbuffers();
       
    88 }
       
    89 
       
    90 unsigned long WebGLFramebuffer::getColorBufferFormat()
       
    91 {
       
    92     if (object() && m_colorAttachment && m_colorAttachment->object()) {
       
    93         if (m_colorAttachment->isRenderbuffer()) {
       
    94             unsigned long format = (reinterpret_cast<WebGLRenderbuffer*>(m_colorAttachment))->getInternalFormat();
       
    95             switch (format) {
       
    96             case GraphicsContext3D::RGBA4:
       
    97             case GraphicsContext3D::RGB5_A1:
       
    98                 return GraphicsContext3D::RGBA;
       
    99             case GraphicsContext3D::RGB565:
       
   100                 return GraphicsContext3D::RGB;
       
   101             }
       
   102         } else if (m_colorAttachment->isTexture())
       
   103             return (reinterpret_cast<WebGLTexture*>(m_colorAttachment))->getInternalFormat();
       
   104     }
       
   105     return 0;
       
   106 }
       
   107 
       
   108 void WebGLFramebuffer::_deleteObject(Platform3DObject object)
       
   109 {
       
   110     context()->graphicsContext3D()->deleteFramebuffer(object);
       
   111 }
       
   112 
       
   113 bool WebGLFramebuffer::isUninitialized(CanvasObject* attachedObject)
       
   114 {
       
   115     if (attachedObject && attachedObject->object() && attachedObject->isRenderbuffer()
       
   116         && !(reinterpret_cast<WebGLRenderbuffer*>(attachedObject))->isInitialized())
       
   117         return true;
       
   118     return false;
       
   119 }
       
   120 
       
   121 void WebGLFramebuffer::setInitialized(CanvasObject* attachedObject)
       
   122 {
       
   123     if (attachedObject && attachedObject->object() && attachedObject->isRenderbuffer())
       
   124         (reinterpret_cast<WebGLRenderbuffer*>(attachedObject))->setInitialized();
       
   125 }
       
   126 
       
   127 void WebGLFramebuffer::initializeRenderbuffers()
       
   128 {
       
   129     if (!object())
       
   130         return;
       
   131     bool initColor = false, initDepth = false, initStencil = false;
       
   132     unsigned long mask = 0;
       
   133     if (isUninitialized(m_colorAttachment)) {
       
   134         initColor = true;
       
   135         mask |= GraphicsContext3D::COLOR_BUFFER_BIT;
       
   136     }
       
   137     if (isUninitialized(m_depthAttachment)) {
       
   138         initDepth = true;
       
   139         mask |= GraphicsContext3D::DEPTH_BUFFER_BIT;
       
   140     }
       
   141     if (isUninitialized(m_stencilAttachment)) {
       
   142         initStencil = true;
       
   143         mask |= GraphicsContext3D::STENCIL_BUFFER_BIT;
       
   144     }
       
   145     if (isUninitialized(m_depthStencilAttachment)) {
       
   146         initDepth = true;
       
   147         initStencil = true;
       
   148         mask |= (GraphicsContext3D::DEPTH_BUFFER_BIT | GraphicsContext3D::STENCIL_BUFFER_BIT);
       
   149     }
       
   150     if (!initColor && !initDepth && !initStencil)
       
   151         return;
       
   152 
       
   153     // We only clear un-initialized renderbuffers when they are ready to be
       
   154     // read, i.e., when the framebuffer is complete.
       
   155     GraphicsContext3D* g3d = context()->graphicsContext3D();
       
   156     if (g3d->checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER) != GraphicsContext3D::FRAMEBUFFER_COMPLETE)
       
   157         return;
       
   158 
       
   159     float colorClearValue[] = {0, 0, 0, 0}, depthClearValue = 0;
       
   160     int stencilClearValue = 0;
       
   161     unsigned char colorMask[] = {1, 1, 1, 1}, depthMask = 1, stencilMask = 1;
       
   162     bool isScissorEnabled = false;
       
   163     bool isDitherEnabled = false;
       
   164     if (initColor) {
       
   165         g3d->getFloatv(GraphicsContext3D::COLOR_CLEAR_VALUE, colorClearValue);
       
   166         g3d->getBooleanv(GraphicsContext3D::COLOR_WRITEMASK, colorMask);
       
   167         g3d->clearColor(0, 0, 0, 0);
       
   168         g3d->colorMask(true, true, true, true);
       
   169     }
       
   170     if (initDepth) {
       
   171         g3d->getFloatv(GraphicsContext3D::DEPTH_CLEAR_VALUE, &depthClearValue);
       
   172         g3d->getBooleanv(GraphicsContext3D::DEPTH_WRITEMASK, &depthMask);
       
   173         g3d->clearDepth(0);
       
   174         g3d->depthMask(true);
       
   175     }
       
   176     if (initStencil) {
       
   177         g3d->getIntegerv(GraphicsContext3D::STENCIL_CLEAR_VALUE, &stencilClearValue);
       
   178         g3d->getBooleanv(GraphicsContext3D::STENCIL_WRITEMASK, &stencilMask);
       
   179         g3d->clearStencil(0);
       
   180         g3d->stencilMask(true);
       
   181     }
       
   182     isScissorEnabled = g3d->isEnabled(GraphicsContext3D::SCISSOR_TEST);
       
   183     g3d->disable(GraphicsContext3D::SCISSOR_TEST);
       
   184     isDitherEnabled = g3d->isEnabled(GraphicsContext3D::DITHER);
       
   185     g3d->disable(GraphicsContext3D::DITHER);
       
   186 
       
   187     g3d->clear(mask);
       
   188 
       
   189     if (initColor) {
       
   190         g3d->clearColor(colorClearValue[0], colorClearValue[1], colorClearValue[2], colorClearValue[3]);
       
   191         g3d->colorMask(colorMask[0], colorMask[1], colorMask[2], colorMask[3]);
       
   192     }
       
   193     if (initDepth) {
       
   194         g3d->clearDepth(depthClearValue);
       
   195         g3d->depthMask(depthMask);
       
   196     }
       
   197     if (initStencil) {
       
   198         g3d->clearStencil(stencilClearValue);
       
   199         g3d->stencilMask(stencilMask);
       
   200     }
       
   201     if (isScissorEnabled)
       
   202         g3d->enable(GraphicsContext3D::SCISSOR_TEST);
       
   203     else
       
   204         g3d->disable(GraphicsContext3D::SCISSOR_TEST);
       
   205     if (isDitherEnabled)
       
   206         g3d->enable(GraphicsContext3D::DITHER);
       
   207     else
       
   208         g3d->disable(GraphicsContext3D::DITHER);
       
   209 
       
   210     if (initColor)
       
   211         setInitialized(m_colorAttachment);
       
   212     if (initDepth && initStencil && m_depthStencilAttachment)
       
   213         setInitialized(m_depthStencilAttachment);
       
   214     else {
       
   215         if (initDepth)
       
   216             setInitialized(m_depthAttachment);
       
   217         if (initStencil)
       
   218             setInitialized(m_stencilAttachment);
       
   219     }
       
   220 }
       
   221 
       
   222 }
       
   223 
       
   224 #endif // ENABLE(3D_CANVAS)