Index: src/gpu/GrContext.cpp |
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp |
index 3ed0b6baa26fc37c9483c44b0fa9b30aee85dd7b..550d7ff7c19a4f4c7d9a65cb66c1abe1250c7f03 100755 |
--- a/src/gpu/GrContext.cpp |
+++ b/src/gpu/GrContext.cpp |
@@ -17,6 +17,7 @@ |
#include "GrCaps.h" |
#include "GrContextOptions.h" |
#include "GrDefaultGeoProcFactory.h" |
+#include "GrDrawContext.h" |
#include "GrGpuResource.h" |
#include "GrGpuResourcePriv.h" |
#include "GrGpu.h" |
@@ -53,23 +54,61 @@ |
#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; } |
+#define RETURN_IF_ABANDONED if (fDrawingMgr.abandoned()) { return; } |
+#define RETURN_FALSE_IF_ABANDONED if (fDrawingMgr.abandoned()) { return false; } |
+#define RETURN_NULL_IF_ABANDONED if (fDrawingMgr.abandoned()) { return NULL; } |
-class GrContext::AutoCheckFlush { |
-public: |
- AutoCheckFlush(GrContext* context) : fContext(context) { SkASSERT(context); } |
- ~AutoCheckFlush() { |
- if (fContext->fFlushToReduceCacheSize) { |
- fContext->flush(); |
- } |
+//////////////////////////////////////////////////////////////////////////////// |
+ |
+void GrContext::DrawingMgr::init(GrContext* context) { |
+#ifdef IMMEDIATE_MODE |
+ fDrawTarget = SkNEW_ARGS(GrImmediateDrawTarget, (context)); |
+#else |
+ fDrawTarget = SkNEW_ARGS(GrInOrderDrawBuffer, (context)); |
+#endif |
+ |
+ fDrawContext = SkNEW_ARGS(GrDrawContext, (context, fDrawTarget)); |
+} |
+ |
+GrContext::DrawingMgr::~DrawingMgr() { |
+ SkSafeUnref(fDrawTarget); |
+ SkSafeUnref(fDrawContext); |
+} |
+ |
+void GrContext::DrawingMgr::abandon() { |
+ SkSafeSetNull(fDrawTarget); |
+ fDrawContext->fDrawTarget.reset(NULL); |
+ SkSafeSetNull(fDrawContext); |
+} |
+ |
+void GrContext::DrawingMgr::purgeResources() { |
+ if (fDrawTarget) { |
+ fDrawTarget->purgeResources(); |
+ } |
+} |
+ |
+void GrContext::DrawingMgr::reset() { |
+ if (fDrawTarget) { |
+ fDrawTarget->reset(); |
} |
+} |
+ |
+void GrContext::DrawingMgr::flush() { |
+ if (fDrawTarget) { |
+ fDrawTarget->flush(); |
+ } |
+} |
+ |
+GrDrawContext* GrContext::DrawingMgr::drawContext() { |
+ if (this->abandoned()) { |
+ return NULL; |
+ } |
+ return fDrawContext; |
+} |
+ |
+//////////////////////////////////////////////////////////////////////////////// |
-private: |
- GrContext* fContext; |
-}; |
GrContext* GrContext::Create(GrBackend backend, GrBackendContext backendContext) { |
GrContextOptions defaultOptions; |
@@ -104,19 +143,16 @@ GrContext::GrContext() : fUniqueID(next_id()) { |
fPathRendererChain = NULL; |
fSoftwarePathRenderer = NULL; |
fBatchFontCache = NULL; |
- fDrawBuffer = NULL; |
fFlushToReduceCacheSize = false; |
- fAARectRenderer = NULL; |
- fOvalRenderer = NULL; |
fMaxTextureSizeOverride = 1 << 20; |
} |
bool GrContext::init(GrBackend backend, GrBackendContext backendContext, |
const GrContextOptions& options) { |
- SkASSERT(NULL == fGpu); |
+ SkASSERT(!fGpu); |
fGpu = GrGpu::Create(backend, backendContext, options, this); |
- if (NULL == fGpu) { |
+ if (!fGpu) { |
return false; |
} |
this->initCommon(); |
@@ -130,16 +166,9 @@ void GrContext::initCommon() { |
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 |
+ fDrawingMgr.init(this); |
// GrBatchFontCache will eventually replace GrFontCache |
fBatchFontCache = SkNEW_ARGS(GrBatchFontCache, (this)); |
@@ -148,7 +177,7 @@ void GrContext::initCommon() { |
} |
GrContext::~GrContext() { |
- if (NULL == fGpu) { |
+ if (!fGpu) { |
return; |
} |
@@ -161,10 +190,6 @@ GrContext::~GrContext() { |
SkDELETE(fResourceProvider); |
SkDELETE(fResourceCache); |
SkDELETE(fBatchFontCache); |
- SkDELETE(fDrawBuffer); |
- |
- fAARectRenderer->unref(); |
- fOvalRenderer->unref(); |
fGpu->unref(); |
SkSafeUnref(fPathRendererChain); |
@@ -184,8 +209,7 @@ void GrContext::abandonContext() { |
SkSafeSetNull(fPathRendererChain); |
SkSafeSetNull(fSoftwarePathRenderer); |
- SkDELETE(fDrawBuffer); |
- fDrawBuffer = NULL; |
+ fDrawingMgr.abandon(); |
fBatchFontCache->freeAll(); |
fLayerCache->freeAll(); |
@@ -199,9 +223,7 @@ void GrContext::resetContext(uint32_t state) { |
void GrContext::freeGpuResources() { |
this->flush(); |
- if (fDrawBuffer) { |
- fDrawBuffer->purgeResources(); |
- } |
+ fDrawingMgr.purgeResources(); |
fBatchFontCache->freeAll(); |
fLayerCache->freeAll(); |
@@ -238,6 +260,10 @@ GrTextContext* GrContext::createTextContext(GrRenderTarget* renderTarget, |
//////////////////////////////////////////////////////////////////////////////// |
+bool GrContext::shaderDerivativeSupport() const { |
+ return fGpu->caps()->shaderCaps()->shaderDerivativeSupport(); |
+} |
+ |
bool GrContext::isConfigTexturable(GrPixelConfig config) const { |
return fGpu->caps()->isConfigTexturable(config); |
} |
@@ -278,1093 +304,15 @@ int GrContext::getMaxSampleCount() const { |
return fGpu->caps()->maxSampleCount(); |
} |
-/////////////////////////////////////////////////////////////////////////////// |
- |
-void GrContext::clear(const SkIRect* rect, |
- const GrColor color, |
- bool canIgnoreRect, |
- GrRenderTarget* renderTarget) { |
- 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) { |
- return; |
- } |
- target->clear(rect, color, canIgnoreRect, renderTarget); |
-} |
- |
-void GrContext::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 |
- SkRect r; |
- r.setLTRB(0, 0, |
- SkIntToScalar(rt->width()), |
- SkIntToScalar(rt->height())); |
- SkTCopyOnFirstWrite<GrPaint> paint(origPaint); |
- |
- // by definition this fills the entire clip, no need for AA |
- if (paint->isAntiAlias()) { |
- paint.writable()->setAntiAlias(false); |
- } |
- |
- bool isPerspective = viewMatrix.hasPerspective(); |
- |
- // We attempt to map r by the inverse matrix and draw that. mapRect will |
- // map the four corners and bound them with a new rect. This will not |
- // produce a correct result for some perspective matrices. |
- if (!isPerspective) { |
- SkMatrix inverse; |
- if (!viewMatrix.invert(&inverse)) { |
- SkDebugf("Could not invert matrix\n"); |
- return; |
- } |
- inverse.mapRect(&r); |
- this->drawRect(rt, clip, *paint, viewMatrix, r); |
- } else { |
- SkMatrix localMatrix; |
- if (!viewMatrix.invert(&localMatrix)) { |
- SkDebugf("Could not invert matrix\n"); |
- return; |
- } |
- |
- AutoCheckFlush acf(this); |
- GrPipelineBuilder pipelineBuilder; |
- GrDrawTarget* target = this->prepareToDraw(&pipelineBuilder, rt, clip, paint, &acf); |
- if (NULL == target) { |
- return; |
- } |
- |
- GR_CREATE_TRACE_MARKER("GrContext::drawPaintWithPerspective", target); |
- target->drawRect(&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); |
-} |
- |
-static bool apply_aa_to_rect(GrDrawTarget* target, |
- GrPipelineBuilder* pipelineBuilder, |
- SkRect* devBoundRect, |
- const SkRect& rect, |
- SkScalar strokeWidth, |
- const SkMatrix& combinedMatrix, |
- GrColor color) { |
- if (pipelineBuilder->getRenderTarget()->isMultisampled()) { |
- return false; |
- } |
- |
-#if defined(SHADER_AA_FILL_RECT) || !defined(IGNORE_ROT_AA_RECT_OPT) |
- if (strokeWidth >= 0) { |
-#endif |
- if (!combinedMatrix.preservesAxisAlignment()) { |
- return false; |
- } |
- |
-#if defined(SHADER_AA_FILL_RECT) || !defined(IGNORE_ROT_AA_RECT_OPT) |
- } else { |
- if (!combinedMatrix.preservesRightAngles()) { |
- return false; |
- } |
- } |
-#endif |
- |
- combinedMatrix.mapRect(devBoundRect, rect); |
- if (!combinedMatrix.rectStaysRect()) { |
- return true; |
- } |
- |
- if (strokeWidth < 0) { |
- return !is_irect(*devBoundRect); |
- } |
- |
- return true; |
-} |
- |
-static inline bool rect_contains_inclusive(const SkRect& rect, const SkPoint& point) { |
- return point.fX >= rect.fLeft && point.fX <= rect.fRight && |
- point.fY >= rect.fTop && point.fY <= rect.fBottom; |
-} |
- |
-class StrokeRectBatch : public GrBatch { |
-public: |
- struct Geometry { |
- GrColor fColor; |
- SkMatrix fViewMatrix; |
- SkRect fRect; |
- SkScalar fStrokeWidth; |
- }; |
- |
- static GrBatch* Create(const Geometry& geometry, bool snapToPixelCenters) { |
- return SkNEW_ARGS(StrokeRectBatch, (geometry, snapToPixelCenters)); |
- } |
- |
- const char* name() const override { return "StrokeRectBatch"; } |
- |
- void getInvariantOutputColor(GrInitInvariantOutput* out) const override { |
- // When this is called on a batch, there is only one geometry bundle |
- out->setKnownFourComponents(fGeoData[0].fColor); |
- } |
- |
- void getInvariantOutputCoverage(GrInitInvariantOutput* out) const override { |
- out->setKnownSingleComponent(0xff); |
- } |
- |
- void initBatchTracker(const GrPipelineInfo& init) override { |
- // Handle any color overrides |
- if (init.fColorIgnored) { |
- fGeoData[0].fColor = GrColor_ILLEGAL; |
- } else if (GrColor_ILLEGAL != init.fOverrideColor) { |
- fGeoData[0].fColor = init.fOverrideColor; |
- } |
- |
- // setup batch properties |
- fBatch.fColorIgnored = init.fColorIgnored; |
- fBatch.fColor = fGeoData[0].fColor; |
- fBatch.fUsesLocalCoords = init.fUsesLocalCoords; |
- fBatch.fCoverageIgnored = init.fCoverageIgnored; |
- } |
- |
- void generateGeometry(GrBatchTarget* batchTarget, const GrPipeline* pipeline) override { |
- SkAutoTUnref<const GrGeometryProcessor> gp( |
- GrDefaultGeoProcFactory::Create(GrDefaultGeoProcFactory::kPosition_GPType, |
- this->color(), |
- this->usesLocalCoords(), |
- this->coverageIgnored(), |
- this->viewMatrix(), |
- SkMatrix::I())); |
- |
- batchTarget->initDraw(gp, pipeline); |
- |
- size_t vertexStride = gp->getVertexStride(); |
- |
- SkASSERT(vertexStride == sizeof(GrDefaultGeoProcFactory::PositionAttr)); |
- |
- Geometry& args = fGeoData[0]; |
- |
- int vertexCount = kVertsPerHairlineRect; |
- if (args.fStrokeWidth > 0) { |
- vertexCount = kVertsPerStrokeRect; |
- } |
- |
- const GrVertexBuffer* vertexBuffer; |
- int firstVertex; |
- |
- void* verts = batchTarget->makeVertSpace(vertexStride, vertexCount, |
- &vertexBuffer, &firstVertex); |
- |
- if (!verts) { |
- SkDebugf("Could not allocate vertices\n"); |
- return; |
- } |
- |
- SkPoint* vertex = reinterpret_cast<SkPoint*>(verts); |
- |
- GrPrimitiveType primType; |
- |
- if (args.fStrokeWidth > 0) {; |
- primType = kTriangleStrip_GrPrimitiveType; |
- args.fRect.sort(); |
- this->setStrokeRectStrip(vertex, args.fRect, args.fStrokeWidth); |
- } else { |
- // hairline |
- primType = kLineStrip_GrPrimitiveType; |
- vertex[0].set(args.fRect.fLeft, args.fRect.fTop); |
- vertex[1].set(args.fRect.fRight, args.fRect.fTop); |
- vertex[2].set(args.fRect.fRight, args.fRect.fBottom); |
- vertex[3].set(args.fRect.fLeft, args.fRect.fBottom); |
- vertex[4].set(args.fRect.fLeft, args.fRect.fTop); |
- } |
- |
- GrVertices vertices; |
- vertices.init(primType, vertexBuffer, firstVertex, vertexCount); |
- batchTarget->draw(vertices); |
- } |
- |
- SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; } |
- |
-private: |
- StrokeRectBatch(const Geometry& geometry, bool snapToPixelCenters) { |
- this->initClassID<StrokeRectBatch>(); |
- |
- fBatch.fHairline = geometry.fStrokeWidth == 0; |
- |
- fGeoData.push_back(geometry); |
- |
- // setup bounds |
- fBounds = geometry.fRect; |
- SkScalar rad = SkScalarHalf(geometry.fStrokeWidth); |
- fBounds.outset(rad, rad); |
- geometry.fViewMatrix.mapRect(&fBounds); |
- |
- // If our caller snaps to pixel centers then we have to round out the bounds |
- if (snapToPixelCenters) { |
- fBounds.roundOut(); |
- } |
- } |
- |
- /* create a triangle strip that strokes the specified rect. There are 8 |
- unique vertices, but we repeat the last 2 to close up. Alternatively we |
- could use an indices array, and then only send 8 verts, but not sure that |
- would be faster. |
- */ |
- void setStrokeRectStrip(SkPoint verts[10], const SkRect& rect, SkScalar width) { |
- const SkScalar rad = SkScalarHalf(width); |
- // TODO we should be able to enable this assert, but we'd have to filter these draws |
- // this is a bug |
- //SkASSERT(rad < rect.width() / 2 && rad < rect.height() / 2); |
- |
- verts[0].set(rect.fLeft + rad, rect.fTop + rad); |
- verts[1].set(rect.fLeft - rad, rect.fTop - rad); |
- verts[2].set(rect.fRight - rad, rect.fTop + rad); |
- verts[3].set(rect.fRight + rad, rect.fTop - rad); |
- verts[4].set(rect.fRight - rad, rect.fBottom - rad); |
- verts[5].set(rect.fRight + rad, rect.fBottom + rad); |
- verts[6].set(rect.fLeft + rad, rect.fBottom - rad); |
- verts[7].set(rect.fLeft - rad, rect.fBottom + rad); |
- verts[8] = verts[0]; |
- verts[9] = verts[1]; |
- } |
- |
- |
- GrColor color() const { return fBatch.fColor; } |
- bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; } |
- bool colorIgnored() const { return fBatch.fColorIgnored; } |
- const SkMatrix& viewMatrix() const { return fGeoData[0].fViewMatrix; } |
- bool hairline() const { return fBatch.fHairline; } |
- bool coverageIgnored() const { return fBatch.fCoverageIgnored; } |
- |
- bool onCombineIfPossible(GrBatch* t) override { |
- // StrokeRectBatch* that = t->cast<StrokeRectBatch>(); |
- |
- // NonAA stroke rects cannot batch right now |
- // TODO make these batchable |
- return false; |
- } |
- |
- struct BatchTracker { |
- GrColor fColor; |
- bool fUsesLocalCoords; |
- bool fColorIgnored; |
- bool fCoverageIgnored; |
- bool fHairline; |
- }; |
- |
- const static int kVertsPerHairlineRect = 5; |
- const static int kVertsPerStrokeRect = 10; |
- |
- BatchTracker fBatch; |
- 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) { |
- RETURN_IF_ABANDONED |
- if (strokeInfo && strokeInfo->isDashed()) { |
- SkPath path; |
- path.setIsVolatile(true); |
- path.addRect(rect); |
- this->drawPath(rt, clip, paint, viewMatrix, path, *strokeInfo); |
- return; |
- } |
- |
- AutoCheckFlush acf(this); |
- GrPipelineBuilder pipelineBuilder; |
- GrDrawTarget* target = this->prepareToDraw(&pipelineBuilder, rt, clip, &paint, &acf); |
- if (NULL == target) { |
- return; |
- } |
- |
- GR_CREATE_TRACE_MARKER("GrContext::drawRect", target); |
- 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 |
- // cases where the RT is fully inside a stroke. |
- if (width < 0) { |
- SkRect rtRect; |
- pipelineBuilder.getRenderTarget()->getBoundsRect(&rtRect); |
- SkRect clipSpaceRTRect = rtRect; |
- bool checkClip = GrClip::kWideOpen_ClipType != clip.clipType(); |
- if (checkClip) { |
- clipSpaceRTRect.offset(SkIntToScalar(clip.origin().fX), |
- SkIntToScalar(clip.origin().fY)); |
- } |
- // Does the clip contain the entire RT? |
- if (!checkClip || clip.quickContains(clipSpaceRTRect)) { |
- SkMatrix invM; |
- if (!viewMatrix.invert(&invM)) { |
- return; |
- } |
- // Does the rect bound the RT? |
- SkPoint srcSpaceRTQuad[4]; |
- invM.mapRectToQuad(srcSpaceRTQuad, rtRect); |
- if (rect_contains_inclusive(rect, srcSpaceRTQuad[0]) && |
- rect_contains_inclusive(rect, srcSpaceRTQuad[1]) && |
- rect_contains_inclusive(rect, srcSpaceRTQuad[2]) && |
- rect_contains_inclusive(rect, srcSpaceRTQuad[3])) { |
- // Will it blend? |
- GrColor clearColor; |
- if (paint.isOpaqueAndConstantColor(&clearColor)) { |
- target->clear(NULL, clearColor, true, rt); |
- return; |
- } |
- } |
- } |
- } |
- |
- 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); |
- |
- if (doAA) { |
- if (width >= 0) { |
- fAARectRenderer->strokeAARect(target, |
- &pipelineBuilder, |
- color, |
- viewMatrix, |
- rect, |
- devBoundRect, |
- *strokeInfo); |
- } else { |
- // filled AA rect |
- fAARectRenderer->fillAARect(target, |
- &pipelineBuilder, |
- color, |
- viewMatrix, |
- rect, |
- devBoundRect); |
- } |
- return; |
- } |
- |
- if (width >= 0) { |
- StrokeRectBatch::Geometry geometry; |
- geometry.fViewMatrix = viewMatrix; |
- geometry.fColor = color; |
- geometry.fRect = rect; |
- geometry.fStrokeWidth = width; |
- |
- // Non-AA hairlines are snapped to pixel centers to make which pixels are hit deterministic |
- bool snapToPixelCenters = (0 == width && !rt->isMultisampled()); |
- SkAutoTUnref<GrBatch> batch(StrokeRectBatch::Create(geometry, snapToPixelCenters)); |
- |
- // Depending on sub-pixel coordinates and the particular GPU, we may lose a corner of |
- // hairline rects. We jam all the vertices to pixel centers to avoid this, but not when MSAA |
- // is enabled because it can cause ugly artifacts. |
- pipelineBuilder.setState(GrPipelineBuilder::kSnapVerticesToPixelCenters_Flag, |
- snapToPixelCenters); |
- target->drawBatch(&pipelineBuilder, batch); |
- } else { |
- // filled BW rect |
- target->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) { |
- RETURN_IF_ABANDONED |
- AutoCheckFlush acf(this); |
- GrPipelineBuilder pipelineBuilder; |
- GrDrawTarget* target = this->prepareToDraw(&pipelineBuilder, rt, clip, &paint, &acf); |
- if (NULL == target) { |
- return; |
- } |
- |
- GR_CREATE_TRACE_MARKER("GrContext::drawRectToRect", target); |
- |
- target->drawRect(&pipelineBuilder, |
- paint.getColor(), |
- viewMatrix, |
- rectToDraw, |
- &localRect, |
- localMatrix); |
-} |
- |
-static const GrGeometryProcessor* set_vertex_attributes(bool hasLocalCoords, |
- bool hasColors, |
- int* colorOffset, |
- int* texOffset, |
- GrColor color, |
- const SkMatrix& viewMatrix, |
- bool coverageIgnored) { |
- *texOffset = -1; |
- *colorOffset = -1; |
- uint32_t flags = GrDefaultGeoProcFactory::kPosition_GPType; |
- if (hasLocalCoords && hasColors) { |
- *colorOffset = sizeof(SkPoint); |
- *texOffset = sizeof(SkPoint) + sizeof(GrColor); |
- flags |= GrDefaultGeoProcFactory::kColor_GPType | |
- GrDefaultGeoProcFactory::kLocalCoord_GPType; |
- } else if (hasLocalCoords) { |
- *texOffset = sizeof(SkPoint); |
- flags |= GrDefaultGeoProcFactory::kLocalCoord_GPType; |
- } else if (hasColors) { |
- *colorOffset = sizeof(SkPoint); |
- flags |= GrDefaultGeoProcFactory::kColor_GPType; |
- } |
- return GrDefaultGeoProcFactory::Create(flags, color, hasLocalCoords, coverageIgnored, |
- viewMatrix, SkMatrix::I()); |
-} |
- |
-class DrawVerticesBatch : public GrBatch { |
-public: |
- struct Geometry { |
- GrColor fColor; |
- SkTDArray<SkPoint> fPositions; |
- SkTDArray<uint16_t> fIndices; |
- SkTDArray<GrColor> fColors; |
- SkTDArray<SkPoint> fLocalCoords; |
- }; |
- |
- static GrBatch* Create(const Geometry& geometry, GrPrimitiveType primitiveType, |
- const SkMatrix& viewMatrix, |
- const SkPoint* positions, int vertexCount, |
- const uint16_t* indices, int indexCount, |
- const GrColor* colors, const SkPoint* localCoords, |
- const SkRect& bounds) { |
- return SkNEW_ARGS(DrawVerticesBatch, (geometry, primitiveType, viewMatrix, positions, |
- vertexCount, indices, indexCount, colors, |
- localCoords, bounds)); |
- } |
- |
- const char* name() const override { return "DrawVerticesBatch"; } |
- |
- void getInvariantOutputColor(GrInitInvariantOutput* out) const override { |
- // When this is called on a batch, there is only one geometry bundle |
- if (this->hasColors()) { |
- out->setUnknownFourComponents(); |
- } else { |
- out->setKnownFourComponents(fGeoData[0].fColor); |
- } |
- } |
- |
- void getInvariantOutputCoverage(GrInitInvariantOutput* out) const override { |
- out->setKnownSingleComponent(0xff); |
- } |
- |
- void initBatchTracker(const GrPipelineInfo& init) override { |
- // Handle any color overrides |
- if (init.fColorIgnored) { |
- fGeoData[0].fColor = GrColor_ILLEGAL; |
- } else if (GrColor_ILLEGAL != init.fOverrideColor) { |
- fGeoData[0].fColor = init.fOverrideColor; |
- } |
- |
- // setup batch properties |
- fBatch.fColorIgnored = init.fColorIgnored; |
- fBatch.fColor = fGeoData[0].fColor; |
- fBatch.fUsesLocalCoords = init.fUsesLocalCoords; |
- fBatch.fCoverageIgnored = init.fCoverageIgnored; |
- } |
- |
- void generateGeometry(GrBatchTarget* batchTarget, const GrPipeline* pipeline) override { |
- int colorOffset = -1, texOffset = -1; |
- SkAutoTUnref<const GrGeometryProcessor> gp( |
- set_vertex_attributes(this->hasLocalCoords(), this->hasColors(), &colorOffset, |
- &texOffset, this->color(), this->viewMatrix(), |
- this->coverageIgnored())); |
- |
- batchTarget->initDraw(gp, pipeline); |
- |
- size_t vertexStride = gp->getVertexStride(); |
- |
- SkASSERT(vertexStride == sizeof(SkPoint) + (this->hasLocalCoords() ? sizeof(SkPoint) : 0) |
- + (this->hasColors() ? sizeof(GrColor) : 0)); |
- |
- int instanceCount = fGeoData.count(); |
- |
- const GrVertexBuffer* vertexBuffer; |
- int firstVertex; |
- |
- void* verts = batchTarget->makeVertSpace(vertexStride, this->vertexCount(), |
- &vertexBuffer, &firstVertex); |
- |
- if (!verts) { |
- SkDebugf("Could not allocate vertices\n"); |
- return; |
- } |
- |
- const GrIndexBuffer* indexBuffer = NULL; |
- int firstIndex = 0; |
- |
- uint16_t* indices = NULL; |
- if (this->hasIndices()) { |
- indices = batchTarget->makeIndexSpace(this->indexCount(), &indexBuffer, &firstIndex); |
- |
- if (!indices) { |
- SkDebugf("Could not allocate indices\n"); |
- return; |
- } |
- } |
- |
- int indexOffset = 0; |
- int vertexOffset = 0; |
- for (int i = 0; i < instanceCount; i++) { |
- const Geometry& args = fGeoData[i]; |
- |
- // TODO we can actually cache this interleaved and then just memcopy |
- if (this->hasIndices()) { |
- for (int j = 0; j < args.fIndices.count(); ++j, ++indexOffset) { |
- *(indices + indexOffset) = args.fIndices[j] + vertexOffset; |
- } |
- } |
- |
- for (int j = 0; j < args.fPositions.count(); ++j) { |
- *((SkPoint*)verts) = args.fPositions[j]; |
- if (this->hasColors()) { |
- *(GrColor*)((intptr_t)verts + colorOffset) = args.fColors[j]; |
- } |
- if (this->hasLocalCoords()) { |
- *(SkPoint*)((intptr_t)verts + texOffset) = args.fLocalCoords[j]; |
- } |
- verts = (void*)((intptr_t)verts + vertexStride); |
- vertexOffset++; |
- } |
- } |
- |
- GrVertices vertices; |
- if (this->hasIndices()) { |
- vertices.initIndexed(this->primitiveType(), vertexBuffer, indexBuffer, firstVertex, |
- firstIndex, this->vertexCount(), this->indexCount()); |
- |
- } else { |
- vertices.init(this->primitiveType(), vertexBuffer, firstVertex, this->vertexCount()); |
- } |
- batchTarget->draw(vertices); |
- } |
- |
- SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; } |
- |
-private: |
- DrawVerticesBatch(const Geometry& geometry, GrPrimitiveType primitiveType, |
- const SkMatrix& viewMatrix, |
- const SkPoint* positions, int vertexCount, |
- const uint16_t* indices, int indexCount, |
- const GrColor* colors, const SkPoint* localCoords, const SkRect& bounds) { |
- this->initClassID<DrawVerticesBatch>(); |
- SkASSERT(positions); |
- |
- fBatch.fViewMatrix = viewMatrix; |
- Geometry& installedGeo = fGeoData.push_back(geometry); |
- |
- installedGeo.fPositions.append(vertexCount, positions); |
- if (indices) { |
- installedGeo.fIndices.append(indexCount, indices); |
- fBatch.fHasIndices = true; |
- } else { |
- fBatch.fHasIndices = false; |
- } |
- |
- if (colors) { |
- installedGeo.fColors.append(vertexCount, colors); |
- fBatch.fHasColors = true; |
- } else { |
- fBatch.fHasColors = false; |
- } |
- |
- if (localCoords) { |
- installedGeo.fLocalCoords.append(vertexCount, localCoords); |
- fBatch.fHasLocalCoords = true; |
- } else { |
- fBatch.fHasLocalCoords = false; |
- } |
- fBatch.fVertexCount = vertexCount; |
- fBatch.fIndexCount = indexCount; |
- fBatch.fPrimitiveType = primitiveType; |
- |
- this->setBounds(bounds); |
- } |
- |
- GrPrimitiveType primitiveType() const { return fBatch.fPrimitiveType; } |
- bool batchablePrimitiveType() const { |
- return kTriangles_GrPrimitiveType == fBatch.fPrimitiveType || |
- kLines_GrPrimitiveType == fBatch.fPrimitiveType || |
- kPoints_GrPrimitiveType == fBatch.fPrimitiveType; |
- } |
- GrColor color() const { return fBatch.fColor; } |
- bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; } |
- bool colorIgnored() const { return fBatch.fColorIgnored; } |
- const SkMatrix& viewMatrix() const { return fBatch.fViewMatrix; } |
- bool hasColors() const { return fBatch.fHasColors; } |
- bool hasIndices() const { return fBatch.fHasIndices; } |
- bool hasLocalCoords() const { return fBatch.fHasLocalCoords; } |
- int vertexCount() const { return fBatch.fVertexCount; } |
- int indexCount() const { return fBatch.fIndexCount; } |
- bool coverageIgnored() const { return fBatch.fCoverageIgnored; } |
- |
- bool onCombineIfPossible(GrBatch* t) override { |
- DrawVerticesBatch* that = t->cast<DrawVerticesBatch>(); |
- |
- if (!this->batchablePrimitiveType() || this->primitiveType() != that->primitiveType()) { |
- return false; |
- } |
- |
- SkASSERT(this->usesLocalCoords() == that->usesLocalCoords()); |
- |
- // We currently use a uniform viewmatrix for this batch |
- if (!this->viewMatrix().cheapEqualTo(that->viewMatrix())) { |
- return false; |
- } |
- |
- if (this->hasColors() != that->hasColors()) { |
- return false; |
- } |
- |
- if (this->hasIndices() != that->hasIndices()) { |
- return false; |
- } |
- |
- if (this->hasLocalCoords() != that->hasLocalCoords()) { |
- return false; |
- } |
- |
- if (!this->hasColors() && this->color() != that->color()) { |
- return false; |
- } |
- |
- if (this->color() != that->color()) { |
- fBatch.fColor = GrColor_ILLEGAL; |
- } |
- fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin()); |
- fBatch.fVertexCount += that->vertexCount(); |
- fBatch.fIndexCount += that->indexCount(); |
- |
- this->joinBounds(that->bounds()); |
- return true; |
- } |
- |
- struct BatchTracker { |
- GrPrimitiveType fPrimitiveType; |
- SkMatrix fViewMatrix; |
- GrColor fColor; |
- bool fUsesLocalCoords; |
- bool fColorIgnored; |
- bool fCoverageIgnored; |
- bool fHasColors; |
- bool fHasIndices; |
- bool fHasLocalCoords; |
- int fVertexCount; |
- int fIndexCount; |
- }; |
- |
- BatchTracker fBatch; |
- 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) { |
- RETURN_IF_ABANDONED |
- AutoCheckFlush acf(this); |
- GrPipelineBuilder pipelineBuilder; |
- |
- GrDrawTarget* target = this->prepareToDraw(&pipelineBuilder, rt, clip, &paint, &acf); |
- if (NULL == target) { |
- return; |
- } |
- |
- GR_CREATE_TRACE_MARKER("GrContext::drawVertices", target); |
- |
- // TODO clients should give us bounds |
- SkRect bounds; |
- if (!bounds.setBoundsCheck(positions, vertexCount)) { |
- SkDebugf("drawVertices call empty bounds\n"); |
- return; |
- } |
- |
- viewMatrix.mapRect(&bounds); |
- |
- // If we don't have AA then we outset for a half pixel in each direction to account for |
- // snapping |
- if (!paint.isAntiAlias()) { |
- bounds.outset(0.5f, 0.5f); |
- } |
- |
- DrawVerticesBatch::Geometry geometry; |
- geometry.fColor = paint.getColor(); |
- SkAutoTUnref<GrBatch> batch(DrawVerticesBatch::Create(geometry, primitiveType, viewMatrix, |
- positions, vertexCount, indices, |
- indexCount, colors, texCoords, |
- bounds)); |
- |
- target->drawBatch(&pipelineBuilder, batch); |
-} |
- |
-/////////////////////////////////////////////////////////////////////////////// |
- |
-void GrContext::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; |
- } |
- |
- if (strokeInfo.isDashed()) { |
- SkPath path; |
- path.setIsVolatile(true); |
- path.addRRect(rrect); |
- this->drawPath(rt, clip, paint, viewMatrix, path, strokeInfo); |
- return; |
- } |
- |
- AutoCheckFlush acf(this); |
- GrPipelineBuilder pipelineBuilder; |
- GrDrawTarget* target = this->prepareToDraw(&pipelineBuilder, rt, clip, &paint, &acf); |
- if (NULL == target) { |
- return; |
- } |
- |
- GR_CREATE_TRACE_MARKER("GrContext::drawRRect", target); |
- |
- GrColor color = paint.getColor(); |
- if (!fOvalRenderer->drawRRect(target, |
- &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); |
- } |
-} |
- |
-/////////////////////////////////////////////////////////////////////////////// |
- |
-void GrContext::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); |
- GrPipelineBuilder pipelineBuilder; |
- GrDrawTarget* target = this->prepareToDraw(&pipelineBuilder, rt, clip, &paint, &acf); |
- |
- GR_CREATE_TRACE_MARKER("GrContext::drawDRRect", target); |
- |
- GrColor color = paint.getColor(); |
- if (!fOvalRenderer->drawDRRect(target, |
- &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); |
- } |
-} |
- |
-/////////////////////////////////////////////////////////////////////////////// |
- |
-void GrContext::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; |
- } |
- |
- if (strokeInfo.isDashed()) { |
- SkPath path; |
- path.setIsVolatile(true); |
- path.addOval(oval); |
- this->drawPath(rt, clip, paint, viewMatrix, path, strokeInfo); |
- return; |
- } |
- |
- AutoCheckFlush acf(this); |
- GrPipelineBuilder pipelineBuilder; |
- GrDrawTarget* target = this->prepareToDraw(&pipelineBuilder, rt, clip, &paint, &acf); |
- if (NULL == target) { |
- return; |
- } |
- |
- GR_CREATE_TRACE_MARKER("GrContext::drawOval", target); |
- |
- GrColor color = paint.getColor(); |
- if (!fOvalRenderer->drawOval(target, |
- &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); |
- } |
-} |
- |
-// Can 'path' be drawn as a pair of filled nested rectangles? |
-static bool is_nested_rects(GrDrawTarget* target, |
- GrPipelineBuilder* pipelineBuilder, |
- GrColor color, |
- const SkMatrix& viewMatrix, |
- const SkPath& path, |
- const SkStrokeRec& stroke, |
- SkRect rects[2]) { |
- SkASSERT(stroke.isFillStyle()); |
- |
- if (path.isInverseFillType()) { |
- return false; |
- } |
- |
- // TODO: this restriction could be lifted if we were willing to apply |
- // the matrix to all the points individually rather than just to the rect |
- if (!viewMatrix.preservesAxisAlignment()) { |
- return false; |
- } |
- |
- SkPath::Direction dirs[2]; |
- if (!path.isNestedFillRects(rects, dirs)) { |
- return false; |
- } |
- |
- if (SkPath::kWinding_FillType == path.getFillType() && dirs[0] == dirs[1]) { |
- // The two rects need to be wound opposite to each other |
- return false; |
- } |
- |
- // Right now, nested rects where the margin is not the same width |
- // all around do not render correctly |
- const SkScalar* outer = rects[0].asScalars(); |
- const SkScalar* inner = rects[1].asScalars(); |
- |
- bool allEq = true; |
- |
- SkScalar margin = SkScalarAbs(outer[0] - inner[0]); |
- bool allGoE1 = margin >= SK_Scalar1; |
- |
- for (int i = 1; i < 4; ++i) { |
- SkScalar temp = SkScalarAbs(outer[i] - inner[i]); |
- if (temp < SK_Scalar1) { |
- allGoE1 = false; |
- } |
- if (!SkScalarNearlyEqual(margin, temp)) { |
- allEq = false; |
- } |
- } |
- |
- return allEq || allGoE1; |
-} |
- |
-void GrContext::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()) { |
- this->drawPaint(rt, clip, paint, viewMatrix); |
- } |
- return; |
- } |
- |
- GrColor color = paint.getColor(); |
- |
- // Note that internalDrawPath may sw-rasterize the path into a scratch texture. |
- // Scratch textures can be recycled after they are returned to the texture |
- // 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); |
- GrPipelineBuilder pipelineBuilder; |
- GrDrawTarget* target = this->prepareToDraw(&pipelineBuilder, rt, clip, &paint, &acf); |
- if (NULL == target) { |
- return; |
- } |
- |
- GR_CREATE_TRACE_MARKER1("GrContext::drawPath", target, "Is Convex", path.isConvex()); |
- |
- if (!strokeInfo.isDashed()) { |
- bool useCoverageAA = paint.isAntiAlias() && |
- !pipelineBuilder.getRenderTarget()->isMultisampled(); |
- |
- if (useCoverageAA && strokeInfo.getWidth() < 0 && !path.isConvex()) { |
- // 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, |
- rects)) { |
- fAARectRenderer->fillAANestedRects(target, &pipelineBuilder, color, viewMatrix, |
- rects); |
- return; |
- } |
- } |
- SkRect ovalRect; |
- bool isOval = path.isOval(&ovalRect); |
- |
- if (isOval && !path.isInverseFillType()) { |
- if (fOvalRenderer->drawOval(target, |
- &pipelineBuilder, |
- color, |
- viewMatrix, |
- paint.isAntiAlias(), |
- ovalRect, |
- strokeInfo)) { |
- return; |
- } |
- } |
- } |
- this->internalDrawPath(target, &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) { |
- RETURN_IF_ABANDONED |
- SkASSERT(!path.isEmpty()); |
- |
- GR_CREATE_TRACE_MARKER("GrContext::internalDrawPath", target); |
- |
- |
- // An Assumption here is that path renderer would use some form of tweaking |
- // the src color (either the input alpha or in the frag shader) to implement |
- // aa. If we have some future driver-mojo path AA that can do the right |
- // thing WRT to the blend then we'll need some query on the PR. |
- bool useCoverageAA = useAA && |
- !pipelineBuilder->getRenderTarget()->isMultisampled(); |
- |
- |
- GrPathRendererChain::DrawType type = |
- useCoverageAA ? GrPathRendererChain::kColorAntiAlias_DrawType : |
- GrPathRendererChain::kColor_DrawType; |
- |
- const SkPath* pathPtr = &path; |
- SkTLazy<SkPath> tmpPath; |
- 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); |
- |
- GrStrokeInfo dashlessStrokeInfo(strokeInfo, false); |
- if (NULL == pr && strokeInfo.isDashed()) { |
- // It didn't work above, so try again with dashed stroke converted to a dashless stroke. |
- if (!strokeInfo.applyDashToPath(tmpPath.init(), &dashlessStrokeInfo, *pathPtr)) { |
- return; |
- } |
- pathPtr = tmpPath.get(); |
- if (pathPtr->isEmpty()) { |
- return; |
- } |
- strokeInfoPtr = &dashlessStrokeInfo; |
- pr = this->getPathRenderer(target, pipelineBuilder, viewMatrix, *pathPtr, *strokeInfoPtr, |
- false, type); |
- } |
- |
- if (NULL == pr) { |
- if (!GrPathRenderer::IsStrokeHairlineOrEquivalent(*strokeInfoPtr, viewMatrix, NULL) && |
- !strokeInfoPtr->isFillStyle()) { |
- // It didn't work above, so try again with stroke converted to a fill. |
- if (!tmpPath.isValid()) { |
- tmpPath.init(); |
- } |
- dashlessStrokeInfo.setResScale(SkScalarAbs(viewMatrix.getMaxScale())); |
- if (!dashlessStrokeInfo.applyToPath(tmpPath.get(), *pathPtr)) { |
- return; |
- } |
- pathPtr = tmpPath.get(); |
- if (pathPtr->isEmpty()) { |
- return; |
- } |
- dashlessStrokeInfo.setFillStyle(); |
- strokeInfoPtr = &dashlessStrokeInfo; |
- } |
- |
- // This time, allow SW renderer |
- pr = this->getPathRenderer(target, pipelineBuilder, viewMatrix, *pathPtr, *strokeInfoPtr, |
- true, type); |
- } |
- |
- if (NULL == pr) { |
-#ifdef SK_DEBUG |
- SkDebugf("Unable to find path renderer compatible with path.\n"); |
-#endif |
- return; |
- } |
- |
- pr->drawPath(target, pipelineBuilder, color, viewMatrix, *pathPtr, *strokeInfoPtr, useCoverageAA); |
-} |
- |
//////////////////////////////////////////////////////////////////////////////// |
void GrContext::flush(int flagsBitfield) { |
- if (NULL == fDrawBuffer) { |
- return; |
- } |
+ RETURN_IF_ABANDONED |
if (kDiscard_FlushBit & flagsBitfield) { |
- fDrawBuffer->reset(); |
+ fDrawingMgr.reset(); |
} else { |
- fDrawBuffer->flush(); |
+ fDrawingMgr.flush(); |
} |
fResourceCache->notifyFlushOccurred(); |
fFlushToReduceCacheSize = false; |
@@ -1412,7 +360,7 @@ bool GrContext::writeSurfacePixels(GrSurface* surface, |
// 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) { |
+ if (!renderTarget) { |
return false; |
} |
@@ -1451,7 +399,7 @@ bool GrContext::writeSurfacePixels(GrSurface* surface, |
} |
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) { |
+ if (!fp) { |
size_t tmpRowBytes = 4 * width; |
tmpPixels.reset(width * height); |
if (!sw_convert_to_premul(srcConfig, width, height, rowBytes, buffer, tmpRowBytes, |
@@ -1462,7 +410,7 @@ bool GrContext::writeSurfacePixels(GrSurface* surface, |
buffer = tmpPixels.get(); |
} |
} |
- if (NULL == fp) { |
+ if (!fp) { |
fp.reset(GrConfigConversionEffect::Create(texture, |
swapRAndB, |
GrConfigConversionEffect::kNone_PMConversion, |
@@ -1483,25 +431,18 @@ bool GrContext::writeSurfacePixels(GrSurface* surface, |
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))); |
+ GrDrawContext* drawContext = this->drawContext(); |
+ if (!drawContext) { |
+ return false; |
} |
+ GrPaint paint; |
+ paint.addColorProcessor(fp); |
+ |
+ SkRect rect = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height)); |
+ |
+ drawContext->drawRect(renderTarget, GrClip::WideOpen(), paint, matrix, rect, NULL); |
+ |
if (kFlushWrites_PixelOp & pixelOpsFlags) { |
this->flushSurfaceWrites(surface); |
} |
@@ -1614,16 +555,19 @@ bool GrContext::readRenderTargetPixels(GrRenderTarget* target, |
// clear to the caller that a draw operation (i.e., drawSimpleRect) |
// can be invoked in this method |
{ |
- GrPipelineBuilder pipelineBuilder; |
- SkASSERT(fp); |
- pipelineBuilder.addColorProcessor(fp); |
+ GrDrawContext* drawContext = this->drawContext(); |
+ if (!drawContext) { |
+ return false; |
+ } |
+ |
+ GrPaint paint; |
+ paint.addColorProcessor(fp); |
- pipelineBuilder.setRenderTarget(tempTexture->asRenderTarget()); |
SkRect rect = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height)); |
- fDrawBuffer->drawSimpleRect(&pipelineBuilder, |
- GrColor_WHITE, |
- SkMatrix::I(), |
- rect); |
+ |
+ drawContext->drawRect(tempTexture->asRenderTarget(), GrClip::WideOpen(), paint, |
+ SkMatrix::I(), rect, NULL); |
+ |
// we want to read back from the scratch's origin |
left = 0; |
top = 0; |
@@ -1673,22 +617,10 @@ void GrContext::prepareSurfaceForExternalRead(GrSurface* surface) { |
} |
} |
-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) { |
+ if (!src || !dst) { |
return; |
} |
ASSERT_OWNED_RESOURCE(src); |
@@ -1696,12 +628,16 @@ void GrContext::copySurface(GrSurface* dst, GrSurface* src, const SkIRect& srcRe |
// Since we're going to the draw target and not GPU, no need to check kNoFlush |
// here. |
+ if (!dst->asRenderTarget()) { |
+ return; |
+ } |
- GrDrawTarget* target = this->prepareToDraw(); |
- if (NULL == target) { |
+ GrDrawContext* drawContext = this->drawContext(); |
+ if (!drawContext) { |
return; |
} |
- target->copySurface(dst, src, srcRect, dstPoint); |
+ |
+ drawContext->copySurface(dst->asRenderTarget(), src, srcRect, dstPoint); |
if (kFlushWrites_PixelOp & pixelOpsFlags) { |
this->flush(); |
@@ -1715,28 +651,6 @@ void GrContext::flushSurfaceWrites(GrSurface* surface) { |
} |
} |
-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. |
@@ -1752,7 +666,7 @@ GrPathRenderer* GrContext::getPathRenderer(const GrDrawTarget* target, |
GrPathRendererChain::DrawType drawType, |
GrPathRendererChain::StencilSupport* stencilSupport) { |
- if (NULL == fPathRendererChain) { |
+ if (!fPathRendererChain) { |
fPathRendererChain = SkNEW_ARGS(GrPathRendererChain, (this)); |
} |
@@ -1764,8 +678,8 @@ GrPathRenderer* GrContext::getPathRenderer(const GrDrawTarget* target, |
drawType, |
stencilSupport); |
- if (NULL == pr && allowSW) { |
- if (NULL == fSoftwarePathRenderer) { |
+ if (!pr && allowSW) { |
+ if (!fSoftwarePathRenderer) { |
fSoftwarePathRenderer = SkNEW_ARGS(GrSoftwarePathRenderer, (this)); |
} |
pr = fSoftwarePathRenderer; |
@@ -1796,10 +710,6 @@ int GrContext::getRecommendedSampleCount(GrPixelConfig config, |
chosenSampleCount : 0; |
} |
-GrDrawTarget* GrContext::getTextTarget() { |
- return this->prepareToDraw(); |
-} |
- |
namespace { |
void test_pm_conversions(GrContext* ctx, int* pmToUPMValue, int* upmToPMValue) { |
GrConfigConversionEffect::PMConversion pmToUPM; |
@@ -1861,141 +771,9 @@ void GrContext::setResourceCacheLimits(int maxTextures, size_t 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); |
- } |
-} |
- |
-/////////////////////////////////////////////////////////////////////////////////////////////////// |
- |
-#ifdef GR_TEST_UTILS |
- |
-BATCH_TEST_DEFINE(StrokeRectBatch) { |
- StrokeRectBatch::Geometry geometry; |
- geometry.fViewMatrix = GrTest::TestMatrix(random); |
- geometry.fColor = GrRandomColor(random); |
- geometry.fRect = GrTest::TestRect(random); |
- geometry.fStrokeWidth = random->nextBool() ? 0.0f : 1.0f; |
- |
- return StrokeRectBatch::Create(geometry, random->nextBool()); |
-} |
- |
-static uint32_t seed_vertices(GrPrimitiveType type) { |
- switch (type) { |
- case kTriangles_GrPrimitiveType: |
- case kTriangleStrip_GrPrimitiveType: |
- case kTriangleFan_GrPrimitiveType: |
- return 3; |
- case kPoints_GrPrimitiveType: |
- return 1; |
- case kLines_GrPrimitiveType: |
- case kLineStrip_GrPrimitiveType: |
- return 2; |
- } |
- SkFAIL("Incomplete switch\n"); |
- return 0; |
-} |
- |
-static uint32_t primitive_vertices(GrPrimitiveType type) { |
- switch (type) { |
- case kTriangles_GrPrimitiveType: |
- return 3; |
- case kLines_GrPrimitiveType: |
- return 2; |
- case kTriangleStrip_GrPrimitiveType: |
- case kTriangleFan_GrPrimitiveType: |
- case kPoints_GrPrimitiveType: |
- case kLineStrip_GrPrimitiveType: |
- return 1; |
- } |
- SkFAIL("Incomplete switch\n"); |
- return 0; |
-} |
- |
-static SkPoint random_point(SkRandom* random, SkScalar min, SkScalar max) { |
- SkPoint p; |
- p.fX = random->nextRangeScalar(min, max); |
- p.fY = random->nextRangeScalar(min, max); |
- return p; |
-} |
- |
-static void randomize_params(size_t count, size_t maxVertex, SkScalar min, SkScalar max, |
- SkRandom* random, |
- SkTArray<SkPoint>* positions, |
- SkTArray<SkPoint>* texCoords, bool hasTexCoords, |
- SkTArray<GrColor>* colors, bool hasColors, |
- SkTArray<uint16_t>* indices, bool hasIndices) { |
- for (uint32_t v = 0; v < count; v++) { |
- positions->push_back(random_point(random, min, max)); |
- if (hasTexCoords) { |
- texCoords->push_back(random_point(random, min, max)); |
- } |
- if (hasColors) { |
- colors->push_back(GrRandomColor(random)); |
- } |
- if (hasIndices) { |
- SkASSERT(maxVertex <= SK_MaxU16); |
- indices->push_back(random->nextULessThan((uint16_t)maxVertex)); |
- } |
- } |
-} |
- |
-BATCH_TEST_DEFINE(VerticesBatch) { |
- GrPrimitiveType type = GrPrimitiveType(random->nextULessThan(kLast_GrPrimitiveType + 1)); |
- uint32_t primitiveCount = random->nextRangeU(1, 100); |
- |
- // TODO make 'sensible' indexbuffers |
- SkTArray<SkPoint> positions; |
- SkTArray<SkPoint> texCoords; |
- SkTArray<GrColor> colors; |
- SkTArray<uint16_t> indices; |
- |
- bool hasTexCoords = random->nextBool(); |
- bool hasIndices = random->nextBool(); |
- bool hasColors = random->nextBool(); |
- |
- uint32_t vertexCount = seed_vertices(type) + (primitiveCount - 1) * primitive_vertices(type); |
- |
- static const SkScalar kMinVertExtent = -100.f; |
- static const SkScalar kMaxVertExtent = 100.f; |
- randomize_params(seed_vertices(type), vertexCount, kMinVertExtent, kMaxVertExtent, |
- random, |
- &positions, |
- &texCoords, hasTexCoords, |
- &colors, hasColors, |
- &indices, hasIndices); |
- |
- for (uint32_t i = 1; i < primitiveCount; i++) { |
- randomize_params(primitive_vertices(type), vertexCount, kMinVertExtent, kMaxVertExtent, |
- random, |
- &positions, |
- &texCoords, hasTexCoords, |
- &colors, hasColors, |
- &indices, hasIndices); |
- } |
- |
- SkMatrix viewMatrix = GrTest::TestMatrix(random); |
- SkRect bounds; |
- SkDEBUGCODE(bool result = ) bounds.setBoundsCheck(positions.begin(), vertexCount); |
- SkASSERT(result); |
- |
- viewMatrix.mapRect(&bounds); |
- |
- DrawVerticesBatch::Geometry geometry; |
- geometry.fColor = GrRandomColor(random); |
- return DrawVerticesBatch::Create(geometry, type, viewMatrix, |
- positions.begin(), vertexCount, |
- indices.begin(), hasIndices ? vertexCount : 0, |
- colors.begin(), |
- texCoords.begin(), |
- bounds); |
} |
-#endif |