Minimize use of SkDraw's matrix in SkGpuDevice.

R=robertphillips@google.com
Review URL: https://codereview.appspot.com/6604068

git-svn-id: http://skia.googlecode.com/svn/trunk@5906 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
bsalomon@google.com 2012-10-11 19:39:09 +00:00
Родитель 5dc26b9736
Коммит 3ab43d5c5b
5 изменённых файлов: 100 добавлений и 60 удалений

Просмотреть файл

@ -63,6 +63,13 @@ public:
BoundsType* boundType,
bool* isIntersectionOfRects = NULL) const;
/**
* Takes an input rect in device space and conservatively clips it to the
* clip-stack. If false is returned then the rect does not intersect the
* clip and is unmodified.
*/
bool intersectRectWithClip(SkRect* devRect) const;
void clipDevRect(const SkIRect& ir, SkRegion::Op op) {
SkRect r;
r.set(ir);

Просмотреть файл

@ -481,6 +481,13 @@ struct SK_API SkRect {
fBottom = y + height;
}
void setWH(SkScalar width, SkScalar height) {
fLeft = 0;
fTop = 0;
fRight = width;
fBottom = height;
}
/**
* Make the largest representable rectangle
*/

Просмотреть файл

@ -145,27 +145,34 @@ private:
bool bindDeviceAsTexture(GrPaint* paint);
void prepareDraw(const SkDraw&); // sets the render target, clip, and matrix on GrContext.
bool shouldTileBitmap(const SkBitmap& bitmap,
const GrTextureParams& sampler,
const SkRect* srcRectPtr) const;
void internalDrawBitmap(const SkDraw&,
const SkBitmap&,
const SkRect&,
const SkMatrix&,
const GrTextureParams& params,
GrPaint* grPaint);
void drawTiledBitmap(const SkDraw& draw,
const SkBitmap& bitmap,
const SkRect& srcRect,
const SkMatrix& m,
const GrTextureParams& params,
GrPaint* grPaint);
/**
* Implementation for both drawBitmap and drawBitmapRect.
*/
void drawBitmapCommon(const SkDraw&,
const SkBitmap& bitmap,
const SkRect* srcRectPtr,
const SkMatrix&,
const SkPaint&);
/**
* Helper functions called by drawBitmapCommon. By the time these are called the SkDraw's
* matrix has already been set on GrContext
*/
bool shouldTileBitmap(const SkBitmap& bitmap,
const GrTextureParams& sampler,
const SkRect* srcRectPtr) const;
void internalDrawBitmap(const SkBitmap&,
const SkRect&,
const SkMatrix&,
const GrTextureParams& params,
GrPaint* grPaint);
void drawTiledBitmap(const SkBitmap& bitmap,
const SkRect& srcRect,
const SkMatrix& m,
const GrTextureParams& params,
GrPaint* grPaint);
/**
* Returns non-initialized instance.
*/

Просмотреть файл

@ -567,6 +567,25 @@ void SkClipStack::getBounds(SkRect* canvFiniteBound,
}
}
bool SkClipStack::intersectRectWithClip(SkRect* rect) const {
SkASSERT(NULL != rect);
SkRect bounds;
SkClipStack::BoundsType bt;
this->getBounds(&bounds, &bt);
if (bt == SkClipStack::kInsideOut_BoundsType) {
if (bounds.contains(*rect)) {
return false;
} else {
// If rect's x values are both within bound's x range we
// could clip here. Same for y. But we don't bother to check.
return true;
}
} else {
return rect->intersect(bounds);
}
}
void SkClipStack::clipDevRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
int32_t genID = GetNextGenID();

Просмотреть файл

