diff options
-rw-r--r-- | samplecode/SampleClipDrawMatch.cpp | 125 | ||||
-rw-r--r-- | src/core/SkClipStack.cpp | 13 | ||||
-rw-r--r-- | src/gpu/effects/GrConvexPolyEffect.cpp | 23 | ||||
-rw-r--r-- | src/gpu/gl/builders/GrGLVertexShaderBuilder.cpp | 10 |
4 files changed, 88 insertions, 83 deletions
diff --git a/samplecode/SampleClipDrawMatch.cpp b/samplecode/SampleClipDrawMatch.cpp index 8e2fb46dc9..f897b7185e 100644 --- a/samplecode/SampleClipDrawMatch.cpp +++ b/samplecode/SampleClipDrawMatch.cpp @@ -16,6 +16,7 @@ // fractionally (via an animator) to expose snapping bugs. The key bindings are: // 1-9: the different geometries // t: toggle which is drawn first the clip or the normal geometry +// f: flip-flops which corner the bottom AA clip rect occupies in the complex clip cases // The possible geometric combinations to test enum Geometry { @@ -35,6 +36,10 @@ static const float kMin = 100.5f; static const float kMid = 200.0f; static const float kMax = 299.5f; +// The translation applied to the base AA rect in the combination cases +// (i.e., kRectAndRect through kRectAndConcave) +static const float kXlate = 100.0f; + SkRect create_rect(const SkPoint& offset) { SkRect r = SkRect::MakeLTRB(kMin, kMin, kMax, kMax); r.offset(offset); @@ -79,62 +84,6 @@ SkPath create_concave_path(const SkPoint& offset) { return concavePath; } -static void draw_clipped_geom(SkCanvas* canvas, const SkPoint& offset, int geom, bool useAA) { - - int count = canvas->save(); - - switch (geom) { - case kRect_Geometry: - canvas->clipRect(create_rect(offset), SkRegion::kReplace_Op, useAA); - break; - case kRRect_Geometry: - canvas->clipRRect(create_rrect(offset), SkRegion::kReplace_Op, useAA); - break; - case kCircle_Geometry: - canvas->clipRRect(create_circle(offset), SkRegion::kReplace_Op, useAA); - break; - case kConvexPath_Geometry: - canvas->clipPath(create_convex_path(offset), SkRegion::kReplace_Op, useAA); - break; - case kConcavePath_Geometry: - canvas->clipPath(create_concave_path(offset), SkRegion::kReplace_Op, useAA); - break; - case kRectAndRect_Geometry: { - SkRect r = create_rect(offset); - r.offset(-100.0f, -100.0f); - canvas->clipRect(r, SkRegion::kReplace_Op, true); // AA here forces shader clips - canvas->clipRect(create_rect(offset), SkRegion::kIntersect_Op, useAA); - } break; - case kRectAndRRect_Geometry: { - SkRect r = create_rect(offset); - r.offset(-100.0f, -100.0f); - canvas->clipRect(r, SkRegion::kReplace_Op, true); // AA here forces shader clips - canvas->clipRRect(create_rrect(offset), SkRegion::kIntersect_Op, useAA); - } break; - case kRectAndConvex_Geometry: { - SkRect r = create_rect(offset); - r.offset(-100.0f, -100.0f); - canvas->clipRect(r, SkRegion::kReplace_Op, true); // AA here forces shader clips - canvas->clipPath(create_convex_path(offset), SkRegion::kIntersect_Op, useAA); - } break; - case kRectAndConcave_Geometry: { - SkRect r = create_rect(offset); - r.offset(-100.0f, -100.0f); - canvas->clipRect(r, SkRegion::kReplace_Op, true); // AA here forces shader clips - canvas->clipPath(create_concave_path(offset), SkRegion::kIntersect_Op, useAA); - } break; - } - - SkISize size = canvas->getDeviceSize(); - SkRect bigR = SkRect::MakeWH(SkIntToScalar(size.width()), SkIntToScalar(size.height())); - - SkPaint p; - p.setColor(SK_ColorRED); - - canvas->drawRect(bigR, p); - canvas->restoreToCount(count); -} - static void draw_normal_geom(SkCanvas* canvas, const SkPoint& offset, int geom, bool useAA) { SkPaint p; p.setAntiAlias(useAA); @@ -165,7 +114,7 @@ static void draw_normal_geom(SkCanvas* canvas, const SkPoint& offset, int geom, class ClipDrawMatchView : public SampleView { public: - ClipDrawMatchView() : fTrans(2, 5), fGeom(kRect_Geometry), fClipFirst(true) { + ClipDrawMatchView() : fTrans(2, 5), fGeom(kRect_Geometry), fClipFirst(true), fSign(1) { SkScalar values[2]; fTrans.setRepeatCount(999); @@ -199,6 +148,7 @@ protected: case '7': fGeom = kRectAndRRect_Geometry; this->inval(NULL); return true; case '8': fGeom = kRectAndConvex_Geometry; this->inval(NULL); return true; case '9': fGeom = kRectAndConcave_Geometry; this->inval(NULL); return true; + case 'f': fSign = -fSign; this->inval(NULL); return true; case 't': fClipFirst = !fClipFirst; this->inval(NULL); return true; default: break; } @@ -206,18 +156,74 @@ protected: return this->INHERITED::onQuery(evt); } + void drawClippedGeom(SkCanvas* canvas, const SkPoint& offset, bool useAA) { + + int count = canvas->save(); + + switch (fGeom) { + case kRect_Geometry: + canvas->clipRect(create_rect(offset), SkRegion::kReplace_Op, useAA); + break; + case kRRect_Geometry: + canvas->clipRRect(create_rrect(offset), SkRegion::kReplace_Op, useAA); + break; + case kCircle_Geometry: + canvas->clipRRect(create_circle(offset), SkRegion::kReplace_Op, useAA); + break; + case kConvexPath_Geometry: + canvas->clipPath(create_convex_path(offset), SkRegion::kReplace_Op, useAA); + break; + case kConcavePath_Geometry: + canvas->clipPath(create_concave_path(offset), SkRegion::kReplace_Op, useAA); + break; + case kRectAndRect_Geometry: { + SkRect r = create_rect(offset); + r.offset(fSign * kXlate, fSign * kXlate); + canvas->clipRect(r, SkRegion::kReplace_Op, true); // AA here forces shader clips + canvas->clipRect(create_rect(offset), SkRegion::kIntersect_Op, useAA); + } break; + case kRectAndRRect_Geometry: { + SkRect r = create_rect(offset); + r.offset(fSign * kXlate, fSign * kXlate); + canvas->clipRect(r, SkRegion::kReplace_Op, true); // AA here forces shader clips + canvas->clipRRect(create_rrect(offset), SkRegion::kIntersect_Op, useAA); + } break; + case kRectAndConvex_Geometry: { + SkRect r = create_rect(offset); + r.offset(fSign * kXlate, fSign * kXlate); + canvas->clipRect(r, SkRegion::kReplace_Op, true); // AA here forces shader clips + canvas->clipPath(create_convex_path(offset), SkRegion::kIntersect_Op, useAA); + } break; + case kRectAndConcave_Geometry: { + SkRect r = create_rect(offset); + r.offset(fSign * kXlate, fSign * kXlate); + canvas->clipRect(r, SkRegion::kReplace_Op, true); // AA here forces shader clips + canvas->clipPath(create_concave_path(offset), SkRegion::kIntersect_Op, useAA); + } break; + } + + SkISize size = canvas->getDeviceSize(); + SkRect bigR = SkRect::MakeWH(SkIntToScalar(size.width()), SkIntToScalar(size.height())); + + SkPaint p; + p.setColor(SK_ColorRED); + + canvas->drawRect(bigR, p); + canvas->restoreToCount(count); + } + // Draw a big red rect through some clip geometry and also draw that same // geometry in black. The order in which they are drawn can be swapped. // This tests whether the clip and normally drawn geometry match up. void drawGeometry(SkCanvas* canvas, const SkPoint& offset, bool useAA) { if (fClipFirst) { - draw_clipped_geom(canvas, offset, fGeom, useAA); + this->drawClippedGeom(canvas, offset, useAA); } draw_normal_geom(canvas, offset, fGeom, useAA); if (!fClipFirst) { - draw_clipped_geom(canvas, offset, fGeom, useAA); + this->drawClippedGeom(canvas, offset, useAA); } } @@ -239,6 +245,7 @@ private: SkInterpolator fTrans; Geometry fGeom; bool fClipFirst; + int fSign; typedef SampleView INHERITED; }; diff --git a/src/core/SkClipStack.cpp b/src/core/SkClipStack.cpp index 515596a969..863dc9a387 100644 --- a/src/core/SkClipStack.cpp +++ b/src/core/SkClipStack.cpp @@ -418,19 +418,6 @@ void SkClipStack::Element::updateBoundAndGenID(const Element* prior) { break; } - if (!fDoAA) { - // Here we mimic a non-anti-aliased scanline system. If there is - // no anti-aliasing we can integerize the bounding box to exclude - // fractional parts that won't be rendered. - // Note: the left edge is handled slightly differently below. We - // are a bit more generous in the rounding since we don't want to - // risk missing the left pixels when fLeft is very close to .5 - fFiniteBound.set(SkScalarFloorToScalar(fFiniteBound.fLeft+0.45f), - SkScalarRoundToScalar(fFiniteBound.fTop), - SkScalarRoundToScalar(fFiniteBound.fRight), - SkScalarRoundToScalar(fFiniteBound.fBottom)); - } - // Now determine the previous Element's bound information taking into // account that there may be no previous clip SkRect prevFinite; diff --git a/src/gpu/effects/GrConvexPolyEffect.cpp b/src/gpu/effects/GrConvexPolyEffect.cpp index 7035094fa6..615c341ef2 100644 --- a/src/gpu/effects/GrConvexPolyEffect.cpp +++ b/src/gpu/effects/GrConvexPolyEffect.cpp @@ -137,10 +137,14 @@ void GLAARectEffect::emitCode(GrGLFPBuilder* builder, fsBuilder->codeAppendf("\t\tfloat alpha = (1.0 + max(xSub, -1.0)) * (1.0 + max(ySub, -1.0));\n"); } else { fsBuilder->codeAppendf("\t\tfloat alpha = 1.0;\n"); - fsBuilder->codeAppendf("\t\talpha *= (%s.x - %s.x) > -0.5 ? 1.0 : 0.0;\n", fragmentPos, rectName); - fsBuilder->codeAppendf("\t\talpha *= (%s.z - %s.x) > -0.5 ? 1.0 : 0.0;\n", rectName, fragmentPos); - fsBuilder->codeAppendf("\t\talpha *= (%s.y - %s.y) > -0.5 ? 1.0 : 0.0;\n", fragmentPos, rectName); - fsBuilder->codeAppendf("\t\talpha *= (%s.w - %s.y) > -0.5 ? 1.0 : 0.0;\n", rectName, fragmentPos); + fsBuilder->codeAppendf("\t\talpha *= (%s.x - %s.x) > -0.5 ? 1.0 : 0.0;\n", + fragmentPos, rectName); + fsBuilder->codeAppendf("\t\talpha *= (%s.z - %s.x) > -0.5 ? 1.0 : 0.0;\n", + rectName, fragmentPos); + fsBuilder->codeAppendf("\t\talpha *= (%s.y - %s.y) > -0.5 ? 1.0 : 0.0;\n", + fragmentPos, rectName); + fsBuilder->codeAppendf("\t\talpha *= (%s.w - %s.y) > -0.5 ? 1.0 : 0.0;\n", + rectName, fragmentPos); } if (GrProcessorEdgeTypeIsInverseFill(aare.getEdgeType())) { @@ -154,8 +158,10 @@ void GLAARectEffect::setData(const GrGLProgramDataManager& pdman, const GrProces const AARectEffect& aare = processor.cast<AARectEffect>(); const SkRect& rect = aare.getRect(); if (rect != fPrevRect) { - pdman.set4f(fRectUniform, rect.fLeft + 0.5f, rect.fTop + 0.5f, - rect.fRight - 0.5f, rect.fBottom - 0.5f); + // Add a device space "nudge" of 0.05f, 0.05f to match raster's rounding behavior for + // BW clipping/drawing + pdman.set4f(fRectUniform, rect.fLeft + 0.55f, rect.fTop + 0.55f, + rect.fRight - 0.45f, rect.fBottom - 0.45f); fPrevRect = rect; } } @@ -221,7 +227,10 @@ void GrGLConvexPolyEffect::emitCode(GrGLFPBuilder* builder, fsBuilder->codeAppend("\t\tfloat edge;\n"); const char* fragmentPos = fsBuilder->fragmentPosition(); for (int i = 0; i < cpe.getEdgeCount(); ++i) { - fsBuilder->codeAppendf("\t\tedge = dot(%s[%d], vec3(%s.x, %s.y, 1));\n", + // Add a device space "nudge" of 0.05f, 0.05f to match raster's rounding behavior for + // BW clipping/drawing. Since we are "nudging" fragment positions we have to go in + // the opposite direction. + fsBuilder->codeAppendf("\t\tedge = dot(%s[%d], vec3(%s.x - 0.05, %s.y - 0.05, 1));\n", edgeArrayName, i, fragmentPos, fragmentPos); if (GrProcessorEdgeTypeIsAA(cpe.getEdgeType())) { fsBuilder->codeAppend("\t\tedge = clamp(edge, 0.0, 1.0);\n"); diff --git a/src/gpu/gl/builders/GrGLVertexShaderBuilder.cpp b/src/gpu/gl/builders/GrGLVertexShaderBuilder.cpp index f17e741169..f0b645ee42 100644 --- a/src/gpu/gl/builders/GrGLVertexShaderBuilder.cpp +++ b/src/gpu/gl/builders/GrGLVertexShaderBuilder.cpp @@ -47,13 +47,15 @@ void GrGLVertexBuilder::transformToNormalizedDeviceSpace(const GrShaderVar& posV // Transform from Skia's device coords to GL's normalized device coords. Note that // because we want to "nudge" the device space positions we are converting to // non-homogeneous NDC. + // The "0.05" nudge serves to match the raster path's rounding for bw draws. + // For aa draws we just assume the impact will be minimal - so we always perform the nudge. if (kVec3f_GrSLType == posVar.getType()) { - this->codeAppendf("gl_Position = vec4(dot(%s.xz, %s.xy)/%s.z, dot(%s.yz, %s.zw)/%s.z, 0, 1);", - posVar.c_str(), fRtAdjustName, posVar.c_str(), - posVar.c_str(), fRtAdjustName, posVar.c_str()); + this->codeAppendf("gl_Position = vec4((dot(%s.xz, %s.xy)/%s.z) + 0.05 * %s.x, (dot(%s.yz, %s.zw)/%s.z) + 0.05 * %s.z, 0, 1);", + posVar.c_str(), fRtAdjustName, posVar.c_str(), fRtAdjustName, + posVar.c_str(), fRtAdjustName, posVar.c_str(), fRtAdjustName); } else { SkASSERT(kVec2f_GrSLType == posVar.getType()); - this->codeAppendf("gl_Position = vec4(%s.x * %s.x + %s.y, %s.y * %s.z + %s.w, 0, 1);", + this->codeAppendf("gl_Position = vec4((%s.x + 0.05) * %s.x + %s.y, (%s.y + 0.05) * %s.z + %s.w, 0, 1);", posVar.c_str(), fRtAdjustName, fRtAdjustName, posVar.c_str(), fRtAdjustName, fRtAdjustName); } |