blob: 435d0cdb02c988255244c53fc343ebf085fc44eb [file] [log] [blame]
junov@google.comf93e7172011-03-31 21:26:24 +00001/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00002 * Copyright 2011 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
junov@google.comf93e7172011-03-31 21:26:24 +00006 */
7
8#include "GrGLProgram.h"
9
tomhudson@google.comd8f856c2012-05-10 12:13:36 +000010#include "GrAllocator.h"
bsalomon@google.coma469c282012-10-24 18:28:34 +000011#include "GrEffect.h"
bsalomon@google.com77af6802013-10-02 13:04:56 +000012#include "GrCoordTransform.h"
bsalomon@google.comc7818882013-03-20 19:19:53 +000013#include "GrDrawEffect.h"
bsalomon@google.comd698f772012-10-25 13:22:00 +000014#include "GrGLEffect.h"
bsalomon@google.com34cccde2013-01-04 18:34:30 +000015#include "GrGpuGL.h"
bsalomon@google.com4fa66942011-09-20 19:06:12 +000016#include "GrGLShaderVar.h"
bsalomon@google.com018f1792013-04-18 19:36:09 +000017#include "GrGLSL.h"
Scroggo97c88c22011-05-11 14:05:25 +000018#include "SkXfermode.h"
19
commit-bot@chromium.org9188a152013-09-05 18:28:24 +000020#define GL_CALL(X) GR_GL_CALL(fGpu->glInterface(), X)
21#define GL_CALL_RET(R, X) GR_GL_CALL_RET(fGpu->glInterface(), R, X)
bsalomon@google.comecb60aa2012-07-18 13:20:29 +000022
commit-bot@chromium.org9188a152013-09-05 18:28:24 +000023GrGLProgram* GrGLProgram::Create(GrGpuGL* gpu,
bsalomon@google.com31ec7982013-03-27 18:14:57 +000024 const GrGLProgramDesc& desc,
bsalomon@google.com2c84aa32013-06-06 20:28:57 +000025 const GrEffectStage* colorStages[],
26 const GrEffectStage* coverageStages[]) {
commit-bot@chromium.org6eac42e2014-05-29 21:29:51 +000027 GrGLShaderBuilder::GenProgramOutput output;
28 SkAutoTUnref<GrGLUniformManager> uman(SkNEW_ARGS(GrGLUniformManager, (gpu)));
29 if (GrGLShaderBuilder::GenProgram(gpu, uman, desc, colorStages, coverageStages,
30 &output)) {
31 SkASSERT(0 != output.fProgramID);
32 return SkNEW_ARGS(GrGLProgram, (gpu, desc, uman, output));
bsalomon@google.comecb60aa2012-07-18 13:20:29 +000033 }
commit-bot@chromium.org6eac42e2014-05-29 21:29:51 +000034 return NULL;
bsalomon@google.comecb60aa2012-07-18 13:20:29 +000035}
36
commit-bot@chromium.org9188a152013-09-05 18:28:24 +000037GrGLProgram::GrGLProgram(GrGpuGL* gpu,
bsalomon@google.com31ec7982013-03-27 18:14:57 +000038 const GrGLProgramDesc& desc,
commit-bot@chromium.org6eac42e2014-05-29 21:29:51 +000039 GrGLUniformManager* uman,
40 const GrGLShaderBuilder::GenProgramOutput& builderOutput)
commit-bot@chromium.orga05fa062014-05-30 18:55:03 +000041 : fColor(GrColor_ILLEGAL)
commit-bot@chromium.org6eac42e2014-05-29 21:29:51 +000042 , fCoverage(GrColor_ILLEGAL)
43 , fDstCopyTexUnit(-1)
commit-bot@chromium.orga05fa062014-05-30 18:55:03 +000044 , fBuilderOutput(builderOutput)
commit-bot@chromium.org6eac42e2014-05-29 21:29:51 +000045 , fDesc(desc)
46 , fGpu(gpu)
commit-bot@chromium.orga05fa062014-05-30 18:55:03 +000047 , fUniformManager(SkRef(uman)) {
commit-bot@chromium.org6eac42e2014-05-29 21:29:51 +000048 this->initSamplerUniforms();
junov@google.comf93e7172011-03-31 21:26:24 +000049}
50
51GrGLProgram::~GrGLProgram() {
commit-bot@chromium.orga05fa062014-05-30 18:55:03 +000052 if (fBuilderOutput.fProgramID) {
53 GL_CALL(DeleteProgram(fBuilderOutput.fProgramID));
bsalomon@google.comecb60aa2012-07-18 13:20:29 +000054 }
junov@google.comf93e7172011-03-31 21:26:24 +000055}
56
bsalomon@google.comecb60aa2012-07-18 13:20:29 +000057void GrGLProgram::abandon() {
commit-bot@chromium.orga05fa062014-05-30 18:55:03 +000058 fBuilderOutput.fProgramID = 0;
bsalomon@google.comecb60aa2012-07-18 13:20:29 +000059}
60
tomhudson@google.com0d3f1fb2011-06-01 19:27:31 +000061void GrGLProgram::overrideBlend(GrBlendCoeff* srcCoeff,
bsalomon@google.com271cffc2011-05-20 14:13:56 +000062 GrBlendCoeff* dstCoeff) const {
bsalomon@google.com2db3ded2013-05-22 14:34:04 +000063 switch (fDesc.getHeader().fCoverageOutput) {
bsalomon@google.com5920ac22013-04-19 13:14:45 +000064 case GrGLProgramDesc::kModulate_CoverageOutput:
bsalomon@google.com271cffc2011-05-20 14:13:56 +000065 break;
bsalomon@google.com5920ac22013-04-19 13:14:45 +000066 // The prog will write a coverage value to the secondary
bsalomon@google.com271cffc2011-05-20 14:13:56 +000067 // output and the dst is blended by one minus that value.
bsalomon@google.com5920ac22013-04-19 13:14:45 +000068 case GrGLProgramDesc::kSecondaryCoverage_CoverageOutput:
69 case GrGLProgramDesc::kSecondaryCoverageISA_CoverageOutput:
70 case GrGLProgramDesc::kSecondaryCoverageISC_CoverageOutput:
71 *dstCoeff = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff;
72 break;
73 case GrGLProgramDesc::kCombineWithDst_CoverageOutput:
74 // We should only have set this if the blend was specified as (1, 0)
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +000075 SkASSERT(kOne_GrBlendCoeff == *srcCoeff && kZero_GrBlendCoeff == *dstCoeff);
bsalomon@google.com5920ac22013-04-19 13:14:45 +000076 break;
bsalomon@google.com271cffc2011-05-20 14:13:56 +000077 default:
commit-bot@chromium.org88cb22b2014-04-30 14:17:00 +000078 SkFAIL("Unexpected coverage output");
bsalomon@google.com271cffc2011-05-20 14:13:56 +000079 break;
80 }
81}
82
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +000083void GrGLProgram::initSamplerUniforms() {
commit-bot@chromium.orga05fa062014-05-30 18:55:03 +000084 GL_CALL(UseProgram(fBuilderOutput.fProgramID));
bsalomon@google.com34cccde2013-01-04 18:34:30 +000085 GrGLint texUnitIdx = 0;
commit-bot@chromium.orga05fa062014-05-30 18:55:03 +000086 if (fBuilderOutput.fUniformHandles.fDstCopySamplerUni.isValid()) {
87 fUniformManager->setSampler(fBuilderOutput.fUniformHandles.fDstCopySamplerUni, texUnitIdx);
bsalomon@google.com804e9942013-06-06 18:04:38 +000088 fDstCopyTexUnit = texUnitIdx++;
bsalomon@google.com26e18b52013-03-29 19:22:36 +000089 }
commit-bot@chromium.orga05fa062014-05-30 18:55:03 +000090 fBuilderOutput.fColorEffects->initSamplers(*fUniformManager, &texUnitIdx);
91 fBuilderOutput.fCoverageEffects->initSamplers(*fUniformManager, &texUnitIdx);
bsalomon@google.com91961302011-05-09 18:39:58 +000092}
93
bsalomon@google.comeb715c82012-07-11 15:03:31 +000094///////////////////////////////////////////////////////////////////////////////
junov@google.comf93e7172011-03-31 21:26:24 +000095
commit-bot@chromium.org9188a152013-09-05 18:28:24 +000096void GrGLProgram::setData(GrDrawState::BlendOptFlags blendOpts,
bsalomon@google.com2c84aa32013-06-06 20:28:57 +000097 const GrEffectStage* colorStages[],
98 const GrEffectStage* coverageStages[],
bsalomon@google.com26e18b52013-03-29 19:22:36 +000099 const GrDeviceCoordTexture* dstCopy,
bsalomon@google.com91207482013-02-12 21:45:24 +0000100 SharedGLState* sharedState) {
commit-bot@chromium.org9188a152013-09-05 18:28:24 +0000101 const GrDrawState& drawState = fGpu->getDrawState();
bsalomon@google.com9ba4fa62012-07-16 17:36:28 +0000102
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000103 GrColor color;
104 GrColor coverage;
105 if (blendOpts & GrDrawState::kEmitTransBlack_BlendOptFlag) {
106 color = 0;
107 coverage = 0;
108 } else if (blendOpts & GrDrawState::kEmitCoverage_BlendOptFlag) {
109 color = 0xffffffff;
commit-bot@chromium.orge0a868c2013-11-22 07:02:11 +0000110 coverage = drawState.getCoverageColor();
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000111 } else {
112 color = drawState.getColor();
commit-bot@chromium.orge0a868c2013-11-22 07:02:11 +0000113 coverage = drawState.getCoverageColor();
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000114 }
115
bsalomon@google.com91207482013-02-12 21:45:24 +0000116 this->setColor(drawState, color, sharedState);
117 this->setCoverage(drawState, coverage, sharedState);
bsalomon@google.com6a51dcb2013-02-13 16:03:51 +0000118 this->setMatrixAndRenderTargetHeight(drawState);
bsalomon@google.com91207482013-02-12 21:45:24 +0000119
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000120 if (NULL != dstCopy) {
commit-bot@chromium.orga05fa062014-05-30 18:55:03 +0000121 if (fBuilderOutput.fUniformHandles.fDstCopyTopLeftUni.isValid()) {
122 fUniformManager->set2f(fBuilderOutput.fUniformHandles.fDstCopyTopLeftUni,
commit-bot@chromium.org6eac42e2014-05-29 21:29:51 +0000123 static_cast<GrGLfloat>(dstCopy->offset().fX),
124 static_cast<GrGLfloat>(dstCopy->offset().fY));
commit-bot@chromium.orga05fa062014-05-30 18:55:03 +0000125 fUniformManager->set2f(fBuilderOutput.fUniformHandles.fDstCopyScaleUni,
commit-bot@chromium.org6eac42e2014-05-29 21:29:51 +0000126 1.f / dstCopy->texture()->width(),
127 1.f / dstCopy->texture()->height());
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000128 GrGLTexture* texture = static_cast<GrGLTexture*>(dstCopy->texture());
129 static GrTextureParams kParams; // the default is clamp, nearest filtering.
commit-bot@chromium.org9188a152013-09-05 18:28:24 +0000130 fGpu->bindTexture(fDstCopyTexUnit, kParams, texture);
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000131 } else {
commit-bot@chromium.orga05fa062014-05-30 18:55:03 +0000132 SkASSERT(!fBuilderOutput.fUniformHandles.fDstCopyScaleUni.isValid());
133 SkASSERT(!fBuilderOutput.fUniformHandles.fDstCopySamplerUni.isValid());
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000134 }
135 } else {
commit-bot@chromium.orga05fa062014-05-30 18:55:03 +0000136 SkASSERT(!fBuilderOutput.fUniformHandles.fDstCopyTopLeftUni.isValid());
137 SkASSERT(!fBuilderOutput.fUniformHandles.fDstCopyScaleUni.isValid());
138 SkASSERT(!fBuilderOutput.fUniformHandles.fDstCopySamplerUni.isValid());
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000139 }
bsalomon@google.comc7818882013-03-20 19:19:53 +0000140
commit-bot@chromium.orga05fa062014-05-30 18:55:03 +0000141 fBuilderOutput.fColorEffects->setData(fGpu, *fUniformManager, colorStages);
142 fBuilderOutput.fCoverageEffects->setData(fGpu, *fUniformManager, coverageStages);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000143
commit-bot@chromium.org20807222013-11-01 11:54:54 +0000144
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000145 // PathTexGen state applies to the the fixed function vertex shader. For
146 // custom shaders, it's ignored, so we don't need to change the texgen
147 // settings in that case.
commit-bot@chromium.orga05fa062014-05-30 18:55:03 +0000148 if (!fBuilderOutput.fHasVertexShader) {
149 fGpu->flushPathTexGenSettings(fBuilderOutput.fTexCoordSetCnt);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000150 }
skia.committer@gmail.com8ae714b2013-01-05 02:02:05 +0000151}
bsalomon@google.com91207482013-02-12 21:45:24 +0000152
153void GrGLProgram::setColor(const GrDrawState& drawState,
154 GrColor color,
155 SharedGLState* sharedState) {
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000156 const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader();
jvanverth@google.com054ae992013-04-01 20:06:51 +0000157 if (!drawState.hasColorVertexAttribute()) {
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000158 switch (header.fColorInput) {
bsalomon@google.com31ec7982013-03-27 18:14:57 +0000159 case GrGLProgramDesc::kAttribute_ColorInput:
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000160 SkASSERT(-1 != header.fColorAttributeIndex);
jvanverth@google.com054ae992013-04-01 20:06:51 +0000161 if (sharedState->fConstAttribColor != color ||
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000162 sharedState->fConstAttribColorIndex != header.fColorAttributeIndex) {
bsalomon@google.com91207482013-02-12 21:45:24 +0000163 // OpenGL ES only supports the float varieties of glVertexAttrib
164 GrGLfloat c[4];
165 GrColorToRGBAFloat(color, c);
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000166 GL_CALL(VertexAttrib4fv(header.fColorAttributeIndex, c));
bsalomon@google.com91207482013-02-12 21:45:24 +0000167 sharedState->fConstAttribColor = color;
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000168 sharedState->fConstAttribColorIndex = header.fColorAttributeIndex;
bsalomon@google.com91207482013-02-12 21:45:24 +0000169 }
170 break;
bsalomon@google.com31ec7982013-03-27 18:14:57 +0000171 case GrGLProgramDesc::kUniform_ColorInput:
commit-bot@chromium.orga05fa062014-05-30 18:55:03 +0000172 if (fColor != color && fBuilderOutput.fUniformHandles.fColorUni.isValid()) {
bsalomon@google.com91207482013-02-12 21:45:24 +0000173 // OpenGL ES doesn't support unsigned byte varieties of glUniform
174 GrGLfloat c[4];
175 GrColorToRGBAFloat(color, c);
commit-bot@chromium.orga05fa062014-05-30 18:55:03 +0000176 fUniformManager->set4fv(fBuilderOutput.fUniformHandles.fColorUni, 1, c);
bsalomon@google.com91207482013-02-12 21:45:24 +0000177 fColor = color;
178 }
jvanverth@google.com054ae992013-04-01 20:06:51 +0000179 sharedState->fConstAttribColorIndex = -1;
bsalomon@google.com91207482013-02-12 21:45:24 +0000180 break;
bsalomon@google.com31ec7982013-03-27 18:14:57 +0000181 case GrGLProgramDesc::kSolidWhite_ColorInput:
182 case GrGLProgramDesc::kTransBlack_ColorInput:
jvanverth@google.com054ae992013-04-01 20:06:51 +0000183 sharedState->fConstAttribColorIndex = -1;
bsalomon@google.com91207482013-02-12 21:45:24 +0000184 break;
185 default:
commit-bot@chromium.org88cb22b2014-04-30 14:17:00 +0000186 SkFAIL("Unknown color type.");
bsalomon@google.com91207482013-02-12 21:45:24 +0000187 }
jvanverth@google.com054ae992013-04-01 20:06:51 +0000188 } else {
189 sharedState->fConstAttribColorIndex = -1;
bsalomon@google.com91207482013-02-12 21:45:24 +0000190 }
191}
192
193void GrGLProgram::setCoverage(const GrDrawState& drawState,
194 GrColor coverage,
195 SharedGLState* sharedState) {
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000196 const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader();
jvanverth@google.com054ae992013-04-01 20:06:51 +0000197 if (!drawState.hasCoverageVertexAttribute()) {
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000198 switch (header.fCoverageInput) {
bsalomon@google.com31ec7982013-03-27 18:14:57 +0000199 case GrGLProgramDesc::kAttribute_ColorInput:
jvanverth@google.com054ae992013-04-01 20:06:51 +0000200 if (sharedState->fConstAttribCoverage != coverage ||
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000201 sharedState->fConstAttribCoverageIndex != header.fCoverageAttributeIndex) {
bsalomon@google.com91207482013-02-12 21:45:24 +0000202 // OpenGL ES only supports the float varieties of glVertexAttrib
203 GrGLfloat c[4];
204 GrColorToRGBAFloat(coverage, c);
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000205 GL_CALL(VertexAttrib4fv(header.fCoverageAttributeIndex, c));
bsalomon@google.com91207482013-02-12 21:45:24 +0000206 sharedState->fConstAttribCoverage = coverage;
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000207 sharedState->fConstAttribCoverageIndex = header.fCoverageAttributeIndex;
bsalomon@google.com91207482013-02-12 21:45:24 +0000208 }
209 break;
bsalomon@google.com31ec7982013-03-27 18:14:57 +0000210 case GrGLProgramDesc::kUniform_ColorInput:
bsalomon@google.com91207482013-02-12 21:45:24 +0000211 if (fCoverage != coverage) {
212 // OpenGL ES doesn't support unsigned byte varieties of glUniform
213 GrGLfloat c[4];
214 GrColorToRGBAFloat(coverage, c);
commit-bot@chromium.orga05fa062014-05-30 18:55:03 +0000215 fUniformManager->set4fv(fBuilderOutput.fUniformHandles.fCoverageUni, 1, c);
bsalomon@google.com91207482013-02-12 21:45:24 +0000216 fCoverage = coverage;
217 }
jvanverth@google.com054ae992013-04-01 20:06:51 +0000218 sharedState->fConstAttribCoverageIndex = -1;
bsalomon@google.com91207482013-02-12 21:45:24 +0000219 break;
bsalomon@google.com31ec7982013-03-27 18:14:57 +0000220 case GrGLProgramDesc::kSolidWhite_ColorInput:
221 case GrGLProgramDesc::kTransBlack_ColorInput:
jvanverth@google.com054ae992013-04-01 20:06:51 +0000222 sharedState->fConstAttribCoverageIndex = -1;
bsalomon@google.com91207482013-02-12 21:45:24 +0000223 break;
224 default:
commit-bot@chromium.org88cb22b2014-04-30 14:17:00 +0000225 SkFAIL("Unknown coverage type.");
bsalomon@google.com91207482013-02-12 21:45:24 +0000226 }
jvanverth@google.com054ae992013-04-01 20:06:51 +0000227 } else {
228 sharedState->fConstAttribCoverageIndex = -1;
bsalomon@google.com91207482013-02-12 21:45:24 +0000229 }
230}
bsalomon@google.com6a51dcb2013-02-13 16:03:51 +0000231
232void GrGLProgram::setMatrixAndRenderTargetHeight(const GrDrawState& drawState) {
233 const GrRenderTarget* rt = drawState.getRenderTarget();
234 SkISize size;
235 size.set(rt->width(), rt->height());
236
237 // Load the RT height uniform if it is needed to y-flip gl_FragCoord.
commit-bot@chromium.orga05fa062014-05-30 18:55:03 +0000238 if (fBuilderOutput.fUniformHandles.fRTHeightUni.isValid() &&
bsalomon@google.com6a51dcb2013-02-13 16:03:51 +0000239 fMatrixState.fRenderTargetSize.fHeight != size.fHeight) {
commit-bot@chromium.orga05fa062014-05-30 18:55:03 +0000240 fUniformManager->set1f(fBuilderOutput.fUniformHandles.fRTHeightUni,
241 SkIntToScalar(size.fHeight));
bsalomon@google.com6a51dcb2013-02-13 16:03:51 +0000242 }
243
commit-bot@chromium.orga05fa062014-05-30 18:55:03 +0000244 if (!fBuilderOutput.fHasVertexShader) {
245 SkASSERT(!fBuilderOutput.fUniformHandles.fViewMatrixUni.isValid());
246 SkASSERT(!fBuilderOutput.fUniformHandles.fRTAdjustmentUni.isValid());
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000247 fGpu->setProjectionMatrix(drawState.getViewMatrix(), size, rt->origin());
248 } else if (fMatrixState.fRenderTargetOrigin != rt->origin() ||
249 fMatrixState.fRenderTargetSize != size ||
250 !fMatrixState.fViewMatrix.cheapEqualTo(drawState.getViewMatrix())) {
commit-bot@chromium.orga05fa062014-05-30 18:55:03 +0000251 SkASSERT(fBuilderOutput.fUniformHandles.fViewMatrixUni.isValid());
bsalomon@google.com6a51dcb2013-02-13 16:03:51 +0000252
bsalomon@google.com6a51dcb2013-02-13 16:03:51 +0000253 fMatrixState.fViewMatrix = drawState.getViewMatrix();
254 fMatrixState.fRenderTargetSize = size;
255 fMatrixState.fRenderTargetOrigin = rt->origin();
commit-bot@chromium.org215a6822013-09-05 18:28:42 +0000256
257 GrGLfloat viewMatrix[3 * 3];
258 fMatrixState.getGLMatrix<3>(viewMatrix);
commit-bot@chromium.orga05fa062014-05-30 18:55:03 +0000259 fUniformManager->setMatrix3f(fBuilderOutput.fUniformHandles.fViewMatrixUni, viewMatrix);
commit-bot@chromium.org47c66dd2014-05-29 01:12:10 +0000260
261 GrGLfloat rtAdjustmentVec[4];
262 fMatrixState.getRTAdjustmentVec(rtAdjustmentVec);
commit-bot@chromium.orga05fa062014-05-30 18:55:03 +0000263 fUniformManager->set4fv(fBuilderOutput.fUniformHandles.fRTAdjustmentUni, 1, rtAdjustmentVec);
bsalomon@google.com6a51dcb2013-02-13 16:03:51 +0000264 }
265}