1/* 2 * Copyright (C) 2010 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 "RenderSurfaceChromium.h" 31 32#include "cc/CCLayerImpl.h" 33#include "GraphicsContext3D.h" 34#include "LayerChromium.h" 35#include "LayerRendererChromium.h" 36#include "LayerTexture.h" 37#include "TextStream.h" 38#include <wtf/text/CString.h> 39 40namespace WebCore { 41 42RenderSurfaceChromium::RenderSurfaceChromium(CCLayerImpl* owningLayer) 43 : m_owningLayer(owningLayer) 44 , m_maskLayer(0) 45 , m_skipsDraw(false) 46{ 47} 48 49RenderSurfaceChromium::~RenderSurfaceChromium() 50{ 51 cleanupResources(); 52} 53 54void RenderSurfaceChromium::cleanupResources() 55{ 56 if (!m_contentsTexture) 57 return; 58 59 ASSERT(layerRenderer()); 60 61 m_contentsTexture.clear(); 62} 63 64LayerRendererChromium* RenderSurfaceChromium::layerRenderer() 65{ 66 ASSERT(m_owningLayer); 67 return m_owningLayer->layerRenderer(); 68} 69 70FloatRect RenderSurfaceChromium::drawableContentRect() const 71{ 72 FloatRect localContentRect(-0.5 * m_contentRect.width(), -0.5 * m_contentRect.height(), 73 m_contentRect.width(), m_contentRect.height()); 74 FloatRect drawableContentRect = m_drawTransform.mapRect(localContentRect); 75 if (m_owningLayer->replicaLayer()) 76 drawableContentRect.unite(m_replicaDrawTransform.mapRect(localContentRect)); 77 78 return drawableContentRect; 79} 80 81bool RenderSurfaceChromium::prepareContentsTexture() 82{ 83 IntSize requiredSize(m_contentRect.size()); 84 TextureManager* textureManager = layerRenderer()->textureManager(); 85 86 if (!m_contentsTexture) 87 m_contentsTexture = LayerTexture::create(layerRenderer()->context(), textureManager); 88 89 if (m_contentsTexture->isReserved()) 90 return true; 91 92 if (!m_contentsTexture->reserve(requiredSize, GraphicsContext3D::RGBA)) { 93 m_skipsDraw = true; 94 return false; 95 } 96 97 m_skipsDraw = false; 98 return true; 99} 100 101void RenderSurfaceChromium::drawSurface(CCLayerImpl* maskLayer, const TransformationMatrix& drawTransform) 102{ 103 GraphicsContext3D* context3D = layerRenderer()->context(); 104 105 int shaderMatrixLocation = -1; 106 int shaderAlphaLocation = -1; 107 const RenderSurfaceChromium::Program* program = layerRenderer()->renderSurfaceProgram(); 108 const RenderSurfaceChromium::MaskProgram* maskProgram = layerRenderer()->renderSurfaceMaskProgram(); 109 ASSERT(program && program->initialized()); 110 bool useMask = false; 111 if (maskLayer && maskLayer->drawsContent()) { 112 if (!maskLayer->bounds().isEmpty()) { 113 context3D->makeContextCurrent(); 114 layerRenderer()->useShader(maskProgram->program()); 115 GLC(context3D, context3D->activeTexture(GraphicsContext3D::TEXTURE0)); 116 GLC(context3D, context3D->uniform1i(maskProgram->fragmentShader().samplerLocation(), 0)); 117 m_contentsTexture->bindTexture(); 118 GLC(context3D, context3D->activeTexture(GraphicsContext3D::TEXTURE1)); 119 GLC(context3D, context3D->uniform1i(maskProgram->fragmentShader().maskSamplerLocation(), 1)); 120 maskLayer->bindContentsTexture(); 121 GLC(context3D, context3D->activeTexture(GraphicsContext3D::TEXTURE0)); 122 shaderMatrixLocation = maskProgram->vertexShader().matrixLocation(); 123 shaderAlphaLocation = maskProgram->fragmentShader().alphaLocation(); 124 useMask = true; 125 } 126 } 127 128 if (!useMask) { 129 layerRenderer()->useShader(program->program()); 130 m_contentsTexture->bindTexture(); 131 GLC(context3D, context3D->uniform1i(program->fragmentShader().samplerLocation(), 0)); 132 shaderMatrixLocation = program->vertexShader().matrixLocation(); 133 shaderAlphaLocation = program->fragmentShader().alphaLocation(); 134 } 135 136 LayerChromium::drawTexturedQuad(layerRenderer()->context(), layerRenderer()->projectionMatrix(), drawTransform, 137 m_contentRect.width(), m_contentRect.height(), m_drawOpacity, 138 shaderMatrixLocation, shaderAlphaLocation); 139} 140 141void RenderSurfaceChromium::draw(const IntRect&) 142{ 143 if (m_skipsDraw || !m_contentsTexture) 144 return; 145 // FIXME: By using the same RenderSurface for both the content and its reflection, 146 // it's currently not possible to apply a separate mask to the reflection layer 147 // or correctly handle opacity in reflections (opacity must be applied after drawing 148 // both the layer and its reflection). The solution is to introduce yet another RenderSurface 149 // to draw the layer and its reflection in. For now we only apply a separate reflection 150 // mask if the contents don't have a mask of their own. 151 CCLayerImpl* replicaMaskLayer = m_maskLayer; 152 if (!m_maskLayer && m_owningLayer->replicaLayer()) 153 replicaMaskLayer = m_owningLayer->replicaLayer()->maskLayer(); 154 155 layerRenderer()->setScissorToRect(m_scissorRect); 156 157 // Reflection draws before the layer. 158 if (m_owningLayer->replicaLayer()) 159 drawSurface(replicaMaskLayer, m_replicaDrawTransform); 160 161 drawSurface(m_maskLayer, m_drawTransform); 162} 163 164String RenderSurfaceChromium::name() const 165{ 166#ifndef NDEBUG 167 return String::format("RenderSurface(id=%i,owner=%s)", m_owningLayer->debugID(), m_owningLayer->name().utf8().data()); 168#else 169 return String::format("RenderSurface(owner=%s)", m_owningLayer->name().utf8().data()); 170#endif 171} 172 173static void writeIndent(TextStream& ts, int indent) 174{ 175 for (int i = 0; i != indent; ++i) 176 ts << " "; 177} 178 179void RenderSurfaceChromium::dumpSurface(TextStream& ts, int indent) const 180{ 181 writeIndent(ts, indent); 182 ts << name() << "\n"; 183 184 writeIndent(ts, indent+1); 185 ts << "contentRect: (" << m_contentRect.x() << ", " << m_contentRect.y() << ", " << m_contentRect.width() << ", " << m_contentRect.height() << "\n"; 186} 187 188} 189#endif // USE(ACCELERATED_COMPOSITING) 190