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