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
generateColorTexture(GraphicsContext3D * context,const IntSize & size)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
DrawingBuffer(GraphicsContext3D * context,const IntSize & size,bool multisampleExtensionSupported,bool packedDepthStencilExtensionSupported)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
~DrawingBuffer()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)
publishToPlatformLayer()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
didReset()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)
platformLayer()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
platformColorBuffer() const164 Platform3DObject DrawingBuffer::platformColorBuffer() const
165 {
166 return m_colorBuffer;
167 }
168
169 #if ENABLE(SKIA_GPU)
setGrContext(GrContext * context)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
getGrPlatformSurfaceDesc(GrPlatformSurfaceDesc * desc)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