Chromium Code Reviews| Index: src/gpu/GrDrawContext.cpp |
| diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrDrawContext.cpp |
| old mode 100755 |
| new mode 100644 |
| similarity index 50% |
| copy from src/gpu/GrContext.cpp |
| copy to src/gpu/GrDrawContext.cpp |
| index 342fb2175e9f4055d33536553486b4c4f33297d8..6a1dafe41ef2f2d1f614e6e9312f777d95bc089b |
| --- a/src/gpu/GrContext.cpp |
| +++ b/src/gpu/GrDrawContext.cpp |
| @@ -1,304 +1,97 @@ |
| /* |
| - * Copyright 2011 Google Inc. |
| + * Copyright 2015 Google Inc. |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| -#include "GrContext.h" |
| - |
| #include "GrAARectRenderer.h" |
| -#include "GrAtlasTextContext.h" |
| -#include "GrBatch.h" |
| -#include "GrBatchFontCache.h" |
| -#include "GrBatchTarget.h" |
| #include "GrBatchTest.h" |
| #include "GrDefaultGeoProcFactory.h" |
| -#include "GrGpuResource.h" |
| -#include "GrGpuResourcePriv.h" |
| -#include "GrDrawTargetCaps.h" |
| -#include "GrGpu.h" |
| -#include "GrImmediateDrawTarget.h" |
| -#include "GrIndexBuffer.h" |
| -#include "GrInOrderDrawBuffer.h" |
| -#include "GrLayerCache.h" |
| +#include "GrDrawContext.h" |
| #include "GrOvalRenderer.h" |
| #include "GrPathRenderer.h" |
| -#include "GrPathUtils.h" |
| -#include "GrRenderTargetPriv.h" |
| -#include "GrResourceCache.h" |
| -#include "GrResourceProvider.h" |
| -#include "GrSoftwarePathRenderer.h" |
| -#include "GrStencilAndCoverTextContext.h" |
| -#include "GrStrokeInfo.h" |
| -#include "GrSurfacePriv.h" |
| -#include "GrTextBlobCache.h" |
| -#include "GrTexturePriv.h" |
| -#include "GrTraceMarker.h" |
| #include "GrTracing.h" |
| -#include "GrVertices.h" |
| -#include "SkDashPathPriv.h" |
| -#include "SkConfig8888.h" |
| -#include "SkGr.h" |
| -#include "SkRRect.h" |
| -#include "SkStrokeRec.h" |
| -#include "SkTLazy.h" |
| -#include "SkTLS.h" |
| -#include "SkTraceEvent.h" |
| - |
| -#include "effects/GrConfigConversionEffect.h" |
| -#include "effects/GrDashingEffect.h" |
| -#include "effects/GrSingleTextureEffect.h" |
| - |
| -#define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == this) |
| -#define RETURN_IF_ABANDONED if (!fDrawBuffer) { return; } |
| -#define RETURN_FALSE_IF_ABANDONED if (!fDrawBuffer) { return false; } |
| -#define RETURN_NULL_IF_ABANDONED if (!fDrawBuffer) { return NULL; } |
| - |
| -class GrContext::AutoCheckFlush { |
| + |
| +#define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == fContext) |
| +#define RETURN_IF_ABANDONED if (!fDrawTarget) { return; } |
| +#define RETURN_FALSE_IF_ABANDONED if (!fDrawTarget) { return false; } |
| +#define RETURN_NULL_IF_ABANDONED if (!fDrawTarget) { return NULL; } |
| + |
| +class AutoCheckFlush { |
| public: |
| AutoCheckFlush(GrContext* context) : fContext(context) { SkASSERT(context); } |
| - |
| - ~AutoCheckFlush() { |
| - if (fContext->fFlushToReduceCacheSize) { |
| - fContext->flush(); |
| - } |
| - } |
| + ~AutoCheckFlush() { fContext->flushIfNecessary(); } |
|
bsalomon
2015/05/22 20:33:58
Is it possible for the flushing to be moved to the
robertphillips
2015/05/26 16:12:58
I think this check could go away when we're in a w
|
| private: |
| GrContext* fContext; |
| }; |
| -GrContext* GrContext::Create(GrBackend backend, GrBackendContext backendContext, |
| - const Options* opts) { |
| - GrContext* context; |
| - if (NULL == opts) { |
| - context = SkNEW_ARGS(GrContext, (Options())); |
| - } else { |
| - context = SkNEW_ARGS(GrContext, (*opts)); |
| - } |
| - |
| - if (context->init(backend, backendContext)) { |
| - return context; |
| - } else { |
| - context->unref(); |
| - return NULL; |
| - } |
| -} |
| - |
| -static int32_t gNextID = 1; |
| -static int32_t next_id() { |
| - int32_t id; |
| - do { |
| - id = sk_atomic_inc(&gNextID); |
| - } while (id == SK_InvalidGenID); |
| - return id; |
| -} |
| - |
| -GrContext::GrContext(const Options& opts) : fOptions(opts), fUniqueID(next_id()) { |
| - fGpu = NULL; |
| - fResourceCache = NULL; |
| - fResourceProvider = NULL; |
| - fPathRendererChain = NULL; |
| - fSoftwarePathRenderer = NULL; |
| - fBatchFontCache = NULL; |
| - fDrawBuffer = NULL; |
| - fFlushToReduceCacheSize = false; |
| - fAARectRenderer = NULL; |
| - fOvalRenderer = NULL; |
| - fMaxTextureSizeOverride = 1 << 20; |
| -} |
| - |
| -bool GrContext::init(GrBackend backend, GrBackendContext backendContext) { |
| - SkASSERT(NULL == fGpu); |
| - |
| - fGpu = GrGpu::Create(backend, backendContext, this); |
| - if (NULL == fGpu) { |
| - return false; |
| - } |
| - this->initCommon(); |
| - return true; |
| +GrDrawContext::GrDrawContext(GrContext* context, GrDrawTarget* drawTarget) |
| + : fContext(context) |
| + , fDrawTarget(SkRef(drawTarget)) { |
| } |
| -void GrContext::initCommon() { |
| - fResourceCache = SkNEW(GrResourceCache); |
| - fResourceCache->setOverBudgetCallback(OverBudgetCB, this); |
| - fResourceProvider = SkNEW_ARGS(GrResourceProvider, (fGpu, fResourceCache)); |
| - |
| - fLayerCache.reset(SkNEW_ARGS(GrLayerCache, (this))); |
| - |
| - fAARectRenderer = SkNEW(GrAARectRenderer); |
| - fOvalRenderer = SkNEW(GrOvalRenderer); |
| - |
| - fDidTestPMConversions = false; |
| - |
| -#ifdef IMMEDIATE_MODE |
| - fDrawBuffer = SkNEW_ARGS(GrImmediateDrawTarget, (this)); |
| -#else |
| - fDrawBuffer = SkNEW_ARGS(GrInOrderDrawBuffer, (this)); |
| -#endif |
| - |
| - // GrBatchFontCache will eventually replace GrFontCache |
| - fBatchFontCache = SkNEW_ARGS(GrBatchFontCache, (this)); |
| - |
| - fTextBlobCache.reset(SkNEW_ARGS(GrTextBlobCache, (TextBlobCacheOverBudgetCB, this))); |
| -} |
| - |
| -GrContext::~GrContext() { |
| - if (NULL == fGpu) { |
| +void GrDrawContext::copySurface(GrRenderTarget* dst, GrSurface* src, |
| + const SkIRect& srcRect, const SkIPoint& dstPoint) { |
| + if (!this->prepareToDraw(dst)) { |
| return; |
| } |
| - this->flush(); |
| - |
| - for (int i = 0; i < fCleanUpData.count(); ++i) { |
| - (*fCleanUpData[i].fFunc)(this, fCleanUpData[i].fInfo); |
| - } |
| - |
| - SkDELETE(fResourceProvider); |
| - SkDELETE(fResourceCache); |
| - SkDELETE(fBatchFontCache); |
| - SkDELETE(fDrawBuffer); |
| - |
| - fAARectRenderer->unref(); |
| - fOvalRenderer->unref(); |
| - |
| - fGpu->unref(); |
| - SkSafeUnref(fPathRendererChain); |
| - SkSafeUnref(fSoftwarePathRenderer); |
| + fDrawTarget->copySurface(dst, src, srcRect, dstPoint); |
| } |
| -void GrContext::abandonContext() { |
| - fResourceProvider->abandon(); |
| - // abandon first to so destructors |
| - // don't try to free the resources in the API. |
| - fResourceCache->abandonAll(); |
| - |
| - fGpu->contextAbandoned(); |
| - |
| - // a path renderer may be holding onto resources that |
| - // are now unusable |
| - SkSafeSetNull(fPathRendererChain); |
| - SkSafeSetNull(fSoftwarePathRenderer); |
| - |
| - SkDELETE(fDrawBuffer); |
| - fDrawBuffer = NULL; |
| - |
| - fBatchFontCache->freeAll(); |
| - fLayerCache->freeAll(); |
| - fTextBlobCache->freeAll(); |
| +void GrDrawContext::drawText(GrPipelineBuilder* pipelineBuilder, GrBatch* batch) { |
| + fDrawTarget->drawBatch(pipelineBuilder, batch); |
| } |
| -void GrContext::resetContext(uint32_t state) { |
| - fGpu->markContextDirty(state); |
| +void GrDrawContext::drawPaths(GrPipelineBuilder* pipelineBuilder, |
| + const GrPathProcessor* pathProc, |
| + const GrPathRange* pathRange, |
| + const void* indices, |
| + GrDrawTarget::PathIndexType indexType, |
| + const float transformValues[], |
| + GrDrawTarget::PathTransformType transformType, |
| + int count, |
| + GrPathRendering::FillType fill) { |
| + fDrawTarget->drawPaths(pipelineBuilder, pathProc, pathRange, |
| + indices, indexType, |
| + transformValues, |
| + transformType, |
| + count, fill); |
| } |
| -void GrContext::freeGpuResources() { |
| - this->flush(); |
| - |
| - if (fDrawBuffer) { |
| - fDrawBuffer->purgeResources(); |
| - } |
| - |
| - fBatchFontCache->freeAll(); |
| - fLayerCache->freeAll(); |
| - // a path renderer may be holding onto resources |
| - SkSafeSetNull(fPathRendererChain); |
| - SkSafeSetNull(fSoftwarePathRenderer); |
| - |
| - fResourceCache->purgeAllUnlocked(); |
| -} |
| - |
| -void GrContext::getResourceCacheUsage(int* resourceCount, size_t* resourceBytes) const { |
| - if (resourceCount) { |
| - *resourceCount = fResourceCache->getBudgetedResourceCount(); |
| - } |
| - if (resourceBytes) { |
| - *resourceBytes = fResourceCache->getBudgetedResourceBytes(); |
| +void GrDrawContext::discard(GrRenderTarget* renderTarget) { |
| + RETURN_IF_ABANDONED |
| + SkASSERT(renderTarget); |
| + AutoCheckFlush acf(fContext); |
| + if (!this->prepareToDraw(renderTarget)) { |
| + return; |
| } |
| + fDrawTarget->discard(renderTarget); |
| } |
| -GrTextContext* GrContext::createTextContext(GrRenderTarget* renderTarget, |
| - SkGpuDevice* gpuDevice, |
| - const SkDeviceProperties& |
| - leakyProperties, |
| - bool enableDistanceFieldFonts) { |
| - if (fGpu->caps()->shaderCaps()->pathRenderingSupport() && renderTarget->isMultisampled()) { |
| - GrStencilAttachment* sb = renderTarget->renderTargetPriv().attachStencilAttachment(); |
| - if (sb) { |
| - return GrStencilAndCoverTextContext::Create(this, gpuDevice, leakyProperties); |
| - } |
| - } |
| - |
| - return GrAtlasTextContext::Create(this, gpuDevice, leakyProperties, enableDistanceFieldFonts); |
| -} |
| - |
| -//////////////////////////////////////////////////////////////////////////////// |
| - |
| -bool GrContext::isConfigTexturable(GrPixelConfig config) const { |
| - return fGpu->caps()->isConfigTexturable(config); |
| -} |
| - |
| -bool GrContext::npotTextureTileSupport() const { |
| - return fGpu->caps()->npotTextureTileSupport(); |
| -} |
| - |
| -void GrContext::OverBudgetCB(void* data) { |
| - SkASSERT(data); |
| - |
| - GrContext* context = reinterpret_cast<GrContext*>(data); |
| - |
| - // Flush the InOrderDrawBuffer to possibly free up some textures |
| - context->fFlushToReduceCacheSize = true; |
| -} |
| - |
| -void GrContext::TextBlobCacheOverBudgetCB(void* data) { |
| - SkASSERT(data); |
| - |
| - // Unlike the GrResourceCache, TextBlobs are drawn at the SkGpuDevice level, therefore they |
| - // cannot use fFlushTorReduceCacheSize because it uses AutoCheckFlush. The solution is to move |
| - // drawText calls to below the GrContext level, but this is not trivial because they call |
| - // drawPath on SkGpuDevice |
| - GrContext* context = reinterpret_cast<GrContext*>(data); |
| - context->flush(); |
| -} |
| - |
| -int GrContext::getMaxTextureSize() const { |
| - return SkTMin(fGpu->caps()->maxTextureSize(), fMaxTextureSizeOverride); |
| -} |
| - |
| -int GrContext::getMaxRenderTargetSize() const { |
| - return fGpu->caps()->maxRenderTargetSize(); |
| -} |
| - |
| -int GrContext::getMaxSampleCount() const { |
| - return fGpu->caps()->maxSampleCount(); |
| -} |
| - |
| -/////////////////////////////////////////////////////////////////////////////// |
| - |
| -void GrContext::clear(const SkIRect* rect, |
| - const GrColor color, |
| - bool canIgnoreRect, |
| - GrRenderTarget* renderTarget) { |
| +void GrDrawContext::clear(GrRenderTarget* renderTarget, |
| + const SkIRect* rect, |
| + const GrColor color, |
| + bool canIgnoreRect) { |
| RETURN_IF_ABANDONED |
| - ASSERT_OWNED_RESOURCE(renderTarget); |
| SkASSERT(renderTarget); |
| - AutoCheckFlush acf(this); |
| - GR_CREATE_TRACE_MARKER_CONTEXT("GrContext::clear", this); |
| - GrDrawTarget* target = this->prepareToDraw(); |
| - if (NULL == target) { |
| + AutoCheckFlush acf(fContext); |
| + GR_CREATE_TRACE_MARKER_CONTEXT("GrDrawContext::clear", fContext); |
| + if (!this->prepareToDraw(renderTarget)) { |
| return; |
| } |
| - target->clear(rect, color, canIgnoreRect, renderTarget); |
| + fDrawTarget->clear(rect, color, canIgnoreRect, renderTarget); |
| } |
| -void GrContext::drawPaint(GrRenderTarget* rt, |
| - const GrClip& clip, |
| - const GrPaint& origPaint, |
| - const SkMatrix& viewMatrix) { |
| + |
| +void GrDrawContext::drawPaint(GrRenderTarget* rt, |
| + const GrClip& clip, |
| + const GrPaint& origPaint, |
| + const SkMatrix& viewMatrix) { |
| RETURN_IF_ABANDONED |
| // set rect to be big enough to fill the space, but not super-huge, so we |
| // don't overflow fixed-point implementations |
| @@ -333,25 +126,22 @@ void GrContext::drawPaint(GrRenderTarget* rt, |
| return; |
| } |
| - AutoCheckFlush acf(this); |
| + AutoCheckFlush acf(fContext); |
| GrPipelineBuilder pipelineBuilder; |
| - GrDrawTarget* target = this->prepareToDraw(&pipelineBuilder, rt, clip, paint, &acf); |
| - if (NULL == target) { |
| + if (!this->prepareToDraw(&pipelineBuilder, rt, clip, paint)) { |
| return; |
| } |
| - GR_CREATE_TRACE_MARKER("GrContext::drawPaintWithPerspective", target); |
| - target->drawRect(&pipelineBuilder, |
| - paint->getColor(), |
| - SkMatrix::I(), |
| - r, |
| - NULL, |
| - &localMatrix); |
| + GR_CREATE_TRACE_MARKER_CONTEXT("GrDrawContext::drawPaint", fContext); |
|
bsalomon
2015/05/22 20:33:58
Let's delete these
robertphillips
2015/05/26 16:12:58
Done.
|
| + fDrawTarget->drawBWRect(&pipelineBuilder, |
| + paint->getColor(), |
| + SkMatrix::I(), |
| + r, |
| + NULL, |
| + &localMatrix); |
| } |
| } |
| -//////////////////////////////////////////////////////////////////////////////// |
| - |
| static inline bool is_irect(const SkRect& r) { |
| return SkScalarIsInt(r.fLeft) && SkScalarIsInt(r.fTop) && |
| SkScalarIsInt(r.fRight) && SkScalarIsInt(r.fBottom); |
| @@ -571,12 +361,12 @@ private: |
| SkSTArray<1, Geometry, true> fGeoData; |
| }; |
| -void GrContext::drawRect(GrRenderTarget* rt, |
| - const GrClip& clip, |
| - const GrPaint& paint, |
| - const SkMatrix& viewMatrix, |
| - const SkRect& rect, |
| - const GrStrokeInfo* strokeInfo) { |
| +void GrDrawContext::drawRect(GrRenderTarget* rt, |
| + const GrClip& clip, |
| + const GrPaint& paint, |
| + const SkMatrix& viewMatrix, |
| + const SkRect& rect, |
| + const GrStrokeInfo* strokeInfo) { |
| RETURN_IF_ABANDONED |
| if (strokeInfo && strokeInfo->isDashed()) { |
| SkPath path; |
| @@ -586,14 +376,13 @@ void GrContext::drawRect(GrRenderTarget* rt, |
| return; |
| } |
| - AutoCheckFlush acf(this); |
| + AutoCheckFlush acf(fContext); |
| GrPipelineBuilder pipelineBuilder; |
| - GrDrawTarget* target = this->prepareToDraw(&pipelineBuilder, rt, clip, &paint, &acf); |
| - if (NULL == target) { |
| + if (!this->prepareToDraw(&pipelineBuilder, rt, clip, &paint)) { |
| return; |
| } |
| - GR_CREATE_TRACE_MARKER("GrContext::drawRect", target); |
| + GR_CREATE_TRACE_MARKER_CONTEXT("GrDrawContext::drawRect", fContext); |
| SkScalar width = NULL == strokeInfo ? -1 : strokeInfo->getWidth(); |
| // Check if this is a full RT draw and can be replaced with a clear. We don't bother checking |
| @@ -623,7 +412,7 @@ void GrContext::drawRect(GrRenderTarget* rt, |
| // Will it blend? |
| GrColor clearColor; |
| if (paint.isOpaqueAndConstantColor(&clearColor)) { |
| - target->clear(NULL, clearColor, true, rt); |
| + fDrawTarget->clear(NULL, clearColor, true, rt); |
| return; |
| } |
| } |
| @@ -633,26 +422,26 @@ void GrContext::drawRect(GrRenderTarget* rt, |
| GrColor color = paint.getColor(); |
| SkRect devBoundRect; |
| bool needAA = paint.isAntiAlias() && !pipelineBuilder.getRenderTarget()->isMultisampled(); |
| - bool doAA = needAA && apply_aa_to_rect(target, &pipelineBuilder, &devBoundRect, rect, width, |
| - viewMatrix, color); |
| + bool doAA = needAA && apply_aa_to_rect(fDrawTarget, &pipelineBuilder, &devBoundRect, rect, |
| + width, viewMatrix, color); |
| if (doAA) { |
| if (width >= 0) { |
| - fAARectRenderer->strokeAARect(target, |
| - &pipelineBuilder, |
| - color, |
| - viewMatrix, |
| - rect, |
| - devBoundRect, |
| - *strokeInfo); |
| + GrAARectRenderer::StrokeAARect(fDrawTarget, |
| + &pipelineBuilder, |
| + color, |
| + viewMatrix, |
| + rect, |
| + devBoundRect, |
| + *strokeInfo); |
| } else { |
| // filled AA rect |
| - fAARectRenderer->fillAARect(target, |
| - &pipelineBuilder, |
| - color, |
| - viewMatrix, |
| - rect, |
| - devBoundRect); |
| + GrAARectRenderer::FillAARect(fDrawTarget, |
| + &pipelineBuilder, |
| + color, |
| + viewMatrix, |
| + rect, |
| + devBoundRect); |
| } |
| return; |
| } |
| @@ -673,36 +462,35 @@ void GrContext::drawRect(GrRenderTarget* rt, |
| // is enabled because it can cause ugly artifacts. |
| pipelineBuilder.setState(GrPipelineBuilder::kSnapVerticesToPixelCenters_Flag, |
| snapToPixelCenters); |
| - target->drawBatch(&pipelineBuilder, batch); |
| + fDrawTarget->drawBatch(&pipelineBuilder, batch); |
| } else { |
| // filled BW rect |
| - target->drawSimpleRect(&pipelineBuilder, color, viewMatrix, rect); |
| + fDrawTarget->drawSimpleRect(&pipelineBuilder, color, viewMatrix, rect); |
| } |
| } |
| -void GrContext::drawNonAARectToRect(GrRenderTarget* rt, |
| - const GrClip& clip, |
| - const GrPaint& paint, |
| - const SkMatrix& viewMatrix, |
| - const SkRect& rectToDraw, |
| - const SkRect& localRect, |
| - const SkMatrix* localMatrix) { |
| +void GrDrawContext::drawNonAARectToRect(GrRenderTarget* rt, |
| + const GrClip& clip, |
| + const GrPaint& paint, |
| + const SkMatrix& viewMatrix, |
| + const SkRect& rectToDraw, |
| + const SkRect& localRect, |
| + const SkMatrix* localMatrix) { |
| RETURN_IF_ABANDONED |
| - AutoCheckFlush acf(this); |
| + AutoCheckFlush acf(fContext); |
| GrPipelineBuilder pipelineBuilder; |
| - GrDrawTarget* target = this->prepareToDraw(&pipelineBuilder, rt, clip, &paint, &acf); |
| - if (NULL == target) { |
| + if (!this->prepareToDraw(&pipelineBuilder, rt, clip, &paint)) { |
| return; |
| } |
| - GR_CREATE_TRACE_MARKER("GrContext::drawRectToRect", target); |
| + GR_CREATE_TRACE_MARKER_CONTEXT("GrDrawContext::drawRectToRect", fContext); |
| - target->drawRect(&pipelineBuilder, |
| - paint.getColor(), |
| - viewMatrix, |
| - rectToDraw, |
| - &localRect, |
| - localMatrix); |
| + fDrawTarget->drawBWRect(&pipelineBuilder, |
| + paint.getColor(), |
| + viewMatrix, |
| + rectToDraw, |
| + &localRect, |
| + localMatrix); |
| } |
| static const GrGeometryProcessor* set_vertex_attributes(bool hasLocalCoords, |
| @@ -976,27 +764,26 @@ private: |
| SkSTArray<1, Geometry, true> fGeoData; |
| }; |
| -void GrContext::drawVertices(GrRenderTarget* rt, |
| - const GrClip& clip, |
| - const GrPaint& paint, |
| - const SkMatrix& viewMatrix, |
| - GrPrimitiveType primitiveType, |
| - int vertexCount, |
| - const SkPoint positions[], |
| - const SkPoint texCoords[], |
| - const GrColor colors[], |
| - const uint16_t indices[], |
| - int indexCount) { |
| +void GrDrawContext::drawVertices(GrRenderTarget* rt, |
| + const GrClip& clip, |
| + const GrPaint& paint, |
| + const SkMatrix& viewMatrix, |
| + GrPrimitiveType primitiveType, |
| + int vertexCount, |
| + const SkPoint positions[], |
| + const SkPoint texCoords[], |
| + const GrColor colors[], |
| + const uint16_t indices[], |
| + int indexCount) { |
| RETURN_IF_ABANDONED |
| - AutoCheckFlush acf(this); |
| + AutoCheckFlush acf(fContext); |
| GrPipelineBuilder pipelineBuilder; |
| - GrDrawTarget* target = this->prepareToDraw(&pipelineBuilder, rt, clip, &paint, &acf); |
| - if (NULL == target) { |
| + if (!this->prepareToDraw(&pipelineBuilder, rt, clip, &paint)) { |
| return; |
| } |
| - GR_CREATE_TRACE_MARKER("GrContext::drawVertices", target); |
| + GR_CREATE_TRACE_MARKER_CONTEXT("GrDrawContext::drawVertices", fContext); |
| // TODO clients should give us bounds |
| SkRect bounds; |
| @@ -1020,17 +807,17 @@ void GrContext::drawVertices(GrRenderTarget* rt, |
| indexCount, colors, texCoords, |
| bounds)); |
| - target->drawBatch(&pipelineBuilder, batch); |
| + fDrawTarget->drawBatch(&pipelineBuilder, batch); |
| } |
| /////////////////////////////////////////////////////////////////////////////// |
| -void GrContext::drawRRect(GrRenderTarget*rt, |
| - const GrClip& clip, |
| - const GrPaint& paint, |
| - const SkMatrix& viewMatrix, |
| - const SkRRect& rrect, |
| - const GrStrokeInfo& strokeInfo) { |
| +void GrDrawContext::drawRRect(GrRenderTarget*rt, |
| + const GrClip& clip, |
| + const GrPaint& paint, |
| + const SkMatrix& viewMatrix, |
| + const SkRRect& rrect, |
| + const GrStrokeInfo& strokeInfo) { |
| RETURN_IF_ABANDONED |
| if (rrect.isEmpty()) { |
| return; |
| @@ -1044,77 +831,79 @@ void GrContext::drawRRect(GrRenderTarget*rt, |
| return; |
| } |
| - AutoCheckFlush acf(this); |
| + AutoCheckFlush acf(fContext); |
| GrPipelineBuilder pipelineBuilder; |
| - GrDrawTarget* target = this->prepareToDraw(&pipelineBuilder, rt, clip, &paint, &acf); |
| - if (NULL == target) { |
| + if (!this->prepareToDraw(&pipelineBuilder, rt, clip, &paint)) { |
| return; |
| } |
| - GR_CREATE_TRACE_MARKER("GrContext::drawRRect", target); |
| + GR_CREATE_TRACE_MARKER_CONTEXT("GrDrawContext::drawRRect", fContext); |
| GrColor color = paint.getColor(); |
| - if (!fOvalRenderer->drawRRect(target, |
| - &pipelineBuilder, |
| - color, |
| - viewMatrix, |
| - paint.isAntiAlias(), |
| - rrect, |
| - strokeInfo)) { |
| + if (!GrOvalRenderer::DrawRRect(fDrawTarget, |
| + &pipelineBuilder, |
| + color, |
| + viewMatrix, |
| + paint.isAntiAlias(), |
| + rrect, |
| + strokeInfo)) { |
| SkPath path; |
| path.setIsVolatile(true); |
| path.addRRect(rrect); |
| - this->internalDrawPath(target, &pipelineBuilder, viewMatrix, color, paint.isAntiAlias(), |
| - path, strokeInfo); |
| + this->internalDrawPath(fDrawTarget, &pipelineBuilder, viewMatrix, color, |
| + paint.isAntiAlias(), path, strokeInfo); |
| } |
| } |
| /////////////////////////////////////////////////////////////////////////////// |
| -void GrContext::drawDRRect(GrRenderTarget* rt, |
| - const GrClip& clip, |
| - const GrPaint& paint, |
| - const SkMatrix& viewMatrix, |
| - const SkRRect& outer, |
| - const SkRRect& inner) { |
| +void GrDrawContext::drawDRRect(GrRenderTarget* rt, |
| + const GrClip& clip, |
| + const GrPaint& paint, |
| + const SkMatrix& viewMatrix, |
| + const SkRRect& outer, |
| + const SkRRect& inner) { |
| RETURN_IF_ABANDONED |
| if (outer.isEmpty()) { |
| return; |
| } |
| - AutoCheckFlush acf(this); |
| + AutoCheckFlush acf(fContext); |
| GrPipelineBuilder pipelineBuilder; |
| - GrDrawTarget* target = this->prepareToDraw(&pipelineBuilder, rt, clip, &paint, &acf); |
| + if (!this->prepareToDraw(&pipelineBuilder, rt, clip, &paint)) { |
| + return; |
| + } |
| - GR_CREATE_TRACE_MARKER("GrContext::drawDRRect", target); |
| + GR_CREATE_TRACE_MARKER_CONTEXT("GrContext::drawDRRect", fContext); |
| GrColor color = paint.getColor(); |
| - if (!fOvalRenderer->drawDRRect(target, |
| - &pipelineBuilder, |
| - color, |
| - viewMatrix, |
| - paint.isAntiAlias(), |
| - outer, |
| - inner)) { |
| + if (!GrOvalRenderer::DrawDRRect(fDrawTarget, |
| + &pipelineBuilder, |
| + color, |
| + viewMatrix, |
| + paint.isAntiAlias(), |
| + outer, |
| + inner)) { |
| SkPath path; |
| path.setIsVolatile(true); |
| path.addRRect(inner); |
| path.addRRect(outer); |
| path.setFillType(SkPath::kEvenOdd_FillType); |
| + |
| GrStrokeInfo fillRec(SkStrokeRec::kFill_InitStyle); |
| - this->internalDrawPath(target, &pipelineBuilder, viewMatrix, color, paint.isAntiAlias(), |
| - path, fillRec); |
| + this->internalDrawPath(fDrawTarget, &pipelineBuilder, viewMatrix, color, |
| + paint.isAntiAlias(), path, fillRec); |
| } |
| } |
| /////////////////////////////////////////////////////////////////////////////// |
| -void GrContext::drawOval(GrRenderTarget* rt, |
| - const GrClip& clip, |
| - const GrPaint& paint, |
| - const SkMatrix& viewMatrix, |
| - const SkRect& oval, |
| - const GrStrokeInfo& strokeInfo) { |
| +void GrDrawContext::drawOval(GrRenderTarget* rt, |
| + const GrClip& clip, |
| + const GrPaint& paint, |
| + const SkMatrix& viewMatrix, |
| + const SkRect& oval, |
| + const GrStrokeInfo& strokeInfo) { |
| RETURN_IF_ABANDONED |
| if (oval.isEmpty()) { |
| return; |
| @@ -1128,28 +917,27 @@ void GrContext::drawOval(GrRenderTarget* rt, |
| return; |
| } |
| - AutoCheckFlush acf(this); |
| + AutoCheckFlush acf(fContext); |
| GrPipelineBuilder pipelineBuilder; |
| - GrDrawTarget* target = this->prepareToDraw(&pipelineBuilder, rt, clip, &paint, &acf); |
| - if (NULL == target) { |
| + if (!this->prepareToDraw(&pipelineBuilder, rt, clip, &paint)) { |
| return; |
| } |
| - GR_CREATE_TRACE_MARKER("GrContext::drawOval", target); |
| + GR_CREATE_TRACE_MARKER_CONTEXT("GrDrawContext::drawOval", fContext); |
| GrColor color = paint.getColor(); |
| - if (!fOvalRenderer->drawOval(target, |
| - &pipelineBuilder, |
| - color, |
| - viewMatrix, |
| - paint.isAntiAlias(), |
| - oval, |
| - strokeInfo)) { |
| + if (!GrOvalRenderer::DrawOval(fDrawTarget, |
| + &pipelineBuilder, |
| + color, |
| + viewMatrix, |
| + paint.isAntiAlias(), |
| + oval, |
| + strokeInfo)) { |
| SkPath path; |
| path.setIsVolatile(true); |
| path.addOval(oval); |
| - this->internalDrawPath(target, &pipelineBuilder, viewMatrix, color, paint.isAntiAlias(), |
| - path, strokeInfo); |
| + this->internalDrawPath(fDrawTarget, &pipelineBuilder, viewMatrix, color, |
| + paint.isAntiAlias(), path, strokeInfo); |
| } |
| } |
| @@ -1206,12 +994,12 @@ static bool is_nested_rects(GrDrawTarget* target, |
| return allEq || allGoE1; |
| } |
| -void GrContext::drawPath(GrRenderTarget* rt, |
| - const GrClip& clip, |
| - const GrPaint& paint, |
| - const SkMatrix& viewMatrix, |
| - const SkPath& path, |
| - const GrStrokeInfo& strokeInfo) { |
| +void GrDrawContext::drawPath(GrRenderTarget* rt, |
| + const GrClip& clip, |
| + const GrPaint& paint, |
| + const SkMatrix& viewMatrix, |
| + const SkPath& path, |
| + const GrStrokeInfo& strokeInfo) { |
| RETURN_IF_ABANDONED |
| if (path.isEmpty()) { |
| if (path.isInverseFillType()) { |
| @@ -1227,14 +1015,13 @@ void GrContext::drawPath(GrRenderTarget* rt, |
| // cache. This presents a potential hazard for buffered drawing. However, |
| // the writePixels that uploads to the scratch will perform a flush so we're |
| // OK. |
| - AutoCheckFlush acf(this); |
| + AutoCheckFlush acf(fContext); |
| GrPipelineBuilder pipelineBuilder; |
| - GrDrawTarget* target = this->prepareToDraw(&pipelineBuilder, rt, clip, &paint, &acf); |
| - if (NULL == target) { |
| + if (!this->prepareToDraw(&pipelineBuilder, rt, clip, &paint)) { |
| return; |
| } |
| - GR_CREATE_TRACE_MARKER1("GrContext::drawPath", target, "Is Convex", path.isConvex()); |
| + GR_CREATE_TRACE_MARKER_CONTEXT("GrDrawContext::drawPath", fContext); |
| if (!strokeInfo.isDashed()) { |
| bool useCoverageAA = paint.isAntiAlias() && |
| @@ -1244,10 +1031,10 @@ void GrContext::drawPath(GrRenderTarget* rt, |
| // Concave AA paths are expensive - try to avoid them for special cases |
| SkRect rects[2]; |
| - if (is_nested_rects(target, &pipelineBuilder, color, viewMatrix, path, strokeInfo, |
| + if (is_nested_rects(fDrawTarget, &pipelineBuilder, color, viewMatrix, path, strokeInfo, |
| rects)) { |
| - fAARectRenderer->fillAANestedRects(target, &pipelineBuilder, color, viewMatrix, |
| - rects); |
| + GrAARectRenderer::FillAANestedRects(fDrawTarget, &pipelineBuilder, color, |
| + viewMatrix, rects); |
| return; |
| } |
| } |
| @@ -1255,28 +1042,28 @@ void GrContext::drawPath(GrRenderTarget* rt, |
| bool isOval = path.isOval(&ovalRect); |
| if (isOval && !path.isInverseFillType()) { |
| - if (fOvalRenderer->drawOval(target, |
| - &pipelineBuilder, |
| - color, |
| - viewMatrix, |
| - paint.isAntiAlias(), |
| - ovalRect, |
| - strokeInfo)) { |
| + if (GrOvalRenderer::DrawOval(fDrawTarget, |
| + &pipelineBuilder, |
| + color, |
| + viewMatrix, |
| + paint.isAntiAlias(), |
| + ovalRect, |
| + strokeInfo)) { |
| return; |
| } |
| } |
| } |
| - this->internalDrawPath(target, &pipelineBuilder, viewMatrix, color, paint.isAntiAlias(), |
| + this->internalDrawPath(fDrawTarget, &pipelineBuilder, viewMatrix, color, paint.isAntiAlias(), |
| path, strokeInfo); |
| } |
| -void GrContext::internalDrawPath(GrDrawTarget* target, |
| - GrPipelineBuilder* pipelineBuilder, |
| - const SkMatrix& viewMatrix, |
| - GrColor color, |
| - bool useAA, |
| - const SkPath& path, |
| - const GrStrokeInfo& strokeInfo) { |
| +void GrDrawContext::internalDrawPath(GrDrawTarget* target, |
| + GrPipelineBuilder* pipelineBuilder, |
| + const SkMatrix& viewMatrix, |
| + GrColor color, |
| + bool useAA, |
| + const SkPath& path, |
| + const GrStrokeInfo& strokeInfo) { |
| RETURN_IF_ABANDONED |
| SkASSERT(!path.isEmpty()); |
| @@ -1300,8 +1087,8 @@ void GrContext::internalDrawPath(GrDrawTarget* target, |
| const GrStrokeInfo* strokeInfoPtr = &strokeInfo; |
| // Try a 1st time without stroking the path and without allowing the SW renderer |
| - GrPathRenderer* pr = this->getPathRenderer(target, pipelineBuilder, viewMatrix, *pathPtr, |
| - *strokeInfoPtr, false, type); |
| + GrPathRenderer* pr = fContext->getPathRenderer(target, pipelineBuilder, viewMatrix, *pathPtr, |
| + *strokeInfoPtr, false, type); |
| GrStrokeInfo dashlessStrokeInfo(strokeInfo, false); |
| if (NULL == pr && strokeInfo.isDashed()) { |
| @@ -1314,8 +1101,8 @@ void GrContext::internalDrawPath(GrDrawTarget* target, |
| return; |
| } |
| strokeInfoPtr = &dashlessStrokeInfo; |
| - pr = this->getPathRenderer(target, pipelineBuilder, viewMatrix, *pathPtr, *strokeInfoPtr, |
| - false, type); |
| + pr = fContext->getPathRenderer(target, pipelineBuilder, viewMatrix, *pathPtr, *strokeInfoPtr, |
| + false, type); |
| } |
| if (NULL == pr) { |
| @@ -1338,8 +1125,8 @@ void GrContext::internalDrawPath(GrDrawTarget* target, |
| } |
| // This time, allow SW renderer |
| - pr = this->getPathRenderer(target, pipelineBuilder, viewMatrix, *pathPtr, *strokeInfoPtr, |
| - true, type); |
| + pr = fContext->getPathRenderer(target, pipelineBuilder, viewMatrix, *pathPtr, *strokeInfoPtr, |
| + true, type); |
| } |
| if (NULL == pr) { |
| @@ -1352,523 +1139,24 @@ void GrContext::internalDrawPath(GrDrawTarget* target, |
| pr->drawPath(target, pipelineBuilder, color, viewMatrix, *pathPtr, *strokeInfoPtr, useCoverageAA); |
| } |
| -//////////////////////////////////////////////////////////////////////////////// |
| - |
| -void GrContext::flush(int flagsBitfield) { |
| - if (NULL == fDrawBuffer) { |
| - return; |
| - } |
| - |
| - if (kDiscard_FlushBit & flagsBitfield) { |
| - fDrawBuffer->reset(); |
| - } else { |
| - fDrawBuffer->flush(); |
| - } |
| - fResourceCache->notifyFlushOccurred(); |
| - fFlushToReduceCacheSize = false; |
| -} |
| - |
| -bool sw_convert_to_premul(GrPixelConfig srcConfig, int width, int height, size_t inRowBytes, |
| - const void* inPixels, size_t outRowBytes, void* outPixels) { |
| - SkSrcPixelInfo srcPI; |
| - if (!GrPixelConfig2ColorAndProfileType(srcConfig, &srcPI.fColorType, NULL)) { |
| - return false; |
| - } |
| - srcPI.fAlphaType = kUnpremul_SkAlphaType; |
| - srcPI.fPixels = inPixels; |
| - srcPI.fRowBytes = inRowBytes; |
| - |
| - SkDstPixelInfo dstPI; |
| - dstPI.fColorType = srcPI.fColorType; |
| - dstPI.fAlphaType = kPremul_SkAlphaType; |
| - dstPI.fPixels = outPixels; |
| - dstPI.fRowBytes = outRowBytes; |
| - |
| - return srcPI.convertPixelsTo(&dstPI, width, height); |
| -} |
| - |
| -bool GrContext::writeSurfacePixels(GrSurface* surface, |
| - int left, int top, int width, int height, |
| - GrPixelConfig srcConfig, const void* buffer, size_t rowBytes, |
| - uint32_t pixelOpsFlags) { |
| +bool GrDrawContext::prepareToDraw(GrPipelineBuilder* pipelineBuilder, |
| + GrRenderTarget* rt, |
| + const GrClip& clip, |
| + const GrPaint* paint) { |
| RETURN_FALSE_IF_ABANDONED |
| - { |
| - GrTexture* texture = NULL; |
| - if (!(kUnpremul_PixelOpsFlag & pixelOpsFlags) && (texture = surface->asTexture()) && |
| - fGpu->canWriteTexturePixels(texture, srcConfig)) { |
| - |
| - if (!(kDontFlush_PixelOpsFlag & pixelOpsFlags) && |
| - surface->surfacePriv().hasPendingIO()) { |
| - this->flush(); |
| - } |
| - return fGpu->writeTexturePixels(texture, left, top, width, height, |
| - srcConfig, buffer, rowBytes); |
| - // Don't need to check kFlushWrites_PixelOp here, we just did a direct write so the |
| - // upload is already flushed. |
| - } |
| - } |
| - |
| - // If we didn't do a direct texture write then we upload the pixels to a texture and draw. |
| - GrRenderTarget* renderTarget = surface->asRenderTarget(); |
| - if (NULL == renderTarget) { |
| - return false; |
| - } |
| - |
| - // We ignore the preferred config unless it is a R/B swap of the src config. In that case |
| - // we will upload the original src data to a scratch texture but we will spoof it as the swapped |
| - // config. This scratch will then have R and B swapped. We correct for this by swapping again |
| - // when drawing the scratch to the dst using a conversion effect. |
| - bool swapRAndB = false; |
| - GrPixelConfig writeConfig = srcConfig; |
| - if (GrPixelConfigSwapRAndB(srcConfig) == |
| - fGpu->preferredWritePixelsConfig(srcConfig, renderTarget->config())) { |
| - writeConfig = GrPixelConfigSwapRAndB(srcConfig); |
| - swapRAndB = true; |
| - } |
| - |
| - GrSurfaceDesc desc; |
| - desc.fWidth = width; |
| - desc.fHeight = height; |
| - desc.fConfig = writeConfig; |
| - SkAutoTUnref<GrTexture> texture(this->textureProvider()->refScratchTexture(desc, |
| - GrTextureProvider::kApprox_ScratchTexMatch)); |
| - if (!texture) { |
| - return false; |
| - } |
| - |
| - SkAutoTUnref<const GrFragmentProcessor> fp; |
| - SkMatrix textureMatrix; |
| - textureMatrix.setIDiv(texture->width(), texture->height()); |
| - |
| - // allocate a tmp buffer and sw convert the pixels to premul |
| - SkAutoSTMalloc<128 * 128, uint32_t> tmpPixels(0); |
| - |
| - if (kUnpremul_PixelOpsFlag & pixelOpsFlags) { |
| - if (!GrPixelConfigIs8888(srcConfig)) { |
| - return false; |
| - } |
| - fp.reset(this->createUPMToPMEffect(texture, swapRAndB, textureMatrix)); |
| - // handle the unpremul step on the CPU if we couldn't create an effect to do it. |
| - if (NULL == fp) { |
| - size_t tmpRowBytes = 4 * width; |
| - tmpPixels.reset(width * height); |
| - if (!sw_convert_to_premul(srcConfig, width, height, rowBytes, buffer, tmpRowBytes, |
| - tmpPixels.get())) { |
| - return false; |
| - } |
| - rowBytes = tmpRowBytes; |
| - buffer = tmpPixels.get(); |
| - } |
| - } |
| - if (NULL == fp) { |
| - fp.reset(GrConfigConversionEffect::Create(texture, |
| - swapRAndB, |
| - GrConfigConversionEffect::kNone_PMConversion, |
| - textureMatrix)); |
| - } |
| - |
| - // Even if the client told us not to flush, we still flush here. The client may have known that |
| - // writes to the original surface caused no data hazards, but they can't know that the scratch |
| - // we just got is safe. |
| - if (texture->surfacePriv().hasPendingIO()) { |
| - this->flush(); |
| - } |
| - if (!fGpu->writeTexturePixels(texture, 0, 0, width, height, |
| - writeConfig, buffer, rowBytes)) { |
| - return false; |
| - } |
| - |
| - SkMatrix matrix; |
| - matrix.setTranslate(SkIntToScalar(left), SkIntToScalar(top)); |
| - |
| - // This function can be called in the midst of drawing another object (e.g., when uploading a |
| - // SW-rasterized clip while issuing a draw). So we push the current geometry state before |
| - // drawing a rect to the render target. |
| - // The bracket ensures we pop the stack if we wind up flushing below. |
| - { |
| - GrDrawTarget* drawTarget = this->prepareToDraw(); |
| - if (!drawTarget) { |
| - return false; |
| - } |
| - |
| - GrPipelineBuilder pipelineBuilder; |
| - pipelineBuilder.addColorProcessor(fp); |
| - pipelineBuilder.setRenderTarget(renderTarget); |
| - drawTarget->drawSimpleRect(&pipelineBuilder, |
| - GrColor_WHITE, |
| - matrix, |
| - SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height))); |
| - } |
| - |
| - if (kFlushWrites_PixelOp & pixelOpsFlags) { |
| - this->flushSurfaceWrites(surface); |
| - } |
| + ASSERT_OWNED_RESOURCE(rt); |
| + SkASSERT(rt && paint); |
| + pipelineBuilder->setFromPaint(*paint, rt, clip); |
| return true; |
| } |
| -// toggles between RGBA and BGRA |
| -static SkColorType toggle_colortype32(SkColorType ct) { |
| - if (kRGBA_8888_SkColorType == ct) { |
| - return kBGRA_8888_SkColorType; |
| - } else { |
| - SkASSERT(kBGRA_8888_SkColorType == ct); |
| - return kRGBA_8888_SkColorType; |
| - } |
| -} |
| - |
| -bool GrContext::readRenderTargetPixels(GrRenderTarget* target, |
| - int left, int top, int width, int height, |
| - GrPixelConfig dstConfig, void* buffer, size_t rowBytes, |
| - uint32_t flags) { |
| +bool GrDrawContext::prepareToDraw(GrRenderTarget* rt) { |
| RETURN_FALSE_IF_ABANDONED |
| - ASSERT_OWNED_RESOURCE(target); |
| - SkASSERT(target); |
| - |
| - if (!(kDontFlush_PixelOpsFlag & flags) && target->surfacePriv().hasPendingWrite()) { |
| - this->flush(); |
| - } |
| - |
| - // Determine which conversions have to be applied: flipY, swapRAnd, and/or unpremul. |
| - |
| - // If fGpu->readPixels would incur a y-flip cost then we will read the pixels upside down. We'll |
| - // either do the flipY by drawing into a scratch with a matrix or on the cpu after the read. |
| - bool flipY = fGpu->readPixelsWillPayForYFlip(target, left, top, |
| - width, height, dstConfig, |
| - rowBytes); |
| - // We ignore the preferred config if it is different than our config unless it is an R/B swap. |
| - // In that case we'll perform an R and B swap while drawing to a scratch texture of the swapped |
| - // config. Then we will call readPixels on the scratch with the swapped config. The swaps during |
| - // the draw cancels out the fact that we call readPixels with a config that is R/B swapped from |
| - // dstConfig. |
| - GrPixelConfig readConfig = dstConfig; |
| - bool swapRAndB = false; |
| - if (GrPixelConfigSwapRAndB(dstConfig) == |
| - fGpu->preferredReadPixelsConfig(dstConfig, target->config())) { |
| - readConfig = GrPixelConfigSwapRAndB(readConfig); |
| - swapRAndB = true; |
| - } |
| - |
| - bool unpremul = SkToBool(kUnpremul_PixelOpsFlag & flags); |
| - |
| - if (unpremul && !GrPixelConfigIs8888(dstConfig)) { |
| - // The unpremul flag is only allowed for these two configs. |
| - return false; |
| - } |
| - |
| - SkAutoTUnref<GrTexture> tempTexture; |
| - |
| - // If the src is a texture and we would have to do conversions after read pixels, we instead |
| - // do the conversions by drawing the src to a scratch texture. If we handle any of the |
| - // conversions in the draw we set the corresponding bool to false so that we don't reapply it |
| - // on the read back pixels. |
| - GrTexture* src = target->asTexture(); |
| - if (src && (swapRAndB || unpremul || flipY)) { |
| - // Make the scratch a render so we can read its pixels. |
| - GrSurfaceDesc desc; |
| - desc.fFlags = kRenderTarget_GrSurfaceFlag; |
| - desc.fWidth = width; |
| - desc.fHeight = height; |
| - desc.fConfig = readConfig; |
| - desc.fOrigin = kTopLeft_GrSurfaceOrigin; |
| - |
| - // When a full read back is faster than a partial we could always make the scratch exactly |
| - // match the passed rect. However, if we see many different size rectangles we will trash |
| - // our texture cache and pay the cost of creating and destroying many textures. So, we only |
| - // request an exact match when the caller is reading an entire RT. |
| - GrTextureProvider::ScratchTexMatch match = GrTextureProvider::kApprox_ScratchTexMatch; |
| - if (0 == left && |
| - 0 == top && |
| - target->width() == width && |
| - target->height() == height && |
| - fGpu->fullReadPixelsIsFasterThanPartial()) { |
| - match = GrTextureProvider::kExact_ScratchTexMatch; |
| - } |
| - tempTexture.reset(this->textureProvider()->refScratchTexture(desc, match)); |
| - if (tempTexture) { |
| - // compute a matrix to perform the draw |
| - SkMatrix textureMatrix; |
| - textureMatrix.setTranslate(SK_Scalar1 *left, SK_Scalar1 *top); |
| - textureMatrix.postIDiv(src->width(), src->height()); |
| - |
| - SkAutoTUnref<const GrFragmentProcessor> fp; |
| - if (unpremul) { |
| - fp.reset(this->createPMToUPMEffect(src, swapRAndB, textureMatrix)); |
| - if (fp) { |
| - unpremul = false; // we no longer need to do this on CPU after the read back. |
| - } |
| - } |
| - // If we failed to create a PM->UPM effect and have no other conversions to perform then |
| - // there is no longer any point to using the scratch. |
| - if (fp || flipY || swapRAndB) { |
| - if (!fp) { |
| - fp.reset(GrConfigConversionEffect::Create( |
| - src, swapRAndB, GrConfigConversionEffect::kNone_PMConversion, |
| - textureMatrix)); |
| - } |
| - swapRAndB = false; // we will handle the swap in the draw. |
| - |
| - // We protect the existing geometry here since it may not be |
| - // clear to the caller that a draw operation (i.e., drawSimpleRect) |
| - // can be invoked in this method |
| - { |
| - GrPipelineBuilder pipelineBuilder; |
| - SkASSERT(fp); |
| - pipelineBuilder.addColorProcessor(fp); |
| - |
| - pipelineBuilder.setRenderTarget(tempTexture->asRenderTarget()); |
| - SkRect rect = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height)); |
| - fDrawBuffer->drawSimpleRect(&pipelineBuilder, |
| - GrColor_WHITE, |
| - SkMatrix::I(), |
| - rect); |
| - // we want to read back from the scratch's origin |
| - left = 0; |
| - top = 0; |
| - target = tempTexture->asRenderTarget(); |
| - } |
| - this->flushSurfaceWrites(target); |
| - } |
| - } |
| - } |
| - |
| - if (!fGpu->readPixels(target, |
| - left, top, width, height, |
| - readConfig, buffer, rowBytes)) { |
| - return false; |
| - } |
| - // Perform any conversions we weren't able to perform using a scratch texture. |
| - if (unpremul || swapRAndB) { |
| - SkDstPixelInfo dstPI; |
| - if (!GrPixelConfig2ColorAndProfileType(dstConfig, &dstPI.fColorType, NULL)) { |
| - return false; |
| - } |
| - dstPI.fAlphaType = kUnpremul_SkAlphaType; |
| - dstPI.fPixels = buffer; |
| - dstPI.fRowBytes = rowBytes; |
| - |
| - SkSrcPixelInfo srcPI; |
| - srcPI.fColorType = swapRAndB ? toggle_colortype32(dstPI.fColorType) : dstPI.fColorType; |
| - srcPI.fAlphaType = kPremul_SkAlphaType; |
| - srcPI.fPixels = buffer; |
| - srcPI.fRowBytes = rowBytes; |
| - |
| - return srcPI.convertPixelsTo(&dstPI, width, height); |
| - } |
| - return true; |
| -} |
| - |
| -void GrContext::prepareSurfaceForExternalRead(GrSurface* surface) { |
| - RETURN_IF_ABANDONED |
| - SkASSERT(surface); |
| - ASSERT_OWNED_RESOURCE(surface); |
| - if (surface->surfacePriv().hasPendingIO()) { |
| - this->flush(); |
| - } |
| - GrRenderTarget* rt = surface->asRenderTarget(); |
| - if (fGpu && rt) { |
| - fGpu->resolveRenderTarget(rt); |
| - } |
| -} |
| - |
| -void GrContext::discardRenderTarget(GrRenderTarget* renderTarget) { |
| - RETURN_IF_ABANDONED |
| - SkASSERT(renderTarget); |
| - ASSERT_OWNED_RESOURCE(renderTarget); |
| - AutoCheckFlush acf(this); |
| - GrDrawTarget* target = this->prepareToDraw(); |
| - if (NULL == target) { |
| - return; |
| - } |
| - target->discard(renderTarget); |
| -} |
| - |
| -void GrContext::copySurface(GrSurface* dst, GrSurface* src, const SkIRect& srcRect, |
| - const SkIPoint& dstPoint, uint32_t pixelOpsFlags) { |
| - RETURN_IF_ABANDONED |
| - if (NULL == src || NULL == dst) { |
| - return; |
| - } |
| - ASSERT_OWNED_RESOURCE(src); |
| - ASSERT_OWNED_RESOURCE(dst); |
| - |
| - // Since we're going to the draw target and not GPU, no need to check kNoFlush |
| - // here. |
| - |
| - GrDrawTarget* target = this->prepareToDraw(); |
| - if (NULL == target) { |
| - return; |
| - } |
| - target->copySurface(dst, src, srcRect, dstPoint); |
| - |
| - if (kFlushWrites_PixelOp & pixelOpsFlags) { |
| - this->flush(); |
| - } |
| -} |
| - |
| -void GrContext::flushSurfaceWrites(GrSurface* surface) { |
| - RETURN_IF_ABANDONED |
| - if (surface->surfacePriv().hasPendingWrite()) { |
| - this->flush(); |
| - } |
| -} |
| - |
| -GrDrawTarget* GrContext::prepareToDraw(GrPipelineBuilder* pipelineBuilder, |
| - GrRenderTarget* rt, |
| - const GrClip& clip, |
| - const GrPaint* paint, |
| - const AutoCheckFlush* acf) { |
| - if (NULL == fGpu || NULL == fDrawBuffer) { |
| - return NULL; |
| - } |
| ASSERT_OWNED_RESOURCE(rt); |
| - SkASSERT(rt && paint && acf); |
| - pipelineBuilder->setFromPaint(*paint, rt, clip); |
| - return fDrawBuffer; |
| -} |
| - |
| -GrDrawTarget* GrContext::prepareToDraw() { |
| - if (NULL == fGpu) { |
| - return NULL; |
| - } |
| - return fDrawBuffer; |
| -} |
| - |
| -/* |
| - * This method finds a path renderer that can draw the specified path on |
| - * the provided target. |
| - * Due to its expense, the software path renderer has split out so it can |
| - * can be individually allowed/disallowed via the "allowSW" boolean. |
| - */ |
| -GrPathRenderer* GrContext::getPathRenderer(const GrDrawTarget* target, |
| - const GrPipelineBuilder* pipelineBuilder, |
| - const SkMatrix& viewMatrix, |
| - const SkPath& path, |
| - const GrStrokeInfo& stroke, |
| - bool allowSW, |
| - GrPathRendererChain::DrawType drawType, |
| - GrPathRendererChain::StencilSupport* stencilSupport) { |
| - |
| - if (NULL == fPathRendererChain) { |
| - fPathRendererChain = SkNEW_ARGS(GrPathRendererChain, (this)); |
| - } |
| - |
| - GrPathRenderer* pr = fPathRendererChain->getPathRenderer(target, |
| - pipelineBuilder, |
| - viewMatrix, |
| - path, |
| - stroke, |
| - drawType, |
| - stencilSupport); |
| - |
| - if (NULL == pr && allowSW) { |
| - if (NULL == fSoftwarePathRenderer) { |
| - fSoftwarePathRenderer = SkNEW_ARGS(GrSoftwarePathRenderer, (this)); |
| - } |
| - pr = fSoftwarePathRenderer; |
| - } |
| - |
| - return pr; |
| -} |
| - |
| -//////////////////////////////////////////////////////////////////////////////// |
| -bool GrContext::isConfigRenderable(GrPixelConfig config, bool withMSAA) const { |
| - return fGpu->caps()->isConfigRenderable(config, withMSAA); |
| -} |
| - |
| -int GrContext::getRecommendedSampleCount(GrPixelConfig config, |
| - SkScalar dpi) const { |
| - if (!this->isConfigRenderable(config, true)) { |
| - return 0; |
| - } |
| - int chosenSampleCount = 0; |
| - if (fGpu->caps()->shaderCaps()->pathRenderingSupport()) { |
| - if (dpi >= 250.0f) { |
| - chosenSampleCount = 4; |
| - } else { |
| - chosenSampleCount = 16; |
| - } |
| - } |
| - return chosenSampleCount <= fGpu->caps()->maxSampleCount() ? |
| - chosenSampleCount : 0; |
| -} |
| - |
| -GrDrawTarget* GrContext::getTextTarget() { |
| - return this->prepareToDraw(); |
| -} |
| - |
| -namespace { |
| -void test_pm_conversions(GrContext* ctx, int* pmToUPMValue, int* upmToPMValue) { |
| - GrConfigConversionEffect::PMConversion pmToUPM; |
| - GrConfigConversionEffect::PMConversion upmToPM; |
| - GrConfigConversionEffect::TestForPreservingPMConversions(ctx, &pmToUPM, &upmToPM); |
| - *pmToUPMValue = pmToUPM; |
| - *upmToPMValue = upmToPM; |
| -} |
| -} |
| - |
| -const GrFragmentProcessor* GrContext::createPMToUPMEffect(GrTexture* texture, |
| - bool swapRAndB, |
| - const SkMatrix& matrix) { |
| - if (!fDidTestPMConversions) { |
| - test_pm_conversions(this, &fPMToUPMConversion, &fUPMToPMConversion); |
| - fDidTestPMConversions = true; |
| - } |
| - GrConfigConversionEffect::PMConversion pmToUPM = |
| - static_cast<GrConfigConversionEffect::PMConversion>(fPMToUPMConversion); |
| - if (GrConfigConversionEffect::kNone_PMConversion != pmToUPM) { |
| - return GrConfigConversionEffect::Create(texture, swapRAndB, pmToUPM, matrix); |
| - } else { |
| - return NULL; |
| - } |
| -} |
| - |
| -const GrFragmentProcessor* GrContext::createUPMToPMEffect(GrTexture* texture, |
| - bool swapRAndB, |
| - const SkMatrix& matrix) { |
| - if (!fDidTestPMConversions) { |
| - test_pm_conversions(this, &fPMToUPMConversion, &fUPMToPMConversion); |
| - fDidTestPMConversions = true; |
| - } |
| - GrConfigConversionEffect::PMConversion upmToPM = |
| - static_cast<GrConfigConversionEffect::PMConversion>(fUPMToPMConversion); |
| - if (GrConfigConversionEffect::kNone_PMConversion != upmToPM) { |
| - return GrConfigConversionEffect::Create(texture, swapRAndB, upmToPM, matrix); |
| - } else { |
| - return NULL; |
| - } |
| -} |
| - |
| -////////////////////////////////////////////////////////////////////////////// |
| - |
| -void GrContext::getResourceCacheLimits(int* maxTextures, size_t* maxTextureBytes) const { |
| - if (maxTextures) { |
| - *maxTextures = fResourceCache->getMaxResourceCount(); |
| - } |
| - if (maxTextureBytes) { |
| - *maxTextureBytes = fResourceCache->getMaxResourceBytes(); |
| - } |
| -} |
| - |
| -void GrContext::setResourceCacheLimits(int maxTextures, size_t maxTextureBytes) { |
| - fResourceCache->setLimits(maxTextures, maxTextureBytes); |
| -} |
| - |
| -////////////////////////////////////////////////////////////////////////////// |
| - |
| -void GrContext::addGpuTraceMarker(const GrGpuTraceMarker* marker) { |
| - fGpu->addGpuTraceMarker(marker); |
| - if (fDrawBuffer) { |
| - fDrawBuffer->addGpuTraceMarker(marker); |
| - } |
| -} |
| - |
| -void GrContext::removeGpuTraceMarker(const GrGpuTraceMarker* marker) { |
| - fGpu->removeGpuTraceMarker(marker); |
| - if (fDrawBuffer) { |
| - fDrawBuffer->removeGpuTraceMarker(marker); |
| - } |
| + SkASSERT(rt); |
| + return true; |
| } |
| /////////////////////////////////////////////////////////////////////////////////////////////////// |
| @@ -1997,3 +1285,4 @@ BATCH_TEST_DEFINE(VerticesBatch) { |
| } |
| #endif |
| + |