@ -686,7 +686,7 @@ void SkGpuDevice::drawPoints(const SkDraw& draw, SkCanvas::PointMode mode,
///////////////////////////////////////////////////////////////////////////////
void SkGpuDevice::drawRect(const SkDraw& draw, const SkRect& rect,
const SkPaint& paint) {
const SkPaint& paint) {
CHECK_FOR_NODRAW_ANNOTATION(paint);
CHECK_SHOULD_DRAW(draw);
@ -704,7 +704,7 @@ void SkGpuDevice::drawRect(const SkDraw& draw, const SkRect& rect,
usePath = true;
}
// until we aa rotated rects...
if (!usePath && paint.isAntiAlias() && !draw.fMatrix->rectStaysRect()) {
if (!usePath && paint.isAntiAlias() && !fContext->getMatrix().rectStaysRect()) {
usePath = true;
}
// small miter limit means right angles show bevel...
@ -773,10 +773,9 @@ inline bool shouldDrawBlurWithCPU(const SkRect& rect, SkScalar radius) {
return false;
}
bool drawWithGPUMaskFilter(GrContext* context, const SkPath& path,
SkMaskFilter* filter, const SkMatrix& matrix,
const SkRegion& clip, SkBounder* bounder,
GrPaint* grp, GrPathFill pathFillType) {
bool drawWithGPUMaskFilter(GrContext* context, const SkPath& devPath,
SkMaskFilter* filter, const SkRegion& clip,
SkBounder* bounder, GrPaint* grp, GrPathFill pathFillType) {
#ifdef SK_DISABLE_GPU_BLUR
return false;
#endif
@ -786,13 +785,13 @@ bool drawWithGPUMaskFilter(GrContext* context, const SkPath& path,
return false;
}
SkScalar radius = info.fIgnoreTransform ? info.fRadius
: matrix.mapRadius(info.fRadius);
: context->getMatrix().mapRadius(info.fRadius);
radius = SkMinScalar(radius, MAX_BLUR_RADIUS);
if (radius <= 0) {
return false;
}
SkRect srcRect = path.getBounds();
SkRect srcRect = devPath.getBounds();
if (shouldDrawBlurWithCPU(srcRect, radius)) {
return false;
}
@ -838,6 +837,8 @@ bool drawWithGPUMaskFilter(GrContext* context, const SkPath& path,
SkAutoTUnref<GrTexture> blurTexture;
GrMatrix origMatrix = context->getMatrix();
// We pass kPreserve here. We will replace the current matrix below.
GrContext::AutoMatrix avm(context, GrContext::AutoMatrix::kPreserve_InitialMatrix);
@ -846,8 +847,12 @@ bool drawWithGPUMaskFilter(GrContext* context, const SkPath& path,
GrContext::AutoClip ac(context, srcRect);
context->clear(NULL, 0);
GrPaint tempPaint;
// Draw hard shadow to pathTexture with path top-left at origin 0,0.
GrMatrix translate;
translate.setTranslate(offset.fX, offset.fY);
GrPaint tempPaint;
if (grp->isAntiAlias()) {
tempPaint.setAntiAlias(true);
// AA uses the "coverage" stages on GrDrawTarget. Coverage with a dst
@ -858,11 +863,8 @@ bool drawWithGPUMaskFilter(GrContext* context, const SkPath& path,
// use a zero dst coeff when dual source blending isn't available.
tempPaint.setBlendFunc(kOne_GrBlendCoeff, kISC_GrBlendCoeff);
}
// Draw hard shadow to pathTexture with path top-left at origin 0,0.
GrMatrix translate;
translate.setTranslate(offset.fX, offset.fY);
context->setMatrix(translate);
context->drawPath(tempPaint, path, pathFillType);
context->drawPath(tempPaint, devPath, pathFillType);
// switch to device coord drawing when going back to the main RT.
context->setIdentityMatrix();
@ -898,7 +900,7 @@ bool drawWithGPUMaskFilter(GrContext* context, const SkPath& path,
}
}
if (!grp->preConcatSamplerMatricesWithInverse(matrix)) {
if (!grp->preConcatSamplerMatricesWithInverse(origMatrix)) {
return false;
}
@ -916,20 +918,18 @@ bool drawWithGPUMaskFilter(GrContext* context, const SkPath& path,
return true;
}
bool drawWithMaskFilter(GrContext* context, const SkPath& path,
SkMaskFilter* filter, const SkMatrix& matrix,
const SkRegion& clip, SkBounder* bounder,
bool drawWithMaskFilter(GrContext* context, const SkPath& devPath,
SkMaskFilter* filter, const SkRegion& clip, SkBounder* bounder,
GrPaint* grp, SkPaint::Style style) {
SkMask srcM, dstM;
if (!SkDraw::DrawToMask(path, &clip.getBounds(), filter, &matrix, &srcM,
SkMask::kComputeBoundsAndRenderImage_CreateMode,
style)) {
if (!SkDraw::DrawToMask(devPath, &clip.getBounds(), filter, &context->getMatrix(), &srcM,
SkMask::kComputeBoundsAndRenderImage_CreateMode, style)) {
return false;
}
SkAutoMaskFreeImage autoSrc(srcM.fImage);
if (!filter->filterMask(&dstM, srcM, matrix, NULL)) {
if (!filter->filterMask(&dstM, srcM, context->getMatrix(), NULL)) {
return false;
}
// this will free-up dstM when we're done (allocated in filterMask())
@ -945,12 +945,12 @@ bool drawWithMaskFilter(GrContext* context, const SkPath& path,
// we now have a device-aligned 8bit mask in dstM, ready to be drawn using
// the current clip (and identity matrix) and grpaint settings
GrContext::AutoMatrix avm(context, GrMatrix::I());
if (!grp->preConcatSamplerMatricesWithInverse(matrix)) {
if (!grp->preConcatSamplerMatricesWithInverse(context->getMatrix())) {
return false;
}
GrContext::AutoMatrix avm(context, GrMatrix::I());
GrTextureDesc desc;
desc.fWidth = dstM.fBounds.width();
desc.fHeight = dstM.fBounds.height();
@ -1010,7 +1010,7 @@ void SkGpuDevice::drawPath(const SkDraw& draw, const SkPath& origSrcPath,
// can we cheat, and threat a thin stroke as a hairline w/ coverage
// if we can, we draw lots faster (raster device does this same test)
SkScalar hairlineCoverage;
if (SkDrawTreatAsHairline(paint, *draw.fMatrix, &hairlineCoverage)) {
if (SkDrawTreatAsHairline(paint, fContext->getMatrix(), &hairlineCoverage)) {
doFill = false;
grPaint.setCoverage(SkScalarRoundToInt(hairlineCoverage * grPaint.getCoverage()));
}
@ -1050,17 +1050,15 @@ void SkGpuDevice::drawPath(const SkDraw& draw, const SkPath& origSrcPath,
SkPath* devPathPtr = pathIsMutable ? pathPtr : &tmpPath;
// transform the path into device space
pathPtr->transform(*draw.fMatrix, devPathPtr);
pathPtr->transform(fContext->getMatrix(), devPathPtr);
GrPathFill pathFillType = doFill ?
skToGrFillType(devPathPtr->getFillType()) : kHairLine_GrPathFill;
if (!drawWithGPUMaskFilter(fContext, *devPathPtr, paint.getMaskFilter(),
*draw.fMatrix, *draw.fClip, draw.fBounder,
&grPaint, pathFillType)) {
*draw.fClip, draw.fBounder, &grPaint, pathFillType)) {
SkPaint::Style style = doFill ? SkPaint::kFill_Style :
SkPaint::kStroke_Style;
drawWithMaskFilter(fContext, *devPathPtr, paint.getMaskFilter(),
*draw.fMatrix, *draw.fClip, draw.fBounder,
&grPaint, style);
*draw.fClip, draw.fBounder, &grPaint, style);
}
return;
}
@ -1235,11 +1233,11 @@ void SkGpuDevice::drawBitmapCommon(const SkDraw& draw,
paintWithTexture.setShader(SkShader::CreateBitmapShader(*bitmapPtr,
SkShader::kClamp_TileMode, SkShader::kClamp_TileMode))->unref();
// Transform 'newM' needs to be concatenated to the draw matrix,
// Transform 'newM' needs to be concatenated to the current matrix,
// rather than transforming the primitive directly, so that 'newM' will
// also affect the behavior of the mask filter.
SkMatrix drawMatrix;
drawMatrix.setConcat(*draw.fMatrix, newM);
drawMatrix.setConcat(fContext->getMatrix(), newM);
SkDraw transformedDraw(draw);
transformedDraw.fMatrix = &drawMatrix;
@ -1258,16 +1256,15 @@ void SkGpuDevice::drawBitmapCommon(const SkDraw& draw,
if (!this->shouldTileBitmap(bitmap, params, srcRectPtr)) {
// take the simple case
this->internalDrawBitmap(draw, bitmap, srcRect, m, params, &grPaint);
this->internalDrawBitmap(bitmap, srcRect, m, params, &grPaint);
} else {
this->drawTiledBitmap(draw, bitmap, srcRect, m, params, &grPaint);
this->drawTiledBitmap(bitmap, srcRect, m, params, &grPaint);
}
}
// Break 'bitmap' into several tiles to draw it since it has already
// been determined to be too large to fit in VRAM
void SkGpuDevice::drawTiledBitmap(const SkDraw& draw,
const SkBitmap& bitmap,
void SkGpuDevice::drawTiledBitmap(const SkBitmap& bitmap,
const SkRect& srcRect,
const SkMatrix& m,
const GrTextureParams& params,
@ -1279,9 +1276,13 @@ void SkGpuDevice::drawTiledBitmap(const SkDraw& draw,
// compute clip bounds in local coordinates
SkRect clipRect;
{
clipRect.set(draw.fClip->getBounds());
const GrRenderTarget* rt = fContext->getRenderTarget();
clipRect.setWH(SkIntToScalar(rt->width()), SkIntToScalar(rt->height()));
if (!fContext->getClip()->fClipStack->intersectRectWithClip(&clipRect)) {
return;
}
SkMatrix matrix, inverse;
matrix.setConcat(*draw.fMatrix, m);
matrix.setConcat(fContext->getMatrix(), m);
if (!matrix.invert(&inverse)) {
return;
}
@ -1316,7 +1317,7 @@ void SkGpuDevice::drawTiledBitmap(const SkDraw& draw,
tmpM.preTranslate(SkIntToScalar(iTileR.fLeft),
SkIntToScalar(iTileR.fTop));
this->internalDrawBitmap(draw, tmpB, tileR, tmpM, params, grPaint);
this->internalDrawBitmap(tmpB, tileR, tmpM, params, grPaint);
}
}
}
@ -1372,8 +1373,7 @@ bool mayColorBleed(const SkRect& srcRect, const SkRect& transformedRect,
* internalDrawBitmap assumes that the specified bitmap will fit in a texture
* and that non-texture portion of the GrPaint has already been setup.
*/
void SkGpuDevice::internalDrawBitmap(const SkDraw& draw,
const SkBitmap& bitmap,
void SkGpuDevice::internalDrawBitmap(const SkBitmap& bitmap,
const SkRect& srcRect,
const SkMatrix& m,
const GrTextureParams& params,
@ -1411,11 +1411,11 @@ void SkGpuDevice::internalDrawBitmap(const SkDraw& draw,
// Need texture domain if drawing a sub rect.
needsTextureDomain = srcRect.width() < bitmap.width() ||
srcRect.height() < bitmap.height();
if (m.rectStaysRect() && draw.fMatrix->rectStaysRect()) {
if (m.rectStaysRect() && fContext->getMatrix().rectStaysRect()) {
// sampling is axis-aligned
GrRect transformedRect;
SkMatrix srcToDeviceMatrix(m);
srcToDeviceMatrix.postConcat(*draw.fMatrix);
srcToDeviceMatrix.postConcat(fContext->getMatrix());
srcToDeviceMatrix.mapRect(&transformedRect, srcRect);
if (hasAlignedSamples(srcRect, transformedRect)) {
@ -1802,7 +1802,7 @@ void SkGpuDevice::drawText(const SkDraw& draw, const void* text,
const SkPaint& paint) {
CHECK_SHOULD_DRAW(draw);
if (draw.fMatrix->hasPerspective()) {
if (fContext->getMatrix().hasPerspective()) {
// this guy will just call our drawPath()
draw.drawText((const char*)text, byteLength, x, y, paint);
} else {
@ -1829,7 +1829,7 @@ void SkGpuDevice::drawPosText(const SkDraw& draw, const void* text,
const SkPaint& paint) {
CHECK_SHOULD_DRAW(draw);
if (draw.fMatrix->hasPerspective()) {
if (fContext->getMatrix().hasPerspective()) {
// this guy will just call our drawPath()
draw.drawPosText((const char*)text, byteLength, pos, constY,
scalarsPerPos, paint);