Home | History | Annotate | Download | only in chromium
      1 /*
      2  * Copyright (c) 2010, Google 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 are
      6  * met:
      7  *
      8  *     * Redistributions of source code must retain the above copyright
      9  * notice, this list of conditions and the following disclaimer.
     10  *     * Redistributions in binary form must reproduce the above
     11  * copyright notice, this list of conditions and the following disclaimer
     12  * in the documentation and/or other materials provided with the
     13  * distribution.
     14  *     * Neither the name of Google Inc. nor the names of its
     15  * contributors may be used to endorse or promote products derived from
     16  * this software without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 
     31 #include "config.h"
     32 
     33 #include "DrawingBuffer.h"
     34 
     35 #include "Extensions3DChromium.h"
     36 #include "GraphicsContext3D.h"
     37 #include "SharedGraphicsContext3D.h"
     38 
     39 #if ENABLE(SKIA_GPU)
     40 #include "GrContext.h"
     41 #endif
     42 
     43 #if USE(ACCELERATED_COMPOSITING)
     44 #include "Canvas2DLayerChromium.h"
     45 #endif
     46 
     47 namespace WebCore {
     48 
     49 struct DrawingBufferInternal {
     50     unsigned offscreenColorTexture;
     51 #if USE(ACCELERATED_COMPOSITING)
     52     RefPtr<Canvas2DLayerChromium> platformLayer;
     53 #endif
     54 };
     55 
     56 static unsigned generateColorTexture(GraphicsContext3D* context, const IntSize& size)
     57 {
     58     unsigned offscreenColorTexture = context->createTexture();
     59     if (!offscreenColorTexture)
     60         return 0;
     61 
     62     context->bindTexture(GraphicsContext3D::TEXTURE_2D, offscreenColorTexture);
     63     context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::NEAREST);
     64     context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::NEAREST);
     65     context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE);
     66     context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE);
     67     context->texImage2DResourceSafe(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, size.width(), size.height(), 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE);
     68     context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, offscreenColorTexture, 0);
     69 
     70     return offscreenColorTexture;
     71 }
     72 
     73 
     74 DrawingBuffer::DrawingBuffer(GraphicsContext3D* context,
     75                              const IntSize& size,
     76                              bool multisampleExtensionSupported,
     77                              bool packedDepthStencilExtensionSupported)
     78     : m_context(context)
     79     , m_size(-1, -1)
     80     , m_multisampleExtensionSupported(multisampleExtensionSupported)
     81     , m_packedDepthStencilExtensionSupported(packedDepthStencilExtensionSupported)
     82     , m_fbo(0)
     83     , m_colorBuffer(0)
     84     , m_depthStencilBuffer(0)
     85     , m_depthBuffer(0)
     86     , m_stencilBuffer(0)
     87     , m_multisampleFBO(0)
     88     , m_multisampleColorBuffer(0)
     89     , m_internal(new DrawingBufferInternal)
     90 #if ENABLE(SKIA_GPU)
     91     , m_grContext(0)
     92 #endif
     93 {
     94     if (!m_context->getExtensions()->supports("GL_CHROMIUM_copy_texture_to_parent_texture")) {
     95         m_context.clear();
     96         return;
     97     }
     98     m_fbo = context->createFramebuffer();
     99     context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_fbo);
    100     m_colorBuffer = generateColorTexture(context, size);
    101     createSecondaryBuffers();
    102     reset(size);
    103 }
    104 
    105 DrawingBuffer::~DrawingBuffer()
    106 {
    107 #if USE(ACCELERATED_COMPOSITING)
    108     if (m_internal->platformLayer)
    109         m_internal->platformLayer->setDrawingBuffer(0);
    110 #endif
    111 
    112     if (!m_context)
    113         return;
    114 
    115     m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_fbo);
    116     m_context->deleteTexture(m_colorBuffer);
    117 
    118     clear();
    119 }
    120 
    121 #if USE(ACCELERATED_COMPOSITING)
    122 void DrawingBuffer::publishToPlatformLayer()
    123 {
    124     if (!m_context)
    125         return;
    126 
    127     if (m_callback)
    128         m_callback->willPublish();
    129     if (multisample())
    130         commit();
    131     unsigned parentTexture = m_internal->platformLayer->textureId();
    132     // FIXME: We do the copy in the canvas' (child) context so that it executes in the correct order relative to
    133     // other commands in the child context.  This ensures that the parent texture always contains a complete
    134     // frame and not some intermediate result.  However, there is no synchronization to ensure that this copy
    135     // happens before the compositor draws.  This means we might draw stale frames sometimes.  Ideally this
    136     // would insert a fence into the child command stream that the compositor could wait for.
    137     m_context->makeContextCurrent();
    138 #if ENABLE(SKIA_GPU)
    139     if (m_grContext)
    140         m_grContext->flush(0);
    141 #endif
    142     static_cast<Extensions3DChromium*>(m_context->getExtensions())->copyTextureToParentTextureCHROMIUM(m_colorBuffer, parentTexture);
    143     m_context->flush();
    144 }
    145 #endif
    146 
    147 void DrawingBuffer::didReset()
    148 {
    149 #if USE(ACCELERATED_COMPOSITING)
    150     if (m_internal->platformLayer)
    151         m_internal->platformLayer->setTextureChanged();
    152 #endif
    153 }
    154 
    155 #if USE(ACCELERATED_COMPOSITING)
    156 PlatformLayer* DrawingBuffer::platformLayer()
    157 {
    158     if (!m_internal->platformLayer)
    159         m_internal->platformLayer = Canvas2DLayerChromium::create(this, 0);
    160     return m_internal->platformLayer.get();
    161 }
    162 #endif
    163 
    164 Platform3DObject DrawingBuffer::platformColorBuffer() const
    165 {
    166     return m_colorBuffer;
    167 }
    168 
    169 #if ENABLE(SKIA_GPU)
    170 void DrawingBuffer::setGrContext(GrContext* context)
    171 {
    172     // We just take a ptr without referencing it, as we require that we never outlive
    173     // the SharedGraphicsContext3D object that is giving us the context.
    174     m_grContext = context;
    175 }
    176 
    177 void DrawingBuffer::getGrPlatformSurfaceDesc(GrPlatformSurfaceDesc* desc)
    178 {
    179     desc->fSurfaceType = kTextureRenderTarget_GrPlatformSurfaceType;
    180 
    181     desc->fPlatformTexture = m_colorBuffer;
    182     if (multisample()) {
    183         desc->fRenderTargetFlags = kIsMultisampled_GrPlatformRenderTargetFlagBit | kGrCanResolve_GrPlatformRenderTargetFlagBit;
    184         desc->fPlatformRenderTarget = m_multisampleFBO;
    185         desc->fPlatformResolveDestination = m_fbo;
    186     } else {
    187         desc->fRenderTargetFlags = kNone_GrPlatformRenderTargetFlagBit;
    188         desc->fPlatformRenderTarget = m_fbo;
    189         desc->fPlatformResolveDestination = 0;
    190     }
    191 
    192     desc->fWidth = m_size.width();
    193     desc->fHeight = m_size.height();
    194     desc->fConfig = kRGBA_8888_GrPixelConfig;
    195 
    196     desc->fStencilBits = (m_depthStencilBuffer || m_stencilBuffer) ? 8 : 0;
    197 }
    198 
    199 #endif
    200 
    201 }
    202