Implement support for CHROMIUM_path_rendering pseudo extension
authorkkinnunen <kkinnunen@nvidia.com>
Tue, 14 Jul 2015 17:59:23 +0000 (10:59 -0700)
committerCommit bot <commit-bot@chromium.org>
Tue, 14 Jul 2015 17:59:23 +0000 (10:59 -0700)
Implement support for path rendering in Chromium through
CHROMIUM_path_rendering pseudo extension.

The extension defines a new pseudo-gl function,
BindFragmentInputLocation. This behaves similarly to the
BindUniformLocation pseudo-gl function. The idea is to assign fragment
input location to a fragment input before linking the program.

BUG=chromium:344330

Committed: https://skia.googlesource.com/skia/+/eeef46d181f9f8db388ecea81df699fc1b3c9280

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

include/gpu/gl/GrGLFunctions.h
include/gpu/gl/GrGLInterface.h
src/gpu/gl/GrGLCaps.cpp
src/gpu/gl/GrGLInterface.cpp
src/gpu/gl/GrGLPathRendering.cpp
src/gpu/gl/GrGLPathRendering.h
src/gpu/gl/builders/GrGLPathProgramBuilder.cpp
src/gpu/gl/builders/GrGLPathProgramBuilder.h
src/gpu/gl/builders/GrGLProgramBuilder.h

index f5240c5..aea6d2c 100644 (file)
@@ -257,6 +257,8 @@ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLStencilThenCoverFillPathInstancedProc
 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);
+// CHROMIUM_path_rendering
+typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLBindFragmentInputLocationProc)(GrGLuint program, GrGLint location, const GrGLchar* name);
 
 /* ARB_program_interface_query */
 typedef GrGLint (GR_GL_FUNCTION_TYPE* GrGLGetProgramResourceLocationProc)(GrGLuint program, GrGLenum programInterface, const GrGLchar *name);
index 9a71758..9d60259 100644 (file)
@@ -350,6 +350,8 @@ public:
         GLPtr<GrGLStencilThenCoverStrokePathInstancedProc> fStencilThenCoverStrokePathInstanced;
         // NV_path_rendering v1.3
         GLPtr<GrGLProgramPathFragmentInputGenProc> fProgramPathFragmentInputGen;
+        // CHROMIUM_path_rendering
+        GLPtr<GrGLBindFragmentInputLocationProc> fBindFragmentInputLocation;
 
         /* NV_framebuffer_mixed_samples */
         GLPtr<GrGLCoverageModulationProc> fCoverageModulation;
