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/CCLayerImpl.h"
31
32#include "GraphicsContext3D.h"
33#include "LayerChromium.h" // FIXME: temporary and bad
34#include "LayerRendererChromium.h"
35#include "RenderSurfaceChromium.h"
36#include <wtf/text/WTFString.h>
37
38namespace {
39void toGLMatrix(float* flattened, const WebCore::TransformationMatrix& m)
40{
41    flattened[0] = m.m11();
42    flattened[1] = m.m12();
43    flattened[2] = m.m13();
44    flattened[3] = m.m14();
45    flattened[4] = m.m21();
46    flattened[5] = m.m22();
47    flattened[6] = m.m23();
48    flattened[7] = m.m24();
49    flattened[8] = m.m31();
50    flattened[9] = m.m32();
51    flattened[10] = m.m33();
52    flattened[11] = m.m34();
53    flattened[12] = m.m41();
54    flattened[13] = m.m42();
55    flattened[14] = m.m43();
56    flattened[15] = m.m44();
57}
58}
59
60
61namespace WebCore {
62
63CCLayerImpl::CCLayerImpl(LayerChromium* owner)
64    : m_owner(owner)
65    , m_anchorPoint(0.5, 0.5)
66    , m_anchorPointZ(0)
67    , m_doubleSided(true)
68    , m_masksToBounds(false)
69    , m_opacity(1.0)
70    , m_preserves3D(false)
71#ifndef NDEBUG
72    , m_debugID(owner->debugID())
73#endif
74    , m_targetRenderSurface(0)
75    , m_drawDepth(0)
76    , m_drawOpacity(0)
77    , m_debugBorderColor(0, 0, 0, 0)
78    , m_debugBorderWidth(0)
79    , m_renderSurface(0)
80    , m_layerRenderer(0)
81{
82}
83
84CCLayerImpl::~CCLayerImpl()
85{
86}
87
88// These are pseudo-structural hacks until we get real tree syncing up in this piece.
89CCLayerImpl* CCLayerImpl::superlayer() const
90{
91    return m_owner->superlayer() ? m_owner->superlayer()->ccLayerImpl() : 0;
92}
93
94CCLayerImpl* CCLayerImpl::maskLayer() const
95{
96    return m_owner->maskLayer() ? m_owner->maskLayer()->ccLayerImpl() : 0;
97}
98
99CCLayerImpl* CCLayerImpl::replicaLayer() const
100{
101    return m_owner->replicaLayer() ? m_owner->replicaLayer()->ccLayerImpl() : 0;
102}
103
104void CCLayerImpl::setLayerRenderer(LayerRendererChromium* renderer)
105{
106    m_layerRenderer = renderer;
107}
108
109RenderSurfaceChromium* CCLayerImpl::createRenderSurface()
110{
111    m_renderSurface = new RenderSurfaceChromium(this);
112    return m_renderSurface.get();
113}
114
115bool CCLayerImpl::descendantsDrawsContent()
116{
117    const Vector<RefPtr<LayerChromium> >& sublayers = m_owner->getSublayers();
118    for (size_t i = 0; i < sublayers.size(); ++i) {
119        sublayers[i]->createCCLayerImplIfNeeded();
120        if (sublayers[i]->ccLayerImpl()->drawsContent() || sublayers[i]->ccLayerImpl()->descendantsDrawsContent())
121            return true;
122    }
123    return false;
124}
125
126// These belong on CCLayerImpl, but should be overridden by each type and not defer to the LayerChromium subtypes.
127bool CCLayerImpl::drawsContent() const
128{
129    return m_owner && m_owner->drawsContent();
130}
131
132void CCLayerImpl::draw(const IntRect& targetSurfaceRect)
133{
134    return m_owner->draw(targetSurfaceRect);
135}
136
137void CCLayerImpl::updateCompositorResources()
138{
139    return m_owner->updateCompositorResources();
140}
141
142void CCLayerImpl::unreserveContentsTexture()
143{
144    m_owner->unreserveContentsTexture();
145}
146
147void CCLayerImpl::bindContentsTexture()
148{
149    m_owner->bindContentsTexture();
150}
151
152void CCLayerImpl::cleanupResources()
153{
154    if (renderSurface())
155        renderSurface()->cleanupResources();
156}
157
158const IntRect CCLayerImpl::getDrawRect() const
159{
160    // Form the matrix used by the shader to map the corners of the layer's
161    // bounds into the view space.
162    FloatRect layerRect(-0.5 * bounds().width(), -0.5 * bounds().height(), bounds().width(), bounds().height());
163    IntRect mappedRect = enclosingIntRect(drawTransform().mapRect(layerRect));
164    return mappedRect;
165}
166
167void CCLayerImpl::drawDebugBorder()
168{
169    static float glMatrix[16];
170    if (!debugBorderColor().alpha())
171        return;
172
173    ASSERT(layerRenderer());
174    const LayerChromium::BorderProgram* program = layerRenderer()->borderProgram();
175    ASSERT(program && program->initialized());
176    layerRenderer()->useShader(program->program());
177    TransformationMatrix renderMatrix = drawTransform();
178    renderMatrix.scale3d(bounds().width(), bounds().height(), 1);
179    toGLMatrix(&glMatrix[0], layerRenderer()->projectionMatrix() * renderMatrix);
180    GraphicsContext3D* context = layerRenderer()->context();
181    GLC(context, context->uniformMatrix4fv(program->vertexShader().matrixLocation(), false, &glMatrix[0], 1));
182
183    GLC(context, context->uniform4f(program->fragmentShader().colorLocation(), debugBorderColor().red() / 255.0, debugBorderColor().green() / 255.0, debugBorderColor().blue() / 255.0, 1));
184
185    GLC(context, context->lineWidth(debugBorderWidth()));
186
187    // The indices for the line are stored in the same array as the triangle indices.
188    GLC(context, context->drawElements(GraphicsContext3D::LINE_LOOP, 4, GraphicsContext3D::UNSIGNED_SHORT, 6 * sizeof(unsigned short)));
189}
190
191void CCLayerImpl::writeIndent(TextStream& ts, int indent)
192{
193    for (int i = 0; i != indent; ++i)
194        ts << "  ";
195}
196
197void CCLayerImpl::dumpLayerProperties(TextStream& ts, int indent) const
198{
199    writeIndent(ts, indent);
200    ts << "bounds: " << bounds().width() << ", " << bounds().height() << "\n";
201
202    if (m_targetRenderSurface) {
203        writeIndent(ts, indent);
204        ts << "targetRenderSurface: " << m_targetRenderSurface->name() << "\n";
205    }
206
207    writeIndent(ts, indent);
208    ts << "drawTransform: ";
209    ts << m_drawTransform.m11() << ", " << m_drawTransform.m12() << ", " << m_drawTransform.m13() << ", " << m_drawTransform.m14() << ", ";
210    ts << m_drawTransform.m21() << ", " << m_drawTransform.m22() << ", " << m_drawTransform.m23() << ", " << m_drawTransform.m24() << ", ";
211    ts << m_drawTransform.m31() << ", " << m_drawTransform.m32() << ", " << m_drawTransform.m33() << ", " << m_drawTransform.m34() << ", ";
212    ts << m_drawTransform.m41() << ", " << m_drawTransform.m42() << ", " << m_drawTransform.m43() << ", " << m_drawTransform.m44() << "\n";
213}
214
215}
216
217#endif // USE(ACCELERATED_COMPOSITING)
218