diff options
Diffstat (limited to 'gpu/src/GrGpuGLShaders.cpp')
-rw-r--r-- | gpu/src/GrGpuGLShaders.cpp | 845 |
1 files changed, 0 insertions, 845 deletions
diff --git a/gpu/src/GrGpuGLShaders.cpp b/gpu/src/GrGpuGLShaders.cpp deleted file mode 100644 index 0a933b5..0000000 --- a/gpu/src/GrGpuGLShaders.cpp +++ /dev/null @@ -1,845 +0,0 @@ -/* - Copyright 2011 Google Inc. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ - -#include "GrBinHashKey.h" -#include "GrGLProgram.h" -#include "GrGpuGLShaders.h" -#include "GrGpuVertex.h" -#include "GrMemory.h" -#include "GrNoncopyable.h" -#include "GrStringBuilder.h" -#include "GrRandom.h" - -#define SKIP_CACHE_CHECK true -#define GR_UINT32_MAX static_cast<uint32_t>(-1) - -#include "GrTHashCache.h" - -class GrGpuGLShaders::ProgramCache : public ::GrNoncopyable { -private: - class Entry; - -#if GR_DEBUG - typedef GrBinHashKey<Entry, 4> ProgramHashKey; // Flex the dynamic allocation muscle in debug -#else - typedef GrBinHashKey<Entry, 64> ProgramHashKey; -#endif - - class Entry : public ::GrNoncopyable { - public: - Entry() {} - void copyAndTakeOwnership(Entry& entry) { - fProgramData.copyAndTakeOwnership(entry.fProgramData); - fKey.copyAndTakeOwnership(entry.fKey); // ownership transfer - fLRUStamp = entry.fLRUStamp; - } - - public: - int compare(const ProgramHashKey& key) const { return fKey.compare(key); } - - public: - GrGLProgram::CachedData fProgramData; - ProgramHashKey fKey; - unsigned int fLRUStamp; - }; - - GrTHashTable<Entry, ProgramHashKey, 8> fHashCache; - - // We may have kMaxEntries+1 shaders in the GL context because - // we create a new shader before evicting from the cache. - enum { - kMaxEntries = 32 - }; - Entry fEntries[kMaxEntries]; - int fCount; - unsigned int fCurrLRUStamp; - -public: - ProgramCache() - : fCount(0) - , fCurrLRUStamp(0) { - } - - ~ProgramCache() { - for (int i = 0; i < fCount; ++i) { - GrGpuGLShaders::DeleteProgram(&fEntries[i].fProgramData); - } - } - - void abandon() { - fCount = 0; - } - - void invalidateViewMatrices() { - for (int i = 0; i < fCount; ++i) { - // set to illegal matrix - fEntries[i].fProgramData.fViewMatrix = GrMatrix::InvalidMatrix(); - } - } - - GrGLProgram::CachedData* getProgramData(const GrGLProgram& desc) { - Entry newEntry; - while (newEntry.fKey.doPass()) { - desc.buildKey(newEntry.fKey); - } - Entry* entry = fHashCache.find(newEntry.fKey); - if (NULL == entry) { - if (!desc.genProgram(&newEntry.fProgramData)) { - return NULL; - } - if (fCount < kMaxEntries) { - entry = fEntries + fCount; - ++fCount; - } else { - GrAssert(kMaxEntries == fCount); - entry = fEntries; - for (int i = 1; i < kMaxEntries; ++i) { - if (fEntries[i].fLRUStamp < entry->fLRUStamp) { - entry = fEntries + i; - } - } - fHashCache.remove(entry->fKey, entry); - GrGpuGLShaders::DeleteProgram(&entry->fProgramData); - } - entry->copyAndTakeOwnership(newEntry); - fHashCache.insert(entry->fKey, entry); - } - - entry->fLRUStamp = fCurrLRUStamp; - if (GR_UINT32_MAX == fCurrLRUStamp) { - // wrap around! just trash our LRU, one time hit. - for (int i = 0; i < fCount; ++i) { - fEntries[i].fLRUStamp = 0; - } - } - ++fCurrLRUStamp; - return &entry->fProgramData; - } -}; - -void GrGpuGLShaders::abandonResources(){ - INHERITED::abandonResources(); - fProgramCache->abandon(); -} - -void GrGpuGLShaders::DeleteProgram(GrGLProgram::CachedData* programData) { - GR_GL(DeleteShader(programData->fVShaderID)); - GR_GL(DeleteShader(programData->fFShaderID)); - GR_GL(DeleteProgram(programData->fProgramID)); - GR_DEBUGCODE(memset(programData, 0, sizeof(*programData));) -} - -void GrGpuGLShaders::ProgramUnitTest() { - - static const int STAGE_OPTS[] = { - 0, - GrGLProgram::ProgramDesc::StageDesc::kNoPerspective_OptFlagBit, - GrGLProgram::ProgramDesc::StageDesc::kIdentity_CoordMapping - }; - static const GrGLProgram::ProgramDesc::StageDesc::Modulation STAGE_MODULATES[] = { - GrGLProgram::ProgramDesc::StageDesc::kColor_Modulation, - GrGLProgram::ProgramDesc::StageDesc::kAlpha_Modulation - }; - static const GrGLProgram::ProgramDesc::StageDesc::CoordMapping STAGE_COORD_MAPPINGS[] = { - GrGLProgram::ProgramDesc::StageDesc::kIdentity_CoordMapping, - GrGLProgram::ProgramDesc::StageDesc::kRadialGradient_CoordMapping, - GrGLProgram::ProgramDesc::StageDesc::kSweepGradient_CoordMapping, - GrGLProgram::ProgramDesc::StageDesc::kRadial2Gradient_CoordMapping - }; - static const GrGLProgram::ProgramDesc::StageDesc::FetchMode FETCH_MODES[] = { - GrGLProgram::ProgramDesc::StageDesc::kSingle_FetchMode, - GrGLProgram::ProgramDesc::StageDesc::k2x2_FetchMode, - }; - GrGLProgram program; - GrGLProgram::ProgramDesc& pdesc = program.fProgramDesc; - - static const int NUM_TESTS = 512; - - // GrRandoms nextU() values have patterns in the low bits - // So using nextU() % array_count might never take some values. - GrRandom random; - for (int t = 0; t < NUM_TESTS; ++t) { - -#if 0 - GrPrintf("\nTest Program %d\n-------------\n", t); - static const int stop = -1; - if (t == stop) { - int breakpointhere = 9; - } -#endif - - pdesc.fVertexLayout = 0; - pdesc.fEmitsPointSize = random.nextF() > .5f; - float colorType = random.nextF(); - if (colorType < 1.f / 3.f) { - pdesc.fColorType = GrGLProgram::ProgramDesc::kAttribute_ColorType; - } else if (colorType < 2.f / 3.f) { - pdesc.fColorType = GrGLProgram::ProgramDesc::kUniform_ColorType; - } else { - pdesc.fColorType = GrGLProgram::ProgramDesc::kNone_ColorType; - } - - int idx = (int)(random.nextF() * (SkXfermode::kCoeffModesCnt)); - pdesc.fColorFilterXfermode = (SkXfermode::Mode)idx; - - idx = (int)(random.nextF() * (kNumStages+1)); - pdesc.fFirstCoverageStage = idx; - - pdesc.fEdgeAANumEdges = (random.nextF() * (getMaxEdges() + 1)); - - if (fDualSourceBlendingSupport) { - pdesc.fDualSrcOutput = - (GrGLProgram::ProgramDesc::DualSrcOutput) - (int)(random.nextF() * GrGLProgram::ProgramDesc::kDualSrcOutputCnt); - } else { - pdesc.fDualSrcOutput = - GrGLProgram::ProgramDesc::kNone_DualSrcOutput; - } - - for (int s = 0; s < kNumStages; ++s) { - // enable the stage? - if (random.nextF() > .5f) { - // use separate tex coords? - if (random.nextF() > .5f) { - int t = (int)(random.nextF() * kMaxTexCoords); - pdesc.fVertexLayout |= StageTexCoordVertexLayoutBit(s, t); - } else { - pdesc.fVertexLayout |= StagePosAsTexCoordVertexLayoutBit(s); - } - } - // use text-formatted verts? - if (random.nextF() > .5f) { - pdesc.fVertexLayout |= kTextFormat_VertexLayoutBit; - } - idx = (int)(random.nextF() * GR_ARRAY_COUNT(STAGE_OPTS)); - pdesc.fStages[s].fOptFlags = STAGE_OPTS[idx]; - idx = (int)(random.nextF() * GR_ARRAY_COUNT(STAGE_MODULATES)); - pdesc.fStages[s].fModulation = STAGE_MODULATES[idx]; - idx = (int)(random.nextF() * GR_ARRAY_COUNT(STAGE_COORD_MAPPINGS)); - pdesc.fStages[s].fCoordMapping = STAGE_COORD_MAPPINGS[idx]; - idx = (int)(random.nextF() * GR_ARRAY_COUNT(FETCH_MODES)); - pdesc.fStages[s].fFetchMode = FETCH_MODES[idx]; - pdesc.fStages[s].setEnabled(VertexUsesStage(s, pdesc.fVertexLayout)); - } - GrGLProgram::CachedData cachedData; - program.genProgram(&cachedData); - DeleteProgram(&cachedData); - bool again = false; - if (again) { - program.genProgram(&cachedData); - DeleteProgram(&cachedData); - } - } -} - -GrGpuGLShaders::GrGpuGLShaders() { - - resetContext(); - int major, minor; - gl_version(&major, &minor); - - f4X4DownsampleFilterSupport = true; - if (GR_GL_SUPPORT_DESKTOP) { - fDualSourceBlendingSupport = - major > 3 ||(3 == major && 3 <= minor) || - has_gl_extension("GL_ARB_blend_func_extended"); - } else { - fDualSourceBlendingSupport = false; - } - - fProgramData = NULL; - fProgramCache = new ProgramCache(); - -#if 0 - ProgramUnitTest(); -#endif -} - -GrGpuGLShaders::~GrGpuGLShaders() { - delete fProgramCache; -} - -const GrMatrix& GrGpuGLShaders::getHWSamplerMatrix(int stage) { - GrAssert(fProgramData); - - if (GrGLProgram::kSetAsAttribute == - fProgramData->fUniLocations.fStages[stage].fTextureMatrixUni) { - return fHWDrawState.fSamplerStates[stage].getMatrix(); - } else { - return fProgramData->fTextureMatrices[stage]; - } -} - -void GrGpuGLShaders::recordHWSamplerMatrix(int stage, const GrMatrix& matrix) { - GrAssert(fProgramData); - if (GrGLProgram::kSetAsAttribute == - fProgramData->fUniLocations.fStages[stage].fTextureMatrixUni) { - fHWDrawState.fSamplerStates[stage].setMatrix(matrix); - } else { - fProgramData->fTextureMatrices[stage] = matrix; - } -} - -void GrGpuGLShaders::resetContext() { - INHERITED::resetContext(); - - fHWGeometryState.fVertexLayout = 0; - fHWGeometryState.fVertexOffset = ~0; - GR_GL(DisableVertexAttribArray(GrGLProgram::ColorAttributeIdx())); - for (int t = 0; t < kMaxTexCoords; ++t) { - GR_GL(DisableVertexAttribArray(GrGLProgram::TexCoordAttributeIdx(t))); - } - GR_GL(EnableVertexAttribArray(GrGLProgram::PositionAttributeIdx())); - - fHWProgramID = 0; -} - -void GrGpuGLShaders::flushViewMatrix() { - GrAssert(NULL != fCurrDrawState.fRenderTarget); - GrMatrix m; - m.setAll( - GrIntToScalar(2) / fCurrDrawState.fRenderTarget->width(), 0, -GR_Scalar1, - 0,-GrIntToScalar(2) / fCurrDrawState.fRenderTarget->height(), GR_Scalar1, - 0, 0, GrMatrix::I()[8]); - m.setConcat(m, fCurrDrawState.fViewMatrix); - - // ES doesn't allow you to pass true to the transpose param, - // so do our own transpose - GrGLfloat mt[] = { - GrScalarToFloat(m[GrMatrix::kMScaleX]), - GrScalarToFloat(m[GrMatrix::kMSkewY]), - GrScalarToFloat(m[GrMatrix::kMPersp0]), - GrScalarToFloat(m[GrMatrix::kMSkewX]), - GrScalarToFloat(m[GrMatrix::kMScaleY]), - GrScalarToFloat(m[GrMatrix::kMPersp1]), - GrScalarToFloat(m[GrMatrix::kMTransX]), - GrScalarToFloat(m[GrMatrix::kMTransY]), - GrScalarToFloat(m[GrMatrix::kMPersp2]) - }; - - if (GrGLProgram::kSetAsAttribute == - fProgramData->fUniLocations.fViewMatrixUni) { - int baseIdx = GrGLProgram::ViewMatrixAttributeIdx(); - GR_GL(VertexAttrib4fv(baseIdx + 0, mt+0)); - GR_GL(VertexAttrib4fv(baseIdx + 1, mt+3)); - GR_GL(VertexAttrib4fv(baseIdx + 2, mt+6)); - } else { - GrAssert(GrGLProgram::kUnusedUniform != - fProgramData->fUniLocations.fViewMatrixUni); - GR_GL(UniformMatrix3fv(fProgramData->fUniLocations.fViewMatrixUni, - 1, false, mt)); - } -} - -void GrGpuGLShaders::flushTextureDomain(int s) { - const GrGLint& uni = fProgramData->fUniLocations.fStages[s].fTexDomUni; - if (GrGLProgram::kUnusedUniform != uni) { - const GrRect &texDom = - fCurrDrawState.fSamplerStates[s].getTextureDomain(); - - if (((1 << s) & fDirtyFlags.fTextureChangedMask) || - fProgramData->fTextureDomain[s] != texDom) { - - fProgramData->fTextureDomain[s] = texDom; - - float values[4] = { - GrScalarToFloat(texDom.left()), - GrScalarToFloat(texDom.top()), - GrScalarToFloat(texDom.right()), - GrScalarToFloat(texDom.bottom()) - }; - - GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTextures[s]; - GrGLTexture::Orientation orientation = texture->orientation(); - - // vertical flip if necessary - if (GrGLTexture::kBottomUp_Orientation == orientation) { - values[1] = 1.0f - values[1]; - values[3] = 1.0f - values[3]; - // The top and bottom were just flipped, so correct the ordering - // of elements so that values = (l, t, r, b). - SkTSwap(values[1], values[3]); - } - - values[0] *= SkScalarToFloat(texture->contentScaleX()); - values[2] *= SkScalarToFloat(texture->contentScaleX()); - values[1] *= SkScalarToFloat(texture->contentScaleY()); - values[3] *= SkScalarToFloat(texture->contentScaleY()); - - GR_GL(Uniform4fv(uni, 1, values)); - } - } -} - -void GrGpuGLShaders::flushTextureMatrix(int s) { - const GrGLint& uni = fProgramData->fUniLocations.fStages[s].fTextureMatrixUni; - GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTextures[s]; - if (NULL != texture) { - if (GrGLProgram::kUnusedUniform != uni && - (((1 << s) & fDirtyFlags.fTextureChangedMask) || - getHWSamplerMatrix(s) != getSamplerMatrix(s))) { - - GrAssert(NULL != fCurrDrawState.fTextures[s]); - - GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTextures[s]; - - GrMatrix m = getSamplerMatrix(s); - GrSamplerState::SampleMode mode = - fCurrDrawState.fSamplerStates[s].getSampleMode(); - AdjustTextureMatrix(texture, mode, &m); - - // ES doesn't allow you to pass true to the transpose param, - // so do our own transpose - GrGLfloat mt[] = { - GrScalarToFloat(m[GrMatrix::kMScaleX]), - GrScalarToFloat(m[GrMatrix::kMSkewY]), - GrScalarToFloat(m[GrMatrix::kMPersp0]), - GrScalarToFloat(m[GrMatrix::kMSkewX]), - GrScalarToFloat(m[GrMatrix::kMScaleY]), - GrScalarToFloat(m[GrMatrix::kMPersp1]), - GrScalarToFloat(m[GrMatrix::kMTransX]), - GrScalarToFloat(m[GrMatrix::kMTransY]), - GrScalarToFloat(m[GrMatrix::kMPersp2]) - }; - - if (GrGLProgram::kSetAsAttribute == - fProgramData->fUniLocations.fStages[s].fTextureMatrixUni) { - int baseIdx = GrGLProgram::TextureMatrixAttributeIdx(s); - GR_GL(VertexAttrib4fv(baseIdx + 0, mt+0)); - GR_GL(VertexAttrib4fv(baseIdx + 1, mt+3)); - GR_GL(VertexAttrib4fv(baseIdx + 2, mt+6)); - } else { - GR_GL(UniformMatrix3fv(uni, 1, false, mt)); - } - recordHWSamplerMatrix(s, getSamplerMatrix(s)); - } - } -} - -void GrGpuGLShaders::flushRadial2(int s) { - - const int &uni = fProgramData->fUniLocations.fStages[s].fRadial2Uni; - const GrSamplerState& sampler = fCurrDrawState.fSamplerStates[s]; - if (GrGLProgram::kUnusedUniform != uni && - (fProgramData->fRadial2CenterX1[s] != sampler.getRadial2CenterX1() || - fProgramData->fRadial2Radius0[s] != sampler.getRadial2Radius0() || - fProgramData->fRadial2PosRoot[s] != sampler.isRadial2PosRoot())) { - - GrScalar centerX1 = sampler.getRadial2CenterX1(); - GrScalar radius0 = sampler.getRadial2Radius0(); - - GrScalar a = GrMul(centerX1, centerX1) - GR_Scalar1; - - float values[6] = { - GrScalarToFloat(a), - 1 / (2.f * values[0]), - GrScalarToFloat(centerX1), - GrScalarToFloat(radius0), - GrScalarToFloat(GrMul(radius0, radius0)), - sampler.isRadial2PosRoot() ? 1.f : -1.f - }; - GR_GL(Uniform1fv(uni, 6, values)); - fProgramData->fRadial2CenterX1[s] = sampler.getRadial2CenterX1(); - fProgramData->fRadial2Radius0[s] = sampler.getRadial2Radius0(); - fProgramData->fRadial2PosRoot[s] = sampler.isRadial2PosRoot(); - } -} - -void GrGpuGLShaders::flushTexelSize(int s) { - const int& uni = fProgramData->fUniLocations.fStages[s].fNormalizedTexelSizeUni; - if (GrGLProgram::kUnusedUniform != uni) { - GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTextures[s]; - if (texture->allocWidth() != fProgramData->fTextureWidth[s] || - texture->allocHeight() != fProgramData->fTextureWidth[s]) { - - float texelSize[] = {1.f / texture->allocWidth(), - 1.f / texture->allocHeight()}; - GR_GL(Uniform2fv(uni, 1, texelSize)); - } - } -} - -void GrGpuGLShaders::flushEdgeAAData() { - const int& uni = fProgramData->fUniLocations.fEdgesUni; - if (GrGLProgram::kUnusedUniform != uni) { - int count = fCurrDrawState.fEdgeAANumEdges; - Edge edges[kMaxEdges]; - // Flip the edges in Y - float height = fCurrDrawState.fRenderTarget->height(); - for (int i = 0; i < count; ++i) { - edges[i] = fCurrDrawState.fEdgeAAEdges[i]; - float b = edges[i].fY; - edges[i].fY = -b; - edges[i].fZ += b * height; - } - GR_GL(Uniform3fv(uni, count, &edges[0].fX)); - } -} - -static const float ONE_OVER_255 = 1.f / 255.f; - -#define GR_COLOR_TO_VEC4(color) {\ - GrColorUnpackR(color) * ONE_OVER_255,\ - GrColorUnpackG(color) * ONE_OVER_255,\ - GrColorUnpackB(color) * ONE_OVER_255,\ - GrColorUnpackA(color) * ONE_OVER_255 \ -} - -void GrGpuGLShaders::flushColor() { - const GrGLProgram::ProgramDesc& desc = fCurrentProgram.getDesc(); - if (fGeometrySrc.fVertexLayout & kColor_VertexLayoutBit) { - // color will be specified per-vertex as an attribute - // invalidate the const vertex attrib color - fHWDrawState.fColor = GrColor_ILLEGAL; - } else { - switch (desc.fColorType) { - case GrGLProgram::ProgramDesc::kAttribute_ColorType: - if (fHWDrawState.fColor != fCurrDrawState.fColor) { - // OpenGL ES only supports the float varities of glVertexAttrib - float c[] = GR_COLOR_TO_VEC4(fCurrDrawState.fColor); - GR_GL(VertexAttrib4fv(GrGLProgram::ColorAttributeIdx(), c)); - fHWDrawState.fColor = fCurrDrawState.fColor; - } - break; - case GrGLProgram::ProgramDesc::kUniform_ColorType: - if (fProgramData->fColor != fCurrDrawState.fColor) { - // OpenGL ES only supports the float varities of glVertexAttrib - float c[] = GR_COLOR_TO_VEC4(fCurrDrawState.fColor); - GrAssert(GrGLProgram::kUnusedUniform != - fProgramData->fUniLocations.fColorUni); - GR_GL(Uniform4fv(fProgramData->fUniLocations.fColorUni, 1, c)); - fProgramData->fColor = fCurrDrawState.fColor; - } - break; - case GrGLProgram::ProgramDesc::kNone_ColorType: - GrAssert(0xffffffff == fCurrDrawState.fColor); - break; - default: - GrCrash("Unknown color type."); - } - } - if (fProgramData->fUniLocations.fColorFilterUni - != GrGLProgram::kUnusedUniform - && fProgramData->fColorFilterColor - != fCurrDrawState.fColorFilterColor) { - float c[] = GR_COLOR_TO_VEC4(fCurrDrawState.fColorFilterColor); - GR_GL(Uniform4fv(fProgramData->fUniLocations.fColorFilterUni, 1, c)); - fProgramData->fColorFilterColor = fCurrDrawState.fColorFilterColor; - } -} - - -bool GrGpuGLShaders::flushGraphicsState(GrPrimitiveType type) { - if (!flushGLStateCommon(type)) { - return false; - } - - if (fDirtyFlags.fRenderTargetChanged) { - // our coords are in pixel space and the GL matrices map to NDC - // so if the viewport changed, our matrix is now wrong. - fHWDrawState.fViewMatrix = GrMatrix::InvalidMatrix(); - // we assume all shader matrices may be wrong after viewport changes - fProgramCache->invalidateViewMatrices(); - } - - buildProgram(type); - fProgramData = fProgramCache->getProgramData(fCurrentProgram); - if (NULL == fProgramData) { - GrAssert(!"Failed to create program!"); - return false; - } - - if (fHWProgramID != fProgramData->fProgramID) { - GR_GL(UseProgram(fProgramData->fProgramID)); - fHWProgramID = fProgramData->fProgramID; - } - GrBlendCoeff srcCoeff = fCurrDrawState.fSrcBlend; - GrBlendCoeff dstCoeff = fCurrDrawState.fDstBlend; - - fCurrentProgram.overrideBlend(&srcCoeff, &dstCoeff); - this->flushBlend(type, srcCoeff, dstCoeff); - - this->flushColor(); - - GrMatrix* currViewMatrix; - if (GrGLProgram::kSetAsAttribute == - fProgramData->fUniLocations.fViewMatrixUni) { - currViewMatrix = &fHWDrawState.fViewMatrix; - } else { - currViewMatrix = &fProgramData->fViewMatrix; - } - - if (*currViewMatrix != fCurrDrawState.fViewMatrix) { - flushViewMatrix(); - *currViewMatrix = fCurrDrawState.fViewMatrix; - } - - for (int s = 0; s < kNumStages; ++s) { - this->flushTextureMatrix(s); - - this->flushRadial2(s); - - this->flushTexelSize(s); - - this->flushTextureDomain(s); - } - this->flushEdgeAAData(); - resetDirtyFlags(); - return true; -} - -void GrGpuGLShaders::postDraw() { -} - -void GrGpuGLShaders::setupGeometry(int* startVertex, - int* startIndex, - int vertexCount, - int indexCount) { - - int newColorOffset; - int newTexCoordOffsets[kMaxTexCoords]; - - GrGLsizei newStride = VertexSizeAndOffsetsByIdx(fGeometrySrc.fVertexLayout, - newTexCoordOffsets, - &newColorOffset); - int oldColorOffset; - int oldTexCoordOffsets[kMaxTexCoords]; - GrGLsizei oldStride = VertexSizeAndOffsetsByIdx(fHWGeometryState.fVertexLayout, - oldTexCoordOffsets, - &oldColorOffset); - bool indexed = NULL != startIndex; - - int extraVertexOffset; - int extraIndexOffset; - setBuffers(indexed, &extraVertexOffset, &extraIndexOffset); - - GrGLenum scalarType; - bool texCoordNorm; - if (fGeometrySrc.fVertexLayout & kTextFormat_VertexLayoutBit) { - scalarType = GrGLTextType; - texCoordNorm = GR_GL_TEXT_TEXTURE_NORMALIZED; - } else { - scalarType = GrGLType; - texCoordNorm = false; - } - - size_t vertexOffset = (*startVertex + extraVertexOffset) * newStride; - *startVertex = 0; - if (indexed) { - *startIndex += extraIndexOffset; - } - - // all the Pointers must be set if any of these are true - bool allOffsetsChange = fHWGeometryState.fArrayPtrsDirty || - vertexOffset != fHWGeometryState.fVertexOffset || - newStride != oldStride; - - // position and tex coord offsets change if above conditions are true - // or the type/normalization changed based on text vs nontext type coords. - bool posAndTexChange = allOffsetsChange || - (((GrGLTextType != GrGLType) || GR_GL_TEXT_TEXTURE_NORMALIZED) && - (kTextFormat_VertexLayoutBit & - (fHWGeometryState.fVertexLayout ^ - fGeometrySrc.fVertexLayout))); - - if (posAndTexChange) { - int idx = GrGLProgram::PositionAttributeIdx(); - GR_GL(VertexAttribPointer(idx, 2, scalarType, false, newStride, - (GrGLvoid*)vertexOffset)); - fHWGeometryState.fVertexOffset = vertexOffset; - } - - for (int t = 0; t < kMaxTexCoords; ++t) { - if (newTexCoordOffsets[t] > 0) { - GrGLvoid* texCoordOffset = (GrGLvoid*)(vertexOffset + newTexCoordOffsets[t]); - int idx = GrGLProgram::TexCoordAttributeIdx(t); - if (oldTexCoordOffsets[t] <= 0) { - GR_GL(EnableVertexAttribArray(idx)); - GR_GL(VertexAttribPointer(idx, 2, scalarType, texCoordNorm, - newStride, texCoordOffset)); - } else if (posAndTexChange || - newTexCoordOffsets[t] != oldTexCoordOffsets[t]) { - GR_GL(VertexAttribPointer(idx, 2, scalarType, texCoordNorm, - newStride, texCoordOffset)); - } - } else if (oldTexCoordOffsets[t] > 0) { - GR_GL(DisableVertexAttribArray(GrGLProgram::TexCoordAttributeIdx(t))); - } - } - - if (newColorOffset > 0) { - GrGLvoid* colorOffset = (int8_t*)(vertexOffset + newColorOffset); - int idx = GrGLProgram::ColorAttributeIdx(); - if (oldColorOffset <= 0) { - GR_GL(EnableVertexAttribArray(idx)); - GR_GL(VertexAttribPointer(idx, 4, GR_GL_UNSIGNED_BYTE, - true, newStride, colorOffset)); - } else if (allOffsetsChange || newColorOffset != oldColorOffset) { - GR_GL(VertexAttribPointer(idx, 4, GR_GL_UNSIGNED_BYTE, - true, newStride, colorOffset)); - } - } else if (oldColorOffset > 0) { - GR_GL(DisableVertexAttribArray(GrGLProgram::ColorAttributeIdx())); - } - - fHWGeometryState.fVertexLayout = fGeometrySrc.fVertexLayout; - fHWGeometryState.fArrayPtrsDirty = false; -} - -void GrGpuGLShaders::buildProgram(GrPrimitiveType type) { - GrGLProgram::ProgramDesc& desc = fCurrentProgram.fProgramDesc; - - // Must initialize all fields or cache will have false negatives! - desc.fVertexLayout = fGeometrySrc.fVertexLayout; - - desc.fEmitsPointSize = kPoints_PrimitiveType == type; - - bool requiresAttributeColors = desc.fVertexLayout & kColor_VertexLayoutBit; - // fColorType records how colors are specified for the program. Strip - // the bit from the layout to avoid false negatives when searching for an - // existing program in the cache. - desc.fVertexLayout &= ~(kColor_VertexLayoutBit); - - desc.fColorFilterXfermode = fCurrDrawState.fColorFilterXfermode; - -#if GR_AGGRESSIVE_SHADER_OPTS - if (!requiresAttributeColors && (0xffffffff == fCurrDrawState.fColor)) { - desc.fColorType = GrGLProgram::ProgramDesc::kNone_ColorType; - } else -#endif -#if GR_GL_NO_CONSTANT_ATTRIBUTES - if (!requiresAttributeColors) { - desc.fColorType = GrGLProgram::ProgramDesc::kUniform_ColorType; - } else -#endif - { - if (requiresAttributeColors) {} // suppress unused var warning - desc.fColorType = GrGLProgram::ProgramDesc::kAttribute_ColorType; - } - - desc.fEdgeAANumEdges = fCurrDrawState.fEdgeAANumEdges; - - int lastEnabledStage = -1; - - for (int s = 0; s < kNumStages; ++s) { - GrGLProgram::ProgramDesc::StageDesc& stage = desc.fStages[s]; - - stage.fOptFlags = 0; - stage.setEnabled(this->isStageEnabled(s)); - - if (stage.isEnabled()) { - lastEnabledStage = s; - GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTextures[s]; - GrAssert(NULL != texture); - // we matrix to invert when orientation is TopDown, so make sure - // we aren't in that case before flagging as identity. - if (TextureMatrixIsIdentity(texture, fCurrDrawState.fSamplerStates[s])) { - stage.fOptFlags |= GrGLProgram::ProgramDesc::StageDesc::kIdentityMatrix_OptFlagBit; - } else if (!getSamplerMatrix(s).hasPerspective()) { - stage.fOptFlags |= GrGLProgram::ProgramDesc::StageDesc::kNoPerspective_OptFlagBit; - } - switch (fCurrDrawState.fSamplerStates[s].getSampleMode()) { - case GrSamplerState::kNormal_SampleMode: - stage.fCoordMapping = GrGLProgram::ProgramDesc::StageDesc::kIdentity_CoordMapping; - break; - case GrSamplerState::kRadial_SampleMode: - stage.fCoordMapping = GrGLProgram::ProgramDesc::StageDesc::kRadialGradient_CoordMapping; - break; - case GrSamplerState::kRadial2_SampleMode: - stage.fCoordMapping = GrGLProgram::ProgramDesc::StageDesc::kRadial2Gradient_CoordMapping; - break; - case GrSamplerState::kSweep_SampleMode: - stage.fCoordMapping = GrGLProgram::ProgramDesc::StageDesc::kSweepGradient_CoordMapping; - break; - default: - GrCrash("Unexpected sample mode!"); - break; - } - - switch (fCurrDrawState.fSamplerStates[s].getFilter()) { - // these both can use a regular texture2D() - case GrSamplerState::kNearest_Filter: - case GrSamplerState::kBilinear_Filter: - stage.fFetchMode = GrGLProgram::ProgramDesc::StageDesc::kSingle_FetchMode; - break; - // performs 4 texture2D()s - case GrSamplerState::k4x4Downsample_Filter: - stage.fFetchMode = GrGLProgram::ProgramDesc::StageDesc::k2x2_FetchMode; - break; - default: - GrCrash("Unexpected filter!"); - break; - } - - if (fCurrDrawState.fSamplerStates[s].hasTextureDomain()) { - GrAssert(GrSamplerState::kClamp_WrapMode == - fCurrDrawState.fSamplerStates[s].getWrapX() && - GrSamplerState::kClamp_WrapMode == - fCurrDrawState.fSamplerStates[s].getWrapY()); - stage.fOptFlags |= - GrGLProgram::ProgramDesc::StageDesc:: - kCustomTextureDomain_OptFlagBit; - } - - if (GrPixelConfigIsAlphaOnly(texture->config())) { - stage.fModulation = GrGLProgram::ProgramDesc::StageDesc::kAlpha_Modulation; - } else { - stage.fModulation = GrGLProgram::ProgramDesc::StageDesc::kColor_Modulation; - } - } else { - stage.fOptFlags = 0; - stage.fCoordMapping = (GrGLProgram::ProgramDesc::StageDesc::CoordMapping)0; - stage.fModulation = (GrGLProgram::ProgramDesc::StageDesc::Modulation)0; - } - } - - desc.fDualSrcOutput = GrGLProgram::ProgramDesc::kNone_DualSrcOutput; - // use canonical value when coverage/color distinction won't affect - // generated code to prevent duplicate programs. - desc.fFirstCoverageStage = kNumStages; - if (fCurrDrawState.fFirstCoverageStage <= lastEnabledStage) { - // color filter is applied between color/coverage computation - if (SkXfermode::kDst_Mode != desc.fColorFilterXfermode) { - desc.fFirstCoverageStage = fCurrDrawState.fFirstCoverageStage; - } - - // We could consider cases where the final color is solid (0xff alpha) - // and the dst coeff can correctly be set to a non-dualsrc gl value. - // (e.g. solid draw, and dst coeff is kZero. It's correct to make - // the dst coeff be kISA. Or solid draw with kSA can be tweaked to be - // kOne). - if (fDualSourceBlendingSupport) { - if (kZero_BlendCoeff == fCurrDrawState.fDstBlend) { - // write the coverage value to second color - desc.fDualSrcOutput = - GrGLProgram::ProgramDesc::kCoverage_DualSrcOutput; - desc.fFirstCoverageStage = fCurrDrawState.fFirstCoverageStage; - } else if (kSA_BlendCoeff == fCurrDrawState.fDstBlend) { - // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially - // cover - desc.fDualSrcOutput = - GrGLProgram::ProgramDesc::kCoverageISA_DualSrcOutput; - desc.fFirstCoverageStage = fCurrDrawState.fFirstCoverageStage; - } else if (kSC_BlendCoeff == fCurrDrawState.fDstBlend) { - // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially - // cover - desc.fDualSrcOutput = - GrGLProgram::ProgramDesc::kCoverageISC_DualSrcOutput; - desc.fFirstCoverageStage = fCurrDrawState.fFirstCoverageStage; - } - } - } -} |