| |
| /* |
| * Copyright 2010 Google Inc. |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| |
| |
| #include "GrDrawTarget.h" |
| #include "GrGpuVertex.h" |
| #include "GrTexture.h" |
| #include "GrVertexBuffer.h" |
| #include "GrIndexBuffer.h" |
| |
| namespace { |
| |
| // recursive helper for creating mask with all the tex coord bits set for |
| // one stage |
| template <int N> |
| int stage_mask_recur(int stage) { |
| return GrDrawTarget::StageTexCoordVertexLayoutBit(stage, N) | |
| stage_mask_recur<N+1>(stage); |
| } |
| template<> |
| int stage_mask_recur<GrDrawTarget::kNumStages>(int) { return 0; } |
| |
| // mask of all tex coord indices for one stage |
| int stage_tex_coord_mask(int stage) { |
| return stage_mask_recur<0>(stage); |
| } |
| |
| // mask of all bits relevant to one stage |
| int stage_mask(int stage) { |
| return stage_tex_coord_mask(stage) | |
| GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(stage); |
| } |
| |
| // recursive helper for creating mask of with all bits set relevant to one |
| // texture coordinate index |
| template <int N> |
| int tex_coord_mask_recur(int texCoordIdx) { |
| return GrDrawTarget::StageTexCoordVertexLayoutBit(N, texCoordIdx) | |
| tex_coord_mask_recur<N+1>(texCoordIdx); |
| } |
| template<> |
| int tex_coord_mask_recur<GrDrawTarget::kMaxTexCoords>(int) { return 0; } |
| |
| // mask of all bits relevant to one texture coordinate index |
| int tex_coord_idx_mask(int texCoordIdx) { |
| return tex_coord_mask_recur<0>(texCoordIdx); |
| } |
| |
| bool check_layout(GrVertexLayout layout) { |
| // can only have 1 or 0 bits set for each stage. |
| for (int s = 0; s < GrDrawTarget::kNumStages; ++s) { |
| int stageBits = layout & stage_mask(s); |
| if (stageBits && !GrIsPow2(stageBits)) { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| int num_tex_coords(GrVertexLayout layout) { |
| int cnt = 0; |
| // figure out how many tex coordinates are present |
| for (int t = 0; t < GrDrawTarget::kMaxTexCoords; ++t) { |
| if (tex_coord_idx_mask(t) & layout) { |
| ++cnt; |
| } |
| } |
| return cnt; |
| } |
| |
| } //unnamed namespace |
| |
| size_t GrDrawTarget::VertexSize(GrVertexLayout vertexLayout) { |
| GrAssert(check_layout(vertexLayout)); |
| |
| size_t vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ? |
| sizeof(GrGpuTextVertex) : |
| sizeof(GrPoint); |
| |
| size_t size = vecSize; // position |
| size += num_tex_coords(vertexLayout) * vecSize; |
| if (vertexLayout & kColor_VertexLayoutBit) { |
| size += sizeof(GrColor); |
| } |
| if (vertexLayout & kCoverage_VertexLayoutBit) { |
| size += sizeof(GrColor); |
| } |
| if (vertexLayout & kEdge_VertexLayoutBit) { |
| size += 4 * sizeof(GrScalar); |
| } |
| return size; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| |
| /** |
| * Functions for computing offsets of various components from the layout |
| * bitfield. |
| * |
| * Order of vertex components: |
| * Position |
| * Tex Coord 0 |
| * ... |
| * Tex Coord kMaxTexCoords-1 |
| * Color |
| * Coverage |
| */ |
| |
| int GrDrawTarget::VertexStageCoordOffset(int stage, GrVertexLayout vertexLayout) { |
| GrAssert(check_layout(vertexLayout)); |
| if (StagePosAsTexCoordVertexLayoutBit(stage) & vertexLayout) { |
| return 0; |
| } |
| int tcIdx = VertexTexCoordsForStage(stage, vertexLayout); |
| if (tcIdx >= 0) { |
| |
| int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ? |
| sizeof(GrGpuTextVertex) : |
| sizeof(GrPoint); |
| int offset = vecSize; // position |
| // figure out how many tex coordinates are present and precede this one. |
| for (int t = 0; t < tcIdx; ++t) { |
| if (tex_coord_idx_mask(t) & vertexLayout) { |
| offset += vecSize; |
| } |
| } |
| return offset; |
| } |
| |
| return -1; |
| } |
| |
| int GrDrawTarget::VertexColorOffset(GrVertexLayout vertexLayout) { |
| GrAssert(check_layout(vertexLayout)); |
| |
| if (vertexLayout & kColor_VertexLayoutBit) { |
| int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ? |
| sizeof(GrGpuTextVertex) : |
| sizeof(GrPoint); |
| return vecSize * (num_tex_coords(vertexLayout) + 1); //+1 for pos |
| } |
| return -1; |
| } |
| |
| int GrDrawTarget::VertexCoverageOffset(GrVertexLayout vertexLayout) { |
| GrAssert(check_layout(vertexLayout)); |
| |
| if (vertexLayout & kCoverage_VertexLayoutBit) { |
| int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ? |
| sizeof(GrGpuTextVertex) : |
| sizeof(GrPoint); |
| |
| int offset = vecSize * (num_tex_coords(vertexLayout) + 1); |
| if (vertexLayout & kColor_VertexLayoutBit) { |
| offset += sizeof(GrColor); |
| } |
| return offset; |
| } |
| return -1; |
| } |
| |
| int GrDrawTarget::VertexEdgeOffset(GrVertexLayout vertexLayout) { |
| GrAssert(check_layout(vertexLayout)); |
| |
| // edge pts are after the pos, tex coords, and color |
| if (vertexLayout & kEdge_VertexLayoutBit) { |
| int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ? |
| sizeof(GrGpuTextVertex) : |
| sizeof(GrPoint); |
| int offset = vecSize * (num_tex_coords(vertexLayout) + 1); //+1 for pos |
| if (vertexLayout & kColor_VertexLayoutBit) { |
| offset += sizeof(GrColor); |
| } |
| if (vertexLayout & kCoverage_VertexLayoutBit) { |
| offset += sizeof(GrColor); |
| } |
| return offset; |
| } |
| return -1; |
| } |
| |
| int GrDrawTarget::VertexSizeAndOffsetsByIdx(GrVertexLayout vertexLayout, |
| int texCoordOffsetsByIdx[kMaxTexCoords], |
| int* colorOffset, |
| int* coverageOffset, |
| int* edgeOffset) { |
| GrAssert(check_layout(vertexLayout)); |
| |
| int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ? |
| sizeof(GrGpuTextVertex) : |
| sizeof(GrPoint); |
| int size = vecSize; // position |
| |
| for (int t = 0; t < kMaxTexCoords; ++t) { |
| if (tex_coord_idx_mask(t) & vertexLayout) { |
| if (NULL != texCoordOffsetsByIdx) { |
| texCoordOffsetsByIdx[t] = size; |
| } |
| size += vecSize; |
| } else { |
| if (NULL != texCoordOffsetsByIdx) { |
| texCoordOffsetsByIdx[t] = -1; |
| } |
| } |
| } |
| if (kColor_VertexLayoutBit & vertexLayout) { |
| if (NULL != colorOffset) { |
| *colorOffset = size; |
| } |
| size += sizeof(GrColor); |
| } else { |
| if (NULL != colorOffset) { |
| *colorOffset = -1; |
| } |
| } |
| if (kCoverage_VertexLayoutBit & vertexLayout) { |
| if (NULL != coverageOffset) { |
| *coverageOffset = size; |
| } |
| size += sizeof(GrColor); |
| } else { |
| if (NULL != coverageOffset) { |
| *coverageOffset = -1; |
| } |
| } |
| if (kEdge_VertexLayoutBit & vertexLayout) { |
| if (NULL != edgeOffset) { |
| *edgeOffset = size; |
| } |
| size += 4 * sizeof(GrScalar); |
| } else { |
| if (NULL != edgeOffset) { |
| *edgeOffset = -1; |
| } |
| } |
| return size; |
| } |
| |
| int GrDrawTarget::VertexSizeAndOffsetsByStage(GrVertexLayout vertexLayout, |
| int texCoordOffsetsByStage[kNumStages], |
| int* colorOffset, |
| int* coverageOffset, |
| int* edgeOffset) { |
| GrAssert(check_layout(vertexLayout)); |
| |
| int texCoordOffsetsByIdx[kMaxTexCoords]; |
| int size = VertexSizeAndOffsetsByIdx(vertexLayout, |
| (NULL == texCoordOffsetsByStage) ? |
| NULL : |
| texCoordOffsetsByIdx, |
| colorOffset, |
| coverageOffset, |
| edgeOffset); |
| if (NULL != texCoordOffsetsByStage) { |
| for (int s = 0; s < kNumStages; ++s) { |
| int tcIdx; |
| if (StagePosAsTexCoordVertexLayoutBit(s) & vertexLayout) { |
| texCoordOffsetsByStage[s] = 0; |
| } else if ((tcIdx = VertexTexCoordsForStage(s, vertexLayout)) >= 0) { |
| texCoordOffsetsByStage[s] = texCoordOffsetsByIdx[tcIdx]; |
| } else { |
| texCoordOffsetsByStage[s] = -1; |
| } |
| } |
| } |
| return size; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| |
| bool GrDrawTarget::VertexUsesStage(int stage, GrVertexLayout vertexLayout) { |
| GrAssert(stage < kNumStages); |
| GrAssert(check_layout(vertexLayout)); |
| return !!(stage_mask(stage) & vertexLayout); |
| } |
| |
| bool GrDrawTarget::VertexUsesTexCoordIdx(int coordIndex, |
| GrVertexLayout vertexLayout) { |
| GrAssert(coordIndex < kMaxTexCoords); |
| GrAssert(check_layout(vertexLayout)); |
| return !!(tex_coord_idx_mask(coordIndex) & vertexLayout); |
| } |
| |
| int GrDrawTarget::VertexTexCoordsForStage(int stage, GrVertexLayout vertexLayout) { |
| GrAssert(stage < kNumStages); |
| GrAssert(check_layout(vertexLayout)); |
| int bit = vertexLayout & stage_tex_coord_mask(stage); |
| if (bit) { |
| // figure out which set of texture coordates is used |
| // bits are ordered T0S0, T0S1, T0S2, ..., T1S0, T1S1, ... |
| // and start at bit 0. |
| GR_STATIC_ASSERT(sizeof(GrVertexLayout) <= sizeof(uint32_t)); |
| return (32 - Gr_clz(bit) - 1) / kNumStages; |
| } |
| return -1; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| |
| void GrDrawTarget::VertexLayoutUnitTest() { |
| // not necessarily exhaustive |
| static bool run; |
| if (!run) { |
| run = true; |
| for (int s = 0; s < kNumStages; ++s) { |
| |
| GrAssert(!VertexUsesStage(s, 0)); |
| GrAssert(-1 == VertexStageCoordOffset(s, 0)); |
| GrVertexLayout stageMask = 0; |
| for (int t = 0; t < kMaxTexCoords; ++t) { |
| stageMask |= StageTexCoordVertexLayoutBit(s,t); |
| } |
| GrAssert(1 == kMaxTexCoords || !check_layout(stageMask)); |
| GrAssert(stage_tex_coord_mask(s) == stageMask); |
| stageMask |= StagePosAsTexCoordVertexLayoutBit(s); |
| GrAssert(stage_mask(s) == stageMask); |
| GrAssert(!check_layout(stageMask)); |
| } |
| for (int t = 0; t < kMaxTexCoords; ++t) { |
| GrVertexLayout tcMask = 0; |
| GrAssert(!VertexUsesTexCoordIdx(t, 0)); |
| for (int s = 0; s < kNumStages; ++s) { |
| tcMask |= StageTexCoordVertexLayoutBit(s,t); |
| GrAssert(VertexUsesStage(s, tcMask)); |
| GrAssert(sizeof(GrPoint) == VertexStageCoordOffset(s, tcMask)); |
| GrAssert(VertexUsesTexCoordIdx(t, tcMask)); |
| GrAssert(2*sizeof(GrPoint) == VertexSize(tcMask)); |
| GrAssert(t == VertexTexCoordsForStage(s, tcMask)); |
| for (int s2 = s + 1; s2 < kNumStages; ++s2) { |
| GrAssert(-1 == VertexStageCoordOffset(s2, tcMask)); |
| GrAssert(!VertexUsesStage(s2, tcMask)); |
| GrAssert(-1 == VertexTexCoordsForStage(s2, tcMask)); |
| |
| #if GR_DEBUG |
| GrVertexLayout posAsTex = tcMask | StagePosAsTexCoordVertexLayoutBit(s2); |
| #endif |
| GrAssert(0 == VertexStageCoordOffset(s2, posAsTex)); |
| GrAssert(VertexUsesStage(s2, posAsTex)); |
| GrAssert(2*sizeof(GrPoint) == VertexSize(posAsTex)); |
| GrAssert(-1 == VertexTexCoordsForStage(s2, posAsTex)); |
| GrAssert(-1 == VertexEdgeOffset(posAsTex)); |
| } |
| GrAssert(-1 == VertexEdgeOffset(tcMask)); |
| GrAssert(-1 == VertexColorOffset(tcMask)); |
| GrAssert(-1 == VertexCoverageOffset(tcMask)); |
| #if GR_DEBUG |
| GrVertexLayout withColor = tcMask | kColor_VertexLayoutBit; |
| #endif |
| GrAssert(-1 == VertexCoverageOffset(withColor)); |
| GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withColor)); |
| GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withColor)); |
| #if GR_DEBUG |
| GrVertexLayout withEdge = tcMask | kEdge_VertexLayoutBit; |
| #endif |
| GrAssert(-1 == VertexColorOffset(withEdge)); |
| GrAssert(2*sizeof(GrPoint) == VertexEdgeOffset(withEdge)); |
| GrAssert(4*sizeof(GrPoint) == VertexSize(withEdge)); |
| #if GR_DEBUG |
| GrVertexLayout withColorAndEdge = withColor | kEdge_VertexLayoutBit; |
| #endif |
| GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withColorAndEdge)); |
| GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexEdgeOffset(withColorAndEdge)); |
| GrAssert(4*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withColorAndEdge)); |
| #if GR_DEBUG |
| GrVertexLayout withCoverage = tcMask | kCoverage_VertexLayoutBit; |
| #endif |
| GrAssert(-1 == VertexColorOffset(withCoverage)); |
| GrAssert(2*sizeof(GrPoint) == VertexCoverageOffset(withCoverage)); |
| GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withCoverage)); |
| #if GR_DEBUG |
| GrVertexLayout withCoverageAndColor = tcMask | kCoverage_VertexLayoutBit | |
| kColor_VertexLayoutBit; |
| #endif |
| GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withCoverageAndColor)); |
| GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexCoverageOffset(withCoverageAndColor)); |
| GrAssert(2*sizeof(GrPoint) + 2 * sizeof(GrColor) == VertexSize(withCoverageAndColor)); |
| } |
| GrAssert(tex_coord_idx_mask(t) == tcMask); |
| GrAssert(check_layout(tcMask)); |
| |
| int stageOffsets[kNumStages]; |
| int colorOffset; |
| int edgeOffset; |
| int coverageOffset; |
| int size; |
| size = VertexSizeAndOffsetsByStage(tcMask, stageOffsets, &colorOffset, |
| &coverageOffset, &edgeOffset); |
| GrAssert(2*sizeof(GrPoint) == size); |
| GrAssert(-1 == colorOffset); |
| GrAssert(-1 == coverageOffset); |
| GrAssert(-1 == edgeOffset); |
| for (int s = 0; s < kNumStages; ++s) { |
| GrAssert(VertexUsesStage(s, tcMask)); |
| GrAssert(sizeof(GrPoint) == stageOffsets[s]); |
| GrAssert(sizeof(GrPoint) == VertexStageCoordOffset(s, tcMask)); |
| } |
| } |
| } |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| |
| #define DEBUG_INVAL_BUFFER 0xdeadcafe |
| #define DEBUG_INVAL_START_IDX -1 |
| |
| GrDrawTarget::GrDrawTarget() { |
| #if GR_DEBUG |
| VertexLayoutUnitTest(); |
| #endif |
| GeometrySrcState& geoSrc = fGeoSrcStateStack.push_back(); |
| #if GR_DEBUG |
| geoSrc.fVertexCount = DEBUG_INVAL_START_IDX; |
| geoSrc.fVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER; |
| geoSrc.fIndexCount = DEBUG_INVAL_START_IDX; |
| geoSrc.fIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER; |
| #endif |
| geoSrc.fVertexSrc = kNone_GeometrySrcType; |
| geoSrc.fIndexSrc = kNone_GeometrySrcType; |
| } |
| |
| GrDrawTarget::~GrDrawTarget() { |
| int popCnt = fGeoSrcStateStack.count() - 1; |
| while (popCnt) { |
| this->popGeometrySource(); |
| --popCnt; |
| } |
| this->releasePreviousVertexSource(); |
| this->releasePreviousIndexSource(); |
| } |
| |
| void GrDrawTarget::setClip(const GrClip& clip) { |
| clipWillBeSet(clip); |
| fClip = clip; |
| } |
| |
| const GrClip& GrDrawTarget::getClip() const { |
| return fClip; |
| } |
| |
| void GrDrawTarget::setTexture(int stage, GrTexture* tex) { |
| GrAssert(stage >= 0 && stage < kNumStages); |
| fCurrDrawState.fTextures[stage] = tex; |
| } |
| |
| const GrTexture* GrDrawTarget::getTexture(int stage) const { |
| GrAssert(stage >= 0 && stage < kNumStages); |
| return fCurrDrawState.fTextures[stage]; |
| } |
| |
| GrTexture* GrDrawTarget::getTexture(int stage) { |
| GrAssert(stage >= 0 && stage < kNumStages); |
| return fCurrDrawState.fTextures[stage]; |
| } |
| |
| void GrDrawTarget::setRenderTarget(GrRenderTarget* target) { |
| fCurrDrawState.fRenderTarget = target; |
| } |
| |
| const GrRenderTarget* GrDrawTarget::getRenderTarget() const { |
| return fCurrDrawState.fRenderTarget; |
| } |
| |
| GrRenderTarget* GrDrawTarget::getRenderTarget() { |
| return fCurrDrawState.fRenderTarget; |
| } |
| |
| void GrDrawTarget::setViewMatrix(const GrMatrix& m) { |
| fCurrDrawState.fViewMatrix = m; |
| } |
| |
| void GrDrawTarget::preConcatViewMatrix(const GrMatrix& matrix) { |
| fCurrDrawState.fViewMatrix.preConcat(matrix); |
| } |
| |
| void GrDrawTarget::postConcatViewMatrix(const GrMatrix& matrix) { |
| fCurrDrawState.fViewMatrix.postConcat(matrix); |
| } |
| |
| const GrMatrix& GrDrawTarget::getViewMatrix() const { |
| return fCurrDrawState.fViewMatrix; |
| } |
| |
| bool GrDrawTarget::getViewInverse(GrMatrix* matrix) const { |
| // Mike: Can we cache this somewhere? |
| // Brian: Sure, do we use it often? |
| |
| GrMatrix inverse; |
| if (fCurrDrawState.fViewMatrix.invert(&inverse)) { |
| if (matrix) { |
| *matrix = inverse; |
| } |
| return true; |
| } |
| return false; |
| } |
| |
| void GrDrawTarget::setSamplerState(int stage, const GrSamplerState& state) { |
| GrAssert(stage >= 0 && stage < kNumStages); |
| fCurrDrawState.fSamplerStates[stage] = state; |
| } |
| |
| void GrDrawTarget::enableState(uint32_t bits) { |
| fCurrDrawState.fFlagBits |= bits; |
| } |
| |
| void GrDrawTarget::disableState(uint32_t bits) { |
| fCurrDrawState.fFlagBits &= ~(bits); |
| } |
| |
| void GrDrawTarget::setBlendFunc(GrBlendCoeff srcCoeff, |
| GrBlendCoeff dstCoeff) { |
| fCurrDrawState.fSrcBlend = srcCoeff; |
| fCurrDrawState.fDstBlend = dstCoeff; |
| #if GR_DEBUG |
| switch (dstCoeff) { |
| case kDC_BlendCoeff: |
| case kIDC_BlendCoeff: |
| case kDA_BlendCoeff: |
| case kIDA_BlendCoeff: |
| GrPrintf("Unexpected dst blend coeff. Won't work correctly with" |
| "coverage stages.\n"); |
| break; |
| default: |
| break; |
| } |
| switch (srcCoeff) { |
| case kSC_BlendCoeff: |
| case kISC_BlendCoeff: |
| case kSA_BlendCoeff: |
| case kISA_BlendCoeff: |
| GrPrintf("Unexpected src blend coeff. Won't work correctly with" |
| "coverage stages.\n"); |
| break; |
| default: |
| break; |
| } |
| #endif |
| } |
| |
| void GrDrawTarget::setColor(GrColor c) { |
| fCurrDrawState.fColor = c; |
| } |
| |
| void GrDrawTarget::setColorFilter(GrColor c, SkXfermode::Mode mode) { |
| fCurrDrawState.fColorFilterColor = c; |
| fCurrDrawState.fColorFilterXfermode = mode; |
| } |
| |
| void GrDrawTarget::setAlpha(uint8_t a) { |
| this->setColor((a << 24) | (a << 16) | (a << 8) | a); |
| } |
| |
| void GrDrawTarget::saveCurrentDrawState(SavedDrawState* state) const { |
| state->fState = fCurrDrawState; |
| } |
| |
| void GrDrawTarget::restoreDrawState(const SavedDrawState& state) { |
| fCurrDrawState = state.fState; |
| } |
| |
| void GrDrawTarget::copyDrawState(const GrDrawTarget& srcTarget) { |
| fCurrDrawState = srcTarget.fCurrDrawState; |
| } |
| |
| bool GrDrawTarget::reserveVertexSpace(GrVertexLayout vertexLayout, |
| int vertexCount, |
| void** vertices) { |
| GeometrySrcState& geoSrc = fGeoSrcStateStack.back(); |
| bool acquired = false; |
| if (vertexCount > 0) { |
| GrAssert(NULL != vertices); |
| this->releasePreviousVertexSource(); |
| geoSrc.fVertexSrc = kNone_GeometrySrcType; |
| |
| acquired = this->onReserveVertexSpace(vertexLayout, |
| vertexCount, |
| vertices); |
| } |
| if (acquired) { |
| geoSrc.fVertexSrc = kReserved_GeometrySrcType; |
| geoSrc.fVertexCount = vertexCount; |
| geoSrc.fVertexLayout = vertexLayout; |
| } else if (NULL != vertices) { |
| *vertices = NULL; |
| } |
| return acquired; |
| } |
| |
| bool GrDrawTarget::reserveIndexSpace(int indexCount, |
| void** indices) { |
| GeometrySrcState& geoSrc = fGeoSrcStateStack.back(); |
| bool acquired = false; |
| if (indexCount > 0) { |
| GrAssert(NULL != indices); |
| this->releasePreviousIndexSource(); |
| geoSrc.fIndexSrc = kNone_GeometrySrcType; |
| |
| acquired = this->onReserveIndexSpace(indexCount, indices); |
| } |
| if (acquired) { |
| geoSrc.fIndexSrc = kReserved_GeometrySrcType; |
| geoSrc.fIndexCount = indexCount; |
| } else if (NULL != indices) { |
| *indices = NULL; |
| } |
| return acquired; |
| |
| } |
| |
| bool GrDrawTarget::geometryHints(GrVertexLayout vertexLayout, |
| int32_t* vertexCount, |
| int32_t* indexCount) const { |
| if (NULL != vertexCount) { |
| *vertexCount = -1; |
| } |
| if (NULL != indexCount) { |
| *indexCount = -1; |
| } |
| return false; |
| } |
| |
| void GrDrawTarget::releasePreviousVertexSource() { |
| GeometrySrcState& geoSrc = fGeoSrcStateStack.back(); |
| switch (geoSrc.fVertexSrc) { |
| case kNone_GeometrySrcType: |
| break; |
| case kArray_GeometrySrcType: |
| this->releaseVertexArray(); |
| break; |
| case kReserved_GeometrySrcType: |
| this->releaseReservedVertexSpace(); |
| break; |
| case kBuffer_GeometrySrcType: |
| geoSrc.fVertexBuffer->unref(); |
| #if GR_DEBUG |
| geoSrc.fVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER; |
| #endif |
| break; |
| default: |
| GrCrash("Unknown Vertex Source Type."); |
| break; |
| } |
| } |
| |
| void GrDrawTarget::releasePreviousIndexSource() { |
| GeometrySrcState& geoSrc = fGeoSrcStateStack.back(); |
| switch (geoSrc.fIndexSrc) { |
| case kNone_GeometrySrcType: // these two don't require |
| break; |
| case kArray_GeometrySrcType: |
| this->releaseIndexArray(); |
| break; |
| case kReserved_GeometrySrcType: |
| this->releaseReservedIndexSpace(); |
| break; |
| case kBuffer_GeometrySrcType: |
| geoSrc.fIndexBuffer->unref(); |
| #if GR_DEBUG |
| geoSrc.fIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER; |
| #endif |
| break; |
| default: |
| GrCrash("Unknown Index Source Type."); |
| break; |
| } |
| } |
| |
| void GrDrawTarget::setVertexSourceToArray(GrVertexLayout vertexLayout, |
| const void* vertexArray, |
| int vertexCount) { |
| this->releasePreviousVertexSource(); |
| GeometrySrcState& geoSrc = fGeoSrcStateStack.back(); |
| geoSrc.fVertexSrc = kArray_GeometrySrcType; |
| geoSrc.fVertexLayout = vertexLayout; |
| geoSrc.fVertexCount = vertexCount; |
| this->onSetVertexSourceToArray(vertexArray, vertexCount); |
| } |
| |
| void GrDrawTarget::setIndexSourceToArray(const void* indexArray, |
| int indexCount) { |
| this->releasePreviousIndexSource(); |
| GeometrySrcState& geoSrc = fGeoSrcStateStack.back(); |
| geoSrc.fIndexSrc = kArray_GeometrySrcType; |
| geoSrc.fIndexCount = indexCount; |
| this->onSetIndexSourceToArray(indexArray, indexCount); |
| } |
| |
| void GrDrawTarget::setVertexSourceToBuffer(GrVertexLayout vertexLayout, |
| const GrVertexBuffer* buffer) { |
| this->releasePreviousVertexSource(); |
| GeometrySrcState& geoSrc = fGeoSrcStateStack.back(); |
| geoSrc.fVertexSrc = kBuffer_GeometrySrcType; |
| geoSrc.fVertexBuffer = buffer; |
| buffer->ref(); |
| geoSrc.fVertexLayout = vertexLayout; |
| } |
| |
| void GrDrawTarget::setIndexSourceToBuffer(const GrIndexBuffer* buffer) { |
| this->releasePreviousIndexSource(); |
| GeometrySrcState& geoSrc = fGeoSrcStateStack.back(); |
| geoSrc.fIndexSrc = kBuffer_GeometrySrcType; |
| geoSrc.fIndexBuffer = buffer; |
| buffer->ref(); |
| } |
| |
| void GrDrawTarget::resetVertexSource() { |
| this->releasePreviousVertexSource(); |
| GeometrySrcState& geoSrc = fGeoSrcStateStack.back(); |
| geoSrc.fVertexSrc = kNone_GeometrySrcType; |
| } |
| |
| void GrDrawTarget::resetIndexSource() { |
| this->releasePreviousIndexSource(); |
| GeometrySrcState& geoSrc = fGeoSrcStateStack.back(); |
| geoSrc.fIndexSrc = kNone_GeometrySrcType; |
| } |
| |
| void GrDrawTarget::pushGeometrySource() { |
| this->geometrySourceWillPush(); |
| GeometrySrcState& newState = fGeoSrcStateStack.push_back(); |
| newState.fIndexSrc = kNone_GeometrySrcType; |
| newState.fVertexSrc = kNone_GeometrySrcType; |
| #if GR_DEBUG |
| newState.fVertexCount = ~0; |
| newState.fVertexBuffer = (GrVertexBuffer*)~0; |
| newState.fIndexCount = ~0; |
| newState.fIndexBuffer = (GrIndexBuffer*)~0; |
| #endif |
| } |
| |
| void GrDrawTarget::popGeometrySource() { |
| const GeometrySrcState& geoSrc = this->getGeomSrc(); |
| // if popping last element then pops are unbalanced with pushes |
| GrAssert(fGeoSrcStateStack.count() > 1); |
| |
| this->geometrySourceWillPop(fGeoSrcStateStack.fromBack(1)); |
| this->releasePreviousVertexSource(); |
| this->releasePreviousIndexSource(); |
| fGeoSrcStateStack.pop_back(); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| |
| void GrDrawTarget::drawIndexed(GrPrimitiveType type, int startVertex, |
| int startIndex, int vertexCount, |
| int indexCount) { |
| #if GR_DEBUG |
| GeometrySrcState& geoSrc = fGeoSrcStateStack.back(); |
| int maxVertex = startVertex + vertexCount; |
| int maxValidVertex; |
| switch (geoSrc.fVertexSrc) { |
| case kNone_GeometrySrcType: |
| GrCrash("Attempting to draw indexed geom without vertex src."); |
| case kReserved_GeometrySrcType: // fallthrough |
| case kArray_GeometrySrcType: |
| maxValidVertex = geoSrc.fVertexCount; |
| break; |
| case kBuffer_GeometrySrcType: |
| maxValidVertex = geoSrc.fVertexBuffer->sizeInBytes() / |
| VertexSize(geoSrc.fVertexLayout); |
| break; |
| } |
| if (maxVertex > maxValidVertex) { |
| GrCrash("Indexed drawing outside valid vertex range."); |
| } |
| int maxIndex = startIndex + indexCount; |
| int maxValidIndex; |
| switch (geoSrc.fIndexSrc) { |
| case kNone_GeometrySrcType: |
| GrCrash("Attempting to draw indexed geom without index src."); |
| case kReserved_GeometrySrcType: // fallthrough |
| case kArray_GeometrySrcType: |
| maxValidIndex = geoSrc.fIndexCount; |
| break; |
| case kBuffer_GeometrySrcType: |
| maxValidIndex = geoSrc.fIndexBuffer->sizeInBytes() / sizeof(uint16_t); |
| break; |
| } |
| if (maxIndex > maxValidIndex) { |
| GrCrash("Indexed drawing outside valid index range."); |
| } |
| #endif |
| if (indexCount > 0) { |
| this->onDrawIndexed(type, startVertex, startIndex, |
| vertexCount, indexCount); |
| } |
| } |
| |
| |
| void GrDrawTarget::drawNonIndexed(GrPrimitiveType type, |
| int startVertex, |
| int vertexCount) { |
| #if GR_DEBUG |
| GeometrySrcState& geoSrc = fGeoSrcStateStack.back(); |
| int maxVertex = startVertex + vertexCount; |
| int maxValidVertex; |
| switch (geoSrc.fVertexSrc) { |
| case kNone_GeometrySrcType: |
| GrCrash("Attempting to draw non-indexed geom without vertex src."); |
| case kReserved_GeometrySrcType: // fallthrough |
| case kArray_GeometrySrcType: |
| maxValidVertex = geoSrc.fVertexCount; |
| break; |
| case kBuffer_GeometrySrcType: |
| maxValidVertex = geoSrc.fVertexBuffer->sizeInBytes() / |
| VertexSize(geoSrc.fVertexLayout); |
| break; |
| } |
| if (maxVertex > maxValidVertex) { |
| GrCrash("Non-indexed drawing outside valid vertex range."); |
| } |
| #endif |
| if (vertexCount > 0) { |
| this->onDrawNonIndexed(type, startVertex, vertexCount); |
| } |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| |
| // Some blend modes allow folding a partial coverage value into the color's |
| // alpha channel, while others will blend incorrectly. |
| bool GrDrawTarget::canTweakAlphaForCoverage() const { |
| /** |
| * The fractional coverage is f |
| * The src and dst coeffs are Cs and Cd |
| * The dst and src colors are S and D |
| * We want the blend to compute: f*Cs*S + (f*Cd + (1-f))D |
| * By tweaking the source color's alpha we're replacing S with S'=fS. It's |
| * obvious that that first term will always be ok. The second term can be |
| * rearranged as [1-(1-Cd)f]D. By substituing in the various possbilities |
| * for Cd we find that only 1, ISA, and ISC produce the correct depth |
| * coeffecient in terms of S' and D. |
| */ |
| return kOne_BlendCoeff == fCurrDrawState.fDstBlend|| |
| kISA_BlendCoeff == fCurrDrawState.fDstBlend || |
| kISC_BlendCoeff == fCurrDrawState.fDstBlend; |
| } |
| |
| |
| bool GrDrawTarget::srcAlphaWillBeOne() const { |
| const GrVertexLayout& layout = this->getGeomSrc().fVertexLayout; |
| |
| // Check if per-vertex or constant color may have partial alpha |
| if ((layout & kColor_VertexLayoutBit) || |
| 0xff != GrColorUnpackA(fCurrDrawState.fColor)) { |
| return false; |
| } |
| // Check if color filter could introduce an alpha |
| // (TODO: Consider being more aggressive with regards to detecting 0xff |
| // final alpha from color filter). |
| if (SkXfermode::kDst_Mode != fCurrDrawState.fColorFilterXfermode) { |
| return false; |
| } |
| // Check if a color stage could create a partial alpha |
| for (int s = 0; s < fCurrDrawState.fFirstCoverageStage; ++s) { |
| if (StageWillBeUsed(s, layout, fCurrDrawState)) { |
| GrAssert(NULL != fCurrDrawState.fTextures[s]); |
| GrPixelConfig config = fCurrDrawState.fTextures[s]->config(); |
| if (!GrPixelConfigIsOpaque(config)) { |
| return false; |
| } |
| } |
| } |
| return true; |
| } |
| |
| GrDrawTarget::BlendOptFlags |
| GrDrawTarget::getBlendOpts(bool forceCoverage, |
| GrBlendCoeff* srcCoeff, |
| GrBlendCoeff* dstCoeff) const { |
| |
| const GrVertexLayout& layout = this->getGeomSrc().fVertexLayout; |
| |
| GrBlendCoeff bogusSrcCoeff, bogusDstCoeff; |
| if (NULL == srcCoeff) { |
| srcCoeff = &bogusSrcCoeff; |
| } |
| *srcCoeff = fCurrDrawState.fSrcBlend; |
| |
| if (NULL == dstCoeff) { |
| dstCoeff = &bogusDstCoeff; |
| } |
| *dstCoeff = fCurrDrawState.fDstBlend; |
| |
| // We don't ever expect source coeffecients to reference the source |
| GrAssert(kSA_BlendCoeff != *srcCoeff && |
| kISA_BlendCoeff != *srcCoeff && |
| kSC_BlendCoeff != *srcCoeff && |
| kISC_BlendCoeff != *srcCoeff); |
| // same for dst |
| GrAssert(kDA_BlendCoeff != *dstCoeff && |
| kIDA_BlendCoeff != *dstCoeff && |
| kDC_BlendCoeff != *dstCoeff && |
| kIDC_BlendCoeff != *dstCoeff); |
| |
| if (SkToBool(kNoColorWrites_StateBit & fCurrDrawState.fFlagBits)) { |
| *srcCoeff = kZero_BlendCoeff; |
| *dstCoeff = kOne_BlendCoeff; |
| } |
| |
| bool srcAIsOne = this->srcAlphaWillBeOne(); |
| bool dstCoeffIsOne = kOne_BlendCoeff == *dstCoeff || |
| (kSA_BlendCoeff == *dstCoeff && srcAIsOne); |
| bool dstCoeffIsZero = kZero_BlendCoeff == *dstCoeff || |
| (kISA_BlendCoeff == *dstCoeff && srcAIsOne); |
| |
| |
| // When coeffs are (0,1) there is no reason to draw at all, unless |
| // stenciling is enabled. Having color writes disabled is effectively |
| // (0,1). |
| if ((kZero_BlendCoeff == *srcCoeff && dstCoeffIsOne)) { |
| if (fCurrDrawState.fStencilSettings.doesWrite()) { |
| if (fCaps.fShaderSupport) { |
| return kDisableBlend_BlendOptFlag | |
| kEmitTransBlack_BlendOptFlag; |
| } else { |
| return kDisableBlend_BlendOptFlag; |
| } |
| } else { |
| return kSkipDraw_BlendOptFlag; |
| } |
| } |
| |
| // check for coverage due to edge aa or coverage texture stage |
| bool hasCoverage = forceCoverage || |
| fCurrDrawState.fEdgeAANumEdges > 0 || |
| (layout & kCoverage_VertexLayoutBit) || |
| (layout & kEdge_VertexLayoutBit); |
| for (int s = fCurrDrawState.fFirstCoverageStage; |
| !hasCoverage && s < kNumStages; |
| ++s) { |
| if (StageWillBeUsed(s, layout, fCurrDrawState)) { |
| hasCoverage = true; |
| } |
| } |
| |
| // if we don't have coverage we can check whether the dst |
| // has to read at all. If not, we'll disable blending. |
| if (!hasCoverage) { |
| if (dstCoeffIsZero) { |
| if (kOne_BlendCoeff == *srcCoeff) { |
| // if there is no coverage and coeffs are (1,0) then we |
| // won't need to read the dst at all, it gets replaced by src |
| return kDisableBlend_BlendOptFlag; |
| } else if (kZero_BlendCoeff == *srcCoeff && |
| fCaps.fShaderSupport) { |
| // if the op is "clear" then we don't need to emit a color |
| // or blend, just write transparent black into the dst. |
| *srcCoeff = kOne_BlendCoeff; |
| *dstCoeff = kZero_BlendCoeff; |
| return kDisableBlend_BlendOptFlag | |
| kEmitTransBlack_BlendOptFlag; |
| } |
| } |
| } else { |
| // check whether coverage can be safely rolled into alpha |
| // of if we can skip color computation and just emit coverage |
| if (this->canTweakAlphaForCoverage()) { |
| return kCoverageAsAlpha_BlendOptFlag; |
| } |
| // We haven't implemented support for these optimizations in the |
| // fixed pipe (which is on its deathbed) |
| if (fCaps.fShaderSupport) { |
| if (dstCoeffIsZero) { |
| if (kZero_BlendCoeff == *srcCoeff) { |
| // the source color is not included in the blend |
| // the dst coeff is effectively zero so blend works out to: |
| // (c)(0)D + (1-c)D = (1-c)D. |
| *dstCoeff = kISA_BlendCoeff; |
| return kEmitCoverage_BlendOptFlag; |
| } else if (srcAIsOne) { |
| // the dst coeff is effectively zero so blend works out to: |
| // cS + (c)(0)D + (1-c)D = cS + (1-c)D. |
| // If Sa is 1 then we can replace Sa with c |
| // and set dst coeff to 1-Sa. |
| *dstCoeff = kISA_BlendCoeff; |
| return kCoverageAsAlpha_BlendOptFlag; |
| } |
| } else if (dstCoeffIsOne) { |
| // the dst coeff is effectively one so blend works out to: |
| // cS + (c)(1)D + (1-c)D = cS + D. |
| *dstCoeff = kOne_BlendCoeff; |
| return kCoverageAsAlpha_BlendOptFlag; |
| } |
| } |
| } |
| return kNone_BlendOpt; |
| } |
| |
| bool GrDrawTarget::willUseHWAALines() const { |
| // there is a conflict between using smooth lines and our use of |
| // premultiplied alpha. Smooth lines tweak the incoming alpha value |
| // but not in a premul-alpha way. So we only use them when our alpha |
| // is 0xff and tweaking the color for partial coverage is OK |
| if (!fCaps.fHWAALineSupport || |
| !(kAntialias_StateBit & fCurrDrawState.fFlagBits)) { |
| return false; |
| } |
| BlendOptFlags opts = this->getBlendOpts(); |
| return (kDisableBlend_BlendOptFlag & opts) && |
| (kCoverageAsAlpha_BlendOptFlag & opts); |
| } |
| |
| bool GrDrawTarget::canApplyCoverage() const { |
| // we can correctly apply coverage if a) we have dual source blending |
| // or b) one of our blend optimizations applies. |
| return this->getCaps().fDualSourceBlendingSupport || |
| kNone_BlendOpt != this->getBlendOpts(true); |
| } |
| |
| bool GrDrawTarget::drawWillReadDst() const { |
| return SkToBool((kDisableBlend_BlendOptFlag | kSkipDraw_BlendOptFlag) & |
| this->getBlendOpts()); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| void GrDrawTarget::setEdgeAAData(const Edge* edges, int numEdges) { |
| GrAssert(numEdges <= kMaxEdges); |
| memcpy(fCurrDrawState.fEdgeAAEdges, edges, numEdges * sizeof(Edge)); |
| fCurrDrawState.fEdgeAANumEdges = numEdges; |
| } |
| |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| |
| void GrDrawTarget::drawRect(const GrRect& rect, |
| const GrMatrix* matrix, |
| StageBitfield stageEnableBitfield, |
| const GrRect* srcRects[], |
| const GrMatrix* srcMatrices[]) { |
| GrVertexLayout layout = GetRectVertexLayout(stageEnableBitfield, srcRects); |
| |
| AutoReleaseGeometry geo(this, layout, 4, 0); |
| if (!geo.succeeded()) { |
| GrPrintf("Failed to get space for vertices!\n"); |
| return; |
| } |
| |
| SetRectVertices(rect, matrix, srcRects, |
| srcMatrices, layout, geo.vertices()); |
| |
| drawNonIndexed(kTriangleFan_PrimitiveType, 0, 4); |
| } |
| |
| GrVertexLayout GrDrawTarget::GetRectVertexLayout(StageBitfield stageEnableBitfield, |
| const GrRect* srcRects[]) { |
| GrVertexLayout layout = 0; |
| |
| for (int i = 0; i < kNumStages; ++i) { |
| int numTC = 0; |
| if (stageEnableBitfield & (1 << i)) { |
| if (NULL != srcRects && NULL != srcRects[i]) { |
| layout |= StageTexCoordVertexLayoutBit(i, numTC); |
| ++numTC; |
| } else { |
| layout |= StagePosAsTexCoordVertexLayoutBit(i); |
| } |
| } |
| } |
| return layout; |
| } |
| |
| void GrDrawTarget::clipWillBeSet(const GrClip& clip) { |
| } |
| |
| void GrDrawTarget::SetRectVertices(const GrRect& rect, |
| const GrMatrix* matrix, |
| const GrRect* srcRects[], |
| const GrMatrix* srcMatrices[], |
| GrVertexLayout layout, |
| void* vertices) { |
| #if GR_DEBUG |
| // check that the layout and srcRects agree |
| for (int i = 0; i < kNumStages; ++i) { |
| if (VertexTexCoordsForStage(i, layout) >= 0) { |
| GR_DEBUGASSERT(NULL != srcRects && NULL != srcRects[i]); |
| } else { |
| GR_DEBUGASSERT(NULL == srcRects || NULL == srcRects[i]); |
| } |
| } |
| #endif |
| |
| int stageOffsets[kNumStages]; |
| int vsize = VertexSizeAndOffsetsByStage(layout, stageOffsets, |
| NULL, NULL, NULL); |
| |
| GrTCast<GrPoint*>(vertices)->setRectFan(rect.fLeft, rect.fTop, |
| rect.fRight, rect.fBottom, |
| vsize); |
| if (NULL != matrix) { |
| matrix->mapPointsWithStride(GrTCast<GrPoint*>(vertices), vsize, 4); |
| } |
| |
| for (int i = 0; i < kNumStages; ++i) { |
| if (stageOffsets[i] > 0) { |
| GrPoint* coords = GrTCast<GrPoint*>(GrTCast<intptr_t>(vertices) + |
| stageOffsets[i]); |
| coords->setRectFan(srcRects[i]->fLeft, srcRects[i]->fTop, |
| srcRects[i]->fRight, srcRects[i]->fBottom, |
| vsize); |
| if (NULL != srcMatrices && NULL != srcMatrices[i]) { |
| srcMatrices[i]->mapPointsWithStride(coords, vsize, 4); |
| } |
| } |
| } |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| |
| GrDrawTarget::AutoStateRestore::AutoStateRestore() { |
| fDrawTarget = NULL; |
| } |
| |
| GrDrawTarget::AutoStateRestore::AutoStateRestore(GrDrawTarget* target) { |
| fDrawTarget = target; |
| if (NULL != fDrawTarget) { |
| fDrawTarget->saveCurrentDrawState(&fDrawState); |
| } |
| } |
| |
| GrDrawTarget::AutoStateRestore::~AutoStateRestore() { |
| if (NULL != fDrawTarget) { |
| fDrawTarget->restoreDrawState(fDrawState); |
| } |
| } |
| |
| void GrDrawTarget::AutoStateRestore::set(GrDrawTarget* target) { |
| if (target != fDrawTarget) { |
| if (NULL != fDrawTarget) { |
| fDrawTarget->restoreDrawState(fDrawState); |
| } |
| if (NULL != target) { |
| target->saveCurrentDrawState(&fDrawState); |
| } |
| fDrawTarget = target; |
| } |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| |
| GrDrawTarget::AutoDeviceCoordDraw::AutoDeviceCoordDraw(GrDrawTarget* target, |
| int stageMask) { |
| GrAssert(NULL != target); |
| |
| fDrawTarget = target; |
| fViewMatrix = target->getViewMatrix(); |
| fStageMask = stageMask; |
| if (fStageMask) { |
| GrMatrix invVM; |
| if (fViewMatrix.invert(&invVM)) { |
| for (int s = 0; s < kNumStages; ++s) { |
| if (fStageMask & (1 << s)) { |
| fSamplerMatrices[s] = target->getSamplerMatrix(s); |
| } |
| } |
| target->preConcatSamplerMatrices(fStageMask, invVM); |
| } else { |
| // sad trombone sound |
| fStageMask = 0; |
| } |
| } |
| target->setViewMatrix(GrMatrix::I()); |
| } |
| |
| GrDrawTarget::AutoDeviceCoordDraw::~AutoDeviceCoordDraw() { |
| fDrawTarget->setViewMatrix(fViewMatrix); |
| for (int s = 0; s < kNumStages; ++s) { |
| if (fStageMask & (1 << s)) { |
| fDrawTarget->setSamplerMatrix(s, fSamplerMatrices[s]); |
| } |
| } |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| |
| GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry( |
| GrDrawTarget* target, |
| GrVertexLayout vertexLayout, |
| int vertexCount, |
| int indexCount) { |
| fTarget = NULL; |
| this->set(target, vertexLayout, vertexCount, indexCount); |
| } |
| |
| GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry() { |
| fTarget = NULL; |
| } |
| |
| GrDrawTarget::AutoReleaseGeometry::~AutoReleaseGeometry() { |
| this->reset(); |
| } |
| |
| bool GrDrawTarget::AutoReleaseGeometry::set(GrDrawTarget* target, |
| GrVertexLayout vertexLayout, |
| int vertexCount, |
| int indexCount) { |
| this->reset(); |
| fTarget = target; |
| bool success = true; |
| if (NULL != fTarget) { |
| fTarget = target; |
| if (vertexCount > 0) { |
| success = target->reserveVertexSpace(vertexLayout, |
| vertexCount, |
| &fVertices); |
| if (!success) { |
| this->reset(); |
| } |
| } |
| if (success && indexCount > 0) { |
| success = target->reserveIndexSpace(indexCount, &fIndices); |
| if (!success) { |
| this->reset(); |
| } |
| } |
| } |
| GrAssert(success == (NULL != fTarget)); |
| return success; |
| } |
| |
| void GrDrawTarget::AutoReleaseGeometry::reset() { |
| if (NULL != fTarget) { |
| if (NULL != fVertices) { |
| fTarget->resetVertexSource(); |
| } |
| if (NULL != fIndices) { |
| fTarget->resetIndexSource(); |
| } |
| fTarget = NULL; |
| } |
| fVertices = NULL; |
| fIndices = NULL; |
| } |
| |
| void GrDrawTarget::Caps::print() const { |
| static const char* gNY[] = {"NO", "YES"}; |
| GrPrintf("8 Bit Palette Support : %s\n", gNY[f8BitPaletteSupport]); |
| GrPrintf("NPOT Texture Support : %s\n", gNY[fNPOTTextureSupport]); |
| GrPrintf("NPOT Texture Tile Support : %s\n", gNY[fNPOTTextureTileSupport]); |
| GrPrintf("NPOT Render Target Support : %s\n", gNY[fNPOTRenderTargetSupport]); |
| GrPrintf("Two Sided Stencil Support : %s\n", gNY[fTwoSidedStencilSupport]); |
| GrPrintf("Stencil Wrap Ops Support : %s\n", gNY[fStencilWrapOpsSupport]); |
| GrPrintf("HW AA Lines Support : %s\n", gNY[fHWAALineSupport]); |
| GrPrintf("Shader Support : %s\n", gNY[fShaderSupport]); |
| GrPrintf("Shader Derivative Support : %s\n", gNY[fShaderDerivativeSupport]); |
| GrPrintf("Geometry Shader Support : %s\n", gNY[fGeometryShaderSupport]); |
| GrPrintf("FSAA Support : %s\n", gNY[fFSAASupport]); |
| GrPrintf("Dual Source Blending Support: %s\n", gNY[fDualSourceBlendingSupport]); |
| GrPrintf("Buffer Lock Support : %s\n", gNY[fBufferLockSupport]); |
| GrPrintf("Min Render Target Width : %d\n", fMinRenderTargetWidth); |
| GrPrintf("Min Render Target Height : %d\n", fMinRenderTargetHeight); |
| GrPrintf("Max Texture Size : %d\n", fMaxTextureSize); |
| GrPrintf("Max Render Target Size : %d\n", fMaxRenderTargetSize); |
| } |
| |