LCOV - code coverage report
Current view: top level - gfx/skia/skia/src/gpu/gl - GrGLPathRendering.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 157 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 18 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright 2014 Google Inc.
       3             :  *
       4             :  * Use of this source code is governed by a BSD-style license that can be
       5             :  * found in the LICENSE file.
       6             :  */
       7             : 
       8             : #include "gl/GrGLPathRendering.h"
       9             : #include "gl/GrGLUtil.h"
      10             : #include "gl/GrGLGpu.h"
      11             : 
      12             : #include "GrGLPath.h"
      13             : #include "GrGLPathRange.h"
      14             : #include "GrGLPathRendering.h"
      15             : 
      16             : #include "SkStream.h"
      17             : #include "SkTypeface.h"
      18             : 
      19             : #define GL_CALL(X) GR_GL_CALL(this->gpu()->glInterface(), X)
      20             : #define GL_CALL_RET(RET, X) GR_GL_CALL_RET(this->gpu()->glInterface(), RET, X)
      21             : 
      22             : // Number of paths to allocate per glGenPaths call. The call can be overly slow on command buffer GL
      23             : // implementation. The call has a result value, and thus waiting for the call completion is needed.
      24             : static const GrGLsizei kPathIDPreallocationAmount = 65536;
      25             : 
      26             : static const GrGLenum gIndexType2GLType[] = {
      27             :     GR_GL_UNSIGNED_BYTE,
      28             :     GR_GL_UNSIGNED_SHORT,
      29             :     GR_GL_UNSIGNED_INT
      30             : };
      31             : 
      32             : GR_STATIC_ASSERT(0 == GrPathRange::kU8_PathIndexType);
      33             : GR_STATIC_ASSERT(1 == GrPathRange::kU16_PathIndexType);
      34             : GR_STATIC_ASSERT(2 == GrPathRange::kU32_PathIndexType);
      35             : GR_STATIC_ASSERT(GrPathRange::kU32_PathIndexType == GrPathRange::kLast_PathIndexType);
      36             : 
      37             : static const GrGLenum gXformType2GLType[] = {
      38             :     GR_GL_NONE,
      39             :     GR_GL_TRANSLATE_X,
      40             :     GR_GL_TRANSLATE_Y,
      41             :     GR_GL_TRANSLATE_2D,
      42             :     GR_GL_TRANSPOSE_AFFINE_2D
      43             : };
      44             : 
      45             : GR_STATIC_ASSERT(0 == GrPathRendering::kNone_PathTransformType);
      46             : GR_STATIC_ASSERT(1 == GrPathRendering::kTranslateX_PathTransformType);
      47             : GR_STATIC_ASSERT(2 == GrPathRendering::kTranslateY_PathTransformType);
      48             : GR_STATIC_ASSERT(3 == GrPathRendering::kTranslate_PathTransformType);
      49             : GR_STATIC_ASSERT(4 == GrPathRendering::kAffine_PathTransformType);
      50             : GR_STATIC_ASSERT(GrPathRendering::kAffine_PathTransformType == GrPathRendering::kLast_PathTransformType);
      51             : 
      52             : #ifdef SK_DEBUG
      53             : static const GrGLenum gXformType2ComponentCount[] = {
      54             :     0,
      55             :     1,
      56             :     1,
      57             :     2,
      58             :     6
      59             : };
      60             : 
      61           0 : static void verify_floats(const float* floats, int count) {
      62           0 :     for (int i = 0; i < count; ++i) {
      63           0 :         SkASSERT(!SkScalarIsNaN(SkFloatToScalar(floats[i])));
      64             :     }
      65           0 : }
      66             : #endif
      67             : 
      68           0 : static GrGLenum gr_stencil_op_to_gl_path_rendering_fill_mode(GrStencilOp op) {
      69           0 :     switch (op) {
      70             :         default:
      71           0 :             SkFAIL("Unexpected path fill.");
      72             :             /* fallthrough */;
      73             :         case GrStencilOp::kIncWrap:
      74           0 :             return GR_GL_COUNT_UP;
      75             :         case GrStencilOp::kInvert:
      76           0 :             return GR_GL_INVERT;
      77             :     }
      78             : }
      79             : 
      80           0 : GrGLPathRendering::GrGLPathRendering(GrGLGpu* gpu)
      81             :     : GrPathRendering(gpu)
      82           0 :     , fPreallocatedPathCount(0) {
      83           0 :     const GrGLInterface* glInterface = gpu->glInterface();
      84           0 :     fCaps.bindFragmentInputSupport =
      85           0 :         nullptr != glInterface->fFunctions.fBindFragmentInputLocation;
      86           0 : }
      87             : 
      88           0 : GrGLPathRendering::~GrGLPathRendering() {
      89           0 :     if (fPreallocatedPathCount > 0) {
      90           0 :         this->deletePaths(fFirstPreallocatedPathID, fPreallocatedPathCount);
      91             :     }
      92           0 : }
      93             : 
      94           0 : void GrGLPathRendering::disconnect(GrGpu::DisconnectType type) {
      95           0 :     if (GrGpu::DisconnectType::kCleanup == type) {
      96           0 :         this->deletePaths(fFirstPreallocatedPathID, fPreallocatedPathCount);
      97             :     };
      98           0 :     fPreallocatedPathCount = 0;
      99           0 : }
     100             : 
     101           0 : void GrGLPathRendering::resetContext() {
     102           0 :     fHWProjectionMatrixState.invalidate();
     103             :     // we don't use the model view matrix.
     104           0 :     GL_CALL(MatrixLoadIdentity(GR_GL_PATH_MODELVIEW));
     105             : 
     106           0 :     fHWPathStencilSettings.invalidate();
     107           0 : }
     108             : 
     109           0 : GrPath* GrGLPathRendering::createPath(const SkPath& inPath, const GrStyle& style) {
     110           0 :     return new GrGLPath(this->gpu(), inPath, style);
     111             : }
     112             : 
     113           0 : GrPathRange* GrGLPathRendering::createPathRange(GrPathRange::PathGenerator* pathGenerator,
     114             :                                                 const GrStyle& style) {
     115           0 :     return new GrGLPathRange(this->gpu(), pathGenerator, style);
     116             : }
     117             : 
     118           0 : void GrGLPathRendering::onStencilPath(const StencilPathArgs& args, const GrPath* path) {
     119           0 :     GrGLGpu* gpu = this->gpu();
     120           0 :     SkASSERT(gpu->caps()->shaderCaps()->pathRenderingSupport());
     121           0 :     gpu->flushColorWrite(false);
     122           0 :     gpu->flushDrawFace(GrDrawFace::kBoth);
     123             : 
     124           0 :     GrGLRenderTarget* rt = static_cast<GrGLRenderTarget*>(args.fRenderTarget);
     125           0 :     SkISize size = SkISize::Make(rt->width(), rt->height());
     126           0 :     this->setProjectionMatrix(*args.fViewMatrix, size, rt->origin());
     127           0 :     gpu->flushScissor(*args.fScissor, rt->getViewport(), rt->origin());
     128           0 :     gpu->flushHWAAState(rt, args.fUseHWAA, true);
     129           0 :     gpu->flushRenderTarget(rt, nullptr);
     130             : 
     131           0 :     const GrGLPath* glPath = static_cast<const GrGLPath*>(path);
     132             : 
     133           0 :     this->flushPathStencilSettings(*args.fStencil);
     134           0 :     SkASSERT(!fHWPathStencilSettings.isTwoSided());
     135             : 
     136             :     GrGLenum fillMode =
     137           0 :         gr_stencil_op_to_gl_path_rendering_fill_mode(fHWPathStencilSettings.front().fPassOp);
     138           0 :     GrGLint writeMask = fHWPathStencilSettings.front().fWriteMask;
     139             : 
     140           0 :     if (glPath->shouldFill()) {
     141           0 :         GL_CALL(StencilFillPath(glPath->pathID(), fillMode, writeMask));
     142             :     }
     143           0 :     if (glPath->shouldStroke()) {
     144           0 :         GL_CALL(StencilStrokePath(glPath->pathID(), 0xffff, writeMask));
     145             :     }
     146           0 : }
     147             : 
     148           0 : void GrGLPathRendering::onDrawPath(const GrPipeline& pipeline,
     149             :                                    const GrPrimitiveProcessor& primProc,
     150             :                                    const GrStencilSettings& stencilPassSettings,
     151             :                                    const GrPath* path) {
     152           0 :     if (!this->gpu()->flushGLState(pipeline, primProc, false)) {
     153           0 :         return;
     154             :     }
     155           0 :     const GrGLPath* glPath = static_cast<const GrGLPath*>(path);
     156             : 
     157           0 :     this->flushPathStencilSettings(stencilPassSettings);
     158           0 :     SkASSERT(!fHWPathStencilSettings.isTwoSided());
     159             : 
     160             :     GrGLenum fillMode =
     161           0 :         gr_stencil_op_to_gl_path_rendering_fill_mode(fHWPathStencilSettings.front().fPassOp);
     162           0 :     GrGLint writeMask = fHWPathStencilSettings.front().fWriteMask;
     163             : 
     164           0 :     if (glPath->shouldStroke()) {
     165           0 :         if (glPath->shouldFill()) {
     166           0 :             GL_CALL(StencilFillPath(glPath->pathID(), fillMode, writeMask));
     167             :         }
     168           0 :         GL_CALL(StencilThenCoverStrokePath(glPath->pathID(), 0xffff, writeMask,
     169             :                                            GR_GL_BOUNDING_BOX));
     170             :     } else {
     171           0 :         GL_CALL(StencilThenCoverFillPath(glPath->pathID(), fillMode, writeMask,
     172             :                                          GR_GL_BOUNDING_BOX));
     173             :     }
     174             : }
     175             : 
     176           0 : void GrGLPathRendering::onDrawPaths(const GrPipeline& pipeline,
     177             :                                     const GrPrimitiveProcessor& primProc,
     178             :                                     const GrStencilSettings& stencilPassSettings,
     179             :                                     const GrPathRange* pathRange, const void* indices,
     180             :                                     PathIndexType indexType, const float transformValues[],
     181             :                                     PathTransformType transformType, int count) {
     182           0 :     SkDEBUGCODE(verify_floats(transformValues, gXformType2ComponentCount[transformType] * count));
     183             : 
     184           0 :     if (!this->gpu()->flushGLState(pipeline, primProc, false)) {
     185           0 :         return;
     186             :     }
     187           0 :     this->flushPathStencilSettings(stencilPassSettings);
     188           0 :     SkASSERT(!fHWPathStencilSettings.isTwoSided());
     189             : 
     190             : 
     191           0 :     const GrGLPathRange* glPathRange = static_cast<const GrGLPathRange*>(pathRange);
     192             : 
     193             :     GrGLenum fillMode =
     194           0 :         gr_stencil_op_to_gl_path_rendering_fill_mode(fHWPathStencilSettings.front().fPassOp);
     195           0 :     GrGLint writeMask = fHWPathStencilSettings.front().fWriteMask;
     196             : 
     197           0 :     if (glPathRange->shouldStroke()) {
     198           0 :         if (glPathRange->shouldFill()) {
     199           0 :             GL_CALL(StencilFillPathInstanced(
     200             :                             count, gIndexType2GLType[indexType], indices, glPathRange->basePathID(),
     201             :                             fillMode, writeMask, gXformType2GLType[transformType],
     202             :                             transformValues));
     203             :         }
     204           0 :         GL_CALL(StencilThenCoverStrokePathInstanced(
     205             :                             count, gIndexType2GLType[indexType], indices, glPathRange->basePathID(),
     206             :                             0xffff, writeMask, GR_GL_BOUNDING_BOX_OF_BOUNDING_BOXES,
     207             :                             gXformType2GLType[transformType], transformValues));
     208             :     } else {
     209           0 :         GL_CALL(StencilThenCoverFillPathInstanced(
     210             :                             count, gIndexType2GLType[indexType], indices, glPathRange->basePathID(),
     211             :                             fillMode, writeMask, GR_GL_BOUNDING_BOX_OF_BOUNDING_BOXES,
     212             :                             gXformType2GLType[transformType], transformValues));
     213             :     }
     214             : }
     215             : 
     216           0 : void GrGLPathRendering::setProgramPathFragmentInputTransform(GrGLuint program, GrGLint location,
     217             :                                                              GrGLenum genMode, GrGLint components,
     218             :                                                              const SkMatrix& matrix) {
     219             :     float coefficients[3 * 3];
     220           0 :     SkASSERT(components >= 1 && components <= 3);
     221             : 
     222           0 :     coefficients[0] = SkScalarToFloat(matrix[SkMatrix::kMScaleX]);
     223           0 :     coefficients[1] = SkScalarToFloat(matrix[SkMatrix::kMSkewX]);
     224           0 :     coefficients[2] = SkScalarToFloat(matrix[SkMatrix::kMTransX]);
     225             : 
     226           0 :     if (components >= 2) {
     227           0 :         coefficients[3] = SkScalarToFloat(matrix[SkMatrix::kMSkewY]);
     228           0 :         coefficients[4] = SkScalarToFloat(matrix[SkMatrix::kMScaleY]);
     229           0 :         coefficients[5] = SkScalarToFloat(matrix[SkMatrix::kMTransY]);
     230             :     }
     231             : 
     232           0 :     if (components >= 3) {
     233           0 :         coefficients[6] = SkScalarToFloat(matrix[SkMatrix::kMPersp0]);
     234           0 :         coefficients[7] = SkScalarToFloat(matrix[SkMatrix::kMPersp1]);
     235           0 :         coefficients[8] = SkScalarToFloat(matrix[SkMatrix::kMPersp2]);
     236             :     }
     237           0 :     SkDEBUGCODE(verify_floats(coefficients, components * 3));
     238             : 
     239           0 :     GL_CALL(ProgramPathFragmentInputGen(program, location, genMode, components, coefficients));
     240           0 : }
     241             : 
     242           0 : void GrGLPathRendering::setProjectionMatrix(const SkMatrix& matrix,
     243             :                                             const SkISize& renderTargetSize,
     244             :                                             GrSurfaceOrigin renderTargetOrigin) {
     245             : 
     246           0 :     SkASSERT(this->gpu()->glCaps().shaderCaps()->pathRenderingSupport());
     247             : 
     248           0 :     if (renderTargetOrigin == fHWProjectionMatrixState.fRenderTargetOrigin &&
     249           0 :         renderTargetSize == fHWProjectionMatrixState.fRenderTargetSize &&
     250           0 :         matrix.cheapEqualTo(fHWProjectionMatrixState.fViewMatrix)) {
     251           0 :         return;
     252             :     }
     253             : 
     254           0 :     fHWProjectionMatrixState.fViewMatrix = matrix;
     255           0 :     fHWProjectionMatrixState.fRenderTargetSize = renderTargetSize;
     256           0 :     fHWProjectionMatrixState.fRenderTargetOrigin = renderTargetOrigin;
     257             : 
     258             :     float glMatrix[4 * 4];
     259           0 :     fHWProjectionMatrixState.getRTAdjustedGLMatrix<4>(glMatrix);
     260           0 :     SkDEBUGCODE(verify_floats(glMatrix, SK_ARRAY_COUNT(glMatrix)));
     261           0 :     GL_CALL(MatrixLoadf(GR_GL_PATH_PROJECTION, glMatrix));
     262             : }
     263             : 
     264           0 : GrGLuint GrGLPathRendering::genPaths(GrGLsizei range) {
     265           0 :     SkASSERT(range > 0);
     266             :     GrGLuint firstID;
     267           0 :     if (fPreallocatedPathCount >= range) {
     268           0 :         firstID = fFirstPreallocatedPathID;
     269           0 :         fPreallocatedPathCount -= range;
     270           0 :         fFirstPreallocatedPathID += range;
     271           0 :         return firstID;
     272             :     }
     273             :     // Allocate range + the amount to fill up preallocation amount. If succeed, either join with
     274             :     // the existing preallocation range or delete the existing and use the new (potentially partial)
     275             :     // preallocation range.
     276           0 :     GrGLsizei allocAmount = range + (kPathIDPreallocationAmount - fPreallocatedPathCount);
     277           0 :     if (allocAmount >= range) {
     278           0 :         GL_CALL_RET(firstID, GenPaths(allocAmount));
     279             : 
     280           0 :         if (firstID != 0) {
     281           0 :             if (fPreallocatedPathCount > 0 &&
     282           0 :                 firstID == fFirstPreallocatedPathID + fPreallocatedPathCount) {
     283           0 :                 firstID = fFirstPreallocatedPathID;
     284           0 :                 fPreallocatedPathCount += allocAmount - range;
     285           0 :                 fFirstPreallocatedPathID += range;
     286           0 :                 return firstID;
     287             :             }
     288             : 
     289           0 :             if (allocAmount > range) {
     290           0 :                 if (fPreallocatedPathCount > 0) {
     291           0 :                     this->deletePaths(fFirstPreallocatedPathID, fPreallocatedPathCount);
     292             :                 }
     293           0 :                 fFirstPreallocatedPathID = firstID + range;
     294           0 :                 fPreallocatedPathCount = allocAmount - range;
     295             :             }
     296             :             // Special case: if allocAmount == range, we have full preallocated range.
     297           0 :             return firstID;
     298             :         }
     299             :     }
     300             :     // Failed to allocate with preallocation. Remove existing preallocation and try to allocate just
     301             :     // the range.
     302           0 :     if (fPreallocatedPathCount > 0) {
     303           0 :         this->deletePaths(fFirstPreallocatedPathID, fPreallocatedPathCount);
     304           0 :         fPreallocatedPathCount = 0;
     305             :     }
     306             : 
     307           0 :     GL_CALL_RET(firstID, GenPaths(range));
     308           0 :     if (firstID == 0) {
     309           0 :         SkDebugf("Warning: Failed to allocate path\n");
     310             :     }
     311           0 :     return firstID;
     312             : }
     313             : 
     314           0 : void GrGLPathRendering::deletePaths(GrGLuint path, GrGLsizei range) {
     315           0 :     GL_CALL(DeletePaths(path, range));
     316           0 : }
     317             : 
     318           0 : void GrGLPathRendering::flushPathStencilSettings(const GrStencilSettings& stencilSettings) {
     319           0 :     if (fHWPathStencilSettings != stencilSettings) {
     320           0 :         SkASSERT(stencilSettings.isValid());
     321             :         // Just the func, ref, and mask is set here. The op and write mask are params to the call
     322             :         // that draws the path to the SB (glStencilFillPath)
     323           0 :         uint16_t ref = stencilSettings.front().fRef;
     324           0 :         GrStencilTest test = stencilSettings.front().fTest;
     325           0 :         uint16_t testMask = stencilSettings.front().fTestMask;
     326             : 
     327           0 :         if (!fHWPathStencilSettings.isValid() ||
     328           0 :             ref != fHWPathStencilSettings.front().fRef ||
     329           0 :             test != fHWPathStencilSettings.front().fTest ||
     330           0 :             testMask != fHWPathStencilSettings.front().fTestMask) {
     331           0 :             GL_CALL(PathStencilFunc(GrToGLStencilFunc(test), ref, testMask));
     332             :         }
     333           0 :         fHWPathStencilSettings = stencilSettings;
     334             :     }
     335           0 : }
     336             : 
     337           0 : inline GrGLGpu* GrGLPathRendering::gpu() {
     338           0 :     return static_cast<GrGLGpu*>(fGpu);
     339             : }

Generated by: LCOV version 1.13