blob: afd9bb6c73273046b188540ba40b572e2747cabc [file] [log] [blame]
reed@google.comac10a2d2010-12-22 21:39:39 +00001/*
2 Copyright 2010 Google Inc.
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15 */
16
17
18#include "GrGLConfig.h"
19
20#if GR_SUPPORT_GLES1 || GR_SUPPORT_GLDESKTOP
21
22#include "GrGpuGLFixed.h"
23#include "GrGpuVertex.h"
24
25#define SKIP_CACHE_CHECK true
26
27struct GrGpuMatrix {
bsalomon@google.comc6cf7232011-02-17 16:43:10 +000028 GLfloat fMat[16];
bsalomon@google.com5782d712011-01-21 21:03:59 +000029
reed@google.comac10a2d2010-12-22 21:39:39 +000030 void reset() {
31 Gr_bzero(fMat, sizeof(fMat));
32 fMat[0] = fMat[5] = fMat[10] = fMat[15] = GR_Scalar1;
33 }
bsalomon@google.com5782d712011-01-21 21:03:59 +000034
reed@google.comac10a2d2010-12-22 21:39:39 +000035 void set(const GrMatrix& m) {
36 Gr_bzero(fMat, sizeof(fMat));
bsalomon@google.comc6cf7232011-02-17 16:43:10 +000037 fMat[0] = GrScalarToFloat(m[GrMatrix::kScaleX]);
38 fMat[4] = GrScalarToFloat(m[GrMatrix::kSkewX]);
39 fMat[12] = GrScalarToFloat(m[GrMatrix::kTransX]);
bsalomon@google.com5782d712011-01-21 21:03:59 +000040
bsalomon@google.comc6cf7232011-02-17 16:43:10 +000041 fMat[1] = GrScalarToFloat(m[GrMatrix::kSkewY]);
42 fMat[5] = GrScalarToFloat(m[GrMatrix::kScaleY]);
43 fMat[13] = GrScalarToFloat(m[GrMatrix::kTransY]);
bsalomon@google.com5782d712011-01-21 21:03:59 +000044
bsalomon@google.comc6cf7232011-02-17 16:43:10 +000045 fMat[3] = GrScalarToFloat(m[GrMatrix::kPersp0]);
46 fMat[7] = GrScalarToFloat(m[GrMatrix::kPersp1]);
47 fMat[15] = GrScalarToFloat(m[GrMatrix::kPersp2]);
bsalomon@google.com5782d712011-01-21 21:03:59 +000048
bsalomon@google.comc6cf7232011-02-17 16:43:10 +000049 fMat[10] = 1.f; // z-scale
reed@google.comac10a2d2010-12-22 21:39:39 +000050 }
51};
52
53// these must match the order in the corresponding enum in GrGpu.h
54static const GLenum gMatrixMode2Enum[] = {
55 GL_MODELVIEW, GL_TEXTURE
56};
57
58///////////////////////////////////////////////////////////////////////////////
59
60GrGpuGLFixed::GrGpuGLFixed() {
reed@google.comac10a2d2010-12-22 21:39:39 +000061}
62
63GrGpuGLFixed::~GrGpuGLFixed() {
64}
65
66void GrGpuGLFixed::resetContext() {
67 INHERITED::resetContext();
reed@google.comac10a2d2010-12-22 21:39:39 +000068
reed@google.comac10a2d2010-12-22 21:39:39 +000069 GR_GL(Disable(GL_TEXTURE_2D));
70
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000071 for (int s = 0; s < kNumStages; ++s) {
72 setTextureUnit(s);
bsalomon@google.com5782d712011-01-21 21:03:59 +000073 GR_GL(EnableClientState(GL_VERTEX_ARRAY));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000074 GR_GL(TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE));
75 GR_GL(TexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE));
76 GR_GL(TexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_TEXTURE0+s));
77 GR_GL(TexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_PREVIOUS));
78 GR_GL(TexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR));
reed@google.comac10a2d2010-12-22 21:39:39 +000079
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000080 GR_GL(TexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE));
81 GR_GL(TexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_TEXTURE0+s));
82 GR_GL(TexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA));
83 GR_GL(TexEnvi(GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_PREVIOUS));
84 GR_GL(TexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA));
bsalomon@google.com5782d712011-01-21 21:03:59 +000085
86 // color oprand0 changes between GL_SRC_COLR and GL_SRC_ALPHA depending
87 // upon whether we have a (premultiplied) RGBA texture or just an ALPHA
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000088 // texture, e.g.:
89 //glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
bsalomon@google.com5782d712011-01-21 21:03:59 +000090 fHWRGBOperand0[s] = (TextureEnvRGBOperands) -1;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000091 }
reed@google.comac10a2d2010-12-22 21:39:39 +000092
93 fHWGeometryState.fVertexLayout = 0;
bsalomon@google.com1c13c962011-02-14 16:51:21 +000094 fHWGeometryState.fVertexOffset = ~0;
reed@google.comac10a2d2010-12-22 21:39:39 +000095 GR_GL(EnableClientState(GL_VERTEX_ARRAY));
96 GR_GL(DisableClientState(GL_TEXTURE_COORD_ARRAY));
97 GR_GL(ShadeModel(GL_FLAT));
98 GR_GL(DisableClientState(GL_COLOR_ARRAY));
bsalomon@google.com5782d712011-01-21 21:03:59 +000099
100 GR_GL(PointSize(1.f));
101
reed@google.comac10a2d2010-12-22 21:39:39 +0000102 GrGLClearErr();
103 fTextVerts = false;
104
reed@google.comac10a2d2010-12-22 21:39:39 +0000105 fBaseVertex = 0xffffffff;
106}
107
108
109void GrGpuGLFixed::flushProjectionMatrix() {
110 float mat[16];
111 Gr_bzero(mat, sizeof(mat));
bsalomon@google.com5782d712011-01-21 21:03:59 +0000112
reed@google.comac10a2d2010-12-22 21:39:39 +0000113 GrAssert(NULL != fCurrDrawState.fRenderTarget);
bsalomon@google.com5782d712011-01-21 21:03:59 +0000114
reed@google.comac10a2d2010-12-22 21:39:39 +0000115 mat[0] = 2.f / fCurrDrawState.fRenderTarget->width();
116 mat[5] = -2.f / fCurrDrawState.fRenderTarget->height();
117 mat[10] = -1.f;
118 mat[15] = 1;
bsalomon@google.com5782d712011-01-21 21:03:59 +0000119
reed@google.comac10a2d2010-12-22 21:39:39 +0000120 mat[12] = -1.f;
121 mat[13] = 1.f;
bsalomon@google.com5782d712011-01-21 21:03:59 +0000122
reed@google.comac10a2d2010-12-22 21:39:39 +0000123 GR_GL(MatrixMode(GL_PROJECTION));
124 GR_GL(LoadMatrixf(mat));
125}
126
bsalomon@google.comffca4002011-02-22 20:34:01 +0000127bool GrGpuGLFixed::flushGraphicsState(GrPrimitiveType type) {
bsalomon@google.com5782d712011-01-21 21:03:59 +0000128
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000129 bool usingTextures[kNumStages];
bsalomon@google.com5782d712011-01-21 21:03:59 +0000130
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000131 for (int s = 0; s < kNumStages; ++s) {
132 usingTextures[s] = VertexUsesStage(s, fGeometrySrc.fVertexLayout);
reed@google.comac10a2d2010-12-22 21:39:39 +0000133
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000134 if (usingTextures[s] && fCurrDrawState.fSamplerStates[s].isGradient()) {
135 unimpl("Fixed pipe doesn't support radial/sweep gradients");
136 return false;
137 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000138 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000139
bsalomon@google.com080773c2011-03-15 19:09:25 +0000140#if GR_SUPPORT_GLES1
141 if (BlendCoefReferencesConstant(fCurrDrawState.fSrcBlend) ||
142 BlendCoefReferencesConstant(fCurrDrawState.fDstBlend)) {
143 uimpl("ES1 doesn't support blend constant");
144 return false;
145 }
146#endif
147
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000148 if (!flushGLStateCommon(type)) {
149 return false;
150 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000151
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000152 if (fDirtyFlags.fRenderTargetChanged) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000153 flushProjectionMatrix();
reed@google.comac10a2d2010-12-22 21:39:39 +0000154 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000155
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000156 for (int s = 0; s < kNumStages; ++s) {
157 bool wasUsingTexture = VertexUsesStage(s, fHWGeometryState.fVertexLayout);
158 if (usingTextures[s] != wasUsingTexture) {
159 setTextureUnit(s);
160 if (usingTextures[s]) {
161 GR_GL(Enable(GL_TEXTURE_2D));
162 } else {
163 GR_GL(Disable(GL_TEXTURE_2D));
164 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000165 }
166 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000167
reed@google.comac10a2d2010-12-22 21:39:39 +0000168 uint32_t vertColor = (fGeometrySrc.fVertexLayout & kColor_VertexLayoutBit);
bsalomon@google.com5782d712011-01-21 21:03:59 +0000169 uint32_t prevVertColor = (fHWGeometryState.fVertexLayout &
reed@google.comac10a2d2010-12-22 21:39:39 +0000170 kColor_VertexLayoutBit);
bsalomon@google.com5782d712011-01-21 21:03:59 +0000171
reed@google.comac10a2d2010-12-22 21:39:39 +0000172 if (vertColor != prevVertColor) {
173 if (vertColor) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000174 GR_GL(ShadeModel(GL_SMOOTH));
175 // invalidate the immediate mode color
176 fHWDrawState.fColor = GrColor_ILLEGAL;
177 } else {
178 GR_GL(ShadeModel(GL_FLAT));
179 }
180 }
181
bsalomon@google.com5782d712011-01-21 21:03:59 +0000182
reed@google.comac10a2d2010-12-22 21:39:39 +0000183 if (!vertColor && fHWDrawState.fColor != fCurrDrawState.fColor) {
184 GR_GL(Color4ub(GrColorUnpackR(fCurrDrawState.fColor),
185 GrColorUnpackG(fCurrDrawState.fColor),
186 GrColorUnpackB(fCurrDrawState.fColor),
187 GrColorUnpackA(fCurrDrawState.fColor)));
188 fHWDrawState.fColor = fCurrDrawState.fColor;
189 }
190
191 // set texture environment, decide whether we are modulating by RGB or A.
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000192 for (int s = 0; s < kNumStages; ++s) {
193 if (usingTextures[s]) {
194 GrGLTexture* texture = (GrGLTexture*)fCurrDrawState.fTextures[s];
195 if (NULL != texture) {
bsalomon@google.com5782d712011-01-21 21:03:59 +0000196 TextureEnvRGBOperands nextRGBOperand0 =
197 (texture->config() == GrTexture::kAlpha_8_PixelConfig) ?
198 kAlpha_TextureEnvRGBOperand :
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000199 kColor_TextureEnvRGBOperand;
200 if (fHWRGBOperand0[s] != nextRGBOperand0) {
201 setTextureUnit(s);
bsalomon@google.com5782d712011-01-21 21:03:59 +0000202 GR_GL(TexEnvi(GL_TEXTURE_ENV,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000203 GL_OPERAND0_RGB,
bsalomon@google.com5782d712011-01-21 21:03:59 +0000204 (nextRGBOperand0==kAlpha_TextureEnvRGBOperand) ?
205 GL_SRC_ALPHA :
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000206 GL_SRC_COLOR));
207 fHWRGBOperand0[s] = nextRGBOperand0;
reed@google.comac10a2d2010-12-22 21:39:39 +0000208 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000209
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000210 if (((1 << s) & fDirtyFlags.fTextureChangedMask) ||
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000211 (fHWDrawState.fSamplerStates[s].getMatrix() !=
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000212 getSamplerMatrix(s))) {
213
214 GrMatrix texMat = getSamplerMatrix(s);
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000215 AdjustTextureMatrix(texture,
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000216 GrSamplerState::kNormal_SampleMode,
217 &texMat);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000218 GrGpuMatrix glm;
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000219 glm.set(texMat);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000220 setTextureUnit(s);
221 GR_GL(MatrixMode(GL_TEXTURE));
222 GR_GL(LoadMatrixf(glm.fMat));
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000223 recordHWSamplerMatrix(s, getSamplerMatrix(s));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000224 }
225 } else {
226 GrAssert(!"Rendering with texture vert flag set but no bound texture");
227 return false;
reed@google.comac10a2d2010-12-22 21:39:39 +0000228 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000229 }
230 }
231
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000232 if (fHWDrawState.fViewMatrix != fCurrDrawState.fViewMatrix) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000233 GrGpuMatrix glm;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000234 glm.set(fCurrDrawState.fViewMatrix);
235 GR_GL(MatrixMode(GL_MODELVIEW));
reed@google.comac10a2d2010-12-22 21:39:39 +0000236 GR_GL(LoadMatrixf(glm.fMat));
bsalomon@google.com5782d712011-01-21 21:03:59 +0000237 fHWDrawState.fViewMatrix =
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000238 fCurrDrawState.fViewMatrix;
reed@google.comac10a2d2010-12-22 21:39:39 +0000239 }
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000240 resetDirtyFlags();
reed@google.comac10a2d2010-12-22 21:39:39 +0000241 return true;
242}
243
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000244void GrGpuGLFixed::setupGeometry(int* startVertex,
245 int* startIndex,
246 int vertexCount,
247 int indexCount) {
bsalomon@google.com5782d712011-01-21 21:03:59 +0000248
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000249 int newColorOffset;
250 int newTexCoordOffsets[kNumStages];
bsalomon@google.com5782d712011-01-21 21:03:59 +0000251
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000252 GLsizei newStride = VertexSizeAndOffsetsByStage(fGeometrySrc.fVertexLayout,
bsalomon@google.com5782d712011-01-21 21:03:59 +0000253 newTexCoordOffsets,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000254 &newColorOffset);
255 int oldColorOffset;
256 int oldTexCoordOffsets[kNumStages];
257 GLsizei oldStride = VertexSizeAndOffsetsByStage(fHWGeometryState.fVertexLayout,
bsalomon@google.com5782d712011-01-21 21:03:59 +0000258 oldTexCoordOffsets,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000259 &oldColorOffset);
bsalomon@google.com5782d712011-01-21 21:03:59 +0000260
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000261 bool indexed = NULL != startIndex;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000262
263 int extraVertexOffset;
264 int extraIndexOffset;
265 setBuffers(indexed, &extraVertexOffset, &extraIndexOffset);
bsalomon@google.com5782d712011-01-21 21:03:59 +0000266
reed@google.comac10a2d2010-12-22 21:39:39 +0000267 GLenum scalarType;
268 if (fGeometrySrc.fVertexLayout & kTextFormat_VertexLayoutBit) {
269 scalarType = GrGLTextType;
270 } else {
271 scalarType = GrGLType;
272 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000273
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000274 size_t vertexOffset = (*startVertex + extraVertexOffset) * newStride;
275 *startVertex = 0;
276 if (indexed) {
277 *startIndex += extraIndexOffset;
278 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000279
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000280 // all the Pointers must be set if any of these are true
281 bool allOffsetsChange = fHWGeometryState.fArrayPtrsDirty ||
282 vertexOffset != fHWGeometryState.fVertexOffset ||
283 newStride != oldStride;
284
285 // position and tex coord offsets change if above conditions are true
286 // or the type changed based on text vs nontext type coords.
287 bool posAndTexChange = allOffsetsChange ||
288 ((GrGLTextType != GrGLType) &&
289 (kTextFormat_VertexLayoutBit &
290 (fHWGeometryState.fVertexLayout ^
291 fGeometrySrc.fVertexLayout)));
292
293 if (posAndTexChange) {
294 GR_GL(VertexPointer(2, scalarType, newStride, (GLvoid*)vertexOffset));
295 fHWGeometryState.fVertexOffset = vertexOffset;
reed@google.comac10a2d2010-12-22 21:39:39 +0000296 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000297
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000298 for (int s = 0; s < kNumStages; ++s) {
bsalomon@google.com5782d712011-01-21 21:03:59 +0000299 // need to enable array if tex coord offset is 0
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000300 // (using positions as coords)
301 if (newTexCoordOffsets[s] >= 0) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000302 GLvoid* texCoordOffset = (GLvoid*)(vertexOffset + newTexCoordOffsets[s]);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000303 if (oldTexCoordOffsets[s] < 0) {
304 GR_GL(ClientActiveTexture(GL_TEXTURE0+s));
305 GR_GL(EnableClientState(GL_TEXTURE_COORD_ARRAY));
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000306 GR_GL(TexCoordPointer(2, scalarType, newStride, texCoordOffset));
307 } else if (posAndTexChange ||
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +0000308 newTexCoordOffsets[s] != oldTexCoordOffsets[s]) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000309 GR_GL(ClientActiveTexture(GL_TEXTURE0+s));
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000310 GR_GL(TexCoordPointer(2, scalarType, newStride, texCoordOffset));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000311 }
312 } else if (oldTexCoordOffsets[s] >= 0) {
313 GR_GL(ClientActiveTexture(GL_TEXTURE0+s));
314 GR_GL(DisableClientState(GL_TEXTURE_COORD_ARRAY));
reed@google.comac10a2d2010-12-22 21:39:39 +0000315 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000316 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000317
reed@google.comac10a2d2010-12-22 21:39:39 +0000318 if (newColorOffset > 0) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000319 GLvoid* colorOffset = (GLvoid*)(vertexOffset + newColorOffset);
reed@google.comac10a2d2010-12-22 21:39:39 +0000320 if (oldColorOffset <= 0) {
321 GR_GL(EnableClientState(GL_COLOR_ARRAY));
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000322 GR_GL(ColorPointer(4, GL_UNSIGNED_BYTE, newStride, colorOffset));
323 } else if (allOffsetsChange || newColorOffset != oldColorOffset) {
324 GR_GL(ColorPointer(4, GL_UNSIGNED_BYTE, newStride, colorOffset));
reed@google.comac10a2d2010-12-22 21:39:39 +0000325 }
326 } else if (oldColorOffset > 0) {
327 GR_GL(DisableClientState(GL_COLOR_ARRAY));
328 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000329
reed@google.comac10a2d2010-12-22 21:39:39 +0000330 fHWGeometryState.fVertexLayout = fGeometrySrc.fVertexLayout;
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +0000331 fHWGeometryState.fArrayPtrsDirty = false;
reed@google.comac10a2d2010-12-22 21:39:39 +0000332}
333
334#endif
335