blob: eb54aa7de305d682d323627df670293f7b5c2f9d [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 "src/gpu/GrRenderTarget.h"
#include "src/gpu/GrShaderCaps.h"
#include "src/gpu/gl/GrGLGpu.h"
#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
#include "src/gpu/glsl/GrGLSLProgramBuilder.h"
#include "src/gpu/glsl/GrGLSLUniformHandler.h"
#include "src/gpu/glsl/GrGLSLVarying.h"
GrGLSLFragmentShaderBuilder::GrGLSLFragmentShaderBuilder(GrGLSLProgramBuilder* program)
: GrGLSLShaderBuilder(program) {}
const char* GrGLSLFragmentShaderBuilder::dstColor() {
SkDEBUGCODE(fHasReadDstColorThisStage_DebugOnly = true;)
const GrShaderCaps* shaderCaps = fProgramBuilder->shaderCaps();
if (shaderCaps->fbFetchSupport()) {
this->addFeature(1 << kFramebufferFetch_GLSLPrivateFeature,
shaderCaps->fbFetchExtensionString());
// Some versions of this extension string require declaring custom color output on ES 3.0+
const char* fbFetchColorName = "sk_LastFragColor";
if (shaderCaps->fbFetchNeedsCustomOutput()) {
this->enableCustomOutput();
fCustomColorOutput->setTypeModifier(GrShaderVar::TypeModifier::InOut);
fbFetchColorName = DeclaredColorOutputName();
// Set the dstColor to an intermediate variable so we don't override it with the output
this->codeAppendf("half4 %s = %s;", kDstColorName, fbFetchColorName);
} else {
return fbFetchColorName;
}
}
return kDstColorName;
}
void GrGLSLFragmentShaderBuilder::enableAdvancedBlendEquationIfNeeded(GrBlendEquation equation) {
SkASSERT(GrBlendEquationIsAdvanced(equation));
if (fProgramBuilder->shaderCaps()->mustEnableAdvBlendEqs()) {
this->addFeature(1 << kBlendEquationAdvanced_GLSLPrivateFeature,
"GL_KHR_blend_equation_advanced");
this->addLayoutQualifier("blend_support_all_equations", kOut_InterfaceQualifier);
}
}
void GrGLSLFragmentShaderBuilder::enableCustomOutput() {
if (!fCustomColorOutput) {
fCustomColorOutput = &fOutputs.emplace_back(DeclaredColorOutputName(), kHalf4_GrSLType,
GrShaderVar::TypeModifier::Out);
fProgramBuilder->finalizeFragmentOutputColor(fOutputs.back());
}
}
void GrGLSLFragmentShaderBuilder::enableSecondaryOutput() {
SkASSERT(!fHasSecondaryOutput);
fHasSecondaryOutput = true;
const GrShaderCaps& caps = *fProgramBuilder->shaderCaps();
if (const char* extension = caps.secondaryOutputExtensionString()) {
this->addFeature(1 << kBlendFuncExtended_GLSLPrivateFeature, extension);
}
// If the primary output is declared, we must declare also the secondary output
// and vice versa, since it is not allowed to use a built-in gl_FragColor and a custom
// output. The condition also co-incides with the condition in which GLES SL 2.0
// requires the built-in gl_SecondaryFragColorEXT, where as 3.0 requires a custom output.
if (caps.mustDeclareFragmentShaderOutput()) {
fOutputs.emplace_back(DeclaredSecondaryColorOutputName(), kHalf4_GrSLType,
GrShaderVar::TypeModifier::Out);
fProgramBuilder->finalizeFragmentSecondaryColor(fOutputs.back());
}
}
const char* GrGLSLFragmentShaderBuilder::getPrimaryColorOutputName() const {
return DeclaredColorOutputName();
}
bool GrGLSLFragmentShaderBuilder::primaryColorOutputIsInOut() const {
return fCustomColorOutput &&
fCustomColorOutput->getTypeModifier() == GrShaderVar::TypeModifier::InOut;
}
const char* GrGLSLFragmentShaderBuilder::getSecondaryColorOutputName() const {
if (this->hasSecondaryOutput()) {
return (fProgramBuilder->shaderCaps()->mustDeclareFragmentShaderOutput())
? DeclaredSecondaryColorOutputName()
: "gl_SecondaryFragColorEXT";
}
return nullptr;
}
GrSurfaceOrigin GrGLSLFragmentShaderBuilder::getSurfaceOrigin() const {
return fProgramBuilder->origin();
}
void GrGLSLFragmentShaderBuilder::onFinalize() {
fProgramBuilder->varyingHandler()->getFragDecls(&this->inputs(), &this->outputs());
}