From f6747b0b90b3a270ec7b7bdfdc211cf5c19f28c2 Mon Sep 17 00:00:00 2001 From: "robertphillips@google.com" Date: Tue, 12 Jun 2012 00:32:28 +0000 Subject: Split GrContext's AA Rect drawing methods into helper class http://codereview.appspot.com/6300070/ git-svn-id: http://skia.googlecode.com/svn/trunk@4233 2bbb7eff-a529-9590-31e7-b0007b416f81 --- src/gpu/GrAARectRenderer.cpp | 237 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 237 insertions(+) create mode 100644 src/gpu/GrAARectRenderer.cpp (limited to 'src/gpu/GrAARectRenderer.cpp') diff --git a/src/gpu/GrAARectRenderer.cpp b/src/gpu/GrAARectRenderer.cpp new file mode 100644 index 0000000000..3eca36215a --- /dev/null +++ b/src/gpu/GrAARectRenderer.cpp @@ -0,0 +1,237 @@ +/* + * Copyright 2012 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "GrAARectRenderer.h" +#include "GrRefCnt.h" +#include "GrGpu.h" + +DEFINE_INST_COUNT(GrAARectRenderer) + +namespace { + +static GrVertexLayout aa_rect_layout(const GrDrawTarget* target, + bool useCoverage) { + GrVertexLayout layout = 0; + for (int s = 0; s < GrDrawState::kNumStages; ++s) { + if (NULL != target->getDrawState().getTexture(s)) { + layout |= GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(s); + } + } + if (useCoverage) { + layout |= GrDrawTarget::kCoverage_VertexLayoutBit; + } else { + layout |= GrDrawTarget::kColor_VertexLayoutBit; + } + return layout; +} + +static void setInsetFan(GrPoint* pts, size_t stride, + const GrRect& r, GrScalar dx, GrScalar dy) { + pts->setRectFan(r.fLeft + dx, r.fTop + dy, + r.fRight - dx, r.fBottom - dy, stride); +} + +}; + +void GrAARectRenderer::reset() { + GrSafeSetNull(fAAFillRectIndexBuffer); + GrSafeSetNull(fAAStrokeRectIndexBuffer); +} + +const uint16_t GrAARectRenderer::gFillAARectIdx[] = { + 0, 1, 5, 5, 4, 0, + 1, 2, 6, 6, 5, 1, + 2, 3, 7, 7, 6, 2, + 3, 0, 4, 4, 7, 3, + 4, 5, 6, 6, 7, 4, +}; + +int GrAARectRenderer::aaFillRectIndexCount() { + return GR_ARRAY_COUNT(gFillAARectIdx); +} + +GrIndexBuffer* GrAARectRenderer::aaFillRectIndexBuffer(GrGpu* gpu) { + if (NULL == fAAFillRectIndexBuffer) { + fAAFillRectIndexBuffer = gpu->createIndexBuffer(sizeof(gFillAARectIdx), + false); + if (NULL != fAAFillRectIndexBuffer) { +#if GR_DEBUG + bool updated = +#endif + fAAFillRectIndexBuffer->updateData(gFillAARectIdx, + sizeof(gFillAARectIdx)); + GR_DEBUGASSERT(updated); + } + } + return fAAFillRectIndexBuffer; +} + +const uint16_t GrAARectRenderer::gStrokeAARectIdx[] = { + 0 + 0, 1 + 0, 5 + 0, 5 + 0, 4 + 0, 0 + 0, + 1 + 0, 2 + 0, 6 + 0, 6 + 0, 5 + 0, 1 + 0, + 2 + 0, 3 + 0, 7 + 0, 7 + 0, 6 + 0, 2 + 0, + 3 + 0, 0 + 0, 4 + 0, 4 + 0, 7 + 0, 3 + 0, + + 0 + 4, 1 + 4, 5 + 4, 5 + 4, 4 + 4, 0 + 4, + 1 + 4, 2 + 4, 6 + 4, 6 + 4, 5 + 4, 1 + 4, + 2 + 4, 3 + 4, 7 + 4, 7 + 4, 6 + 4, 2 + 4, + 3 + 4, 0 + 4, 4 + 4, 4 + 4, 7 + 4, 3 + 4, + + 0 + 8, 1 + 8, 5 + 8, 5 + 8, 4 + 8, 0 + 8, + 1 + 8, 2 + 8, 6 + 8, 6 + 8, 5 + 8, 1 + 8, + 2 + 8, 3 + 8, 7 + 8, 7 + 8, 6 + 8, 2 + 8, + 3 + 8, 0 + 8, 4 + 8, 4 + 8, 7 + 8, 3 + 8, +}; + +int GrAARectRenderer::aaStrokeRectIndexCount() { + return GR_ARRAY_COUNT(gStrokeAARectIdx); +} + +GrIndexBuffer* GrAARectRenderer::aaStrokeRectIndexBuffer(GrGpu* gpu) { + if (NULL == fAAStrokeRectIndexBuffer) { + fAAStrokeRectIndexBuffer = + gpu->createIndexBuffer(sizeof(gStrokeAARectIdx), false); + if (NULL != fAAStrokeRectIndexBuffer) { +#if GR_DEBUG + bool updated = +#endif + fAAStrokeRectIndexBuffer->updateData(gStrokeAARectIdx, + sizeof(gStrokeAARectIdx)); + GR_DEBUGASSERT(updated); + } + } + return fAAStrokeRectIndexBuffer; +} + +void GrAARectRenderer::fillAARect(GrGpu* gpu, + GrDrawTarget* target, + const GrRect& devRect, + bool useVertexCoverage) { + GrVertexLayout layout = aa_rect_layout(target, useVertexCoverage); + + size_t vsize = GrDrawTarget::VertexSize(layout); + + GrDrawTarget::AutoReleaseGeometry geo(target, layout, 8, 0); + if (!geo.succeeded()) { + GrPrintf("Failed to get space for vertices!\n"); + return; + } + GrIndexBuffer* indexBuffer = this->aaFillRectIndexBuffer(gpu); + if (NULL == indexBuffer) { + GrPrintf("Failed to create index buffer!\n"); + return; + } + + intptr_t verts = reinterpret_cast(geo.vertices()); + + GrPoint* fan0Pos = reinterpret_cast(verts); + GrPoint* fan1Pos = reinterpret_cast(verts + 4 * vsize); + + setInsetFan(fan0Pos, vsize, devRect, -GR_ScalarHalf, -GR_ScalarHalf); + setInsetFan(fan1Pos, vsize, devRect, GR_ScalarHalf, GR_ScalarHalf); + + verts += sizeof(GrPoint); + for (int i = 0; i < 4; ++i) { + *reinterpret_cast(verts + i * vsize) = 0; + } + + GrColor innerColor; + if (useVertexCoverage) { + innerColor = 0xffffffff; + } else { + innerColor = target->getDrawState().getColor(); + } + + verts += 4 * vsize; + for (int i = 0; i < 4; ++i) { + *reinterpret_cast(verts + i * vsize) = innerColor; + } + + target->setIndexSourceToBuffer(indexBuffer); + + target->drawIndexed(kTriangles_GrPrimitiveType, 0, + 0, 8, this->aaFillRectIndexCount()); +} + +void GrAARectRenderer::strokeAARect(GrGpu* gpu, + GrDrawTarget* target, + const GrRect& devRect, + const GrVec& devStrokeSize, + bool useVertexCoverage) { + const GrScalar& dx = devStrokeSize.fX; + const GrScalar& dy = devStrokeSize.fY; + const GrScalar rx = GrMul(dx, GR_ScalarHalf); + const GrScalar ry = GrMul(dy, GR_ScalarHalf); + + GrScalar spare; + { + GrScalar w = devRect.width() - dx; + GrScalar h = devRect.height() - dy; + spare = GrMin(w, h); + } + + if (spare <= 0) { + GrRect r(devRect); + r.inset(-rx, -ry); + this->fillAARect(gpu, target, r, useVertexCoverage); + return; + } + GrVertexLayout layout = aa_rect_layout(target, useVertexCoverage); + size_t vsize = GrDrawTarget::VertexSize(layout); + + GrDrawTarget::AutoReleaseGeometry geo(target, layout, 16, 0); + if (!geo.succeeded()) { + GrPrintf("Failed to get space for vertices!\n"); + return; + } + GrIndexBuffer* indexBuffer = this->aaStrokeRectIndexBuffer(gpu); + if (NULL == indexBuffer) { + GrPrintf("Failed to create index buffer!\n"); + return; + } + + intptr_t verts = reinterpret_cast(geo.vertices()); + + GrPoint* fan0Pos = reinterpret_cast(verts); + GrPoint* fan1Pos = reinterpret_cast(verts + 4 * vsize); + GrPoint* fan2Pos = reinterpret_cast(verts + 8 * vsize); + GrPoint* fan3Pos = reinterpret_cast(verts + 12 * vsize); + + setInsetFan(fan0Pos, vsize, devRect, + -rx - GR_ScalarHalf, -ry - GR_ScalarHalf); + setInsetFan(fan1Pos, vsize, devRect, + -rx + GR_ScalarHalf, -ry + GR_ScalarHalf); + setInsetFan(fan2Pos, vsize, devRect, + rx - GR_ScalarHalf, ry - GR_ScalarHalf); + setInsetFan(fan3Pos, vsize, devRect, + rx + GR_ScalarHalf, ry + GR_ScalarHalf); + + verts += sizeof(GrPoint); + for (int i = 0; i < 4; ++i) { + *reinterpret_cast(verts + i * vsize) = 0; + } + + GrColor innerColor; + if (useVertexCoverage) { + innerColor = 0xffffffff; + } else { + innerColor = target->getDrawState().getColor(); + } + verts += 4 * vsize; + for (int i = 0; i < 8; ++i) { + *reinterpret_cast(verts + i * vsize) = innerColor; + } + + verts += 8 * vsize; + for (int i = 0; i < 8; ++i) { + *reinterpret_cast(verts + i * vsize) = 0; + } + + target->setIndexSourceToBuffer(indexBuffer); + target->drawIndexed(kTriangles_GrPrimitiveType, + 0, 0, 16, aaStrokeRectIndexCount()); +} -- cgit v1.2.3