Wrap NV_path_rendering API with GrGLPathRendering
Adds a GrGLPathRendering class that wraps the NV_path_rendering extension and manages its various API versions. It also provides backup implementations when certain NVpr methods from later API versions are not present on the current system. BUG=skia: R=bungeman@google.com, bsalomon@google.com, kkinnunen@nvidia.com Author: cdalton@nvidia.com Review URL: https://codereview.chromium.org/444223002
This commit is contained in:
parent
5acfea789d
commit
c7103a104f
@ -203,6 +203,8 @@
|
||||
'<(skia_src_path)/gpu/gl/GrGLPath.h',
|
||||
'<(skia_src_path)/gpu/gl/GrGLPathRange.cpp',
|
||||
'<(skia_src_path)/gpu/gl/GrGLPathRange.h',
|
||||
'<(skia_src_path)/gpu/gl/GrGLPathRendering.cpp',
|
||||
'<(skia_src_path)/gpu/gl/GrGLPathRendering.h',
|
||||
'<(skia_src_path)/gpu/gl/GrGLSLPrettyPrint.cpp',
|
||||
'<(skia_src_path)/gpu/gl/GrGLProgram.cpp',
|
||||
'<(skia_src_path)/gpu/gl/GrGLProgram.h',
|
||||
|
@ -245,11 +245,12 @@ extern "C" {
|
||||
typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLCoverStrokePathProc)(GrGLuint name, GrGLenum coverMode);
|
||||
typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLCoverFillPathInstancedProc)(GrGLsizei numPaths, GrGLenum pathNameType, const GrGLvoid *paths, GrGLuint pathBase, GrGLenum coverMode, GrGLenum transformType, const GrGLfloat *transformValues);
|
||||
typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLCoverStrokePathInstancedProc)(GrGLsizei numPaths, GrGLenum pathNameType, const GrGLvoid *paths, GrGLuint pathBase, GrGLenum coverMode, GrGLenum transformType, const GrGLfloat* transformValues);
|
||||
// NV_path_rendering v1.2
|
||||
typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLStencilThenCoverFillPathProc)(GrGLuint path, GrGLenum fillMode, GrGLuint mask, GrGLenum coverMode);
|
||||
typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLStencilThenCoverStrokePathProc)(GrGLuint path, GrGLint reference, GrGLuint mask, GrGLenum coverMode);
|
||||
typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLStencilThenCoverFillPathInstancedProc)(GrGLsizei numPaths, GrGLenum pathNameType, const GrGLvoid *paths, GrGLuint pathBase, GrGLenum fillMode, GrGLuint mask, GrGLenum coverMode, GrGLenum transformType, const GrGLfloat *transformValues);
|
||||
typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLStencilThenCoverStrokePathInstancedProc)(GrGLsizei numPaths, GrGLenum pathNameType, const GrGLvoid *paths, GrGLuint pathBase, GrGLint reference, GrGLuint mask, GrGLenum coverMode, GrGLenum transformType, const GrGLfloat *transformValues);
|
||||
|
||||
// NV_path_rendering v1.3
|
||||
typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLProgramPathFragmentInputGenProc)(GrGLuint program, GrGLint location, GrGLenum genMode, GrGLint components,const GrGLfloat *coeffs);
|
||||
} // extern "C"
|
||||
|
||||
|
@ -335,10 +335,12 @@ public:
|
||||
GLPtr<GrGLCoverStrokePathProc> fCoverStrokePath;
|
||||
GLPtr<GrGLCoverFillPathInstancedProc> fCoverFillPathInstanced;
|
||||
GLPtr<GrGLCoverStrokePathInstancedProc> fCoverStrokePathInstanced;
|
||||
// NV_path_rendering v1.2
|
||||
GLPtr<GrGLStencilThenCoverFillPathProc> fStencilThenCoverFillPath;
|
||||
GLPtr<GrGLStencilThenCoverStrokePathProc> fStencilThenCoverStrokePath;
|
||||
GLPtr<GrGLStencilThenCoverFillPathInstancedProc> fStencilThenCoverFillPathInstanced;
|
||||
GLPtr<GrGLStencilThenCoverStrokePathInstancedProc> fStencilThenCoverStrokePathInstanced;
|
||||
// NV_path_rendering v1.3
|
||||
GLPtr<GrGLProgramPathFragmentInputGenProc> fProgramPathFragmentInputGen;
|
||||
} fFunctions;
|
||||
|
||||
|
@ -14,12 +14,6 @@
|
||||
#define GET_PROC_SUFFIX(F, S) functions->f ## F = (GrGL ## F ## Proc) get(ctx, "gl" #F #S)
|
||||
#define GET_PROC_LOCAL(F) GrGL ## F ## Proc F = (GrGL ## F ## Proc) get(ctx, "gl" #F)
|
||||
|
||||
// The glStencilThenCover* methods are a new addition to NV_path_rendering. They
|
||||
// aren't available on all drivers. In the event that they are not present, this
|
||||
// function can be used to add methods to the given GrGLInterface that emulate
|
||||
// them using the existing glStencil*/glCover* methods.
|
||||
static void emulate_nvpr_stencil_then_cover(GrGLInterface*);
|
||||
|
||||
const GrGLInterface* GrGLAssembleGLInterface(void* ctx, GrGLGetProc get) {
|
||||
GET_PROC_LOCAL(GetString);
|
||||
GET_PROC_LOCAL(GetStringi);
|
||||
@ -245,18 +239,13 @@ const GrGLInterface* GrGLAssembleGLInterface(void* ctx, GrGLGetProc get) {
|
||||
GET_PROC_SUFFIX(CoverStrokePath, NV);
|
||||
GET_PROC_SUFFIX(CoverFillPathInstanced, NV);
|
||||
GET_PROC_SUFFIX(CoverStrokePathInstanced, NV);
|
||||
// NV_path_rendering v1.2 (These methods may not be present)
|
||||
GET_PROC_SUFFIX(StencilThenCoverFillPath, NV);
|
||||
GET_PROC_SUFFIX(StencilThenCoverStrokePath, NV);
|
||||
GET_PROC_SUFFIX(StencilThenCoverFillPathInstanced, NV);
|
||||
GET_PROC_SUFFIX(StencilThenCoverStrokePathInstanced, NV);
|
||||
// NV_path_rendering v1.3 (These methods may not be present)
|
||||
GET_PROC_SUFFIX(ProgramPathFragmentInputGen, NV);
|
||||
|
||||
if (NULL == interface->fFunctions.fStencilThenCoverFillPath ||
|
||||
NULL == interface->fFunctions.fStencilThenCoverStrokePath ||
|
||||
NULL == interface->fFunctions.fStencilThenCoverFillPathInstanced ||
|
||||
NULL == interface->fFunctions.fStencilThenCoverFillPathInstanced) {
|
||||
emulate_nvpr_stencil_then_cover(interface);
|
||||
}
|
||||
}
|
||||
|
||||
if (extensions.has("GL_EXT_debug_marker")) {
|
||||
@ -283,101 +272,3 @@ const GrGLInterface* GrGLAssembleGLInterface(void* ctx, GrGLGetProc get) {
|
||||
|
||||
return interface;
|
||||
}
|
||||
|
||||
static GrGLStencilFillPathProc gStencilFillPath;
|
||||
static GrGLCoverFillPathProc gCoverFillPath;
|
||||
static GrGLvoid GR_GL_FUNCTION_TYPE stencil_then_cover_fill_path(
|
||||
GrGLuint path, GrGLenum fillMode,
|
||||
GrGLuint mask, GrGLenum coverMode) {
|
||||
gStencilFillPath(path, fillMode, mask);
|
||||
gCoverFillPath(path, coverMode);
|
||||
}
|
||||
|
||||
|
||||
static GrGLStencilStrokePathProc gStencilStrokePath;
|
||||
static GrGLCoverStrokePathProc gCoverStrokePath;
|
||||
static GrGLvoid GR_GL_FUNCTION_TYPE stencil_then_cover_stroke_path(
|
||||
GrGLuint path, GrGLint reference,
|
||||
GrGLuint mask, GrGLenum coverMode) {
|
||||
gStencilStrokePath(path, reference, mask);
|
||||
gCoverStrokePath(path, coverMode);
|
||||
}
|
||||
|
||||
static GrGLStencilFillPathInstancedProc gStencilFillPathInstanced;
|
||||
static GrGLCoverFillPathInstancedProc gCoverFillPathInstanced;
|
||||
static GrGLvoid GR_GL_FUNCTION_TYPE stencil_then_cover_fill_path_instanced(
|
||||
GrGLsizei numPaths, GrGLenum pathNameType,
|
||||
const GrGLvoid *paths, GrGLuint pathBase,
|
||||
GrGLenum fillMode, GrGLuint mask,
|
||||
GrGLenum coverMode, GrGLenum transformType,
|
||||
const GrGLfloat *transformValues) {
|
||||
gStencilFillPathInstanced(numPaths, pathNameType, paths, pathBase,
|
||||
fillMode, mask, transformType, transformValues);
|
||||
gCoverFillPathInstanced(numPaths, pathNameType, paths, pathBase,
|
||||
coverMode, transformType, transformValues);
|
||||
}
|
||||
|
||||
static GrGLStencilStrokePathInstancedProc gStencilStrokePathInstanced;
|
||||
static GrGLCoverStrokePathInstancedProc gCoverStrokePathInstanced;
|
||||
static GrGLvoid GR_GL_FUNCTION_TYPE stencil_then_cover_stroke_path_instanced(
|
||||
GrGLsizei numPaths, GrGLenum pathNameType,
|
||||
const GrGLvoid *paths, GrGLuint pathBase,
|
||||
GrGLint reference, GrGLuint mask,
|
||||
GrGLenum coverMode, GrGLenum transformType,
|
||||
const GrGLfloat *transformValues) {
|
||||
gStencilStrokePathInstanced(numPaths, pathNameType, paths, pathBase,
|
||||
reference, mask, transformType, transformValues);
|
||||
gCoverStrokePathInstanced(numPaths, pathNameType, paths, pathBase,
|
||||
coverMode, transformType, transformValues);
|
||||
}
|
||||
|
||||
static void emulate_nvpr_stencil_then_cover(GrGLInterface* interface) {
|
||||
if (NULL == gStencilFillPath) {
|
||||
gStencilFillPath = (GrGLStencilFillPathProc)interface->fFunctions.fStencilFillPath;
|
||||
}
|
||||
if (NULL == gCoverFillPath) {
|
||||
gCoverFillPath = (GrGLCoverFillPathProc)interface->fFunctions.fCoverFillPath;
|
||||
}
|
||||
if (NULL == gStencilStrokePath) {
|
||||
gStencilStrokePath = (GrGLStencilStrokePathProc)interface->fFunctions.fStencilStrokePath;
|
||||
}
|
||||
if (NULL == gCoverStrokePath) {
|
||||
gCoverStrokePath = (GrGLCoverStrokePathProc)interface->fFunctions.fCoverStrokePath;
|
||||
}
|
||||
if (NULL == gStencilFillPathInstanced) {
|
||||
gStencilFillPathInstanced = (GrGLStencilFillPathInstancedProc)
|
||||
interface->fFunctions.fStencilFillPathInstanced;
|
||||
}
|
||||
if (NULL == gCoverFillPathInstanced) {
|
||||
gCoverFillPathInstanced = (GrGLCoverFillPathInstancedProc)
|
||||
interface->fFunctions.fCoverFillPathInstanced;
|
||||
}
|
||||
if (NULL == gStencilStrokePathInstanced) {
|
||||
gStencilStrokePathInstanced = (GrGLStencilStrokePathInstancedProc)
|
||||
interface->fFunctions.fStencilStrokePathInstanced;
|
||||
}
|
||||
if (NULL == gCoverStrokePathInstanced) {
|
||||
gCoverStrokePathInstanced = (GrGLCoverStrokePathInstancedProc)
|
||||
interface->fFunctions.fCoverStrokePathInstanced;
|
||||
}
|
||||
|
||||
if (interface->fFunctions.fStencilFillPath != gStencilFillPath ||
|
||||
interface->fFunctions.fCoverFillPath != gCoverFillPath ||
|
||||
interface->fFunctions.fStencilStrokePath != gStencilStrokePath ||
|
||||
interface->fFunctions.fCoverStrokePath != gCoverStrokePath ||
|
||||
interface->fFunctions.fStencilFillPathInstanced != gStencilFillPathInstanced ||
|
||||
interface->fFunctions.fCoverFillPathInstanced != gCoverFillPathInstanced ||
|
||||
interface->fFunctions.fStencilStrokePathInstanced != gStencilStrokePathInstanced ||
|
||||
interface->fFunctions.fCoverStrokePathInstanced != gCoverStrokePathInstanced) {
|
||||
// While not every windowing system requires GetProcAddress to return
|
||||
// the same addresses in different contexts, it is guaranteed to do so
|
||||
// in any context that supports NV_path_rendering.
|
||||
SkFAIL("GetProcAddress returned different addresses for the same nvpr functions");
|
||||
return;
|
||||
}
|
||||
|
||||
interface->fFunctions.fStencilThenCoverFillPath = &stencil_then_cover_fill_path;
|
||||
interface->fFunctions.fStencilThenCoverStrokePath = &stencil_then_cover_stroke_path;
|
||||
interface->fFunctions.fStencilThenCoverFillPathInstanced = &stencil_then_cover_fill_path_instanced;
|
||||
interface->fFunctions.fStencilThenCoverStrokePathInstanced = &stencil_then_cover_stroke_path_instanced;
|
||||
}
|
||||
|
@ -56,6 +56,10 @@ const GrGLInterface* GrGLInterfaceRemoveNVPR(const GrGLInterface* interface) {
|
||||
newInterface->fFunctions.fCoverStrokePath = NULL;
|
||||
newInterface->fFunctions.fCoverFillPathInstanced = NULL;
|
||||
newInterface->fFunctions.fCoverStrokePathInstanced = NULL;
|
||||
newInterface->fFunctions.fStencilThenCoverFillPath = NULL;
|
||||
newInterface->fFunctions.fStencilThenCoverStrokePath = NULL;
|
||||
newInterface->fFunctions.fStencilThenCoverFillPathInstanced = NULL;
|
||||
newInterface->fFunctions.fStencilThenCoverStrokePathInstanced = NULL;
|
||||
newInterface->fFunctions.fProgramPathFragmentInputGen = NULL;
|
||||
return newInterface;
|
||||
}
|
||||
@ -467,18 +471,23 @@ bool GrGLInterface::validate() const {
|
||||
NULL == fFunctions.fCoverFillPath ||
|
||||
NULL == fFunctions.fCoverStrokePath ||
|
||||
NULL == fFunctions.fCoverFillPathInstanced ||
|
||||
NULL == fFunctions.fCoverStrokePathInstanced ||
|
||||
NULL == fFunctions.fStencilThenCoverFillPath ||
|
||||
NULL == fFunctions.fStencilThenCoverStrokePath ||
|
||||
NULL == fFunctions.fStencilThenCoverFillPathInstanced ||
|
||||
NULL == fFunctions.fStencilThenCoverStrokePathInstanced) {
|
||||
NULL == fFunctions.fCoverStrokePathInstanced) {
|
||||
RETURN_FALSE_INTERFACE
|
||||
}
|
||||
// Currently ProgramPathFragmentInputGen is not used on
|
||||
// OpenGL, rather PathTexGen is.
|
||||
if ((kGL_GrGLStandard == fStandard && NULL == fFunctions.fPathTexGen) ||
|
||||
(kGLES_GrGLStandard == fStandard && NULL == fFunctions.fProgramPathFragmentInputGen)) {
|
||||
RETURN_FALSE_INTERFACE
|
||||
if (kGL_GrGLStandard == fStandard) {
|
||||
// Some methods only exist on desktop
|
||||
if (NULL == fFunctions.fPathTexGen) {
|
||||
RETURN_FALSE_INTERFACE
|
||||
}
|
||||
} else {
|
||||
// All additions through v1.3 exist on GLES
|
||||
if (NULL == fFunctions.fStencilThenCoverFillPath ||
|
||||
NULL == fFunctions.fStencilThenCoverStrokePath ||
|
||||
NULL == fFunctions.fStencilThenCoverFillPathInstanced ||
|
||||
NULL == fFunctions.fStencilThenCoverStrokePathInstanced ||
|
||||
NULL == fFunctions.fProgramPathFragmentInputGen) {
|
||||
RETURN_FALSE_INTERFACE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7,13 +7,9 @@
|
||||
*/
|
||||
|
||||
#include "GrGLPath.h"
|
||||
#include "GrGLPathRendering.h"
|
||||
#include "GrGpuGL.h"
|
||||
|
||||
#define GPUGL static_cast<GrGpuGL*>(this->getGpu())
|
||||
|
||||
#define GL_CALL(X) GR_GL_CALL(GPUGL->glInterface(), X)
|
||||
#define GL_CALL_RET(R, X) GR_GL_CALL_RET(GPUGL->glInterface(), R, X)
|
||||
|
||||
namespace {
|
||||
inline GrGLubyte verb_to_gl_path_cmd(SkPath::Verb verb) {
|
||||
static const GrGLubyte gTable[] = {
|
||||
@ -85,10 +81,11 @@ inline GrGLenum cap_to_gl_cap(SkPaint::Cap cap) {
|
||||
|
||||
static const bool kIsWrapped = false; // The constructor creates the GL path object.
|
||||
|
||||
void GrGLPath::InitPathObject(const GrGLInterface* gl,
|
||||
void GrGLPath::InitPathObject(GrGpuGL* gpu,
|
||||
GrGLuint pathID,
|
||||
const SkPath& skPath,
|
||||
const SkStrokeRec& stroke) {
|
||||
GrGLPathRendering* pr = gpu->pathRendering();
|
||||
SkSTArray<16, GrGLubyte, true> pathCommands;
|
||||
SkSTArray<16, SkPoint, true> pathPoints;
|
||||
|
||||
@ -109,30 +106,25 @@ void GrGLPath::InitPathObject(const GrGLInterface* gl,
|
||||
}
|
||||
SkASSERT(pathPoints.count() == numPts);
|
||||
|
||||
GR_GL_CALL(gl, PathCommands(pathID,
|
||||
verbCnt, &pathCommands[0],
|
||||
2 * pointCnt, GR_GL_FLOAT, &pathPoints[0]));
|
||||
|
||||
pr->pathCommands(pathID, verbCnt, &pathCommands[0], 2 * pointCnt, GR_GL_FLOAT, &pathPoints[0]);
|
||||
if (stroke.needToApply()) {
|
||||
SkASSERT(!stroke.isHairlineStyle());
|
||||
GR_GL_CALL(gl, PathParameterf(pathID, GR_GL_PATH_STROKE_WIDTH, SkScalarToFloat(stroke.getWidth())));
|
||||
GR_GL_CALL(gl, PathParameterf(pathID, GR_GL_PATH_MITER_LIMIT, SkScalarToFloat(stroke.getMiter())));
|
||||
pr->pathParameterf(pathID, GR_GL_PATH_STROKE_WIDTH, SkScalarToFloat(stroke.getWidth()));
|
||||
pr->pathParameterf(pathID, GR_GL_PATH_MITER_LIMIT, SkScalarToFloat(stroke.getMiter()));
|
||||
GrGLenum join = join_to_gl_join(stroke.getJoin());
|
||||
GR_GL_CALL(gl, PathParameteri(pathID, GR_GL_PATH_JOIN_STYLE, join));
|
||||
pr->pathParameteri(pathID, GR_GL_PATH_JOIN_STYLE, join);
|
||||
GrGLenum cap = cap_to_gl_cap(stroke.getCap());
|
||||
GR_GL_CALL(gl, PathParameteri(pathID, GR_GL_PATH_INITIAL_END_CAP, cap));
|
||||
GR_GL_CALL(gl, PathParameteri(pathID, GR_GL_PATH_TERMINAL_END_CAP, cap));
|
||||
pr->pathParameteri(pathID, GR_GL_PATH_INITIAL_END_CAP, cap);
|
||||
pr->pathParameteri(pathID, GR_GL_PATH_TERMINAL_END_CAP, cap);
|
||||
}
|
||||
}
|
||||
|
||||
GrGLPath::GrGLPath(GrGpuGL* gpu, const SkPath& path, const SkStrokeRec& stroke)
|
||||
: INHERITED(gpu, kIsWrapped, path, stroke) {
|
||||
: INHERITED(gpu, kIsWrapped, path, stroke),
|
||||
fPathID(gpu->pathRendering()->genPaths(1)) {
|
||||
SkASSERT(!path.isEmpty());
|
||||
|
||||
fPathID = gpu->createGLPathObject();
|
||||
|
||||
InitPathObject(static_cast<GrGpuGL*>(this->getGpu())->glInterface(),
|
||||
fPathID, fSkPath, stroke);
|
||||
InitPathObject(gpu, fPathID, fSkPath, stroke);
|
||||
|
||||
if (stroke.needToApply()) {
|
||||
// FIXME: try to account for stroking, without rasterizing the stroke.
|
||||
@ -146,7 +138,7 @@ GrGLPath::~GrGLPath() {
|
||||
|
||||
void GrGLPath::onRelease() {
|
||||
if (0 != fPathID && !this->isWrapped()) {
|
||||
static_cast<GrGpuGL*>(this->getGpu())->deleteGLPathObject(fPathID);
|
||||
static_cast<GrGpuGL*>(this->getGpu())->pathRendering()->deletePaths(fPathID, 1);
|
||||
fPathID = 0;
|
||||
}
|
||||
|
||||
|
@ -13,7 +13,6 @@
|
||||
#include "gl/GrGLFunctions.h"
|
||||
|
||||
class GrGpuGL;
|
||||
struct GrGLInterface;
|
||||
|
||||
/**
|
||||
* Currently this represents a path built using GL_NV_path_rendering. If we
|
||||
@ -23,7 +22,7 @@ struct GrGLInterface;
|
||||
|
||||
class GrGLPath : public GrPath {
|
||||
public:
|
||||
static void InitPathObject(const GrGLInterface*,
|
||||
static void InitPathObject(GrGpuGL*,
|
||||
GrGLuint pathID,
|
||||
const SkPath&,
|
||||
const SkStrokeRec&);
|
||||
|
@ -8,17 +8,13 @@
|
||||
|
||||
#include "GrGLPathRange.h"
|
||||
#include "GrGLPath.h"
|
||||
#include "GrGLPathRendering.h"
|
||||
#include "GrGpuGL.h"
|
||||
|
||||
#define GPUGL static_cast<GrGpuGL*>(this->getGpu())
|
||||
|
||||
#define GL_CALL(X) GR_GL_CALL(GPUGL->glInterface(), X)
|
||||
#define GL_CALL_RET(R, X) GR_GL_CALL_RET(GPUGL->glInterface(), R, X)
|
||||
|
||||
GrGLPathRange::GrGLPathRange(GrGpu* gpu, size_t size, const SkStrokeRec& stroke)
|
||||
GrGLPathRange::GrGLPathRange(GrGpuGL* gpu, size_t size, const SkStrokeRec& stroke)
|
||||
: INHERITED(gpu, size, stroke),
|
||||
fBasePathID(gpu->pathRendering()->genPaths(fSize)),
|
||||
fNumDefinedPaths(0) {
|
||||
GL_CALL_RET(fBasePathID, GenPaths(fSize));
|
||||
}
|
||||
|
||||
GrGLPathRange::~GrGLPathRange() {
|
||||
@ -31,15 +27,10 @@ void GrGLPathRange::initAt(size_t index, const SkPath& skPath) {
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
// Make sure the path at this index hasn't been initted already.
|
||||
GrGLboolean hasPathAtIndex;
|
||||
GL_CALL_RET(hasPathAtIndex, IsPath(fBasePathID + index));
|
||||
SkASSERT(GR_GL_FALSE == hasPathAtIndex);
|
||||
#endif
|
||||
|
||||
GrGLPath::InitPathObject(gpu->glInterface(), fBasePathID + index, skPath, fStroke);
|
||||
SkASSERT(GR_GL_FALSE == gpu->pathRendering()->isPath(fBasePathID + index));
|
||||
|
||||
GrGLPath::InitPathObject(gpu, fBasePathID + index, skPath, fStroke);
|
||||
++fNumDefinedPaths;
|
||||
this->didChangeGpuMemorySize();
|
||||
}
|
||||
@ -48,7 +39,7 @@ void GrGLPathRange::onRelease() {
|
||||
SkASSERT(NULL != this->getGpu());
|
||||
|
||||
if (0 != fBasePathID && !this->isWrapped()) {
|
||||
GL_CALL(DeletePaths(fBasePathID, fSize));
|
||||
static_cast<GrGpuGL*>(this->getGpu())->pathRendering()->deletePaths(fBasePathID, fSize);
|
||||
fBasePathID = 0;
|
||||
}
|
||||
|
||||
|
@ -22,7 +22,7 @@ class GrGpuGL;
|
||||
|
||||
class GrGLPathRange : public GrPathRange {
|
||||
public:
|
||||
GrGLPathRange(GrGpu*, size_t size, const SkStrokeRec&);
|
||||
GrGLPathRange(GrGpuGL*, size_t size, const SkStrokeRec&);
|
||||
virtual ~GrGLPathRange();
|
||||
|
||||
GrGLuint basePathID() const { return fBasePathID; }
|
||||
|
281
src/gpu/gl/GrGLPathRendering.cpp
Normal file
281
src/gpu/gl/GrGLPathRendering.cpp
Normal file
@ -0,0 +1,281 @@
|
||||
/*
|
||||
* Copyright 2014 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "gl/GrGLPathRendering.h"
|
||||
#include "gl/GrGLInterface.h"
|
||||
#include "gl/GrGLNameAllocator.h"
|
||||
#include "gl/GrGLUtil.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)
|
||||
|
||||
class GrGLPathRenderingV12 : public GrGLPathRendering {
|
||||
public:
|
||||
GrGLPathRenderingV12(const GrGLInterface* glInterface)
|
||||
: GrGLPathRendering(glInterface) {
|
||||
}
|
||||
|
||||
virtual GrGLvoid stencilThenCoverFillPath(GrGLuint path, GrGLenum fillMode,
|
||||
GrGLuint mask, GrGLenum coverMode) SK_OVERRIDE;
|
||||
virtual GrGLvoid stencilThenCoverStrokePath(GrGLuint path, GrGLint reference,
|
||||
GrGLuint mask, GrGLenum coverMode) SK_OVERRIDE;
|
||||
virtual GrGLvoid stencilThenCoverFillPathInstanced(
|
||||
GrGLsizei numPaths, GrGLenum pathNameType, const GrGLvoid *paths,
|
||||
GrGLuint pathBase, GrGLenum fillMode, GrGLuint mask, GrGLenum coverMode,
|
||||
GrGLenum transformType, const GrGLfloat *transformValues) SK_OVERRIDE;
|
||||
virtual GrGLvoid stencilThenCoverStrokePathInstanced(
|
||||
GrGLsizei numPaths, GrGLenum pathNameType, const GrGLvoid *paths,
|
||||
GrGLuint pathBase, GrGLint reference, GrGLuint mask, GrGLenum coverMode,
|
||||
GrGLenum transformType, const GrGLfloat *transformValues) SK_OVERRIDE;
|
||||
};
|
||||
|
||||
class GrGLPathRenderingV13 : public GrGLPathRenderingV12 {
|
||||
public:
|
||||
GrGLPathRenderingV13(const GrGLInterface* glInterface)
|
||||
: GrGLPathRenderingV12(glInterface) {
|
||||
fCaps.fragmentInputGenSupport = true;
|
||||
}
|
||||
|
||||
virtual GrGLvoid programPathFragmentInputGen(GrGLuint program, GrGLint location,
|
||||
GrGLenum genMode, GrGLint components,
|
||||
const GrGLfloat *coeffs) SK_OVERRIDE;
|
||||
};
|
||||
|
||||
|
||||
GrGLPathRendering* GrGLPathRendering::Create(const GrGLInterface* glInterface) {
|
||||
if (NULL == glInterface->fFunctions.fStencilThenCoverFillPath ||
|
||||
NULL == glInterface->fFunctions.fStencilThenCoverStrokePath ||
|
||||
NULL == glInterface->fFunctions.fStencilThenCoverFillPathInstanced ||
|
||||
NULL == glInterface->fFunctions.fStencilThenCoverStrokePathInstanced) {
|
||||
return new GrGLPathRendering(glInterface);
|
||||
}
|
||||
|
||||
if (NULL == glInterface->fFunctions.fProgramPathFragmentInputGen) {
|
||||
return new GrGLPathRenderingV12(glInterface);
|
||||
}
|
||||
|
||||
return new GrGLPathRenderingV13(glInterface);
|
||||
}
|
||||
|
||||
GrGLPathRendering::GrGLPathRendering(const GrGLInterface* glInterface)
|
||||
: fGLInterface(SkRef(glInterface)) {
|
||||
memset(&fCaps, 0, sizeof(fCaps));
|
||||
}
|
||||
|
||||
GrGLPathRendering::~GrGLPathRendering() {
|
||||
}
|
||||
|
||||
void GrGLPathRendering::abandonGpuResources() {
|
||||
fPathNameAllocator.reset(NULL);
|
||||
}
|
||||
|
||||
|
||||
// NV_path_rendering
|
||||
GrGLuint GrGLPathRendering::genPaths(GrGLsizei range) {
|
||||
if (range > 1) {
|
||||
GrGLuint name;
|
||||
GL_CALL_RET(name, GenPaths(range));
|
||||
return name;
|
||||
}
|
||||
|
||||
if (NULL == fPathNameAllocator.get()) {
|
||||
static const int range = 65536;
|
||||
GrGLuint firstName;
|
||||
GL_CALL_RET(firstName, GenPaths(range));
|
||||
fPathNameAllocator.reset(SkNEW_ARGS(GrGLNameAllocator, (firstName, firstName + range)));
|
||||
}
|
||||
|
||||
// When allocating names one at a time, pull from a client-side pool of
|
||||
// available names in order to save a round trip to the GL server.
|
||||
GrGLuint name = fPathNameAllocator->allocateName();
|
||||
|
||||
if (0 == name) {
|
||||
// Our reserved path names are all in use. Fall back on GenPaths.
|
||||
GL_CALL_RET(name, GenPaths(1));
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
GrGLvoid GrGLPathRendering::deletePaths(GrGLuint path, GrGLsizei range) {
|
||||
if (range > 1) {
|
||||
// It is not supported to delete names in ranges that were allocated
|
||||
// individually using GrGLPathNameAllocator.
|
||||
SkASSERT(NULL == fPathNameAllocator.get() ||
|
||||
path + range <= fPathNameAllocator->firstName() ||
|
||||
path >= fPathNameAllocator->endName());
|
||||
GL_CALL(DeletePaths(path, range));
|
||||
return;
|
||||
}
|
||||
|
||||
if (NULL == fPathNameAllocator.get() ||
|
||||
path < fPathNameAllocator->firstName() ||
|
||||
path >= fPathNameAllocator->endName()) {
|
||||
// If we aren't inside fPathNameAllocator's range then this name was
|
||||
// generated by the GenPaths fallback (or else was never allocated).
|
||||
GL_CALL(DeletePaths(path, 1));
|
||||
return;
|
||||
}
|
||||
|
||||
// Make the path empty to save memory, but don't free the name in the driver.
|
||||
GL_CALL(PathCommands(path, 0, NULL, 0, GR_GL_FLOAT, NULL));
|
||||
fPathNameAllocator->free(path);
|
||||
}
|
||||
|
||||
GrGLvoid GrGLPathRendering::pathCommands(GrGLuint path, GrGLsizei numCommands,
|
||||
const GrGLubyte *commands, GrGLsizei numCoords,
|
||||
GrGLenum coordType, const GrGLvoid *coords) {
|
||||
GL_CALL(PathCommands(path, numCommands, commands, numCoords, coordType, coords));
|
||||
}
|
||||
|
||||
GrGLvoid GrGLPathRendering::pathCoords(GrGLuint path, GrGLsizei numCoords,
|
||||
GrGLenum coordType, const GrGLvoid *coords) {
|
||||
GL_CALL(PathCoords(path, numCoords, coordType, coords));
|
||||
}
|
||||
|
||||
GrGLvoid GrGLPathRendering::pathParameteri(GrGLuint path, GrGLenum pname, GrGLint value) {
|
||||
GL_CALL(PathParameteri(path, pname, value));
|
||||
}
|
||||
|
||||
GrGLvoid GrGLPathRendering::pathParameterf(GrGLuint path, GrGLenum pname, GrGLfloat value) {
|
||||
GL_CALL(PathParameterf(path, pname, value));
|
||||
}
|
||||
|
||||
GrGLboolean GrGLPathRendering::isPath(GrGLuint path) {
|
||||
GrGLboolean ret;
|
||||
GL_CALL_RET(ret, IsPath(path));
|
||||
return ret;
|
||||
}
|
||||
|
||||
GrGLvoid GrGLPathRendering::pathStencilFunc(GrGLenum func, GrGLint ref, GrGLuint mask) {
|
||||
GL_CALL(PathStencilFunc(func, ref, mask));
|
||||
}
|
||||
|
||||
GrGLvoid GrGLPathRendering::stencilFillPath(GrGLuint path, GrGLenum fillMode, GrGLuint mask) {
|
||||
GL_CALL(StencilFillPath(path, fillMode, mask));
|
||||
}
|
||||
|
||||
GrGLvoid GrGLPathRendering::stencilStrokePath(GrGLuint path, GrGLint reference, GrGLuint mask) {
|
||||
GL_CALL(StencilStrokePath(path, reference, mask));
|
||||
}
|
||||
|
||||
GrGLvoid GrGLPathRendering::stencilFillPathInstanced(
|
||||
GrGLsizei numPaths, GrGLenum pathNameType, const GrGLvoid *paths,
|
||||
GrGLuint pathBase, GrGLenum fillMode, GrGLuint mask,
|
||||
GrGLenum transformType, const GrGLfloat *transformValues) {
|
||||
GL_CALL(StencilFillPathInstanced(numPaths, pathNameType, paths, pathBase,
|
||||
fillMode, mask, transformType, transformValues));
|
||||
}
|
||||
|
||||
GrGLvoid GrGLPathRendering::stencilStrokePathInstanced(
|
||||
GrGLsizei numPaths, GrGLenum pathNameType, const GrGLvoid *paths,
|
||||
GrGLuint pathBase, GrGLint reference, GrGLuint mask,
|
||||
GrGLenum transformType, const GrGLfloat *transformValues) {
|
||||
GL_CALL(StencilStrokePathInstanced(numPaths, pathNameType, paths, pathBase,
|
||||
reference, mask, transformType, transformValues));
|
||||
}
|
||||
|
||||
GrGLvoid GrGLPathRendering::pathTexGen(GrGLenum texCoordSet, GrGLenum genMode,
|
||||
GrGLint components, const GrGLfloat *coeffs) {
|
||||
GL_CALL(PathTexGen(texCoordSet, genMode, components, coeffs));
|
||||
}
|
||||
|
||||
GrGLvoid GrGLPathRendering::coverFillPath(GrGLuint path, GrGLenum coverMode) {
|
||||
GL_CALL(CoverFillPath(path, coverMode));
|
||||
}
|
||||
|
||||
GrGLvoid GrGLPathRendering::coverStrokePath(GrGLuint name, GrGLenum coverMode) {
|
||||
GL_CALL(CoverStrokePath(name, coverMode));
|
||||
}
|
||||
|
||||
GrGLvoid GrGLPathRendering::coverFillPathInstanced(
|
||||
GrGLsizei numPaths, GrGLenum pathNameType, const GrGLvoid *paths, GrGLuint pathBase,
|
||||
GrGLenum coverMode, GrGLenum transformType, const GrGLfloat *transformValues) {
|
||||
GL_CALL(CoverFillPathInstanced(numPaths, pathNameType, paths, pathBase,
|
||||
coverMode, transformType, transformValues));
|
||||
}
|
||||
|
||||
GrGLvoid GrGLPathRendering::coverStrokePathInstanced(
|
||||
GrGLsizei numPaths, GrGLenum pathNameType, const GrGLvoid *paths, GrGLuint pathBase,
|
||||
GrGLenum coverMode, GrGLenum transformType, const GrGLfloat* transformValues) {
|
||||
GL_CALL(CoverStrokePathInstanced(numPaths, pathNameType, paths, pathBase,
|
||||
coverMode, transformType, transformValues));
|
||||
}
|
||||
|
||||
GrGLvoid GrGLPathRendering::stencilThenCoverFillPath(GrGLuint path, GrGLenum fillMode,
|
||||
GrGLuint mask, GrGLenum coverMode) {
|
||||
GL_CALL(StencilFillPath(path, fillMode, mask));
|
||||
GL_CALL(CoverFillPath(path, coverMode));
|
||||
}
|
||||
|
||||
GrGLvoid GrGLPathRendering::stencilThenCoverStrokePath(GrGLuint path, GrGLint reference,
|
||||
GrGLuint mask, GrGLenum coverMode) {
|
||||
GL_CALL(StencilStrokePath(path, reference, mask));
|
||||
GL_CALL(CoverStrokePath(path, coverMode));
|
||||
}
|
||||
|
||||
GrGLvoid GrGLPathRendering::stencilThenCoverFillPathInstanced(
|
||||
GrGLsizei numPaths, GrGLenum pathNameType, const GrGLvoid *paths,
|
||||
GrGLuint pathBase, GrGLenum fillMode, GrGLuint mask, GrGLenum coverMode,
|
||||
GrGLenum transformType, const GrGLfloat *transformValues) {
|
||||
GL_CALL(StencilFillPathInstanced(numPaths, pathNameType, paths, pathBase,
|
||||
fillMode, mask, transformType, transformValues));
|
||||
GL_CALL(CoverFillPathInstanced(numPaths, pathNameType, paths, pathBase,
|
||||
coverMode, transformType, transformValues));
|
||||
}
|
||||
|
||||
GrGLvoid GrGLPathRendering::stencilThenCoverStrokePathInstanced(
|
||||
GrGLsizei numPaths, GrGLenum pathNameType, const GrGLvoid *paths,
|
||||
GrGLuint pathBase, GrGLint reference, GrGLuint mask, GrGLenum coverMode,
|
||||
GrGLenum transformType, const GrGLfloat *transformValues) {
|
||||
GL_CALL(StencilStrokePathInstanced(numPaths, pathNameType, paths, pathBase,
|
||||
reference, mask, transformType, transformValues));
|
||||
GL_CALL(CoverStrokePathInstanced(numPaths, pathNameType, paths, pathBase,
|
||||
coverMode, transformType, transformValues));
|
||||
}
|
||||
|
||||
GrGLvoid GrGLPathRendering::programPathFragmentInputGen(
|
||||
GrGLuint program, GrGLint location, GrGLenum genMode,
|
||||
GrGLint components, const GrGLfloat *coeffs) {
|
||||
SkFAIL("ProgramPathFragmentInputGen not supported in this GL context.");
|
||||
}
|
||||
|
||||
|
||||
// NV_path_rendering v1.2
|
||||
GrGLvoid GrGLPathRenderingV12::stencilThenCoverFillPath(GrGLuint path, GrGLenum fillMode,
|
||||
GrGLuint mask, GrGLenum coverMode) {
|
||||
GL_CALL(StencilThenCoverFillPath(path, fillMode, mask, coverMode));
|
||||
}
|
||||
|
||||
GrGLvoid GrGLPathRenderingV12::stencilThenCoverStrokePath(GrGLuint path, GrGLint reference,
|
||||
GrGLuint mask, GrGLenum coverMode) {
|
||||
GL_CALL(StencilThenCoverStrokePath(path, reference, mask, coverMode));
|
||||
}
|
||||
|
||||
GrGLvoid GrGLPathRenderingV12::stencilThenCoverFillPathInstanced(
|
||||
GrGLsizei numPaths, GrGLenum pathNameType, const GrGLvoid *paths,
|
||||
GrGLuint pathBase, GrGLenum fillMode, GrGLuint mask, GrGLenum coverMode,
|
||||
GrGLenum transformType, const GrGLfloat *transformValues) {
|
||||
GL_CALL(StencilThenCoverFillPathInstanced(numPaths, pathNameType, paths, pathBase, fillMode,
|
||||
mask, coverMode, transformType, transformValues));
|
||||
}
|
||||
|
||||
GrGLvoid GrGLPathRenderingV12::stencilThenCoverStrokePathInstanced(
|
||||
GrGLsizei numPaths, GrGLenum pathNameType, const GrGLvoid *paths,
|
||||
GrGLuint pathBase, GrGLint reference, GrGLuint mask, GrGLenum coverMode,
|
||||
GrGLenum transformType, const GrGLfloat *transformValues) {
|
||||
GL_CALL(StencilThenCoverStrokePathInstanced(numPaths, pathNameType, paths, pathBase, reference,
|
||||
mask, coverMode, transformType, transformValues));
|
||||
}
|
||||
|
||||
|
||||
// NV_path_rendering v1.3
|
||||
GrGLvoid GrGLPathRenderingV13::programPathFragmentInputGen(
|
||||
GrGLuint program, GrGLint location, GrGLenum genMode,
|
||||
GrGLint components, const GrGLfloat *coeffs) {
|
||||
GL_CALL(ProgramPathFragmentInputGen(program, location, genMode, components, coeffs));
|
||||
}
|
108
src/gpu/gl/GrGLPathRendering.h
Normal file
108
src/gpu/gl/GrGLPathRendering.h
Normal file
@ -0,0 +1,108 @@
|
||||
/*
|
||||
* 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 GrGLPathRendering_DEFINED
|
||||
#define GrGLPathRendering_DEFINED
|
||||
|
||||
#include "SkRefCnt.h"
|
||||
#include "gl/GrGLFunctions.h"
|
||||
|
||||
class GrGLNameAllocator;
|
||||
struct GrGLInterface;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
class GrGLPathRendering {
|
||||
public:
|
||||
/**
|
||||
* Create a new GrGLPathRendering object from a given GL interface. Unless
|
||||
* otherwise specified in the caps, every method will work properly, even
|
||||
* if it did not exist in the GL interface.
|
||||
*/
|
||||
static GrGLPathRendering* Create(const GrGLInterface*);
|
||||
virtual ~GrGLPathRendering();
|
||||
|
||||
/**
|
||||
* Mark certain functionality as not supported if the driver version is too
|
||||
* old and a backup implementation is not practical.
|
||||
*/
|
||||
struct Caps {
|
||||
bool fragmentInputGenSupport : 1;
|
||||
};
|
||||
const Caps& caps() const { return fCaps; }
|
||||
|
||||
/**
|
||||
* Called when the GPU resources have been lost and need to be abandoned
|
||||
* (for example after a context loss).
|
||||
*/
|
||||
void abandonGpuResources();
|
||||
|
||||
// NV_path_rendering
|
||||
GrGLuint genPaths(GrGLsizei range);
|
||||
GrGLvoid deletePaths(GrGLuint path, GrGLsizei range);
|
||||
GrGLvoid pathCommands(GrGLuint path, GrGLsizei numCommands, const GrGLubyte *commands,
|
||||
GrGLsizei numCoords, GrGLenum coordType, const GrGLvoid *coords);
|
||||
GrGLvoid pathCoords(GrGLuint path, GrGLsizei numCoords,
|
||||
GrGLenum coordType, const GrGLvoid *coords);
|
||||
GrGLvoid pathParameteri(GrGLuint path, GrGLenum pname, GrGLint value);
|
||||
GrGLvoid pathParameterf(GrGLuint path, GrGLenum pname, GrGLfloat value);
|
||||
GrGLboolean isPath(GrGLuint path);
|
||||
GrGLvoid pathStencilFunc(GrGLenum func, GrGLint ref, GrGLuint mask);
|
||||
GrGLvoid stencilFillPath(GrGLuint path, GrGLenum fillMode, GrGLuint mask);
|
||||
GrGLvoid stencilStrokePath(GrGLuint path, GrGLint reference, GrGLuint mask);
|
||||
GrGLvoid stencilFillPathInstanced(GrGLsizei numPaths, GrGLenum pathNameType,
|
||||
const GrGLvoid *paths, GrGLuint pathBase, GrGLenum fillMode,
|
||||
GrGLuint mask, GrGLenum transformType,
|
||||
const GrGLfloat *transformValues);
|
||||
GrGLvoid stencilStrokePathInstanced(GrGLsizei numPaths, GrGLenum pathNameType,
|
||||
const GrGLvoid *paths, GrGLuint pathBase,
|
||||
GrGLint reference, GrGLuint mask, GrGLenum transformType,
|
||||
const GrGLfloat *transformValues);
|
||||
GrGLvoid pathTexGen(GrGLenum texCoordSet, GrGLenum genMode,
|
||||
GrGLint components, const GrGLfloat *coeffs);
|
||||
GrGLvoid coverFillPath(GrGLuint path, GrGLenum coverMode);
|
||||
GrGLvoid coverStrokePath(GrGLuint name, GrGLenum coverMode);
|
||||
GrGLvoid coverFillPathInstanced(GrGLsizei numPaths, GrGLenum pathNameType,
|
||||
const GrGLvoid *paths, GrGLuint pathBase, GrGLenum coverMode,
|
||||
GrGLenum transformType, const GrGLfloat *transformValues);
|
||||
GrGLvoid coverStrokePathInstanced(GrGLsizei numPaths, GrGLenum pathNameType,
|
||||
const GrGLvoid *paths, GrGLuint pathBase, GrGLenum coverMode,
|
||||
GrGLenum transformType, const GrGLfloat* transformValues);
|
||||
|
||||
// NV_path_rendering v1.2
|
||||
virtual GrGLvoid stencilThenCoverFillPath(GrGLuint path, GrGLenum fillMode,
|
||||
GrGLuint mask, GrGLenum coverMode);
|
||||
virtual GrGLvoid stencilThenCoverStrokePath(GrGLuint path, GrGLint reference,
|
||||
GrGLuint mask, GrGLenum coverMode);
|
||||
virtual GrGLvoid stencilThenCoverFillPathInstanced(
|
||||
GrGLsizei numPaths, GrGLenum pathNameType, const GrGLvoid *paths,
|
||||
GrGLuint pathBase, GrGLenum fillMode, GrGLuint mask, GrGLenum coverMode,
|
||||
GrGLenum transformType, const GrGLfloat *transformValues);
|
||||
virtual GrGLvoid stencilThenCoverStrokePathInstanced(
|
||||
GrGLsizei numPaths, GrGLenum pathNameType, const GrGLvoid *paths,
|
||||
GrGLuint pathBase, GrGLint reference, GrGLuint mask, GrGLenum coverMode,
|
||||
GrGLenum transformType, const GrGLfloat *transformValues);
|
||||
|
||||
// NV_path_rendering v1.3
|
||||
virtual GrGLvoid programPathFragmentInputGen(GrGLuint program, GrGLint location,
|
||||
GrGLenum genMode, GrGLint components,
|
||||
const GrGLfloat *coeffs);
|
||||
|
||||
protected:
|
||||
GrGLPathRendering(const GrGLInterface*);
|
||||
|
||||
SkAutoTUnref<const GrGLInterface> fGLInterface;
|
||||
SkAutoTDelete<GrGLNameAllocator> fPathNameAllocator;
|
||||
Caps fCaps;
|
||||
};
|
||||
|
||||
#endif
|
@ -7,10 +7,10 @@
|
||||
|
||||
|
||||
#include "GrGpuGL.h"
|
||||
#include "GrGLNameAllocator.h"
|
||||
#include "GrGLStencilBuffer.h"
|
||||
#include "GrGLPath.h"
|
||||
#include "GrGLPathRange.h"
|
||||
#include "GrGLPathRendering.h"
|
||||
#include "GrGLShaderBuilder.h"
|
||||
#include "GrTemplates.h"
|
||||
#include "GrTypes.h"
|
||||
@ -164,6 +164,10 @@ GrGpuGL::GrGpuGL(const GrGLContext& ctx, GrContext* context)
|
||||
|
||||
fLastSuccessfulStencilFmtIdx = 0;
|
||||
fHWProgramID = 0;
|
||||
|
||||
if (this->glCaps().pathRenderingSupport()) {
|
||||
fPathRendering.reset(GrGLPathRendering::Create(glInterface()));
|
||||
}
|
||||
}
|
||||
|
||||
GrGpuGL::~GrGpuGL() {
|
||||
@ -329,7 +333,7 @@ void GrGpuGL::onResetContext(uint32_t resetBits) {
|
||||
GL_CALL(MatrixLoadIdentity(GR_GL_MODELVIEW));
|
||||
|
||||
for (int i = 0; i < this->glCaps().maxFixedFunctionTextureCoords(); ++i) {
|
||||
GL_CALL(PathTexGen(GR_GL_TEXTURE0 + i, GR_GL_NONE, 0, NULL));
|
||||
fPathRendering->pathTexGen(GR_GL_TEXTURE0 + i, GR_GL_NONE, 0, NULL);
|
||||
fHWPathTexGenSettings[i].fMode = GR_GL_NONE;
|
||||
fHWPathTexGenSettings[i].fNumComponents = 0;
|
||||
}
|
||||
@ -1881,7 +1885,7 @@ void GrGpuGL::onGpuStencilPath(const GrPath* path, SkPath::FillType fill) {
|
||||
GrGLenum fillMode =
|
||||
gr_stencil_op_to_gl_path_rendering_fill_mode(fHWPathStencilSettings.passOp(GrStencilSettings::kFront_Face));
|
||||
GrGLint writeMask = fHWPathStencilSettings.writeMask(GrStencilSettings::kFront_Face);
|
||||
GL_CALL(StencilFillPath(id, fillMode, writeMask));
|
||||
fPathRendering->stencilFillPath(id, fillMode, writeMask);
|
||||
}
|
||||
|
||||
void GrGpuGL::onGpuDrawPath(const GrPath* path, SkPath::FillType fill) {
|
||||
@ -1904,18 +1908,18 @@ void GrGpuGL::onGpuDrawPath(const GrPath* path, SkPath::FillType fill) {
|
||||
if (nonInvertedFill == fill) {
|
||||
if (stroke.needToApply()) {
|
||||
if (SkStrokeRec::kStrokeAndFill_Style == stroke.getStyle()) {
|
||||
GL_CALL(StencilFillPath(id, fillMode, writeMask));
|
||||
fPathRendering->stencilFillPath(id, fillMode, writeMask);
|
||||
}
|
||||
GL_CALL(StencilThenCoverStrokePath(id, 0xffff, writeMask, GR_GL_BOUNDING_BOX));
|
||||
fPathRendering->stencilThenCoverStrokePath(id, 0xffff, writeMask, GR_GL_BOUNDING_BOX);
|
||||
} else {
|
||||
GL_CALL(StencilThenCoverFillPath(id, fillMode, writeMask, GR_GL_BOUNDING_BOX));
|
||||
fPathRendering->stencilThenCoverFillPath(id, fillMode, writeMask, GR_GL_BOUNDING_BOX);
|
||||
}
|
||||
} else {
|
||||
if (stroke.isFillStyle() || SkStrokeRec::kStrokeAndFill_Style == stroke.getStyle()) {
|
||||
GL_CALL(StencilFillPath(id, fillMode, writeMask));
|
||||
fPathRendering->stencilFillPath(id, fillMode, writeMask);
|
||||
}
|
||||
if (stroke.needToApply()) {
|
||||
GL_CALL(StencilStrokePath(id, 0xffff, writeMask));
|
||||
fPathRendering->stencilStrokePath(id, 0xffff, writeMask);
|
||||
}
|
||||
|
||||
GrDrawState* drawState = this->drawState();
|
||||
@ -1966,33 +1970,33 @@ void GrGpuGL::onGpuDrawPaths(const GrPathRange* pathRange,
|
||||
if (nonInvertedFill == fill) {
|
||||
if (stroke.needToApply()) {
|
||||
if (SkStrokeRec::kStrokeAndFill_Style == stroke.getStyle()) {
|
||||
GL_CALL(StencilFillPathInstanced(
|
||||
count, GR_GL_UNSIGNED_INT, indices, baseID, fillMode,
|
||||
writeMask, gXformType2GLType[transformsType],
|
||||
transforms));
|
||||
fPathRendering->stencilFillPathInstanced(
|
||||
count, GR_GL_UNSIGNED_INT, indices, baseID, fillMode,
|
||||
writeMask, gXformType2GLType[transformsType],
|
||||
transforms);
|
||||
}
|
||||
GL_CALL(StencilThenCoverStrokePathInstanced(
|
||||
count, GR_GL_UNSIGNED_INT, indices, baseID, 0xffff, writeMask,
|
||||
GR_GL_BOUNDING_BOX_OF_BOUNDING_BOXES,
|
||||
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 {
|
||||
GL_CALL(StencilThenCoverFillPathInstanced(
|
||||
count, GR_GL_UNSIGNED_INT, indices, baseID, fillMode, writeMask,
|
||||
GR_GL_BOUNDING_BOX_OF_BOUNDING_BOXES,
|
||||
gXformType2GLType[transformsType], transforms));
|
||||
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()) {
|
||||
GL_CALL(StencilFillPathInstanced(
|
||||
count, GR_GL_UNSIGNED_INT, indices, baseID, fillMode,
|
||||
writeMask, gXformType2GLType[transformsType],
|
||||
transforms));
|
||||
fPathRendering->stencilFillPathInstanced(
|
||||
count, GR_GL_UNSIGNED_INT, indices, baseID, fillMode,
|
||||
writeMask, gXformType2GLType[transformsType],
|
||||
transforms);
|
||||
}
|
||||
if (stroke.needToApply()) {
|
||||
GL_CALL(StencilStrokePathInstanced(
|
||||
count, GR_GL_UNSIGNED_INT, indices, baseID, 0xffff,
|
||||
writeMask, gXformType2GLType[transformsType],
|
||||
transforms));
|
||||
fPathRendering->stencilStrokePathInstanced(
|
||||
count, GR_GL_UNSIGNED_INT, indices, baseID, 0xffff,
|
||||
writeMask, gXformType2GLType[transformsType],
|
||||
transforms);
|
||||
}
|
||||
|
||||
GrDrawState* drawState = this->drawState();
|
||||
@ -2210,9 +2214,9 @@ void GrGpuGL::flushPathStencilSettings(SkPath::FillType fill) {
|
||||
// that draws the path to the SB (glStencilFillPath)
|
||||
GrGLenum func =
|
||||
gr_to_gl_stencil_func(pathStencilSettings.func(GrStencilSettings::kFront_Face));
|
||||
GL_CALL(PathStencilFunc(func,
|
||||
pathStencilSettings.funcRef(GrStencilSettings::kFront_Face),
|
||||
pathStencilSettings.funcMask(GrStencilSettings::kFront_Face)));
|
||||
fPathRendering->pathStencilFunc(
|
||||
func, pathStencilSettings.funcRef(GrStencilSettings::kFront_Face),
|
||||
pathStencilSettings.funcMask(GrStencilSettings::kFront_Face));
|
||||
|
||||
fHWPathStencilSettings = pathStencilSettings;
|
||||
}
|
||||
@ -2403,10 +2407,10 @@ void GrGpuGL::enablePathTexGen(int unitIdx,
|
||||
this->setTextureUnit(unitIdx);
|
||||
|
||||
fHWPathTexGenSettings[unitIdx].fNumComponents = components;
|
||||
GL_CALL(PathTexGen(GR_GL_TEXTURE0 + unitIdx,
|
||||
GR_GL_OBJECT_LINEAR,
|
||||
components,
|
||||
coefficients));
|
||||
fPathRendering->pathTexGen(GR_GL_TEXTURE0 + unitIdx,
|
||||
GR_GL_OBJECT_LINEAR,
|
||||
components,
|
||||
coefficients);
|
||||
|
||||
memcpy(fHWPathTexGenSettings[unitIdx].fCoefficients, coefficients,
|
||||
3 * components * sizeof(GrGLfloat));
|
||||
@ -2455,7 +2459,7 @@ void GrGpuGL::flushPathTexGenSettings(int numUsedTexCoordSets) {
|
||||
SkASSERT(0 != fHWPathTexGenSettings[i].fNumComponents);
|
||||
|
||||
this->setTextureUnit(i);
|
||||
GL_CALL(PathTexGen(GR_GL_TEXTURE0 + i, GR_GL_NONE, 0, NULL));
|
||||
fPathRendering->pathTexGen(GR_GL_TEXTURE0 + i, GR_GL_NONE, 0, NULL);
|
||||
fHWPathTexGenSettings[i].fNumComponents = 0;
|
||||
}
|
||||
|
||||
@ -2511,38 +2515,6 @@ void GrGpuGL::flushMiscFixedFunctionState() {
|
||||
}
|
||||
}
|
||||
|
||||
GrGLuint GrGpuGL::createGLPathObject() {
|
||||
if (NULL == fPathNameAllocator.get()) {
|
||||
static const int range = 65536;
|
||||
GrGLuint firstName;
|
||||
GL_CALL_RET(firstName, GenPaths(range));
|
||||
fPathNameAllocator.reset(SkNEW_ARGS(GrGLNameAllocator, (firstName, firstName + range)));
|
||||
}
|
||||
|
||||
GrGLuint name = fPathNameAllocator->allocateName();
|
||||
if (0 == name) {
|
||||
// Our reserved path names are all in use. Fall back on GenPaths.
|
||||
GL_CALL_RET(name, GenPaths(1));
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
void GrGpuGL::deleteGLPathObject(GrGLuint name) {
|
||||
if (NULL == fPathNameAllocator.get() ||
|
||||
name < fPathNameAllocator->firstName() ||
|
||||
name >= fPathNameAllocator->endName()) {
|
||||
// If we aren't inside fPathNameAllocator's range then this name was
|
||||
// generated by the GenPaths fallback (or else the name is unallocated).
|
||||
GL_CALL(DeletePaths(name, 1));
|
||||
return;
|
||||
}
|
||||
|
||||
// Make the path empty to save memory, but don't free the name in the driver.
|
||||
GL_CALL(PathCommands(name, 0, NULL, 0, GR_GL_FLOAT, NULL));
|
||||
fPathNameAllocator->free(name);
|
||||
}
|
||||
|
||||
bool GrGpuGL::configToGLFormats(GrPixelConfig config,
|
||||
bool getSizedInternalFormat,
|
||||
GrGLenum* internalFormat,
|
||||
|
@ -24,7 +24,7 @@
|
||||
#define PROGRAM_CACHE_STATS
|
||||
#endif
|
||||
|
||||
class GrGLNameAllocator;
|
||||
class GrGLPathRendering;
|
||||
|
||||
class GrGpuGL : public GrGpu {
|
||||
public:
|
||||
@ -40,6 +40,11 @@ public:
|
||||
GrGLSLGeneration glslGeneration() const { return fGLContext.glslGeneration(); }
|
||||
const GrGLCaps& glCaps() const { return *fGLContext.caps(); }
|
||||
|
||||
GrGLPathRendering* pathRendering() const {
|
||||
SkASSERT(glCaps().pathRenderingSupport());
|
||||
return fPathRendering.get();
|
||||
}
|
||||
|
||||
virtual void discard(GrRenderTarget*) SK_OVERRIDE;
|
||||
|
||||
// Used by GrGLProgram and GrGLPathTexGenProgramEffects to configure OpenGL
|
||||
@ -104,11 +109,6 @@ public:
|
||||
fHWGeometryState.notifyIndexBufferDelete(id);
|
||||
}
|
||||
|
||||
// These functions should be used to generate and delete GL path names. They have their own
|
||||
// allocator that runs on the client side, so they are much faster than going through GenPaths.
|
||||
GrGLuint createGLPathObject();
|
||||
void deleteGLPathObject(GrGLuint);
|
||||
|
||||
protected:
|
||||
virtual bool onCopySurface(GrSurface* dst,
|
||||
GrSurface* src,
|
||||
@ -470,7 +470,7 @@ private:
|
||||
// from our loop that tries stencil formats and calls check fb status.
|
||||
int fLastSuccessfulStencilFmtIdx;
|
||||
|
||||
SkAutoTDelete<GrGLNameAllocator> fPathNameAllocator;
|
||||
SkAutoTDelete<GrGLPathRendering> fPathRendering;
|
||||
|
||||
typedef GrGpu INHERITED;
|
||||
};
|
||||
|
@ -10,7 +10,7 @@
|
||||
#include "GrEffect.h"
|
||||
#include "GrGLEffect.h"
|
||||
#include "SkRTConf.h"
|
||||
#include "GrGLNameAllocator.h"
|
||||
#include "GrGLPathRendering.h"
|
||||
#include "SkTSearch.h"
|
||||
|
||||
#ifdef PROGRAM_CACHE_STATS
|
||||
@ -203,7 +203,9 @@ void GrGpuGL::abandonResources(){
|
||||
INHERITED::abandonResources();
|
||||
fProgramCache->abandon();
|
||||
fHWProgramID = 0;
|
||||
fPathNameAllocator.reset(NULL);
|
||||
if (this->glCaps().pathRenderingSupport()) {
|
||||
fPathRendering->abandonGpuResources();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
Loading…
Reference in New Issue
Block a user