Turn NVPR on by default (but off in tools).

BUG=skia:2042

Committed: http://code.google.com/p/skia/source/detail?r=13164

R=robertphillips@google.com

Author: bsalomon@google.com

Review URL: https://codereview.chromium.org/144003006

git-svn-id: http://skia.googlecode.com/svn/trunk@13176 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
commit-bot@chromium.org 2014-01-24 20:49:44 +00:00
parent 8f22011449
commit d8ed85101e
14 changed files with 190 additions and 16468 deletions

View File

@ -86,7 +86,6 @@
'skia_sanitizer%': '',
'skia_scalar%': 'float',
'skia_mesa%': 0,
'skia_nv_path_rendering%': 0,
'skia_stroke_path_rendering%': 0,
'skia_android_path_rendering%': 0,
'skia_resource_cache_mb_limit%': 0,
@ -145,7 +144,6 @@
'skia_sanitizer%': '<(skia_sanitizer)',
'skia_scalar%': '<(skia_scalar)',
'skia_mesa%': '<(skia_mesa)',
'skia_nv_path_rendering%': '<(skia_nv_path_rendering)',
'skia_stroke_path_rendering%': '<(skia_stroke_path_rendering)',
'skia_android_path_rendering%': '<(skia_android_path_rendering)',
'skia_resource_cache_mb_limit%': '<(skia_resource_cache_mb_limit)',

View File

