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; |
} |