blob: 695b22c156f3c02a035ecda8a21e3cbb5eabbfeb [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.com2e7b43d2011-01-18 20:57:22 +0000140 if (!flushGLStateCommon(type)) {
141 return false;
142 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000143
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000144 if (fDirtyFlags.fRenderTargetChanged) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000145 flushProjectionMatrix();
reed@google.comac10a2d2010-12-22 21:39:39 +0000146 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000147
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000148 for (int s = 0; s < kNumStages; ++s) {
149 bool wasUsingTexture = VertexUsesStage(s, fHWGeometryState.fVertexLayout);
150 if (usingTextures[s] != wasUsingTexture) {
151 setTextureUnit(s);
152 if (usingTextures[s]) {
153 GR_GL(Enable(GL_TEXTURE_2D));
154 } else {
155 GR_GL(Disable(GL_TEXTURE_2D));
156 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000157 }
158 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000159
reed@google.comac10a2d2010-12-22 21:39:39 +0000160 uint32_t vertColor = (fGeometrySrc.fVertexLayout & kColor_VertexLayoutBit);
bsalomon@google.com5782d712011-01-21 21:03:59 +0000161 uint32_t prevVertColor = (fHWGeometryState.fVertexLayout &
reed@google.comac10a2d2010-12-22 21:39:39 +0000162 kColor_VertexLayoutBit);
bsalomon@google.com5782d712011-01-21 21:03:59 +0000163
reed@google.comac10a2d2010-12-22 21:39:39 +0000164 if (vertColor != prevVertColor) {
165 if (vertColor) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000166 GR_GL(ShadeModel(GL_SMOOTH));
167 // invalidate the immediate mode color
168 fHWDrawState.fColor = GrColor_ILLEGAL;
169 } else {
170 GR_GL(ShadeModel(GL_FLAT));
171 }
172 }
173
bsalomon@google.com5782d712011-01-21 21:03:59 +0000174
reed@google.comac10a2d2010-12-22 21:39:39 +0000175 if (!vertColor && fHWDrawState.fColor != fCurrDrawState.fColor) {
176 GR_GL(Color4ub(GrColorUnpackR(fCurrDrawState.fColor),
177 GrColorUnpackG(fCurrDrawState.fColor),
178 GrColorUnpackB(fCurrDrawState.fColor),
179 GrColorUnpackA(fCurrDrawState.fColor)));
180 fHWDrawState.fColor = fCurrDrawState.fColor;
181 }
182
183 // set texture environment, decide whether we are modulating by RGB or A.
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000184 for (int s = 0; s < kNumStages; ++s) {
185 if (usingTextures[s]) {
186 GrGLTexture* texture = (GrGLTexture*)fCurrDrawState.fTextures[s];
187 if (NULL != texture) {
bsalomon@google.com5782d712011-01-21 21:03:59 +0000188 TextureEnvRGBOperands nextRGBOperand0 =
189 (texture->config() == GrTexture::kAlpha_8_PixelConfig) ?
190 kAlpha_TextureEnvRGBOperand :
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000191 kColor_TextureEnvRGBOperand;
192 if (fHWRGBOperand0[s] != nextRGBOperand0) {
193 setTextureUnit(s);
bsalomon@google.com5782d712011-01-21 21:03:59 +0000194 GR_GL(TexEnvi(GL_TEXTURE_ENV,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000195 GL_OPERAND0_RGB,
bsalomon@google.com5782d712011-01-21 21:03:59 +0000196 (nextRGBOperand0==kAlpha_TextureEnvRGBOperand) ?
197 GL_SRC_ALPHA :
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000198 GL_SRC_COLOR));
199 fHWRGBOperand0[s] = nextRGBOperand0;
reed@google.comac10a2d2010-12-22 21:39:39 +0000200 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000201
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000202 if (((1 << s) & fDirtyFlags.fTextureChangedMask) ||
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000203 (fHWDrawState.fSamplerStates[s].getMatrix() !=
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000204 getSamplerMatrix(s))) {
205
206 GrMatrix texMat = getSamplerMatrix(s);
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000207 AdjustTextureMatrix(texture,
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000208 GrSamplerState::kNormal_SampleMode,
209 &texMat);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000210 GrGpuMatrix glm;
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000211 glm.set(texMat);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000212 setTextureUnit(s);
213 GR_GL(MatrixMode(GL_TEXTURE));
214 GR_GL(LoadMatrixf(glm.fMat));
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000215 recordHWSamplerMatrix(s, getSamplerMatrix(s));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000216 }
217 } else {
218 GrAssert(!"Rendering with texture vert flag set but no bound texture");
219 return false;
reed@google.comac10a2d2010-12-22 21:39:39 +0000220 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000221 }
222 }
223
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000224 if (fHWDrawState.fViewMatrix != fCurrDrawState.fViewMatrix) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000225 GrGpuMatrix glm;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000226 glm.set(fCurrDrawState.fViewMatrix);
227 GR_GL(MatrixMode(GL_MODELVIEW));
reed@google.comac10a2d2010-12-22 21:39:39 +0000228 GR_GL(LoadMatrixf(glm.fMat));
bsalomon@google.com5782d712011-01-21 21:03:59 +0000229 fHWDrawState.fViewMatrix =
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000230 fCurrDrawState.fViewMatrix;
reed@google.comac10a2d2010-12-22 21:39:39 +0000231 }
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000232 resetDirtyFlags();
reed@google.comac10a2d2010-12-22 21:39:39 +0000233 return true;
234}
235
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000236void GrGpuGLFixed::setupGeometry(int* startVertex,
237 int* startIndex,
238 int vertexCount,
239 int indexCount) {
bsalomon@google.com5782d712011-01-21 21:03:59 +0000240
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000241 int newColorOffset;
242 int newTexCoordOffsets[kNumStages];
bsalomon@google.com5782d712011-01-21 21:03:59 +0000243
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000244 GLsizei newStride = VertexSizeAndOffsetsByStage(fGeometrySrc.fVertexLayout,
bsalomon@google.com5782d712011-01-21 21:03:59 +0000245 newTexCoordOffsets,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000246 &newColorOffset);
247 int oldColorOffset;
248 int oldTexCoordOffsets[kNumStages];
249 GLsizei oldStride = VertexSizeAndOffsetsByStage(fHWGeometryState.fVertexLayout,
bsalomon@google.com5782d712011-01-21 21:03:59 +0000250 oldTexCoordOffsets,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000251 &oldColorOffset);
bsalomon@google.com5782d712011-01-21 21:03:59 +0000252
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000253 bool indexed = NULL != startIndex;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000254
255 int extraVertexOffset;
256 int extraIndexOffset;
257 setBuffers(indexed, &extraVertexOffset, &extraIndexOffset);
bsalomon@google.com5782d712011-01-21 21:03:59 +0000258
reed@google.comac10a2d2010-12-22 21:39:39 +0000259 GLenum scalarType;
260 if (fGeometrySrc.fVertexLayout & kTextFormat_VertexLayoutBit) {
261 scalarType = GrGLTextType;
262 } else {
263 scalarType = GrGLType;
264 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000265
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000266 size_t vertexOffset = (*startVertex + extraVertexOffset) * newStride;
267 *startVertex = 0;
268 if (indexed) {
269 *startIndex += extraIndexOffset;
270 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000271
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000272 // all the Pointers must be set if any of these are true
273 bool allOffsetsChange = fHWGeometryState.fArrayPtrsDirty ||
274 vertexOffset != fHWGeometryState.fVertexOffset ||
275 newStride != oldStride;
276
277 // position and tex coord offsets change if above conditions are true
278 // or the type changed based on text vs nontext type coords.
279 bool posAndTexChange = allOffsetsChange ||
280 ((GrGLTextType != GrGLType) &&
281 (kTextFormat_VertexLayoutBit &
282 (fHWGeometryState.fVertexLayout ^
283 fGeometrySrc.fVertexLayout)));
284
285 if (posAndTexChange) {
286 GR_GL(VertexPointer(2, scalarType, newStride, (GLvoid*)vertexOffset));
287 fHWGeometryState.fVertexOffset = vertexOffset;
reed@google.comac10a2d2010-12-22 21:39:39 +0000288 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000289
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000290 for (int s = 0; s < kNumStages; ++s) {
bsalomon@google.com5782d712011-01-21 21:03:59 +0000291 // need to enable array if tex coord offset is 0
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000292 // (using positions as coords)
293 if (newTexCoordOffsets[s] >= 0) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000294 GLvoid* texCoordOffset = (GLvoid*)(vertexOffset + newTexCoordOffsets[s]);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000295 if (oldTexCoordOffsets[s] < 0) {
296 GR_GL(ClientActiveTexture(GL_TEXTURE0+s));
297 GR_GL(EnableClientState(GL_TEXTURE_COORD_ARRAY));
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000298 GR_GL(TexCoordPointer(2, scalarType, newStride, texCoordOffset));
299 } else if (posAndTexChange ||
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +0000300 newTexCoordOffsets[s] != oldTexCoordOffsets[s]) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000301 GR_GL(ClientActiveTexture(GL_TEXTURE0+s));
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000302 GR_GL(TexCoordPointer(2, scalarType, newStride, texCoordOffset));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000303 }
304 } else if (oldTexCoordOffsets[s] >= 0) {
305 GR_GL(ClientActiveTexture(GL_TEXTURE0+s));
306 GR_GL(DisableClientState(GL_TEXTURE_COORD_ARRAY));
reed@google.comac10a2d2010-12-22 21:39:39 +0000307 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000308 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000309
reed@google.comac10a2d2010-12-22 21:39:39 +0000310 if (newColorOffset > 0) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000311 GLvoid* colorOffset = (GLvoid*)(vertexOffset + newColorOffset);
reed@google.comac10a2d2010-12-22 21:39:39 +0000312 if (oldColorOffset <= 0) {
313 GR_GL(EnableClientState(GL_COLOR_ARRAY));
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000314 GR_GL(ColorPointer(4, GL_UNSIGNED_BYTE, newStride, colorOffset));
315 } else if (allOffsetsChange || newColorOffset != oldColorOffset) {
316 GR_GL(ColorPointer(4, GL_UNSIGNED_BYTE, newStride, colorOffset));
reed@google.comac10a2d2010-12-22 21:39:39 +0000317 }
318 } else if (oldColorOffset > 0) {
319 GR_GL(DisableClientState(GL_COLOR_ARRAY));
320 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000321
reed@google.comac10a2d2010-12-22 21:39:39 +0000322 fHWGeometryState.fVertexLayout = fGeometrySrc.fVertexLayout;
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +0000323 fHWGeometryState.fArrayPtrsDirty = false;
reed@google.comac10a2d2010-12-22 21:39:39 +0000324}
325
326#endif
327