blob: 516381e308cce37ef64a7331e38eb7163f24035b [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() {
61 resetContextHelper();
62}
63
64GrGpuGLFixed::~GrGpuGLFixed() {
65}
66
67void GrGpuGLFixed::resetContext() {
68 INHERITED::resetContext();
69 resetContextHelper();
70}
71
72void GrGpuGLFixed::resetContextHelper() {
73 GR_GL(Disable(GL_TEXTURE_2D));
74
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000075 for (int s = 0; s < kNumStages; ++s) {
76 setTextureUnit(s);
bsalomon@google.com5782d712011-01-21 21:03:59 +000077 GR_GL(EnableClientState(GL_VERTEX_ARRAY));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000078 GR_GL(TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE));
79 GR_GL(TexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE));
80 GR_GL(TexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_TEXTURE0+s));
81 GR_GL(TexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_PREVIOUS));
82 GR_GL(TexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR));
reed@google.comac10a2d2010-12-22 21:39:39 +000083
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000084 GR_GL(TexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE));
85 GR_GL(TexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_TEXTURE0+s));
86 GR_GL(TexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA));
87 GR_GL(TexEnvi(GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_PREVIOUS));
88 GR_GL(TexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA));
bsalomon@google.com5782d712011-01-21 21:03:59 +000089
90 // color oprand0 changes between GL_SRC_COLR and GL_SRC_ALPHA depending
91 // upon whether we have a (premultiplied) RGBA texture or just an ALPHA
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000092 // texture, e.g.:
93 //glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
bsalomon@google.com5782d712011-01-21 21:03:59 +000094 fHWRGBOperand0[s] = (TextureEnvRGBOperands) -1;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000095 }
reed@google.comac10a2d2010-12-22 21:39:39 +000096
97 fHWGeometryState.fVertexLayout = 0;
bsalomon@google.com1c13c962011-02-14 16:51:21 +000098 fHWGeometryState.fVertexOffset = ~0;
reed@google.comac10a2d2010-12-22 21:39:39 +000099 GR_GL(EnableClientState(GL_VERTEX_ARRAY));
100 GR_GL(DisableClientState(GL_TEXTURE_COORD_ARRAY));
101 GR_GL(ShadeModel(GL_FLAT));
102 GR_GL(DisableClientState(GL_COLOR_ARRAY));
bsalomon@google.com5782d712011-01-21 21:03:59 +0000103
104 GR_GL(PointSize(1.f));
105
reed@google.comac10a2d2010-12-22 21:39:39 +0000106 GrGLClearErr();
107 fTextVerts = false;
108
reed@google.comac10a2d2010-12-22 21:39:39 +0000109 fBaseVertex = 0xffffffff;
110}
111
112
113void GrGpuGLFixed::flushProjectionMatrix() {
114 float mat[16];
115 Gr_bzero(mat, sizeof(mat));
bsalomon@google.com5782d712011-01-21 21:03:59 +0000116
reed@google.comac10a2d2010-12-22 21:39:39 +0000117 GrAssert(NULL != fCurrDrawState.fRenderTarget);
bsalomon@google.com5782d712011-01-21 21:03:59 +0000118
reed@google.comac10a2d2010-12-22 21:39:39 +0000119 mat[0] = 2.f / fCurrDrawState.fRenderTarget->width();
120 mat[5] = -2.f / fCurrDrawState.fRenderTarget->height();
121 mat[10] = -1.f;
122 mat[15] = 1;
bsalomon@google.com5782d712011-01-21 21:03:59 +0000123
reed@google.comac10a2d2010-12-22 21:39:39 +0000124 mat[12] = -1.f;
125 mat[13] = 1.f;
bsalomon@google.com5782d712011-01-21 21:03:59 +0000126
reed@google.comac10a2d2010-12-22 21:39:39 +0000127 GR_GL(MatrixMode(GL_PROJECTION));
128 GR_GL(LoadMatrixf(mat));
129}
130
bsalomon@google.comffca4002011-02-22 20:34:01 +0000131bool GrGpuGLFixed::flushGraphicsState(GrPrimitiveType type) {
bsalomon@google.com5782d712011-01-21 21:03:59 +0000132
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000133 bool usingTextures[kNumStages];
bsalomon@google.com5782d712011-01-21 21:03:59 +0000134
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000135 for (int s = 0; s < kNumStages; ++s) {
136 usingTextures[s] = VertexUsesStage(s, fGeometrySrc.fVertexLayout);
reed@google.comac10a2d2010-12-22 21:39:39 +0000137
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000138 if (usingTextures[s] && fCurrDrawState.fSamplerStates[s].isGradient()) {
139 unimpl("Fixed pipe doesn't support radial/sweep gradients");
140 return false;
141 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000142 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000143
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000144 if (!flushGLStateCommon(type)) {
145 return false;
146 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000147
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000148 if (fDirtyFlags.fRenderTargetChanged) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000149 flushProjectionMatrix();
reed@google.comac10a2d2010-12-22 21:39:39 +0000150 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000151
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000152 for (int s = 0; s < kNumStages; ++s) {
153 bool wasUsingTexture = VertexUsesStage(s, fHWGeometryState.fVertexLayout);
154 if (usingTextures[s] != wasUsingTexture) {
155 setTextureUnit(s);
156 if (usingTextures[s]) {
157 GR_GL(Enable(GL_TEXTURE_2D));
158 } else {
159 GR_GL(Disable(GL_TEXTURE_2D));
160 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000161 }
162 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000163
reed@google.comac10a2d2010-12-22 21:39:39 +0000164 uint32_t vertColor = (fGeometrySrc.fVertexLayout & kColor_VertexLayoutBit);
bsalomon@google.com5782d712011-01-21 21:03:59 +0000165 uint32_t prevVertColor = (fHWGeometryState.fVertexLayout &
reed@google.comac10a2d2010-12-22 21:39:39 +0000166 kColor_VertexLayoutBit);
bsalomon@google.com5782d712011-01-21 21:03:59 +0000167
reed@google.comac10a2d2010-12-22 21:39:39 +0000168 if (vertColor != prevVertColor) {
169 if (vertColor) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000170 GR_GL(ShadeModel(GL_SMOOTH));
171 // invalidate the immediate mode color
172 fHWDrawState.fColor = GrColor_ILLEGAL;
173 } else {
174 GR_GL(ShadeModel(GL_FLAT));
175 }
176 }
177
bsalomon@google.com5782d712011-01-21 21:03:59 +0000178
reed@google.comac10a2d2010-12-22 21:39:39 +0000179 if (!vertColor && fHWDrawState.fColor != fCurrDrawState.fColor) {
180 GR_GL(Color4ub(GrColorUnpackR(fCurrDrawState.fColor),
181 GrColorUnpackG(fCurrDrawState.fColor),
182 GrColorUnpackB(fCurrDrawState.fColor),
183 GrColorUnpackA(fCurrDrawState.fColor)));
184 fHWDrawState.fColor = fCurrDrawState.fColor;
185 }
186
187 // set texture environment, decide whether we are modulating by RGB or A.
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000188 for (int s = 0; s < kNumStages; ++s) {
189 if (usingTextures[s]) {
190 GrGLTexture* texture = (GrGLTexture*)fCurrDrawState.fTextures[s];
191 if (NULL != texture) {
bsalomon@google.com5782d712011-01-21 21:03:59 +0000192 TextureEnvRGBOperands nextRGBOperand0 =
193 (texture->config() == GrTexture::kAlpha_8_PixelConfig) ?
194 kAlpha_TextureEnvRGBOperand :
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000195 kColor_TextureEnvRGBOperand;
196 if (fHWRGBOperand0[s] != nextRGBOperand0) {
197 setTextureUnit(s);
bsalomon@google.com5782d712011-01-21 21:03:59 +0000198 GR_GL(TexEnvi(GL_TEXTURE_ENV,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000199 GL_OPERAND0_RGB,
bsalomon@google.com5782d712011-01-21 21:03:59 +0000200 (nextRGBOperand0==kAlpha_TextureEnvRGBOperand) ?
201 GL_SRC_ALPHA :
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000202 GL_SRC_COLOR));
203 fHWRGBOperand0[s] = nextRGBOperand0;
reed@google.comac10a2d2010-12-22 21:39:39 +0000204 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000205
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000206 if (((1 << s) & fDirtyFlags.fTextureChangedMask) ||
207 (fHWDrawState.fSamplerStates[s].getMatrix() !=
208 getSamplerMatrix(s))) {
209
210 GrMatrix texMat = getSamplerMatrix(s);
211 AdjustTextureMatrix(texture,
212 GrSamplerState::kNormal_SampleMode,
213 &texMat);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000214 GrGpuMatrix glm;
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000215 glm.set(texMat);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000216 setTextureUnit(s);
217 GR_GL(MatrixMode(GL_TEXTURE));
218 GR_GL(LoadMatrixf(glm.fMat));
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000219 recordHWSamplerMatrix(s, getSamplerMatrix(s));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000220 }
221 } else {
222 GrAssert(!"Rendering with texture vert flag set but no bound texture");
223 return false;
reed@google.comac10a2d2010-12-22 21:39:39 +0000224 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000225 }
226 }
227
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000228 if (fHWDrawState.fViewMatrix != fCurrDrawState.fViewMatrix) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000229 GrGpuMatrix glm;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000230 glm.set(fCurrDrawState.fViewMatrix);
231 GR_GL(MatrixMode(GL_MODELVIEW));
reed@google.comac10a2d2010-12-22 21:39:39 +0000232 GR_GL(LoadMatrixf(glm.fMat));
bsalomon@google.com5782d712011-01-21 21:03:59 +0000233 fHWDrawState.fViewMatrix =
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000234 fCurrDrawState.fViewMatrix;
reed@google.comac10a2d2010-12-22 21:39:39 +0000235 }
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000236 resetDirtyFlags();
reed@google.comac10a2d2010-12-22 21:39:39 +0000237 return true;
238}
239
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000240void GrGpuGLFixed::setupGeometry(int* startVertex,
241 int* startIndex,
242 int vertexCount,
243 int indexCount) {
bsalomon@google.com5782d712011-01-21 21:03:59 +0000244
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000245 int newColorOffset;
246 int newTexCoordOffsets[kNumStages];
bsalomon@google.com5782d712011-01-21 21:03:59 +0000247
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000248 GLsizei newStride = VertexSizeAndOffsetsByStage(fGeometrySrc.fVertexLayout,
bsalomon@google.com5782d712011-01-21 21:03:59 +0000249 newTexCoordOffsets,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000250 &newColorOffset);
251 int oldColorOffset;
252 int oldTexCoordOffsets[kNumStages];
253 GLsizei oldStride = VertexSizeAndOffsetsByStage(fHWGeometryState.fVertexLayout,
bsalomon@google.com5782d712011-01-21 21:03:59 +0000254 oldTexCoordOffsets,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000255 &oldColorOffset);
bsalomon@google.com5782d712011-01-21 21:03:59 +0000256
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000257 bool indexed = NULL != startIndex;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000258
259 int extraVertexOffset;
260 int extraIndexOffset;
261 setBuffers(indexed, &extraVertexOffset, &extraIndexOffset);
bsalomon@google.com5782d712011-01-21 21:03:59 +0000262
reed@google.comac10a2d2010-12-22 21:39:39 +0000263 GLenum scalarType;
264 if (fGeometrySrc.fVertexLayout & kTextFormat_VertexLayoutBit) {
265 scalarType = GrGLTextType;
266 } else {
267 scalarType = GrGLType;
268 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000269
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000270 size_t vertexOffset = (*startVertex + extraVertexOffset) * newStride;
271 *startVertex = 0;
272 if (indexed) {
273 *startIndex += extraIndexOffset;
274 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000275
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000276 // all the Pointers must be set if any of these are true
277 bool allOffsetsChange = fHWGeometryState.fArrayPtrsDirty ||
278 vertexOffset != fHWGeometryState.fVertexOffset ||
279 newStride != oldStride;
280
281 // position and tex coord offsets change if above conditions are true
282 // or the type changed based on text vs nontext type coords.
283 bool posAndTexChange = allOffsetsChange ||
284 ((GrGLTextType != GrGLType) &&
285 (kTextFormat_VertexLayoutBit &
286 (fHWGeometryState.fVertexLayout ^
287 fGeometrySrc.fVertexLayout)));
288
289 if (posAndTexChange) {
290 GR_GL(VertexPointer(2, scalarType, newStride, (GLvoid*)vertexOffset));
291 fHWGeometryState.fVertexOffset = vertexOffset;
reed@google.comac10a2d2010-12-22 21:39:39 +0000292 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000293
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000294 for (int s = 0; s < kNumStages; ++s) {
bsalomon@google.com5782d712011-01-21 21:03:59 +0000295 // need to enable array if tex coord offset is 0
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000296 // (using positions as coords)
297 if (newTexCoordOffsets[s] >= 0) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000298 GLvoid* texCoordOffset = (GLvoid*)(vertexOffset + newTexCoordOffsets[s]);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000299 if (oldTexCoordOffsets[s] < 0) {
300 GR_GL(ClientActiveTexture(GL_TEXTURE0+s));
301 GR_GL(EnableClientState(GL_TEXTURE_COORD_ARRAY));
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000302 GR_GL(TexCoordPointer(2, scalarType, newStride, texCoordOffset));
303 } else if (posAndTexChange ||
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +0000304 newTexCoordOffsets[s] != oldTexCoordOffsets[s]) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000305 GR_GL(ClientActiveTexture(GL_TEXTURE0+s));
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000306 GR_GL(TexCoordPointer(2, scalarType, newStride, texCoordOffset));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000307 }
308 } else if (oldTexCoordOffsets[s] >= 0) {
309 GR_GL(ClientActiveTexture(GL_TEXTURE0+s));
310 GR_GL(DisableClientState(GL_TEXTURE_COORD_ARRAY));
reed@google.comac10a2d2010-12-22 21:39:39 +0000311 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000312 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000313
reed@google.comac10a2d2010-12-22 21:39:39 +0000314 if (newColorOffset > 0) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000315 GLvoid* colorOffset = (GLvoid*)(vertexOffset + newColorOffset);
reed@google.comac10a2d2010-12-22 21:39:39 +0000316 if (oldColorOffset <= 0) {
317 GR_GL(EnableClientState(GL_COLOR_ARRAY));
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000318 GR_GL(ColorPointer(4, GL_UNSIGNED_BYTE, newStride, colorOffset));
319 } else if (allOffsetsChange || newColorOffset != oldColorOffset) {
320 GR_GL(ColorPointer(4, GL_UNSIGNED_BYTE, newStride, colorOffset));
reed@google.comac10a2d2010-12-22 21:39:39 +0000321 }
322 } else if (oldColorOffset > 0) {
323 GR_GL(DisableClientState(GL_COLOR_ARRAY));
324 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000325
reed@google.comac10a2d2010-12-22 21:39:39 +0000326 fHWGeometryState.fVertexLayout = fGeometrySrc.fVertexLayout;
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +0000327 fHWGeometryState.fArrayPtrsDirty = false;
reed@google.comac10a2d2010-12-22 21:39:39 +0000328}
329
330#endif
331