| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2014 Google Inc. | 2 * Copyright 2014 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #include "GrLayerCache.h" | 8 #include "GrLayerCache.h" |
| 9 #include "GrLayerHoister.h" | 9 #include "GrLayerHoister.h" |
| 10 #include "GrRecordReplaceDraw.h" | 10 #include "GrRecordReplaceDraw.h" |
| 11 | 11 |
| 12 #include "SkCanvas.h" | 12 #include "SkCanvas.h" |
| 13 #include "SkGrPixelRef.h" | 13 #include "SkGrPixelRef.h" |
| 14 #include "SkRecordDraw.h" | 14 #include "SkRecordDraw.h" |
| 15 #include "SkSurface.h" | 15 #include "SkSurface.h" |
| 16 | 16 |
| 17 // Create the layer information for the hoisted layer and secure the | 17 // Create the layer information for the hoisted layer and secure the |
| 18 // required texture/render target resources. | 18 // required texture/render target resources. |
| 19 static void prepare_for_hoisting(GrLayerCache* layerCache, | 19 static void prepare_for_hoisting(GrLayerCache* layerCache, |
| 20 const SkPicture* topLevelPicture, | 20 const SkPicture* topLevelPicture, |
| 21 const GrAccelData::SaveLayerInfo& info, | 21 const GrAccelData::SaveLayerInfo& info, |
| 22 const SkIRect& layerRect, | 22 const SkIRect& layerRect, |
| 23 SkTDArray<GrHoistedLayer>* atlased, | 23 SkTDArray<GrHoistedLayer>* atlased, |
| 24 SkTDArray<GrHoistedLayer>* nonAtlased, | 24 SkTDArray<GrHoistedLayer>* nonAtlased, |
| 25 SkTDArray<GrHoistedLayer>* recycled) { | 25 SkTDArray<GrHoistedLayer>* recycled) { |
| 26 const SkPicture* pict = info.fPicture ? info.fPicture : topLevelPicture; | 26 const SkPicture* pict = info.fPicture ? info.fPicture : topLevelPicture; |
| 27 | 27 |
| 28 SkMatrix combined = SkMatrix::Concat(info.fPreMat, info.fLocalMat); |
| 29 |
| 28 GrCachedLayer* layer = layerCache->findLayerOrCreate(pict->uniqueID(), | 30 GrCachedLayer* layer = layerCache->findLayerOrCreate(pict->uniqueID(), |
| 29 info.fSaveLayerOpID, | 31 info.fSaveLayerOpID, |
| 30 info.fRestoreOpID, | 32 info.fRestoreOpID, |
| 31 layerRect, | 33 layerRect, |
| 32 info.fOriginXform, | 34 combined, |
| 33 info.fPaint); | 35 info.fPaint); |
| 34 | |
| 35 GrTextureDesc desc; | 36 GrTextureDesc desc; |
| 36 desc.fFlags = kRenderTarget_GrTextureFlagBit; | 37 desc.fFlags = kRenderTarget_GrTextureFlagBit; |
| 37 desc.fWidth = layerRect.width(); | 38 desc.fWidth = layerRect.width(); |
| 38 desc.fHeight = layerRect.height(); | 39 desc.fHeight = layerRect.height(); |
| 39 desc.fConfig = kSkia8888_GrPixelConfig; | 40 desc.fConfig = kSkia8888_GrPixelConfig; |
| 40 // TODO: need to deal with sample count | 41 // TODO: need to deal with sample count |
| 41 | 42 |
| 42 | 43 |
| 43 bool disallowAtlasing = info.fHasNestedLayers || info.fIsNested || | 44 bool disallowAtlasing = info.fHasNestedLayers || info.fIsNested || |
| 44 (layer->paint() && layer->paint()->getImageFilter())
; | 45 (layer->paint() && layer->paint()->getImageFilter())
; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 58 hl = nonAtlased->append(); | 59 hl = nonAtlased->append(); |
| 59 } | 60 } |
| 60 } else { | 61 } else { |
| 61 hl = recycled->append(); | 62 hl = recycled->append(); |
| 62 } | 63 } |
| 63 | 64 |
| 64 layerCache->addUse(layer); | 65 layerCache->addUse(layer); |
| 65 hl->fLayer = layer; | 66 hl->fLayer = layer; |
| 66 hl->fPicture = pict; | 67 hl->fPicture = pict; |
| 67 hl->fOffset = SkIPoint::Make(layerRect.fLeft, layerRect.fTop); | 68 hl->fOffset = SkIPoint::Make(layerRect.fLeft, layerRect.fTop); |
| 68 hl->fCTM = info.fOriginXform; | 69 hl->fLocalMat = info.fLocalMat; |
| 70 hl->fPreMat = info.fPreMat; |
| 69 } | 71 } |
| 70 | 72 |
| 71 // Return true if any layers are suitable for hoisting | 73 // Return true if any layers are suitable for hoisting |
| 72 bool GrLayerHoister::FindLayersToHoist(GrContext* context, | 74 bool GrLayerHoister::FindLayersToHoist(GrContext* context, |
| 73 const SkPicture* topLevelPicture, | 75 const SkPicture* topLevelPicture, |
| 74 const SkRect& query, | 76 const SkRect& query, |
| 75 SkTDArray<GrHoistedLayer>* atlased, | 77 SkTDArray<GrHoistedLayer>* atlased, |
| 76 SkTDArray<GrHoistedLayer>* nonAtlased, | 78 SkTDArray<GrHoistedLayer>* nonAtlased, |
| 77 SkTDArray<GrHoistedLayer>* recycled) { | 79 SkTDArray<GrHoistedLayer>* recycled) { |
| 78 GrLayerCache* layerCache = context->getLayerCache(); | 80 GrLayerCache* layerCache = context->getLayerCache(); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 106 // Find and prepare for hoisting all the layers that intersect the query rec
t | 108 // Find and prepare for hoisting all the layers that intersect the query rec
t |
| 107 for (int i = 0; i < topLevelGPUData->numSaveLayers(); ++i) { | 109 for (int i = 0; i < topLevelGPUData->numSaveLayers(); ++i) { |
| 108 | 110 |
| 109 const GrAccelData::SaveLayerInfo& info = topLevelGPUData->saveLayerInfo(
i); | 111 const GrAccelData::SaveLayerInfo& info = topLevelGPUData->saveLayerInfo(
i); |
| 110 | 112 |
| 111 SkRect layerRect = SkRect::Make(info.fBounds); | 113 SkRect layerRect = SkRect::Make(info.fBounds); |
| 112 if (!layerRect.intersect(query)) { | 114 if (!layerRect.intersect(query)) { |
| 113 continue; | 115 continue; |
| 114 } | 116 } |
| 115 | 117 |
| 116 | |
| 117 SkIRect ir; | 118 SkIRect ir; |
| 118 layerRect.roundOut(&ir); | 119 layerRect.roundOut(&ir); |
| 119 | 120 |
| 120 // TODO: ignore perspective projected layers here! | 121 // TODO: ignore perspective projected layers here! |
| 121 // TODO: once this code is more stable unsuitable layers can | 122 // TODO: once this code is more stable unsuitable layers can |
| 122 // just be omitted during the optimization stage | 123 // just be omitted during the optimization stage |
| 123 if (info.fIsNested) { | 124 if (info.fIsNested) { |
| 124 continue; | 125 continue; |
| 125 } | 126 } |
| 126 | 127 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 137 result->setPixelRef(SkNEW_ARGS(SkGrPixelRef, (info, texture)))->unref(); | 138 result->setPixelRef(SkNEW_ARGS(SkGrPixelRef, (info, texture)))->unref(); |
| 138 } | 139 } |
| 139 | 140 |
| 140 static void convert_layers_to_replacements(const SkTDArray<GrHoistedLayer>& laye
rs, | 141 static void convert_layers_to_replacements(const SkTDArray<GrHoistedLayer>& laye
rs, |
| 141 GrReplacements* replacements) { | 142 GrReplacements* replacements) { |
| 142 // TODO: just replace GrReplacements::ReplacementInfo with GrCachedLayer? | 143 // TODO: just replace GrReplacements::ReplacementInfo with GrCachedLayer? |
| 143 for (int i = 0; i < layers.count(); ++i) { | 144 for (int i = 0; i < layers.count(); ++i) { |
| 144 GrCachedLayer* layer = layers[i].fLayer; | 145 GrCachedLayer* layer = layers[i].fLayer; |
| 145 const SkPicture* picture = layers[i].fPicture; | 146 const SkPicture* picture = layers[i].fPicture; |
| 146 | 147 |
| 148 SkMatrix combined = SkMatrix::Concat(layers[i].fPreMat, layers[i].fLocal
Mat); |
| 149 |
| 147 GrReplacements::ReplacementInfo* layerInfo = | 150 GrReplacements::ReplacementInfo* layerInfo = |
| 148 replacements->newReplacement(picture->uniqueID(), | 151 replacements->newReplacement(picture->uniqueID(), |
| 149 layer->start(), | 152 layer->start(), |
| 150 layers[i].fCTM); | 153 combined); |
| 151 layerInfo->fStop = layer->stop(); | 154 layerInfo->fStop = layer->stop(); |
| 152 layerInfo->fPos = layers[i].fOffset; | 155 layerInfo->fPos = layers[i].fOffset; |
| 153 | 156 |
| 154 SkBitmap bm; | 157 SkBitmap bm; |
| 155 wrap_texture(layers[i].fLayer->texture(), | 158 wrap_texture(layers[i].fLayer->texture(), |
| 156 !layers[i].fLayer->isAtlased() ? layers[i].fLayer->rect().w
idth() | 159 !layers[i].fLayer->isAtlased() ? layers[i].fLayer->rect().w
idth() |
| 157 : layers[i].fLayer->texture(
)->width(), | 160 : layers[i].fLayer->texture(
)->width(), |
| 158 !layers[i].fLayer->isAtlased() ? layers[i].fLayer->rect().h
eight() | 161 !layers[i].fLayer->isAtlased() ? layers[i].fLayer->rect().h
eight() |
| 159 : layers[i].fLayer->texture(
)->height(), | 162 : layers[i].fLayer->texture(
)->height(), |
| 160 &bm); | 163 &bm); |
| 161 layerInfo->fImage = SkImage::NewTexture(bm); | 164 layerInfo->fImage = SkImage::NewTexture(bm); |
| 162 | 165 |
| 163 layerInfo->fPaint = layers[i].fLayer->paint() | 166 layerInfo->fPaint = layers[i].fLayer->paint() |
| 164 ? SkNEW_ARGS(SkPaint, (*layers[i].fLayer->paint(
))) | 167 ? SkNEW_ARGS(SkPaint, (*layers[i].fLayer->paint(
))) |
| 165 : NULL; | 168 : NULL; |
| 166 | 169 |
| 167 layerInfo->fSrcRect = SkIRect::MakeXYWH(layers[i].fLayer->rect().fLeft, | 170 layerInfo->fSrcRect = SkIRect::MakeXYWH(layers[i].fLayer->rect().fLeft, |
| 168 layers[i].fLayer->rect().fTop, | 171 layers[i].fLayer->rect().fTop, |
| 169 layers[i].fLayer->rect().width()
, | 172 layers[i].fLayer->rect().width()
, |
| 170 layers[i].fLayer->rect().height(
)); | 173 layers[i].fLayer->rect().height(
)); |
| 171 } | 174 } |
| 172 } | 175 } |
| 173 | 176 |
| 174 void GrLayerHoister::DrawLayers(const SkTDArray<GrHoistedLayer>& atlased, | 177 void GrLayerHoister::DrawLayers(GrContext* context, |
| 178 const SkTDArray<GrHoistedLayer>& atlased, |
| 175 const SkTDArray<GrHoistedLayer>& nonAtlased, | 179 const SkTDArray<GrHoistedLayer>& nonAtlased, |
| 176 const SkTDArray<GrHoistedLayer>& recycled, | 180 const SkTDArray<GrHoistedLayer>& recycled, |
| 177 GrReplacements* replacements) { | 181 GrReplacements* replacements) { |
| 178 // Render the atlased layers that require it | 182 // Render the atlased layers that require it |
| 179 if (atlased.count() > 0) { | 183 if (atlased.count() > 0) { |
| 180 // All the atlased layers are rendered into the same GrTexture | 184 // All the atlased layers are rendered into the same GrTexture |
| 181 SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTargetDirect( | 185 SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTargetDirect( |
| 182 atlased[0].fLayer->texture()->asRenderTa
rget(), NULL)); | 186 atlased[0].fLayer->texture()->asRenderTa
rget(), NULL)); |
| 183 | 187 |
| 184 SkCanvas* atlasCanvas = surface->getCanvas(); | 188 SkCanvas* atlasCanvas = surface->getCanvas(); |
| 185 | 189 |
| 186 SkPaint paint; | 190 SkPaint clearPaint; |
| 187 paint.setColor(SK_ColorTRANSPARENT); | 191 clearPaint.setColor(SK_ColorTRANSPARENT); |
| 188 paint.setXfermode(SkXfermode::Create(SkXfermode::kSrc_Mode))->unref(); | 192 clearPaint.setXfermode(SkXfermode::Create(SkXfermode::kSrc_Mode))->unref
(); |
| 189 | 193 |
| 190 for (int i = 0; i < atlased.count(); ++i) { | 194 for (int i = 0; i < atlased.count(); ++i) { |
| 191 GrCachedLayer* layer = atlased[i].fLayer; | 195 const GrCachedLayer* layer = atlased[i].fLayer; |
| 192 const SkPicture* pict = atlased[i].fPicture; | 196 const SkPicture* pict = atlased[i].fPicture; |
| 193 const SkIPoint offset = atlased[i].fOffset; | 197 const SkIPoint offset = atlased[i].fOffset; |
| 198 SkDEBUGCODE(const SkPaint* layerPaint = layer->paint();) |
| 199 |
| 200 SkASSERT(!layerPaint || !layerPaint->getImageFilter()); |
| 194 | 201 |
| 195 atlasCanvas->save(); | 202 atlasCanvas->save(); |
| 196 | 203 |
| 197 // Add a rect clip to make sure the rendering doesn't | 204 // Add a rect clip to make sure the rendering doesn't |
| 198 // extend beyond the boundaries of the atlased sub-rect | 205 // extend beyond the boundaries of the atlased sub-rect |
| 199 SkRect bound = SkRect::MakeXYWH(SkIntToScalar(layer->rect().fLeft), | 206 SkRect bound = SkRect::MakeXYWH(SkIntToScalar(layer->rect().fLeft), |
| 200 SkIntToScalar(layer->rect().fTop), | 207 SkIntToScalar(layer->rect().fTop), |
| 201 SkIntToScalar(layer->rect().width())
, | 208 SkIntToScalar(layer->rect().width())
, |
| 202 SkIntToScalar(layer->rect().height()
)); | 209 SkIntToScalar(layer->rect().height()
)); |
| 203 atlasCanvas->clipRect(bound); | 210 atlasCanvas->clipRect(bound); |
| 204 | 211 |
| 205 // Since 'clear' doesn't respect the clip we need to draw a rect | 212 // Since 'clear' doesn't respect the clip we need to draw a rect |
| 206 // TODO: ensure none of the atlased layers contain a clear call! | 213 // TODO: ensure none of the atlased layers contain a clear call! |
| 207 atlasCanvas->drawRect(bound, paint); | 214 atlasCanvas->drawRect(bound, clearPaint); |
| 208 | 215 |
| 209 // info.fCTM maps the layer's top/left to the origin. | 216 // info.fCTM maps the layer's top/left to the origin. |
| 210 // Since this layer is atlased, the top/left corner needs | 217 // Since this layer is atlased, the top/left corner needs |
| 211 // to be offset to the correct location in the backing texture. | 218 // to be offset to the correct location in the backing texture. |
| 212 SkMatrix initialCTM; | 219 SkMatrix initialCTM; |
| 213 initialCTM.setTranslate(SkIntToScalar(-offset.fX), | 220 initialCTM.setTranslate(SkIntToScalar(-offset.fX), |
| 214 SkIntToScalar(-offset.fY)); | 221 SkIntToScalar(-offset.fY)); |
| 215 initialCTM.postTranslate(bound.fLeft, bound.fTop); | 222 initialCTM.postTranslate(bound.fLeft, bound.fTop); |
| 216 | 223 initialCTM.postConcat(atlased[i].fPreMat); |
| 224 |
| 217 atlasCanvas->translate(SkIntToScalar(-offset.fX), | 225 atlasCanvas->translate(SkIntToScalar(-offset.fX), |
| 218 SkIntToScalar(-offset.fY)); | 226 SkIntToScalar(-offset.fY)); |
| 219 atlasCanvas->translate(bound.fLeft, bound.fTop); | 227 atlasCanvas->translate(bound.fLeft, bound.fTop); |
| 220 atlasCanvas->concat(atlased[i].fCTM); | 228 atlasCanvas->concat(atlased[i].fPreMat); |
| 229 atlasCanvas->concat(atlased[i].fLocalMat); |
| 221 | 230 |
| 222 SkRecordPartialDraw(*pict->fRecord.get(), atlasCanvas, bound, | 231 SkRecordPartialDraw(*pict->fRecord.get(), atlasCanvas, bound, |
| 223 layer->start()+1, layer->stop(), initialCTM); | 232 layer->start()+1, layer->stop(), initialCTM); |
| 224 | 233 |
| 225 atlasCanvas->restore(); | 234 atlasCanvas->restore(); |
| 226 } | 235 } |
| 227 | 236 |
| 228 atlasCanvas->flush(); | 237 atlasCanvas->flush(); |
| 229 } | 238 } |
| 230 | 239 |
| 231 // Render the non-atlased layers that require it | 240 // Render the non-atlased layers that require it |
| 232 for (int i = 0; i < nonAtlased.count(); ++i) { | 241 for (int i = 0; i < nonAtlased.count(); ++i) { |
| 233 GrCachedLayer* layer = nonAtlased[i].fLayer; | 242 GrCachedLayer* layer = nonAtlased[i].fLayer; |
| 234 const SkPicture* pict = nonAtlased[i].fPicture; | 243 const SkPicture* pict = nonAtlased[i].fPicture; |
| 235 const SkIPoint offset = nonAtlased[i].fOffset; | 244 const SkIPoint& offset = nonAtlased[i].fOffset; |
| 236 | 245 |
| 237 // Each non-atlased layer has its own GrTexture | 246 // Each non-atlased layer has its own GrTexture |
| 238 SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTargetDirect( | 247 SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTargetDirect( |
| 239 layer->texture()->asRenderTarget(), NULL
)); | 248 layer->texture()->asRenderTarget(), NULL
)); |
| 240 | 249 |
| 241 SkCanvas* layerCanvas = surface->getCanvas(); | 250 SkCanvas* layerCanvas = surface->getCanvas(); |
| 242 | 251 |
| 252 SkASSERT(0 == layer->rect().fLeft && 0 == layer->rect().fTop); |
| 253 |
| 243 // Add a rect clip to make sure the rendering doesn't | 254 // Add a rect clip to make sure the rendering doesn't |
| 244 // extend beyond the boundaries of the atlased sub-rect | 255 // extend beyond the boundaries of the atlased sub-rect |
| 245 SkRect bound = SkRect::MakeXYWH(SkIntToScalar(layer->rect().fLeft), | 256 SkRect bound = SkRect::MakeXYWH(SkIntToScalar(layer->rect().fLeft), |
| 246 SkIntToScalar(layer->rect().fTop), | 257 SkIntToScalar(layer->rect().fTop), |
| 247 SkIntToScalar(layer->rect().width()), | 258 SkIntToScalar(layer->rect().width()), |
| 248 SkIntToScalar(layer->rect().height())); | 259 SkIntToScalar(layer->rect().height())); |
| 249 | 260 |
| 250 layerCanvas->clipRect(bound); // TODO: still useful? | 261 layerCanvas->clipRect(bound); // TODO: still useful? |
| 251 | 262 |
| 252 layerCanvas->clear(SK_ColorTRANSPARENT); | 263 layerCanvas->clear(SK_ColorTRANSPARENT); |
| 253 | 264 |
| 254 SkMatrix initialCTM; | 265 SkMatrix initialCTM; |
| 255 initialCTM.setTranslate(SkIntToScalar(-offset.fX), | 266 initialCTM.setTranslate(SkIntToScalar(-offset.fX), SkIntToScalar(-offset
.fY)); |
| 256 SkIntToScalar(-offset.fY)); | 267 initialCTM.postConcat(nonAtlased[i].fPreMat); |
| 257 | 268 |
| 258 layerCanvas->translate(SkIntToScalar(-offset.fX), | 269 layerCanvas->translate(SkIntToScalar(-offset.fX), SkIntToScalar(-offset.
fY)); |
| 259 SkIntToScalar(-offset.fY)); | 270 layerCanvas->concat(nonAtlased[i].fPreMat); |
| 260 layerCanvas->concat(nonAtlased[i].fCTM); | 271 layerCanvas->concat(nonAtlased[i].fLocalMat); |
| 261 | 272 |
| 262 SkRecordPartialDraw(*pict->fRecord.get(), layerCanvas, bound, | 273 SkRecordPartialDraw(*pict->fRecord.get(), layerCanvas, bound, |
| 263 layer->start()+1, layer->stop(), initialCTM); | 274 layer->start()+1, layer->stop(), initialCTM); |
| 264 | 275 |
| 265 layerCanvas->flush(); | 276 layerCanvas->flush(); |
| 266 } | 277 } |
| 267 | 278 |
| 268 convert_layers_to_replacements(atlased, replacements); | 279 convert_layers_to_replacements(atlased, replacements); |
| 269 convert_layers_to_replacements(nonAtlased, replacements); | 280 convert_layers_to_replacements(nonAtlased, replacements); |
| 270 convert_layers_to_replacements(recycled, replacements); | 281 convert_layers_to_replacements(recycled, replacements); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 291 #if DISABLE_CACHING | 302 #if DISABLE_CACHING |
| 292 // This code completely clears out the atlas. It is required when | 303 // This code completely clears out the atlas. It is required when |
| 293 // caching is disabled so the atlas doesn't fill up and force more | 304 // caching is disabled so the atlas doesn't fill up and force more |
| 294 // free floating layers | 305 // free floating layers |
| 295 layerCache->purgeAll(); | 306 layerCache->purgeAll(); |
| 296 #endif | 307 #endif |
| 297 | 308 |
| 298 SkDEBUGCODE(layerCache->validate();) | 309 SkDEBUGCODE(layerCache->validate();) |
| 299 } | 310 } |
| 300 | 311 |
| OLD | NEW |