Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / tests / GLProgramsTest.cpp
index 3df08a7..a16173b 100644 (file)
 
 #if SK_SUPPORT_GPU && SK_ALLOW_STATIC_GLOBAL_INITIALIZERS
 
-#include "GrBackendEffectFactory.h"
+#include "GrBackendProcessorFactory.h"
 #include "GrContextFactory.h"
-#include "GrDrawEffect.h"
+#include "GrOptDrawState.h"
 #include "effects/GrConfigConversionEffect.h"
+#include "gl/GrGLPathRendering.h"
 #include "gl/GrGpuGL.h"
-
 #include "SkChecksum.h"
 #include "SkRandom.h"
 #include "Test.h"
 
-void GrGLProgramDesc::setRandom(SkRandom* random,
-                                const GrGpuGL* gpu,
+static void get_stage_stats(const GrFragmentStage stage, bool* readsDst,
+                            bool* readsFragPosition, bool* requiresVertexShader) {
+    if (stage.getFragmentProcessor()->willReadDstColor()) {
+        *readsDst = true;
+    }
+    if (stage.getProcessor()->willReadFragmentPosition()) {
+        *readsFragPosition = true;
+    }
+}
+
+bool GrGLProgramDesc::setRandom(SkRandom* random,
+                                GrGpuGL* gpu,
                                 const GrRenderTarget* dstRenderTarget,
                                 const GrTexture* dstCopyTexture,
-                                const GrEffectStage* stages[],
+                                const GrGeometryStage* geometryProcessor,
+                                const GrFragmentStage* stages[],
                                 int numColorStages,
                                 int numCoverageStages,
-                                int currAttribIndex) {
-    int numEffects = numColorStages + numCoverageStages;
-    size_t keyLength = KeyLength(numEffects);
-    fKey.reset(keyLength);
-    *this->atOffset<uint32_t, kLengthOffset>() = static_cast<uint32_t>(keyLength);
-    memset(this->header(), 0, kHeaderSize);
+                                int currAttribIndex,
+                                GrGpu::DrawType drawType) {
+    bool isPathRendering = GrGpu::IsPathRenderingDrawType(drawType);
+    bool useLocalCoords = !isPathRendering &&
+                          random->nextBool() &&
+                          currAttribIndex < GrDrawState::kMaxVertexAttribCnt;
+
+    int numStages = numColorStages + numCoverageStages;
+    fKey.reset();
+
+    GR_STATIC_ASSERT(0 == kEffectKeyOffsetsAndLengthOffset % sizeof(uint32_t));
+
+    // Make room for everything up to and including the array of offsets to effect keys.
+    fKey.push_back_n(kEffectKeyOffsetsAndLengthOffset + 2 * sizeof(uint16_t) * (numStages +
+            (geometryProcessor ? 1 : 0)));
+
+    bool dstRead = false;
+    bool fragPos = false;
+    bool vertexShader = SkToBool(geometryProcessor);
+    int offset = 0;
+    if (geometryProcessor) {
+        const GrGeometryStage* stage = geometryProcessor;
+        uint16_t* offsetAndSize = reinterpret_cast<uint16_t*>(fKey.begin() +
+                                                              kEffectKeyOffsetsAndLengthOffset +
+                                                              offset * 2 * sizeof(uint16_t));
+        uint32_t effectKeyOffset = fKey.count();
+        if (effectKeyOffset > SK_MaxU16) {
+            fKey.reset();
+            return false;
+        }
+        GrProcessorKeyBuilder b(&fKey);
+        uint16_t effectKeySize;
+        if (!GetProcessorKey(*stage, gpu->glCaps(), useLocalCoords, &b, &effectKeySize)) {
+            fKey.reset();
+            return false;
+        }
+        vertexShader = true;
+        fragPos = stage->getProcessor()->willReadFragmentPosition();
+        offsetAndSize[0] = effectKeyOffset;
+        offsetAndSize[1] = effectKeySize;
+        offset++;
+    }
+
+    for (int s = 0; s < numStages; ++s, ++offset) {
+        const GrFragmentStage* stage = stages[s];
+        uint16_t* offsetAndSize = reinterpret_cast<uint16_t*>(fKey.begin() +
+                                                              kEffectKeyOffsetsAndLengthOffset +
+                                                              offset * 2 * sizeof(uint16_t));
+        uint32_t effectKeyOffset = fKey.count();
+        if (effectKeyOffset > SK_MaxU16) {
+            fKey.reset();
+            return false;
+        }
+        GrProcessorKeyBuilder b(&fKey);
+        uint16_t effectKeySize;
+        if (!GetProcessorKey(*stages[s], gpu->glCaps(), useLocalCoords, &b, &effectKeySize)) {
+            fKey.reset();
+            return false;
+        }
+        get_stage_stats(*stage, &dstRead, &fragPos, &vertexShader);
+        offsetAndSize[0] = effectKeyOffset;
+        offsetAndSize[1] = effectKeySize;
+    }
 
     KeyHeader* header = this->header();
+    memset(header, 0, kHeaderSize);
     header->fEmitsPointSize = random->nextBool();
 
     header->fPositionAttributeIndex = 0;
@@ -45,8 +114,8 @@ void GrGLProgramDesc::setRandom(SkRandom* random,
     // don't try to use color or coverage attributes as input
     do {
         header->fColorInput = static_cast<GrGLProgramDesc::ColorInput>(
-                                  random->nextULessThan(kColorInputCnt));
-    } while (GrDrawState::kMaxVertexAttribCnt <= currAttribIndex &&
+                                     random->nextULessThan(kColorInputCnt));
+    } while ((GrDrawState::kMaxVertexAttribCnt <= currAttribIndex || isPathRendering) &&
              kAttribute_ColorInput == header->fColorInput);
     header->fColorAttributeIndex = (header->fColorInput == kAttribute_ColorInput) ?
                                         currAttribIndex++ :
@@ -55,73 +124,94 @@ void GrGLProgramDesc::setRandom(SkRandom* random,
     do {
         header->fCoverageInput = static_cast<GrGLProgramDesc::ColorInput>(
                                      random->nextULessThan(kColorInputCnt));
-    } while (GrDrawState::kMaxVertexAttribCnt <= currAttribIndex  &&
+    } while ((GrDrawState::kMaxVertexAttribCnt <= currAttribIndex || isPathRendering)  &&
              kAttribute_ColorInput == header->fCoverageInput);
     header->fCoverageAttributeIndex = (header->fCoverageInput == kAttribute_ColorInput) ?
                                         currAttribIndex++ :
                                         -1;
-
+    bool useGS = random->nextBool();
 #if GR_GL_EXPERIMENTAL_GS
-    header->fExperimentalGS = gpu->caps()->geometryShaderSupport() && random->nextBool();
+    header->fExperimentalGS = gpu->caps()->geometryShaderSupport() && useGS;
+#else
+    (void) useGS;
 #endif
 
-    bool useLocalCoords = random->nextBool() && currAttribIndex < GrDrawState::kMaxVertexAttribCnt;
     header->fLocalCoordAttributeIndex = useLocalCoords ? currAttribIndex++ : -1;
 
     header->fColorEffectCnt = numColorStages;
     header->fCoverageEffectCnt = numCoverageStages;
 
-    bool dstRead = false;
-    bool fragPos = false;
-    bool vertexCode = false;
-    int numStages = numColorStages + numCoverageStages;
-    for (int s = 0; s < numStages; ++s) {
-        const GrBackendEffectFactory& factory = (*stages[s]->getEffect())->getFactory();
-        GrDrawEffect drawEffect(*stages[s], useLocalCoords);
-        this->effectKeys()[s] = factory.glEffectKey(drawEffect, gpu->glCaps());
-        if ((*stages[s]->getEffect())->willReadDstColor()) {
-            dstRead = true;
-        }
-        if ((*stages[s]->getEffect())->willReadFragmentPosition()) {
-            fragPos = true;
-        }
-        if ((*stages[s]->getEffect())->hasVertexCode()) {
-            vertexCode = true;
-        }
-    }
-
     if (dstRead) {
-        header->fDstReadKey = GrGLShaderBuilder::KeyForDstRead(dstCopyTexture, gpu->glCaps());
+        header->fDstReadKey = SkToU8(GrGLFragmentShaderBuilder::KeyForDstRead(dstCopyTexture,
+                                                                      gpu->glCaps()));
     } else {
         header->fDstReadKey = 0;
     }
     if (fragPos) {
-        header->fFragPosKey = GrGLShaderBuilder::KeyForFragmentPosition(dstRenderTarget,
-                                                                         gpu->glCaps());
+        header->fFragPosKey = SkToU8(GrGLFragmentShaderBuilder::KeyForFragmentPosition(dstRenderTarget,
+                                                                               gpu->glCaps()));
     } else {
         header->fFragPosKey = 0;
     }
 
-    header->fHasVertexCode = vertexCode ||
-                             useLocalCoords ||
-                             kAttribute_ColorInput == header->fColorInput ||
-                             kAttribute_ColorInput == header->fCoverageInput;
+    header->fUseFragShaderOnly = isPathRendering && gpu->glPathRendering()->texturingMode() ==
+                                                    GrGLPathRendering::FixedFunction_TexturingMode;
+    header->fHasGeometryProcessor = vertexShader;
 
-    CoverageOutput coverageOutput;
-    bool illegalCoverageOutput;
-    do {
-        coverageOutput = static_cast<CoverageOutput>(random->nextULessThan(kCoverageOutputCnt));
-        illegalCoverageOutput = (!gpu->caps()->dualSourceBlendingSupport() &&
-                                 CoverageOutputUsesSecondaryOutput(coverageOutput)) ||
-                                (!dstRead && kCombineWithDst_CoverageOutput == coverageOutput);
-    } while (illegalCoverageOutput);
+    GrOptDrawState::PrimaryOutputType primaryOutput;
+    GrOptDrawState::SecondaryOutputType secondaryOutput;
+    if (!dstRead) {
+        primaryOutput = GrOptDrawState::kModulate_PrimaryOutputType;
+    } else {
+        primaryOutput = static_cast<GrOptDrawState::PrimaryOutputType>(
+            random->nextULessThan(GrOptDrawState::kPrimaryOutputTypeCnt));
+    }
+
+    if (GrOptDrawState::kCombineWithDst_PrimaryOutputType == primaryOutput ||
+        !gpu->caps()->dualSourceBlendingSupport()) {
+        secondaryOutput = GrOptDrawState::kNone_SecondaryOutputType;
+    } else {
+        secondaryOutput = static_cast<GrOptDrawState::SecondaryOutputType>(
+            random->nextULessThan(GrOptDrawState::kSecondaryOutputTypeCnt));
+    }
 
-    header->fCoverageOutput = coverageOutput;
+    header->fPrimaryOutputType = primaryOutput;
+    header->fSecondaryOutputType = secondaryOutput;
 
-    *this->checksum() = 0;
-    *this->checksum() = SkChecksum::Compute(reinterpret_cast<uint32_t*>(fKey.get()), keyLength);
-    fInitialized = true;
+    this->finalize();
+    return true;
+}
+
+// TODO clean this up, we have to do this to test geometry processors but there has got to be
+// a better way.  In the mean time, we actually fill out these generic vertex attribs below with
+// the correct vertex attribs from the GP.  We have to ensure, however, we don't try to add more
+// than two attributes.
+GrVertexAttrib genericVertexAttribs[] = {
+    { kVec2f_GrVertexAttribType, 0,   kPosition_GrVertexAttribBinding },
+    { kVec2f_GrVertexAttribType, 0,   kGeometryProcessor_GrVertexAttribBinding },
+    { kVec2f_GrVertexAttribType, 0,   kGeometryProcessor_GrVertexAttribBinding }
+};
+
+/*
+ * convert sl type to vertexattrib type, not a complete implementation, only use for debugging
+ */
+GrVertexAttribType convert_sltype_to_attribtype(GrSLType type) {
+    switch (type) {
+        case kFloat_GrSLType:
+            return kFloat_GrVertexAttribType;
+        case kVec2f_GrSLType:
+            return kVec2f_GrVertexAttribType;
+        case kVec3f_GrSLType:
+            return kVec3f_GrVertexAttribType;
+        case kVec4f_GrSLType:
+            return kVec4f_GrVertexAttribType;
+        default:
+            SkFAIL("Type isn't convertible");
+            return kFloat_GrVertexAttribType;
+    }
 }
+// TODO end test hack
+
 
 bool GrGpuGL::programUnitTest(int maxStages) {
 
@@ -137,6 +227,10 @@ bool GrGpuGL::programUnitTest(int maxStages) {
     dummyDesc.fHeight = 22;
     SkAutoTUnref<GrTexture> dummyTexture2(this->createTexture(dummyDesc, NULL, 0));
 
+    if (!dummyTexture1 || ! dummyTexture2) {
+        return false;
+    }
+
     static const int NUM_TESTS = 512;
 
     SkRandom random;
@@ -154,65 +248,93 @@ bool GrGpuGL::programUnitTest(int maxStages) {
 
         int currAttribIndex = 1;  // we need to always leave room for position
         int currTextureCoordSet = 0;
-        int attribIndices[2] = { 0, 0 };
         GrTexture* dummyTextures[] = {dummyTexture1.get(), dummyTexture2.get()};
 
         int numStages = random.nextULessThan(maxStages + 1);
         int numColorStages = random.nextULessThan(numStages + 1);
         int numCoverageStages = numStages - numColorStages;
 
-        SkAutoSTMalloc<8, const GrEffectStage*> stages(numStages);
-
-        bool useFixedFunctionTexturing = this->shouldUseFixedFunctionTexturing();
+        SkAutoSTMalloc<8, const GrFragmentStage*> stages(numStages);
+
+        bool usePathRendering = this->glCaps().pathRenderingSupport() && random.nextBool();
+
+        GrGpu::DrawType drawType = usePathRendering ? GrGpu::kDrawPath_DrawType :
+                                                      GrGpu::kDrawPoints_DrawType;
+
+        SkAutoTDelete<GrGeometryStage> geometryProcessor;
+        bool hasGeometryProcessor = usePathRendering ? false : random.nextBool();
+        if (hasGeometryProcessor) {
+            while (true) {
+                SkAutoTUnref<const GrGeometryProcessor> effect(
+                        GrProcessorTestFactory<GrGeometryProcessor>::CreateStage(&random, this->getContext(), *this->caps(),
+                                                         dummyTextures));
+                SkASSERT(effect);
+                // Only geometryProcessor can use vertex shader
+                GrGeometryStage* stage = SkNEW_ARGS(GrGeometryStage, (effect.get()));
+                geometryProcessor.reset(stage);
+
+                // we have to set dummy vertex attribs
+                const GrGeometryProcessor::VertexAttribArray& v = effect->getVertexAttribs();
+                int numVertexAttribs = v.count();
+
+                SkASSERT(GrGeometryProcessor::kMaxVertexAttribs == 2 &&
+                         GrGeometryProcessor::kMaxVertexAttribs >= numVertexAttribs);
+                size_t runningStride = GrVertexAttribTypeSize(genericVertexAttribs[0].fType);
+                for (int i = 0; i < numVertexAttribs; i++) {
+                    genericVertexAttribs[i + 1].fOffset = runningStride;
+                    genericVertexAttribs[i + 1].fType =
+                            convert_sltype_to_attribtype(v[i].getType());
+                    runningStride += GrVertexAttribTypeSize(genericVertexAttribs[i + 1].fType);
+                }
 
+                // update the vertex attributes with the ds
+                GrDrawState* ds = this->drawState();
+                ds->setVertexAttribs<genericVertexAttribs>(numVertexAttribs + 1, runningStride);
+                currAttribIndex = numVertexAttribs + 1;
+                break;
+            }
+        }
         for (int s = 0; s < numStages;) {
-            SkAutoTUnref<const GrEffectRef> effect(GrEffectTestFactory::CreateStage(
+            SkAutoTUnref<const GrFragmentProcessor> effect(
+                    GrProcessorTestFactory<GrFragmentProcessor>::CreateStage(
                                                                             &random,
                                                                             this->getContext(),
                                                                             *this->caps(),
                                                                             dummyTextures));
             SkASSERT(effect);
-            int numAttribs = (*effect)->numVertexAttribs();
-
-            // If adding this effect would exceed the max attrib count then generate a
-            // new random effect.
-            if (currAttribIndex + numAttribs > GrDrawState::kMaxVertexAttribCnt) {
-                continue;
-            }
-
 
             // If adding this effect would exceed the max texture coord set count then generate a
             // new random effect.
-            if (useFixedFunctionTexturing && !(*effect)->hasVertexCode()) {
-                int numTransforms = (*effect)->numTransforms();
+            if (usePathRendering && this->glPathRendering()->texturingMode() ==
+                                    GrGLPathRendering::FixedFunction_TexturingMode) {;
+                int numTransforms = effect->numTransforms();
                 if (currTextureCoordSet + numTransforms > this->glCaps().maxFixedFunctionTextureCoords()) {
                     continue;
                 }
                 currTextureCoordSet += numTransforms;
             }
+            GrFragmentStage* stage = SkNEW_ARGS(GrFragmentStage, (effect.get()));
 
-            useFixedFunctionTexturing = useFixedFunctionTexturing && !(*effect)->hasVertexCode();
-
-            for (int i = 0; i < numAttribs; ++i) {
-                attribIndices[i] = currAttribIndex++;
-            }
-            GrEffectStage* stage = SkNEW_ARGS(GrEffectStage,
-                                              (effect.get(), attribIndices[0], attribIndices[1]));
             stages[s] = stage;
             ++s;
         }
         const GrTexture* dstTexture = random.nextBool() ? dummyTextures[0] : dummyTextures[1];
-        pdesc.setRandom(&random,
-                        this,
-                        dummyTextures[0]->asRenderTarget(),
-                        dstTexture,
-                        stages.get(),
-                        numColorStages,
-                        numCoverageStages,
-                        currAttribIndex);
+        if (!pdesc.setRandom(&random,
+                             this,
+                             dummyTextures[0]->asRenderTarget(),
+                             dstTexture,
+                             geometryProcessor.get(),
+                             stages.get(),
+                             numColorStages,
+                             numCoverageStages,
+                             currAttribIndex,
+                             drawType)) {
+            return false;
+        }
 
         SkAutoTUnref<GrGLProgram> program(GrGLProgram::Create(this,
                                                               pdesc,
+                                                              geometryProcessor.get(),
                                                               stages,
                                                               stages + numColorStages));
         for (int s = 0; s < numStages; ++s) {
@@ -221,6 +343,9 @@ bool GrGpuGL::programUnitTest(int maxStages) {
         if (NULL == program.get()) {
             return false;
         }
+
+        // We have to reset the drawstate because we might have added a gp
+        this->drawState()->reset();
     }
     return true;
 }
@@ -228,7 +353,7 @@ bool GrGpuGL::programUnitTest(int maxStages) {
 DEF_GPUTEST(GLPrograms, reporter, factory) {
     for (int type = 0; type < GrContextFactory::kLastGLContextType; ++type) {
         GrContext* context = factory->get(static_cast<GrContextFactory::GLContextType>(type));
-        if (NULL != context) {
+        if (context) {
             GrGpuGL* gpu = static_cast<GrGpuGL*>(context->getGpu());
             int maxStages = 6;
 #if SK_ANGLE
@@ -257,7 +382,7 @@ void forceLinking();
 void forceLinking() {
     SkLightingImageFilter::CreateDistantLitDiffuse(SkPoint3(0,0,0), 0, 0, 0);
     SkAlphaThresholdFilter::Create(SkRegion(), .5f, .5f);
-    SkAutoTUnref<SkMagnifierImageFilter> mag(SkMagnifierImageFilter::Create(
+    SkAutoTUnref<SkImageFilter> mag(SkMagnifierImageFilter::Create(
         SkRect::MakeWH(SK_Scalar1, SK_Scalar1), SK_Scalar1));
     GrConfigConversionEffect::Create(NULL,
                                      false,