blob: a63e434c3fb1fe7f01162735d8ac7ebbd11dc330 [file] [log] [blame]
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "SkNormalBevelSource.h"
#include "SkNormalSource.h"
#include "SkNormalSourcePriv.h"
#include "SkPoint3.h"
#include "SkReadBuffer.h"
#include "SkWriteBuffer.h"
#if SK_SUPPORT_GPU
#include "GrInvariantOutput.h"
#include "glsl/GrGLSLFragmentProcessor.h"
#include "glsl/GrGLSLFragmentShaderBuilder.h"
#include "SkGr.h"
class NormalBevelFP : public GrFragmentProcessor {
public:
NormalBevelFP(SkNormalSource::BevelType type, SkScalar width, SkScalar height)
: fType(type)
, fWidth(width)
, fHeight(height) {
this->initClassID<NormalBevelFP>();
fUsesDistanceVectorField = true;
}
class GLSLNormalBevelFP : public GLSLNormalFP {
public:
GLSLNormalBevelFP() {
fPrevWidth = SkFloatToScalar(0.0f);
fPrevHeight = SkFloatToScalar(0.0f);
}
void onEmitCode(EmitArgs& args) override {
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
const char* widthUniName = nullptr;
fWidthUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kFloat_GrSLType,
kDefault_GrSLPrecision, "Width", &widthUniName);
const char* heightUniName = nullptr;
fHeightUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kFloat_GrSLType,
kDefault_GrSLPrecision, "Height", &heightUniName);
fragBuilder->codeAppendf("%s = vec4(0.0, 0.0, 1.0, 0.0);", args.fOutputColor);
}
static void GenKey(const GrProcessor& proc, const GrGLSLCaps&,
GrProcessorKeyBuilder* b) {
const NormalBevelFP& fp = proc.cast<NormalBevelFP>();
b->add32(static_cast<int>(fp.fType));
}
protected:
void setNormalData(const GrGLSLProgramDataManager& pdman,
const GrProcessor& proc) override {
const NormalBevelFP& normalBevelFP = proc.cast<NormalBevelFP>();
if (fPrevWidth != normalBevelFP.fWidth) {
pdman.set1f(fWidthUni, normalBevelFP.fWidth);
fPrevWidth = normalBevelFP.fWidth;
}
if (fPrevHeight != normalBevelFP.fHeight) {
pdman.set1f(fHeightUni, normalBevelFP.fHeight);
fPrevHeight = normalBevelFP.fHeight;
}
}
private:
SkScalar fPrevWidth;
GrGLSLProgramDataManager::UniformHandle fWidthUni;
SkScalar fPrevHeight;
GrGLSLProgramDataManager::UniformHandle fHeightUni;
};
void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override {
GLSLNormalBevelFP::GenKey(*this, caps, b);
}
const char* name() const override { return "NormalBevelFP"; }
void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
inout->setToUnknown(GrInvariantOutput::ReadInput::kWillNot_ReadInput);
}
private:
GrGLSLFragmentProcessor* onCreateGLSLInstance() const override { return new GLSLNormalBevelFP; }
bool onIsEqual(const GrFragmentProcessor& proc) const override {
const NormalBevelFP& normalBevelFP = proc.cast<NormalBevelFP>();
return fType == normalBevelFP.fType &&
fWidth == normalBevelFP.fWidth &&
fHeight == normalBevelFP.fHeight;
}
SkNormalSource::BevelType fType;
SkScalar fWidth;
SkScalar fHeight;
};
sk_sp<GrFragmentProcessor> SkNormalBevelSourceImpl::asFragmentProcessor(
const SkShader::AsFPArgs&) const {
return sk_make_sp<NormalBevelFP>(fType, fWidth, fHeight);
}
#endif // SK_SUPPORT_GPU
////////////////////////////////////////////////////////////////////////////
SkNormalBevelSourceImpl::Provider::Provider() {}
SkNormalBevelSourceImpl::Provider::~Provider() {}
SkNormalSource::Provider* SkNormalBevelSourceImpl::asProvider(const SkShader::ContextRec &rec,
void *storage) const {
return new (storage) Provider();
}
size_t SkNormalBevelSourceImpl::providerSize(const SkShader::ContextRec&) const {
return sizeof(Provider);
}
void SkNormalBevelSourceImpl::Provider::fillScanLine(int x, int y, SkPoint3 output[],
int count) const {
for (int i = 0; i < count; i++) {
output[i] = {0.0f, 0.0f, 1.0f};
}
}
////////////////////////////////////////////////////////////////////////////////
sk_sp<SkFlattenable> SkNormalBevelSourceImpl::CreateProc(SkReadBuffer& buf) {
auto type = static_cast<SkNormalSource::BevelType>(buf.readInt());
SkScalar width = buf.readScalar();
SkScalar height = buf.readScalar();
return sk_make_sp<SkNormalBevelSourceImpl>(type, width, height);
}
void SkNormalBevelSourceImpl::flatten(SkWriteBuffer& buf) const {
this->INHERITED::flatten(buf);
buf.writeInt(static_cast<int>(fType));
buf.writeScalar(fWidth);
buf.writeScalar(fHeight);
}
////////////////////////////////////////////////////////////////////////////
sk_sp<SkNormalSource> SkNormalSource::MakeBevel(BevelType type, SkScalar width, SkScalar height) {
/* TODO make sure this checks are tolerant enough to account for loss of conversion when GPUs
use 16-bit float types. We don't want to assume stuff is non-zero on the GPU and be wrong.*/
SkASSERT(width > 0.0f && !SkScalarNearlyZero(width));
if (SkScalarNearlyZero(height)) {
return SkNormalSource::MakeFlat();
}
return sk_make_sp<SkNormalBevelSourceImpl>(type, width, height);
}