blob: 99a593daaaa9175e81369d597fd3d58085b1f725 [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 {
28 GrScalar fMat[16];
29
30 void reset() {
31 Gr_bzero(fMat, sizeof(fMat));
32 fMat[0] = fMat[5] = fMat[10] = fMat[15] = GR_Scalar1;
33 }
34
35 void set(const GrMatrix& m) {
36 Gr_bzero(fMat, sizeof(fMat));
37 fMat[0] = m[GrMatrix::kScaleX];
38 fMat[4] = m[GrMatrix::kSkewX];
39 fMat[12] = m[GrMatrix::kTransX];
40
41 fMat[1] = m[GrMatrix::kSkewY];
42 fMat[5] = m[GrMatrix::kScaleY];
43 fMat[13] = m[GrMatrix::kTransY];
44
45 fMat[3] = m[GrMatrix::kPersp0];
46 fMat[7] = m[GrMatrix::kPersp1];
47 fMat[15] = m[GrMatrix::kPersp2];
48
49 fMat[10] = GR_Scalar1; // z-scale
50 }
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);
77 GR_GL(EnableClientState(GL_VERTEX_ARRAY));
78 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));
89
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
92 // texture, e.g.:
93 //glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
94 fHWRGBOperand0[s] = (TextureEnvRGBOperands) -1;
95 }
reed@google.comac10a2d2010-12-22 21:39:39 +000096
97 fHWGeometryState.fVertexLayout = 0;
98 fHWGeometryState.fPositionPtr = (void*) ~0;
99 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));
103
104 GrGLClearErr();
105 fTextVerts = false;
106
107 fHWTextureOrientation = (GrGLTexture::Orientation)-1; // illegal
108 fBaseVertex = 0xffffffff;
109}
110
111
112void GrGpuGLFixed::flushProjectionMatrix() {
113 float mat[16];
114 Gr_bzero(mat, sizeof(mat));
115
116 GrAssert(NULL != fCurrDrawState.fRenderTarget);
117
118 mat[0] = 2.f / fCurrDrawState.fRenderTarget->width();
119 mat[5] = -2.f / fCurrDrawState.fRenderTarget->height();
120 mat[10] = -1.f;
121 mat[15] = 1;
122
123 mat[12] = -1.f;
124 mat[13] = 1.f;
125
126 GR_GL(MatrixMode(GL_PROJECTION));
127 GR_GL(LoadMatrixf(mat));
128}
129
130bool GrGpuGLFixed::flushGraphicsState(PrimitiveType type) {
131
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000132 bool usingTextures[kNumStages];
133
134 for (int s = 0; s < kNumStages; ++s) {
135 usingTextures[s] = VertexUsesStage(s, fGeometrySrc.fVertexLayout);
reed@google.comac10a2d2010-12-22 21:39:39 +0000136
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000137 if (usingTextures[s] && fCurrDrawState.fSamplerStates[s].isGradient()) {
138 unimpl("Fixed pipe doesn't support radial/sweep gradients");
139 return false;
140 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000141 }
142
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000143 if (!flushGLStateCommon(type)) {
144 return false;
145 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000146
147 if (fRenderTargetChanged) {
148 flushProjectionMatrix();
149 fRenderTargetChanged = false;
150 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000151
152 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.com8531c1c2011-01-13 19:52:45 +0000163
reed@google.comac10a2d2010-12-22 21:39:39 +0000164 uint32_t vertColor = (fGeometrySrc.fVertexLayout & kColor_VertexLayoutBit);
165 uint32_t prevVertColor = (fHWGeometryState.fVertexLayout &
166 kColor_VertexLayoutBit);
167
168 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
178 if (kPoints_PrimitiveType == type &&
179 fHWDrawState.fPointSize != fCurrDrawState.fPointSize) {
180 GR_GL(PointSize(fCurrDrawState.fPointSize));
181 fHWDrawState.fPointSize = fCurrDrawState.fPointSize;
182 }
183
184 if (!vertColor && fHWDrawState.fColor != fCurrDrawState.fColor) {
185 GR_GL(Color4ub(GrColorUnpackR(fCurrDrawState.fColor),
186 GrColorUnpackG(fCurrDrawState.fColor),
187 GrColorUnpackB(fCurrDrawState.fColor),
188 GrColorUnpackA(fCurrDrawState.fColor)));
189 fHWDrawState.fColor = fCurrDrawState.fColor;
190 }
191
192 // set texture environment, decide whether we are modulating by RGB or A.
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000193 for (int s = 0; s < kNumStages; ++s) {
194 if (usingTextures[s]) {
195 GrGLTexture* texture = (GrGLTexture*)fCurrDrawState.fTextures[s];
196 if (NULL != texture) {
197 TextureEnvRGBOperands nextRGBOperand0 =
198 (texture->config() == GrTexture::kAlpha_8_PixelConfig) ?
199 kAlpha_TextureEnvRGBOperand :
200 kColor_TextureEnvRGBOperand;
201 if (fHWRGBOperand0[s] != nextRGBOperand0) {
202 setTextureUnit(s);
203 GR_GL(TexEnvi(GL_TEXTURE_ENV,
204 GL_OPERAND0_RGB,
205 (nextRGBOperand0==kAlpha_TextureEnvRGBOperand) ?
206 GL_SRC_ALPHA :
207 GL_SRC_COLOR));
208 fHWRGBOperand0[s] = nextRGBOperand0;
reed@google.comac10a2d2010-12-22 21:39:39 +0000209 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000210
211 if (fHWTextureOrientation != texture->orientation() ||
212 fHWDrawState.fTextureMatrices[s] !=
213 fCurrDrawState.fTextureMatrices[s]) {
214 GrGpuMatrix glm;
215 if (GrGLTexture::kBottomUp_Orientation ==
216 texture->orientation()) {
217 GrMatrix m(
218 GR_Scalar1, 0, 0,
219 0, -GR_Scalar1, GR_Scalar1,
220 0, 0, GrMatrix::I()[8]
221 );
222 m.preConcat(fCurrDrawState.fTextureMatrices[s]);
223 glm.set(m);
224 } else {
225 glm.set(fCurrDrawState.fTextureMatrices[s]);
226 }
227 setTextureUnit(s);
228 GR_GL(MatrixMode(GL_TEXTURE));
229 GR_GL(LoadMatrixf(glm.fMat));
230 fHWDrawState.fTextureMatrices[s] =
231 fCurrDrawState.fTextureMatrices[s];
232 fHWTextureOrientation = texture->orientation();
233 }
234 } else {
235 GrAssert(!"Rendering with texture vert flag set but no bound texture");
236 return false;
reed@google.comac10a2d2010-12-22 21:39:39 +0000237 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000238 }
239 }
240
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000241 if (fHWDrawState.fViewMatrix != fCurrDrawState.fViewMatrix) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000242 GrGpuMatrix glm;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000243 glm.set(fCurrDrawState.fViewMatrix);
244 GR_GL(MatrixMode(GL_MODELVIEW));
reed@google.comac10a2d2010-12-22 21:39:39 +0000245 GR_GL(LoadMatrixf(glm.fMat));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000246 fHWDrawState.fViewMatrix =
247 fCurrDrawState.fViewMatrix;
reed@google.comac10a2d2010-12-22 21:39:39 +0000248 }
249 return true;
250}
251
252void GrGpuGLFixed::setupGeometry(uint32_t startVertex,
253 uint32_t startIndex,
254 uint32_t vertexCount,
255 uint32_t indexCount) {
256
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000257 int newColorOffset;
258 int newTexCoordOffsets[kNumStages];
reed@google.comac10a2d2010-12-22 21:39:39 +0000259
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000260 GLsizei newStride = VertexSizeAndOffsetsByStage(fGeometrySrc.fVertexLayout,
261 newTexCoordOffsets,
262 &newColorOffset);
263 int oldColorOffset;
264 int oldTexCoordOffsets[kNumStages];
265 GLsizei oldStride = VertexSizeAndOffsetsByStage(fHWGeometryState.fVertexLayout,
266 oldTexCoordOffsets,
267 &oldColorOffset);
reed@google.comac10a2d2010-12-22 21:39:39 +0000268
269 const GLvoid* posPtr = (GLvoid*)(newStride * startVertex);
270
271 if (kBuffer_GeometrySrcType == fGeometrySrc.fVertexSrc) {
272 GrAssert(NULL != fGeometrySrc.fVertexBuffer);
273 GrAssert(!fGeometrySrc.fVertexBuffer->isLocked());
274 if (fHWGeometryState.fVertexBuffer != fGeometrySrc.fVertexBuffer) {
275 GrGLVertexBuffer* buf =
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000276 (GrGLVertexBuffer*)fGeometrySrc.fVertexBuffer;
reed@google.comac10a2d2010-12-22 21:39:39 +0000277 GR_GL(BindBuffer(GL_ARRAY_BUFFER, buf->bufferID()));
278 fHWGeometryState.fVertexBuffer = fGeometrySrc.fVertexBuffer;
279 }
280 } else {
281 if (kArray_GeometrySrcType == fGeometrySrc.fVertexSrc) {
282 posPtr = (void*)((intptr_t)fGeometrySrc.fVertexArray +
283 (intptr_t)posPtr);
284 } else {
285 GrAssert(kReserved_GeometrySrcType == fGeometrySrc.fVertexSrc);
286 posPtr = (void*)((intptr_t)fVertices.get() + (intptr_t)posPtr);
287 }
288 if (NULL != fHWGeometryState.fVertexBuffer) {
289 GR_GL(BindBuffer(GL_ARRAY_BUFFER, 0));
290 fHWGeometryState.fVertexBuffer = NULL;
291 }
292 }
293
294 if (kBuffer_GeometrySrcType == fGeometrySrc.fIndexSrc) {
295 GrAssert(NULL != fGeometrySrc.fIndexBuffer);
296 GrAssert(!fGeometrySrc.fIndexBuffer->isLocked());
297 if (fHWGeometryState.fIndexBuffer != fGeometrySrc.fIndexBuffer) {
298 GrGLIndexBuffer* buf =
299 (GrGLIndexBuffer*)fGeometrySrc.fIndexBuffer;
300 GR_GL(BindBuffer(GL_ELEMENT_ARRAY_BUFFER, buf->bufferID()));
301 fHWGeometryState.fIndexBuffer = fGeometrySrc.fIndexBuffer;
302 }
303 } else if (NULL != fHWGeometryState.fIndexBuffer) {
304 GR_GL(BindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
305 fHWGeometryState.fIndexBuffer = NULL;
306 }
307
308 GLenum scalarType;
309 if (fGeometrySrc.fVertexLayout & kTextFormat_VertexLayoutBit) {
310 scalarType = GrGLTextType;
311 } else {
312 scalarType = GrGLType;
313 }
314
315 bool baseChange = posPtr != fHWGeometryState.fPositionPtr;
316 bool scalarChange =
317 (GrGLTextType != GrGLType) &&
318 (kTextFormat_VertexLayoutBit &
319 (fHWGeometryState.fVertexLayout ^ fGeometrySrc.fVertexLayout));
320 bool strideChange = newStride != oldStride;
321 bool posChange = baseChange || scalarChange || strideChange;
322
323 if (posChange) {
324 GR_GL(VertexPointer(2, scalarType, newStride, posPtr));
325 fHWGeometryState.fPositionPtr = posPtr;
326 }
327
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000328 for (int s = 0; s < kNumStages; ++s) {
329 // need to enable array if tex coord offset is 0
330 // (using positions as coords)
331 if (newTexCoordOffsets[s] >= 0) {
332 GLvoid* texCoordPtr = (int8_t*)posPtr + newTexCoordOffsets[s];
333 if (oldTexCoordOffsets[s] < 0) {
334 GR_GL(ClientActiveTexture(GL_TEXTURE0+s));
335 GR_GL(EnableClientState(GL_TEXTURE_COORD_ARRAY));
336 }
337 if (posChange || newTexCoordOffsets[s] != oldTexCoordOffsets[s]) {
338 GR_GL(ClientActiveTexture(GL_TEXTURE0+s));
339 GR_GL(TexCoordPointer(2, scalarType, newStride, texCoordPtr));
340 }
341 } else if (oldTexCoordOffsets[s] >= 0) {
342 GR_GL(ClientActiveTexture(GL_TEXTURE0+s));
343 GR_GL(DisableClientState(GL_TEXTURE_COORD_ARRAY));
reed@google.comac10a2d2010-12-22 21:39:39 +0000344 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000345 }
346
347 if (newColorOffset > 0) {
348 GLvoid* colorPtr = (int8_t*)posPtr + newColorOffset;
349 if (oldColorOffset <= 0) {
350 GR_GL(EnableClientState(GL_COLOR_ARRAY));
351 }
352 if (posChange || newColorOffset != oldColorOffset) {
353 GR_GL(ColorPointer(4, GL_UNSIGNED_BYTE, newStride, colorPtr));
354 }
355 } else if (oldColorOffset > 0) {
356 GR_GL(DisableClientState(GL_COLOR_ARRAY));
357 }
358
359 fHWGeometryState.fVertexLayout = fGeometrySrc.fVertexLayout;
360}
361
362#endif
363