index 22ad057..318426b 100644 (file)
@@ -464,16 +464,20 @@ void GrGLCaps::init(const GrContextOptions& contextOptions,
 }
 
 bool GrGLCaps::hasPathRenderingSupport(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) {
-    if (!ctxInfo.hasExtension("GL_NV_path_rendering")) {
+    bool hasChromiumPathRendering = ctxInfo.hasExtension("GL_CHROMIUM_path_rendering");
+
+    if (!(ctxInfo.hasExtension("GL_NV_path_rendering") || hasChromiumPathRendering)) {
         return false;
     }
+
     if (kGL_GrGLStandard == ctxInfo.standard()) {
         if (ctxInfo.version() < GR_GL_VER(4, 3) &&
             !ctxInfo.hasExtension("GL_ARB_program_interface_query")) {
             return false;
         }
     } else {
-        if (ctxInfo.version() < GR_GL_VER(3, 1)) {
+        if (!hasChromiumPathRendering &&
+            ctxInfo.version() < GR_GL_VER(3, 1)) {
             return false;
         }
     }
index 56f1e59..9f58c73 100644 (file)
@@ -59,6 +59,7 @@ const GrGLInterface* GrGLInterfaceRemoveNVPR(const GrGLInterface* interface) {
     newInterface->fFunctions.fStencilThenCoverFillPathInstanced = NULL;
     newInterface->fFunctions.fStencilThenCoverStrokePathInstanced = NULL;
     newInterface->fFunctions.fProgramPathFragmentInputGen = NULL;
+    newInterface->fFunctions.fBindFragmentInputLocation = NULL;
     return newInterface;
 }
 
@@ -483,7 +484,7 @@ bool GrGLInterface::validate() const {
 #endif
     }
 
-    if (fExtensions.has("GL_NV_path_rendering")) {
+    if (fExtensions.has("GL_NV_path_rendering") || fExtensions.has("GL_CHROMIUM_path_rendering")) {
         if (NULL == fFunctions.fMatrixLoadf ||
             NULL == fFunctions.fMatrixLoadIdentity ||
             NULL == fFunctions.fPathCommands ||
@@ -515,6 +516,11 @@ bool GrGLInterface::validate() const {
             ) {
             RETURN_FALSE_INTERFACE
         }
+        if (fExtensions.has("GL_CHROMIUM_path_rendering")) {
+            if (NULL == fFunctions.fBindFragmentInputLocation) {
+                RETURN_FALSE_INTERFACE
+            }
+        }
     }
 
     if (fExtensions.has("GL_EXT_raster_multisample")) {
index ffdbbda..7c77155 100644 (file)
@@ -61,6 +61,9 @@ static GrGLenum gr_stencil_op_to_gl_path_rendering_fill_mode(GrStencilOp op) {
 
 GrGLPathRendering::GrGLPathRendering(GrGLGpu* gpu)
     : GrPathRendering(gpu) {
+    const GrGLInterface* glInterface = gpu->glInterface();
+    fCaps.bindFragmentInputSupport =
+        NULL != glInterface->fFunctions.fBindFragmentInputLocation;
 }
 
 GrGLPathRendering::~GrGLPathRendering() {
index 86cf1b1..5996e90 100644 (file)
@@ -46,6 +46,10 @@ public:
      */
     void abandonGpuResources();
 
+    bool shouldBindFragmentInputs() const {
+        return fCaps.bindFragmentInputSupport;
+    }
+
     // Functions for "separable shader" texturing support.
     void setProgramPathFragmentInputTransform(GrGLuint program, GrGLint location,
                                               GrGLenum genMode, GrGLint components,
@@ -65,6 +69,13 @@ protected:
     void onDrawPaths(const DrawPathArgs&, const GrPathRange*, const void* indices, PathIndexType,
                      const float transformValues[], PathTransformType, int count) override;
 private:
+    /**
+     * Mark certain functionality as not supported.
+     */
+    struct Caps {
+        bool bindFragmentInputSupport : 1;
+    };
+
     void flushPathStencilSettings(const GrStencilSettings&);
 
     struct MatrixState {
@@ -103,6 +114,7 @@ private:
     SkAutoTDelete<GrGLNameAllocator> fPathNameAllocator;
     MatrixState fHWProjectionMatrixState;
     GrStencilSettings fHWPathStencilSettings;
+    Caps fCaps;
 };
 
 #endif
index c9f88cd..9bebe0d 100644 (file)
@@ -35,9 +35,25 @@ GrGLProgramBuilder::SeparableVaryingHandle GrGLPathProgramBuilder::addSeparableV
     return SeparableVaryingHandle::CreateFromSeparableVaryingIndex(varyingInfo.fLocation);
 }
 
+void GrGLPathProgramBuilder::bindProgramResourceLocations(GrGLuint programID) {
+    this->INHERITED::bindProgramResourceLocations(programID);
+    if (!fGpu->glPathRendering()->shouldBindFragmentInputs()) {
+        return;
+    }
+    int count = fSeparableVaryingInfos.count();
+    for (int i = 0; i < count; ++i) {
+        GL_CALL(BindFragmentInputLocation(programID,
+                                          i,
+                                          fSeparableVaryingInfos[i].fVariable.c_str()));
+        fSeparableVaryingInfos[i].fLocation = i;
+    }
+}
+
 void GrGLPathProgramBuilder::resolveProgramResourceLocations(GrGLuint programID) {
     this->INHERITED::resolveProgramResourceLocations(programID);
-
+    if (fGpu->glPathRendering()->shouldBindFragmentInputs()) {
+        return;
+    }
     int count = fSeparableVaryingInfos.count();
     for (int i = 0; i < count; ++i) {
         GrGLint location;
index 28260cf..d0c77fc 100644 (file)
@@ -17,6 +17,7 @@ public:
 
     SeparableVaryingHandle addSeparableVarying(const char* name, GrGLVertToFrag* v,
                                                GrSLPrecision fsPrecision) override;
+    void bindProgramResourceLocations(GrGLuint programID) override;
     void resolveProgramResourceLocations(GrGLuint programID) override;
 
 private:
index 4b784ac..22b67ae 100644 (file)
@@ -328,7 +328,7 @@ protected:
                       GrGLInstalledProc<Proc>*);
 
     GrGLProgram* finalize();
-    void bindProgramResourceLocations(GrGLuint programID);
+    virtual void bindProgramResourceLocations(GrGLuint programID);
     bool checkLinkStatus(GrGLuint programID);
     virtual void resolveProgramResourceLocations(GrGLuint programID);
     void cleanupProgram(GrGLuint programID, const SkTDArray<GrGLuint>& shaderIDs);