1 /* 2 * Copyright 2014 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #include "GrLayerCache.h" 9 #include "GrLayerHoister.h" 10 #include "SkCanvas.h" 11 #include "SkRecordDraw.h" 12 #include "GrRecordReplaceDraw.h" 13 #include "SkGrPixelRef.h" 14 #include "SkSurface.h" 15 16 // Return true if any layers are suitable for hoisting 17 bool GrLayerHoister::FindLayersToHoist(const SkPicture* topLevelPicture, 18 const SkRect& query, 19 SkTDArray<HoistedLayer>* atlased, 20 SkTDArray<HoistedLayer>* nonAtlased, 21 GrLayerCache* layerCache) { 22 bool anyHoisted = false; 23 24 SkPicture::AccelData::Key key = GrAccelData::ComputeAccelDataKey(); 25 26 const SkPicture::AccelData* topLevelData = topLevelPicture->EXPERIMENTAL_getAccelData(key); 27 if (NULL == topLevelData) { 28 return false; 29 } 30 31 const GrAccelData *topLevelGPUData = static_cast<const GrAccelData*>(topLevelData); 32 if (0 == topLevelGPUData->numSaveLayers()) { 33 return false; 34 } 35 36 // Layer hoisting pre-renders the entire layer since it will be cached and potentially 37 // reused with different clips (e.g., in different tiles). Because of this the 38 // clip will not be limiting the size of the pre-rendered layer. kSaveLayerMaxSize 39 // is used to limit which clips are pre-rendered. 40 static const int kSaveLayerMaxSize = 256; 41 42 SkAutoTArray<bool> pullForward(topLevelGPUData->numSaveLayers()); 43 44 // Pre-render all the layers that intersect the query rect 45 for (int i = 0; i < topLevelGPUData->numSaveLayers(); ++i) { 46 pullForward[i] = false; 47 48 const GrAccelData::SaveLayerInfo& info = topLevelGPUData->saveLayerInfo(i); 49 50 SkRect layerRect = SkRect::MakeXYWH(SkIntToScalar(info.fOffset.fX), 51 SkIntToScalar(info.fOffset.fY), 52 SkIntToScalar(info.fSize.fWidth), 53 SkIntToScalar(info.fSize.fHeight)); 54 55 if (!SkRect::Intersects(query, layerRect)) { 56 continue; 57 } 58 59 // TODO: once this code is more stable unsuitable layers can 60 // just be omitted during the optimization stage 61 if (!info.fValid || 62 kSaveLayerMaxSize < info.fSize.fWidth || 63 kSaveLayerMaxSize < info.fSize.fHeight || 64 info.fIsNested) { 65 continue; 66 } 67 68 pullForward[i] = true; 69 anyHoisted = true; 70 } 71 72 if (!anyHoisted) { 73 return false; 74 } 75 76 atlased->setReserve(atlased->reserved() + topLevelGPUData->numSaveLayers()); 77 78 // Generate the layer and/or ensure it is locked 79 for (int i = 0; i < topLevelGPUData->numSaveLayers(); ++i) { 80 if (pullForward[i]) { 81 const GrAccelData::SaveLayerInfo& info = topLevelGPUData->saveLayerInfo(i); 82 const SkPicture* pict = info.fPicture ? info.fPicture : topLevelPicture; 83 84 GrCachedLayer* layer = layerCache->findLayerOrCreate(pict->uniqueID(), 85 info.fSaveLayerOpID, 86 info.fRestoreOpID, 87 info.fOffset, 88 info.fOriginXform, 89 info.fPaint); 90 91 GrTextureDesc desc; 92 desc.fFlags = kRenderTarget_GrTextureFlagBit; 93 desc.fWidth = info.fSize.fWidth; 94 desc.fHeight = info.fSize.fHeight; 95 desc.fConfig = kSkia8888_GrPixelConfig; 96 // TODO: need to deal with sample count 97 98 bool needsRendering = layerCache->lock(layer, desc, 99 info.fHasNestedLayers || info.fIsNested); 100 if (NULL == layer->texture()) { 101 continue; 102 } 103 104 if (needsRendering) { 105 HoistedLayer* info; 106 107 if (layer->isAtlased()) { 108 info = atlased->append(); 109 } else { 110 info = nonAtlased->append(); 111 } 112 113 info->fLayer = layer; 114 info->fPicture = pict; 115 } 116 } 117 } 118 119 return anyHoisted; 120 } 121 122 static void wrap_texture(GrTexture* texture, int width, int height, SkBitmap* result) { 123 SkImageInfo info = SkImageInfo::MakeN32Premul(width, height); 124 result->setInfo(info); 125 result->setPixelRef(SkNEW_ARGS(SkGrPixelRef, (info, texture)))->unref(); 126 } 127 128 static void convert_layers_to_replacements(const SkTDArray<GrLayerHoister::HoistedLayer>& layers, 129 GrReplacements* replacements) { 130 // TODO: just replace GrReplacements::ReplacementInfo with GrCachedLayer? 131 for (int i = 0; i < layers.count(); ++i) { 132 GrReplacements::ReplacementInfo* layerInfo = replacements->push(); 133 layerInfo->fStart = layers[i].fLayer->start(); 134 layerInfo->fStop = layers[i].fLayer->stop(); 135 layerInfo->fPos = layers[i].fLayer->offset();; 136 137 SkBitmap bm; 138 wrap_texture(layers[i].fLayer->texture(), 139 !layers[i].fLayer->isAtlased() ? layers[i].fLayer->rect().width() 140 : layers[i].fLayer->texture()->width(), 141 !layers[i].fLayer->isAtlased() ? layers[i].fLayer->rect().height() 142 : layers[i].fLayer->texture()->height(), 143 &bm); 144 layerInfo->fImage = SkImage::NewTexture(bm); 145 146 layerInfo->fPaint = layers[i].fLayer->paint() 147 ? SkNEW_ARGS(SkPaint, (*layers[i].fLayer->paint())) 148 : NULL; 149 150 layerInfo->fSrcRect = SkIRect::MakeXYWH(layers[i].fLayer->rect().fLeft, 151 layers[i].fLayer->rect().fTop, 152 layers[i].fLayer->rect().width(), 153 layers[i].fLayer->rect().height()); 154 } 155 } 156 157 void GrLayerHoister::DrawLayers(const SkTDArray<HoistedLayer>& atlased, 158 const SkTDArray<HoistedLayer>& nonAtlased, 159 GrReplacements* replacements) { 160 // Render the atlased layers that require it 161 if (atlased.count() > 0) { 162 // All the atlased layers are rendered into the same GrTexture 163 SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTargetDirect( 164 atlased[0].fLayer->texture()->asRenderTarget(), NULL)); 165 166 SkCanvas* atlasCanvas = surface->getCanvas(); 167 168 SkPaint paint; 169 paint.setColor(SK_ColorTRANSPARENT); 170 paint.setXfermode(SkXfermode::Create(SkXfermode::kSrc_Mode))->unref(); 171 172 for (int i = 0; i < atlased.count(); ++i) { 173 GrCachedLayer* layer = atlased[i].fLayer; 174 const SkPicture* pict = atlased[i].fPicture; 175 176 atlasCanvas->save(); 177 178 // Add a rect clip to make sure the rendering doesn't 179 // extend beyond the boundaries of the atlased sub-rect 180 SkRect bound = SkRect::MakeXYWH(SkIntToScalar(layer->rect().fLeft), 181 SkIntToScalar(layer->rect().fTop), 182 SkIntToScalar(layer->rect().width()), 183 SkIntToScalar(layer->rect().height())); 184 atlasCanvas->clipRect(bound); 185 186 // Since 'clear' doesn't respect the clip we need to draw a rect 187 // TODO: ensure none of the atlased layers contain a clear call! 188 atlasCanvas->drawRect(bound, paint); 189 190 // info.fCTM maps the layer's top/left to the origin. 191 // Since this layer is atlased, the top/left corner needs 192 // to be offset to the correct location in the backing texture. 193 SkMatrix initialCTM; 194 initialCTM.setTranslate(SkIntToScalar(-layer->offset().fX), 195 SkIntToScalar(-layer->offset().fY)); 196 initialCTM.postTranslate(bound.fLeft, bound.fTop); 197 198 atlasCanvas->translate(SkIntToScalar(-layer->offset().fX), 199 SkIntToScalar(-layer->offset().fY)); 200 atlasCanvas->translate(bound.fLeft, bound.fTop); 201 atlasCanvas->concat(layer->ctm()); 202 203 SkRecordPartialDraw(*pict->fRecord.get(), atlasCanvas, bound, 204 layer->start()+1, layer->stop(), initialCTM); 205 206 atlasCanvas->restore(); 207 } 208 209 atlasCanvas->flush(); 210 } 211 212 // Render the non-atlased layers that require it 213 for (int i = 0; i < nonAtlased.count(); ++i) { 214 GrCachedLayer* layer = nonAtlased[i].fLayer; 215 const SkPicture* pict = nonAtlased[i].fPicture; 216 217 // Each non-atlased layer has its own GrTexture 218 SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTargetDirect( 219 layer->texture()->asRenderTarget(), NULL)); 220 221 SkCanvas* layerCanvas = surface->getCanvas(); 222 223 // Add a rect clip to make sure the rendering doesn't 224 // extend beyond the boundaries of the atlased sub-rect 225 SkRect bound = SkRect::MakeXYWH(SkIntToScalar(layer->rect().fLeft), 226 SkIntToScalar(layer->rect().fTop), 227 SkIntToScalar(layer->rect().width()), 228 SkIntToScalar(layer->rect().height())); 229 230 layerCanvas->clipRect(bound); // TODO: still useful? 231 232 layerCanvas->clear(SK_ColorTRANSPARENT); 233 234 SkMatrix initialCTM; 235 initialCTM.setTranslate(SkIntToScalar(-layer->offset().fX), 236 SkIntToScalar(-layer->offset().fY)); 237 238 layerCanvas->translate(SkIntToScalar(-layer->offset().fX), 239 SkIntToScalar(-layer->offset().fY)); 240 layerCanvas->concat(layer->ctm()); 241 242 SkRecordPartialDraw(*pict->fRecord.get(), layerCanvas, bound, 243 layer->start()+1, layer->stop(), initialCTM); 244 245 layerCanvas->flush(); 246 } 247 248 convert_layers_to_replacements(atlased, replacements); 249 convert_layers_to_replacements(nonAtlased, replacements); 250 } 251 252 static void unlock_layer_in_cache(GrLayerCache* layerCache, 253 const SkPicture* picture, 254 GrCachedLayer* layer) { 255 layerCache->unlock(layer); 256 257 #if DISABLE_CACHING 258 // This code completely clears out the atlas. It is required when 259 // caching is disabled so the atlas doesn't fill up and force more 260 // free floating layers 261 layerCache->purge(picture->uniqueID()); 262 #endif 263 } 264 265 void GrLayerHoister::UnlockLayers(GrLayerCache* layerCache, 266 const SkTDArray<HoistedLayer>& atlased, 267 const SkTDArray<HoistedLayer>& nonAtlased) { 268 269 for (int i = 0; i < atlased.count(); ++i) { 270 unlock_layer_in_cache(layerCache, atlased[i].fPicture, atlased[i].fLayer); 271 } 272 273 for (int i = 0; i < nonAtlased.count(); ++i) { 274 unlock_layer_in_cache(layerCache, nonAtlased[i].fPicture, nonAtlased[i].fLayer); 275 } 276 277 #if DISABLE_CACHING 278 // This code completely clears out the atlas. It is required when 279 // caching is disabled so the atlas doesn't fill up and force more 280 // free floating layers 281 layerCache->purgeAll(); 282 #endif 283 } 284 285