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); }
bool GrAndroidPathRenderer::onDrawPath(const SkPath& origPath, const SkStrokeRec& stroke, GrDrawTarget* target, bool antiAlias) { // generate verts using Android algorithm android::uirenderer::VertexBuffer vertices; android::uirenderer::PathRenderer::ConvexPathVertices(origPath, stroke, antiAlias, NULL, &vertices); // set vertex attributes depending on anti-alias GrDrawState* drawState = target->drawState(); if (antiAlias) { // position + coverage GrVertexAttrib attribs[] = { GrVertexAttrib(kVec2f_GrVertexAttribType, 0), GrVertexAttrib(kVec4ub_GrVertexAttribType, sizeof(GrPoint)) }; drawState->setVertexAttribs(attribs, SK_ARRAY_COUNT(attribs)); drawState->setAttribIndex(GrDrawState::kPosition_AttribIndex, 0); drawState->setAttribIndex(GrDrawState::kCoverage_AttribIndex, 1); drawState->setAttribBindings(GrDrawState::kCoverage_AttribBindingsBit); } else { drawState->setDefaultVertexAttribs(); } // allocate our vert buffer int vertCount = vertices.getSize(); GrDrawTarget::AutoReleaseGeometry geo(target, vertCount, 0); if (!geo.succeeded()) { SkDebugf("Failed to get space for vertices!\n"); return false; } // copy android verts to our vertex buffer if (antiAlias) { SkASSERT(sizeof(ColorVertex) == drawState->getVertexSize()); ColorVertex* outVert = reinterpret_cast<ColorVertex*>(geo.vertices()); android::uirenderer::AlphaVertex* inVert = reinterpret_cast<android::uirenderer::AlphaVertex*>(vertices.getBuffer()); for (int i = 0; i < vertCount; ++i) { // copy vertex position outVert->pos.set(inVert->position[0], inVert->position[1]); // copy alpha int coverage = static_cast<int>(inVert->alpha * 0xff); outVert->color = GrColorPackRGBA(coverage, coverage, coverage, coverage); ++outVert; ++inVert; } } else { size_t vsize = drawState->getVertexSize(); size_t copySize = vsize*vertCount; memcpy(geo.vertices(), vertices.getBuffer(), copySize); } // render it target->drawNonIndexed(kTriangleStrip_GrPrimitiveType, 0, vertCount); return true; }