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 40 namespace WebCore { 41 42 RenderSurfaceChromium::RenderSurfaceChromium(CCLayerImpl* owningLayer) 43 : m_owningLayer(owningLayer) 44 , m_maskLayer(0) 45 , m_skipsDraw(false) 46 { 47 } 48 49 RenderSurfaceChromium::~RenderSurfaceChromium() 50 { 51 cleanupResources(); 52 } 53 54 void RenderSurfaceChromium::cleanupResources() 55 { 56 if (!m_contentsTexture) 57 return; 58 59 ASSERT(layerRenderer()); 60 61 m_contentsTexture.clear(); 62 } 63 64 LayerRendererChromium* RenderSurfaceChromium::layerRenderer() 65 { 66 ASSERT(m_owningLayer); 67 return m_owningLayer->layerRenderer(); 68 } 69 70 FloatRect 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 81 bool 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 101 void 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 141 void 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 164 String 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 173 static void writeIndent(TextStream& ts, int indent) 174 { 175 for (int i = 0; i != indent; ++i) 176 ts << " "; 177 } 178 179 void 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