16b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner/*
26b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner * Copyright (C) 2010 Google Inc. All rights reserved.
36b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner *
46b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner * Redistribution and use in source and binary forms, with or without
56b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner * modification, are permitted provided that the following conditions
66b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner * are met:
76b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner *
86b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner * 1.  Redistributions of source code must retain the above copyright
96b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner *     notice, this list of conditions and the following disclaimer.
106b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner * 2.  Redistributions in binary form must reproduce the above copyright
116b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner *     notice, this list of conditions and the following disclaimer in the
126b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner *     documentation and/or other materials provided with the distribution.
136b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner *
146b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
156b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
166b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
176b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
186b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
196b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
206b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
216b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
226b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
236b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
246b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner */
256b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
266b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner#include "config.h"
276b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
286b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner#if USE(ACCELERATED_COMPOSITING)
296b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
306b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner#include "RenderSurfaceChromium.h"
316b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
3281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch#include "cc/CCLayerImpl.h"
336b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner#include "GraphicsContext3D.h"
3481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch#include "LayerChromium.h"
356b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner#include "LayerRendererChromium.h"
36f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#include "LayerTexture.h"
3781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch#include "TextStream.h"
3881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch#include <wtf/text/CString.h>
396b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
406b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennernamespace WebCore {
416b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
4281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen MurdochRenderSurfaceChromium::RenderSurfaceChromium(CCLayerImpl* owningLayer)
436b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    : m_owningLayer(owningLayer)
442fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    , m_maskLayer(0)
45f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    , m_skipsDraw(false)
466b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner{
476b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner}
486b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
496b70adc33054f8aee8c54d0f460458a9df11b8a5Russell BrennerRenderSurfaceChromium::~RenderSurfaceChromium()
506b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner{
516b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    cleanupResources();
526b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner}
536b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
546b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennervoid RenderSurfaceChromium::cleanupResources()
556b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner{
56f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    if (!m_contentsTexture)
576b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        return;
586b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
596b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    ASSERT(layerRenderer());
606b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
61f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    m_contentsTexture.clear();
626b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner}
636b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
646b70adc33054f8aee8c54d0f460458a9df11b8a5Russell BrennerLayerRendererChromium* RenderSurfaceChromium::layerRenderer()
656b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner{
666b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    ASSERT(m_owningLayer);
676b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    return m_owningLayer->layerRenderer();
686b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner}
696b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
702fc2651226baac27029e38c9d6ef883fa32084dbSteve BlockFloatRect RenderSurfaceChromium::drawableContentRect() const
712fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{
722fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    FloatRect localContentRect(-0.5 * m_contentRect.width(), -0.5 * m_contentRect.height(),
732fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                               m_contentRect.width(), m_contentRect.height());
742fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    FloatRect drawableContentRect = m_drawTransform.mapRect(localContentRect);
752fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (m_owningLayer->replicaLayer())
762fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        drawableContentRect.unite(m_replicaDrawTransform.mapRect(localContentRect));
772fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
782fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    return drawableContentRect;
792fc2651226baac27029e38c9d6ef883fa32084dbSteve Block}
802fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
81f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochbool RenderSurfaceChromium::prepareContentsTexture()
826b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner{
83f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    IntSize requiredSize(m_contentRect.size());
84f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    TextureManager* textureManager = layerRenderer()->textureManager();
856b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
86f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    if (!m_contentsTexture)
87f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        m_contentsTexture = LayerTexture::create(layerRenderer()->context(), textureManager);
886b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
8965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    if (m_contentsTexture->isReserved())
9065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        return true;
9165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
92f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    if (!m_contentsTexture->reserve(requiredSize, GraphicsContext3D::RGBA)) {
93f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        m_skipsDraw = true;
94f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        return false;
956b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    }
96f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
97f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    m_skipsDraw = false;
98f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    return true;
99f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch}
100f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
10181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochvoid RenderSurfaceChromium::drawSurface(CCLayerImpl* maskLayer, const TransformationMatrix& drawTransform)
102f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{
1032fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    GraphicsContext3D* context3D = layerRenderer()->context();
104f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
1052fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    int shaderMatrixLocation = -1;
1062fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    int shaderAlphaLocation = -1;
10781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    const RenderSurfaceChromium::Program* program = layerRenderer()->renderSurfaceProgram();
10881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    const RenderSurfaceChromium::MaskProgram* maskProgram = layerRenderer()->renderSurfaceMaskProgram();
10981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    ASSERT(program && program->initialized());
1102fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    bool useMask = false;
1112fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (maskLayer && maskLayer->drawsContent()) {
1122fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        if (!maskLayer->bounds().isEmpty()) {
1132fc2651226baac27029e38c9d6ef883fa32084dbSteve Block            context3D->makeContextCurrent();
11481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            layerRenderer()->useShader(maskProgram->program());
1152fc2651226baac27029e38c9d6ef883fa32084dbSteve Block            GLC(context3D, context3D->activeTexture(GraphicsContext3D::TEXTURE0));
11681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            GLC(context3D, context3D->uniform1i(maskProgram->fragmentShader().samplerLocation(), 0));
1172fc2651226baac27029e38c9d6ef883fa32084dbSteve Block            m_contentsTexture->bindTexture();
1182fc2651226baac27029e38c9d6ef883fa32084dbSteve Block            GLC(context3D, context3D->activeTexture(GraphicsContext3D::TEXTURE1));
11981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            GLC(context3D, context3D->uniform1i(maskProgram->fragmentShader().maskSamplerLocation(), 1));
1202fc2651226baac27029e38c9d6ef883fa32084dbSteve Block            maskLayer->bindContentsTexture();
1212fc2651226baac27029e38c9d6ef883fa32084dbSteve Block            GLC(context3D, context3D->activeTexture(GraphicsContext3D::TEXTURE0));
12281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            shaderMatrixLocation = maskProgram->vertexShader().matrixLocation();
12381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            shaderAlphaLocation = maskProgram->fragmentShader().alphaLocation();
1242fc2651226baac27029e38c9d6ef883fa32084dbSteve Block            useMask = true;
1252fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        }
1262fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    }
1272fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1282fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (!useMask) {
12981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        layerRenderer()->useShader(program->program());
1302fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        m_contentsTexture->bindTexture();
13181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        GLC(context3D, context3D->uniform1i(program->fragmentShader().samplerLocation(), 0));
13281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        shaderMatrixLocation = program->vertexShader().matrixLocation();
13381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        shaderAlphaLocation = program->fragmentShader().alphaLocation();
1342fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    }
1352fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1362fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    LayerChromium::drawTexturedQuad(layerRenderer()->context(), layerRenderer()->projectionMatrix(), drawTransform,
1372fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                                        m_contentRect.width(), m_contentRect.height(), m_drawOpacity,
1382fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                                        shaderMatrixLocation, shaderAlphaLocation);
1392fc2651226baac27029e38c9d6ef883fa32084dbSteve Block}
1402fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1412daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochvoid RenderSurfaceChromium::draw(const IntRect&)
1422fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{
1432fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (m_skipsDraw || !m_contentsTexture)
1442fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        return;
1452fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    // FIXME: By using the same RenderSurface for both the content and its reflection,
1462fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    // it's currently not possible to apply a separate mask to the reflection layer
1472fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    // or correctly handle opacity in reflections (opacity must be applied after drawing
1482fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    // both the layer and its reflection). The solution is to introduce yet another RenderSurface
1492fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    // to draw the layer and its reflection in. For now we only apply a separate reflection
1502fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    // mask if the contents don't have a mask of their own.
15181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    CCLayerImpl* replicaMaskLayer = m_maskLayer;
1522fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (!m_maskLayer && m_owningLayer->replicaLayer())
1532fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        replicaMaskLayer = m_owningLayer->replicaLayer()->maskLayer();
154f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
155f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    layerRenderer()->setScissorToRect(m_scissorRect);
156f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
1572fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    // Reflection draws before the layer.
1582fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (m_owningLayer->replicaLayer())
1592fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        drawSurface(replicaMaskLayer, m_replicaDrawTransform);
160f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
1612fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    drawSurface(m_maskLayer, m_drawTransform);
1626b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner}
1636b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
16481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen MurdochString RenderSurfaceChromium::name() const
16581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch{
16681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch#ifndef NDEBUG
16781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    return String::format("RenderSurface(id=%i,owner=%s)", m_owningLayer->debugID(), m_owningLayer->name().utf8().data());
16881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch#else
16981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    return String::format("RenderSurface(owner=%s)", m_owningLayer->name().utf8().data());
17081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch#endif
17181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch}
17281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
17381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochstatic void writeIndent(TextStream& ts, int indent)
17481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch{
17581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    for (int i = 0; i != indent; ++i)
17681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        ts << "  ";
17781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch}
17881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
17981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochvoid RenderSurfaceChromium::dumpSurface(TextStream& ts, int indent) const
18081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch{
18181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    writeIndent(ts, indent);
18281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    ts << name() << "\n";
18381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
18481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    writeIndent(ts, indent+1);
18581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    ts << "contentRect: (" << m_contentRect.x() << ", " << m_contentRect.y() << ", " << m_contentRect.width() << ", " << m_contentRect.height() << "\n";
18681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch}
18781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
1886b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner}
1896b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner#endif // USE(ACCELERATED_COMPOSITING)
190