[chromium] Improved composited debug borders
[WebKit-https.git] / Source / WebCore / platform / graphics / chromium / cc / CCTiledLayerImpl.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/CCTiledLayerImpl.h"
31
32 #include "LayerRendererChromium.h"
33 #include "cc/CCDebugBorderDrawQuad.h"
34 #include "cc/CCQuadCuller.h"
35 #include "cc/CCSolidColorDrawQuad.h"
36 #include "cc/CCTileDrawQuad.h"
37 #include <wtf/text/WTFString.h>
38
39 using namespace std;
40
41 namespace WebCore {
42
43 static const int debugTileBorderWidth = 1;
44 static const int debugTileBorderAlpha = 100;
45 static const int debugTileBorderColorRed = 80;
46 static const int debugTileBorderColorGreen = 200;
47 static const int debugTileBorderColorBlue = 200;
48 static const int debugTileBorderMissingTileColorRed = 255;
49 static const int debugTileBorderMissingTileColorGreen = 0;
50 static const int debugTileBorderMissingTileColorBlue = 0;
51
52 class ManagedTexture;
53
54 class DrawableTile : public CCLayerTilingData::Tile {
55     WTF_MAKE_NONCOPYABLE(DrawableTile);
56 public:
57     static PassOwnPtr<DrawableTile> create() { return adoptPtr(new DrawableTile()); }
58
59     Platform3DObject textureId() const { return m_textureId; }
60     void setTextureId(Platform3DObject textureId) { m_textureId = textureId; }
61
62 private:
63     DrawableTile() : m_textureId(0) { }
64
65     Platform3DObject m_textureId;
66 };
67
68 CCTiledLayerImpl::CCTiledLayerImpl(int id)
69     : CCLayerImpl(id)
70     , m_skipsDraw(true)
71     , m_contentsSwizzled(false)
72 {
73 }
74
75 CCTiledLayerImpl::~CCTiledLayerImpl()
76 {
77 }
78
79 void CCTiledLayerImpl::bindContentsTexture(LayerRendererChromium* layerRenderer)
80 {
81     // This function is only valid for single texture layers, e.g. masks.
82     ASSERT(m_tiler);
83     ASSERT(m_tiler->numTiles() == 1);
84
85     DrawableTile* tile = tileAt(0, 0);
86     Platform3DObject textureId = tile ? tile->textureId() : 0;
87     ASSERT(textureId);
88
89     layerRenderer->context()->bindTexture(GraphicsContext3D::TEXTURE_2D, textureId);
90 }
91
92 void CCTiledLayerImpl::dumpLayerProperties(TextStream& ts, int indent) const
93 {
94     CCLayerImpl::dumpLayerProperties(ts, indent);
95     writeIndent(ts, indent);
96     ts << "skipsDraw: " << (!m_tiler || m_skipsDraw) << "\n";
97 }
98
99 bool CCTiledLayerImpl::hasTileAt(int i, int j) const
100 {
101     return m_tiler->tileAt(i, j);
102 }
103
104 DrawableTile* CCTiledLayerImpl::tileAt(int i, int j) const
105 {
106     return static_cast<DrawableTile*>(m_tiler->tileAt(i, j));
107 }
108
109 DrawableTile* CCTiledLayerImpl::createTile(int i, int j)
110 {
111     OwnPtr<DrawableTile> tile(DrawableTile::create());
112     DrawableTile* addedTile = tile.get();
113     m_tiler->addTile(tile.release(), i, j);
114     return addedTile;
115 }
116
117 TransformationMatrix CCTiledLayerImpl::quadTransform() const
118 {
119     TransformationMatrix transform = drawTransform();
120
121     if (contentBounds().isEmpty())
122         return transform;
123
124     transform.scaleNonUniform(bounds().width() / static_cast<double>(contentBounds().width()),
125                               bounds().height() / static_cast<double>(contentBounds().height()));
126
127     // Tiler draws with a different origin from other layers.
128     transform.translate(-contentBounds().width() / 2.0, -contentBounds().height() / 2.0);
129     return transform;
130 }
131
132 void CCTiledLayerImpl::appendQuads(CCQuadCuller& quadList, const CCSharedQuadState* sharedQuadState, bool& usedCheckerboard)
133 {
134     const IntRect& layerRect = visibleLayerRect();
135
136     if (m_skipsDraw)
137         return;
138
139     appendGutterQuads(quadList, sharedQuadState);
140
141     if (!m_tiler || !m_tiler->numTiles() || layerRect.isEmpty())
142         return;
143
144     int left, top, right, bottom;
145     m_tiler->layerRectToTileIndices(layerRect, left, top, right, bottom);
146
147     if (hasDebugBorders()) {
148         for (int j = top; j <= bottom; ++j) {
149             for (int i = left; i <= right; ++i) {
150                 DrawableTile* tile = tileAt(i, j);
151                 IntRect tileRect = m_tiler->tileBounds(i, j);
152                 Color borderColor;
153
154                 if (!tile || !tile->textureId())
155                     borderColor = Color(debugTileBorderMissingTileColorRed, debugTileBorderMissingTileColorGreen, debugTileBorderMissingTileColorBlue, debugTileBorderAlpha);
156                 else
157                     borderColor = Color(debugTileBorderColorRed, debugTileBorderColorGreen, debugTileBorderColorBlue, debugTileBorderAlpha);
158                 quadList.append(CCDebugBorderDrawQuad::create(sharedQuadState, tileRect, borderColor, debugTileBorderWidth));
159             }
160         }
161     }
162
163     for (int j = top; j <= bottom; ++j) {
164         for (int i = left; i <= right; ++i) {
165             DrawableTile* tile = tileAt(i, j);
166             IntRect tileRect = m_tiler->tileBounds(i, j);
167             IntRect displayRect = tileRect;
168             tileRect.intersect(layerRect);
169
170             // Skip empty tiles.
171             if (tileRect.isEmpty())
172                 continue;
173
174             if (!tile || !tile->textureId()) {
175                 usedCheckerboard |= quadList.append(CCSolidColorDrawQuad::create(sharedQuadState, tileRect, backgroundColor()));
176                 continue;
177             }
178
179             IntRect tileOpaqueRect = tile->opaqueRect();
180             tileOpaqueRect.intersect(layerRect);
181
182             // Keep track of how the top left has moved, so the texture can be
183             // offset the same amount.
184             IntSize displayOffset = tileRect.minXMinYCorner() - displayRect.minXMinYCorner();
185             IntPoint textureOffset = m_tiler->textureOffset(i, j) + displayOffset;
186             float tileWidth = static_cast<float>(m_tiler->tileSize().width());
187             float tileHeight = static_cast<float>(m_tiler->tileSize().height());
188             IntSize textureSize(tileWidth, tileHeight);
189
190             bool useAA = m_tiler->hasBorderTexels() && !sharedQuadState->isLayerAxisAlignedIntRect();
191
192             bool leftEdgeAA = !i && useAA;
193             bool topEdgeAA = !j && useAA;
194             bool rightEdgeAA = i == m_tiler->numTilesX() - 1 && useAA;
195             bool bottomEdgeAA = j == m_tiler->numTilesY() - 1 && useAA;
196
197             const GC3Dint textureFilter = m_tiler->hasBorderTexels() ? GraphicsContext3D::LINEAR : GraphicsContext3D::NEAREST;
198             quadList.append(CCTileDrawQuad::create(sharedQuadState, tileRect, tileOpaqueRect, tile->textureId(), textureOffset, textureSize, textureFilter, contentsSwizzled(), leftEdgeAA, topEdgeAA, rightEdgeAA, bottomEdgeAA));
199         }
200     }
201 }
202
203 void CCTiledLayerImpl::setTilingData(const CCLayerTilingData& tiler)
204 {
205     if (m_tiler)
206         m_tiler->reset();
207     else
208         m_tiler = CCLayerTilingData::create(tiler.tileSize(), tiler.hasBorderTexels() ? CCLayerTilingData::HasBorderTexels : CCLayerTilingData::NoBorderTexels);
209     *m_tiler = tiler;
210 }
211
212 void CCTiledLayerImpl::pushTileProperties(int i, int j, Platform3DObject textureId, const IntRect& opaqueRect)
213 {
214     DrawableTile* tile = tileAt(i, j);
215     if (!tile)
216         tile = createTile(i, j);
217     tile->setTextureId(textureId);
218     tile->setOpaqueRect(opaqueRect);
219 }
220
221 Region CCTiledLayerImpl::opaqueContentsRegion() const
222 {
223     if (m_skipsDraw)
224         return Region();
225
226     return m_tiler->opaqueRegionInLayerRect(visibleLayerRect());
227 }
228
229 } // namespace WebCore
230
231 #endif // USE(ACCELERATED_COMPOSITING)