blob: 3fd8d5c866affc2052eeddf1106503b163835508 [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];
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));
37 fMat[0] = m[GrMatrix::kScaleX];
38 fMat[4] = m[GrMatrix::kSkewX];
39 fMat[12] = m[GrMatrix::kTransX];
bsalomon@google.com5782d712011-01-21 21:03:59 +000040
reed@google.comac10a2d2010-12-22 21:39:39 +000041 fMat[1] = m[GrMatrix::kSkewY];
42 fMat[5] = m[GrMatrix::kScaleY];
43 fMat[13] = m[GrMatrix::kTransY];
bsalomon@google.com5782d712011-01-21 21:03:59 +000044
reed@google.comac10a2d2010-12-22 21:39:39 +000045 fMat[3] = m[GrMatrix::kPersp0];
46 fMat[7] = m[GrMatrix::kPersp1];
47 fMat[15] = m[GrMatrix::kPersp2];
bsalomon@google.com5782d712011-01-21 21:03:59 +000048
reed@google.comac10a2d2010-12-22 21:39:39 +000049 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);
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;
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));
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
bsalomon@google.com5782d712011-01-21 21:03:59 +0000109 fHWTextureOrientation = (GrGLTexture::Orientation)-1; // illegal
reed@google.comac10a2d2010-12-22 21:39:39 +0000110 fBaseVertex = 0xffffffff;
111}
112
113
114void GrGpuGLFixed::flushProjectionMatrix() {
115 float mat[16];
116 Gr_bzero(mat, sizeof(mat));
bsalomon@google.com5782d712011-01-21 21:03:59 +0000117
reed@google.comac10a2d2010-12-22 21:39:39 +0000118 GrAssert(NULL != fCurrDrawState.fRenderTarget);
bsalomon@google.com5782d712011-01-21 21:03:59 +0000119
reed@google.comac10a2d2010-12-22 21:39:39 +0000120 mat[0] = 2.f / fCurrDrawState.fRenderTarget->width();
121 mat[5] = -2.f / fCurrDrawState.fRenderTarget->height();
122 mat[10] = -1.f;
123 mat[15] = 1;
bsalomon@google.com5782d712011-01-21 21:03:59 +0000124
reed@google.comac10a2d2010-12-22 21:39:39 +0000125 mat[12] = -1.f;
126 mat[13] = 1.f;
bsalomon@google.com5782d712011-01-21 21:03:59 +0000127
reed@google.comac10a2d2010-12-22 21:39:39 +0000128 GR_GL(MatrixMode(GL_PROJECTION));
129 GR_GL(LoadMatrixf(mat));
130}
131
132bool GrGpuGLFixed::flushGraphicsState(PrimitiveType type) {
bsalomon@google.com5782d712011-01-21 21:03:59 +0000133
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000134 bool usingTextures[kNumStages];
bsalomon@google.com5782d712011-01-21 21:03:59 +0000135
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000136 for (int s = 0; s < kNumStages; ++s) {
137 usingTextures[s] = VertexUsesStage(s, fGeometrySrc.fVertexLayout);
reed@google.comac10a2d2010-12-22 21:39:39 +0000138
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000139 if (usingTextures[s] && fCurrDrawState.fSamplerStates[s].isGradient()) {
140 unimpl("Fixed pipe doesn't support radial/sweep gradients");
141 return false;
142 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000143 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000144
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000145 if (!flushGLStateCommon(type)) {
146 return false;
147 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000148
bsalomon@google.com5782d712011-01-21 21:03:59 +0000149 if (fRenderTargetChanged) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000150 flushProjectionMatrix();
151 fRenderTargetChanged = false;
152 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000153
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000154 for (int s = 0; s < kNumStages; ++s) {
155 bool wasUsingTexture = VertexUsesStage(s, fHWGeometryState.fVertexLayout);
156 if (usingTextures[s] != wasUsingTexture) {
157 setTextureUnit(s);
158 if (usingTextures[s]) {
159 GR_GL(Enable(GL_TEXTURE_2D));
160 } else {
161 GR_GL(Disable(GL_TEXTURE_2D));
162 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000163 }
164 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000165
reed@google.comac10a2d2010-12-22 21:39:39 +0000166 uint32_t vertColor = (fGeometrySrc.fVertexLayout & kColor_VertexLayoutBit);
bsalomon@google.com5782d712011-01-21 21:03:59 +0000167 uint32_t prevVertColor = (fHWGeometryState.fVertexLayout &
reed@google.comac10a2d2010-12-22 21:39:39 +0000168 kColor_VertexLayoutBit);
bsalomon@google.com5782d712011-01-21 21:03:59 +0000169
reed@google.comac10a2d2010-12-22 21:39:39 +0000170 if (vertColor != prevVertColor) {
171 if (vertColor) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000172 GR_GL(ShadeModel(GL_SMOOTH));
173 // invalidate the immediate mode color
174 fHWDrawState.fColor = GrColor_ILLEGAL;
175 } else {
176 GR_GL(ShadeModel(GL_FLAT));
177 }
178 }
179
bsalomon@google.com5782d712011-01-21 21:03:59 +0000180
reed@google.comac10a2d2010-12-22 21:39:39 +0000181 if (!vertColor && fHWDrawState.fColor != fCurrDrawState.fColor) {
182 GR_GL(Color4ub(GrColorUnpackR(fCurrDrawState.fColor),
183 GrColorUnpackG(fCurrDrawState.fColor),
184 GrColorUnpackB(fCurrDrawState.fColor),
185 GrColorUnpackA(fCurrDrawState.fColor)));
186 fHWDrawState.fColor = fCurrDrawState.fColor;
187 }
188
189 // set texture environment, decide whether we are modulating by RGB or A.
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000190 for (int s = 0; s < kNumStages; ++s) {
191 if (usingTextures[s]) {
192 GrGLTexture* texture = (GrGLTexture*)fCurrDrawState.fTextures[s];
193 if (NULL != texture) {
bsalomon@google.com5782d712011-01-21 21:03:59 +0000194 TextureEnvRGBOperands nextRGBOperand0 =
195 (texture->config() == GrTexture::kAlpha_8_PixelConfig) ?
196 kAlpha_TextureEnvRGBOperand :
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000197 kColor_TextureEnvRGBOperand;
198 if (fHWRGBOperand0[s] != nextRGBOperand0) {
199 setTextureUnit(s);
bsalomon@google.com5782d712011-01-21 21:03:59 +0000200 GR_GL(TexEnvi(GL_TEXTURE_ENV,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000201 GL_OPERAND0_RGB,
bsalomon@google.com5782d712011-01-21 21:03:59 +0000202 (nextRGBOperand0==kAlpha_TextureEnvRGBOperand) ?
203 GL_SRC_ALPHA :
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000204 GL_SRC_COLOR));
205 fHWRGBOperand0[s] = nextRGBOperand0;
reed@google.comac10a2d2010-12-22 21:39:39 +0000206 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000207
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000208 if (fHWTextureOrientation != texture->orientation() ||
bsalomon@google.com5782d712011-01-21 21:03:59 +0000209 fHWDrawState.fTextureMatrices[s] !=
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000210 fCurrDrawState.fTextureMatrices[s]) {
211 GrGpuMatrix glm;
bsalomon@google.com5782d712011-01-21 21:03:59 +0000212 if (GrGLTexture::kBottomUp_Orientation ==
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000213 texture->orientation()) {
214 GrMatrix m(
215 GR_Scalar1, 0, 0,
216 0, -GR_Scalar1, GR_Scalar1,
217 0, 0, GrMatrix::I()[8]
218 );
219 m.preConcat(fCurrDrawState.fTextureMatrices[s]);
220 glm.set(m);
221 } else {
222 glm.set(fCurrDrawState.fTextureMatrices[s]);
223 }
224 setTextureUnit(s);
225 GR_GL(MatrixMode(GL_TEXTURE));
226 GR_GL(LoadMatrixf(glm.fMat));
bsalomon@google.com5782d712011-01-21 21:03:59 +0000227 fHWDrawState.fTextureMatrices[s] =
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000228 fCurrDrawState.fTextureMatrices[s];
229 fHWTextureOrientation = texture->orientation();
230 }
231 } else {
232 GrAssert(!"Rendering with texture vert flag set but no bound texture");
233 return false;
reed@google.comac10a2d2010-12-22 21:39:39 +0000234 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000235 }
236 }
237
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000238 if (fHWDrawState.fViewMatrix != fCurrDrawState.fViewMatrix) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000239 GrGpuMatrix glm;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000240 glm.set(fCurrDrawState.fViewMatrix);
241 GR_GL(MatrixMode(GL_MODELVIEW));
reed@google.comac10a2d2010-12-22 21:39:39 +0000242 GR_GL(LoadMatrixf(glm.fMat));
bsalomon@google.com5782d712011-01-21 21:03:59 +0000243 fHWDrawState.fViewMatrix =
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000244 fCurrDrawState.fViewMatrix;
reed@google.comac10a2d2010-12-22 21:39:39 +0000245 }
246 return true;
247}
248
249void GrGpuGLFixed::setupGeometry(uint32_t startVertex,
250 uint32_t startIndex,
251 uint32_t vertexCount,
252 uint32_t indexCount) {
bsalomon@google.com5782d712011-01-21 21:03:59 +0000253
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000254 int newColorOffset;
255 int newTexCoordOffsets[kNumStages];
bsalomon@google.com5782d712011-01-21 21:03:59 +0000256
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000257 GLsizei newStride = VertexSizeAndOffsetsByStage(fGeometrySrc.fVertexLayout,
bsalomon@google.com5782d712011-01-21 21:03:59 +0000258 newTexCoordOffsets,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000259 &newColorOffset);
260 int oldColorOffset;
261 int oldTexCoordOffsets[kNumStages];
262 GLsizei oldStride = VertexSizeAndOffsetsByStage(fHWGeometryState.fVertexLayout,
bsalomon@google.com5782d712011-01-21 21:03:59 +0000263 oldTexCoordOffsets,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000264 &oldColorOffset);
bsalomon@google.com5782d712011-01-21 21:03:59 +0000265
reed@google.comac10a2d2010-12-22 21:39:39 +0000266 const GLvoid* posPtr = (GLvoid*)(newStride * startVertex);
bsalomon@google.com5782d712011-01-21 21:03:59 +0000267
reed@google.comac10a2d2010-12-22 21:39:39 +0000268 if (kBuffer_GeometrySrcType == fGeometrySrc.fVertexSrc) {
269 GrAssert(NULL != fGeometrySrc.fVertexBuffer);
270 GrAssert(!fGeometrySrc.fVertexBuffer->isLocked());
271 if (fHWGeometryState.fVertexBuffer != fGeometrySrc.fVertexBuffer) {
bsalomon@google.com5782d712011-01-21 21:03:59 +0000272 GrGLVertexBuffer* buf =
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000273 (GrGLVertexBuffer*)fGeometrySrc.fVertexBuffer;
reed@google.comac10a2d2010-12-22 21:39:39 +0000274 GR_GL(BindBuffer(GL_ARRAY_BUFFER, buf->bufferID()));
275 fHWGeometryState.fVertexBuffer = fGeometrySrc.fVertexBuffer;
276 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000277 } else {
reed@google.comac10a2d2010-12-22 21:39:39 +0000278 if (kArray_GeometrySrcType == fGeometrySrc.fVertexSrc) {
bsalomon@google.com5782d712011-01-21 21:03:59 +0000279 posPtr = (void*)((intptr_t)fGeometrySrc.fVertexArray +
reed@google.comac10a2d2010-12-22 21:39:39 +0000280 (intptr_t)posPtr);
281 } else {
282 GrAssert(kReserved_GeometrySrcType == fGeometrySrc.fVertexSrc);
bsalomon@google.com5782d712011-01-21 21:03:59 +0000283 posPtr = (void*)((intptr_t)fVertices.get() + (intptr_t)posPtr);
reed@google.comac10a2d2010-12-22 21:39:39 +0000284 }
285 if (NULL != fHWGeometryState.fVertexBuffer) {
286 GR_GL(BindBuffer(GL_ARRAY_BUFFER, 0));
287 fHWGeometryState.fVertexBuffer = NULL;
288 }
289 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000290
reed@google.comac10a2d2010-12-22 21:39:39 +0000291 if (kBuffer_GeometrySrcType == fGeometrySrc.fIndexSrc) {
292 GrAssert(NULL != fGeometrySrc.fIndexBuffer);
293 GrAssert(!fGeometrySrc.fIndexBuffer->isLocked());
294 if (fHWGeometryState.fIndexBuffer != fGeometrySrc.fIndexBuffer) {
bsalomon@google.com5782d712011-01-21 21:03:59 +0000295 GrGLIndexBuffer* buf =
reed@google.comac10a2d2010-12-22 21:39:39 +0000296 (GrGLIndexBuffer*)fGeometrySrc.fIndexBuffer;
297 GR_GL(BindBuffer(GL_ELEMENT_ARRAY_BUFFER, buf->bufferID()));
298 fHWGeometryState.fIndexBuffer = fGeometrySrc.fIndexBuffer;
299 }
300 } else if (NULL != fHWGeometryState.fIndexBuffer) {
301 GR_GL(BindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
302 fHWGeometryState.fIndexBuffer = NULL;
303 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000304
reed@google.comac10a2d2010-12-22 21:39:39 +0000305 GLenum scalarType;
306 if (fGeometrySrc.fVertexLayout & kTextFormat_VertexLayoutBit) {
307 scalarType = GrGLTextType;
308 } else {
309 scalarType = GrGLType;
310 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000311
reed@google.comac10a2d2010-12-22 21:39:39 +0000312 bool baseChange = posPtr != fHWGeometryState.fPositionPtr;
bsalomon@google.com5782d712011-01-21 21:03:59 +0000313 bool scalarChange =
reed@google.comac10a2d2010-12-22 21:39:39 +0000314 (GrGLTextType != GrGLType) &&
315 (kTextFormat_VertexLayoutBit &
316 (fHWGeometryState.fVertexLayout ^ fGeometrySrc.fVertexLayout));
317 bool strideChange = newStride != oldStride;
318 bool posChange = baseChange || scalarChange || strideChange;
bsalomon@google.com5782d712011-01-21 21:03:59 +0000319
reed@google.comac10a2d2010-12-22 21:39:39 +0000320 if (posChange) {
321 GR_GL(VertexPointer(2, scalarType, newStride, posPtr));
322 fHWGeometryState.fPositionPtr = posPtr;
323 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000324
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000325 for (int s = 0; s < kNumStages; ++s) {
bsalomon@google.com5782d712011-01-21 21:03:59 +0000326 // need to enable array if tex coord offset is 0
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000327 // (using positions as coords)
328 if (newTexCoordOffsets[s] >= 0) {
329 GLvoid* texCoordPtr = (int8_t*)posPtr + newTexCoordOffsets[s];
330 if (oldTexCoordOffsets[s] < 0) {
331 GR_GL(ClientActiveTexture(GL_TEXTURE0+s));
332 GR_GL(EnableClientState(GL_TEXTURE_COORD_ARRAY));
333 }
334 if (posChange || newTexCoordOffsets[s] != oldTexCoordOffsets[s]) {
335 GR_GL(ClientActiveTexture(GL_TEXTURE0+s));
336 GR_GL(TexCoordPointer(2, scalarType, newStride, texCoordPtr));
337 }
338 } else if (oldTexCoordOffsets[s] >= 0) {
339 GR_GL(ClientActiveTexture(GL_TEXTURE0+s));
340 GR_GL(DisableClientState(GL_TEXTURE_COORD_ARRAY));
reed@google.comac10a2d2010-12-22 21:39:39 +0000341 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000342 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000343
reed@google.comac10a2d2010-12-22 21:39:39 +0000344 if (newColorOffset > 0) {
345 GLvoid* colorPtr = (int8_t*)posPtr + newColorOffset;
346 if (oldColorOffset <= 0) {
347 GR_GL(EnableClientState(GL_COLOR_ARRAY));
348 }
349 if (posChange || newColorOffset != oldColorOffset) {
350 GR_GL(ColorPointer(4, GL_UNSIGNED_BYTE, newStride, colorPtr));
351 }
352 } else if (oldColorOffset > 0) {
353 GR_GL(DisableClientState(GL_COLOR_ARRAY));
354 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000355
reed@google.comac10a2d2010-12-22 21:39:39 +0000356 fHWGeometryState.fVertexLayout = fGeometrySrc.fVertexLayout;
357}
358
359#endif
360