| Index: src/gpu/SkGpuDevice.cpp
|
| diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
|
| index 94ded8de98b631d6c2c61cef3c390f8825b606d3..0008540cb57defbc420f583e1f26383b43fc3581 100644
|
| --- a/src/gpu/SkGpuDevice.cpp
|
| +++ b/src/gpu/SkGpuDevice.cpp
|
| @@ -7,6 +7,7 @@
|
|
|
| #include "SkGpuDevice.h"
|
|
|
| +#include "GrBlurUtils.h"
|
| #include "GrContext.h"
|
| #include "GrDrawContext.h"
|
| #include "GrGpu.h"
|
| @@ -167,8 +168,7 @@ SkGpuDevice::SkGpuDevice(GrRenderTarget* rt, int width, int height,
|
| fLegacyBitmap.setPixelRef(pr)->unref();
|
|
|
| bool useDFT = fSurfaceProps.isUseDistanceFieldFonts();
|
| - fTextContext = fContext->createTextContext(fRenderTarget, this, this->getLeakyProperties(),
|
| - useDFT);
|
| + fTextContext = fContext->createTextContext(fRenderTarget, this->getLeakyProperties(), useDFT);
|
| fDrawContext.reset(SkRef(fContext->drawContext()));
|
| }
|
|
|
| @@ -626,145 +626,13 @@ void SkGpuDevice::drawOval(const SkDraw& draw, const SkRect& oval,
|
|
|
| ///////////////////////////////////////////////////////////////////////////////
|
|
|
| -// helpers for applying mask filters
|
| -namespace {
|
| -
|
| -// Draw a mask using the supplied paint. Since the coverage/geometry
|
| -// is already burnt into the mask this boils down to a rect draw.
|
| -// Return true if the mask was successfully drawn.
|
| -bool draw_mask(GrDrawContext* drawContext,
|
| - GrRenderTarget* rt,
|
| - const GrClip& clip,
|
| - const SkMatrix& viewMatrix,
|
| - const SkRect& maskRect,
|
| - GrPaint* grp,
|
| - GrTexture* mask) {
|
| - SkMatrix matrix;
|
| - matrix.setTranslate(-maskRect.fLeft, -maskRect.fTop);
|
| - matrix.postIDiv(mask->width(), mask->height());
|
| -
|
| - grp->addCoverageProcessor(GrSimpleTextureEffect::Create(mask, matrix,
|
| - kDevice_GrCoordSet))->unref();
|
| -
|
| - SkMatrix inverse;
|
| - if (!viewMatrix.invert(&inverse)) {
|
| - return false;
|
| - }
|
| - drawContext->drawNonAARectWithLocalMatrix(rt, clip, *grp, SkMatrix::I(), maskRect, inverse);
|
| - return true;
|
| -}
|
| -
|
| -static bool clip_bounds_quick_reject(const SkIRect& clipBounds, const SkIRect& rect) {
|
| - return clipBounds.isEmpty() || rect.isEmpty() || !SkIRect::Intersects(clipBounds, rect);
|
| -}
|
| -
|
| -bool draw_with_mask_filter(GrDrawContext* drawContext,
|
| - GrTextureProvider* textureProvider,
|
| - GrRenderTarget* rt,
|
| - const GrClip& clipData,
|
| - const SkMatrix& viewMatrix,
|
| - const SkPath& devPath,
|
| - SkMaskFilter* filter,
|
| - const SkIRect& clipBounds,
|
| - GrPaint* grp,
|
| - SkPaint::Style style) {
|
| - SkMask srcM, dstM;
|
| -
|
| - if (!SkDraw::DrawToMask(devPath, &clipBounds, filter, &viewMatrix, &srcM,
|
| - SkMask::kComputeBoundsAndRenderImage_CreateMode, style)) {
|
| - return false;
|
| - }
|
| - SkAutoMaskFreeImage autoSrc(srcM.fImage);
|
| -
|
| - if (!filter->filterMask(&dstM, srcM, viewMatrix, NULL)) {
|
| - return false;
|
| - }
|
| - // this will free-up dstM when we're done (allocated in filterMask())
|
| - SkAutoMaskFreeImage autoDst(dstM.fImage);
|
| -
|
| - if (clip_bounds_quick_reject(clipBounds, dstM.fBounds)) {
|
| - return false;
|
| - }
|
| -
|
| - // we now have a device-aligned 8bit mask in dstM, ready to be drawn using
|
| - // the current clip (and identity matrix) and GrPaint settings
|
| - GrSurfaceDesc desc;
|
| - desc.fWidth = dstM.fBounds.width();
|
| - desc.fHeight = dstM.fBounds.height();
|
| - desc.fConfig = kAlpha_8_GrPixelConfig;
|
| -
|
| - SkAutoTUnref<GrTexture> texture(textureProvider->refScratchTexture(
|
| - desc, GrTextureProvider::kApprox_ScratchTexMatch));
|
| - if (!texture) {
|
| - return false;
|
| - }
|
| - texture->writePixels(0, 0, desc.fWidth, desc.fHeight, desc.fConfig,
|
| - dstM.fImage, dstM.fRowBytes);
|
| -
|
| - SkRect maskRect = SkRect::Make(dstM.fBounds);
|
| -
|
| - return draw_mask(drawContext, rt, clipData, viewMatrix, maskRect, grp, texture);
|
| -}
|
| -
|
| -// Create a mask of 'devPath' and place the result in 'mask'.
|
| -GrTexture* create_mask_GPU(GrContext* context,
|
| - const SkRect& maskRect,
|
| - const SkPath& devPath,
|
| - const GrStrokeInfo& strokeInfo,
|
| - bool doAA,
|
| - int sampleCnt) {
|
| - GrSurfaceDesc desc;
|
| - desc.fFlags = kRenderTarget_GrSurfaceFlag;
|
| - desc.fWidth = SkScalarCeilToInt(maskRect.width());
|
| - desc.fHeight = SkScalarCeilToInt(maskRect.height());
|
| - desc.fSampleCnt = doAA ? sampleCnt : 0;
|
| - // We actually only need A8, but it often isn't supported as a
|
| - // render target so default to RGBA_8888
|
| - desc.fConfig = kRGBA_8888_GrPixelConfig;
|
| -
|
| - if (context->isConfigRenderable(kAlpha_8_GrPixelConfig,
|
| - desc.fSampleCnt > 0)) {
|
| - desc.fConfig = kAlpha_8_GrPixelConfig;
|
| - }
|
| -
|
| - GrTexture* mask = context->textureProvider()->refScratchTexture(
|
| - desc, GrTextureProvider::kApprox_ScratchTexMatch);
|
| - if (NULL == mask) {
|
| - return NULL;
|
| - }
|
| -
|
| - SkRect clipRect = SkRect::MakeWH(maskRect.width(), maskRect.height());
|
| -
|
| - GrDrawContext* drawContext = context->drawContext();
|
| - if (!drawContext) {
|
| - return NULL;
|
| - }
|
| -
|
| - drawContext->clear(mask->asRenderTarget(), NULL, 0x0, true);
|
| -
|
| - GrPaint tempPaint;
|
| - tempPaint.setAntiAlias(doAA);
|
| - tempPaint.setCoverageSetOpXPFactory(SkRegion::kReplace_Op);
|
| -
|
| - // setup new clip
|
| - GrClip clip(clipRect);
|
| -
|
| - // Draw the mask into maskTexture with the path's top-left at the origin using tempPaint.
|
| - SkMatrix translate;
|
| - translate.setTranslate(-maskRect.fLeft, -maskRect.fTop);
|
| - drawContext->drawPath(mask->asRenderTarget(), clip, tempPaint, translate, devPath, strokeInfo);
|
| - return mask;
|
| -}
|
| -
|
| -SkBitmap wrap_texture(GrTexture* texture, int width, int height) {
|
| +static SkBitmap wrap_texture(GrTexture* texture, int width, int height) {
|
| SkBitmap result;
|
| result.setInfo(SkImageInfo::MakeN32Premul(width, height));
|
| result.setPixelRef(SkNEW_ARGS(SkGrPixelRef, (result.info(), texture)))->unref();
|
| return result;
|
| }
|
|
|
| -};
|
| -
|
| void SkGpuDevice::drawPath(const SkDraw& draw, const SkPath& origSrcPath,
|
| const SkPaint& paint, const SkMatrix* prePathMatrix,
|
| bool pathIsMutable) {
|
| @@ -772,150 +640,10 @@ void SkGpuDevice::drawPath(const SkDraw& draw, const SkPath& origSrcPath,
|
| CHECK_SHOULD_DRAW(draw);
|
| GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice::drawPath", fContext);
|
|
|
| - return this->internalDrawPath(origSrcPath, paint, *draw.fMatrix, prePathMatrix,
|
| - draw.fClip->getBounds(), pathIsMutable);
|
| -}
|
| -
|
| -void SkGpuDevice::internalDrawPath(const SkPath& origSrcPath, const SkPaint& paint,
|
| - const SkMatrix& origViewMatrix, const SkMatrix* prePathMatrix,
|
| - const SkIRect& clipBounds, bool pathIsMutable) {
|
| - SkASSERT(!pathIsMutable || origSrcPath.isVolatile());
|
| -
|
| - GrStrokeInfo strokeInfo(paint);
|
| -
|
| - // If we have a prematrix, apply it to the path, optimizing for the case
|
| - // where the original path can in fact be modified in place (even though
|
| - // its parameter type is const).
|
| - SkPath* pathPtr = const_cast<SkPath*>(&origSrcPath);
|
| - SkTLazy<SkPath> tmpPath;
|
| - SkTLazy<SkPath> effectPath;
|
| - SkPathEffect* pathEffect = paint.getPathEffect();
|
| -
|
| - SkMatrix viewMatrix = origViewMatrix;
|
| -
|
| - if (prePathMatrix) {
|
| - // stroking, path effects, and blurs are supposed to be applied *after* the prePathMatrix.
|
| - // The pre-path-matrix also should not affect shading.
|
| - if (NULL == paint.getMaskFilter() && NULL == pathEffect && NULL == paint.getShader() &&
|
| - (strokeInfo.isFillStyle() || strokeInfo.isHairlineStyle())) {
|
| - viewMatrix.preConcat(*prePathMatrix);
|
| - } else {
|
| - SkPath* result = pathPtr;
|
| -
|
| - if (!pathIsMutable) {
|
| - result = tmpPath.init();
|
| - result->setIsVolatile(true);
|
| - pathIsMutable = true;
|
| - }
|
| - // should I push prePathMatrix on our MV stack temporarily, instead
|
| - // of applying it here? See SkDraw.cpp
|
| - pathPtr->transform(*prePathMatrix, result);
|
| - pathPtr = result;
|
| - }
|
| - }
|
| - // at this point we're done with prePathMatrix
|
| - SkDEBUGCODE(prePathMatrix = (const SkMatrix*)0x50FF8001;)
|
| -
|
| - GrPaint grPaint;
|
| - if (!SkPaint2GrPaint(this->context(), fRenderTarget, paint, viewMatrix, true, &grPaint)) {
|
| - return;
|
| - }
|
| -
|
| - const SkRect* cullRect = NULL; // TODO: what is our bounds?
|
| - if (!strokeInfo.isDashed() && pathEffect && pathEffect->filterPath(effectPath.init(), *pathPtr,
|
| - &strokeInfo, cullRect)) {
|
| - pathPtr = effectPath.get();
|
| - pathIsMutable = true;
|
| - }
|
| -
|
| - if (paint.getMaskFilter()) {
|
| - if (!strokeInfo.isHairlineStyle()) {
|
| - SkPath* strokedPath = pathIsMutable ? pathPtr : tmpPath.init();
|
| - if (strokeInfo.isDashed()) {
|
| - if (pathEffect->filterPath(strokedPath, *pathPtr, &strokeInfo, cullRect)) {
|
| - pathPtr = strokedPath;
|
| - pathIsMutable = true;
|
| - }
|
| - strokeInfo.removeDash();
|
| - }
|
| - if (strokeInfo.applyToPath(strokedPath, *pathPtr)) {
|
| - pathPtr = strokedPath;
|
| - pathIsMutable = true;
|
| - strokeInfo.setFillStyle();
|
| - }
|
| - }
|
| -
|
| - // avoid possibly allocating a new path in transform if we can
|
| - SkPath* devPathPtr = pathIsMutable ? pathPtr : tmpPath.init();
|
| - if (!pathIsMutable) {
|
| - devPathPtr->setIsVolatile(true);
|
| - }
|
| -
|
| - // transform the path into device space
|
| - pathPtr->transform(viewMatrix, devPathPtr);
|
| -
|
| - SkRect maskRect;
|
| - if (paint.getMaskFilter()->canFilterMaskGPU(devPathPtr->getBounds(),
|
| - clipBounds,
|
| - viewMatrix,
|
| - &maskRect)) {
|
| - SkIRect finalIRect;
|
| - maskRect.roundOut(&finalIRect);
|
| - if (clip_bounds_quick_reject(clipBounds, finalIRect)) {
|
| - // clipped out
|
| - return;
|
| - }
|
| -
|
| - if (paint.getMaskFilter()->directFilterMaskGPU(fContext,
|
| - fRenderTarget,
|
| - &grPaint,
|
| - fClip,
|
| - viewMatrix,
|
| - strokeInfo,
|
| - *devPathPtr)) {
|
| - // the mask filter was able to draw itself directly, so there's nothing
|
| - // left to do.
|
| - return;
|
| - }
|
| -
|
| -
|
| - SkAutoTUnref<GrTexture> mask(create_mask_GPU(fContext,
|
| - maskRect,
|
| - *devPathPtr,
|
| - strokeInfo,
|
| - grPaint.isAntiAlias(),
|
| - fRenderTarget->numSamples()));
|
| - if (mask) {
|
| - GrTexture* filtered;
|
| -
|
| - if (paint.getMaskFilter()->filterMaskGPU(mask, viewMatrix, maskRect, &filtered, true)) {
|
| - // filterMaskGPU gives us ownership of a ref to the result
|
| - SkAutoTUnref<GrTexture> atu(filtered);
|
| - if (draw_mask(fDrawContext,
|
| - fRenderTarget,
|
| - fClip,
|
| - viewMatrix,
|
| - maskRect,
|
| - &grPaint,
|
| - filtered)) {
|
| - // This path is completely drawn
|
| - return;
|
| - }
|
| - }
|
| - }
|
| - }
|
| -
|
| - // draw the mask on the CPU - this is a fallthrough path in case the
|
| - // GPU path fails
|
| - SkPaint::Style style = strokeInfo.isHairlineStyle() ? SkPaint::kStroke_Style :
|
| - SkPaint::kFill_Style;
|
| - draw_with_mask_filter(fDrawContext, fContext->textureProvider(), fRenderTarget,
|
| - fClip, viewMatrix, *devPathPtr,
|
| - paint.getMaskFilter(), clipBounds, &grPaint, style);
|
| - return;
|
| - }
|
| -
|
| - fDrawContext->drawPath(fRenderTarget, fClip, grPaint, viewMatrix, *pathPtr, strokeInfo);
|
| + GrBlurUtils::drawPathWithMaskFilter(fContext, fDrawContext, fRenderTarget,
|
| + fClip, origSrcPath, paint,
|
| + *draw.fMatrix, prePathMatrix,
|
| + draw.fClip->getBounds(), pathIsMutable);
|
| }
|
|
|
| static const int kBmpSmallTileSize = 1 << 10;
|
| @@ -1931,8 +1659,8 @@ void SkGpuDevice::drawTextBlob(const SkDraw& draw, const SkTextBlob* blob, SkSca
|
|
|
| SkDEBUGCODE(this->validate();)
|
|
|
| - fTextContext->drawTextBlob(fRenderTarget, fClip, paint, *draw.fMatrix, blob, x, y, drawFilter,
|
| - draw.fClip->getBounds());
|
| + fTextContext->drawTextBlob(this, fRenderTarget, fClip, paint, *draw.fMatrix,
|
| + blob, x, y, drawFilter, draw.fClip->getBounds());
|
| }
|
|
|
| ///////////////////////////////////////////////////////////////////////////////
|
|
|