aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar robertphillips@google.com <robertphillips@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-05-01 14:30:24 +0000
committerGravatar robertphillips@google.com <robertphillips@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-05-01 14:30:24 +0000
commited4155d610442b75e906a3489c984394c34b5ff9 (patch)
tree56dcc05226812f2458c2fb6104c07d14ea490346 /src
parenta5f406e9984e09d084cc995895712eb3f8f1c3cf (diff)
Moved SW path renderer from GrContext.cpp to GrSoftwarePathRenderer.cpp
Diffstat (limited to 'src')
-rw-r--r--src/gpu/GrContext.cpp231
-rw-r--r--src/gpu/GrSoftwarePathRenderer.cpp235
2 files changed, 230 insertions, 236 deletions
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index ac812cbd49..a434237bc8 100644
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -1268,173 +1268,8 @@ void GrContext::drawVertices(const GrPaint& paint,
}
///////////////////////////////////////////////////////////////////////////////
-#include "SkDraw.h"
-#include "SkRasterClip.h"
-
namespace {
-SkPath::FillType gr_fill_to_sk_fill(GrPathFill fill) {
- switch (fill) {
- case kWinding_PathFill:
- return SkPath::kWinding_FillType;
- case kEvenOdd_PathFill:
- return SkPath::kEvenOdd_FillType;
- case kInverseWinding_PathFill:
- return SkPath::kInverseWinding_FillType;
- case kInverseEvenOdd_PathFill:
- return SkPath::kInverseEvenOdd_FillType;
- default:
- GrCrash("Unexpected fill.");
- return SkPath::kWinding_FillType;
- }
-}
-
-// gets device coord bounds of path (not considering the fill) and clip. The
-// path bounds will be a subset of the clip bounds. returns false if
-// path bounds would be empty.
-bool get_path_and_clip_bounds(const GrDrawTarget* target,
- const SkPath& path,
- const GrVec* translate,
- GrIRect* pathBounds,
- GrIRect* clipBounds) {
- // compute bounds as intersection of rt size, clip, and path
- const GrRenderTarget* rt = target->getDrawState().getRenderTarget();
- if (NULL == rt) {
- return false;
- }
- *pathBounds = GrIRect::MakeWH(rt->width(), rt->height());
- const GrClip& clip = target->getClip();
- if (clip.hasConservativeBounds()) {
- clip.getConservativeBounds().roundOut(clipBounds);
- if (!pathBounds->intersect(*clipBounds)) {
- return false;
- }
- } else {
- // pathBounds is currently the rt extent, set clip bounds to that rect.
- *clipBounds = *pathBounds;
- }
- GrRect pathSBounds = path.getBounds();
- if (!pathSBounds.isEmpty()) {
- if (NULL != translate) {
- pathSBounds.offset(*translate);
- }
- target->getDrawState().getViewMatrix().mapRect(&pathSBounds,
- pathSBounds);
- GrIRect pathIBounds;
- pathSBounds.roundOut(&pathIBounds);
- if (!pathBounds->intersect(pathIBounds)) {
- return false;
- }
- } else {
- return false;
- }
- return true;
-}
-
-/**
- * sw rasterizes path to A8 mask using the context's matrix and uploads to a
- * scratch texture.
- */
-
-bool sw_draw_path_to_mask_texture(const SkPath& clientPath,
- const GrIRect& pathDevBounds,
- GrPathFill fill,
- GrContext* context,
- const GrPoint* translate,
- GrAutoScratchTexture* tex,
- bool antiAlias) {
- SkPaint paint;
- SkPath tmpPath;
- const SkPath* pathToDraw = &clientPath;
- if (kHairLine_PathFill == fill) {
- paint.setStyle(SkPaint::kStroke_Style);
- paint.setStrokeWidth(SK_Scalar1);
- } else {
- paint.setStyle(SkPaint::kFill_Style);
- SkPath::FillType skfill = gr_fill_to_sk_fill(fill);
- if (skfill != pathToDraw->getFillType()) {
- tmpPath = *pathToDraw;
- tmpPath.setFillType(skfill);
- pathToDraw = &tmpPath;
- }
- }
- paint.setAntiAlias(antiAlias);
- paint.setColor(SK_ColorWHITE);
-
- GrMatrix matrix = context->getMatrix();
- if (NULL != translate) {
- matrix.postTranslate(translate->fX, translate->fY);
- }
-
- matrix.postTranslate(-pathDevBounds.fLeft * SK_Scalar1,
- -pathDevBounds.fTop * SK_Scalar1);
- GrIRect bounds = GrIRect::MakeWH(pathDevBounds.width(),
- pathDevBounds.height());
-
- SkBitmap bm;
- bm.setConfig(SkBitmap::kA8_Config, bounds.fRight, bounds.fBottom);
- if (!bm.allocPixels()) {
- return false;
- }
- sk_bzero(bm.getPixels(), bm.getSafeSize());
-
- SkDraw draw;
- sk_bzero(&draw, sizeof(draw));
- SkRasterClip rc(bounds);
- draw.fRC = &rc;
- draw.fClip = &rc.bwRgn();
- draw.fMatrix = &matrix;
- draw.fBitmap = &bm;
- draw.drawPath(*pathToDraw, paint);
-
- const GrTextureDesc desc = {
- kNone_GrTextureFlags,
- bounds.fRight,
- bounds.fBottom,
- kAlpha_8_GrPixelConfig,
- 0 // samples
- };
-
- tex->set(context, desc);
- GrTexture* texture = tex->texture();
-
- if (NULL == texture) {
- return false;
- }
- SkAutoLockPixels alp(bm);
- texture->writePixels(0, 0, desc.fWidth, desc.fHeight, desc.fConfig,
- bm.getPixels(), bm.rowBytes());
- return true;
-}
-
-void draw_around_inv_path(GrDrawTarget* target,
- GrDrawState::StageMask stageMask,
- const GrIRect& clipBounds,
- const GrIRect& pathBounds) {
- GrDrawTarget::AutoDeviceCoordDraw adcd(target, stageMask);
- GrRect rect;
- if (clipBounds.fTop < pathBounds.fTop) {
- rect.iset(clipBounds.fLeft, clipBounds.fTop,
- clipBounds.fRight, pathBounds.fTop);
- target->drawSimpleRect(rect, NULL, stageMask);
- }
- if (clipBounds.fLeft < pathBounds.fLeft) {
- rect.iset(clipBounds.fLeft, pathBounds.fTop,
- pathBounds.fLeft, pathBounds.fBottom);
- target->drawSimpleRect(rect, NULL, stageMask);
- }
- if (clipBounds.fRight > pathBounds.fRight) {
- rect.iset(pathBounds.fRight, pathBounds.fTop,
- clipBounds.fRight, pathBounds.fBottom);
- target->drawSimpleRect(rect, NULL, stageMask);
- }
- if (clipBounds.fBottom > pathBounds.fBottom) {
- rect.iset(clipBounds.fLeft, pathBounds.fBottom,
- clipBounds.fRight, clipBounds.fBottom);
- target->drawSimpleRect(rect, NULL, stageMask);
- }
-}
-
struct CircleVertex {
GrPoint fPos;
GrPoint fCenter;
@@ -1554,58 +1389,6 @@ void GrContext::drawOval(const GrPaint& paint,
target->drawNonIndexed(kTriangleStrip_PrimitiveType, 0, 4);
}
-
-
-// return true on success; false on failure
-bool onDrawPath(const SkPath& path,
- GrPathFill fill,
- const GrVec* translate,
- GrDrawTarget* target,
- GrDrawState::StageMask stageMask,
- bool antiAlias,
- GrContext* context) {
-
- GrAutoScratchTexture ast;
- GrIRect pathBounds, clipBounds;
- if (!get_path_and_clip_bounds(target, path, translate,
- &pathBounds, &clipBounds)) {
- return true; // path is empty so there is nothing to do
- }
- if (sw_draw_path_to_mask_texture(path, pathBounds,
- fill, context,
- translate, &ast, antiAlias)) {
- GrTexture* texture = ast.texture();
- GrAssert(NULL != texture);
- GrDrawTarget::AutoDeviceCoordDraw adcd(target, stageMask);
- enum {
- kPathMaskStage = GrPaint::kTotalStages,
- };
- target->drawState()->setTexture(kPathMaskStage, texture);
- target->drawState()->sampler(kPathMaskStage)->reset();
- GrScalar w = GrIntToScalar(pathBounds.width());
- GrScalar h = GrIntToScalar(pathBounds.height());
- GrRect maskRect = GrRect::MakeWH(w / texture->width(),
- h / texture->height());
- const GrRect* srcRects[GrDrawState::kNumStages] = {NULL};
- srcRects[kPathMaskStage] = &maskRect;
- stageMask |= 1 << kPathMaskStage;
- GrRect dstRect = GrRect::MakeLTRB(
- SK_Scalar1* pathBounds.fLeft,
- SK_Scalar1* pathBounds.fTop,
- SK_Scalar1* pathBounds.fRight,
- SK_Scalar1* pathBounds.fBottom);
- target->drawRect(dstRect, NULL, stageMask, srcRects, NULL);
- target->drawState()->setTexture(kPathMaskStage, NULL);
- if (GrIsFillInverted(fill)) {
- draw_around_inv_path(target, stageMask,
- clipBounds, pathBounds);
- }
- return true;
- }
-
- return false;
-}
-
void GrContext::drawPath(const GrPaint& paint, const SkPath& path,
GrPathFill fill, const GrPoint* translate) {
@@ -1655,19 +1438,7 @@ void GrContext::internalDrawPath(const GrPaint& paint, const SkPath& path,
prAA = false;
}
- GrPathRenderer* pr = NULL;
- if (prAA) {
- pr = this->getPathRenderer(path, fill, target, true);
- if (NULL == pr) {
- if (onDrawPath(path, fill, translate,
- target, stageMask, prAA, this)) {
- return;
- }
- }
- } else {
- pr = this->getPathRenderer(path, fill, target, false);
- }
-
+ GrPathRenderer* pr = this->getPathRenderer(path, fill, target, prAA);
if (NULL == pr) {
#if GR_DEBUG
GrPrintf("Unable to find path renderer compatible with path.\n");
diff --git a/src/gpu/GrSoftwarePathRenderer.cpp b/src/gpu/GrSoftwarePathRenderer.cpp
index c591ac5bae..6780e0f6af 100644
--- a/src/gpu/GrSoftwarePathRenderer.cpp
+++ b/src/gpu/GrSoftwarePathRenderer.cpp
@@ -7,21 +7,203 @@
*/
#include "GrSoftwarePathRenderer.h"
+#include "GrPaint.h"
+#include "SkPaint.h"
+#include "GrRenderTarget.h"
+#include "GrContext.h"
+#include "SkDraw.h"
+#include "SkRasterClip.h"
-
+////////////////////////////////////////////////////////////////////////////////
bool GrSoftwarePathRenderer::canDrawPath(const SkPath& path,
GrPathFill fill,
const GrDrawTarget* target,
bool antiAlias) const {
- if (!antiAlias) {
- // TODO: the SW renderer can also handle non-AA paths
+ if (!antiAlias || NULL == fContext) {
+ // TODO: We could allow the SW path to also handle non-AA paths but
+ // this would mean that GrDefaultPathRenderer would never be called
+ // (since it appears after the SW renderer in the path renderer
+ // chain). Some testing would need to be done r.e. performance
+ // and consistency of the resulting images before removing
+ // the "!antiAlias" clause from the above test
return false;
}
- // TODO: set to true when filled out
- return false;
+ return true;
+}
+
+namespace {
+
+////////////////////////////////////////////////////////////////////////////////
+SkPath::FillType gr_fill_to_sk_fill(GrPathFill fill) {
+ switch (fill) {
+ case kWinding_PathFill:
+ return SkPath::kWinding_FillType;
+ case kEvenOdd_PathFill:
+ return SkPath::kEvenOdd_FillType;
+ case kInverseWinding_PathFill:
+ return SkPath::kInverseWinding_FillType;
+ case kInverseEvenOdd_PathFill:
+ return SkPath::kInverseEvenOdd_FillType;
+ default:
+ GrCrash("Unexpected fill.");
+ return SkPath::kWinding_FillType;
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// gets device coord bounds of path (not considering the fill) and clip. The
+// path bounds will be a subset of the clip bounds. returns false if
+// path bounds would be empty.
+bool get_path_and_clip_bounds(const GrDrawTarget* target,
+ const SkPath& path,
+ const GrVec* translate,
+ GrIRect* pathBounds,
+ GrIRect* clipBounds) {
+ // compute bounds as intersection of rt size, clip, and path
+ const GrRenderTarget* rt = target->getDrawState().getRenderTarget();
+ if (NULL == rt) {
+ return false;
+ }
+ *pathBounds = GrIRect::MakeWH(rt->width(), rt->height());
+ const GrClip& clip = target->getClip();
+ if (clip.hasConservativeBounds()) {
+ clip.getConservativeBounds().roundOut(clipBounds);
+ if (!pathBounds->intersect(*clipBounds)) {
+ return false;
+ }
+ } else {
+ // pathBounds is currently the rt extent, set clip bounds to that rect.
+ *clipBounds = *pathBounds;
+ }
+ GrRect pathSBounds = path.getBounds();
+ if (!pathSBounds.isEmpty()) {
+ if (NULL != translate) {
+ pathSBounds.offset(*translate);
+ }
+ target->getDrawState().getViewMatrix().mapRect(&pathSBounds,
+ pathSBounds);
+ GrIRect pathIBounds;
+ pathSBounds.roundOut(&pathIBounds);
+ if (!pathBounds->intersect(pathIBounds)) {
+ return false;
+ }
+ } else {
+ return false;
+ }
+ return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * sw rasterizes path to A8 mask using the context's matrix and uploads to a
+ * scratch texture.
+ */
+
+bool sw_draw_path_to_mask_texture(const SkPath& clientPath,
+ const GrIRect& pathDevBounds,
+ GrPathFill fill,
+ GrContext* context,
+ const GrPoint* translate,
+ GrAutoScratchTexture* tex,
+ bool antiAlias) {
+ SkPaint paint;
+ SkPath tmpPath;
+ const SkPath* pathToDraw = &clientPath;
+ if (kHairLine_PathFill == fill) {
+ paint.setStyle(SkPaint::kStroke_Style);
+ paint.setStrokeWidth(SK_Scalar1);
+ } else {
+ paint.setStyle(SkPaint::kFill_Style);
+ SkPath::FillType skfill = gr_fill_to_sk_fill(fill);
+ if (skfill != pathToDraw->getFillType()) {
+ tmpPath = *pathToDraw;
+ tmpPath.setFillType(skfill);
+ pathToDraw = &tmpPath;
+ }
+ }
+ paint.setAntiAlias(antiAlias);
+ paint.setColor(SK_ColorWHITE);
+
+ GrMatrix matrix = context->getMatrix();
+ if (NULL != translate) {
+ matrix.postTranslate(translate->fX, translate->fY);
+ }
+
+ matrix.postTranslate(-pathDevBounds.fLeft * SK_Scalar1,
+ -pathDevBounds.fTop * SK_Scalar1);
+ GrIRect bounds = GrIRect::MakeWH(pathDevBounds.width(),
+ pathDevBounds.height());
+
+ SkBitmap bm;
+ bm.setConfig(SkBitmap::kA8_Config, bounds.fRight, bounds.fBottom);
+ if (!bm.allocPixels()) {
+ return false;
+ }
+ sk_bzero(bm.getPixels(), bm.getSafeSize());
+
+ SkDraw draw;
+ sk_bzero(&draw, sizeof(draw));
+ SkRasterClip rc(bounds);
+ draw.fRC = &rc;
+ draw.fClip = &rc.bwRgn();
+ draw.fMatrix = &matrix;
+ draw.fBitmap = &bm;
+ draw.drawPath(*pathToDraw, paint);
+
+ const GrTextureDesc desc = {
+ kNone_GrTextureFlags,
+ bounds.fRight,
+ bounds.fBottom,
+ kAlpha_8_GrPixelConfig,
+ 0 // samples
+ };
+
+ tex->set(context, desc);
+ GrTexture* texture = tex->texture();
+
+ if (NULL == texture) {
+ return false;
+ }
+ SkAutoLockPixels alp(bm);
+ texture->writePixels(0, 0, desc.fWidth, desc.fHeight, desc.fConfig,
+ bm.getPixels(), bm.rowBytes());
+ return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void draw_around_inv_path(GrDrawTarget* target,
+ GrDrawState::StageMask stageMask,
+ const GrIRect& clipBounds,
+ const GrIRect& pathBounds) {
+ GrDrawTarget::AutoDeviceCoordDraw adcd(target, stageMask);
+ GrRect rect;
+ if (clipBounds.fTop < pathBounds.fTop) {
+ rect.iset(clipBounds.fLeft, clipBounds.fTop,
+ clipBounds.fRight, pathBounds.fTop);
+ target->drawSimpleRect(rect, NULL, stageMask);
+ }
+ if (clipBounds.fLeft < pathBounds.fLeft) {
+ rect.iset(clipBounds.fLeft, pathBounds.fTop,
+ pathBounds.fLeft, pathBounds.fBottom);
+ target->drawSimpleRect(rect, NULL, stageMask);
+ }
+ if (clipBounds.fRight > pathBounds.fRight) {
+ rect.iset(pathBounds.fRight, pathBounds.fTop,
+ clipBounds.fRight, pathBounds.fBottom);
+ target->drawSimpleRect(rect, NULL, stageMask);
+ }
+ if (clipBounds.fBottom > pathBounds.fBottom) {
+ rect.iset(clipBounds.fLeft, pathBounds.fBottom,
+ clipBounds.fRight, clipBounds.fBottom);
+ target->drawSimpleRect(rect, NULL, stageMask);
+ }
}
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// return true on success; false on failure
bool GrSoftwarePathRenderer::onDrawPath(const SkPath& path,
GrPathFill fill,
const GrVec* translate,
@@ -29,7 +211,48 @@ bool GrSoftwarePathRenderer::onDrawPath(const SkPath& path,
GrDrawState::StageMask stageMask,
bool antiAlias) {
- // TODO: move onDrawPath routine (& its helpers) here from GrContext.cpp
+ if (NULL == fContext) {
+ return false;
+ }
+
+ GrAutoScratchTexture ast;
+ GrIRect pathBounds, clipBounds;
+ if (!get_path_and_clip_bounds(target, path, translate,
+ &pathBounds, &clipBounds)) {
+ return true; // path is empty so there is nothing to do
+ }
+ if (sw_draw_path_to_mask_texture(path, pathBounds,
+ fill, fContext,
+ translate, &ast, antiAlias)) {
+ GrTexture* texture = ast.texture();
+ GrAssert(NULL != texture);
+ GrDrawTarget::AutoDeviceCoordDraw adcd(target, stageMask);
+ enum {
+ kPathMaskStage = GrPaint::kTotalStages,
+ };
+ target->drawState()->setTexture(kPathMaskStage, texture);
+ target->drawState()->sampler(kPathMaskStage)->reset();
+ GrScalar w = GrIntToScalar(pathBounds.width());
+ GrScalar h = GrIntToScalar(pathBounds.height());
+ GrRect maskRect = GrRect::MakeWH(w / texture->width(),
+ h / texture->height());
+ const GrRect* srcRects[GrDrawState::kNumStages] = {NULL};
+ srcRects[kPathMaskStage] = &maskRect;
+ stageMask |= 1 << kPathMaskStage;
+ GrRect dstRect = GrRect::MakeLTRB(
+ SK_Scalar1* pathBounds.fLeft,
+ SK_Scalar1* pathBounds.fTop,
+ SK_Scalar1* pathBounds.fRight,
+ SK_Scalar1* pathBounds.fBottom);
+ target->drawRect(dstRect, NULL, stageMask, srcRects, NULL);
+ target->drawState()->setTexture(kPathMaskStage, NULL);
+ if (GrIsFillInverted(fill)) {
+ draw_around_inv_path(target, stageMask,
+ clipBounds, pathBounds);
+ }
+ return true;
+ }
+
return false;
}