1 /* 2 * Copyright 2011, The Android Open Source Project 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 * * Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * * Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #include "config.h" 27 #include "PaintedSurface.h" 28 29 30 #include "LayerAndroid.h" 31 #include "TiledTexture.h" 32 #include "TilesManager.h" 33 #include "SkCanvas.h" 34 #include "SkPicture.h" 35 36 #include <cutils/log.h> 37 #include <wtf/CurrentTime.h> 38 #include <wtf/text/CString.h> 39 40 #undef XLOGC 41 #define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "PaintedSurface", __VA_ARGS__) 42 43 #ifdef DEBUG 44 45 #undef XLOG 46 #define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "PaintedSurface", __VA_ARGS__) 47 48 #else 49 50 #undef XLOG 51 #define XLOG(...) 52 53 #endif // DEBUG 54 55 // Layers with an area larger than 2048*2048 should never be unclipped 56 #define MAX_UNCLIPPED_AREA 4194304 57 58 namespace WebCore { 59 60 PaintedSurface::PaintedSurface() 61 : m_drawingLayer(0) 62 , m_paintingLayer(0) 63 , m_tiledTexture(0) 64 , m_scale(0) 65 , m_pictureUsed(0) 66 { 67 TilesManager::instance()->addPaintedSurface(this); 68 #ifdef DEBUG_COUNT 69 ClassTracker::instance()->increment("PaintedSurface"); 70 #endif 71 m_tiledTexture = new DualTiledTexture(this); 72 } 73 74 PaintedSurface::~PaintedSurface() 75 { 76 #ifdef DEBUG_COUNT 77 ClassTracker::instance()->decrement("PaintedSurface"); 78 #endif 79 delete m_tiledTexture; 80 } 81 82 void PaintedSurface::prepare(GLWebViewState* state) 83 { 84 XLOG("PS %p has PL %p, DL %p", this, m_paintingLayer, m_drawingLayer); 85 LayerAndroid* paintingLayer = m_paintingLayer; 86 if (!paintingLayer) 87 paintingLayer = m_drawingLayer; 88 89 if (!paintingLayer) 90 return; 91 92 bool startFastSwap = false; 93 if (state->isScrolling()) { 94 // when scrolling, block updates and swap tiles as soon as they're ready 95 startFastSwap = true; 96 } 97 98 XLOG("prepare layer %d %x at scale %.2f", 99 paintingLayer->uniqueId(), paintingLayer, 100 paintingLayer->getScale()); 101 102 IntRect visibleArea = computeVisibleArea(paintingLayer); 103 104 m_scale = state->scale(); 105 106 // If we do not have text, we may as well limit ourselves to 107 // a scale factor of one... this saves up textures. 108 if (m_scale > 1 && !paintingLayer->hasText()) 109 m_scale = 1; 110 111 m_tiledTexture->prepare(state, m_scale, m_pictureUsed != paintingLayer->pictureUsed(), 112 startFastSwap, visibleArea); 113 } 114 115 bool PaintedSurface::draw() 116 { 117 if (!m_drawingLayer || !m_drawingLayer->needsTexture()) 118 return false; 119 120 bool askRedraw = false; 121 if (m_tiledTexture) 122 askRedraw = m_tiledTexture->draw(); 123 124 return askRedraw; 125 } 126 127 void PaintedSurface::setPaintingLayer(LayerAndroid* layer, const SkRegion& dirtyArea) 128 { 129 m_paintingLayer = layer; 130 if (m_tiledTexture) 131 m_tiledTexture->update(dirtyArea, layer->picture()); 132 } 133 134 bool PaintedSurface::isReady() 135 { 136 if (m_tiledTexture) 137 return m_tiledTexture->isReady(); 138 return false; 139 } 140 141 void PaintedSurface::swapTiles() 142 { 143 if (m_tiledTexture) 144 m_tiledTexture->swapTiles(); 145 } 146 147 float PaintedSurface::opacity() { 148 if (m_drawingLayer) 149 return m_drawingLayer->drawOpacity(); 150 return 1.0; 151 } 152 153 const TransformationMatrix* PaintedSurface::transform() { 154 // used exclusively for drawing, so only use m_drawingLayer 155 if (!m_drawingLayer) 156 return 0; 157 158 return m_drawingLayer->drawTransform(); 159 } 160 161 void PaintedSurface::computeTexturesAmount(TexturesResult* result) 162 { 163 if (!m_tiledTexture) 164 return; 165 166 // for now, always done on drawinglayer 167 LayerAndroid* layer = m_drawingLayer; 168 169 if (!layer) 170 return; 171 172 IntRect unclippedArea = layer->unclippedArea(); 173 IntRect clippedVisibleArea = layer->visibleArea(); 174 // get two numbers here: 175 // - textures needed for a clipped area 176 // - textures needed for an un-clipped area 177 int nbTexturesUnclipped = m_tiledTexture->nbTextures(unclippedArea, m_scale); 178 int nbTexturesClipped = m_tiledTexture->nbTextures(clippedVisibleArea, m_scale); 179 180 // Set kFixedLayers level 181 if (layer->isFixed()) 182 result->fixed += nbTexturesClipped; 183 184 // Set kScrollableAndFixedLayers level 185 if (layer->contentIsScrollable() 186 || layer->isFixed()) 187 result->scrollable += nbTexturesClipped; 188 189 // Set kClippedTextures level 190 result->clipped += nbTexturesClipped; 191 192 // Set kAllTextures level 193 if (layer->contentIsScrollable()) 194 result->full += nbTexturesClipped; 195 else 196 result->full += nbTexturesUnclipped; 197 } 198 199 IntRect PaintedSurface::computeVisibleArea(LayerAndroid* layer) { 200 IntRect area; 201 if (!layer) 202 return area; 203 204 if (!layer->contentIsScrollable() 205 && layer->state()->layersRenderingMode() == GLWebViewState::kAllTextures) { 206 area = layer->unclippedArea(); 207 double total = ((double) area.width()) * ((double) area.height()); 208 if (total > MAX_UNCLIPPED_AREA) 209 area = layer->visibleArea(); 210 } else { 211 area = layer->visibleArea(); 212 } 213 214 return area; 215 } 216 217 bool PaintedSurface::owns(BaseTileTexture* texture) 218 { 219 if (m_tiledTexture) 220 return m_tiledTexture->owns(texture); 221 return false; 222 } 223 224 } // namespace WebCore 225