| 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 "SkCanvas.h" | 10 #include "SkCanvas.h" |
| 11 #include "SkRecordDraw.h" | 11 #include "SkRecordDraw.h" |
| 12 #include "GrRecordReplaceDraw.h" | 12 #include "GrRecordReplaceDraw.h" |
| 13 #include "SkGrPixelRef.h" | 13 #include "SkGrPixelRef.h" |
| 14 #include "SkSurface.h" | 14 #include "SkSurface.h" |
| 15 | 15 |
| 16 // Create the layer information for the hoisted layer and secure the | |
| 17 // required texture/render target resources. | |
| 18 static void prepare_for_hoisting(GrLayerCache* layerCache, | |
| 19 const SkPicture* topLevelPicture, | |
| 20 const GrAccelData::SaveLayerInfo& info, | |
| 21 SkTDArray<GrHoistedLayer>* atlased, | |
| 22 SkTDArray<GrHoistedLayer>* nonAtlased, | |
| 23 SkTDArray<GrHoistedLayer>* recycled) { | |
| 24 const SkPicture* pict = info.fPicture ? info.fPicture : topLevelPicture; | |
| 25 | |
| 26 GrCachedLayer* layer = layerCache->findLayerOrCreate(pict->uniqueID(), | |
| 27 info.fSaveLayerOpID, | |
| 28 info.fRestoreOpID, | |
| 29 info.fOriginXform, | |
| 30 info.fPaint); | |
| 31 | |
| 32 GrTextureDesc desc; | |
| 33 desc.fFlags = kRenderTarget_GrTextureFlagBit; | |
| 34 desc.fWidth = info.fSize.fWidth; | |
| 35 desc.fHeight = info.fSize.fHeight; | |
| 36 desc.fConfig = kSkia8888_GrPixelConfig; | |
| 37 // TODO: need to deal with sample count | |
| 38 | |
| 39 bool needsRendering = layerCache->lock(layer, desc, info.fHasNestedLayers ||
info.fIsNested); | |
| 40 if (NULL == layer->texture()) { | |
| 41 // GPU resources could not be secured for the hoisting of this layer | |
| 42 return; | |
| 43 } | |
| 44 | |
| 45 GrHoistedLayer* hl; | |
| 46 | |
| 47 if (needsRendering) { | |
| 48 if (layer->isAtlased()) { | |
| 49 hl = atlased->append(); | |
| 50 } else { | |
| 51 hl = nonAtlased->append(); | |
| 52 } | |
| 53 } else { | |
| 54 hl = recycled->append(); | |
| 55 } | |
| 56 | |
| 57 hl->fLayer = layer; | |
| 58 hl->fPicture = pict; | |
| 59 hl->fOffset = info.fOffset; | |
| 60 hl->fCTM = info.fOriginXform; | |
| 61 } | |
| 62 | |
| 63 // Return true if any layers are suitable for hoisting | 16 // Return true if any layers are suitable for hoisting |
| 64 bool GrLayerHoister::FindLayersToHoist(GrContext* context, | 17 bool GrLayerHoister::FindLayersToHoist(GrContext* context, |
| 65 const SkPicture* topLevelPicture, | 18 const SkPicture* topLevelPicture, |
| 66 const SkRect& query, | 19 const SkRect& query, |
| 67 SkTDArray<GrHoistedLayer>* atlased, | 20 SkTDArray<GrHoistedLayer>* atlased, |
| 68 SkTDArray<GrHoistedLayer>* nonAtlased, | 21 SkTDArray<GrHoistedLayer>* nonAtlased, |
| 69 SkTDArray<GrHoistedLayer>* recycled) { | 22 SkTDArray<GrHoistedLayer>* recycled) { |
| 23 bool anyHoisted = false; |
| 70 | 24 |
| 71 GrLayerCache* layerCache = context->getLayerCache(); | 25 GrLayerCache* layerCache = context->getLayerCache(); |
| 72 | 26 |
| 73 layerCache->processDeletedPictures(); | 27 layerCache->processDeletedPictures(); |
| 74 | 28 |
| 75 SkPicture::AccelData::Key key = GrAccelData::ComputeAccelDataKey(); | 29 SkPicture::AccelData::Key key = GrAccelData::ComputeAccelDataKey(); |
| 76 | 30 |
| 77 const SkPicture::AccelData* topLevelData = topLevelPicture->EXPERIMENTAL_get
AccelData(key); | 31 const SkPicture::AccelData* topLevelData = topLevelPicture->EXPERIMENTAL_get
AccelData(key); |
| 78 if (!topLevelData) { | 32 if (NULL == topLevelData) { |
| 79 return false; | 33 return false; |
| 80 } | 34 } |
| 81 | 35 |
| 82 const GrAccelData *topLevelGPUData = static_cast<const GrAccelData*>(topLeve
lData); | 36 const GrAccelData *topLevelGPUData = static_cast<const GrAccelData*>(topLeve
lData); |
| 83 if (0 == topLevelGPUData->numSaveLayers()) { | 37 if (0 == topLevelGPUData->numSaveLayers()) { |
| 84 return false; | 38 return false; |
| 85 } | 39 } |
| 86 | 40 |
| 87 bool anyHoisted = false; | 41 // Layer hoisting pre-renders the entire layer since it will be cached and p
otentially |
| 42 // reused with different clips (e.g., in different tiles). Because of this t
he |
| 43 // clip will not be limiting the size of the pre-rendered layer. kSaveLayerM
axSize |
| 44 // is used to limit which clips are pre-rendered. |
| 45 static const int kSaveLayerMaxSize = 256; |
| 88 | 46 |
| 89 // The layer hoisting code will pre-render and cache an entire layer if most | 47 SkAutoTArray<bool> pullForward(topLevelGPUData->numSaveLayers()); |
| 90 // of it is being used (~70%) and it will fit in a texture. This is to allow | |
| 91 // such layers to be re-used for different clips/tiles. | |
| 92 // Small layers will additionally be atlased. | |
| 93 // The only limitation right now is that nested layers are currently not hoi
sted. | |
| 94 // Parent layers are hoisted but are never atlased (so that we never swap | |
| 95 // away from the atlas rendertarget when generating the hoisted layers). | |
| 96 | 48 |
| 97 atlased->setReserve(atlased->count() + topLevelGPUData->numSaveLayers()); | 49 // Pre-render all the layers that intersect the query rect |
| 98 | |
| 99 // Find and prepare for hoisting all the layers that intersect the query rec
t | |
| 100 for (int i = 0; i < topLevelGPUData->numSaveLayers(); ++i) { | 50 for (int i = 0; i < topLevelGPUData->numSaveLayers(); ++i) { |
| 51 pullForward[i] = false; |
| 101 | 52 |
| 102 const GrAccelData::SaveLayerInfo& info = topLevelGPUData->saveLayerInfo(
i); | 53 const GrAccelData::SaveLayerInfo& info = topLevelGPUData->saveLayerInfo(
i); |
| 103 | 54 |
| 104 SkRect layerRect = SkRect::MakeXYWH(SkIntToScalar(info.fOffset.fX), | 55 SkRect layerRect = SkRect::MakeXYWH(SkIntToScalar(info.fOffset.fX), |
| 105 SkIntToScalar(info.fOffset.fY), | 56 SkIntToScalar(info.fOffset.fY), |
| 106 SkIntToScalar(info.fSize.fWidth), | 57 SkIntToScalar(info.fSize.fWidth), |
| 107 SkIntToScalar(info.fSize.fHeight)); | 58 SkIntToScalar(info.fSize.fHeight)); |
| 108 | 59 |
| 109 if (!SkRect::Intersects(query, layerRect)) { | 60 if (!SkRect::Intersects(query, layerRect)) { |
| 110 continue; | 61 continue; |
| 111 } | 62 } |
| 112 | 63 |
| 113 // TODO: ignore perspective projected layers here! | 64 // TODO: ignore perspective projected layers here! |
| 114 // TODO: once this code is more stable unsuitable layers can | 65 // TODO: once this code is more stable unsuitable layers can |
| 115 // just be omitted during the optimization stage | 66 // just be omitted during the optimization stage |
| 116 if (!info.fValid || info.fIsNested) { | 67 if (!info.fValid || |
| 68 kSaveLayerMaxSize < info.fSize.fWidth || |
| 69 kSaveLayerMaxSize < info.fSize.fHeight || |
| 70 info.fIsNested) { |
| 117 continue; | 71 continue; |
| 118 } | 72 } |
| 119 | 73 |
| 120 prepare_for_hoisting(layerCache, topLevelPicture, info, atlased, nonAtla
sed, recycled); | 74 pullForward[i] = true; |
| 121 anyHoisted = true; | 75 anyHoisted = true; |
| 122 } | 76 } |
| 123 | 77 |
| 78 if (!anyHoisted) { |
| 79 return false; |
| 80 } |
| 81 |
| 82 atlased->setReserve(atlased->reserved() + topLevelGPUData->numSaveLayers()); |
| 83 |
| 84 // Generate the layer and/or ensure it is locked |
| 85 for (int i = 0; i < topLevelGPUData->numSaveLayers(); ++i) { |
| 86 if (pullForward[i]) { |
| 87 const GrAccelData::SaveLayerInfo& info = topLevelGPUData->saveLayerI
nfo(i); |
| 88 const SkPicture* pict = info.fPicture ? info.fPicture : topLevelPict
ure; |
| 89 |
| 90 GrCachedLayer* layer = layerCache->findLayerOrCreate(pict->uniqueID(
), |
| 91 info.fSaveLayer
OpID, |
| 92 info.fRestoreOp
ID, |
| 93 info.fOriginXfo
rm, |
| 94 info.fPaint); |
| 95 |
| 96 GrTextureDesc desc; |
| 97 desc.fFlags = kRenderTarget_GrTextureFlagBit; |
| 98 desc.fWidth = info.fSize.fWidth; |
| 99 desc.fHeight = info.fSize.fHeight; |
| 100 desc.fConfig = kSkia8888_GrPixelConfig; |
| 101 // TODO: need to deal with sample count |
| 102 |
| 103 bool needsRendering = layerCache->lock(layer, desc, |
| 104 info.fHasNestedLayers || info
.fIsNested); |
| 105 if (NULL == layer->texture()) { |
| 106 continue; |
| 107 } |
| 108 |
| 109 GrHoistedLayer* hl; |
| 110 |
| 111 if (needsRendering) { |
| 112 if (layer->isAtlased()) { |
| 113 hl = atlased->append(); |
| 114 } else { |
| 115 hl = nonAtlased->append(); |
| 116 } |
| 117 } else { |
| 118 hl = recycled->append(); |
| 119 } |
| 120 |
| 121 hl->fLayer = layer; |
| 122 hl->fPicture = pict; |
| 123 hl->fOffset = info.fOffset; |
| 124 hl->fCTM = info.fOriginXform; |
| 125 } |
| 126 } |
| 127 |
| 124 return anyHoisted; | 128 return anyHoisted; |
| 125 } | 129 } |
| 126 | 130 |
| 127 static void wrap_texture(GrTexture* texture, int width, int height, SkBitmap* re
sult) { | 131 static void wrap_texture(GrTexture* texture, int width, int height, SkBitmap* re
sult) { |
| 128 SkImageInfo info = SkImageInfo::MakeN32Premul(width, height); | 132 SkImageInfo info = SkImageInfo::MakeN32Premul(width, height); |
| 129 result->setInfo(info); | 133 result->setInfo(info); |
| 130 result->setPixelRef(SkNEW_ARGS(SkGrPixelRef, (info, texture)))->unref(); | 134 result->setPixelRef(SkNEW_ARGS(SkGrPixelRef, (info, texture)))->unref(); |
| 131 } | 135 } |
| 132 | 136 |
| 133 static void convert_layers_to_replacements(const SkTDArray<GrHoistedLayer>& laye
rs, | 137 static void convert_layers_to_replacements(const SkTDArray<GrHoistedLayer>& laye
rs, |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 295 } | 299 } |
| 296 | 300 |
| 297 #if DISABLE_CACHING | 301 #if DISABLE_CACHING |
| 298 // This code completely clears out the atlas. It is required when | 302 // This code completely clears out the atlas. It is required when |
| 299 // caching is disabled so the atlas doesn't fill up and force more | 303 // caching is disabled so the atlas doesn't fill up and force more |
| 300 // free floating layers | 304 // free floating layers |
| 301 layerCache->purgeAll(); | 305 layerCache->purgeAll(); |
| 302 #endif | 306 #endif |
| 303 } | 307 } |
| 304 | 308 |
| OLD | NEW |