blob: aae9bd8ce19bb463ba17dec926a74449da7bdcff [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 */
joshualitt23e280d2014-09-18 12:26:38 -07007
junov@google.comf93e7172011-03-31 21:26:24 +00008#include "GrGLProgram.h"
9
joshualitt408d6122014-09-17 07:00:35 -070010#include "builders/GrGLFullProgramBuilder.h"
joshualittb0a8a372014-09-23 09:50:21 -070011#include "builders/GrGLFragmentOnlyProgramBuilder.h"
tomhudson@google.comd8f856c2012-05-10 12:13:36 +000012#include "GrAllocator.h"
joshualittb0a8a372014-09-23 09:50:21 -070013#include "GrProcessor.h"
bsalomon@google.com77af6802013-10-02 13:04:56 +000014#include "GrCoordTransform.h"
joshualittb0a8a372014-09-23 09:50:21 -070015#include "GrGLProcessor.h"
bsalomon@google.com34cccde2013-01-04 18:34:30 +000016#include "GrGpuGL.h"
kkinnunenec56e452014-08-25 22:21:16 -070017#include "GrGLPathRendering.h"
bsalomon@google.com4fa66942011-09-20 19:06:12 +000018#include "GrGLShaderVar.h"
bsalomon@google.com018f1792013-04-18 19:36:09 +000019#include "GrGLSL.h"
egdaniel170f90b2014-09-16 12:54:40 -070020#include "GrOptDrawState.h"
Scroggo97c88c22011-05-11 14:05:25 +000021#include "SkXfermode.h"
22
commit-bot@chromium.org9188a152013-09-05 18:28:24 +000023#define GL_CALL(X) GR_GL_CALL(fGpu->glInterface(), X)
24#define GL_CALL_RET(R, X) GR_GL_CALL_RET(fGpu->glInterface(), R, X)
bsalomon@google.comecb60aa2012-07-18 13:20:29 +000025
commit-bot@chromium.org9188a152013-09-05 18:28:24 +000026GrGLProgram* GrGLProgram::Create(GrGpuGL* gpu,
bsalomon@google.com31ec7982013-03-27 18:14:57 +000027 const GrGLProgramDesc& desc,
joshualittb0a8a372014-09-23 09:50:21 -070028 const GrGeometryStage* geometryProcessor,
29 const GrFragmentStage* colorStages[],
30 const GrFragmentStage* coverageStages[]) {
joshualitt30ba4362014-08-21 20:18:45 -070031 SkAutoTDelete<GrGLProgramBuilder> builder;
egdanielae444962014-09-22 12:29:52 -070032 if (desc.getHeader().fUseFragShaderOnly) {
33 SkASSERT(gpu->glCaps().pathRenderingSupport());
34 SkASSERT(gpu->glPathRendering()->texturingMode() ==
35 GrGLPathRendering::FixedFunction_TexturingMode);
joshualittbd769d02014-09-04 08:56:46 -070036 SkASSERT(NULL == geometryProcessor);
joshualitt30ba4362014-08-21 20:18:45 -070037 builder.reset(SkNEW_ARGS(GrGLFragmentOnlyProgramBuilder, (gpu, desc)));
kkinnunenec56e452014-08-25 22:21:16 -070038 } else {
39 builder.reset(SkNEW_ARGS(GrGLFullProgramBuilder, (gpu, desc)));
kkinnunendddc18a2014-08-03 23:19:46 -070040 }
joshualittbd769d02014-09-04 08:56:46 -070041 if (builder->genProgram(geometryProcessor, colorStages, coverageStages)) {
kkinnunendddc18a2014-08-03 23:19:46 -070042 SkASSERT(0 != builder->getProgramID());
43 return SkNEW_ARGS(GrGLProgram, (gpu, desc, *builder));
bsalomon@google.comecb60aa2012-07-18 13:20:29 +000044 }
commit-bot@chromium.org6eac42e2014-05-29 21:29:51 +000045 return NULL;
bsalomon@google.comecb60aa2012-07-18 13:20:29 +000046}
47
commit-bot@chromium.org9188a152013-09-05 18:28:24 +000048GrGLProgram::GrGLProgram(GrGpuGL* gpu,
bsalomon@google.com31ec7982013-03-27 18:14:57 +000049 const GrGLProgramDesc& desc,
joshualitt30ba4362014-08-21 20:18:45 -070050 const GrGLProgramBuilder& builder)
commit-bot@chromium.orga05fa062014-05-30 18:55:03 +000051 : fColor(GrColor_ILLEGAL)
commit-bot@chromium.org6eac42e2014-05-29 21:29:51 +000052 , fCoverage(GrColor_ILLEGAL)
53 , fDstCopyTexUnit(-1)
kkinnunendddc18a2014-08-03 23:19:46 -070054 , fBuiltinUniformHandles(builder.getBuiltinUniformHandles())
joshualittbd769d02014-09-04 08:56:46 -070055 , fGeometryProcessor(SkSafeRef(builder.getGeometryProcessor()))
kkinnunendddc18a2014-08-03 23:19:46 -070056 , fColorEffects(SkRef(builder.getColorEffects()))
57 , fCoverageEffects(SkRef(builder.getCoverageEffects()))
58 , fProgramID(builder.getProgramID())
59 , fHasVertexShader(builder.hasVertexShader())
60 , fTexCoordSetCnt(builder.getTexCoordSetCount())
commit-bot@chromium.org6eac42e2014-05-29 21:29:51 +000061 , fDesc(desc)
62 , fGpu(gpu)
kkinnunendddc18a2014-08-03 23:19:46 -070063 , fProgramDataManager(gpu, this, builder) {
commit-bot@chromium.org6eac42e2014-05-29 21:29:51 +000064 this->initSamplerUniforms();
junov@google.comf93e7172011-03-31 21:26:24 +000065}
66
67GrGLProgram::~GrGLProgram() {
kkinnunendddc18a2014-08-03 23:19:46 -070068 if (fProgramID) {
69 GL_CALL(DeleteProgram(fProgramID));
bsalomon@google.comecb60aa2012-07-18 13:20:29 +000070 }
junov@google.comf93e7172011-03-31 21:26:24 +000071}
72
bsalomon@google.comecb60aa2012-07-18 13:20:29 +000073void GrGLProgram::abandon() {
kkinnunendddc18a2014-08-03 23:19:46 -070074 fProgramID = 0;
bsalomon@google.comecb60aa2012-07-18 13:20:29 +000075}
76
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +000077void GrGLProgram::initSamplerUniforms() {
kkinnunendddc18a2014-08-03 23:19:46 -070078 GL_CALL(UseProgram(fProgramID));
bsalomon@google.com34cccde2013-01-04 18:34:30 +000079 GrGLint texUnitIdx = 0;
kkinnunendddc18a2014-08-03 23:19:46 -070080 if (fBuiltinUniformHandles.fDstCopySamplerUni.isValid()) {
81 fProgramDataManager.setSampler(fBuiltinUniformHandles.fDstCopySamplerUni, texUnitIdx);
bsalomon@google.com804e9942013-06-06 18:04:38 +000082 fDstCopyTexUnit = texUnitIdx++;
bsalomon@google.com26e18b52013-03-29 19:22:36 +000083 }
bsalomon49f085d2014-09-05 13:34:00 -070084 if (fGeometryProcessor.get()) {
joshualittbd769d02014-09-04 08:56:46 -070085 fGeometryProcessor->initSamplers(fProgramDataManager, &texUnitIdx);
86 }
kkinnunendddc18a2014-08-03 23:19:46 -070087 fColorEffects->initSamplers(fProgramDataManager, &texUnitIdx);
88 fCoverageEffects->initSamplers(fProgramDataManager, &texUnitIdx);
bsalomon@google.com91961302011-05-09 18:39:58 +000089}
90
bsalomon@google.comeb715c82012-07-11 15:03:31 +000091///////////////////////////////////////////////////////////////////////////////
junov@google.comf93e7172011-03-31 21:26:24 +000092
egdaniel170f90b2014-09-16 12:54:40 -070093void GrGLProgram::setData(const GrOptDrawState& optState,
94 GrGpu::DrawType drawType,
joshualittb0a8a372014-09-23 09:50:21 -070095 const GrGeometryStage* geometryProcessor,
96 const GrFragmentStage* colorStages[],
97 const GrFragmentStage* coverageStages[],
bsalomon@google.com26e18b52013-03-29 19:22:36 +000098 const GrDeviceCoordTexture* dstCopy,
bsalomon@google.com91207482013-02-12 21:45:24 +000099 SharedGLState* sharedState) {
egdaniel170f90b2014-09-16 12:54:40 -0700100 GrColor color = optState.getColor();
101 GrColor coverage = optState.getCoverageColor();
bsalomon@google.com9ba4fa62012-07-16 17:36:28 +0000102
egdaniel170f90b2014-09-16 12:54:40 -0700103 this->setColor(optState, color, sharedState);
104 this->setCoverage(optState, coverage, sharedState);
105 this->setMatrixAndRenderTargetHeight(drawType, optState);
bsalomon@google.com91207482013-02-12 21:45:24 +0000106
bsalomon49f085d2014-09-05 13:34:00 -0700107 if (dstCopy) {
kkinnunendddc18a2014-08-03 23:19:46 -0700108 if (fBuiltinUniformHandles.fDstCopyTopLeftUni.isValid()) {
109 fProgramDataManager.set2f(fBuiltinUniformHandles.fDstCopyTopLeftUni,
kkinnunen7510b222014-07-30 00:04:16 -0700110 static_cast<GrGLfloat>(dstCopy->offset().fX),
111 static_cast<GrGLfloat>(dstCopy->offset().fY));
kkinnunendddc18a2014-08-03 23:19:46 -0700112 fProgramDataManager.set2f(fBuiltinUniformHandles.fDstCopyScaleUni,
kkinnunen7510b222014-07-30 00:04:16 -0700113 1.f / dstCopy->texture()->width(),
114 1.f / dstCopy->texture()->height());
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000115 GrGLTexture* texture = static_cast<GrGLTexture*>(dstCopy->texture());
116 static GrTextureParams kParams; // the default is clamp, nearest filtering.
commit-bot@chromium.org9188a152013-09-05 18:28:24 +0000117 fGpu->bindTexture(fDstCopyTexUnit, kParams, texture);
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000118 } else {
kkinnunendddc18a2014-08-03 23:19:46 -0700119 SkASSERT(!fBuiltinUniformHandles.fDstCopyScaleUni.isValid());
120 SkASSERT(!fBuiltinUniformHandles.fDstCopySamplerUni.isValid());
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000121 }
122 } else {
kkinnunendddc18a2014-08-03 23:19:46 -0700123 SkASSERT(!fBuiltinUniformHandles.fDstCopyTopLeftUni.isValid());
124 SkASSERT(!fBuiltinUniformHandles.fDstCopyScaleUni.isValid());
125 SkASSERT(!fBuiltinUniformHandles.fDstCopySamplerUni.isValid());
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000126 }
bsalomon@google.comc7818882013-03-20 19:19:53 +0000127
bsalomon49f085d2014-09-05 13:34:00 -0700128 if (fGeometryProcessor.get()) {
129 SkASSERT(geometryProcessor);
joshualittb0a8a372014-09-23 09:50:21 -0700130 fGeometryProcessor->setData(fGpu, drawType, fProgramDataManager, geometryProcessor);
joshualittbd769d02014-09-04 08:56:46 -0700131 }
joshualitt23e280d2014-09-18 12:26:38 -0700132 fColorEffects->setData(fGpu, drawType, fProgramDataManager, colorStages);
133 fCoverageEffects->setData(fGpu, drawType, fProgramDataManager, coverageStages);
commit-bot@chromium.org20807222013-11-01 11:54:54 +0000134
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000135 // PathTexGen state applies to the the fixed function vertex shader. For
136 // custom shaders, it's ignored, so we don't need to change the texgen
137 // settings in that case.
kkinnunendddc18a2014-08-03 23:19:46 -0700138 if (!fHasVertexShader) {
kkinnunenccdaa042014-08-20 01:36:23 -0700139 fGpu->glPathRendering()->flushPathTexGenSettings(fTexCoordSetCnt);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000140 }
skia.committer@gmail.com8ae714b2013-01-05 02:02:05 +0000141}
bsalomon@google.com91207482013-02-12 21:45:24 +0000142
egdaniel170f90b2014-09-16 12:54:40 -0700143void GrGLProgram::setColor(const GrOptDrawState& optState,
bsalomon@google.com91207482013-02-12 21:45:24 +0000144 GrColor color,
145 SharedGLState* sharedState) {
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000146 const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader();
egdaniel170f90b2014-09-16 12:54:40 -0700147 if (!optState.hasColorVertexAttribute()) {
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000148 switch (header.fColorInput) {
bsalomon@google.com31ec7982013-03-27 18:14:57 +0000149 case GrGLProgramDesc::kAttribute_ColorInput:
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000150 SkASSERT(-1 != header.fColorAttributeIndex);
jvanverth@google.com054ae992013-04-01 20:06:51 +0000151 if (sharedState->fConstAttribColor != color ||
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000152 sharedState->fConstAttribColorIndex != header.fColorAttributeIndex) {
bsalomon@google.com91207482013-02-12 21:45:24 +0000153 // OpenGL ES only supports the float varieties of glVertexAttrib
154 GrGLfloat c[4];
155 GrColorToRGBAFloat(color, c);
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000156 GL_CALL(VertexAttrib4fv(header.fColorAttributeIndex, c));
bsalomon@google.com91207482013-02-12 21:45:24 +0000157 sharedState->fConstAttribColor = color;
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000158 sharedState->fConstAttribColorIndex = header.fColorAttributeIndex;
bsalomon@google.com91207482013-02-12 21:45:24 +0000159 }
160 break;
bsalomon@google.com31ec7982013-03-27 18:14:57 +0000161 case GrGLProgramDesc::kUniform_ColorInput:
kkinnunendddc18a2014-08-03 23:19:46 -0700162 if (fColor != color && fBuiltinUniformHandles.fColorUni.isValid()) {
bsalomon@google.com91207482013-02-12 21:45:24 +0000163 // OpenGL ES doesn't support unsigned byte varieties of glUniform
164 GrGLfloat c[4];
165 GrColorToRGBAFloat(color, c);
kkinnunendddc18a2014-08-03 23:19:46 -0700166 fProgramDataManager.set4fv(fBuiltinUniformHandles.fColorUni, 1, c);
bsalomon@google.com91207482013-02-12 21:45:24 +0000167 fColor = color;
168 }
jvanverth@google.com054ae992013-04-01 20:06:51 +0000169 sharedState->fConstAttribColorIndex = -1;
bsalomon@google.com91207482013-02-12 21:45:24 +0000170 break;
egdaniel842b0862014-09-02 10:01:30 -0700171 case GrGLProgramDesc::kAllOnes_ColorInput:
172 sharedState->fConstAttribColorIndex = -1;
173 break;
bsalomon@google.com91207482013-02-12 21:45:24 +0000174 default:
egdaniel02cafcc2014-07-21 11:37:28 -0700175 SkFAIL("Unexpected color type.");
bsalomon@google.com91207482013-02-12 21:45:24 +0000176 }
jvanverth@google.com054ae992013-04-01 20:06:51 +0000177 } else {
178 sharedState->fConstAttribColorIndex = -1;
bsalomon@google.com91207482013-02-12 21:45:24 +0000179 }
180}
181
egdaniel170f90b2014-09-16 12:54:40 -0700182void GrGLProgram::setCoverage(const GrOptDrawState& optState,
bsalomon@google.com91207482013-02-12 21:45:24 +0000183 GrColor coverage,
184 SharedGLState* sharedState) {
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000185 const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader();
egdaniel170f90b2014-09-16 12:54:40 -0700186 if (!optState.hasCoverageVertexAttribute()) {
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000187 switch (header.fCoverageInput) {
bsalomon@google.com31ec7982013-03-27 18:14:57 +0000188 case GrGLProgramDesc::kAttribute_ColorInput:
jvanverth@google.com054ae992013-04-01 20:06:51 +0000189 if (sharedState->fConstAttribCoverage != coverage ||
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000190 sharedState->fConstAttribCoverageIndex != header.fCoverageAttributeIndex) {
bsalomon@google.com91207482013-02-12 21:45:24 +0000191 // OpenGL ES only supports the float varieties of glVertexAttrib
192 GrGLfloat c[4];
193 GrColorToRGBAFloat(coverage, c);
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000194 GL_CALL(VertexAttrib4fv(header.fCoverageAttributeIndex, c));
bsalomon@google.com91207482013-02-12 21:45:24 +0000195 sharedState->fConstAttribCoverage = coverage;
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000196 sharedState->fConstAttribCoverageIndex = header.fCoverageAttributeIndex;
bsalomon@google.com91207482013-02-12 21:45:24 +0000197 }
198 break;
bsalomon@google.com31ec7982013-03-27 18:14:57 +0000199 case GrGLProgramDesc::kUniform_ColorInput:
bsalomon@google.com91207482013-02-12 21:45:24 +0000200 if (fCoverage != coverage) {
201 // OpenGL ES doesn't support unsigned byte varieties of glUniform
202 GrGLfloat c[4];
203 GrColorToRGBAFloat(coverage, c);
kkinnunendddc18a2014-08-03 23:19:46 -0700204 fProgramDataManager.set4fv(fBuiltinUniformHandles.fCoverageUni, 1, c);
bsalomon@google.com91207482013-02-12 21:45:24 +0000205 fCoverage = coverage;
206 }
jvanverth@google.com054ae992013-04-01 20:06:51 +0000207 sharedState->fConstAttribCoverageIndex = -1;
bsalomon@google.com91207482013-02-12 21:45:24 +0000208 break;
egdaniel842b0862014-09-02 10:01:30 -0700209 case GrGLProgramDesc::kAllOnes_ColorInput:
jvanverth@google.com054ae992013-04-01 20:06:51 +0000210 sharedState->fConstAttribCoverageIndex = -1;
bsalomon@google.com91207482013-02-12 21:45:24 +0000211 break;
212 default:
egdaniel02cafcc2014-07-21 11:37:28 -0700213 SkFAIL("Unexpected coverage type.");
bsalomon@google.com91207482013-02-12 21:45:24 +0000214 }
jvanverth@google.com054ae992013-04-01 20:06:51 +0000215 } else {
216 sharedState->fConstAttribCoverageIndex = -1;
bsalomon@google.com91207482013-02-12 21:45:24 +0000217 }
218}
bsalomon@google.com6a51dcb2013-02-13 16:03:51 +0000219
kkinnunenec56e452014-08-25 22:21:16 -0700220void GrGLProgram::setMatrixAndRenderTargetHeight(GrGpu::DrawType drawType,
egdaniel170f90b2014-09-16 12:54:40 -0700221 const GrOptDrawState& optState) {
222 const GrRenderTarget* rt = optState.getRenderTarget();
bsalomon@google.com6a51dcb2013-02-13 16:03:51 +0000223 SkISize size;
224 size.set(rt->width(), rt->height());
225
226 // Load the RT height uniform if it is needed to y-flip gl_FragCoord.
kkinnunendddc18a2014-08-03 23:19:46 -0700227 if (fBuiltinUniformHandles.fRTHeightUni.isValid() &&
bsalomon@google.com6a51dcb2013-02-13 16:03:51 +0000228 fMatrixState.fRenderTargetSize.fHeight != size.fHeight) {
kkinnunendddc18a2014-08-03 23:19:46 -0700229 fProgramDataManager.set1f(fBuiltinUniformHandles.fRTHeightUni,
kkinnunen7510b222014-07-30 00:04:16 -0700230 SkIntToScalar(size.fHeight));
bsalomon@google.com6a51dcb2013-02-13 16:03:51 +0000231 }
232
kkinnunenec56e452014-08-25 22:21:16 -0700233 if (GrGpu::IsPathRenderingDrawType(drawType)) {
egdaniel170f90b2014-09-16 12:54:40 -0700234 fGpu->glPathRendering()->setProjectionMatrix(optState.getViewMatrix(), size, rt->origin());
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000235 } else if (fMatrixState.fRenderTargetOrigin != rt->origin() ||
236 fMatrixState.fRenderTargetSize != size ||
egdaniel170f90b2014-09-16 12:54:40 -0700237 !fMatrixState.fViewMatrix.cheapEqualTo(optState.getViewMatrix())) {
kkinnunendddc18a2014-08-03 23:19:46 -0700238 SkASSERT(fBuiltinUniformHandles.fViewMatrixUni.isValid());
bsalomon@google.com6a51dcb2013-02-13 16:03:51 +0000239
egdaniel170f90b2014-09-16 12:54:40 -0700240 fMatrixState.fViewMatrix = optState.getViewMatrix();
bsalomon@google.com6a51dcb2013-02-13 16:03:51 +0000241 fMatrixState.fRenderTargetSize = size;
242 fMatrixState.fRenderTargetOrigin = rt->origin();
commit-bot@chromium.org215a6822013-09-05 18:28:42 +0000243
244 GrGLfloat viewMatrix[3 * 3];
245 fMatrixState.getGLMatrix<3>(viewMatrix);
kkinnunendddc18a2014-08-03 23:19:46 -0700246 fProgramDataManager.setMatrix3f(fBuiltinUniformHandles.fViewMatrixUni, viewMatrix);
commit-bot@chromium.org47c66dd2014-05-29 01:12:10 +0000247
248 GrGLfloat rtAdjustmentVec[4];
249 fMatrixState.getRTAdjustmentVec(rtAdjustmentVec);
kkinnunendddc18a2014-08-03 23:19:46 -0700250 fProgramDataManager.set4fv(fBuiltinUniformHandles.fRTAdjustmentUni, 1, rtAdjustmentVec);
bsalomon@google.com6a51dcb2013-02-13 16:03:51 +0000251 }
252}