blob: 77bec409797e5171f6439926cd2c8ad75d2211f6 [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
75 GR_GL(EnableClientState(GL_VERTEX_ARRAY));
76 GR_GL(TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE));
77 GR_GL(TexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE));
78 GR_GL(TexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_TEXTURE0));
79 GR_GL(TexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_PRIMARY_COLOR));
80 GR_GL(TexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR));
81
82 GR_GL(TexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE));
83 GR_GL(TexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_TEXTURE0));
84 GR_GL(TexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA));
85 GR_GL(TexEnvi(GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_PRIMARY_COLOR));
86 GR_GL(TexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA));
87
88 // this changes between GL_SRC_COLR and GL_SRC_ALPHA depending upon
89 // whether we have a (premultiplied) RGBA texture or just an ALPHA texture
90 //glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
91 fHWRGBOperand0 = (TextureEnvRGBOperands) -1;
92
93 GR_GL(ClientActiveTexture(GL_TEXTURE0));
94
95 fHWGeometryState.fVertexLayout = 0;
96 fHWGeometryState.fPositionPtr = (void*) ~0;
97 GR_GL(EnableClientState(GL_VERTEX_ARRAY));
98 GR_GL(DisableClientState(GL_TEXTURE_COORD_ARRAY));
99 GR_GL(ShadeModel(GL_FLAT));
100 GR_GL(DisableClientState(GL_COLOR_ARRAY));
101
102 GrGLClearErr();
103 fTextVerts = false;
104
105 fHWTextureOrientation = (GrGLTexture::Orientation)-1; // illegal
106 fBaseVertex = 0xffffffff;
107}
108
109
110void GrGpuGLFixed::flushProjectionMatrix() {
111 float mat[16];
112 Gr_bzero(mat, sizeof(mat));
113
114 GrAssert(NULL != fCurrDrawState.fRenderTarget);
115
116 mat[0] = 2.f / fCurrDrawState.fRenderTarget->width();
117 mat[5] = -2.f / fCurrDrawState.fRenderTarget->height();
118 mat[10] = -1.f;
119 mat[15] = 1;
120
121 mat[12] = -1.f;
122 mat[13] = 1.f;
123
124 GR_GL(MatrixMode(GL_PROJECTION));
125 GR_GL(LoadMatrixf(mat));
126}
127
128bool GrGpuGLFixed::flushGraphicsState(PrimitiveType type) {
129
130 bool usingTexture = VertexHasTexCoords(fGeometrySrc.fVertexLayout);
131
132 if (usingTexture && fCurrDrawState.fSamplerState.isGradient()) {
133 unimpl("Fixed pipe doesn't support radial/sweep gradients");
134 return false;
135 }
136
137 flushGLStateCommon(type);
138
139 if (fRenderTargetChanged) {
140 flushProjectionMatrix();
141 fRenderTargetChanged = false;
142 }
143
144 bool wasUsingTexture = VertexHasTexCoords(fHWGeometryState.fVertexLayout);
145 if (usingTexture != wasUsingTexture) {
146 if (usingTexture) {
147 GR_GL(Enable(GL_TEXTURE_2D));
148 } else {
149 GR_GL(Disable(GL_TEXTURE_2D));
150 }
151 }
152
153 uint32_t vertColor = (fGeometrySrc.fVertexLayout & kColor_VertexLayoutBit);
154 uint32_t prevVertColor = (fHWGeometryState.fVertexLayout &
155 kColor_VertexLayoutBit);
156
157 if (vertColor != prevVertColor) {
158 if (vertColor) {
159 GrAssert(fCurrDrawState.fSamplerState.getSampleMode() !=
160 GrSamplerState::kAlphaMod_SampleMode);
161 GR_GL(ShadeModel(GL_SMOOTH));
162 // invalidate the immediate mode color
163 fHWDrawState.fColor = GrColor_ILLEGAL;
164 } else {
165 GR_GL(ShadeModel(GL_FLAT));
166 }
167 }
168
169 if (kPoints_PrimitiveType == type &&
170 fHWDrawState.fPointSize != fCurrDrawState.fPointSize) {
171 GR_GL(PointSize(fCurrDrawState.fPointSize));
172 fHWDrawState.fPointSize = fCurrDrawState.fPointSize;
173 }
174
175 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.
184 if (usingTexture) {
185 GrGLTexture* texture = (GrGLTexture*)fCurrDrawState.fTexture;
186 if (NULL != texture) {
187 TextureEnvRGBOperands nextRGBOperand0 =
188 (texture->uploadFormat() == GL_ALPHA) ?
189 kAlpha_TextureEnvRGBOperand :
190 kColor_TextureEnvRGBOperand;
191 if (fHWRGBOperand0 != nextRGBOperand0) {
192 GR_GL(TexEnvi(GL_TEXTURE_ENV,
193 GL_OPERAND0_RGB,
194 (nextRGBOperand0==kAlpha_TextureEnvRGBOperand) ?
195 GL_SRC_ALPHA :
196 GL_SRC_COLOR));
197 fHWRGBOperand0 = nextRGBOperand0;
198 }
199
200 if (fHWTextureOrientation != texture->orientation() ||
201 fHWDrawState.fMatrixModeCache[kTexture_MatrixMode] !=
202 fCurrDrawState.fMatrixModeCache[kTexture_MatrixMode]) {
203 GrGpuMatrix glm;
204 if (GrGLTexture::kBottomUp_Orientation == texture->orientation()) {
205 GrMatrix m(
206 GR_Scalar1, 0, 0,
207 0, -GR_Scalar1, GR_Scalar1,
208 0, 0, GrMatrix::I()[8]
209 );
210 m.preConcat(fCurrDrawState.fMatrixModeCache[kTexture_MatrixMode]);
211 glm.set(m);
212 } else {
213 glm.set(fCurrDrawState.fMatrixModeCache[kTexture_MatrixMode]);
214 }
215 GR_GL(MatrixMode(gMatrixMode2Enum[kTexture_MatrixMode]));
216 GR_GL(LoadMatrixf(glm.fMat));
217 fHWDrawState.fMatrixModeCache[kTexture_MatrixMode] =
218 fCurrDrawState.fMatrixModeCache[kTexture_MatrixMode];
219 fHWTextureOrientation = texture->orientation();
220 }
221 } else {
222 GrAssert(!"Rendering with texture vert flag set but no bound texture");
223 return false;
224 }
225 }
226
227 if (fHWDrawState.fMatrixModeCache[kModelView_MatrixMode] !=
228 fCurrDrawState.fMatrixModeCache[kModelView_MatrixMode]) {
229 GrGpuMatrix glm;
230 glm.set(fCurrDrawState.fMatrixModeCache[kModelView_MatrixMode]);
231 GR_GL(MatrixMode(gMatrixMode2Enum[kModelView_MatrixMode]));
232 GR_GL(LoadMatrixf(glm.fMat));
233 fHWDrawState.fMatrixModeCache[kModelView_MatrixMode] =
234 fCurrDrawState.fMatrixModeCache[kModelView_MatrixMode];
235 }
236 return true;
237}
238
239void GrGpuGLFixed::setupGeometry(uint32_t startVertex,
240 uint32_t startIndex,
241 uint32_t vertexCount,
242 uint32_t indexCount) {
243
244 int newColorOffset, newTexCoordOffset;
245
246 GLsizei newStride = VertexSizeAndOffsets(fGeometrySrc.fVertexLayout,
247 &newTexCoordOffset,
248 &newColorOffset);
249 int oldColorOffset, oldTexCoordOffset;
250 GLsizei oldStride = VertexSizeAndOffsets(fHWGeometryState.fVertexLayout,
251 &oldTexCoordOffset,
252 &oldColorOffset);
253
254 const GLvoid* posPtr = (GLvoid*)(newStride * startVertex);
255
256 if (kBuffer_GeometrySrcType == fGeometrySrc.fVertexSrc) {
257 GrAssert(NULL != fGeometrySrc.fVertexBuffer);
258 GrAssert(!fGeometrySrc.fVertexBuffer->isLocked());
259 if (fHWGeometryState.fVertexBuffer != fGeometrySrc.fVertexBuffer) {
260 GrGLVertexBuffer* buf =
261 (GrGLVertexBuffer*)fGeometrySrc.fVertexBuffer;
262 GR_GL(BindBuffer(GL_ARRAY_BUFFER, buf->bufferID()));
263 fHWGeometryState.fVertexBuffer = fGeometrySrc.fVertexBuffer;
264 }
265 } else {
266 if (kArray_GeometrySrcType == fGeometrySrc.fVertexSrc) {
267 posPtr = (void*)((intptr_t)fGeometrySrc.fVertexArray +
268 (intptr_t)posPtr);
269 } else {
270 GrAssert(kReserved_GeometrySrcType == fGeometrySrc.fVertexSrc);
271 posPtr = (void*)((intptr_t)fVertices.get() + (intptr_t)posPtr);
272 }
273 if (NULL != fHWGeometryState.fVertexBuffer) {
274 GR_GL(BindBuffer(GL_ARRAY_BUFFER, 0));
275 fHWGeometryState.fVertexBuffer = NULL;
276 }
277 }
278
279 if (kBuffer_GeometrySrcType == fGeometrySrc.fIndexSrc) {
280 GrAssert(NULL != fGeometrySrc.fIndexBuffer);
281 GrAssert(!fGeometrySrc.fIndexBuffer->isLocked());
282 if (fHWGeometryState.fIndexBuffer != fGeometrySrc.fIndexBuffer) {
283 GrGLIndexBuffer* buf =
284 (GrGLIndexBuffer*)fGeometrySrc.fIndexBuffer;
285 GR_GL(BindBuffer(GL_ELEMENT_ARRAY_BUFFER, buf->bufferID()));
286 fHWGeometryState.fIndexBuffer = fGeometrySrc.fIndexBuffer;
287 }
288 } else if (NULL != fHWGeometryState.fIndexBuffer) {
289 GR_GL(BindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
290 fHWGeometryState.fIndexBuffer = NULL;
291 }
292
293 GLenum scalarType;
294 if (fGeometrySrc.fVertexLayout & kTextFormat_VertexLayoutBit) {
295 scalarType = GrGLTextType;
296 } else {
297 scalarType = GrGLType;
298 }
299
300 bool baseChange = posPtr != fHWGeometryState.fPositionPtr;
301 bool scalarChange =
302 (GrGLTextType != GrGLType) &&
303 (kTextFormat_VertexLayoutBit &
304 (fHWGeometryState.fVertexLayout ^ fGeometrySrc.fVertexLayout));
305 bool strideChange = newStride != oldStride;
306 bool posChange = baseChange || scalarChange || strideChange;
307
308 if (posChange) {
309 GR_GL(VertexPointer(2, scalarType, newStride, posPtr));
310 fHWGeometryState.fPositionPtr = posPtr;
311 }
312
313 // need to enable array if tex coord offset is 0 (using positions as coords)
314 if (newTexCoordOffset >= 0) {
315 GLvoid* texCoordPtr = (int8_t*)posPtr + newTexCoordOffset;
316 if (oldTexCoordOffset < 0) {
317 GR_GL(EnableClientState(GL_TEXTURE_COORD_ARRAY));
318 }
319 if (posChange || newTexCoordOffset != oldTexCoordOffset) {
320 GR_GL(TexCoordPointer(2, scalarType, newStride, texCoordPtr));
321 }
322 } else if (oldTexCoordOffset >= 0) {
323 GR_GL(DisableClientState(GL_TEXTURE_COORD_ARRAY));
324 }
325
326 if (newColorOffset > 0) {
327 GLvoid* colorPtr = (int8_t*)posPtr + newColorOffset;
328 if (oldColorOffset <= 0) {
329 GR_GL(EnableClientState(GL_COLOR_ARRAY));
330 }
331 if (posChange || newColorOffset != oldColorOffset) {
332 GR_GL(ColorPointer(4, GL_UNSIGNED_BYTE, newStride, colorPtr));
333 }
334 } else if (oldColorOffset > 0) {
335 GR_GL(DisableClientState(GL_COLOR_ARRAY));
336 }
337
338 fHWGeometryState.fVertexLayout = fGeometrySrc.fVertexLayout;
339}
340
341#endif
342