| Index: src/gpu/SkGpuDevice.cpp
|
| diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
|
| index 2853805a5b1b3bcbb73e461eb4a493d01756badb..b1e23f9474afe22abd0a06e5be4de0bba6729dcd 100644
|
| --- a/src/gpu/SkGpuDevice.cpp
|
| +++ b/src/gpu/SkGpuDevice.cpp
|
| @@ -1871,7 +1871,7 @@ static void wrap_texture(GrTexture* texture, int width, int height, SkBitmap* re
|
| result->setPixelRef(SkNEW_ARGS(SkGrPixelRef, (info, texture)))->unref();
|
| }
|
|
|
| -bool SkGpuDevice::EXPERIMENTAL_drawPicture(SkCanvas* canvas, const SkPicture* picture) {
|
| +bool SkGpuDevice::EXPERIMENTAL_drawPicture(SkCanvas* mainCanvas, const SkPicture* picture) {
|
| fContext->getLayerCache()->processDeletedPictures();
|
|
|
| SkPicture::AccelData::Key key = GPUAccelData::ComputeAccelDataKey();
|
| @@ -1893,7 +1893,7 @@ bool SkGpuDevice::EXPERIMENTAL_drawPicture(SkCanvas* canvas, const SkPicture* pi
|
| }
|
|
|
| SkRect clipBounds;
|
| - if (!canvas->getClipBounds(&clipBounds)) {
|
| + if (!mainCanvas->getClipBounds(&clipBounds)) {
|
| return true;
|
| }
|
| SkIRect query;
|
| @@ -1970,13 +1970,19 @@ bool SkGpuDevice::EXPERIMENTAL_drawPicture(SkCanvas* canvas, const SkPicture* pi
|
|
|
| SkPictureReplacementPlayback::PlaybackReplacements replacements;
|
|
|
| + SkTDArray<GrCachedLayer*> atlased, nonAtlased;
|
| + atlased.setReserve(gpuData->numSaveLayers());
|
| +
|
| // Generate the layer and/or ensure it is locked
|
| for (int i = 0; i < gpuData->numSaveLayers(); ++i) {
|
| if (pullForward[i]) {
|
| - GrCachedLayer* layer = fContext->getLayerCache()->findLayerOrCreate(picture, i);
|
| -
|
| const GPUAccelData::SaveLayerInfo& info = gpuData->saveLayerInfo(i);
|
|
|
| + GrCachedLayer* layer = fContext->getLayerCache()->findLayerOrCreate(picture,
|
| + info.fSaveLayerOpID,
|
| + info.fRestoreOpID,
|
| + info.fCTM);
|
| +
|
| SkPictureReplacementPlayback::PlaybackReplacements::ReplacementInfo* layerInfo =
|
| replacements.push();
|
| layerInfo->fStart = info.fSaveLayerOpID;
|
| @@ -2009,56 +2015,110 @@ bool SkGpuDevice::EXPERIMENTAL_drawPicture(SkCanvas* canvas, const SkPicture* pi
|
| layer->rect().width(),
|
| layer->rect().height());
|
|
|
| -
|
| if (needsRendering) {
|
| - SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTargetDirect(
|
| - layer->texture()->asRenderTarget(),
|
| - SkSurface::kStandard_TextRenderMode,
|
| - SkSurface::kDontClear_RenderTargetFlag));
|
| -
|
| - SkCanvas* canvas = surface->getCanvas();
|
| -
|
| - // Add a rect clip to make sure the rendering doesn't
|
| - // extend beyond the boundaries of the atlased sub-rect
|
| - SkRect bound = SkRect::Make(layerInfo->fSrcRect);
|
| - canvas->clipRect(bound);
|
| -
|
| if (layer->isAtlased()) {
|
| - // Since 'clear' doesn't respect the clip we need to draw a rect
|
| - // TODO: ensure none of the atlased layers contain a clear call!
|
| - SkPaint paint;
|
| - paint.setColor(SK_ColorTRANSPARENT);
|
| - paint.setXfermode(SkXfermode::Create(SkXfermode::kSrc_Mode))->unref();
|
| - canvas->drawRect(bound, paint);
|
| + *atlased.append() = layer;
|
| } else {
|
| - canvas->clear(SK_ColorTRANSPARENT);
|
| + *nonAtlased.append() = layer;
|
| }
|
| + }
|
| + }
|
| + }
|
|
|
| - // info.fCTM maps the layer's top/left to the origin.
|
| - // If this layer is atlased the top/left corner needs
|
| - // to be offset to some arbitrary location in the backing
|
| - // texture.
|
| - canvas->translate(bound.fLeft, bound.fTop);
|
| - canvas->concat(info.fCTM);
|
| + // Render the atlased layers that require it
|
| + if (atlased.count() > 0) {
|
| + // All the atlased layers are rendered into the same GrTexture
|
| + SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTargetDirect(
|
| + atlased[0]->texture()->asRenderTarget(),
|
| + SkSurface::kStandard_TextRenderMode,
|
| + SkSurface::kDontClear_RenderTargetFlag));
|
|
|
| - SkPictureRangePlayback rangePlayback(picture,
|
| - info.fSaveLayerOpID,
|
| - info.fRestoreOpID);
|
| - rangePlayback.draw(canvas, NULL);
|
| + SkCanvas* atlasCanvas = surface->getCanvas();
|
|
|
| - canvas->flush();
|
| - }
|
| + SkPaint paint;
|
| + paint.setColor(SK_ColorTRANSPARENT);
|
| + paint.setXfermode(SkXfermode::Create(SkXfermode::kSrc_Mode))->unref();
|
| +
|
| + for (int i = 0; i < atlased.count(); ++i) {
|
| + GrCachedLayer* layer = atlased[i];
|
| +
|
| + atlasCanvas->save();
|
| +
|
| + // Add a rect clip to make sure the rendering doesn't
|
| + // extend beyond the boundaries of the atlased sub-rect
|
| + SkRect bound = SkRect::MakeXYWH(SkIntToScalar(layer->rect().fLeft),
|
| + SkIntToScalar(layer->rect().fTop),
|
| + SkIntToScalar(layer->rect().width()),
|
| + SkIntToScalar(layer->rect().height()));
|
| + atlasCanvas->clipRect(bound);
|
| +
|
| + // Since 'clear' doesn't respect the clip we need to draw a rect
|
| + // TODO: ensure none of the atlased layers contain a clear call!
|
| + atlasCanvas->drawRect(bound, paint);
|
| +
|
| + // info.fCTM maps the layer's top/left to the origin.
|
| + // Since this layer is atlased, the top/left corner needs
|
| + // to be offset to the correct location in the backing texture.
|
| + atlasCanvas->translate(bound.fLeft, bound.fTop);
|
| + atlasCanvas->concat(layer->ctm());
|
| +
|
| + SkPictureRangePlayback rangePlayback(picture,
|
| + layer->start(),
|
| + layer->stop());
|
| + rangePlayback.draw(atlasCanvas, NULL);
|
| +
|
| + atlasCanvas->restore();
|
| }
|
| +
|
| + atlasCanvas->flush();
|
| }
|
|
|
| - // Playback using new layers
|
| + // Render the non-atlased layers that require it
|
| + for (int i = 0; i < nonAtlased.count(); ++i) {
|
| + GrCachedLayer* layer = nonAtlased[i];
|
| +
|
| + // Each non-atlased layer has its own GrTexture
|
| + SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTargetDirect(
|
| + layer->texture()->asRenderTarget(),
|
| + SkSurface::kStandard_TextRenderMode,
|
| + SkSurface::kDontClear_RenderTargetFlag));
|
| +
|
| + SkCanvas* layerCanvas = surface->getCanvas();
|
| +
|
| + // Add a rect clip to make sure the rendering doesn't
|
| + // extend beyond the boundaries of the atlased sub-rect
|
| + SkRect bound = SkRect::MakeXYWH(SkIntToScalar(layer->rect().fLeft),
|
| + SkIntToScalar(layer->rect().fTop),
|
| + SkIntToScalar(layer->rect().width()),
|
| + SkIntToScalar(layer->rect().height()));
|
| +
|
| + layerCanvas->clipRect(bound); // TODO: still useful?
|
| +
|
| + layerCanvas->clear(SK_ColorTRANSPARENT);
|
| +
|
| + layerCanvas->concat(layer->ctm());
|
| +
|
| + SkPictureRangePlayback rangePlayback(picture,
|
| + layer->start(),
|
| + layer->stop());
|
| + rangePlayback.draw(layerCanvas, NULL);
|
| +
|
| + layerCanvas->flush();
|
| + }
|
| +
|
| + // Render the entire picture using new layers
|
| SkPictureReplacementPlayback playback(picture, &replacements, ops.get());
|
|
|
| - playback.draw(canvas, NULL);
|
| + playback.draw(mainCanvas, NULL);
|
|
|
| // unlock the layers
|
| for (int i = 0; i < gpuData->numSaveLayers(); ++i) {
|
| - GrCachedLayer* layer = fContext->getLayerCache()->findLayer(picture, i);
|
| + const GPUAccelData::SaveLayerInfo& info = gpuData->saveLayerInfo(i);
|
| +
|
| + GrCachedLayer* layer = fContext->getLayerCache()->findLayer(picture,
|
| + info.fSaveLayerOpID,
|
| + info.fRestoreOpID,
|
| + info.fCTM);
|
| fContext->getLayerCache()->unlock(layer);
|
| }
|
|
|
|
|