@ -107,11 +107,6 @@
'gpu.gypi', # Makes the gypi appear in IDEs (but does not modify the build).
],
'conditions': [
[ 'skia_nv_path_rendering', {
'defines': [
'GR_GL_USE_NV_PATH_RENDERING=1',
],
}],
[ 'skia_stroke_path_rendering', {
'sources': [
'../experimental/StrokePathRenderer/GrStrokePathRenderer.h',

View File

@ -26,12 +26,15 @@
* GrContexts backed by different types of GL contexts. It manages creating the
* GL context and a GrContext that uses it. The GL/Gr contexts persist until the
* factory is destroyed (though the caller can always grab a ref on the returned
* GrContext to make it outlive the factory).
* Gr and GL contexts to make them outlive the factory).
*/
class GrContextFactory : public SkNoncopyable {
public:
/**
* Types of GL contexts supported.
* Types of GL contexts supported. For historical and testing reasons the native GrContext will
* not use "GL_NV_path_rendering" even when the driver supports it. There is a separate context
* type that does not remove NVPR support and which will fail when the driver does not support
* the extension.
*/
enum GLContextType {
kNative_GLContextType,
@ -41,6 +44,9 @@ public:
#if SK_MESA
kMESA_GLContextType,
#endif
/** Similar to kNative but does not filter NVPR. It will fail if the GL driver does not
support NVPR */
kNVPR_GLContextType,
kNull_GLContextType,
kDebug_GLContextType,
@ -73,6 +79,8 @@ public:
case kMESA_GLContextType:
return "mesa";
#endif
case kNVPR_GLContextType:
return "nvpr";
case kDebug_GLContextType:
return "debug";
default:
@ -87,6 +95,7 @@ public:
void destroyContexts() {
for (int i = 0; i < fContexts.count(); ++i) {
fContexts[i].fGLContext->makeCurrent();
fContexts[i].fGrContext->unref();
fContexts[i].fGLContext->unref();
}
@ -107,6 +116,7 @@ public:
SkAutoTUnref<SkGLContextHelper> glCtx;
SkAutoTUnref<GrContext> grCtx;
switch (type) {
case kNVPR_GLContextType: // fallthru
case kNative_GLContextType:
glCtx.reset(SkNEW(SkNativeGLContext));
break;
@ -134,7 +144,22 @@ public:
if (!glCtx.get()->init(kBogusSize, kBogusSize)) {
return NULL;
}
GrBackendContext p3dctx = reinterpret_cast<GrBackendContext>(glCtx.get()->gl());
// Ensure NVPR is available for the NVPR type and block it from other types.
SkAutoTUnref<const GrGLInterface> glInterface(SkRef(glCtx.get()->gl()));
if (kNVPR_GLContextType == type) {
if (!glInterface->hasExtension("GL_NV_path_rendering")) {
return NULL;
}
} else {
glInterface.reset(GrGLInterfaceRemoveNVPR(glInterface));
if (!glInterface) {
return NULL;
}
}
glCtx->makeCurrent();
GrBackendContext p3dctx = reinterpret_cast<GrBackendContext>(glInterface.get());
grCtx.reset(GrContext::Create(kOpenGL_GrBackend, p3dctx));
if (!grCtx.get()) {
return NULL;

View File

@ -93,10 +93,6 @@
* stencil formats as attachments. If the FBO is complete we will assume
* subsequent attachments with the same formats are complete as well.
*
* GR_GL_USE_NV_PATH_RENDERING: Enable experimental support for
* GL_NV_path_rendering. There are known issues with clipping, non-AA paths, and
* perspective.
*
* GR_GL_MUST_USE_VBO: Indicates that all vertices and indices must be rendered
* from VBOs. Chromium's command buffer doesn't allow glVertexAttribArray with
* ARARY_BUFFER 0 bound or glDrawElements with ELEMENT_ARRAY_BUFFER 0 bound.
@ -158,10 +154,6 @@
#define GR_GL_CHECK_FBO_STATUS_ONCE_PER_FORMAT 0
#endif
#if !defined(GR_GL_USE_NV_PATH_RENDERING)
#define GR_GL_USE_NV_PATH_RENDERING 0
#endif
#if !defined(GR_GL_MUST_USE_VBO)
#define GR_GL_MUST_USE_VBO 0
#endif

View File

@ -19,12 +19,17 @@ struct GrGLInterface;
* queried. It supports both glGetString- and glGetStringi-style extension string APIs and will
* use the latter if it is available.
*/
class GrGLExtensions : public SkNoncopyable {
class GrGLExtensions {
public:
GrGLExtensions() : fInitialized(false), fStrings(SkNEW(SkTArray<SkString>)) {}
GrGLExtensions(const GrGLExtensions&);
GrGLExtensions& operator=(const GrGLExtensions&);
void swap(GrGLExtensions* that) {
fStrings.swap(&that->fStrings);
SkTSwap(fInitialized, that->fInitialized);
}
/**
@ -42,7 +47,12 @@ public:
/**
* Queries whether an extension is present. This will fail if init() has not been called.
*/
bool has(const char*) const;
bool has(const char[]) const;
/**
* Removes an extension if present. Returns true if the extension was present before the call.
*/
bool remove(const char[]);
void reset() { fStrings->reset(); }

View File

@ -72,7 +72,11 @@ typedef void (*GrGLInterfaceCallbackProc)(const GrGLInterface*);
typedef intptr_t GrGLInterfaceCallbackData;
#endif
/*
/** Function that returns a new interface identical to "interface" but without support for
GL_NV_path_rendering. */
const GrGLInterface* GrGLInterfaceRemoveNVPR(const GrGLInterface*);
/**
* GrContext uses the following interface to make all calls into OpenGL. When a
* GrContext is created it is given a GrGLInterface. The interface's function
* pointers must be valid for the OpenGL context associated with the GrContext.
@ -112,6 +116,8 @@ public:
GrGLInterface();
static GrGLInterface* NewClone(const GrGLInterface*);
// Validates that the GrGLInterface supports its advertised standard. This means the necessary
// function pointers have been initialized for both the GL version and any advertised
// extensions.
@ -358,7 +364,6 @@ public:
GLPtr<GrGLPointAlongPathProc> fPointAlongPath;
} fFunctions;
// Temporary workaround aliases to keep Chromium GrGLInterface factories compiling until they
// assign the members of fFunctions.
GLPtrAlias<GrGLActiveTextureProc> fActiveTexture;

View File

@ -210,6 +210,7 @@ public:
fMSAASampleCount = msaaSampleCount;
SkASSERT(NULL == fCurIntf);
SkAutoTUnref<const GrGLInterface> glInterface;
switch (win->getDeviceType()) {
case kRaster_DeviceType:
// fallthrough
@ -217,21 +218,25 @@ public:
// fallthrough
case kGPU_DeviceType:
// all these guys use the native interface
fCurIntf = GrGLCreateNativeInterface();
glInterface.reset(GrGLCreateNativeInterface());
break;
#if SK_ANGLE
case kANGLE_DeviceType:
fCurIntf = GrGLCreateANGLEInterface();
glInterface.reset(GrGLCreateANGLEInterface());
break;
#endif // SK_ANGLE
case kNullGPU_DeviceType:
fCurIntf = GrGLCreateNullInterface();
glInterface.reset(GrGLCreateNullInterface());
break;
default:
SkASSERT(false);
break;
}
// Currently SampleApp does not use NVPR. TODO: Provide an NVPR device type that is skipped
// when the driver doesn't support NVPR.
fCurIntf = GrGLInterfaceRemoveNVPR(glInterface.get());
SkASSERT(NULL == fCurContext);
fCurContext = GrContext::Create(kOpenGL_GrBackend, (GrBackendContext) fCurIntf);
@ -239,6 +244,8 @@ public:
// We need some context and interface to see results
SkSafeUnref(fCurContext);
SkSafeUnref(fCurIntf);
fCurContext = NULL;
fCurIntf = NULL;
SkDebugf("Failed to setup 3D");
win->detach();

View File

@ -309,8 +309,7 @@ void GrGLCaps::init(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) {
// attachment, hence this min:
fMaxRenderTargetSize = GrMin(fMaxTextureSize, fMaxRenderTargetSize);
fPathRenderingSupport = GR_GL_USE_NV_PATH_RENDERING &&
ctxInfo.hasExtension("GL_NV_path_rendering");
fPathRenderingSupport = ctxInfo.hasExtension("GL_NV_path_rendering");
SkASSERT(!fPathRenderingSupport || fFixedFunctionSupport);
fDstReadInShaderSupport = kNone_FBFetchType != fFBFetchType;

View File

@ -12,12 +12,35 @@
#include "SkTSearch.h"
#include "SkTSort.h"
namespace {
namespace { // This cannot be static because it is used as a template parameter.
inline bool extension_compare(const SkString& a, const SkString& b) {
return strcmp(a.c_str(), b.c_str()) < 0;
}
}
// finds the index of ext in strings or a negative result if ext is not found.
static int find_string(const SkTArray<SkString>& strings, const char ext[]) {
if (strings.empty()) {
return -1;
}
SkString extensionStr(ext);
int idx = SkTSearch<SkString, extension_compare>(&strings.front(),
strings.count(),
extensionStr,
sizeof(SkString));
return idx;
}
GrGLExtensions::GrGLExtensions(const GrGLExtensions& that) : fStrings(SkNEW(SkTArray<SkString>)) {
*this = that;
}
GrGLExtensions& GrGLExtensions::operator=(const GrGLExtensions& that) {
*fStrings = *that.fStrings;
fInitialized = that.fInitialized;
return *this;
}
bool GrGLExtensions::init(GrGLStandard standard,
GrGLGetStringProc getString,
GrGLGetStringiProc getStringi,
@ -76,16 +99,25 @@ bool GrGLExtensions::init(GrGLStandard standard,
return true;
}
bool GrGLExtensions::has(const char* ext) const {
if (fStrings->empty()) {
bool GrGLExtensions::has(const char ext[]) const {
SkASSERT(fInitialized);
return find_string(*fStrings, ext) >= 0;
}
bool GrGLExtensions::remove(const char ext[]) {
SkASSERT(fInitialized);
int idx = find_string(*fStrings, ext);
if (idx >= 0) {
// This is not terribly effecient but we really only expect this function to be called at
// most a handful of times when our test programs start.
SkAutoTDelete< SkTArray<SkString> > oldStrings(fStrings.detach());
fStrings.reset(SkNEW(SkTArray<SkString>(oldStrings->count() - 1)));
fStrings->push_back_n(idx, &oldStrings->front());
fStrings->push_back_n(oldStrings->count() - idx - 1, &(*oldStrings)[idx] + 1);
return true;
} else {
return false;
}
SkString extensionStr(ext);
int idx = SkTSearch<SkString, extension_compare>(&fStrings->front(),
fStrings->count(),
extensionStr,
sizeof(SkString));
return idx >= 0;
}
void GrGLExtensions::print(const char* sep) const {

View File

@ -18,6 +18,64 @@ void GrGLDefaultInterfaceCallback(const GrGLInterface*) {}
}
#endif
const GrGLInterface* GrGLInterfaceRemoveNVPR(const GrGLInterface* interface) {
GrGLInterface* newInterface = GrGLInterface::NewClone(interface);
newInterface->fExtensions.remove("GL_NV_path_rendering");
newInterface->fPathCommands = NULL;
newInterface->fPathCoords = NULL;
newInterface->fPathSubCommands = NULL;
newInterface->fPathSubCoords = NULL;
newInterface->fPathString = NULL;
newInterface->fPathGlyphs = NULL;
newInterface->fPathGlyphRange = NULL;
newInterface->fWeightPaths = NULL;
newInterface->fCopyPath = NULL;
newInterface->fInterpolatePaths = NULL;
newInterface->fTransformPath = NULL;
newInterface->fPathParameteriv = NULL;
newInterface->fPathParameteri = NULL;
newInterface->fPathParameterfv = NULL;
newInterface->fPathParameterf = NULL;
newInterface->fPathDashArray = NULL;
newInterface->fGenPaths = NULL;
newInterface->fDeletePaths = NULL;
newInterface->fIsPath = NULL;
newInterface->fPathStencilFunc = NULL;
newInterface->fPathStencilDepthOffset = NULL;
newInterface->fStencilFillPath = NULL;
newInterface->fStencilStrokePath = NULL;
newInterface->fStencilFillPathInstanced = NULL;
newInterface->fStencilStrokePathInstanced = NULL;
newInterface->fPathCoverDepthFunc = NULL;
newInterface->fPathColorGen = NULL;
newInterface->fPathTexGen = NULL;
newInterface->fPathFogGen = NULL;
newInterface->fCoverFillPath = NULL;
newInterface->fCoverStrokePath = NULL;
newInterface->fCoverFillPathInstanced = NULL;
newInterface->fCoverStrokePathInstanced = NULL;
newInterface->fGetPathParameteriv = NULL;
newInterface->fGetPathParameterfv = NULL;
newInterface->fGetPathCommands = NULL;
newInterface->fGetPathCoords = NULL;
newInterface->fGetPathDashArray = NULL;
newInterface->fGetPathMetrics = NULL;
newInterface->fGetPathMetricRange = NULL;
newInterface->fGetPathSpacing = NULL;
newInterface->fGetPathColorGeniv = NULL;
newInterface->fGetPathColorGenfv = NULL;
newInterface->fGetPathTexGeniv = NULL;
newInterface->fGetPathTexGenfv = NULL;
newInterface->fIsPointInFillPath = NULL;
newInterface->fIsPointInStrokePath = NULL;
newInterface->fGetPathLength = NULL;
newInterface->fPointAlongPath = NULL;
return newInterface;
}
GrGLInterface::GrGLInterface()
// TODO: Remove this madness ASAP.
: fActiveTexture(&fFunctions.fActiveTexture)
@ -205,8 +263,7 @@ GrGLInterface::GrGLInterface()
, fIsPointInFillPath(&fFunctions.fIsPointInFillPath)
, fIsPointInStrokePath(&fFunctions.fIsPointInStrokePath)
, fGetPathLength(&fFunctions.fGetPathLength)
, fPointAlongPath(&fFunctions.fPointAlongPath)
{
, fPointAlongPath(&fFunctions.fPointAlongPath) {
fStandard = kNone_GrGLStandard;
#if GR_GL_PER_GL_FUNC_CALLBACK
@ -215,6 +272,20 @@ GrGLInterface::GrGLInterface()
#endif
}
GrGLInterface* GrGLInterface::NewClone(const GrGLInterface* interface) {
SkASSERT(NULL != interface);
GrGLInterface* clone = SkNEW(GrGLInterface);
clone->fStandard = interface->fStandard;
clone->fExtensions = interface->fExtensions;
clone->fFunctions = interface->fFunctions;
#if GR_GL_PER_GL_FUNC_CALLBACK
clone->fCallback = interface->fCallback;
clone->fCallbackData = interface->fCallbackData;
#endif
return clone;
}
bool GrGLInterface::validate() const {
if (kNone_GrGLStandard == fStandard) {
@ -405,7 +476,7 @@ bool GrGLInterface::validate() const {
return false;
}
}
if (false && fExtensions.has("GL_NV_path_rendering")) {
if (fExtensions.has("GL_NV_path_rendering")) {
if (NULL == fFunctions.fPathCommands ||
NULL == fFunctions.fPathCoords ||
NULL == fFunctions.fPathSubCommands ||

View File

@ -152,5 +152,10 @@ const GrGLInterface* GrGLCreateANGLEInterface() {
functions->fMapBuffer = (GrGLMapBufferProc) eglGetProcAddress("glMapBufferOES");
functions->fUnmapBuffer = (GrGLUnmapBufferProc) eglGetProcAddress("glUnmapBufferOES");
interface->fExtensions.init(kGLES_GrGLStandard,
interface->fFunctions.fGetString,
interface->fFunctions.fGetStringi,
interface->fFunctions.fGetIntegerv);
return interface;
}

View File

@ -86,10 +86,8 @@ const GrGLInterface* SkNativeGLContext::createGLContext() {
return NULL;
}
// We don't want the core profile when using NV path rendering (since
// NV path rendering relies on fixed function calls)
if (!(fGlRenderContext = SkCreateWGLContext(fDeviceContext, 0,
!GR_GL_USE_NV_PATH_RENDERING))) {
// Requesting a Core profile would bar us from using NVPR. So we pass false.
if (!(fGlRenderContext = SkCreateWGLContext(fDeviceContext, 0, false))) {
SkDebugf("Could not create rendering context.\n");
this->destroyGLContext();
return NULL;

View File

@ -18,6 +18,16 @@ DEF_GPUTEST(GLInterfaceValidation, reporter, factory) {
// this forces the factory to make the context if it hasn't yet
factory->get(glCtxType);
SkGLContextHelper* glCtxHelper = factory->getGLContext(glCtxType);
// We're supposed to fail the NVPR context type when we the native context that does not
// support the NVPR extension.
if (GrContextFactory::kNVPR_GLContextType == glCtxType &&
NULL != factory->getGLContext(GrContextFactory::kNative_GLContextType) &&
!factory->getGLContext(GrContextFactory::kNative_GLContextType)->hasExtension("GL_NV_path_rendering")) {
REPORTER_ASSERT(reporter, NULL == glCtxHelper);
continue;
}
REPORTER_ASSERT(reporter, NULL != glCtxHelper);
if (NULL != glCtxHelper) {
const GrGLInterface* interface = glCtxHelper->gl();