/*
* Copyright 2015 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "GrDrawPathOp.h"
#include "GrAppliedClip.h"
#include "GrMemoryPool.h"
#include "GrRecordingContext.h"
#include "GrRecordingContextPriv.h"
#include "GrRenderTargetContext.h"
#include "GrRenderTargetPriv.h"
#include "SkTemplates.h"
static constexpr GrUserStencilSettings kCoverPass{
GrUserStencilSettings::StaticInit<
0x0000,
GrUserStencilTest::kNotEqual,
0xffff,
GrUserStencilOp::kZero,
GrUserStencilOp::kKeep,
0xffff>()
};
GrDrawPathOpBase::GrDrawPathOpBase(uint32_t classID, const SkMatrix& viewMatrix, GrPaint&& paint,
GrPathRendering::FillType fill, GrAAType aaType)
: INHERITED(classID)
, fViewMatrix(viewMatrix)
, fInputColor(paint.getColor4f())
, fFillType(fill)
, fAAType(aaType)
, fProcessorSet(std::move(paint)) {}
#ifdef SK_DEBUG
SkString GrDrawPathOp::dumpInfo() const {
SkString string;
string.printf("PATH: 0x%p", fPath.get());
string.append(INHERITED::dumpInfo());
return string;
}
#endif
GrPipeline::InitArgs GrDrawPathOpBase::pipelineInitArgs(const GrOpFlushState& state) {
GrPipeline::InitArgs args;
if (GrAATypeIsHW(fAAType)) {
args.fFlags |= GrPipeline::kHWAntialias_Flag;
}
args.fUserStencil = &kCoverPass;
args.fCaps = &state.caps();
args.fResourceProvider = state.resourceProvider();
args.fDstProxy = state.drawOpArgs().fDstProxy;
return args;
}
const GrProcessorSet::Analysis& GrDrawPathOpBase::doProcessorAnalysis(
const GrCaps& caps, const GrAppliedClip* clip, GrFSAAType fsaaType,
GrClampType clampType) {
fAnalysis = fProcessorSet.finalize(
fInputColor, GrProcessorAnalysisCoverage::kNone, clip, &kCoverPass, fsaaType, caps,
clampType, &fInputColor);
return fAnalysis;
}
//////////////////////////////////////////////////////////////////////////////
void init_stencil_pass_settings(const GrOpFlushState& flushState,
GrPathRendering::FillType fillType, GrStencilSettings* stencil) {
const GrAppliedClip* appliedClip = flushState.drawOpArgs().fAppliedClip;
bool stencilClip = appliedClip && appliedClip->hasStencilClip();
stencil->reset(GrPathRendering::GetStencilPassSettings(fillType), stencilClip,
flushState.drawOpArgs().renderTarget()->renderTargetPriv().numStencilBits());
}
//////////////////////////////////////////////////////////////////////////////
std::unique_ptr<GrDrawOp> GrDrawPathOp::Make(GrRecordingContext* context,
const SkMatrix& viewMatrix,
GrPaint&& paint,
GrAAType aaType,
GrPath* path) {
GrOpMemoryPool* pool = context->priv().opMemoryPool();
return pool->allocate<GrDrawPathOp>(viewMatrix, std::move(paint), aaType, path);
}
void GrDrawPathOp::onExecute(GrOpFlushState* state, const SkRect& chainBounds) {
GrAppliedClip appliedClip = state->detachAppliedClip();
GrPipeline::FixedDynamicState fixedDynamicState(appliedClip.scissorState().rect());
GrPipeline pipeline(this->pipelineInitArgs(*state), this->detachProcessors(),
std::move(appliedClip));
sk_sp<GrPathProcessor> pathProc(GrPathProcessor::Create(this->color(), this->viewMatrix()));
GrStencilSettings stencil;
init_stencil_pass_settings(*state, this->fillType(), &stencil);
state->gpu()->pathRendering()->drawPath(state->drawOpArgs().renderTarget(),
state->drawOpArgs().origin(),
*pathProc, pipeline, fixedDynamicState, stencil,
fPath.get());
}
//////////////////////////////////////////////////////////////////////////////
inline void pre_translate_transform_values(const float* xforms,
GrPathRendering::PathTransformType type, int count,
SkScalar x, SkScalar y, float* dst) {
if (0 == x && 0 == y) {
memcpy(dst, xforms, count * GrPathRendering::PathTransformSize(type) * sizeof(float));
return;
}
switch (type) {
case GrPathRendering::kNone_PathTransformType:
SK_ABORT("Cannot pre-translate kNone_PathTransformType.");
break;
case GrPathRendering::kTranslateX_PathTransformType:
SkASSERT(0 == y);
for (int i = 0; i < count; i++) {
dst[i] = xforms[i] + x;
}
break;
case GrPathRendering::kTranslateY_PathTransformType:
SkASSERT(0 == x);
for (int i = 0; i < count; i++) {
dst[i] = xforms[i] + y;
}
break;
case GrPathRendering::kTranslate_PathTransformType:
for (int i = 0; i < 2 * count; i += 2) {
dst[i] = xforms[i] + x;
dst[i + 1] = xforms[i + 1] + y;
}
break;
case GrPathRendering::kAffine_PathTransformType:
for (int i = 0; i < 6 * count; i += 6) {
dst[i] = xforms[i];
dst[i + 1] = xforms[i + 1];
dst[i + 2] = xforms[i] * x + xforms[i + 1] * y + xforms[i + 2];
dst[i + 3] = xforms[i + 3];
dst[i + 4] = xforms[i + 4];
dst[i + 5] = xforms[i + 3] * x + xforms[i + 4] * y + xforms[i + 5];
}
break;
default:
SK_ABORT("Unknown transform type.");
break;
}
}