// This method fills int the four vertices for drawing 'rect'. // matrix - is applied to each vertex // srcRects - provide the uvs for each vertex // srcMatrices - are applied to the corresponding 'srcRect' // color - vertex color (replicated in each vertex) // layout - specifies which uvs and/or color are present // vertices - storage for the resulting vertices // Note: the color parameter will only be used when kColor_VertexLayoutBit // is present in 'layout' void GrDrawTarget::SetRectVertices(const GrRect& rect, const SkMatrix* matrix, const GrRect* srcRects[], const SkMatrix* srcMatrices[], GrColor color, GrVertexLayout layout, void* vertices) { #if GR_DEBUG // check that the layout and srcRects agree for (int i = 0; i < GrDrawState::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[GrDrawState::kNumStages], colorOffset; int vsize = VertexSizeAndOffsetsByStage(layout, stageOffsets, &colorOffset, 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 < GrDrawState::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); } } } if (layout & kColor_VertexLayoutBit) { GrColor* vertCol = GrTCast<GrColor*>(GrTCast<intptr_t>(vertices) + colorOffset); for (int i = 0; i < 4; ++i) { *vertCol = color; vertCol = (GrColor*) ((intptr_t) vertCol + vsize); } } }
void GrDrawTarget::onDrawRect(const SkRect& rect, const SkMatrix* matrix, const SkRect* localRect, const SkMatrix* localMatrix) { GrDrawState::AutoViewMatrixRestore avmr; if (NULL != matrix) { avmr.set(this->drawState(), *matrix); } set_vertex_attributes(this->drawState(), NULL != localRect); AutoReleaseGeometry geo(this, 4, 0); if (!geo.succeeded()) { GrPrintf("Failed to get space for vertices!\n"); return; } size_t vsize = this->drawState()->getVertexSize(); geo.positions()->setRectFan(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, vsize); if (NULL != localRect) { GrPoint* coords = GrTCast<GrPoint*>(GrTCast<intptr_t>(geo.vertices()) + sizeof(GrPoint)); coords->setRectFan(localRect->fLeft, localRect->fTop, localRect->fRight, localRect->fBottom, vsize); if (NULL != localMatrix) { localMatrix->mapPointsWithStride(coords, vsize, 4); } } SkTLazy<SkRect> bounds; if (this->getDrawState().willEffectReadDstColor()) { bounds.init(); this->getDrawState().getViewMatrix().mapRect(bounds.get(), rect); } this->drawNonIndexed(kTriangleFan_GrPrimitiveType, 0, 4, bounds.getMaybeNull()); }
void GrInOrderDrawBuffer::onDrawRect(const GrRect& rect, const SkMatrix* matrix, const GrRect* localRect, const SkMatrix* localMatrix) { GrDrawState::AutoColorRestore acr; GrDrawState* drawState = this->drawState(); GrColor color = drawState->getColor(); int colorOffset, localOffset; set_vertex_attributes(drawState, this->caps()->dualSourceBlendingSupport() || drawState->hasSolidCoverage(), NULL != localRect, &colorOffset, &localOffset); if (colorOffset >= 0) { // We set the draw state's color to white here. This is done so that any batching performed // in our subclass's onDraw() won't get a false from GrDrawState::op== due to a color // mismatch. TODO: Once vertex layout is owned by GrDrawState it should skip comparing the // constant color in its op== when the kColor layout bit is set and then we can remove // this. acr.set(drawState, 0xFFFFFFFF); } AutoReleaseGeometry geo(this, 4, 0); if (!geo.succeeded()) { GrPrintf("Failed to get space for vertices!\n"); return; } // Go to device coords to allow batching across matrix changes SkMatrix combinedMatrix; if (NULL != matrix) { combinedMatrix = *matrix; } else { combinedMatrix.reset(); } combinedMatrix.postConcat(drawState->getViewMatrix()); // When the caller has provided an explicit source rect for a stage then we don't want to // modify that stage's matrix. Otherwise if the effect is generating its source rect from // the vertex positions then we have to account for the view matrix change. GrDrawState::AutoViewMatrixRestore avmr; if (!avmr.setIdentity(drawState)) { return; } size_t vsize = drawState->getVertexSize(); geo.positions()->setRectFan(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, vsize); combinedMatrix.mapPointsWithStride(geo.positions(), vsize, 4); SkRect devBounds; // since we already computed the dev verts, set the bounds hint. This will help us avoid // unnecessary clipping in our onDraw(). get_vertex_bounds(geo.vertices(), vsize, 4, &devBounds); if (localOffset >= 0) { GrPoint* coords = GrTCast<GrPoint*>(GrTCast<intptr_t>(geo.vertices()) + localOffset); coords->setRectFan(localRect->fLeft, localRect->fTop, localRect->fRight, localRect->fBottom, vsize); if (NULL != localMatrix) { localMatrix->mapPointsWithStride(coords, vsize, 4); } } if (colorOffset >= 0) { GrColor* vertColor = GrTCast<GrColor*>(GrTCast<intptr_t>(geo.vertices()) + colorOffset); for (int i = 0; i < 4; ++i) { *vertColor = color; vertColor = (GrColor*) ((intptr_t) vertColor + vsize); } } this->setIndexSourceToBuffer(this->getContext()->getQuadIndexBuffer()); this->drawIndexedInstances(kTriangles_GrPrimitiveType, 1, 4, 6, &devBounds); // to ensure that stashing the drawState ptr is valid GrAssert(this->drawState() == drawState); }
void GrInOrderDrawBuffer::drawRect(const GrRect& rect, const SkMatrix* matrix, const GrRect* srcRects[], const SkMatrix* srcMatrices[]) { GrVertexLayout layout = 0; GrDrawState::AutoColorRestore acr; GrColor color = this->drawState()->getColor(); // Using per-vertex colors allows batching across colors. (A lot of rects in a row differing // only in color is a common occurrence in tables). However, having per-vertex colors disables // blending optimizations because we don't know if the color will be solid or not. These // optimizations help determine whether coverage and color can be blended correctly when // dual-source blending isn't available. This comes into play when there is coverage. If colors // were a stage it could take a hint that every vertex's color will be opaque. if (this->getCaps().dualSourceBlendingSupport() || this->getDrawState().hasSolidCoverage(this->getGeomSrc().fVertexLayout)) { layout |= GrDrawState::kColor_VertexLayoutBit;; // We set the draw state's color to white here. This is done so that any batching performed // in our subclass's onDraw() won't get a false from GrDrawState::op== due to a color // mismatch. TODO: Once vertex layout is owned by GrDrawState it should skip comparing the // constant color in its op== when the kColor layout bit is set and then we can remove this. acr.set(this->drawState(), 0xFFFFFFFF); } uint32_t explicitCoordMask = 0; if (NULL != srcRects) { for (int s = 0; s < GrDrawState::kNumStages; ++s) { int numTC = 0; if (NULL != srcRects[s]) { layout |= GrDrawState::StageTexCoordVertexLayoutBit(s, numTC); ++numTC; explicitCoordMask |= (1 << s); } } } AutoReleaseGeometry geo(this, layout, 4, 0); if (!geo.succeeded()) { GrPrintf("Failed to get space for vertices!\n"); return; } // Go to device coords to allow batching across matrix changes SkMatrix combinedMatrix; if (NULL != matrix) { combinedMatrix = *matrix; } else { combinedMatrix.reset(); } combinedMatrix.postConcat(this->drawState()->getViewMatrix()); // When the caller has provided an explicit source rects for a stage then we don't want to // modify that stage's matrix. Otherwise if the effect is generating its source rect from // the vertex positions then we have to account for the view matrix change. GrDrawState::AutoDeviceCoordDraw adcd(this->drawState(), explicitCoordMask); if (!adcd.succeeded()) { return; } int stageOffsets[GrDrawState::kNumStages], colorOffset; int vsize = GrDrawState::VertexSizeAndOffsetsByStage(layout, stageOffsets, &colorOffset, NULL, NULL); geo.positions()->setRectFan(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, vsize); combinedMatrix.mapPointsWithStride(geo.positions(), vsize, 4); SkRect devBounds; // since we already computed the dev verts, set the bounds hint. This will help us avoid // unnecessary clipping in our onDraw(). get_vertex_bounds(geo.vertices(), vsize, 4, &devBounds); for (int i = 0; i < GrDrawState::kNumStages; ++i) { if (explicitCoordMask & (1 << i)) { GrAssert(0 != stageOffsets[i]); GrPoint* coords = GrTCast<GrPoint*>(GrTCast<intptr_t>(geo.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); } } else { GrAssert(0 == stageOffsets[i]); } } if (colorOffset >= 0) { GrColor* vertColor = GrTCast<GrColor*>(GrTCast<intptr_t>(geo.vertices()) + colorOffset); for (int i = 0; i < 4; ++i) { *vertColor = color; vertColor = (GrColor*) ((intptr_t) vertColor + vsize); } } this->setIndexSourceToBuffer(fGpu->getQuadIndexBuffer()); this->drawIndexedInstances(kTriangles_GrPrimitiveType, 1, 4, 6, &devBounds); }