| Index: src/gpu/SkGpuDevice.cpp
|
| ===================================================================
|
| --- src/gpu/SkGpuDevice.cpp (revision 14079)
|
| +++ src/gpu/SkGpuDevice.cpp (working copy)
|
| @@ -28,6 +28,7 @@
|
| #include "SkMaskFilter.h"
|
| #include "SkPathEffect.h"
|
| #include "SkPicture.h"
|
| +#include "SkPicturePlayback.h"
|
| #include "SkRRect.h"
|
| #include "SkStroke.h"
|
| #include "SkSurface.h"
|
| @@ -35,6 +36,8 @@
|
| #include "SkUtils.h"
|
| #include "SkErrorInternals.h"
|
|
|
| +#define USE_SCRATCH 1
|
| +
|
| #define CACHE_COMPATIBLE_DEVICE_TEXTURES 1
|
|
|
| #if 0
|
| @@ -193,20 +196,21 @@
|
| fMainTextContext = SkNEW_ARGS(GrDistanceFieldTextContext, (fContext, fLeakyProperties));
|
| fFallbackTextContext = SkNEW_ARGS(GrBitmapTextContext, (fContext, fLeakyProperties));
|
|
|
| - fRenderTarget = NULL;
|
| + fRenderTarget1 = NULL;
|
| fNeedClear = flags & kNeedClear_Flag;
|
|
|
| SkASSERT(NULL != renderTarget);
|
| - fRenderTarget = renderTarget;
|
| - fRenderTarget->ref();
|
| +// SkDebugf("initFromRenderTarget\n");
|
| + fRenderTarget1 = renderTarget;
|
| + fRenderTarget1->ref();
|
|
|
| // Hold onto to the texture in the pixel ref (if there is one) because the texture holds a ref
|
| // on the RT but not vice-versa.
|
| // TODO: Remove this trickery once we figure out how to make SkGrPixelRef do this without
|
| // busting chrome (for a currently unknown reason).
|
| - GrSurface* surface = fRenderTarget->asTexture();
|
| + GrSurface* surface = fRenderTarget1->asTexture();
|
| if (NULL == surface) {
|
| - surface = fRenderTarget;
|
| + surface = fRenderTarget1;
|
| }
|
|
|
| SkImageInfo info;
|
| @@ -324,7 +328,7 @@
|
|
|
| // The GrContext takes a ref on the target. We don't want to cause the render
|
| // target to be unnecessarily kept alive.
|
| - if (fContext->getRenderTarget() == fRenderTarget) {
|
| + if (fContext->getRenderTarget() == fRenderTarget1) {
|
| fContext->setRenderTarget(NULL);
|
| }
|
|
|
| @@ -332,7 +336,7 @@
|
| fContext->setClip(NULL);
|
| }
|
|
|
| - SkSafeUnref(fRenderTarget);
|
| + SkSafeUnref(fRenderTarget1);
|
| fContext->unref();
|
| }
|
|
|
| @@ -340,7 +344,7 @@
|
|
|
| void SkGpuDevice::makeRenderTargetCurrent() {
|
| DO_DEFERRED_CLEAR();
|
| - fContext->setRenderTarget(fRenderTarget);
|
| + fContext->setRenderTarget(fRenderTarget1);
|
| }
|
|
|
| ///////////////////////////////////////////////////////////////////////////////
|
| @@ -359,7 +363,7 @@
|
| if (kUnpremul_SkAlphaType == dstInfo.alphaType()) {
|
| flags = GrContext::kUnpremul_PixelOpsFlag;
|
| }
|
| - return fContext->readRenderTargetPixels(fRenderTarget, x, y, dstInfo.width(), dstInfo.height(),
|
| + return fContext->readRenderTargetPixels(fRenderTarget1, x, y, dstInfo.width(), dstInfo.height(),
|
| config, dstPixels, dstRowBytes, flags);
|
| }
|
|
|
| @@ -374,7 +378,7 @@
|
| if (kUnpremul_SkAlphaType == info.alphaType()) {
|
| flags = GrContext::kUnpremul_PixelOpsFlag;
|
| }
|
| - fRenderTarget->writePixels(x, y, info.width(), info.height(), config, pixels, rowBytes, flags);
|
| + fRenderTarget1->writePixels(x, y, info.width(), info.height(), config, pixels, rowBytes, flags);
|
|
|
| // need to bump our genID for compatibility with clients that "know" we have a bitmap
|
| this->onAccessBitmap().notifyPixelsChanged();
|
| @@ -404,7 +408,7 @@
|
| void SkGpuDevice::prepareDraw(const SkDraw& draw, bool forceIdentity) {
|
| SkASSERT(NULL != fClipData.fClipStack);
|
|
|
| - fContext->setRenderTarget(fRenderTarget);
|
| + fContext->setRenderTarget(fRenderTarget1);
|
|
|
| SkASSERT(draw.fClipStack && draw.fClipStack == fClipData.fClipStack);
|
|
|
| @@ -422,7 +426,7 @@
|
|
|
| GrRenderTarget* SkGpuDevice::accessRenderTarget() {
|
| DO_DEFERRED_CLEAR();
|
| - return fRenderTarget;
|
| + return fRenderTarget1;
|
| }
|
|
|
| ///////////////////////////////////////////////////////////////////////////////
|
| @@ -554,17 +558,17 @@
|
| ///////////////////////////////////////////////////////////////////////////////
|
|
|
| SkBitmap::Config SkGpuDevice::config() const {
|
| - if (NULL == fRenderTarget) {
|
| + if (NULL == fRenderTarget1) {
|
| return SkBitmap::kNo_Config;
|
| }
|
|
|
| bool isOpaque;
|
| - return grConfig2skConfig(fRenderTarget->config(), &isOpaque);
|
| + return grConfig2skConfig(fRenderTarget1->config(), &isOpaque);
|
| }
|
|
|
| void SkGpuDevice::clear(SkColor color) {
|
| SkIRect rect = SkIRect::MakeWH(this->width(), this->height());
|
| - fContext->clear(&rect, SkColor2GrColor(color), true, fRenderTarget);
|
| + fContext->clear(&rect, SkColor2GrColor(color), true, fRenderTarget1);
|
| fNeedClear = false;
|
| }
|
|
|
| @@ -918,6 +922,8 @@
|
| return;
|
| }
|
|
|
| +// grPaint.setAntiAlias(false);
|
| +
|
| // If we have a prematrix, apply it to the path, optimizing for the case
|
| // where the original path can in fact be modified in place (even though
|
| // its parameter type is const).
|
| @@ -1905,18 +1911,18 @@
|
|
|
| void SkGpuDevice::flush() {
|
| DO_DEFERRED_CLEAR();
|
| - fContext->resolveRenderTarget(fRenderTarget);
|
| + fContext->resolveRenderTarget(fRenderTarget1);
|
| }
|
|
|
| ///////////////////////////////////////////////////////////////////////////////
|
|
|
| SkBaseDevice* SkGpuDevice::onCreateDevice(const SkImageInfo& info, Usage usage) {
|
| GrTextureDesc desc;
|
| - desc.fConfig = fRenderTarget->config();
|
| + desc.fConfig = fRenderTarget1->config();
|
| desc.fFlags = kRenderTarget_GrTextureFlagBit;
|
| desc.fWidth = info.width();
|
| desc.fHeight = info.height();
|
| - desc.fSampleCnt = fRenderTarget->numSamples();
|
| + desc.fSampleCnt = fRenderTarget1->numSamples();
|
|
|
| SkAutoTUnref<GrTexture> texture;
|
| // Skia's convention is to only clear a device if it is non-opaque.
|
| @@ -1943,7 +1949,7 @@
|
| }
|
|
|
| SkSurface* SkGpuDevice::newSurface(const SkImageInfo& info) {
|
| - return SkSurface::NewRenderTarget(fContext, info, fRenderTarget->numSamples());
|
| + return SkSurface::NewRenderTarget(fContext, info, fRenderTarget1->numSamples());
|
| }
|
|
|
| // In the future this may not be a static method if we need to incorporate the
|
| @@ -1955,6 +1961,7 @@
|
| }
|
|
|
| void SkGpuDevice::EXPERIMENTAL_optimize(SkPicture* picture) {
|
| +
|
| SkPicture::AccelData::Key key = ComputeAccelDataKey();
|
|
|
| GPUAccelData* data = SkNEW_ARGS(GPUAccelData, (key));
|
| @@ -1964,8 +1971,34 @@
|
| GatherGPUInfo(picture, data);
|
| }
|
|
|
| -bool SkGpuDevice::EXPERIMENTAL_drawPicture(SkPicture* picture) {
|
| +void SkGpuDevice::EXPERIMENTAL_purge() {
|
|
|
| +}
|
| +
|
| +static void wrap_texture(GrTexture* texture, int width, int height, SkBitmap* result) {
|
| + SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
|
| + result->setConfig(info);
|
| + result->setPixelRef(SkNEW_ARGS(SkGrPixelRef, (info, texture)))->unref();
|
| +}
|
| +
|
| +#ifndef USE_SCRATCH
|
| +
|
| +static void generate_layer_cache_id(const SkPicture& picture, int layerID, GrCacheID* id) {
|
| + uint32_t genID = picture.uniqueID();
|
| +
|
| + GrCacheID::Key key;
|
| + memcpy(key.fData8 + 0, &genID, 4);
|
| + memcpy(key.fData8 + 4, &layerID, 4);
|
| + static const size_t kKeyDataSize = 8;
|
| + memset(key.fData8 + kKeyDataSize, 0, sizeof(key) - kKeyDataSize);
|
| + GR_STATIC_ASSERT(sizeof(key) >= kKeyDataSize);
|
| + static const GrCacheID::Domain gLayerDomain = GrCacheID::GenerateDomain();
|
| + id->reset(gLayerDomain, key);
|
| +}
|
| +#endif
|
| +
|
| +bool SkGpuDevice::EXPERIMENTAL_drawPicture(SkCanvas* canvas1, SkPicture* picture) {
|
| +
|
| SkPicture::AccelData::Key key = ComputeAccelDataKey();
|
|
|
| const SkPicture::AccelData* data = picture->EXPERIMENTAL_getAccelData(key);
|
| @@ -2020,27 +2053,119 @@
|
| SkDebugf("rect: %d %d %d %d\n", clip.fLeft, clip.fTop, clip.fRight, clip.fBottom);
|
| #endif
|
|
|
| - for (int i = 0; i < ops.numOps(); ++i) {
|
| - for (int j = 0; j < gpuData->numSaveLayers(); ++j) {
|
| - const GPUAccelData::SaveLayerInfo& info = gpuData->saveLayerInfo(j);
|
| + if (ops.valid()) {
|
| + for (int i = 0; i < ops.numOps(); ++i) {
|
| + for (int j = 0; j < gpuData->numSaveLayers(); ++j) {
|
| + const GPUAccelData::SaveLayerInfo& info = gpuData->saveLayerInfo(j);
|
|
|
| - if (ops.offset(i) > info.fSaveLayerOpID && ops.offset(i) < info.fRestoreOpID) {
|
| - pullForward[j] = true;
|
| + if (ops.offset(i) > info.fSaveLayerOpID && ops.offset(i) < info.fRestoreOpID) {
|
| + pullForward[j] = true;
|
| + }
|
| }
|
| }
|
| + } else {
|
| + for (int j = 0; j < gpuData->numSaveLayers(); ++j) {
|
| + pullForward[j] = true;
|
| + }
|
| }
|
|
|
| + SkPicturePlayback::Bar bar;
|
| +
|
| #ifdef SK_PRINT_PULL_FORWARD_INFO
|
| SkDebugf("Need SaveLayers: ");
|
| +#endif
|
| +
|
| for (int i = 0; i < gpuData->numSaveLayers(); ++i) {
|
| if (pullForward[i]) {
|
| - const GrAtlasedLayer* layer = fContext->getLayerCache()->findLayerOrCreate(picture, i);
|
| + GrCachedLayer* layer = fContext->getLayerCache()->findLayerOrCreate(picture, i);
|
|
|
| +#ifdef SK_PRINT_PULL_FORWARD_INFO
|
| SkDebugf("%d (%d), ", i, layer->layerID());
|
| +#endif
|
| +
|
| + const GPUAccelData::SaveLayerInfo& info = gpuData->saveLayerInfo(i);
|
| +
|
| + if (NULL != picture->fPlayback) {
|
| + SkPicturePlayback::Foo* temp = bar.push();
|
| +
|
| + temp->fStart = info.fSaveLayerOpID;
|
| + temp->fStop = info.fRestoreOpID;
|
| + temp->fPos = info.fOrigin;
|
| +
|
| + 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 bNeedsRendering = true;
|
| +
|
| +#if USE_SCRATCH
|
| + // This path just uses scratch textures and doesn't cache the texture.
|
| + // This can yield a lot of re-rendering
|
| + if (NULL == layer->getTexture()) {
|
| + layer->setTexture(fContext->lockAndRefScratchTexture(desc, GrContext::kApprox_ScratchTexMatch));
|
| + if (NULL == layer->getTexture()) {
|
| + continue;
|
| + }
|
| + } else {
|
| + bNeedsRendering = false;
|
| + }
|
| +#else
|
| + // This path caches the rendering result
|
| + GrCacheID cacheID;
|
| + generate_layer_cache_id(*picture, i, &cacheID);
|
| +
|
| + layer->setTexture(fContext->findAndRefTexture(desc, cacheID, NULL));
|
| +
|
| + if (NULL == layer->getTexture()) {
|
| + layer->setTexture(fContext->createTexture(NULL, desc, cacheID, NULL, 0));
|
| + } else {
|
| + bNeedsRendering = false;
|
| + }
|
| +#endif
|
| +
|
| + temp->fBM = SkNEW(SkBitmap);
|
| + wrap_texture(layer->getTexture(), desc.fWidth, desc.fHeight, temp->fBM);
|
| +
|
| + temp->fPaint = info.fPaint;
|
| +
|
| +
|
| + if (bNeedsRendering) {
|
| + SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTargetDirect(layer->getTexture()->asRenderTarget()));
|
| +
|
| + SkCanvas* canvas = surface->getCanvas();
|
| +
|
| + canvas->translate(SkIntToScalar(-info.fOrigin.fX), SkIntToScalar(-info.fOrigin.fY));
|
| + canvas->clear(SK_ColorTRANSPARENT);
|
| +
|
| + picture->fPlayback->draw(*canvas, info.fSaveLayerOpID, info.fRestoreOpID, NULL, NULL);
|
| + canvas->flush();
|
| + }
|
| + }
|
| }
|
| }
|
| +#ifdef SK_PRINT_PULL_FORWARD_INFO
|
| SkDebugf("\n");
|
| #endif
|
|
|
| - return false;
|
| + // Playback using new layers
|
| + picture->fPlayback->draw(*canvas1, -1, -1, NULL, &bar);
|
| +
|
| + // playback normally
|
| +// picture->fPlayback->draw(*canvas1, -1, -1, NULL, NULL);
|
| +
|
| + bar.freeAll();
|
| +
|
| + for (int i = 0; i < gpuData->numSaveLayers(); ++i) {
|
| +// GrCachedLayer* layer = fContext->getLayerCache()->findLayerOrCreate(picture, i);
|
| +
|
| +#if USE_SCRATCH
|
| +// fContext->unlockScratchTexture(layer->getTexture());
|
| +#endif
|
| +// layer->setTexture(NULL);
|
| + }
|
| +
|
| + return true;
|
| }
|
|
|