| Index: src/gpu/SkGpuDevice.cpp
|
| diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
|
| index 693e16c0e320d13ad9889320f947c7b9f11ed8bf..3b2e5b17d78407bc55eeddde4070c72c8eb79f48 100644
|
| --- a/src/gpu/SkGpuDevice.cpp
|
| +++ b/src/gpu/SkGpuDevice.cpp
|
| @@ -1887,7 +1887,7 @@ bool SkGpuDevice::FindLayersToHoist(const GrAccelData *gpuData,
|
| // reused with different clips (e.g., in different tiles). Because of this the
|
| // clip will not be limiting the size of the pre-rendered layer. kSaveLayerMaxSize
|
| // is used to limit which clips are pre-rendered.
|
| - static const int kSaveLayerMaxSize = 256;
|
| + static const int kSaveLayerMaxSize1 = 512;
|
|
|
| if (NULL != ops) {
|
| // In this case the picture has been generated with a BBH so we use
|
| @@ -1913,8 +1913,9 @@ bool SkGpuDevice::FindLayersToHoist(const GrAccelData *gpuData,
|
| // TODO: once this code is more stable unsuitable layers can
|
| // just be omitted during the optimization stage
|
| if (!info.fValid ||
|
| - kSaveLayerMaxSize < info.fSize.fWidth ||
|
| - kSaveLayerMaxSize < info.fSize.fHeight ||
|
| + kSaveLayerMaxSize1 < info.fSize.fWidth ||
|
| + kSaveLayerMaxSize1 < info.fSize.fHeight ||
|
| + info.fSize.fWidth * info.fSize.fHeight > 256 * 256 ||
|
| info.fIsNested) {
|
| continue; // this layer is unsuitable
|
| }
|
| @@ -1941,8 +1942,9 @@ bool SkGpuDevice::FindLayersToHoist(const GrAccelData *gpuData,
|
| // TODO: once this code is more stable unsuitable layers can
|
| // just be omitted during the optimization stage
|
| if (!info.fValid ||
|
| - kSaveLayerMaxSize < info.fSize.fWidth ||
|
| - kSaveLayerMaxSize < info.fSize.fHeight ||
|
| + kSaveLayerMaxSize1 < info.fSize.fWidth ||
|
| + kSaveLayerMaxSize1 < info.fSize.fHeight ||
|
| + info.fSize.fWidth * info.fSize.fHeight > 256 * 256 ||
|
| info.fIsNested) {
|
| continue;
|
| }
|
| @@ -1957,8 +1959,7 @@ bool SkGpuDevice::FindLayersToHoist(const GrAccelData *gpuData,
|
|
|
| bool SkGpuDevice::EXPERIMENTAL_drawPicture(SkCanvas* mainCanvas, const SkPicture* picture,
|
| const SkMatrix* matrix, const SkPaint* paint) {
|
| - // todo: should handle these natively
|
| - if (matrix || paint) {
|
| + if (NULL != matrix || NULL != paint) {
|
| return false;
|
| }
|
|
|
| @@ -1996,62 +1997,97 @@ bool SkGpuDevice::EXPERIMENTAL_drawPicture(SkCanvas* mainCanvas, const SkPicture
|
| }
|
|
|
| SkPictureReplacementPlayback::PlaybackReplacements replacements;
|
| +}
|
| +
|
| +void SkGpuDevice::EXPERIMENTAL_preDrawPicture(const SkPicture* picture,
|
| + const SkMatrix* matrix, const SkPaint* paint,
|
| + const SkIRect* target) {
|
| + if (NULL != matrix || NULL != paint) {
|
| + return;
|
| + }
|
|
|
| - SkTDArray<GrCachedLayer*> atlased, nonAtlased;
|
| - atlased.setReserve(gpuData->numSaveLayers());
|
| + fContext->getLayerCache()->processDeletedPictures();
|
|
|
| - // Generate the layer and/or ensure it is locked
|
| + SkPicture::AccelData::Key key = GrAccelData::ComputeAccelDataKey();
|
| +
|
| + const SkPicture::AccelData* data = picture->EXPERIMENTAL_getAccelData(key);
|
| + if (NULL == data) {
|
| + return;
|
| + }
|
| +
|
| + const GrAccelData *gpuData = static_cast<const GrAccelData*>(data);
|
| +
|
| + if (0 == gpuData->numSaveLayers()) {
|
| + return;
|
| + }
|
| +
|
| + SkAutoTArray<bool> pullForward(gpuData->numSaveLayers());
|
| for (int i = 0; i < gpuData->numSaveLayers(); ++i) {
|
| - if (pullForward[i]) {
|
| - const GrAccelData::SaveLayerInfo& info = gpuData->saveLayerInfo(i);
|
| + pullForward[i] = false;
|
| + }
|
|
|
| - GrCachedLayer* layer = fContext->getLayerCache()->findLayerOrCreate(picture->uniqueID(),
|
| - info.fSaveLayerOpID,
|
| - info.fRestoreOpID,
|
| - info.fCTM);
|
| -
|
| - SkPictureReplacementPlayback::PlaybackReplacements::ReplacementInfo* layerInfo =
|
| - replacements.push();
|
| - layerInfo->fStart = info.fSaveLayerOpID;
|
| - layerInfo->fStop = info.fRestoreOpID;
|
| - layerInfo->fPos = info.fOffset;
|
| -
|
| - GrTextureDesc desc;
|
| - desc.fFlags = kRenderTarget_GrTextureFlagBit;
|
| - desc.fWidth = info.fSize.fWidth;
|
| - desc.fHeight = info.fSize.fHeight;
|
| - desc.fConfig = kSkia8888_GrPixelConfig;
|
| - // TODO: need to deal with sample count
|
| -
|
| - bool needsRendering = fContext->getLayerCache()->lock(layer, desc,
|
| - info.fHasNestedLayers || info.fIsNested);
|
| - if (NULL == layer->texture()) {
|
| - continue;
|
| - }
|
| + SkAutoTDelete<const SkPicture::OperationList> ops;
|
| + SkIRect query;
|
| +
|
| + if (NULL != target) {
|
| + // TODO: this is suboptimal since it will be repeated in EXPERIMENTAL_drawPicture!
|
| + // TODO: just always use 'target' to determine hoisting (rather than active ops)?
|
| + ops.reset(picture->EXPERIMENTAL_getActiveOps(*target));
|
| + query = *target;
|
| + } else {
|
| + query = SkIRect::MakeWH(picture->width(), picture->height());
|
| + }
|
|
|
| - layerInfo->fBM = SkNEW(SkBitmap); // fBM is allocated so ReplacementInfo can be POD
|
| - wrap_texture(layer->texture(),
|
| - !layer->isAtlased() ? desc.fWidth : layer->texture()->width(),
|
| - !layer->isAtlased() ? desc.fHeight : layer->texture()->height(),
|
| - layerInfo->fBM);
|
| + if (!FindLayersToHoist(gpuData, ops.get(), query, pullForward.get())) {
|
| + return;
|
| + }
|
|
|
| - SkASSERT(info.fPaint);
|
| - layerInfo->fPaint = info.fPaint;
|
| + *fPreprocessed.append() = SkRef(picture);
|
|
|
| - layerInfo->fSrcRect = SkIRect::MakeXYWH(layer->rect().fLeft,
|
| - layer->rect().fTop,
|
| - layer->rect().width(),
|
| - layer->rect().height());
|
| + fDeferredAtlasDraws.setReserve(fDeferredAtlasDraws.count() + gpuData->numSaveLayers());
|
|
|
| - if (needsRendering) {
|
| - if (layer->isAtlased()) {
|
| - *atlased.append() = layer;
|
| - } else {
|
| - *nonAtlased.append() = layer;
|
| - }
|
| + // Lock the memory required for all the hoisted layers and add them
|
| + // to the deferred drawing lists
|
| + // TODO: this may be a bit more VRAM intensive then necessary
|
| + for (int i = 0; i < gpuData->numSaveLayers(); ++i) {
|
| + if (!pullForward[i]) {
|
| + continue;
|
| + }
|
| +
|
| + const GrAccelData::SaveLayerInfo& info = gpuData->saveLayerInfo(i);
|
| +
|
| + GrCachedLayer* layer = fContext->getLayerCache()->findLayerOrCreate(picture->uniqueID(),
|
| + info.fSaveLayerOpID,
|
| + info.fRestoreOpID,
|
| + info.fCTM);
|
| +
|
| + GrTextureDesc desc;
|
| + desc.fFlags = kRenderTarget_GrTextureFlagBit;
|
| + desc.fWidth = info.fSize.fWidth;
|
| + desc.fHeight = info.fSize.fHeight;
|
| + desc.fConfig = kSkia8888_GrPixelConfig;
|
| + // TODO: need to deal with sample count
|
| +
|
| + bool needsRendering = fContext->getLayerCache()->lock(layer, desc,
|
| + info.fHasNestedLayers || info.fIsNested);
|
| + if (NULL == layer->texture()) {
|
| + continue;
|
| + }
|
| +
|
| + if (needsRendering) {
|
| + DeferredDraw* draw;
|
| +
|
| + if (layer->isAtlased()) {
|
| + draw = fDeferredAtlasDraws.append();
|
| + } else {
|
| + draw = fDeferredNonAtlasDraws.append();
|
| }
|
| +
|
| + draw->layer = layer;
|
| + draw->picture1 = picture;
|
| }
|
| }
|
| +}
|
|
|
| this->drawLayers(picture, atlased, nonAtlased);
|
|
|
| @@ -2150,6 +2186,7 @@ void SkGpuDevice::drawLayers(const SkPicture* picture,
|
| }
|
| }
|
|
|
| +<<<<<<< HEAD
|
| void SkGpuDevice::unlockLayers(const SkPicture* picture) {
|
| SkPicture::AccelData::Key key = GrAccelData::ComputeAccelDataKey();
|
|
|
| @@ -2158,26 +2195,147 @@ void SkGpuDevice::unlockLayers(const SkPicture* picture) {
|
|
|
| const GrAccelData *gpuData = static_cast<const GrAccelData*>(data);
|
| SkASSERT(0 != gpuData->numSaveLayers());
|
| +=======
|
| + fDeferredAtlasDraws.rewind();
|
| + fDeferredNonAtlasDraws.rewind();
|
| +}
|
| +
|
| +bool SkGpuDevice::EXPERIMENTAL_drawPicture(SkCanvas* mainCanvas, const SkPicture* picture,
|
| + const SkMatrix* matrix, const SkPaint* paint) {
|
| + // todo: should handle these natively
|
| + if (matrix || paint) {
|
| + return false;
|
| + }
|
| +
|
| + fContext->getLayerCache()->processDeletedPictures();
|
| +
|
| + SkPicture::AccelData::Key key = GrAccelData::ComputeAccelDataKey();
|
|
|
| - // unlock the layers
|
| + const SkPicture::AccelData* data = picture->EXPERIMENTAL_getAccelData(key);
|
| + if (NULL == data) {
|
| + return false;
|
| + }
|
| +
|
| + const GrAccelData *gpuData = static_cast<const GrAccelData*>(data);
|
| +
|
| + if (0 == gpuData->numSaveLayers()) {
|
| + return false;
|
| + }
|
| +
|
| + SkAutoTArray<bool> pullForward(gpuData->numSaveLayers());
|
| + for (int i = 0; i < gpuData->numSaveLayers(); ++i) {
|
| + pullForward[i] = false;
|
| + }
|
| +
|
| + SkRect clipBounds;
|
| + if (!mainCanvas->getClipBounds(&clipBounds)) {
|
| + return true;
|
| + }
|
| + SkIRect query;
|
| + clipBounds.roundOut(&query);
|
| +
|
| + SkAutoTDelete<const SkPicture::OperationList> ops(picture->EXPERIMENTAL_getActiveOps(query));
|
| +>>>>>>> Reapply patch
|
| +
|
| + if (!FindLayersToHoist(gpuData, ops.get(), query, pullForward.get())) {
|
| + return false;
|
| + }
|
| +
|
| + this->flushDeferredDraws();
|
| +
|
| + SkPictureReplacementPlayback::PlaybackReplacements replacements;
|
| +
|
| + // Assemble the information needed to render the original picture with the
|
| + // hoisted layers
|
| for (int i = 0; i < gpuData->numSaveLayers(); ++i) {
|
| + if (!pullForward[i]) {
|
| + continue;
|
| + }
|
| +
|
| const GrAccelData::SaveLayerInfo& info = gpuData->saveLayerInfo(i);
|
|
|
| +<<<<<<< HEAD
|
| GrCachedLayer* layer = fContext->getLayerCache()->findLayer(picture->uniqueID(),
|
| info.fSaveLayerOpID,
|
| info.fRestoreOpID,
|
| info.fCTM);
|
| fContext->getLayerCache()->unlock(layer);
|
| +=======
|
| + GrCachedLayer* layer = fContext->getLayerCache()->findLayerOrCreate(picture->uniqueID(),
|
| + info.fSaveLayerOpID,
|
| + info.fRestoreOpID,
|
| + info.fCTM);
|
| + SkASSERT(layer->locked());
|
| +
|
| + SkPictureReplacementPlayback::PlaybackReplacements::ReplacementInfo* layerInfo =
|
| + replacements.push();
|
| + layerInfo->fStart = info.fSaveLayerOpID;
|
| + layerInfo->fStop = info.fRestoreOpID;
|
| + layerInfo->fPos = info.fOffset;
|
| +
|
| + layerInfo->fBM = SkNEW(SkBitmap); // fBM is allocated so ReplacementInfo can be POD
|
| + wrap_texture(layer->texture(),
|
| + layer->isAtlased() ? layer->texture()->width() : info.fSize.fWidth,
|
| + layer->isAtlased() ? layer->texture()->height() : info.fSize.fHeight,
|
| + layerInfo->fBM);
|
| +
|
| + SkASSERT(info.fPaint);
|
| + layerInfo->fPaint = info.fPaint;
|
| +
|
| + layerInfo->fSrcRect = SkIRect::MakeXYWH(layer->rect().fLeft,
|
| + layer->rect().fTop,
|
| + layer->rect().width(),
|
| + layer->rect().height());
|
| +>>>>>>> Reapply patch
|
| + }
|
| +
|
| + // Render the entire picture using new layers
|
| + SkPictureReplacementPlayback playback(picture, &replacements, ops.get());
|
| +
|
| + playback.draw(mainCanvas, NULL);
|
| +
|
| + return true;
|
| +}
|
| +
|
| +void SkGpuDevice::EXPERIMENTAL_postDrawPicture() {
|
| + SkPicture::AccelData::Key key = GrAccelData::ComputeAccelDataKey();
|
| +
|
| + for (int i = 0; i < fPreprocessed.count(); ++i) {
|
| + const SkPicture* picture = fPreprocessed[i];
|
| +
|
| + const SkPicture::AccelData* data = picture->EXPERIMENTAL_getAccelData(key);
|
| + SkASSERT(NULL != data);
|
| +
|
| + const GrAccelData *gpuData = static_cast<const GrAccelData*>(data);
|
| + SkASSERT(0 != gpuData->numSaveLayers());
|
| +
|
| + // unlock the layers associated with the current picture
|
| + for (int i = 0; i < gpuData->numSaveLayers(); ++i) {
|
| + const GrAccelData::SaveLayerInfo& info = gpuData->saveLayerInfo(i);
|
| +
|
| + GrCachedLayer* layer = fContext->getLayerCache()->findLayer(picture->uniqueID(),
|
| + info.fSaveLayerOpID,
|
| + info.fRestoreOpID,
|
| + info.fCTM);
|
| + fContext->getLayerCache()->unlock(layer);
|
| + }
|
| +
|
| +#if DISABLE_CACHING
|
| + // TODO: for debugging only
|
| + fContext->getLayerCache()->purge(picture->uniqueID());
|
| +#endif
|
| +
|
| + picture->unref();
|
| }
|
|
|
| #if DISABLE_CACHING
|
| // This code completely clears out the atlas. It is required when
|
| // caching is disabled so the atlas doesn't fill up and force more
|
| // free floating layers
|
| - fContext->getLayerCache()->purge(picture->uniqueID());
|
| -
|
| fContext->getLayerCache()->purgeAll();
|
| #endif
|
| +
|
| + fPreprocessed.rewind();
|
| }
|
|
|
| SkImageFilter::Cache* SkGpuDevice::getImageFilterCache() {
|
|
|