aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--gyp/gpu.gypi1
-rw-r--r--src/gpu/GrDrawTarget.h31
-rw-r--r--src/gpu/GrGpu.cpp11
-rw-r--r--src/gpu/GrGpu.h17
-rw-r--r--src/gpu/GrInOrderDrawBuffer.cpp2
-rw-r--r--src/gpu/GrPathRendering.h75
-rw-r--r--src/gpu/GrStencilAndCoverTextContext.cpp12
-rw-r--r--src/gpu/gl/GrGLPath.cpp6
-rw-r--r--src/gpu/gl/GrGLPathRange.cpp6
-rw-r--r--src/gpu/gl/GrGLPathRendering.cpp336
-rw-r--r--src/gpu/gl/GrGLPathRendering.h64
-rw-r--r--src/gpu/gl/GrGLProgram.cpp4
-rw-r--r--src/gpu/gl/GrGLProgramEffects.cpp14
-rw-r--r--src/gpu/gl/GrGLUtil.cpp25
-rw-r--r--src/gpu/gl/GrGLUtil.h4
-rw-r--r--src/gpu/gl/GrGpuGL.cpp344
-rw-r--r--src/gpu/gl/GrGpuGL.h42
-rw-r--r--src/gpu/gl/GrGpuGL_program.cpp4
18 files changed, 531 insertions, 467 deletions
diff --git a/gyp/gpu.gypi b/gyp/gpu.gypi
index 589cc51b1d..ec2a07fc97 100644
--- a/gyp/gpu.gypi
+++ b/gyp/gpu.gypi
@@ -97,6 +97,7 @@
'<(skia_src_path)/gpu/GrPathRendererChain.cpp',
'<(skia_src_path)/gpu/GrPathRenderer.cpp',
'<(skia_src_path)/gpu/GrPathRenderer.h',
+ '<(skia_src_path)/gpu/GrPathRendering.h',
'<(skia_src_path)/gpu/GrPathUtils.cpp',
'<(skia_src_path)/gpu/GrPathUtils.h',
'<(skia_src_path)/gpu/GrPictureUtils.h',
diff --git a/src/gpu/GrDrawTarget.h b/src/gpu/GrDrawTarget.h
index d1023d2682..998f41282d 100644
--- a/src/gpu/GrDrawTarget.h
+++ b/src/gpu/GrDrawTarget.h
@@ -12,6 +12,7 @@
#include "GrContext.h"
#include "GrDrawState.h"
#include "GrIndexBuffer.h"
+#include "GrPathRendering.h"
#include "GrTraceMarker.h"
#include "SkClipStack.h"
@@ -36,6 +37,9 @@ protected:
public:
SK_DECLARE_INST_COUNT(GrDrawTarget)
+
+ typedef GrPathRendering::PathTransformType PathTransformType ;
+
///////////////////////////////////////////////////////////////////////////
// The context may not be fully constructed and should not be used during GrDrawTarget
@@ -333,38 +337,11 @@ public:
PathTransformSize(transformsType) * count elements
* @param fill Fill type for drawing all the paths
*/
- enum PathTransformType {
- kNone_PathTransformType, //!< []
- kTranslateX_PathTransformType, //!< [kMTransX]
- kTranslateY_PathTransformType, //!< [kMTransY]
- kTranslate_PathTransformType, //!< [kMTransX, kMTransY]
- kAffine_PathTransformType, //!< [kMScaleX, kMSkewX, kMTransX, kMSkewY, kMScaleY, kMTransY]
-
- kLast_PathTransformType = kAffine_PathTransformType
- };
void drawPaths(const GrPathRange* pathRange,
const uint32_t indices[], int count,
const float transforms[], PathTransformType transformsType,
SkPath::FillType fill);
- static inline int PathTransformSize(PathTransformType type) {
- switch (type) {
- case kNone_PathTransformType:
- return 0;
- case kTranslateX_PathTransformType:
- case kTranslateY_PathTransformType:
- return 1;
- case kTranslate_PathTransformType:
- return 2;
- case kAffine_PathTransformType:
- return 6;
-
- default:
- SkFAIL("Unknown path transform type");
- return 0;
- }
- }
-
/**
* Helper function for drawing rects. It performs a geometry src push and pop
* and thus will finalize any reserved geometry.
diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp
index 0b49e7445a..74df26002d 100644
--- a/src/gpu/GrGpu.cpp
+++ b/src/gpu/GrGpu.cpp
@@ -215,13 +215,12 @@ GrIndexBuffer* GrGpu::createIndexBuffer(size_t size, bool dynamic) {
GrPath* GrGpu::createPath(const SkPath& path, const SkStrokeRec& stroke) {
SkASSERT(this->caps()->pathRenderingSupport());
this->handleDirtyContext();
- return this->onCreatePath(path, stroke);
+ return this->pathRendering()->createPath(path, stroke);
}
GrPathRange* GrGpu::createPathRange(size_t size, const SkStrokeRec& stroke) {
- SkASSERT(this->caps()->pathRenderingSupport());
this->handleDirtyContext();
- return this->onCreatePathRange(size, stroke);
+ return this->pathRendering()->createPathRange(size, stroke);
}
void GrGpu::clear(const SkIRect* rect,
@@ -407,7 +406,7 @@ void GrGpu::onStencilPath(const GrPath* path, SkPath::FillType fill) {
return;
}
- this->onGpuStencilPath(path, fill);
+ this->pathRendering()->stencilPath(path, fill);
}
@@ -422,7 +421,7 @@ void GrGpu::onDrawPath(const GrPath* path, SkPath::FillType fill,
return;
}
- this->onGpuDrawPath(path, fill);
+ this->pathRendering()->drawPath(path, fill);
}
void GrGpu::onDrawPaths(const GrPathRange* pathRange,
@@ -438,7 +437,7 @@ void GrGpu::onDrawPaths(const GrPathRange* pathRange,
return;
}
- this->onGpuDrawPaths(pathRange, indices, count, transforms, transformsType, fill);
+ this->pathRendering()->drawPaths(pathRange, indices, count, transforms, transformsType, fill);
}
void GrGpu::finalizeReservedVertices() {
diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h
index b752f7c09c..5020bddb39 100644
--- a/src/gpu/GrGpu.h
+++ b/src/gpu/GrGpu.h
@@ -10,6 +10,7 @@
#include "GrDrawTarget.h"
#include "GrClipMaskManager.h"
+#include "GrPathRendering.h"
#include "SkPath.h"
class GrContext;
@@ -54,6 +55,10 @@ public:
GrContext* getContext() { return this->INHERITED::getContext(); }
const GrContext* getContext() const { return this->INHERITED::getContext(); }
+ GrPathRendering* pathRendering() {
+ return fPathRendering.get();
+ }
+
/**
* The GrGpu object normally assumes that no outsider is setting state
* within the underlying 3D API's context/device/whatever. This call informs
@@ -410,6 +415,8 @@ protected:
void finalizeReservedVertices();
void finalizeReservedIndices();
+ SkAutoTDelete<GrPathRendering> fPathRendering;
+
private:
// GrDrawTarget overrides
virtual bool onReserveVertexSpace(size_t vertexSize, int vertexCount, void** vertices) SK_OVERRIDE;
@@ -438,8 +445,6 @@ private:
virtual GrRenderTarget* onWrapBackendRenderTarget(const GrBackendRenderTargetDesc&) = 0;
virtual GrVertexBuffer* onCreateVertexBuffer(size_t size, bool dynamic) = 0;
virtual GrIndexBuffer* onCreateIndexBuffer(size_t size, bool dynamic) = 0;
- virtual GrPath* onCreatePath(const SkPath& path, const SkStrokeRec&) = 0;
- virtual GrPathRange* onCreatePathRange(size_t size, const SkStrokeRec&) = 0;
// overridden by backend-specific derived class to perform the clear and
// clearRect. NULL rect means clear whole target. If canIgnoreRect is
@@ -449,14 +454,6 @@ private:
// overridden by backend-specific derived class to perform the draw call.
virtual void onGpuDraw(const DrawInfo&) = 0;
- // overridden by backend-specific derived class to perform the path stenciling.
- virtual void onGpuStencilPath(const GrPath*, SkPath::FillType) = 0;
- virtual void onGpuDrawPath(const GrPath*, SkPath::FillType) = 0;
- virtual void onGpuDrawPaths(const GrPathRange*,
- const uint32_t indices[], int count,
- const float transforms[], PathTransformType,
- SkPath::FillType) = 0;
-
// overridden by backend-specific derived class to perform the read pixels.
virtual bool onReadPixels(GrRenderTarget* target,
int left, int top, int width, int height,
diff --git a/src/gpu/GrInOrderDrawBuffer.cpp b/src/gpu/GrInOrderDrawBuffer.cpp
index 6d0bbd11c0..9df54a8076 100644
--- a/src/gpu/GrInOrderDrawBuffer.cpp
+++ b/src/gpu/GrInOrderDrawBuffer.cpp
@@ -430,7 +430,7 @@ void GrInOrderDrawBuffer::onDrawPaths(const GrPathRange* pathRange,
memcpy(dp->fIndices, indices, sizeof(uint32_t) * count);
dp->fCount = count;
- const int transformsLength = PathTransformSize(transformsType) * count;
+ const int transformsLength = GrPathRendering::PathTransformSize(transformsType) * count;
dp->fTransforms = SkNEW_ARRAY(float, transformsLength);
memcpy(dp->fTransforms, transforms, sizeof(float) * transformsLength);
dp->fTransformsType = transformsType;
diff --git a/src/gpu/GrPathRendering.h b/src/gpu/GrPathRendering.h
new file mode 100644
index 0000000000..863da270c7
--- /dev/null
+++ b/src/gpu/GrPathRendering.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrPathRendering_DEFINED
+#define GrPathRendering_DEFINED
+
+#include "SkPath.h"
+
+class SkStrokeRec;
+class GrPath;
+class GrPathRange;
+class GrGpu;
+
+/**
+ * Abstract class wrapping HW path rendering API.
+ *
+ * The subclasses of this class use the possible HW API to render paths (as opposed to path
+ * rendering implemented in Skia on top of a "3d" HW API).
+ * The subclasses hold the global state needed to render paths, including shadow of the global HW
+ * API state. Similar to GrGpu.
+ *
+ * It is expected that the lifetimes of GrGpuXX and GrXXPathRendering are the same. The call context
+ * interface (eg. * the concrete instance of GrGpu subclass) should be provided to the instance
+ * during construction.
+ */
+class GrPathRendering {
+public:
+ virtual ~GrPathRendering() { }
+
+ enum PathTransformType {
+ kNone_PathTransformType, //!< []
+ kTranslateX_PathTransformType, //!< [kMTransX]
+ kTranslateY_PathTransformType, //!< [kMTransY]
+ kTranslate_PathTransformType, //!< [kMTransX, kMTransY]
+ kAffine_PathTransformType, //!< [kMScaleX, kMSkewX, kMTransX, kMSkewY, kMScaleY, kMTransY]
+
+ kLast_PathTransformType = kAffine_PathTransformType
+ };
+
+ static inline int PathTransformSize(PathTransformType type) {
+ switch (type) {
+ case kNone_PathTransformType:
+ return 0;
+ case kTranslateX_PathTransformType:
+ case kTranslateY_PathTransformType:
+ return 1;
+ case kTranslate_PathTransformType:
+ return 2;
+ case kAffine_PathTransformType:
+ return 6;
+
+ default:
+ SkFAIL("Unknown path transform type");
+ return 0;
+ }
+ }
+
+ virtual GrPath* createPath(const SkPath&, const SkStrokeRec&) = 0;
+ virtual GrPathRange* createPathRange(size_t size, const SkStrokeRec&) = 0;
+ virtual void stencilPath(const GrPath*, SkPath::FillType) = 0;
+ virtual void drawPath(const GrPath*, SkPath::FillType) = 0;
+ virtual void drawPaths(const GrPathRange*, const uint32_t indices[], int count,
+ const float transforms[], PathTransformType, SkPath::FillType) = 0;
+protected:
+ GrPathRendering() { }
+
+private:
+ GrPathRendering& operator=(const GrPathRendering&);
+};
+
+#endif
diff --git a/src/gpu/GrStencilAndCoverTextContext.cpp b/src/gpu/GrStencilAndCoverTextContext.cpp
index ff7c23ef23..af4ba64343 100644
--- a/src/gpu/GrStencilAndCoverTextContext.cpp
+++ b/src/gpu/GrStencilAndCoverTextContext.cpp
@@ -155,7 +155,7 @@ void GrStencilAndCoverTextContext::drawText(const GrPaint& paint,
SkAutoGlyphCache autoCache(fSkPaint, &fDeviceProperties, glyphCacheTransform);
fGlyphCache = autoCache.getCache();
fGlyphs = GlyphPathRange::Create(fContext, fGlyphCache, fStroke);
- fTransformType = GrDrawTarget::kTranslate_PathTransformType;
+ fTransformType = GrPathRendering::kTranslate_PathTransformType;
const char* stop = text + byteLength;
@@ -243,7 +243,7 @@ void GrStencilAndCoverTextContext::drawPosText(const GrPaint& paint,
if (SkPaint::kLeft_Align == fSkPaint.getTextAlign()) {
if (1 == scalarsPerPosition) {
- fTransformType = GrDrawTarget::kTranslateX_PathTransformType;
+ fTransformType = GrPathRendering::kTranslateX_PathTransformType;
while (text < stop) {
const SkGlyph& glyph = glyphCacheProc(fGlyphCache, &text, 0, 0);
if (glyph.fWidth) {
@@ -253,7 +253,7 @@ void GrStencilAndCoverTextContext::drawPosText(const GrPaint& paint,
}
} else {
SkASSERT(2 == scalarsPerPosition);
- fTransformType = GrDrawTarget::kTranslate_PathTransformType;
+ fTransformType = GrPathRendering::kTranslate_PathTransformType;
while (text < stop) {
const SkGlyph& glyph = glyphCacheProc(fGlyphCache, &text, 0, 0);
if (glyph.fWidth) {
@@ -263,7 +263,7 @@ void GrStencilAndCoverTextContext::drawPosText(const GrPaint& paint,
}
}
} else {
- fTransformType = GrDrawTarget::kTranslate_PathTransformType;
+ fTransformType = GrPathRendering::kTranslate_PathTransformType;
SkTextMapStateProc tmsProc(SkMatrix::I(), 0, scalarsPerPosition);
SkTextAlignProcScalar alignProc(fSkPaint.getTextAlign());
while (text < stop) {
@@ -396,7 +396,7 @@ void GrStencilAndCoverTextContext::init(const GrPaint& paint,
}
inline void GrStencilAndCoverTextContext::appendGlyph(uint16_t glyphID, float x) {
- SkASSERT(GrDrawTarget::kTranslateX_PathTransformType == fTransformType);
+ SkASSERT(GrPathRendering::kTranslateX_PathTransformType == fTransformType);
if (fPendingGlyphCount >= kGlyphBufferSize) {
this->flush();
@@ -411,7 +411,7 @@ inline void GrStencilAndCoverTextContext::appendGlyph(uint16_t glyphID, float x)
}
inline void GrStencilAndCoverTextContext::appendGlyph(uint16_t glyphID, float x, float y) {
- SkASSERT(GrDrawTarget::kTranslate_PathTransformType == fTransformType);
+ SkASSERT(GrPathRendering::kTranslate_PathTransformType == fTransformType);
if (fPendingGlyphCount >= kGlyphBufferSize) {
this->flush();
diff --git a/src/gpu/gl/GrGLPath.cpp b/src/gpu/gl/GrGLPath.cpp
index 6f158cdea9..930ec4a8f6 100644
--- a/src/gpu/gl/GrGLPath.cpp
+++ b/src/gpu/gl/GrGLPath.cpp
@@ -85,7 +85,7 @@ void GrGLPath::InitPathObject(GrGpuGL* gpu,
GrGLuint pathID,
const SkPath& skPath,
const SkStrokeRec& stroke) {
- GrGLPathRendering* pr = gpu->pathRendering();
+ GrGLPathRendering* pr = gpu->glPathRendering();
SkSTArray<16, GrGLubyte, true> pathCommands;
SkSTArray<16, SkPoint, true> pathPoints;
@@ -121,7 +121,7 @@ void GrGLPath::InitPathObject(GrGpuGL* gpu,
GrGLPath::GrGLPath(GrGpuGL* gpu, const SkPath& path, const SkStrokeRec& stroke)
: INHERITED(gpu, kIsWrapped, path, stroke),
- fPathID(gpu->pathRendering()->genPaths(1)) {
+ fPathID(gpu->glPathRendering()->genPaths(1)) {
SkASSERT(!path.isEmpty());
InitPathObject(gpu, fPathID, fSkPath, stroke);
@@ -138,7 +138,7 @@ GrGLPath::~GrGLPath() {
void GrGLPath::onRelease() {
if (0 != fPathID && !this->isWrapped()) {
- static_cast<GrGpuGL*>(this->getGpu())->pathRendering()->deletePaths(fPathID, 1);
+ static_cast<GrGpuGL*>(this->getGpu())->glPathRendering()->deletePaths(fPathID, 1);
fPathID = 0;
}
diff --git a/src/gpu/gl/GrGLPathRange.cpp b/src/gpu/gl/GrGLPathRange.cpp
index 5e89cb5d87..9aaf9db26b 100644
--- a/src/gpu/gl/GrGLPathRange.cpp
+++ b/src/gpu/gl/GrGLPathRange.cpp
@@ -13,7 +13,7 @@
GrGLPathRange::GrGLPathRange(GrGpuGL* gpu, size_t size, const SkStrokeRec& stroke)
: INHERITED(gpu, size, stroke),
- fBasePathID(gpu->pathRendering()->genPaths(fSize)),
+ fBasePathID(gpu->glPathRendering()->genPaths(fSize)),
fNumDefinedPaths(0) {
}
@@ -28,7 +28,7 @@ void GrGLPathRange::initAt(size_t index, const SkPath& skPath) {
}
// Make sure the path at this index hasn't been initted already.
- SkASSERT(GR_GL_FALSE == gpu->pathRendering()->isPath(fBasePathID + index));
+ SkASSERT(GR_GL_FALSE == gpu->glPathRendering()->isPath(fBasePathID + index));
GrGLPath::InitPathObject(gpu, fBasePathID + index, skPath, fStroke);
++fNumDefinedPaths;
@@ -39,7 +39,7 @@ void GrGLPathRange::onRelease() {
SkASSERT(NULL != this->getGpu());
if (0 != fBasePathID && !this->isWrapped()) {
- static_cast<GrGpuGL*>(this->getGpu())->pathRendering()->deletePaths(fBasePathID, fSize);
+ static_cast<GrGpuGL*>(this->getGpu())->glPathRendering()->deletePaths(fBasePathID, fSize);
fBasePathID = 0;
}
diff --git a/src/gpu/gl/GrGLPathRendering.cpp b/src/gpu/gl/GrGLPathRendering.cpp
index 249d98139a..53d7cf0074 100644
--- a/src/gpu/gl/GrGLPathRendering.cpp
+++ b/src/gpu/gl/GrGLPathRendering.cpp
@@ -6,17 +6,49 @@
*/
#include "gl/GrGLPathRendering.h"
-#include "gl/GrGLInterface.h"
#include "gl/GrGLNameAllocator.h"
#include "gl/GrGLUtil.h"
+#include "gl/GrGpuGL.h"
-#define GL_CALL(X) GR_GL_CALL(fGLInterface.get(), X)
-#define GL_CALL_RET(RET, X) GR_GL_CALL_RET(fGLInterface.get(), RET, X)
+#include "GrGLPath.h"
+#include "GrGLPathRange.h"
+#include "GrGLPathRendering.h"
+
+#define GL_CALL(X) GR_GL_CALL(fGpu->glInterface(), X)
+#define GL_CALL_RET(RET, X) GR_GL_CALL_RET(fGpu->glInterface(), RET, X)
+
+
+static const GrGLenum gXformType2GLType[] = {
+ GR_GL_NONE,
+ GR_GL_TRANSLATE_X,
+ GR_GL_TRANSLATE_Y,
+ GR_GL_TRANSLATE_2D,
+ GR_GL_TRANSPOSE_AFFINE_2D
+};
+
+GR_STATIC_ASSERT(0 == GrPathRendering::kNone_PathTransformType);
+GR_STATIC_ASSERT(1 == GrPathRendering::kTranslateX_PathTransformType);
+GR_STATIC_ASSERT(2 == GrPathRendering::kTranslateY_PathTransformType);
+GR_STATIC_ASSERT(3 == GrPathRendering::kTranslate_PathTransformType);
+GR_STATIC_ASSERT(4 == GrPathRendering::kAffine_PathTransformType);
+GR_STATIC_ASSERT(GrPathRendering::kAffine_PathTransformType == GrPathRendering::kLast_PathTransformType);
+
+static GrGLenum gr_stencil_op_to_gl_path_rendering_fill_mode(GrStencilOp op) {
+ switch (op) {
+ default:
+ SkFAIL("Unexpected path fill.");
+ /* fallthrough */;
+ case kIncClamp_StencilOp:
+ return GR_GL_COUNT_UP;
+ case kInvert_StencilOp:
+ return GR_GL_INVERT;
+ }
+}
class GrGLPathRenderingV12 : public GrGLPathRendering {
public:
- GrGLPathRenderingV12(const GrGLInterface* glInterface)
- : GrGLPathRendering(glInterface) {
+ GrGLPathRenderingV12(GrGpuGL* gpu)
+ : GrGLPathRendering(gpu) {
}
virtual GrGLvoid stencilThenCoverFillPath(GrGLuint path, GrGLenum fillMode,
@@ -35,8 +67,8 @@ public:
class GrGLPathRenderingV13 : public GrGLPathRenderingV12 {
public:
- GrGLPathRenderingV13(const GrGLInterface* glInterface)
- : GrGLPathRenderingV12(glInterface) {
+ GrGLPathRenderingV13(GrGpuGL* gpu)
+ : GrGLPathRenderingV12(gpu) {
fCaps.fragmentInputGenSupport = true;
}
@@ -46,24 +78,26 @@ public:
};
-GrGLPathRendering* GrGLPathRendering::Create(const GrGLInterface* glInterface) {
+GrGLPathRendering* GrGLPathRendering::Create(GrGpuGL* gpu) {
+ const GrGLInterface* glInterface = gpu->glInterface();
if (NULL == glInterface->fFunctions.fStencilThenCoverFillPath ||
NULL == glInterface->fFunctions.fStencilThenCoverStrokePath ||
NULL == glInterface->fFunctions.fStencilThenCoverFillPathInstanced ||
NULL == glInterface->fFunctions.fStencilThenCoverStrokePathInstanced) {
- return new GrGLPathRendering(glInterface);
+ return new GrGLPathRendering(gpu);
}
if (NULL == glInterface->fFunctions.fProgramPathFragmentInputGen) {
- return new GrGLPathRenderingV12(glInterface);
+ return new GrGLPathRenderingV12(gpu);
}
- return new GrGLPathRenderingV13(glInterface);
+ return new GrGLPathRenderingV13(gpu);
}
-GrGLPathRendering::GrGLPathRendering(const GrGLInterface* glInterface)
- : fGLInterface(SkRef(glInterface)) {
+GrGLPathRendering::GrGLPathRendering(GrGpuGL* gpu)
+ : fGpu(gpu) {
memset(&fCaps, 0, sizeof(fCaps));
+ fHWPathTexGenSettings.reset(fGpu->glCaps().maxFixedFunctionTextureCoords());
}
GrGLPathRendering::~GrGLPathRendering() {
@@ -73,6 +107,281 @@ void GrGLPathRendering::abandonGpuResources() {
fPathNameAllocator.reset(NULL);
}
+void GrGLPathRendering::resetContext() {
+ fHWProjectionMatrixState.invalidate();
+ // we don't use the model view matrix.
+ GL_CALL(MatrixLoadIdentity(GR_GL_MODELVIEW));
+
+ for (int i = 0; i < fGpu->glCaps().maxFixedFunctionTextureCoords(); ++i) {
+ this->pathTexGen(GR_GL_TEXTURE0 + i, GR_GL_NONE, 0, NULL);
+ fHWPathTexGenSettings[i].fMode = GR_GL_NONE;
+ fHWPathTexGenSettings[i].fNumComponents = 0;
+ }
+ fHWActivePathTexGenSets = 0;
+ fHWPathStencilSettings.invalidate();
+}
+
+GrPath* GrGLPathRendering::createPath(const SkPath& inPath, const SkStrokeRec& stroke) {
+ return SkNEW_ARGS(GrGLPath, (fGpu, inPath, stroke));
+}
+
+GrPathRange* GrGLPathRendering::createPathRange(size_t size, const SkStrokeRec& stroke) {
+ return SkNEW_ARGS(GrGLPathRange, (fGpu, size, stroke));
+}
+
+void GrGLPathRendering::enablePathTexGen(int unitIdx, PathTexGenComponents components,
+ const GrGLfloat* coefficients) {
+ SkASSERT(components >= kS_PathTexGenComponents &&
+ components <= kSTR_PathTexGenComponents);
+ SkASSERT(fGpu->glCaps().maxFixedFunctionTextureCoords() >= unitIdx);
+
+ if (GR_GL_OBJECT_LINEAR == fHWPathTexGenSettings[unitIdx].fMode &&
+ components == fHWPathTexGenSettings[unitIdx].fNumComponents &&
+ !memcmp(coefficients, fHWPathTexGenSettings[unitIdx].fCoefficients,
+ 3 * components * sizeof(GrGLfloat))) {
+ return;
+ }
+
+ fGpu->setTextureUnit(unitIdx);
+
+ fHWPathTexGenSettings[unitIdx].fNumComponents = components;
+ this->pathTexGen(GR_GL_TEXTURE0 + unitIdx, GR_GL_OBJECT_LINEAR, components, coefficients);
+
+ memcpy(fHWPathTexGenSettings[unitIdx].fCoefficients, coefficients,
+ 3 * components * sizeof(GrGLfloat));
+}
+
+void GrGLPathRendering::enablePathTexGen(int unitIdx, PathTexGenComponents components,
+ const SkMatrix& matrix) {
+ GrGLfloat coefficients[3 * 3];
+ SkASSERT(components >= kS_PathTexGenComponents &&
+ components <= kSTR_PathTexGenComponents);
+
+ coefficients[0] = SkScalarToFloat(matrix[SkMatrix::kMScaleX]);
+ coefficients[1] = SkScalarToFloat(matrix[SkMatrix::kMSkewX]);
+ coefficients[2] = SkScalarToFloat(matrix[SkMatrix::kMTransX]);
+
+ if (components >= kST_PathTexGenComponents) {
+ coefficients[3] = SkScalarToFloat(matrix[SkMatrix::kMSkewY]);
+ coefficients[4] = SkScalarToFloat(matrix[SkMatrix::kMScaleY]);
+ coefficients[5] = SkScalarToFloat(matrix[SkMatrix::kMTransY]);
+ }
+
+ if (components >= kSTR_PathTexGenComponents) {
+ coefficients[6] = SkScalarToFloat(matrix[SkMatrix::kMPersp0]);
+ coefficients[7] = SkScalarToFloat(matrix[SkMatrix::kMPersp1]);
+ coefficients[8] = SkScalarToFloat(matrix[SkMatrix::kMPersp2]);
+ }
+
+ this->enablePathTexGen(unitIdx, components, coefficients);
+}
+
+void GrGLPathRendering::flushPathTexGenSettings(int numUsedTexCoordSets) {
+ SkASSERT(fGpu->glCaps().maxFixedFunctionTextureCoords() >= numUsedTexCoordSets);
+
+ // Only write the inactive path tex gens, since active path tex gens were
+ // written when they were enabled.
+
+ SkDEBUGCODE(
+ for (int i = 0; i < numUsedTexCoordSets; i++) {
+ SkASSERT(0 != fHWPathTexGenSettings[i].fNumComponents);
+ }
+ );
+
+ for (int i = numUsedTexCoordSets; i < fHWActivePathTexGenSets; i++) {
+ SkASSERT(0 != fHWPathTexGenSettings[i].fNumComponents);
+
+ fGpu->setTextureUnit(i);
+ GL_CALL(PathTexGen(GR_GL_TEXTURE0 + i, GR_GL_NONE, 0, NULL));
+ fHWPathTexGenSettings[i].fNumComponents = 0;
+ }
+
+ fHWActivePathTexGenSets = numUsedTexCoordSets;
+}
+
+void GrGLPathRendering::stencilPath(const GrPath* path, SkPath::FillType fill) {
+ GrGLuint id = static_cast<const GrGLPath*>(path)->pathID();
+ SkASSERT(NULL != fGpu->drawState()->getRenderTarget());
+ SkASSERT(NULL != fGpu->drawState()->getRenderTarget()->getStencilBuffer());
+
+ this->flushPathStencilSettings(fill);
+ SkASSERT(!fHWPathStencilSettings.isTwoSided());
+
+ GrGLenum fillMode =
+ gr_stencil_op_to_gl_path_rendering_fill_mode(fHWPathStencilSettings.passOp(GrStencilSettings::kFront_Face));
+ GrGLint writeMask = fHWPathStencilSettings.writeMask(GrStencilSettings::kFront_Face);
+ this->stencilFillPath(id, fillMode, writeMask);
+}
+
+void GrGLPathRendering::drawPath(const GrPath* path, SkPath::FillType fill) {
+ GrGLuint id = static_cast<const GrGLPath*>(path)->pathID();
+ SkASSERT(NULL != fGpu->drawState()->getRenderTarget());
+ SkASSERT(NULL != fGpu->drawState()->getRenderTarget()->getStencilBuffer());
+ SkASSERT(!fGpu->fCurrentProgram->hasVertexShader());
+
+ this->flushPathStencilSettings(fill);
+ SkASSERT(!fHWPathStencilSettings.isTwoSided());
+
+ const SkStrokeRec& stroke = path->getStroke();
+
+ SkPath::FillType nonInvertedFill = SkPath::ConvertToNonInverseFillType(fill);
+
+ GrGLenum fillMode =
+ gr_stencil_op_to_gl_path_rendering_fill_mode(fHWPathStencilSettings.passOp(GrStencilSettings::kFront_Face));
+ GrGLint writeMask = fHWPathStencilSettings.writeMask(GrStencilSettings::kFront_Face);
+
+ if (nonInvertedFill == fill) {
+ if (stroke.needToApply()) {
+ if (SkStrokeRec::kStrokeAndFill_Style == stroke.getStyle()) {
+ this->stencilFillPath(id, fillMode, writeMask);
+ }
+ this->stencilThenCoverStrokePath(id, 0xffff, writeMask, GR_GL_BOUNDING_BOX);
+ } else {
+ this->stencilThenCoverFillPath(id, fillMode, writeMask, GR_GL_BOUNDING_BOX);
+ }
+ } else {
+ if (stroke.isFillStyle() || SkStrokeRec::kStrokeAndFill_Style == stroke.getStyle()) {
+ this->stencilFillPath(id, fillMode, writeMask);
+ }
+ if (stroke.needToApply()) {
+ this->stencilStrokePath(id, 0xffff, writeMask);
+ }
+
+ GrDrawState* drawState = fGpu->drawState();
+ GrDrawState::AutoViewMatrixRestore avmr;
+ SkRect bounds = SkRect::MakeLTRB(0, 0,
+ SkIntToScalar(drawState->getRenderTarget()->width()),
+ SkIntToScalar(drawState->getRenderTarget()->height()));
+ SkMatrix vmi;
+ // mapRect through persp matrix may not be correct
+ if (!drawState->getViewMatrix().hasPerspective() && drawState->getViewInverse(&vmi)) {
+ vmi.mapRect(&bounds);
+ // theoretically could set bloat = 0, instead leave it because of matrix inversion
+ // precision.
+ SkScalar bloat = drawState->getViewMatrix().getMaxScale() * SK_ScalarHalf;
+ bounds.outset(bloat, bloat);
+ } else {
+ avmr.setIdentity(drawState);
+ }
+
+ fGpu->drawSimpleRect(bounds);
+ }
+}
+
+void GrGLPathRendering::drawPaths(const GrPathRange* pathRange, const uint32_t indices[], int count,
+ const float transforms[], PathTransformType transformsType,
+ SkPath::FillType fill) {
+ SkASSERT(fGpu->caps()->pathRenderingSupport());
+ SkASSERT(NULL != fGpu->drawState()->getRenderTarget());
+ SkASSERT(NULL != fGpu->drawState()->getRenderTarget()->getStencilBuffer());
+ SkASSERT(!fGpu->fCurrentProgram->hasVertexShader());
+
+ GrGLuint baseID = static_cast<const GrGLPathRange*>(pathRange)->basePathID();
+
+ this->flushPathStencilSettings(fill);
+ SkASSERT(!fHWPathStencilSettings.isTwoSided());
+
+ const SkStrokeRec& stroke = pathRange->getStroke();
+
+ SkPath::FillType nonInvertedFill =
+ SkPath::ConvertToNonInverseFillType(fill);
+
+ GrGLenum fillMode =
+ gr_stencil_op_to_gl_path_rendering_fill_mode(
+ fHWPathStencilSettings.passOp(GrStencilSettings::kFront_Face));
+ GrGLint writeMask =
+ fHWPathStencilSettings.writeMask(GrStencilSettings::kFront_Face);
+
+ if (nonInvertedFill == fill) {
+ if (stroke.needToApply()) {
+ if (SkStrokeRec::kStrokeAndFill_Style == stroke.getStyle()) {
+ this->stencilFillPathInstanced(
+ count, GR_GL_UNSIGNED_INT, indices, baseID, fillMode,
+ writeMask, gXformType2GLType[transformsType],
+ transforms);
+ }
+ this->stencilThenCoverStrokePathInstanced(
+ count, GR_GL_UNSIGNED_INT, indices, baseID, 0xffff, writeMask,
+ GR_GL_BOUNDING_BOX_OF_BOUNDING_BOXES,
+ gXformType2GLType[transformsType], transforms);
+ } else {
+ this->stencilThenCoverFillPathInstanced(
+ count, GR_GL_UNSIGNED_INT, indices, baseID, fillMode, writeMask,
+ GR_GL_BOUNDING_BOX_OF_BOUNDING_BOXES,
+ gXformType2GLType[transformsType], transforms);
+ }
+ } else {
+ if (stroke.isFillStyle() || SkStrokeRec::kStrokeAndFill_Style == stroke.getStyle()) {
+ this->stencilFillPathInstanced(
+ count, GR_GL_UNSIGNED_INT, indices, baseID, fillMode,
+ writeMask, gXformType2GLType[transformsType],
+ transforms);
+ }
+ if (stroke.needToApply()) {
+ this->stencilStrokePathInstanced(
+ count, GR_GL_UNSIGNED_INT, indices, baseID, 0xffff,
+ writeMask, gXformType2GLType[transformsType],
+ transforms);
+ }
+
+ GrDrawState* drawState = fGpu->drawState();
+ GrDrawState::AutoViewMatrixRestore avmr;
+ SkRect bounds = SkRect::MakeLTRB(0, 0,
+ SkIntToScalar(drawState->getRenderTarget()->width()),
+ SkIntToScalar(drawState->getRenderTarget()->height()));
+ SkMatrix vmi;
+ // mapRect through persp matrix may not be correct
+ if (!drawState->getViewMatrix().hasPerspective() && drawState->getViewInverse(&vmi)) {
+ vmi.mapRect(&bounds);
+ // theoretically could set bloat = 0, instead leave it because of matrix inversion
+ // precision.
+ SkScalar bloat = drawState->getViewMatrix().getMaxScale() * SK_ScalarHalf;
+ bounds.outset(bloat, bloat);
+ } else {
+ avmr.setIdentity(drawState);
+ }
+
+ fGpu->drawSimpleRect(bounds);
+ }
+}
+
+void GrGLPathRendering::flushPathStencilSettings(SkPath::FillType fill) {
+ GrStencilSettings pathStencilSettings;
+ fGpu->getPathStencilSettingsForFillType(fill, &pathStencilSettings);
+ if (fHWPathStencilSettings != pathStencilSettings) {
+ // Just the func, ref, and mask is set here. The op and write mask are params to the call
+ // that draws the path to the SB (glStencilFillPath)
+ GrGLenum func =
+ GrToGLStencilFunc(pathStencilSettings.func(GrStencilSettings::kFront_Face));
+ this->pathStencilFunc(func, pathStencilSettings.funcRef(GrStencilSettings::kFront_Face),
+ pathStencilSettings.funcMask(GrStencilSettings::kFront_Face));
+
+ fHWPathStencilSettings = pathStencilSettings;
+ }
+}
+
+void GrGLPathRendering::setProjectionMatrix(const SkMatrix& matrix,
+ const SkISize& renderTargetSize,
+ GrSurfaceOrigin renderTargetOrigin) {
+
+ SkASSERT(fGpu->glCaps().pathRenderingSupport());
+
+ if (renderTargetOrigin == fHWProjectionMatrixState.fRenderTargetOrigin &&
+ renderTargetSize == fHWProjectionMatrixState.fRenderTargetSize &&
+ matrix.cheapEqualTo(fHWProjectionMatrixState.fViewMatrix)) {
+ return;
+ }
+
+ fHWProjectionMatrixState.fViewMatrix = matrix;
+ fHWProjectionMatrixState.fRenderTargetSize = renderTargetSize;
+ fHWProjectionMatrixState.fRenderTargetOrigin = renderTargetOrigin;
+
+ GrGLfloat glMatrix[4 * 4];
+ fHWProjectionMatrixState.getRTAdjustedGLMatrix<4>(glMatrix);
+ GL_CALL(MatrixLoadf(GR_GL_PROJECTION, glMatrix));
+}
+
+
// NV_path_rendering
GrGLuint GrGLPathRendering::genPaths(GrGLsizei range) {
@@ -156,6 +465,7 @@ GrGLvoid GrGLPathRendering::pathStencilFunc(GrGLenum func, GrGLint ref, GrGLuint
}
GrGLvoid GrGLPathRendering::stencilFillPath(GrGLuint path, GrGLenum fillMode, GrGLuint mask) {
+ // Decide how to manipulate the stencil buffer based on the fill rule.
GL_CALL(StencilFillPath(path, fillMode, mask));
}
diff --git a/src/gpu/gl/GrGLPathRendering.h b/src/gpu/gl/GrGLPathRendering.h
index 53b8750356..e16f0591a7 100644
--- a/src/gpu/gl/GrGLPathRendering.h
+++ b/src/gpu/gl/GrGLPathRendering.h
@@ -9,28 +9,40 @@
#define GrGLPathRendering_DEFINED
#include "SkRefCnt.h"
+#include "GrPathRendering.h"
+#include "GrStencil.h"
#include "gl/GrGLFunctions.h"
+#include "gl/GrGLProgram.h"
class GrGLNameAllocator;
-struct GrGLInterface;
+class GrGpuGL;
/**
* This class wraps the NV_path_rendering extension and manages its various
- * API versions. If a method is not present in the GrGLInterface (because the
- * driver version is old), it tries to provide a backup implementation. But if
- * a backup implementation is not practical, it marks the method as not
- * supported.
+ * API versions. If a method is not present in the GrGLInterface of the GrGpuGL
+ * (because the driver version is old), it tries to provide a backup
+ * implementation. But if a backup implementation is not practical, it marks the
+ * method as not supported.
*/
-class GrGLPathRendering {
+class GrGLPathRendering : public GrPathRendering {
public:
/**
- * Create a new GrGLPathRendering object from a given GL interface. Unless
+ * Create a new GrGLPathRendering object from a given GrGpuGL. Unless
* otherwise specified in the caps, every method will work properly, even
- * if it did not exist in the GL interface.
+ * if it did not exist in the GL interface of the gpu.
*/
- static GrGLPathRendering* Create(const GrGLInterface*);
+ static GrGLPathRendering* Create(GrGpuGL* gpu);
virtual ~GrGLPathRendering();
+ // GrPathRendering implementations.
+ virtual GrPath* createPath(const SkPath&, const SkStrokeRec&) SK_OVERRIDE;
+ virtual GrPathRange* createPathRange(size_t size, const SkStrokeRec&) SK_OVERRIDE;
+ virtual void stencilPath(const GrPath*, SkPath::FillType) SK_OVERRIDE;
+ virtual void drawPath(const GrPath*, SkPath::FillType) SK_OVERRIDE;
+ virtual void drawPaths(const GrPathRange*, const uint32_t indices[], int count,
+ const float transforms[], PathTransformType,
+ SkPath::FillType) SK_OVERRIDE;
+
/**
* Mark certain functionality as not supported if the driver version is too
* old and a backup implementation is not practical.
@@ -40,12 +52,29 @@ public:
};
const Caps& caps() const { return fCaps; }
+
+ /* Called when the 3D context state is unknown. */
+ void resetContext();
+
/**
* Called when the GPU resources have been lost and need to be abandoned
* (for example after a context loss).
*/
void abandonGpuResources();
+ enum PathTexGenComponents {
+ kS_PathTexGenComponents = 1,
+ kST_PathTexGenComponents = 2,
+ kSTR_PathTexGenComponents = 3
+ };
+ void enablePathTexGen(int unitIdx, PathTexGenComponents, const GrGLfloat* coefficients);
+ void enablePathTexGen(int unitIdx, PathTexGenComponents, const SkMatrix& matrix);
+ void flushPathTexGenSettings(int numUsedTexCoordSets);
+ void setProjectionMatrix(const SkMatrix& matrix,
+ const SkISize& renderTargetSize,
+ GrSurfaceOrigin renderTargetOrigin);
+
+
// NV_path_rendering
GrGLuint genPaths(GrGLsizei range);
GrGLvoid deletePaths(GrGLuint path, GrGLsizei range);
@@ -98,11 +127,24 @@ public:
const GrGLfloat *coeffs);
protected:
- GrGLPathRendering(const GrGLInterface*);
+ GrGLPathRendering(GrGpuGL* gpu);
- SkAutoTUnref<const GrGLInterface> fGLInterface;
+ GrGpuGL* fGpu;
SkAutoTDelete<GrGLNameAllocator> fPathNameAllocator;
Caps fCaps;
+ GrGLProgram::MatrixState fHWProjectionMatrixState;
+ GrStencilSettings fHWPathStencilSettings;
+ struct PathTexGenData {
+ GrGLenum fMode;
+ GrGLint fNumComponents;
+ GrGLfloat fCoefficients[3 * 3];
+ };
+ int fHWActivePathTexGenSets;
+ SkTArray<PathTexGenData, true> fHWPathTexGenSettings;
+
+private:
+ void flushPathStencilSettings(SkPath::FillType fill);
+
};
#endif
diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp
index 0ad7a18756..d8c751d71d 100644
--- a/src/gpu/gl/GrGLProgram.cpp
+++ b/src/gpu/gl/GrGLProgram.cpp
@@ -154,7 +154,7 @@ void GrGLProgram::setData(GrDrawState::BlendOptFlags blendOpts,
// custom shaders, it's ignored, so we don't need to change the texgen
// settings in that case.
if (!fHasVertexShader) {
- fGpu->flushPathTexGenSettings(fTexCoordSetCnt);
+ fGpu->glPathRendering()->flushPathTexGenSettings(fTexCoordSetCnt);
}
}
@@ -247,7 +247,7 @@ void GrGLProgram::setMatrixAndRenderTargetHeight(const GrDrawState& drawState) {
if (!fHasVertexShader) {
SkASSERT(!fBuiltinUniformHandles.fViewMatrixUni.isValid());
SkASSERT(!fBuiltinUniformHandles.fRTAdjustmentUni.isValid());
- fGpu->setProjectionMatrix(drawState.getViewMatrix(), size, rt->origin());
+ fGpu->glPathRendering()->setProjectionMatrix(drawState.getViewMatrix(), size, rt->origin());
} else if (fMatrixState.fRenderTargetOrigin != rt->origin() ||
fMatrixState.fRenderTargetSize != size ||
!fMatrixState.fViewMatrix.cheapEqualTo(drawState.getViewMatrix())) {
diff --git a/src/gpu/gl/GrGLProgramEffects.cpp b/src/gpu/gl/GrGLProgramEffects.cpp
index 3fa4f15ac8..8ea77d05eb 100644
--- a/src/gpu/gl/GrGLProgramEffects.cpp
+++ b/src/gpu/gl/GrGLProgramEffects.cpp
@@ -478,16 +478,18 @@ void GrGLPathTexGenProgramEffects::setPathTexGenState(GrGpuGL* gpu,
switch (get_matrix_type(totalKey, t)) {
case kNoPersp_MatrixType: {
const SkMatrix& transform = get_transform_matrix(drawEffect, t);
- gpu->enablePathTexGen(texCoordIndex++,
- GrGpuGL::kST_PathTexGenComponents,
- transform);
+ gpu->glPathRendering()->enablePathTexGen(
+ texCoordIndex++,
+ GrGLPathRendering::kST_PathTexGenComponents,
+ transform);
break;
}
case kGeneral_MatrixType: {
const SkMatrix& transform = get_transform_matrix(drawEffect, t);
- gpu->enablePathTexGen(texCoordIndex++,
- GrGpuGL::kSTR_PathTexGenComponents,
- transform);
+ gpu->glPathRendering()->enablePathTexGen(
+ texCoordIndex++,
+ GrGLPathRendering::kSTR_PathTexGenComponents,
+ transform);
break;
}
default:
diff --git a/src/gpu/gl/GrGLUtil.cpp b/src/gpu/gl/GrGLUtil.cpp
index 86a3a59e91..9bc2c5d67a 100644
--- a/src/gpu/gl/GrGLUtil.cpp
+++ b/src/gpu/gl/GrGLUtil.cpp
@@ -264,3 +264,28 @@ template<> void GrGLGetMatrix<4>(GrGLfloat* dest, const SkMatrix& src) {
dest[14] = 0;
dest[15] = SkScalarToFloat(src[SkMatrix::kMPersp2]);
}
+
+GrGLenum GrToGLStencilFunc(GrStencilFunc basicFunc) {
+ static const GrGLenum gTable[] = {
+ GR_GL_ALWAYS, // kAlways_StencilFunc
+ GR_GL_NEVER, // kNever_StencilFunc
+ GR_GL_GREATER, // kGreater_StencilFunc
+ GR_GL_GEQUAL, // kGEqual_StencilFunc
+ GR_GL_LESS, // kLess_StencilFunc
+ GR_GL_LEQUAL, // kLEqual_StencilFunc,
+ GR_GL_EQUAL, // kEqual_StencilFunc,
+ GR_GL_NOTEQUAL, // kNotEqual_StencilFunc,
+ };
+ GR_STATIC_ASSERT(SK_ARRAY_COUNT(gTable) == kBasicStencilFuncCount);
+ GR_STATIC_ASSERT(0 == kAlways_StencilFunc);
+ GR_STATIC_ASSERT(1 == kNever_StencilFunc);
+ GR_STATIC_ASSERT(2 == kGreater_StencilFunc);
+ GR_STATIC_ASSERT(3 == kGEqual_StencilFunc);
+ GR_STATIC_ASSERT(4 == kLess_StencilFunc);
+ GR_STATIC_ASSERT(5 == kLEqual_StencilFunc);
+ GR_STATIC_ASSERT(6 == kEqual_StencilFunc);
+ GR_STATIC_ASSERT(7 == kNotEqual_StencilFunc);
+ SkASSERT((unsigned) basicFunc < kBasicStencilFuncCount);
+
+ return gTable[basicFunc];
+}
diff --git a/src/gpu/gl/GrGLUtil.h b/src/gpu/gl/GrGLUtil.h
index 89d8076139..06210ee1ab 100644
--- a/src/gpu/gl/GrGLUtil.h
+++ b/src/gpu/gl/GrGLUtil.h
@@ -10,6 +10,7 @@
#include "gl/GrGLInterface.h"
#include "GrGLDefines.h"
+#include "GrStencil.h"
class SkMatrix;
@@ -181,4 +182,7 @@ template<int MatrixSize> void GrGLGetMatrix(GrGLfloat* dest, const SkMatrix& src
// call glGetError without doing a redundant error check or logging.
#define GR_GL_GET_ERROR(IFACE) (IFACE)->fFunctions.fGetError()
+GrGLenum GrToGLStencilFunc(GrStencilFunc basicFunc);
+
+
#endif
diff --git a/src/gpu/gl/GrGpuGL.cpp b/src/gpu/gl/GrGpuGL.cpp
index 7131cfa1eb..c6bd6bbe14 100644
--- a/src/gpu/gl/GrGpuGL.cpp
+++ b/src/gpu/gl/GrGpuGL.cpp
@@ -8,9 +8,6 @@
#include "GrGpuGL.h"
#include "GrGLStencilBuffer.h"
-#include "GrGLPath.h"
-#include "GrGLPathRange.h"
-#include "GrGLPathRendering.h"
#include "GrGLShaderBuilder.h"
#include "GrTemplates.h"
#include "GrTypes.h"
@@ -35,20 +32,6 @@
///////////////////////////////////////////////////////////////////////////////
-static const GrGLenum gXformType2GLType[] = {
- GR_GL_NONE,
- GR_GL_TRANSLATE_X,
- GR_GL_TRANSLATE_Y,
- GR_GL_TRANSLATE_2D,
- GR_GL_TRANSPOSE_AFFINE_2D
-};
-
-GR_STATIC_ASSERT(0 == GrDrawTarget::kNone_PathTransformType);
-GR_STATIC_ASSERT(1 == GrDrawTarget::kTranslateX_PathTransformType);
-GR_STATIC_ASSERT(2 == GrDrawTarget::kTranslateY_PathTransformType);
-GR_STATIC_ASSERT(3 == GrDrawTarget::kTranslate_PathTransformType);
-GR_STATIC_ASSERT(4 == GrDrawTarget::kAffine_PathTransformType);
-GR_STATIC_ASSERT(GrDrawTarget::kAffine_PathTransformType == GrDrawTarget::kLast_PathTransformType);
static const GrGLenum gXfermodeCoeff2Blend[] = {
GR_GL_ZERO,
@@ -137,7 +120,6 @@ GrGpuGL::GrGpuGL(const GrGLContext& ctx, GrContext* context)
fCaps.reset(SkRef(ctx.caps()));
fHWBoundTextureUniqueIDs.reset(this->glCaps().maxFragmentTextureUnits());
- fHWPathTexGenSettings.reset(this->glCaps().maxFixedFunctionTextureCoords());
GrGLClearErr(fGLContext.interface());
if (gPrintStartupSpew) {
@@ -166,7 +148,7 @@ GrGpuGL::GrGpuGL(const GrGLContext& ctx, GrContext* context)
fHWProgramID = 0;
if (this->glCaps().pathRenderingSupport()) {
- fPathRendering.reset(GrGLPathRendering::Create(glInterface()));
+ fPathRendering.reset(GrGLPathRendering::Create(this));
}
}
@@ -328,18 +310,8 @@ void GrGpuGL::onResetContext(uint32_t resetBits) {
if (resetBits & kPathRendering_GrGLBackendState) {
if (this->caps()->pathRenderingSupport()) {
- fHWProjectionMatrixState.invalidate();
- // we don't use the model view matrix.
- GL_CALL(MatrixLoadIdentity(GR_GL_MODELVIEW));
-
- for (int i = 0; i < this->glCaps().maxFixedFunctionTextureCoords(); ++i) {
- fPathRendering->pathTexGen(GR_GL_TEXTURE0 + i, GR_GL_NONE, 0, NULL);
- fHWPathTexGenSettings[i].fMode = GR_GL_NONE;
- fHWPathTexGenSettings[i].fNumComponents = 0;
- }
- fHWActivePathTexGenSets = 0;
+ this->glPathRendering()->resetContext();
}
- fHWPathStencilSettings.invalidate();
}
// we assume these values
@@ -1372,16 +1344,6 @@ GrIndexBuffer* GrGpuGL::onCreateIndexBuffer(size_t size, bool dynamic) {
}
}
-GrPath* GrGpuGL::onCreatePath(const SkPath& inPath, const SkStrokeRec& stroke) {
- SkASSERT(this->caps()->pathRenderingSupport());
- return SkNEW_ARGS(GrGLPath, (this, inPath, stroke));
-}
-
-GrPathRange* GrGpuGL::onCreatePathRange(size_t size, const SkStrokeRec& stroke) {
- SkASSERT(this->caps()->pathRenderingSupport());
- return SkNEW_ARGS(GrGLPathRange, (this, size, stroke));
-}
-
void GrGpuGL::flushScissor() {
if (fScissorState.fEnabled) {
// Only access the RT if scissoring is being enabled. We can call this before performing
@@ -1839,168 +1801,6 @@ void GrGpuGL::onGpuDraw(const DrawInfo& info) {
#endif
}
-static GrGLenum gr_stencil_op_to_gl_path_rendering_fill_mode(GrStencilOp op) {
- switch (op) {
- default:
- SkFAIL("Unexpected path fill.");
- /* fallthrough */;
- case kIncClamp_StencilOp:
- return GR_GL_COUNT_UP;
- case kInvert_StencilOp:
- return GR_GL_INVERT;
- }
-}
-
-void GrGpuGL::onGpuStencilPath(const GrPath* path, SkPath::FillType fill) {
- SkASSERT(this->caps()->pathRenderingSupport());
-
- GrGLuint id = static_cast<const GrGLPath*>(path)->pathID();
- SkASSERT(NULL != this->drawState()->getRenderTarget());
- SkASSERT(NULL != this->drawState()->getRenderTarget()->getStencilBuffer());
-
- flushPathStencilSettings(fill);
-
- // Decide how to manipulate the stencil buffer based on the fill rule.
- SkASSERT(!fHWPathStencilSettings.isTwoSided());
-
- GrGLenum fillMode =
- gr_stencil_op_to_gl_path_rendering_fill_mode(fHWPathStencilSettings.passOp(GrStencilSettings::kFront_Face));
- GrGLint writeMask = fHWPathStencilSettings.writeMask(GrStencilSettings::kFront_Face);
- fPathRendering->stencilFillPath(id, fillMode, writeMask);
-}
-
-void GrGpuGL::onGpuDrawPath(const GrPath* path, SkPath::FillType fill) {
- SkASSERT(this->caps()->pathRenderingSupport());
-
- GrGLuint id = static_cast<const GrGLPath*>(path)->pathID();
- SkASSERT(NULL != this->drawState()->getRenderTarget());
- SkASSERT(NULL != this->drawState()->getRenderTarget()->getStencilBuffer());
- SkASSERT(!fCurrentProgram->hasVertexShader());
-
- flushPathStencilSettings(fill);
- const SkStrokeRec& stroke = path->getStroke();
-
- SkPath::FillType nonInvertedFill = SkPath::ConvertToNonInverseFillType(fill);
- SkASSERT(!fHWPathStencilSettings.isTwoSided());
- GrGLenum fillMode =
- gr_stencil_op_to_gl_path_rendering_fill_mode(fHWPathStencilSettings.passOp(GrStencilSettings::kFront_Face));
- GrGLint writeMask = fHWPathStencilSettings.writeMask(GrStencilSettings::kFront_Face);
-
- if (nonInvertedFill == fill) {
- if (stroke.needToApply()) {
- if (SkStrokeRec::kStrokeAndFill_Style == stroke.getStyle()) {
- fPathRendering->stencilFillPath(id, fillMode, writeMask);
- }
- fPathRendering->stencilThenCoverStrokePath(id, 0xffff, writeMask, GR_GL_BOUNDING_BOX);
- } else {
- fPathRendering->stencilThenCoverFillPath(id, fillMode, writeMask, GR_GL_BOUNDING_BOX);
- }
- } else {
- if (stroke.isFillStyle() || SkStrokeRec::kStrokeAndFill_Style == stroke.getStyle()) {
- fPathRendering->stencilFillPath(id, fillMode, writeMask);
- }
- if (stroke.needToApply()) {
- fPathRendering->stencilStrokePath(id, 0xffff, writeMask);
- }
-
- GrDrawState* drawState = this->drawState();
- GrDrawState::AutoViewMatrixRestore avmr;
- SkRect bounds = SkRect::MakeLTRB(0, 0,
- SkIntToScalar(drawState->getRenderTarget()->width()),
- SkIntToScalar(drawState->getRenderTarget()->height()));
- SkMatrix vmi;
- // mapRect through persp matrix may not be correct
- if (!drawState->getViewMatrix().hasPerspective() && drawState->getViewInverse(&vmi)) {
- vmi.mapRect(&bounds);
- // theoretically could set bloat = 0, instead leave it because of matrix inversion
- // precision.
- SkScalar bloat = drawState->getViewMatrix().getMaxScale() * SK_ScalarHalf;
- bounds.outset(bloat, bloat);
- } else {
- avmr.setIdentity(drawState);
- }
-
- this->drawSimpleRect(bounds);
- }
-}
-
-void GrGpuGL::onGpuDrawPaths(const GrPathRange* pathRange,
- const uint32_t indices[], int count,
- const float transforms[], PathTransformType transformsType,
- SkPath::FillType fill) {
- SkASSERT(this->caps()->pathRenderingSupport());
- SkASSERT(NULL != this->drawState()->getRenderTarget());
- SkASSERT(NULL != this->drawState()->getRenderTarget()->getStencilBuffer());
- SkASSERT(!fCurrentProgram->hasVertexShader());
-
- GrGLuint baseID = static_cast<const GrGLPathRange*>(pathRange)->basePathID();
-
- flushPathStencilSettings(fill);
- const SkStrokeRec& stroke = pathRange->getStroke();
-
- SkPath::FillType nonInvertedFill =
- SkPath::ConvertToNonInverseFillType(fill);
-
- SkASSERT(!fHWPathStencilSettings.isTwoSided());
- GrGLenum fillMode =
- gr_stencil_op_to_gl_path_rendering_fill_mode(
- fHWPathStencilSettings.passOp(GrStencilSettings::kFront_Face));
- GrGLint writeMask =
- fHWPathStencilSettings.writeMask(GrStencilSettings::kFront_Face);
-
- if (nonInvertedFill == fill) {
- if (stroke.needToApply()) {
- if (SkStrokeRec::kStrokeAndFill_Style == stroke.getStyle()) {
- fPathRendering->stencilFillPathInstanced(
- count, GR_GL_UNSIGNED_INT, indices, baseID, fillMode,
- writeMask, gXformType2GLType[transformsType],
- transforms);
- }
- fPathRendering->stencilThenCoverStrokePathInstanced(
- count, GR_GL_UNSIGNED_INT, indices, baseID, 0xffff, writeMask,
- GR_GL_BOUNDING_BOX_OF_BOUNDING_BOXES,
- gXformType2GLType[transformsType], transforms);
- } else {
- fPathRendering->stencilThenCoverFillPathInstanced(
- count, GR_GL_UNSIGNED_INT, indices, baseID, fillMode, writeMask,
- GR_GL_BOUNDING_BOX_OF_BOUNDING_BOXES,
- gXformType2GLType[transformsType], transforms);
- }
- } else {
- if (stroke.isFillStyle() || SkStrokeRec::kStrokeAndFill_Style == stroke.getStyle()) {
- fPathRendering->stencilFillPathInstanced(
- count, GR_GL_UNSIGNED_INT, indices, baseID, fillMode,
- writeMask, gXformType2GLType[transformsType],
- transforms);
- }
- if (stroke.needToApply()) {
- fPathRendering->stencilStrokePathInstanced(
- count, GR_GL_UNSIGNED_INT, indices, baseID, 0xffff,
- writeMask, gXformType2GLType[transformsType],
- transforms);
- }
-
- GrDrawState* drawState = this->drawState();
- GrDrawState::AutoViewMatrixRestore avmr;
- SkRect bounds = SkRect::MakeLTRB(0, 0,
- SkIntToScalar(drawState->getRenderTarget()->width()),
- SkIntToScalar(drawState->getRenderTarget()->height()));
- SkMatrix vmi;
- // mapRect through persp matrix may not be correct
- if (!drawState->getViewMatrix().hasPerspective() && drawState->getViewInverse(&vmi)) {
- vmi.mapRect(&bounds);
- // theoretically could set bloat = 0, instead leave it because of matrix inversion
- // precision.
- SkScalar bloat = drawState->getViewMatrix().getMaxScale() * SK_ScalarHalf;
- bounds.outset(bloat, bloat);
- } else {
- avmr.setIdentity(drawState);
- }
-
- this->drawSimpleRect(bounds);
- }
-}
-
void GrGpuGL::onResolveRenderTarget(GrRenderTarget* target) {
GrGLRenderTarget* rt = static_cast<GrGLRenderTarget*>(target);
if (rt->needsResolve()) {
@@ -2046,30 +1846,6 @@ void GrGpuGL::onResolveRenderTarget(GrRenderTarget* target) {
namespace {
-GrGLenum gr_to_gl_stencil_func(GrStencilFunc basicFunc) {
- static const GrGLenum gTable[] = {
- GR_GL_ALWAYS, // kAlways_StencilFunc
- GR_GL_NEVER, // kNever_StencilFunc
- GR_GL_GREATER, // kGreater_StencilFunc
- GR_GL_GEQUAL, // kGEqual_StencilFunc
- GR_GL_LESS, // kLess_StencilFunc
- GR_GL_LEQUAL, // kLEqual_StencilFunc,
- GR_GL_EQUAL, // kEqual_StencilFunc,
- GR_GL_NOTEQUAL, // kNotEqual_StencilFunc,
- };
- GR_STATIC_ASSERT(SK_ARRAY_COUNT(gTable) == kBasicStencilFuncCount);
- GR_STATIC_ASSERT(0 == kAlways_StencilFunc);
- GR_STATIC_ASSERT(1 == kNever_StencilFunc);
- GR_STATIC_ASSERT(2 == kGreater_StencilFunc);
- GR_STATIC_ASSERT(3 == kGEqual_StencilFunc);
- GR_STATIC_ASSERT(4 == kLess_StencilFunc);
- GR_STATIC_ASSERT(5 == kLEqual_StencilFunc);
- GR_STATIC_ASSERT(6 == kEqual_StencilFunc);
- GR_STATIC_ASSERT(7 == kNotEqual_StencilFunc);
- SkASSERT((unsigned) basicFunc < kBasicStencilFuncCount);
-
- return gTable[basicFunc];
-}
GrGLenum gr_to_gl_stencil_op(GrStencilOp op) {
static const GrGLenum gTable[] = {
@@ -2099,7 +1875,7 @@ void set_gl_stencil(const GrGLInterface* gl,
const GrStencilSettings& settings,
GrGLenum glFace,
GrStencilSettings::Face grFace) {
- GrGLenum glFunc = gr_to_gl_stencil_func(settings.func(grFace));
+ GrGLenum glFunc = GrToGLStencilFunc(settings.func(grFace));
GrGLenum glFailOp = gr_to_gl_stencil_op(settings.failOp(grFace));
GrGLenum glPassOp = gr_to_gl_stencil_op(settings.passOp(grFace));
@@ -2187,22 +1963,6 @@ void GrGpuGL::flushAAState(DrawType type) {
}
}
-void GrGpuGL::flushPathStencilSettings(SkPath::FillType fill) {
- GrStencilSettings pathStencilSettings;
- this->getPathStencilSettingsForFillType(fill, &pathStencilSettings);
- if (fHWPathStencilSettings != pathStencilSettings) {
- // Just the func, ref, and mask is set here. The op and write mask are params to the call
- // that draws the path to the SB (glStencilFillPath)
- GrGLenum func =
- gr_to_gl_stencil_func(pathStencilSettings.func(GrStencilSettings::kFront_Face));
- fPathRendering->pathStencilFunc(
- func, pathStencilSettings.funcRef(GrStencilSettings::kFront_Face),
- pathStencilSettings.funcMask(GrStencilSettings::kFront_Face));
-
- fHWPathStencilSettings = pathStencilSettings;
- }
-}
-
void GrGpuGL::flushBlend(bool isLines,
GrBlendCoeff srcCoeff,
GrBlendCoeff dstCoeff) {
@@ -2349,104 +2109,6 @@ void GrGpuGL::bindTexture(int unitIdx, const GrTextureParams& params, GrGLTextur
texture->setCachedTexParams(newTexParams, this->getResetTimestamp());
}
-void GrGpuGL::setProjectionMatrix(const SkMatrix& matrix,
- const SkISize& renderTargetSize,
- GrSurfaceOrigin renderTargetOrigin) {
-
- SkASSERT(this->glCaps().pathRenderingSupport());
-
- if (renderTargetOrigin == fHWProjectionMatrixState.fRenderTargetOrigin &&
- renderTargetSize == fHWProjectionMatrixState.fRenderTargetSize &&
- matrix.cheapEqualTo(fHWProjectionMatrixState.fViewMatrix)) {
- return;
- }
-
- fHWProjectionMatrixState.fViewMatrix = matrix;
- fHWProjectionMatrixState.fRenderTargetSize = renderTargetSize;
- fHWProjectionMatrixState.fRenderTargetOrigin = renderTargetOrigin;
-
- GrGLfloat glMatrix[4 * 4];
- fHWProjectionMatrixState.getRTAdjustedGLMatrix<4>(glMatrix);
- GL_CALL(MatrixLoadf(GR_GL_PROJECTION, glMatrix));
-}
-
-void GrGpuGL::enablePathTexGen(int unitIdx,
- PathTexGenComponents components,
- const GrGLfloat* coefficients) {
- SkASSERT(this->glCaps().pathRenderingSupport());
- SkASSERT(components >= kS_PathTexGenComponents &&
- components <= kSTR_PathTexGenComponents);
- SkASSERT(this->glCaps().maxFixedFunctionTextureCoords() >= unitIdx);
-
- if (GR_GL_OBJECT_LINEAR == fHWPathTexGenSettings[unitIdx].fMode &&
- components == fHWPathTexGenSettings[unitIdx].fNumComponents &&
- !memcmp(coefficients, fHWPathTexGenSettings[unitIdx].fCoefficients,
- 3 * components * sizeof(GrGLfloat))) {
- return;
- }
-
- this->setTextureUnit(unitIdx);
-
- fHWPathTexGenSettings[unitIdx].fNumComponents = components;
- fPathRendering->pathTexGen(GR_GL_TEXTURE0 + unitIdx,
- GR_GL_OBJECT_LINEAR,
- components,
- coefficients);
-
- memcpy(fHWPathTexGenSettings[unitIdx].fCoefficients, coefficients,
- 3 * components * sizeof(GrGLfloat));
-}
-
-void GrGpuGL::enablePathTexGen(int unitIdx, PathTexGenComponents components,
- const SkMatrix& matrix) {
- GrGLfloat coefficients[3 * 3];
- SkASSERT(this->glCaps().pathRenderingSupport());
- SkASSERT(components >= kS_PathTexGenComponents &&
- components <= kSTR_PathTexGenComponents);
-
- coefficients[0] = SkScalarToFloat(matrix[SkMatrix::kMScaleX]);
- coefficients[1] = SkScalarToFloat(matrix[SkMatrix::kMSkewX]);
- coefficients[2] = SkScalarToFloat(matrix[SkMatrix::kMTransX]);
-
- if (components >= kST_PathTexGenComponents) {
- coefficients[3] = SkScalarToFloat(matrix[SkMatrix::kMSkewY]);
- coefficients[4] = SkScalarToFloat(matrix[SkMatrix::kMScaleY]);
- coefficients[5] = SkScalarToFloat(matrix[SkMatrix::kMTransY]);
- }
-
- if (components >= kSTR_PathTexGenComponents) {
- coefficients[6] = SkScalarToFloat(matrix[SkMatrix::kMPersp0]);
- coefficients[7] = SkScalarToFloat(matrix[SkMatrix::kMPersp1]);
- coefficients[8] = SkScalarToFloat(matrix[SkMatrix::kMPersp2]);
- }
-
- enablePathTexGen(unitIdx, components, coefficients);
-}
-
-void GrGpuGL::flushPathTexGenSettings(int numUsedTexCoordSets) {
- SkASSERT(this->glCaps().pathRenderingSupport());
- SkASSERT(this->glCaps().maxFixedFunctionTextureCoords() >= numUsedTexCoordSets);
-
- // Only write the inactive path tex gens, since active path tex gens were
- // written when they were enabled.
-
- SkDEBUGCODE(
- for (int i = 0; i < numUsedTexCoordSets; i++) {
- SkASSERT(0 != fHWPathTexGenSettings[i].fNumComponents);
- }
- );
-
- for (int i = numUsedTexCoordSets; i < fHWActivePathTexGenSets; i++) {
- SkASSERT(0 != fHWPathTexGenSettings[i].fNumComponents);
-
- this->setTextureUnit(i);
- fPathRendering->pathTexGen(GR_GL_TEXTURE0 + i, GR_GL_NONE, 0, NULL);
- fHWPathTexGenSettings[i].fNumComponents = 0;
- }
-
- fHWActivePathTexGenSets = numUsedTexCoordSets;
-}
-
void GrGpuGL::flushMiscFixedFunctionState() {
const GrDrawState& drawState = this->getDrawState();
diff --git a/src/gpu/gl/GrGpuGL.h b/src/gpu/gl/GrGpuGL.h
index b39aedb824..40104f8825 100644
--- a/src/gpu/gl/GrGpuGL.h
+++ b/src/gpu/gl/GrGpuGL.h
@@ -12,6 +12,7 @@
#include "GrGLContext.h"
#include "GrGLIRect.h"
#include "GrGLIndexBuffer.h"
+#include "GrGLPathRendering.h"
#include "GrGLProgram.h"
#include "GrGLStencilBuffer.h"
#include "GrGLTexture.h"
@@ -24,8 +25,6 @@
#define PROGRAM_CACHE_STATS
#endif
-class GrGLPathRendering;
-
class GrGpuGL : public GrGpu {
public:
GrGpuGL(const GrGLContext& ctx, GrContext* context);
@@ -40,9 +39,9 @@ public:
GrGLSLGeneration glslGeneration() const { return fGLContext.glslGeneration(); }
const GrGLCaps& glCaps() const { return *fGLContext.caps(); }
- GrGLPathRendering* pathRendering() const {
+ GrGLPathRendering* glPathRendering() {
SkASSERT(glCaps().pathRenderingSupport());
- return fPathRendering.get();
+ return static_cast<GrGLPathRendering*>(pathRendering());
}
virtual void discard(GrRenderTarget*) SK_OVERRIDE;
@@ -50,17 +49,7 @@ public:
// Used by GrGLProgram and GrGLPathTexGenProgramEffects to configure OpenGL
// state.
void bindTexture(int unitIdx, const GrTextureParams& params, GrGLTexture* texture);
- void setProjectionMatrix(const SkMatrix& matrix,
- const SkISize& renderTargetSize,
- GrSurfaceOrigin renderTargetOrigin);
- enum PathTexGenComponents {
- kS_PathTexGenComponents = 1,
- kST_PathTexGenComponents = 2,
- kSTR_PathTexGenComponents = 3
- };
- void enablePathTexGen(int unitIdx, PathTexGenComponents, const GrGLfloat* coefficients);
- void enablePathTexGen(int unitIdx, PathTexGenComponents, const SkMatrix& matrix);
- void flushPathTexGenSettings(int numUsedTexCoordSets);
+
bool shouldUseFixedFunctionTexturing() const {
return this->glCaps().pathRenderingSupport();
}
@@ -131,8 +120,6 @@ private:
const void* srcData) SK_OVERRIDE;
virtual GrVertexBuffer* onCreateVertexBuffer(size_t size, bool dynamic) SK_OVERRIDE;
virtual GrIndexBuffer* onCreateIndexBuffer(size_t size, bool dynamic) SK_OVERRIDE;
- virtual GrPath* onCreatePath(const SkPath&, const SkStrokeRec&) SK_OVERRIDE;
- virtual GrPathRange* onCreatePathRange(size_t size, const SkStrokeRec&) SK_OVERRIDE;
virtual GrTexture* onWrapBackendTexture(const GrBackendTextureDesc&) SK_OVERRIDE;
virtual GrRenderTarget* onWrapBackendRenderTarget(const GrBackendRenderTargetDesc&) SK_OVERRIDE;
virtual bool createStencilBufferForRenderTarget(GrRenderTarget* rt,
@@ -160,12 +147,6 @@ private:
virtual void onGpuDraw(const DrawInfo&) SK_OVERRIDE;
- virtual void onGpuStencilPath(const GrPath*, SkPath::FillType) SK_OVERRIDE;
- virtual void onGpuDrawPath(const GrPath*, SkPath::FillType) SK_OVERRIDE;
- virtual void onGpuDrawPaths(const GrPathRange*,
- const uint32_t indices[], int count,
- const float transforms[], PathTransformType,
- SkPath::FillType) SK_OVERRIDE;
virtual void clearStencil() SK_OVERRIDE;
virtual void clearStencilClip(const SkIRect& rect,
@@ -257,7 +238,6 @@ private:
void flushRenderTarget(const SkIRect* bound);
void flushStencil(DrawType);
void flushAAState(DrawType);
- void flushPathStencilSettings(SkPath::FillType fill);
bool configToGLFormats(GrPixelConfig config,
bool getSizedInternal,
@@ -445,11 +425,9 @@ private:
TriState fMSAAEnabled;
- GrGLProgram::MatrixState fHWProjectionMatrixState;
-
GrStencilSettings fHWStencilSettings;
TriState fHWStencilTestEnabled;
- GrStencilSettings fHWPathStencilSettings;
+
GrDrawState::DrawFace fHWDrawFace;
TriState fHWWriteToColor;
@@ -457,22 +435,14 @@ private:
uint32_t fHWBoundRenderTargetUniqueID;
SkTArray<uint32_t, true> fHWBoundTextureUniqueIDs;
- struct PathTexGenData {
- GrGLenum fMode;
- GrGLint fNumComponents;
- GrGLfloat fCoefficients[3 * 3];
- };
- int fHWActivePathTexGenSets;
- SkTArray<PathTexGenData, true> fHWPathTexGenSettings;
///@}
// we record what stencil format worked last time to hopefully exit early
// from our loop that tries stencil formats and calls check fb status.
int fLastSuccessfulStencilFmtIdx;
- SkAutoTDelete<GrGLPathRendering> fPathRendering;
-
typedef GrGpu INHERITED;
+ friend class GrGLPathRendering; // For accessing setTextureUnit.
};
#endif
diff --git a/src/gpu/gl/GrGpuGL_program.cpp b/src/gpu/gl/GrGpuGL_program.cpp
index beaaa903b2..c4011e7314 100644
--- a/src/gpu/gl/GrGpuGL_program.cpp
+++ b/src/gpu/gl/GrGpuGL_program.cpp
@@ -204,7 +204,7 @@ void GrGpuGL::abandonResources(){
fProgramCache->abandon();
fHWProgramID = 0;
if (this->glCaps().pathRenderingSupport()) {
- fPathRendering->abandonGpuResources();
+ this->glPathRendering()->abandonGpuResources();
}
}
@@ -222,7 +222,7 @@ bool GrGpuGL::flushGraphicsState(DrawType type, const GrDeviceCoordTexture* dstC
const GrRenderTarget* rt = this->getDrawState().getRenderTarget();
SkISize size;
size.set(rt->width(), rt->height());
- this->setProjectionMatrix(drawState.getViewMatrix(), size, rt->origin());
+ this->glPathRendering()->setProjectionMatrix(drawState.getViewMatrix(), size, rt->origin());
} else {
this->flushMiscFixedFunctionState();