GrSoftwarePathRenderer.cpp revision 366f1c6a09f63c76e78145cb08028f66062f31fd
1f4c2c527dd3cab979621fdfbc07eb22fee103472robertphillips@google.com 2f4c2c527dd3cab979621fdfbc07eb22fee103472robertphillips@google.com/* 3f4c2c527dd3cab979621fdfbc07eb22fee103472robertphillips@google.com * Copyright 2012 Google Inc. 4f4c2c527dd3cab979621fdfbc07eb22fee103472robertphillips@google.com * 5f4c2c527dd3cab979621fdfbc07eb22fee103472robertphillips@google.com * Use of this source code is governed by a BSD-style license that can be 6f4c2c527dd3cab979621fdfbc07eb22fee103472robertphillips@google.com * found in the LICENSE file. 7f4c2c527dd3cab979621fdfbc07eb22fee103472robertphillips@google.com */ 8f4c2c527dd3cab979621fdfbc07eb22fee103472robertphillips@google.com 9f4c2c527dd3cab979621fdfbc07eb22fee103472robertphillips@google.com#include "GrSoftwarePathRenderer.h" 10ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com#include "GrContext.h" 1158b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com#include "GrSWMaskHelper.h" 12f4c2c527dd3cab979621fdfbc07eb22fee103472robertphillips@google.com 13ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com//////////////////////////////////////////////////////////////////////////////// 14f4c2c527dd3cab979621fdfbc07eb22fee103472robertphillips@google.combool GrSoftwarePathRenderer::canDrawPath(const SkPath& path, 15f4c2c527dd3cab979621fdfbc07eb22fee103472robertphillips@google.com GrPathFill fill, 16f4c2c527dd3cab979621fdfbc07eb22fee103472robertphillips@google.com const GrDrawTarget* target, 17f4c2c527dd3cab979621fdfbc07eb22fee103472robertphillips@google.com bool antiAlias) const { 18ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com if (!antiAlias || NULL == fContext) { 19ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com // TODO: We could allow the SW path to also handle non-AA paths but 20ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com // this would mean that GrDefaultPathRenderer would never be called 21ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com // (since it appears after the SW renderer in the path renderer 22ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com // chain). Some testing would need to be done r.e. performance 23ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com // and consistency of the resulting images before removing 24ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com // the "!antiAlias" clause from the above test 25f4c2c527dd3cab979621fdfbc07eb22fee103472robertphillips@google.com return false; 26f4c2c527dd3cab979621fdfbc07eb22fee103472robertphillips@google.com } 27f4c2c527dd3cab979621fdfbc07eb22fee103472robertphillips@google.com 28ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com return true; 29ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com} 30ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com 31ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.comnamespace { 32ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com 33ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com//////////////////////////////////////////////////////////////////////////////// 34ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com// gets device coord bounds of path (not considering the fill) and clip. The 35ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com// path bounds will be a subset of the clip bounds. returns false if 36ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com// path bounds would be empty. 37ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.combool get_path_and_clip_bounds(const GrDrawTarget* target, 38ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com const SkPath& path, 39366f1c6a09f63c76e78145cb08028f66062f31fdrobertphillips@google.com const GrMatrix& matrix, 40ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com GrIRect* pathBounds, 41ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com GrIRect* clipBounds) { 42ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com // compute bounds as intersection of rt size, clip, and path 43ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com const GrRenderTarget* rt = target->getDrawState().getRenderTarget(); 44ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com if (NULL == rt) { 45ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com return false; 46ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com } 47ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com *pathBounds = GrIRect::MakeWH(rt->width(), rt->height()); 48ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com const GrClip& clip = target->getClip(); 49ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com if (clip.hasConservativeBounds()) { 50ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com clip.getConservativeBounds().roundOut(clipBounds); 51ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com if (!pathBounds->intersect(*clipBounds)) { 52ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com return false; 53ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com } 54ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com } else { 55ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com // pathBounds is currently the rt extent, set clip bounds to that rect. 56ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com *clipBounds = *pathBounds; 57ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com } 58366f1c6a09f63c76e78145cb08028f66062f31fdrobertphillips@google.com if (!path.getBounds().isEmpty()) { 59366f1c6a09f63c76e78145cb08028f66062f31fdrobertphillips@google.com GrRect pathSBounds; 60366f1c6a09f63c76e78145cb08028f66062f31fdrobertphillips@google.com matrix.mapRect(&pathSBounds, path.getBounds()); 61ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com GrIRect pathIBounds; 62ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com pathSBounds.roundOut(&pathIBounds); 63ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com if (!pathBounds->intersect(pathIBounds)) { 64276c1fabc22d4980c2ed8fe879f6510289b87cdebsalomon@google.com // set the correct path bounds, as this would be used later. 65276c1fabc22d4980c2ed8fe879f6510289b87cdebsalomon@google.com *pathBounds = pathIBounds; 66ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com return false; 67ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com } 68ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com } else { 69276c1fabc22d4980c2ed8fe879f6510289b87cdebsalomon@google.com *pathBounds = GrIRect::EmptyIRect(); 70ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com return false; 71ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com } 72ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com return true; 73ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com} 74ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com 75ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com//////////////////////////////////////////////////////////////////////////////// 76ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.comvoid draw_around_inv_path(GrDrawTarget* target, 77ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com GrDrawState::StageMask stageMask, 78ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com const GrIRect& clipBounds, 79ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com const GrIRect& pathBounds) { 80ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com GrDrawTarget::AutoDeviceCoordDraw adcd(target, stageMask); 81ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com GrRect rect; 82ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com if (clipBounds.fTop < pathBounds.fTop) { 83ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com rect.iset(clipBounds.fLeft, clipBounds.fTop, 84ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com clipBounds.fRight, pathBounds.fTop); 85ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com target->drawSimpleRect(rect, NULL, stageMask); 86ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com } 87ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com if (clipBounds.fLeft < pathBounds.fLeft) { 88ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com rect.iset(clipBounds.fLeft, pathBounds.fTop, 89ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com pathBounds.fLeft, pathBounds.fBottom); 90ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com target->drawSimpleRect(rect, NULL, stageMask); 91ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com } 92ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com if (clipBounds.fRight > pathBounds.fRight) { 93ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com rect.iset(pathBounds.fRight, pathBounds.fTop, 94ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com clipBounds.fRight, pathBounds.fBottom); 95ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com target->drawSimpleRect(rect, NULL, stageMask); 96ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com } 97ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com if (clipBounds.fBottom > pathBounds.fBottom) { 98ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com rect.iset(clipBounds.fLeft, pathBounds.fBottom, 99ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com clipBounds.fRight, clipBounds.fBottom); 100ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com target->drawSimpleRect(rect, NULL, stageMask); 101ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com } 102f4c2c527dd3cab979621fdfbc07eb22fee103472robertphillips@google.com} 103f4c2c527dd3cab979621fdfbc07eb22fee103472robertphillips@google.com 104ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com} 105ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com 106ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com//////////////////////////////////////////////////////////////////////////////// 107ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com// return true on success; false on failure 108f4c2c527dd3cab979621fdfbc07eb22fee103472robertphillips@google.combool GrSoftwarePathRenderer::onDrawPath(const SkPath& path, 109f4c2c527dd3cab979621fdfbc07eb22fee103472robertphillips@google.com GrPathFill fill, 110f4c2c527dd3cab979621fdfbc07eb22fee103472robertphillips@google.com const GrVec* translate, 111f4c2c527dd3cab979621fdfbc07eb22fee103472robertphillips@google.com GrDrawTarget* target, 112f4c2c527dd3cab979621fdfbc07eb22fee103472robertphillips@google.com GrDrawState::StageMask stageMask, 113f4c2c527dd3cab979621fdfbc07eb22fee103472robertphillips@google.com bool antiAlias) { 114f4c2c527dd3cab979621fdfbc07eb22fee103472robertphillips@google.com 115ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com if (NULL == fContext) { 116ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com return false; 117ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com } 118ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com 119366f1c6a09f63c76e78145cb08028f66062f31fdrobertphillips@google.com GrDrawState* drawState = target->drawState(); 120366f1c6a09f63c76e78145cb08028f66062f31fdrobertphillips@google.com 121366f1c6a09f63c76e78145cb08028f66062f31fdrobertphillips@google.com GrMatrix vm = drawState->getViewMatrix(); 122366f1c6a09f63c76e78145cb08028f66062f31fdrobertphillips@google.com if (NULL != translate) { 123366f1c6a09f63c76e78145cb08028f66062f31fdrobertphillips@google.com vm.postTranslate(translate->fX, translate->fY); 124366f1c6a09f63c76e78145cb08028f66062f31fdrobertphillips@google.com } 125366f1c6a09f63c76e78145cb08028f66062f31fdrobertphillips@google.com 126ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com GrAutoScratchTexture ast; 127ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com GrIRect pathBounds, clipBounds; 128366f1c6a09f63c76e78145cb08028f66062f31fdrobertphillips@google.com if (!get_path_and_clip_bounds(target, path, vm, 129ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com &pathBounds, &clipBounds)) { 130276c1fabc22d4980c2ed8fe879f6510289b87cdebsalomon@google.com if (GrIsFillInverted(fill)) { 131276c1fabc22d4980c2ed8fe879f6510289b87cdebsalomon@google.com draw_around_inv_path(target, stageMask, 132276c1fabc22d4980c2ed8fe879f6510289b87cdebsalomon@google.com clipBounds, pathBounds); 133276c1fabc22d4980c2ed8fe879f6510289b87cdebsalomon@google.com } 134276c1fabc22d4980c2ed8fe879f6510289b87cdebsalomon@google.com return true; 135ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com } 136366f1c6a09f63c76e78145cb08028f66062f31fdrobertphillips@google.com 137366f1c6a09f63c76e78145cb08028f66062f31fdrobertphillips@google.com if (GrSWMaskHelper::DrawToTexture(fContext, path, pathBounds, fill, 138366f1c6a09f63c76e78145cb08028f66062f31fdrobertphillips@google.com &ast, antiAlias, &vm)) { 13915c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com SkAutoTUnref<GrTexture> texture(ast.detach()); 140ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com GrAssert(NULL != texture); 141ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com GrDrawTarget::AutoDeviceCoordDraw adcd(target, stageMask); 142ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com enum { 1437ff2e371859982cad995f9d2a8cbdbb8601fc780robertphillips@google.com // the SW path renderer shares this stage with glyph 1447ff2e371859982cad995f9d2a8cbdbb8601fc780robertphillips@google.com // rendering (kGlyphMaskStage in GrBatchedTextContext) 1457ff2e371859982cad995f9d2a8cbdbb8601fc780robertphillips@google.com kPathMaskStage = GrPaint::kTotalStages, 146ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com }; 147366f1c6a09f63c76e78145cb08028f66062f31fdrobertphillips@google.com GrAssert(NULL == drawState->getTexture(kPathMaskStage)); 148366f1c6a09f63c76e78145cb08028f66062f31fdrobertphillips@google.com drawState->setTexture(kPathMaskStage, texture); 149366f1c6a09f63c76e78145cb08028f66062f31fdrobertphillips@google.com drawState->sampler(kPathMaskStage)->reset(); 150ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com GrScalar w = GrIntToScalar(pathBounds.width()); 151ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com GrScalar h = GrIntToScalar(pathBounds.height()); 152ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com GrRect maskRect = GrRect::MakeWH(w / texture->width(), 153ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com h / texture->height()); 15415c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com 155ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com const GrRect* srcRects[GrDrawState::kNumStages] = {NULL}; 156ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com srcRects[kPathMaskStage] = &maskRect; 157ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com stageMask |= 1 << kPathMaskStage; 158ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com GrRect dstRect = GrRect::MakeLTRB( 159ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com SK_Scalar1* pathBounds.fLeft, 160ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com SK_Scalar1* pathBounds.fTop, 161ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com SK_Scalar1* pathBounds.fRight, 162ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com SK_Scalar1* pathBounds.fBottom); 163ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com target->drawRect(dstRect, NULL, stageMask, srcRects, NULL); 164366f1c6a09f63c76e78145cb08028f66062f31fdrobertphillips@google.com drawState->setTexture(kPathMaskStage, NULL); 165ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com if (GrIsFillInverted(fill)) { 166ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com draw_around_inv_path(target, stageMask, 167ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com clipBounds, pathBounds); 168ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com } 169ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com return true; 170ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com } 171ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com 172f4c2c527dd3cab979621fdfbc07eb22fee103472robertphillips@google.com return false; 173f4c2c527dd3cab979621fdfbc07eb22fee103472robertphillips@google.com} 174