DrawingBufferChromium.cpp revision 2bde8e466a4451c7319e3a072d118917957d6554
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
47namespace WebCore {
48
49struct DrawingBufferInternal {
50    unsigned offscreenColorTexture;
51#if USE(ACCELERATED_COMPOSITING)
52    RefPtr<Canvas2DLayerChromium> platformLayer;
53#endif
54};
55
56static 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
74DrawingBuffer::DrawingBuffer(GraphicsContext3D* context,
75                             const IntSize& size,
76                             bool multisampleExtensionSupported,
77                             bool packedDepthStencilExtensionSupported)
78    : m_context(context)
79    , m_size(size)
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
105DrawingBuffer::~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)
122void 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
147void 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)
156PlatformLayer* 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
164Platform3DObject DrawingBuffer::platformColorBuffer() const
165{
166    return m_colorBuffer;
167}
168
169#if ENABLE(SKIA_GPU)
170void 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#endif
177
178}
179