[chromium] Improved composited debug borders
[WebKit-https.git] / Source / WebCore / platform / graphics / chromium / cc / CCRenderSurface.cpp
1 /*
2  * Copyright (C) 2011 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
6  * are met:
7  *
8  * 1.  Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer.
10  * 2.  Redistributions in binary form must reproduce the above copyright
11  *     notice, this list of conditions and the following disclaimer in the
12  *     documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
18  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27
28 #if USE(ACCELERATED_COMPOSITING)
29
30 #include "cc/CCRenderSurface.h"
31
32 #include "GeometryBinding.h"
33 #include "GrTexture.h"
34 #include "GraphicsContext3D.h"
35 #include "LayerChromium.h"
36 #include "LayerRendererChromium.h"
37 #include "ManagedTexture.h"
38 #include "SharedGraphicsContext3D.h"
39 #include "TextStream.h"
40 #include "cc/CCDamageTracker.h"
41 #include "cc/CCLayerImpl.h"
42 #include "cc/CCProxy.h"
43 #include "cc/CCRenderSurfaceFilters.h"
44 #include "cc/CCSharedQuadState.h"
45 #include <wtf/text/CString.h>
46
47 namespace WebCore {
48
49 CCRenderSurface::CCRenderSurface(CCLayerImpl* owningLayer)
50     : m_owningLayer(owningLayer)
51     , m_maskLayer(0)
52     , m_skipsDraw(false)
53     , m_surfacePropertyChanged(false)
54     , m_drawOpacity(1)
55     , m_drawOpacityIsAnimating(false)
56     , m_targetSurfaceTransformsAreAnimating(false)
57     , m_screenSpaceTransformsAreAnimating(false)
58     , m_nearestAncestorThatMovesPixels(0)
59 {
60     m_damageTracker = CCDamageTracker::create();
61 }
62
63 CCRenderSurface::~CCRenderSurface()
64 {
65 }
66
67 FloatRect CCRenderSurface::drawableContentRect() const
68 {
69     FloatRect localContentRect(-0.5 * m_contentRect.width(), -0.5 * m_contentRect.height(),
70                                m_contentRect.width(), m_contentRect.height());
71     FloatRect drawableContentRect = m_drawTransform.mapRect(localContentRect);
72     if (m_owningLayer->replicaLayer())
73         drawableContentRect.unite(m_replicaDrawTransform.mapRect(localContentRect));
74
75     return drawableContentRect;
76 }
77
78 bool CCRenderSurface::prepareContentsTexture(LayerRendererChromium* layerRenderer)
79 {
80     IntSize requiredSize(m_contentRect.size());
81     TextureManager* textureManager = layerRenderer->renderSurfaceTextureManager();
82
83     if (!m_contentsTexture)
84         m_contentsTexture = ManagedTexture::create(textureManager);
85
86     if (m_contentsTexture->isReserved())
87         return true;
88
89     if (!m_contentsTexture->reserve(requiredSize, GraphicsContext3D::RGBA)) {
90         m_skipsDraw = true;
91         return false;
92     }
93
94     m_skipsDraw = false;
95     return true;
96 }
97
98 void CCRenderSurface::releaseContentsTexture()
99 {
100     if (m_skipsDraw || !m_contentsTexture)
101         return;
102     m_contentsTexture->unreserve();
103 }
104
105 void CCRenderSurface::draw(LayerRendererChromium* layerRenderer, const FloatRect& surfaceDamageRect)
106 {
107     if (m_skipsDraw || !m_contentsTexture)
108         return;
109
110     SkBitmap filterBitmap = applyFilters(layerRenderer);
111     // FIXME: By using the same RenderSurface for both the content and its reflection,
112     // it's currently not possible to apply a separate mask to the reflection layer
113     // or correctly handle opacity in reflections (opacity must be applied after drawing
114     // both the layer and its reflection). The solution is to introduce yet another RenderSurface
115     // to draw the layer and its reflection in. For now we only apply a separate reflection
116     // mask if the contents don't have a mask of their own.
117     CCLayerImpl* replicaMaskLayer = m_maskLayer;
118     if (!m_maskLayer && m_owningLayer->replicaLayer())
119         replicaMaskLayer = m_owningLayer->replicaLayer()->maskLayer();
120
121     if (m_owningLayer->parent() && m_owningLayer->parent()->usesLayerClipping() && layerRenderer->capabilities().usingPartialSwap) {
122         FloatRect clipAndDamageRect = m_clipRect;
123         clipAndDamageRect.intersect(surfaceDamageRect);
124         layerRenderer->setScissorToRect(enclosingIntRect(clipAndDamageRect));
125     } else if (layerRenderer->capabilities().usingPartialSwap)
126         layerRenderer->setScissorToRect(enclosingIntRect(surfaceDamageRect));
127     else if (m_owningLayer->parent() && m_owningLayer->parent()->usesLayerClipping())
128         layerRenderer->setScissorToRect(m_clipRect);
129     else
130         GLC(layerRenderer->context(), layerRenderer->context()->disable(GraphicsContext3D::SCISSOR_TEST));
131
132     // Reflection draws before the layer.
133     if (m_owningLayer->replicaLayer())
134         drawLayer(layerRenderer, replicaMaskLayer, m_replicaDrawTransform, filterBitmap);
135
136     drawLayer(layerRenderer, m_maskLayer, m_drawTransform, filterBitmap);
137 }
138
139 void CCRenderSurface::drawLayer(LayerRendererChromium* layerRenderer, CCLayerImpl* maskLayer, const TransformationMatrix& drawTransform, const SkBitmap& filterBitmap)
140 {
141     TransformationMatrix renderMatrix = drawTransform;
142     // Apply a scaling factor to size the quad from 1x1 to its intended size.
143     renderMatrix.scale3d(m_contentRect.width(), m_contentRect.height(), 1);
144
145     TransformationMatrix deviceMatrix = TransformationMatrix(layerRenderer->windowMatrix() * layerRenderer->projectionMatrix() * renderMatrix).to2dTransform();
146
147     // Can only draw surface if device matrix is invertible.
148     if (!deviceMatrix.isInvertible())
149         return;
150
151     FloatQuad quad = deviceMatrix.mapQuad(layerRenderer->sharedGeometryQuad());
152     CCLayerQuad deviceRect = CCLayerQuad(FloatQuad(quad.boundingBox()));
153     CCLayerQuad layerQuad = CCLayerQuad(quad);
154
155     // Use anti-aliasing programs only when necessary.
156     bool useAA = (!quad.isRectilinear() || !quad.boundingBox().isExpressibleAsIntRect());
157
158     if (useAA) {
159         deviceRect.inflateAntiAliasingDistance();
160         layerQuad.inflateAntiAliasingDistance();
161     }
162
163     bool useMask = false;
164     if (maskLayer && maskLayer->drawsContent())
165         if (!maskLayer->bounds().isEmpty())
166             useMask = true;
167
168     if (useMask) {
169         if (useAA) {
170             const MaskProgramAA* program = layerRenderer->renderSurfaceMaskProgramAA();
171             drawSurface(layerRenderer, maskLayer, drawTransform, deviceMatrix, deviceRect, layerQuad, program, program->fragmentShader().maskSamplerLocation(), program->vertexShader().pointLocation(), program->fragmentShader().edgeLocation(), filterBitmap);
172         } else {
173             const MaskProgram* program = layerRenderer->renderSurfaceMaskProgram();
174             drawSurface(layerRenderer, maskLayer, drawTransform, deviceMatrix, deviceRect, layerQuad, program, program->fragmentShader().maskSamplerLocation(), -1, -1, filterBitmap);
175         }
176     } else {
177         if (useAA) {
178             const ProgramAA* program = layerRenderer->renderSurfaceProgramAA();
179             drawSurface(layerRenderer, maskLayer, drawTransform, deviceMatrix, deviceRect, layerQuad, program, -1, program->vertexShader().pointLocation(), program->fragmentShader().edgeLocation(), filterBitmap);
180         } else {
181             const Program* program = layerRenderer->renderSurfaceProgram();
182             drawSurface(layerRenderer, maskLayer, drawTransform, deviceMatrix, deviceRect, layerQuad, program, -1, -1, -1, filterBitmap);
183         }
184     }
185 }
186
187 template <class T>
188 void CCRenderSurface::drawSurface(LayerRendererChromium* layerRenderer, CCLayerImpl* maskLayer, const TransformationMatrix& drawTransform, const TransformationMatrix& deviceTransform, const CCLayerQuad& deviceRect, const CCLayerQuad& layerQuad, const T* program, int shaderMaskSamplerLocation, int shaderQuadLocation, int shaderEdgeLocation, const SkBitmap& filterBitmap)
189 {
190     GraphicsContext3D* context3D = layerRenderer->context();
191
192     context3D->makeContextCurrent();
193     GLC(context3D, context3D->useProgram(program->program()));
194
195     GLC(context3D, context3D->activeTexture(GraphicsContext3D::TEXTURE0));
196     GLC(context3D, context3D->uniform1i(program->fragmentShader().samplerLocation(), 0));
197     if (filterBitmap.getTexture()) {
198         GrTexture* texture = reinterpret_cast<GrTexture*>(filterBitmap.getTexture());
199         context3D->bindTexture(GraphicsContext3D::TEXTURE_2D, texture->getTextureHandle());
200     } else
201         m_contentsTexture->bindTexture(context3D, layerRenderer->renderSurfaceTextureAllocator());
202
203     if (shaderMaskSamplerLocation != -1) {
204         GLC(context3D, context3D->activeTexture(GraphicsContext3D::TEXTURE1));
205         GLC(context3D, context3D->uniform1i(shaderMaskSamplerLocation, 1));
206         maskLayer->bindContentsTexture(layerRenderer);
207         GLC(context3D, context3D->activeTexture(GraphicsContext3D::TEXTURE0));
208     }
209
210     if (shaderEdgeLocation != -1) {
211         float edge[24];
212         layerQuad.toFloatArray(edge);
213         deviceRect.toFloatArray(&edge[12]);
214         GLC(context3D, context3D->uniform3fv(shaderEdgeLocation, 8, edge));
215     }
216
217     // Map device space quad to layer space.
218     FloatQuad quad = deviceTransform.inverse().mapQuad(layerQuad.floatQuad());
219
220     layerRenderer->drawTexturedQuad(drawTransform, m_contentRect.width(), m_contentRect.height(), m_drawOpacity, quad,
221                                     program->vertexShader().matrixLocation(), program->fragmentShader().alphaLocation(), shaderQuadLocation);
222 }
223
224 SkBitmap CCRenderSurface::applyFilters(LayerRendererChromium* layerRenderer)
225 {
226     // Don't use the utility context if we have a compositor thread, since
227     // it can race with canvas's use.
228     if (!m_contentsTexture || !m_filters.size() || CCProxy::hasImplThread())
229         return SkBitmap();
230
231     layerRenderer->context()->flush();
232     return CCRenderSurfaceFilters::apply(m_filters, m_contentsTexture->textureId(), m_contentRect.size(), SharedGraphicsContext3D::get().get());
233 }
234
235 String CCRenderSurface::name() const
236 {
237     return String::format("RenderSurface(id=%i,owner=%s)", m_owningLayer->id(), m_owningLayer->debugName().utf8().data());
238 }
239
240 static void writeIndent(TextStream& ts, int indent)
241 {
242     for (int i = 0; i != indent; ++i)
243         ts << "  ";
244 }
245
246 void CCRenderSurface::dumpSurface(TextStream& ts, int indent) const
247 {
248     writeIndent(ts, indent);
249     ts << name() << "\n";
250
251     writeIndent(ts, indent+1);
252     ts << "contentRect: (" << m_contentRect.x() << ", " << m_contentRect.y() << ", " << m_contentRect.width() << ", " << m_contentRect.height() << "\n";
253
254     writeIndent(ts, indent+1);
255     ts << "drawTransform: ";
256     ts << m_drawTransform.m11() << ", " << m_drawTransform.m12() << ", " << m_drawTransform.m13() << ", " << m_drawTransform.m14() << "  //  ";
257     ts << m_drawTransform.m21() << ", " << m_drawTransform.m22() << ", " << m_drawTransform.m23() << ", " << m_drawTransform.m24() << "  //  ";
258     ts << m_drawTransform.m31() << ", " << m_drawTransform.m32() << ", " << m_drawTransform.m33() << ", " << m_drawTransform.m34() << "  //  ";
259     ts << m_drawTransform.m41() << ", " << m_drawTransform.m42() << ", " << m_drawTransform.m43() << ", " << m_drawTransform.m44() << "\n";
260
261     writeIndent(ts, indent+1);
262     ts << "damageRect is pos(" << m_damageTracker->currentDamageRect().x() << "," << m_damageTracker->currentDamageRect().y() << "), ";
263     ts << "size(" << m_damageTracker->currentDamageRect().width() << "," << m_damageTracker->currentDamageRect().height() << ")\n";
264 }
265
266 int CCRenderSurface::owningLayerId() const
267 {
268     return m_owningLayer ? m_owningLayer->id() : 0;
269 }
270
271 bool CCRenderSurface::hasReplica()
272 {
273     return m_owningLayer->replicaLayer();
274 }
275
276 void CCRenderSurface::setClipRect(const IntRect& clipRect)
277 {
278     if (m_clipRect == clipRect)
279         return;
280
281     m_surfacePropertyChanged = true;
282     m_clipRect = clipRect;
283 }
284
285 void CCRenderSurface::setContentRect(const IntRect& contentRect)
286 {
287     if (m_contentRect == contentRect)
288         return;
289
290     m_surfacePropertyChanged = true;
291     m_contentRect = contentRect;
292 }
293
294 bool CCRenderSurface::surfacePropertyChanged() const
295 {
296     // Surface property changes are tracked as follows:
297     //
298     // - m_surfacePropertyChanged is flagged when the clipRect or contentRect change. As
299     //   of now, these are the only two properties that can be affected by descendant layers.
300     //
301     // - all other property changes come from the owning layer (or some ancestor layer
302     //   that propagates its change to the owning layer).
303     //
304     ASSERT(m_owningLayer);
305     return m_surfacePropertyChanged || m_owningLayer->layerPropertyChanged();
306 }
307
308 bool CCRenderSurface::surfacePropertyChangedOnlyFromDescendant() const
309 {
310     return m_surfacePropertyChanged && !m_owningLayer->layerPropertyChanged();
311 }
312
313 PassOwnPtr<CCSharedQuadState> CCRenderSurface::createSharedQuadState() const
314 {
315     bool isOpaque = false;
316     return CCSharedQuadState::create(originTransform(), drawTransform(), contentRect(), clipRect(), drawOpacity(), isOpaque);
317 }
318
319 PassOwnPtr<CCSharedQuadState> CCRenderSurface::createReplicaSharedQuadState() const
320 {
321     bool isOpaque = false;
322     return CCSharedQuadState::create(replicaOriginTransform(), replicaDrawTransform(), contentRect(), clipRect(), drawOpacity(), isOpaque);
323 }
324
325 }
326 #endif // USE(ACCELERATED_COMPOSITING)