本文整理汇总了C++中GrClip类的典型用法代码示例。如果您正苦于以下问题:C++ GrClip类的具体用法?C++ GrClip怎么用?C++ GrClip使用的例子?那么, 这里精选的类代码示例或许可以为您提供帮助。
在下文中一共展示了GrClip类的14个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: clipMaskPreamble
////////////////////////////////////////////////////////////////////////////////
// Shared preamble between gpu and SW-only AA clip mask creation paths.
// Handles caching, determination of clip mask bound & allocation (if needed)
// of the result texture
// Returns true if there is no more work to be done (i.e., we got a cache hit)
bool GrClipMaskManager::clipMaskPreamble(GrGpu* gpu,
const GrClip& clipIn,
GrTexture** result,
GrIRect *resultBounds) {
GrDrawState* origDrawState = gpu->drawState();
GrAssert(origDrawState->isClipState());
GrRenderTarget* rt = origDrawState->getRenderTarget();
GrAssert(NULL != rt);
GrRect rtRect;
rtRect.setLTRB(0, 0,
GrIntToScalar(rt->width()), GrIntToScalar(rt->height()));
// unlike the stencil path the alpha path is not bound to the size of the
// render target - determine the minimum size required for the mask
GrRect bounds;
if (clipIn.hasConservativeBounds()) {
bounds = clipIn.getConservativeBounds();
if (!bounds.intersect(rtRect)) {
// the mask will be empty in this case
GrAssert(false);
bounds.setEmpty();
}
} else {
// still locked to the size of the render target
bounds = rtRect;
}
GrIRect intBounds;
bounds.roundOut(&intBounds);
// need to outset a pixel since the standard bounding box computation
// path doesn't leave any room for antialiasing (esp. w.r.t. rects)
intBounds.outset(1, 1);
// TODO: make sure we don't outset if bounds are still 0,0 @ min
if (fAACache.canReuse(clipIn,
intBounds.width(),
intBounds.height())) {
*result = fAACache.getLastMask();
fAACache.getLastBound(resultBounds);
return true;
}
this->setupCache(clipIn, intBounds);
*resultBounds = intBounds;
return false;
}
示例2: drawClipShape
bool GrClipMaskManager::drawClipShape(GrGpu* gpu,
GrTexture* target,
const GrClip& clipIn,
int index) {
GrDrawState* drawState = gpu->drawState();
GrAssert(NULL != drawState);
drawState->setRenderTarget(target->asRenderTarget());
if (kRect_ClipType == clipIn.getElementType(index)) {
if (clipIn.getDoAA(index)) {
// convert the rect to a path for AA
SkPath temp;
temp.addRect(clipIn.getRect(index));
return this->drawPath(gpu, temp,
kEvenOdd_PathFill, clipIn.getDoAA(index));
} else {
gpu->drawSimpleRect(clipIn.getRect(index), NULL, 0);
}
} else {
return this->drawPath(gpu,
clipIn.getPath(index),
clipIn.getPathFill(index),
clipIn.getDoAA(index));
}
return true;
}
示例3: add_rect_to_clip
static void add_rect_to_clip(const GrClip& clip, const SkRect& devRect, GrClip* out) {
switch (clip.clipType()) {
case GrClip::kClipStack_ClipType: {
SkClipStack* stack = new SkClipStack;
*stack = *clip.clipStack();
// The stack is actually in clip space not device space.
SkRect clipRect = devRect;
SkPoint origin = { SkIntToScalar(clip.origin().fX), SkIntToScalar(clip.origin().fY) };
clipRect.offset(origin);
SkIRect iclipRect;
clipRect.roundOut(&iclipRect);
clipRect = SkRect::Make(iclipRect);
stack->clipDevRect(clipRect, SkRegion::kIntersect_Op, false);
out->setClipStack(stack, &clip.origin());
break;
}
case GrClip::kWideOpen_ClipType:
*out = GrClip(devRect);
break;
case GrClip::kIRect_ClipType: {
SkIRect intersect;
devRect.roundOut(&intersect);
if (intersect.intersect(clip.irect())) {
*out = GrClip(intersect);
} else {
*out = clip;
}
break;
}
}
}
示例4: stencilPath
void GrDrawTarget::stencilPath(const GrPipelineBuilder& pipelineBuilder,
GrDrawContext* drawContext,
const GrClip& clip,
const SkMatrix& viewMatrix,
const GrPath* path,
GrPathRendering::FillType fill) {
// TODO: extract portions of checkDraw that are relevant to path stenciling.
SkASSERT(path);
SkASSERT(this->caps()->shaderCaps()->pathRenderingSupport());
// Setup clip
GrAppliedClip appliedClip;
if (!clip.apply(fContext, pipelineBuilder, drawContext, nullptr, &appliedClip)) {
return;
}
// TODO: respect fClipBatchToBounds if we ever start computing bounds here.
// Coverage AA does not make sense when rendering to the stencil buffer. The caller should never
// attempt this in a situation that would require coverage AA.
SkASSERT(!appliedClip.getClipCoverageFragmentProcessor());
GrStencilAttachment* stencilAttachment = fResourceProvider->attachStencilAttachment(
drawContext->accessRenderTarget());
if (!stencilAttachment) {
SkDebugf("ERROR creating stencil attachment. Draw skipped.\n");
return;
}
GrBatch* batch = GrStencilPathBatch::Create(viewMatrix,
pipelineBuilder.isHWAntialias(),
fill,
appliedClip.hasStencilClip(),
stencilAttachment->bits(),
appliedClip.scissorState(),
drawContext->accessRenderTarget(),
path);
this->recordBatch(batch);
batch->unref();
}
示例5: addDrawOp
void SkInternalAtlasTextTarget::addDrawOp(const GrClip& clip, std::unique_ptr<GrAtlasTextOp> op) {
SkASSERT(clip.quickContains(SkRect::MakeIWH(fWidth, fHeight)));
// The SkAtlasTextRenderer currently only handles grayscale SDF glyphs.
if (op->maskType() != GrAtlasTextOp::kGrayscaleDistanceField_MaskType) {
return;
}
const GrCaps& caps = *this->context()->internal().grContext()->contextPriv().caps();
op->finalizeForTextTarget(fColor, caps);
int n = SkTMin(kMaxBatchLookBack, fOps.count());
for (int i = 0; i < n; ++i) {
GrAtlasTextOp* other = fOps.fromBack(i).get();
if (other->combineIfPossible(op.get(), caps) == GrOp::CombineResult::kMerged) {
fOpMemoryPool->release(std::move(op));
return;
}
if (GrRectsOverlap(op->bounds(), other->bounds())) {
break;
}
}
op->visitProxies([](GrSurfaceProxy*) {});
fOps.emplace_back(std::move(op));
}
示例6: createClipMask
////////////////////////////////////////////////////////////////////////////////
// sort out what kind of clip mask needs to be created: alpha, stencil,
// scissor, or entirely software
bool GrClipMaskManager::createClipMask(GrGpu* gpu,
const GrClip& clipIn,
ScissoringSettings* scissorSettings) {
GrAssert(scissorSettings);
scissorSettings->fEnableScissoring = false;
fClipMaskInStencil = false;
fClipMaskInAlpha = false;
GrDrawState* drawState = gpu->drawState();
if (!drawState->isClipState()) {
return true;
}
GrRenderTarget* rt = drawState->getRenderTarget();
// GrDrawTarget should have filtered this for us
GrAssert(NULL != rt);
#if GR_SW_CLIP
if (create_mask_in_sw()) {
// The clip geometry is complex enough that it will be more
// efficient to create it entirely in software
GrTexture* result = NULL;
GrIRect bound;
if (this->createSoftwareClipMask(gpu, clipIn, &result, &bound)) {
fClipMaskInAlpha = true;
setup_drawstate_aaclip(gpu, result, bound);
return true;
}
}
#endif
#if GR_AA_CLIP
// If MSAA is enabled use the (faster) stencil path for AA clipping
// otherwise the alpha clip mask is our only option
if (clipIn.requiresAA() && 0 == rt->numSamples()) {
// Since we are going to create a destination texture of the correct
// size for the mask (rather than being bound by the size of the
// render target) we aren't going to use scissoring like the stencil
// path does (see scissorSettings below)
GrTexture* result = NULL;
GrIRect bound;
if (this->createAlphaClipMask(gpu, clipIn, &result, &bound)) {
fClipMaskInAlpha = true;
setup_drawstate_aaclip(gpu, result, bound);
return true;
}
// if alpha clip mask creation fails fall through to the stencil
// buffer method
}
#endif // GR_AA_CLIP
GrRect bounds;
GrRect rtRect;
rtRect.setLTRB(0, 0,
GrIntToScalar(rt->width()), GrIntToScalar(rt->height()));
if (clipIn.hasConservativeBounds()) {
bounds = clipIn.getConservativeBounds();
if (!bounds.intersect(rtRect)) {
bounds.setEmpty();
}
} else {
bounds = rtRect;
}
bounds.roundOut(&scissorSettings->fScissorRect);
if (scissorSettings->fScissorRect.isEmpty()) {
scissorSettings->fScissorRect.setLTRB(0,0,0,0);
// TODO: I think we can do an early exit here - after refactoring try:
// set fEnableScissoring to true but leave fClipMaskInStencil false
// and return - everything is going to be scissored away anyway!
}
scissorSettings->fEnableScissoring = true;
// use the stencil clip if we can't represent the clip as a rectangle.
fClipMaskInStencil = !clipIn.isRect() && !clipIn.isEmpty() &&
!bounds.isEmpty();
if (fClipMaskInStencil) {
return this->createStencilClipMask(gpu, clipIn, bounds, scissorSettings);
}
return true;
}
示例7: asr
////////////////////////////////////////////////////////////////////////////////
// Create a 8-bit clip mask in alpha
bool GrClipMaskManager::createAlphaClipMask(GrGpu* gpu,
const GrClip& clipIn,
GrTexture** result,
GrIRect *resultBounds) {
if (this->clipMaskPreamble(gpu, clipIn, result, resultBounds)) {
return true;
}
GrTexture* accum = fAACache.getLastMask();
if (NULL == accum) {
fClipMaskInAlpha = false;
fAACache.reset();
return false;
}
GrDrawTarget::AutoStateRestore asr(gpu, GrDrawTarget::kReset_ASRInit);
GrDrawState* drawState = gpu->drawState();
GrDrawTarget::AutoGeometryPush agp(gpu);
int count = clipIn.getElementCount();
if (0 != resultBounds->fTop || 0 != resultBounds->fLeft) {
// if we were able to trim down the size of the mask we need to
// offset the paths & rects that will be used to compute it
GrMatrix m;
m.setTranslate(SkIntToScalar(-resultBounds->fLeft),
SkIntToScalar(-resultBounds->fTop));
drawState->setViewMatrix(m);
}
bool clearToInside;
SkRegion::Op startOp = SkRegion::kReplace_Op; // suppress warning
int start = process_initial_clip_elements(clipIn,
*resultBounds,
&clearToInside,
&startOp);
clear(gpu, accum, clearToInside ? 0xffffffff : 0x00000000);
GrAutoScratchTexture temp;
// walk through each clip element and perform its set op
for (int c = start; c < count; ++c) {
SkRegion::Op op = (c == start) ? startOp : clipIn.getOp(c);
if (SkRegion::kReplace_Op == op) {
// TODO: replace is actually a lot faster then intersection
// for this path - refactor the stencil path so it can handle
// replace ops and alter GrClip to allow them through
// clear the accumulator and draw the new object directly into it
clear(gpu, accum, 0x00000000);
setup_boolean_blendcoeffs(drawState, op);
this->drawClipShape(gpu, accum, clipIn, c);
} else if (SkRegion::kReverseDifference_Op == op ||
SkRegion::kIntersect_Op == op) {
// there is no point in intersecting a screen filling rectangle.
if (SkRegion::kIntersect_Op == op &&
kRect_ClipType == clipIn.getElementType(c) &&
contains(clipIn.getRect(c), *resultBounds)) {
continue;
}
getTemp(*resultBounds, &temp);
if (NULL == temp.texture()) {
fClipMaskInAlpha = false;
fAACache.reset();
return false;
}
// clear the temp target & draw into it
clear(gpu, temp.texture(), 0x00000000);
setup_boolean_blendcoeffs(drawState, SkRegion::kReplace_Op);
this->drawClipShape(gpu, temp.texture(), clipIn, c);
// TODO: rather than adding these two translations here
// compute the bounding box needed to render the texture
// into temp
if (0 != resultBounds->fTop || 0 != resultBounds->fLeft) {
GrMatrix m;
m.setTranslate(SkIntToScalar(resultBounds->fLeft),
SkIntToScalar(resultBounds->fTop));
drawState->preConcatViewMatrix(m);
}
// Now draw into the accumulator using the real operation
// and the temp buffer as a texture
setup_boolean_blendcoeffs(drawState, op);
//.........这里部分代码省略.........
示例8: draw_path_with_mask_filter
static void draw_path_with_mask_filter(GrContext* context,
GrDrawContext* drawContext,
const GrClip& clip,
GrPaint* paint,
const SkMatrix& viewMatrix,
const SkMaskFilter* maskFilter,
const GrStyle& style,
const SkPath* path,
bool pathIsMutable) {
SkASSERT(maskFilter);
SkIRect clipBounds;
clip.getConservativeBounds(drawContext->width(), drawContext->height(), &clipBounds);
SkTLazy<SkPath> tmpPath;
SkStrokeRec::InitStyle fillOrHairline;
// We just fully apply the style here.
if (style.applies()) {
if (!style.applyToPath(tmpPath.init(), &fillOrHairline, *path,
GrStyle::MatrixToScaleFactor(viewMatrix))) {
return;
}
pathIsMutable = true;
path = tmpPath.get();
} else if (style.isSimpleHairline()) {
fillOrHairline = SkStrokeRec::kHairline_InitStyle;
} else {
SkASSERT(style.isSimpleFill());
fillOrHairline = SkStrokeRec::kFill_InitStyle;
}
// transform the path into device space
if (!viewMatrix.isIdentity()) {
SkPath* result;
if (pathIsMutable) {
result = const_cast<SkPath*>(path);
} else {
if (!tmpPath.isValid()) {
tmpPath.init();
}
result = tmpPath.get();
}
path->transform(viewMatrix, result);
path = result;
result->setIsVolatile(true);
pathIsMutable = true;
}
SkRect maskRect;
if (maskFilter->canFilterMaskGPU(SkRRect::MakeRect(path->getBounds()),
clipBounds,
viewMatrix,
&maskRect)) {
// This mask will ultimately be drawn as a non-AA rect (see draw_mask).
// Non-AA rects have a bad habit of snapping arbitrarily. Integerize here
// so the mask draws in a reproducible manner.
SkIRect finalIRect;
maskRect.roundOut(&finalIRect);
if (clip_bounds_quick_reject(clipBounds, finalIRect)) {
// clipped out
return;
}
if (maskFilter->directFilterMaskGPU(context->textureProvider(),
drawContext,
paint,
clip,
viewMatrix,
SkStrokeRec(fillOrHairline),
*path)) {
// the mask filter was able to draw itself directly, so there's nothing
// left to do.
return;
}
sk_sp<GrTexture> mask(create_mask_GPU(context,
finalIRect,
*path,
fillOrHairline,
paint->isAntiAlias(),
drawContext->numColorSamples()));
if (mask) {
GrTexture* filtered;
if (maskFilter->filterMaskGPU(mask.get(), viewMatrix, finalIRect, &filtered, true)) {
// filterMaskGPU gives us ownership of a ref to the result
SkAutoTUnref<GrTexture> atu(filtered);
if (draw_mask(drawContext, clip, viewMatrix, finalIRect, paint, filtered)) {
// This path is completely drawn
return;
}
}
}
}
sw_draw_with_mask_filter(drawContext, context->textureProvider(),
clip, viewMatrix, *path,
maskFilter, clipBounds, paint, fillOrHairline);
}
示例9: drawBatch
void GrDrawTarget::drawBatch(const GrPipelineBuilder& pipelineBuilder,
GrDrawContext* drawContext,
const GrClip& clip,
GrDrawBatch* batch) {
// Setup clip
GrAppliedClip appliedClip;
if (!clip.apply(fContext, pipelineBuilder, drawContext, &batch->bounds(), &appliedClip)) {
return;
}
// TODO: this is the only remaining usage of the AutoRestoreFragmentProcessorState - remove it
GrPipelineBuilder::AutoRestoreFragmentProcessorState arfps;
if (appliedClip.getClipCoverageFragmentProcessor()) {
arfps.set(&pipelineBuilder);
arfps.addCoverageFragmentProcessor(sk_ref_sp(appliedClip.getClipCoverageFragmentProcessor()));
}
GrPipeline::CreateArgs args;
args.fPipelineBuilder = &pipelineBuilder;
args.fDrawContext = drawContext;
args.fCaps = this->caps();
args.fScissor = &appliedClip.scissorState();
args.fHasStencilClip = appliedClip.hasStencilClip();
if (pipelineBuilder.hasUserStencilSettings() || appliedClip.hasStencilClip()) {
if (!fResourceProvider->attachStencilAttachment(drawContext->accessRenderTarget())) {
SkDebugf("ERROR creating stencil attachment. Draw skipped.\n");
return;
}
}
batch->getPipelineOptimizations(&args.fOpts);
GrScissorState finalScissor;
if (args.fOpts.fOverrides.fUsePLSDstRead || fClipBatchToBounds) {
GrGLIRect viewport;
viewport.fLeft = 0;
viewport.fBottom = 0;
viewport.fWidth = drawContext->width();
viewport.fHeight = drawContext->height();
SkIRect ibounds;
ibounds.fLeft = SkTPin(SkScalarFloorToInt(batch->bounds().fLeft), viewport.fLeft,
viewport.fWidth);
ibounds.fTop = SkTPin(SkScalarFloorToInt(batch->bounds().fTop), viewport.fBottom,
viewport.fHeight);
ibounds.fRight = SkTPin(SkScalarCeilToInt(batch->bounds().fRight), viewport.fLeft,
viewport.fWidth);
ibounds.fBottom = SkTPin(SkScalarCeilToInt(batch->bounds().fBottom), viewport.fBottom,
viewport.fHeight);
if (appliedClip.scissorState().enabled()) {
const SkIRect& scissorRect = appliedClip.scissorState().rect();
if (!ibounds.intersect(scissorRect)) {
return;
}
}
finalScissor.set(ibounds);
args.fScissor = &finalScissor;
}
args.fOpts.fColorPOI.completeCalculations(
sk_sp_address_as_pointer_address(pipelineBuilder.fColorFragmentProcessors.begin()),
pipelineBuilder.numColorFragmentProcessors());
args.fOpts.fCoveragePOI.completeCalculations(
sk_sp_address_as_pointer_address(pipelineBuilder.fCoverageFragmentProcessors.begin()),
pipelineBuilder.numCoverageFragmentProcessors());
if (!this->setupDstReadIfNecessary(pipelineBuilder, drawContext->accessRenderTarget(),
clip, args.fOpts,
&args.fDstTexture, batch->bounds())) {
return;
}
if (!batch->installPipeline(args)) {
return;
}
#ifdef ENABLE_MDB
SkASSERT(fRenderTarget);
batch->pipeline()->addDependenciesTo(fRenderTarget);
#endif
this->recordBatch(batch);
}
示例10: setupDstReadIfNecessary
bool GrDrawTarget::setupDstReadIfNecessary(const GrPipelineBuilder& pipelineBuilder,
GrRenderTarget* rt,
const GrClip& clip,
const GrPipelineOptimizations& optimizations,
GrXferProcessor::DstTexture* dstTexture,
const SkRect& batchBounds) {
SkRect bounds = batchBounds;
bounds.outset(0.5f, 0.5f);
if (!pipelineBuilder.willXPNeedDstTexture(*this->caps(), optimizations)) {
return true;
}
if (this->caps()->textureBarrierSupport()) {
if (GrTexture* rtTex = rt->asTexture()) {
// The render target is a texture, so we can read from it directly in the shader. The XP
// will be responsible to detect this situation and request a texture barrier.
dstTexture->setTexture(rtTex);
dstTexture->setOffset(0, 0);
return true;
}
}
SkIRect copyRect;
clip.getConservativeBounds(rt->width(), rt->height(), ©Rect);
SkIRect drawIBounds;
bounds.roundOut(&drawIBounds);
if (!copyRect.intersect(drawIBounds)) {
#ifdef SK_DEBUG
GrCapsDebugf(this->caps(), "Missed an early reject. "
"Bailing on draw from setupDstReadIfNecessary.\n");
#endif
return false;
}
// MSAA consideration: When there is support for reading MSAA samples in the shader we could
// have per-sample dst values by making the copy multisampled.
GrSurfaceDesc desc;
if (!fGpu->initCopySurfaceDstDesc(rt, &desc)) {
desc.fOrigin = kDefault_GrSurfaceOrigin;
desc.fFlags = kRenderTarget_GrSurfaceFlag;
desc.fConfig = rt->config();
}
desc.fWidth = copyRect.width();
desc.fHeight = copyRect.height();
static const uint32_t kFlags = 0;
SkAutoTUnref<GrTexture> copy(fResourceProvider->createApproxTexture(desc, kFlags));
if (!copy) {
SkDebugf("Failed to create temporary copy of destination texture.\n");
return false;
}
SkIPoint dstPoint = {0, 0};
this->copySurface(copy, rt, copyRect, dstPoint);
dstTexture->setTexture(copy);
dstTexture->setOffset(copyRect.fLeft, copyRect.fTop);
return true;
}
示例11: draw_path_with_mask_filter
static void draw_path_with_mask_filter(GrContext* context,
GrDrawContext* drawContext,
const GrClip& clip,
GrPaint* paint,
const SkMatrix& viewMatrix,
const SkMaskFilter* maskFilter,
const SkPathEffect* pathEffect,
const GrStrokeInfo& origStrokeInfo,
SkPath* pathPtr,
bool pathIsMutable) {
SkASSERT(maskFilter);
SkIRect clipBounds;
clip.getConservativeBounds(drawContext->width(), drawContext->height(), &clipBounds);
SkTLazy<SkPath> tmpPath;
GrStrokeInfo strokeInfo(origStrokeInfo);
static const SkRect* cullRect = nullptr; // TODO: what is our bounds?
SkASSERT(strokeInfo.isDashed() || !pathEffect);
if (!strokeInfo.isHairlineStyle()) {
SkPath* strokedPath = pathIsMutable ? pathPtr : tmpPath.init();
if (strokeInfo.isDashed()) {
if (pathEffect->filterPath(strokedPath, *pathPtr, &strokeInfo, cullRect)) {
pathPtr = strokedPath;
pathPtr->setIsVolatile(true);
pathIsMutable = true;
}
strokeInfo.removeDash();
}
if (strokeInfo.applyToPath(strokedPath, *pathPtr)) {
// Apply the stroke to the path if there is one
pathPtr = strokedPath;
pathPtr->setIsVolatile(true);
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 (maskFilter->canFilterMaskGPU(SkRRect::MakeRect(devPathPtr->getBounds()),
clipBounds,
viewMatrix,
&maskRect)) {
SkIRect finalIRect;
maskRect.roundOut(&finalIRect);
if (clip_bounds_quick_reject(clipBounds, finalIRect)) {
// clipped out
return;
}
if (maskFilter->directFilterMaskGPU(context->textureProvider(),
drawContext,
paint,
clip,
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(context,
&maskRect,
*devPathPtr,
strokeInfo,
paint->isAntiAlias(),
drawContext->numColorSamples()));
if (mask) {
GrTexture* filtered;
if (maskFilter->filterMaskGPU(mask, viewMatrix, maskRect, &filtered, true)) {
// filterMaskGPU gives us ownership of a ref to the result
SkAutoTUnref<GrTexture> atu(filtered);
if (draw_mask(drawContext, clip, viewMatrix, maskRect, paint, 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;
sw_draw_with_mask_filter(drawContext, context->textureProvider(),
clip, viewMatrix, *devPathPtr,
maskFilter, clipBounds, paint, style);
//.........这里部分代码省略.........
示例12: flush
void GrTextBlob::flush(GrTextTarget* target, const SkSurfaceProps& props,
const GrDistanceFieldAdjustTable* distanceAdjustTable,
const SkPaint& paint, GrColor filteredColor, const GrClip& clip,
const SkMatrix& viewMatrix, SkScalar x, SkScalar y) {
// GrTextBlob::makeOp only takes uint16_t values for run and subRun indices.
// Encountering something larger than this is highly unlikely, so we'll just not draw it.
int lastRun = SkTMin(fRunCount, (1 << 16)) - 1;
// For each run in the GrTextBlob we're going to churn through all the glyphs.
// Each run is broken into a path part and a Mask / DFT / ARGB part.
for (int runIndex = 0; runIndex <= lastRun; runIndex++) {
Run& run = fRuns[runIndex];
// first flush any path glyphs
if (run.fPathGlyphs.count()) {
SkPaint runPaint{paint};
runPaint.setFlags((runPaint.getFlags() & ~Run::kPaintFlagsMask) | run.fPaintFlags);
for (int i = 0; i < run.fPathGlyphs.count(); i++) {
GrTextBlob::Run::PathGlyph& pathGlyph = run.fPathGlyphs[i];
SkMatrix ctm;
const SkPath* path = &pathGlyph.fPath;
// TmpPath must be in the same scope as GrShape shape below.
SkTLazy<SkPath> tmpPath;
// The glyph positions and glyph outlines are either in device space or in source
// space based on fPreTransformed.
if (!pathGlyph.fPreTransformed) {
// Positions and outlines are in source space.
ctm = viewMatrix;
SkMatrix pathMatrix = SkMatrix::MakeScale(pathGlyph.fScale, pathGlyph.fScale);
// The origin for the blob may have changed, so figure out the delta.
SkVector originShift = SkPoint{x, y} - SkPoint{fInitialX, fInitialY};
// Shift the original glyph location in source space to the position of the new
// blob.
pathMatrix.postTranslate(originShift.x() + pathGlyph.fX,
originShift.y() + pathGlyph.fY);
// If there are shaders, blurs or styles, the path must be scaled into source
// space independently of the CTM. This allows the CTM to be correct for the
// different effects.
GrStyle style(runPaint);
bool scalePath = runPaint.getShader()
|| style.applies()
|| runPaint.getMaskFilter();
if (!scalePath) {
// Scale can be applied to CTM -- no effects.
ctm.preConcat(pathMatrix);
} else {
// Scale the outline into source space.
// Transform the path form the normalized outline to source space. This
// way the CTM will remain the same so it can be used by the effects.
SkPath* sourceOutline = tmpPath.init();
path->transform(pathMatrix, sourceOutline);
sourceOutline->setIsVolatile(true);
path = sourceOutline;
}
} else {
// Positions and outlines are in device space.
SkPoint originalOrigin = {fInitialX, fInitialY};
fInitialViewMatrix.mapPoints(&originalOrigin, 1);
SkPoint newOrigin = {x, y};
viewMatrix.mapPoints(&newOrigin, 1);
// The origin shift in device space.
SkPoint originShift = newOrigin - originalOrigin;
// Shift the original glyph location in device space to the position of the
// new blob.
ctm = SkMatrix::MakeTrans(originShift.x() + pathGlyph.fX,
originShift.y() + pathGlyph.fY);
}
// TODO: we are losing the mutability of the path here
GrShape shape(*path, paint);
target->drawShape(clip, runPaint, ctm, shape);
}
}
// then flush each subrun, if any
if (!run.fInitialized) {
continue;
}
int lastSubRun = SkTMin(run.fSubRunInfo.count(), 1 << 16) - 1;
for (int subRun = 0; subRun <= lastSubRun; subRun++) {
//.........这里部分代码省略.........
示例13: useSWOnlyPath
/*
* This method traverses the clip stack to see if the GrSoftwarePathRenderer
* will be used on any element. If so, it returns true to indicate that the
* entire clip should be rendered in SW and then uploaded en masse to the gpu.
*/
bool GrClipMaskManager::useSWOnlyPath(GrGpu* gpu, const GrClip& clipIn) {
if (!clipIn.requiresAA()) {
// The stencil buffer can handle this case
return false;
}
// TODO: generalize this test so that when
// a clip gets complex enough it can just be done in SW regardless
// of whether it would invoke the GrSoftwarePathRenderer.
bool useSW = false;
for (int i = 0; i < clipIn.getElementCount(); ++i) {
if (SkRegion::kReplace_Op == clipIn.getOp(i)) {
// Everything before a replace op can be ignored so start
// afresh w.r.t. determining if any element uses the SW path
useSW = false;
}
if (!clipIn.getDoAA(i)) {
// non-anti-aliased rects and paths can always be drawn either
// directly or by the GrDefaultPathRenderer
continue;
}
if (kRect_ClipType == clipIn.getElementType(i)) {
// Antialiased rects are converted to paths and then drawn with
// kEvenOdd_PathFill.
if (!GrAAConvexPathRenderer::staticCanDrawPath(
true, // always convex
kEvenOdd_PathFill,
gpu,
true)) { // anti-aliased
// if the GrAAConvexPathRenderer can't render this rect (due
// to lack of derivative support in the shaders) then
// the GrSoftwarePathRenderer will be used
useSW = true;
}
continue;
}
// only paths need to be considered in the rest of the loop body
if (GrAAHairLinePathRenderer::staticCanDrawPath(clipIn.getPath(i),
clipIn.getPathFill(i),
gpu,
clipIn.getDoAA(i))) {
// the hair line path renderer can handle this one
continue;
}
if (GrAAConvexPathRenderer::staticCanDrawPath(
clipIn.getPath(i).isConvex(),
clipIn.getPathFill(i),
gpu,
clipIn.getDoAA(i))) {
// the convex path renderer can handle this one
continue;
}
// otherwise the GrSoftwarePathRenderer is going to be invoked
useSW = true;
}
return useSW;
}
示例14: createClipMask
////////////////////////////////////////////////////////////////////////////////
// sort out what kind of clip mask needs to be created: alpha, stencil,
// scissor, or entirely software
bool GrClipMaskManager::createClipMask(GrGpu* gpu,
const GrClip& clipIn,
ScissoringSettings* scissorSettings) {
GrAssert(scissorSettings);
scissorSettings->fEnableScissoring = false;
fClipMaskInStencil = false;
fClipMaskInAlpha = false;
GrDrawState* drawState = gpu->drawState();
if (!drawState->isClipState()) {
return true;
}
GrRenderTarget* rt = drawState->getRenderTarget();
// GrDrawTarget should have filtered this for us
GrAssert(NULL != rt);
#if GR_SW_CLIP
// If MSAA is enabled we can do everything in the stencil buffer.
// Otherwise check if we should just create the entire clip mask
// in software (this will only happen if the clip mask is anti-aliased
// and too complex for the gpu to handle in its entirety)
if (0 == rt->numSamples() && useSWOnlyPath(gpu, clipIn)) {
// The clip geometry is complex enough that it will be more
// efficient to create it entirely in software
GrTexture* result = NULL;
GrIRect bound;
if (this->createSoftwareClipMask(gpu, clipIn, &result, &bound)) {
fClipMaskInAlpha = true;
setup_drawstate_aaclip(gpu, result, bound);
return true;
}
// if SW clip mask creation fails fall through to the other
// two possible methods (bottoming out at stencil clipping)
}
#endif // GR_SW_CLIP
#if GR_AA_CLIP
// If MSAA is enabled use the (faster) stencil path for AA clipping
// otherwise the alpha clip mask is our only option
if (0 == rt->numSamples() && clipIn.requiresAA()) {
// Since we are going to create a destination texture of the correct
// size for the mask (rather than being bound by the size of the
// render target) we aren't going to use scissoring like the stencil
// path does (see scissorSettings below)
GrTexture* result = NULL;
GrIRect bound;
if (this->createAlphaClipMask(gpu, clipIn, &result, &bound)) {
fClipMaskInAlpha = true;
setup_drawstate_aaclip(gpu, result, bound);
return true;
}
// if alpha clip mask creation fails fall through to the stencil
// buffer method
}
#endif // GR_AA_CLIP
// Either a hard (stencil buffer) clip was explicitly requested or
// an antialiased clip couldn't be created. In either case, free up
// the texture in the antialiased mask cache.
// TODO: this may require more investigation. Ganesh performs a lot of
// utility draws (e.g., clears, InOrderDrawBuffer playbacks) that hit
// the stencil buffer path. These may be "incorrectly" clearing the
// AA cache.
fAACache.reset();
GrRect bounds;
GrRect rtRect;
rtRect.setLTRB(0, 0,
GrIntToScalar(rt->width()), GrIntToScalar(rt->height()));
if (clipIn.hasConservativeBounds()) {
bounds = clipIn.getConservativeBounds();
if (!bounds.intersect(rtRect)) {
bounds.setEmpty();
}
} else {
bounds = rtRect;
}
bounds.roundOut(&scissorSettings->fScissorRect);
if (scissorSettings->fScissorRect.isEmpty()) {
scissorSettings->fScissorRect.setLTRB(0,0,0,0);
// TODO: I think we can do an early exit here - after refactoring try:
// set fEnableScissoring to true but leave fClipMaskInStencil false
// and return - everything is going to be scissored away anyway!
}
scissorSettings->fEnableScissoring = true;
// use the stencil clip if we can't represent the clip as a rectangle.
fClipMaskInStencil = !clipIn.isRect() && !clipIn.isEmpty() &&
//.........这里部分代码省略.........