blob: 1258d59dc5415e276a333d285cd7a94666291194 [file] [log] [blame]
/*
* Copyright 2014 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "GrDefaultGeoProcFactory.h"
#include "gl/builders/GrGLProgramBuilder.h"
#include "gl/GrGLGeometryProcessor.h"
#include "GrDrawState.h"
#include "GrInvariantOutput.h"
#include "GrTBackendProcessorFactory.h"
/*
* The default Geometry Processor simply takes position and multiplies it by the uniform view
* matrix. It also leaves coverage untouched. Behind the scenes, we may add per vertex color or
* local coords.
*/
class DefaultGeoProc : public GrGeometryProcessor {
public:
static GrGeometryProcessor* Create() {
GR_CREATE_STATIC_PROCESSOR(gDefaultGeoProc, DefaultGeoProc, ());
return SkRef(gDefaultGeoProc);
}
static const char* Name() { return "DefaultGeometryProcessor"; }
virtual const GrBackendGeometryProcessorFactory& getFactory() const SK_OVERRIDE {
return GrTBackendGeometryProcessorFactory<DefaultGeoProc>::getInstance();
}
class GLProcessor : public GrGLGeometryProcessor {
public:
GLProcessor(const GrBackendProcessorFactory& factory, const GrProcessor&)
: INHERITED (factory) {}
virtual void emitCode(const EmitArgs& args) SK_OVERRIDE {
GrGLVertexBuilder* vs = args.fPB->getVertexShaderBuilder();
// setup position varying
vs->codeAppendf("%s = %s * vec3(%s, 1);", vs->glPosition(), vs->uViewM(),
vs->inPosition());
// output coverage in FS(pass through)
GrGLGPFragmentBuilder* fs = args.fPB->getFragmentShaderBuilder();
fs->codeAppendf("%s = %s;", args.fOutput, GrGLSLExpr4(args.fInput).c_str());
}
static inline void GenKey(const GrProcessor&, const GrGLCaps&, GrProcessorKeyBuilder*) {}
virtual void setData(const GrGLProgramDataManager&, const GrProcessor&) SK_OVERRIDE {}
private:
typedef GrGLGeometryProcessor INHERITED;
};
private:
DefaultGeoProc() {}
virtual bool onIsEqual(const GrGeometryProcessor& other) const SK_OVERRIDE {
return true;
}
virtual void onComputeInvariantOutput(GrInvariantOutput* inout) const SK_OVERRIDE {
inout->mulByUnknownAlpha();
}
GR_DECLARE_GEOMETRY_PROCESSOR_TEST;
typedef GrFragmentProcessor INHERITED;
};
GR_DEFINE_GEOMETRY_PROCESSOR_TEST(DefaultGeoProc);
GrGeometryProcessor* DefaultGeoProc::TestCreate(SkRandom* random,
GrContext*,
const GrDrawTargetCaps& caps,
GrTexture*[]) {
return DefaultGeoProc::Create();
}
// We use these arrays to customize our default GP. We only need 4 because we omit coverage if
// coverage is not requested in the flags to the create function.
GrVertexAttrib kDefaultPositionGeoProc[] = {
{ kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding },
{ kVec4ub_GrVertexAttribType, sizeof(SkPoint), kCoverage_GrVertexAttribBinding },
};
GrVertexAttrib kDefaultPosColorGeoProc[] = {
{ kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding },
{ kVec4ub_GrVertexAttribType, sizeof(SkPoint), kColor_GrVertexAttribBinding },
{ kVec4ub_GrVertexAttribType, sizeof(SkPoint) + sizeof(GrColor), kCoverage_GrVertexAttribBinding },
};
GrVertexAttrib kDefaultPosUVGeoProc[] = {
{ kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding },
{ kVec2f_GrVertexAttribType, sizeof(SkPoint), kLocalCoord_GrVertexAttribBinding },
{ kVec4ub_GrVertexAttribType, 2 * sizeof(SkPoint), kCoverage_GrVertexAttribBinding },
};
GrVertexAttrib kDefaultPosColUVGeoProc[] = {
{ kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding },
{ kVec4ub_GrVertexAttribType, sizeof(SkPoint), kColor_GrVertexAttribBinding },
{ kVec2f_GrVertexAttribType, sizeof(SkPoint) + sizeof(GrColor), kLocalCoord_GrVertexAttribBinding },
{ kVec4ub_GrVertexAttribType, 2 * sizeof(SkPoint) + sizeof(GrColor), kCoverage_GrVertexAttribBinding },
};
static size_t get_size(GrDefaultGeoProcFactory::GPType flag) {
switch (flag) {
case GrDefaultGeoProcFactory::kPosition_GPType:
return GrVertexAttribTypeSize(kVec2f_GrVertexAttribType);
case GrDefaultGeoProcFactory::kColor_GPType:
return GrVertexAttribTypeSize(kVec4ub_GrVertexAttribType);
case GrDefaultGeoProcFactory::kLocalCoord_GPType:
return GrVertexAttribTypeSize(kVec2f_GrVertexAttribType);
case GrDefaultGeoProcFactory::kCoverage_GPType:
return GrVertexAttribTypeSize(kVec4ub_GrVertexAttribType);
default:
SkFAIL("Should never get here");
return 0;
}
}
const GrGeometryProcessor*
GrDefaultGeoProcFactory::CreateAndSetAttribs(GrDrawState* ds, uint32_t gpTypeFlags) {
SkASSERT(ds);
// always atleast position in the GP
size_t size = get_size(kPosition_GPType);
int count = 1;
bool hasColor = SkToBool(gpTypeFlags & kColor_GPType);
bool hasLocalCoord = SkToBool(gpTypeFlags & kLocalCoord_GPType);
bool hasCoverage = SkToBool(gpTypeFlags & kCoverage_GPType);
if (hasColor) {
size += get_size(kColor_GPType);
count++;
if (hasLocalCoord) {
size += get_size(kLocalCoord_GPType);
count++;
if (hasCoverage) {
size += get_size(kCoverage_GPType);
count++;
ds->setVertexAttribs<kDefaultPosColUVGeoProc>(count, size);
} else {
ds->setVertexAttribs<kDefaultPosColUVGeoProc>(count, size);
}
} else {
if (hasCoverage) {
size += get_size(kCoverage_GPType);
count++;
ds->setVertexAttribs<kDefaultPosColorGeoProc>(count, size);
} else {
ds->setVertexAttribs<kDefaultPosColorGeoProc>(count, size);
}
}
} else if (hasLocalCoord) {
size += get_size(kLocalCoord_GPType);
count++;
if (hasCoverage) {
size += get_size(kCoverage_GPType);
count++;
ds->setVertexAttribs<kDefaultPosUVGeoProc>(count, size);
} else {
ds->setVertexAttribs<kDefaultPosUVGeoProc>(count, size);
}
} else if (hasCoverage) {
size += get_size(kCoverage_GPType);
count++;
ds->setVertexAttribs<kDefaultPositionGeoProc>(count, size);
} else {
// Just position
ds->setVertexAttribs<kDefaultPositionGeoProc>(count, size);
}
return DefaultGeoProc::Create();
}
const GrGeometryProcessor* GrDefaultGeoProcFactory::Create() {
return DefaultGeoProc::Create();
}