reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 1 | /* |
| 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 | |
| 27 | struct 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 |
| 54 | static const GLenum gMatrixMode2Enum[] = { |
| 55 | GL_MODELVIEW, GL_TEXTURE |
| 56 | }; |
| 57 | |
| 58 | /////////////////////////////////////////////////////////////////////////////// |
| 59 | |
| 60 | GrGpuGLFixed::GrGpuGLFixed() { |
| 61 | resetContextHelper(); |
| 62 | } |
| 63 | |
| 64 | GrGpuGLFixed::~GrGpuGLFixed() { |
| 65 | } |
| 66 | |
| 67 | void GrGpuGLFixed::resetContext() { |
| 68 | INHERITED::resetContext(); |
| 69 | resetContextHelper(); |
| 70 | } |
| 71 | |
| 72 | void GrGpuGLFixed::resetContextHelper() { |
| 73 | GR_GL(Disable(GL_TEXTURE_2D)); |
| 74 | |
bsalomon@google.com | 8531c1c | 2011-01-13 19:52:45 +0000 | [diff] [blame^] | 75 | 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.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 83 | |
bsalomon@google.com | 8531c1c | 2011-01-13 19:52:45 +0000 | [diff] [blame^] | 84 | 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.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 96 | |
| 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 | |
| 112 | void 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 | |
| 130 | bool GrGpuGLFixed::flushGraphicsState(PrimitiveType type) { |
| 131 | |
bsalomon@google.com | 8531c1c | 2011-01-13 19:52:45 +0000 | [diff] [blame^] | 132 | bool usingTextures[kNumStages]; |
| 133 | |
| 134 | for (int s = 0; s < kNumStages; ++s) { |
| 135 | usingTextures[s] = VertexUsesStage(s, fGeometrySrc.fVertexLayout); |
reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 136 | |
bsalomon@google.com | 8531c1c | 2011-01-13 19:52:45 +0000 | [diff] [blame^] | 137 | if (usingTextures[s] && fCurrDrawState.fSamplerStates[s].isGradient()) { |
| 138 | unimpl("Fixed pipe doesn't support radial/sweep gradients"); |
| 139 | return false; |
| 140 | } |
reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 141 | } |
| 142 | |
| 143 | flushGLStateCommon(type); |
| 144 | |
| 145 | if (fRenderTargetChanged) { |
| 146 | flushProjectionMatrix(); |
| 147 | fRenderTargetChanged = false; |
| 148 | } |
bsalomon@google.com | 8531c1c | 2011-01-13 19:52:45 +0000 | [diff] [blame^] | 149 | |
| 150 | for (int s = 0; s < kNumStages; ++s) { |
| 151 | bool wasUsingTexture = VertexUsesStage(s, fHWGeometryState.fVertexLayout); |
| 152 | if (usingTextures[s] != wasUsingTexture) { |
| 153 | setTextureUnit(s); |
| 154 | if (usingTextures[s]) { |
| 155 | GR_GL(Enable(GL_TEXTURE_2D)); |
| 156 | } else { |
| 157 | GR_GL(Disable(GL_TEXTURE_2D)); |
| 158 | } |
reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 159 | } |
| 160 | } |
bsalomon@google.com | 8531c1c | 2011-01-13 19:52:45 +0000 | [diff] [blame^] | 161 | |
reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 162 | uint32_t vertColor = (fGeometrySrc.fVertexLayout & kColor_VertexLayoutBit); |
| 163 | uint32_t prevVertColor = (fHWGeometryState.fVertexLayout & |
| 164 | kColor_VertexLayoutBit); |
| 165 | |
| 166 | if (vertColor != prevVertColor) { |
| 167 | if (vertColor) { |
reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 168 | GR_GL(ShadeModel(GL_SMOOTH)); |
| 169 | // invalidate the immediate mode color |
| 170 | fHWDrawState.fColor = GrColor_ILLEGAL; |
| 171 | } else { |
| 172 | GR_GL(ShadeModel(GL_FLAT)); |
| 173 | } |
| 174 | } |
| 175 | |
| 176 | if (kPoints_PrimitiveType == type && |
| 177 | fHWDrawState.fPointSize != fCurrDrawState.fPointSize) { |
| 178 | GR_GL(PointSize(fCurrDrawState.fPointSize)); |
| 179 | fHWDrawState.fPointSize = fCurrDrawState.fPointSize; |
| 180 | } |
| 181 | |
| 182 | if (!vertColor && fHWDrawState.fColor != fCurrDrawState.fColor) { |
| 183 | GR_GL(Color4ub(GrColorUnpackR(fCurrDrawState.fColor), |
| 184 | GrColorUnpackG(fCurrDrawState.fColor), |
| 185 | GrColorUnpackB(fCurrDrawState.fColor), |
| 186 | GrColorUnpackA(fCurrDrawState.fColor))); |
| 187 | fHWDrawState.fColor = fCurrDrawState.fColor; |
| 188 | } |
| 189 | |
| 190 | // set texture environment, decide whether we are modulating by RGB or A. |
bsalomon@google.com | 8531c1c | 2011-01-13 19:52:45 +0000 | [diff] [blame^] | 191 | for (int s = 0; s < kNumStages; ++s) { |
| 192 | if (usingTextures[s]) { |
| 193 | GrGLTexture* texture = (GrGLTexture*)fCurrDrawState.fTextures[s]; |
| 194 | if (NULL != texture) { |
| 195 | TextureEnvRGBOperands nextRGBOperand0 = |
| 196 | (texture->config() == GrTexture::kAlpha_8_PixelConfig) ? |
| 197 | kAlpha_TextureEnvRGBOperand : |
| 198 | kColor_TextureEnvRGBOperand; |
| 199 | if (fHWRGBOperand0[s] != nextRGBOperand0) { |
| 200 | setTextureUnit(s); |
| 201 | GR_GL(TexEnvi(GL_TEXTURE_ENV, |
| 202 | GL_OPERAND0_RGB, |
| 203 | (nextRGBOperand0==kAlpha_TextureEnvRGBOperand) ? |
| 204 | GL_SRC_ALPHA : |
| 205 | GL_SRC_COLOR)); |
| 206 | fHWRGBOperand0[s] = nextRGBOperand0; |
reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 207 | } |
bsalomon@google.com | 8531c1c | 2011-01-13 19:52:45 +0000 | [diff] [blame^] | 208 | |
| 209 | if (fHWTextureOrientation != texture->orientation() || |
| 210 | fHWDrawState.fTextureMatrices[s] != |
| 211 | fCurrDrawState.fTextureMatrices[s]) { |
| 212 | GrGpuMatrix glm; |
| 213 | if (GrGLTexture::kBottomUp_Orientation == |
| 214 | texture->orientation()) { |
| 215 | GrMatrix m( |
| 216 | GR_Scalar1, 0, 0, |
| 217 | 0, -GR_Scalar1, GR_Scalar1, |
| 218 | 0, 0, GrMatrix::I()[8] |
| 219 | ); |
| 220 | m.preConcat(fCurrDrawState.fTextureMatrices[s]); |
| 221 | glm.set(m); |
| 222 | } else { |
| 223 | glm.set(fCurrDrawState.fTextureMatrices[s]); |
| 224 | } |
| 225 | setTextureUnit(s); |
| 226 | GR_GL(MatrixMode(GL_TEXTURE)); |
| 227 | GR_GL(LoadMatrixf(glm.fMat)); |
| 228 | fHWDrawState.fTextureMatrices[s] = |
| 229 | fCurrDrawState.fTextureMatrices[s]; |
| 230 | fHWTextureOrientation = texture->orientation(); |
| 231 | } |
| 232 | } else { |
| 233 | GrAssert(!"Rendering with texture vert flag set but no bound texture"); |
| 234 | return false; |
reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 235 | } |
reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 236 | } |
| 237 | } |
| 238 | |
bsalomon@google.com | 8531c1c | 2011-01-13 19:52:45 +0000 | [diff] [blame^] | 239 | if (fHWDrawState.fViewMatrix != fCurrDrawState.fViewMatrix) { |
reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 240 | GrGpuMatrix glm; |
bsalomon@google.com | 8531c1c | 2011-01-13 19:52:45 +0000 | [diff] [blame^] | 241 | glm.set(fCurrDrawState.fViewMatrix); |
| 242 | GR_GL(MatrixMode(GL_MODELVIEW)); |
reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 243 | GR_GL(LoadMatrixf(glm.fMat)); |
bsalomon@google.com | 8531c1c | 2011-01-13 19:52:45 +0000 | [diff] [blame^] | 244 | fHWDrawState.fViewMatrix = |
| 245 | fCurrDrawState.fViewMatrix; |
reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 246 | } |
| 247 | return true; |
| 248 | } |
| 249 | |
| 250 | void GrGpuGLFixed::setupGeometry(uint32_t startVertex, |
| 251 | uint32_t startIndex, |
| 252 | uint32_t vertexCount, |
| 253 | uint32_t indexCount) { |
| 254 | |
bsalomon@google.com | 8531c1c | 2011-01-13 19:52:45 +0000 | [diff] [blame^] | 255 | int newColorOffset; |
| 256 | int newTexCoordOffsets[kNumStages]; |
reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 257 | |
bsalomon@google.com | 8531c1c | 2011-01-13 19:52:45 +0000 | [diff] [blame^] | 258 | GLsizei newStride = VertexSizeAndOffsetsByStage(fGeometrySrc.fVertexLayout, |
| 259 | newTexCoordOffsets, |
| 260 | &newColorOffset); |
| 261 | int oldColorOffset; |
| 262 | int oldTexCoordOffsets[kNumStages]; |
| 263 | GLsizei oldStride = VertexSizeAndOffsetsByStage(fHWGeometryState.fVertexLayout, |
| 264 | oldTexCoordOffsets, |
| 265 | &oldColorOffset); |
reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 266 | |
| 267 | const GLvoid* posPtr = (GLvoid*)(newStride * startVertex); |
| 268 | |
| 269 | if (kBuffer_GeometrySrcType == fGeometrySrc.fVertexSrc) { |
| 270 | GrAssert(NULL != fGeometrySrc.fVertexBuffer); |
| 271 | GrAssert(!fGeometrySrc.fVertexBuffer->isLocked()); |
| 272 | if (fHWGeometryState.fVertexBuffer != fGeometrySrc.fVertexBuffer) { |
| 273 | GrGLVertexBuffer* buf = |
bsalomon@google.com | 8531c1c | 2011-01-13 19:52:45 +0000 | [diff] [blame^] | 274 | (GrGLVertexBuffer*)fGeometrySrc.fVertexBuffer; |
reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 275 | GR_GL(BindBuffer(GL_ARRAY_BUFFER, buf->bufferID())); |
| 276 | fHWGeometryState.fVertexBuffer = fGeometrySrc.fVertexBuffer; |
| 277 | } |
| 278 | } else { |
| 279 | if (kArray_GeometrySrcType == fGeometrySrc.fVertexSrc) { |
| 280 | posPtr = (void*)((intptr_t)fGeometrySrc.fVertexArray + |
| 281 | (intptr_t)posPtr); |
| 282 | } else { |
| 283 | GrAssert(kReserved_GeometrySrcType == fGeometrySrc.fVertexSrc); |
| 284 | posPtr = (void*)((intptr_t)fVertices.get() + (intptr_t)posPtr); |
| 285 | } |
| 286 | if (NULL != fHWGeometryState.fVertexBuffer) { |
| 287 | GR_GL(BindBuffer(GL_ARRAY_BUFFER, 0)); |
| 288 | fHWGeometryState.fVertexBuffer = NULL; |
| 289 | } |
| 290 | } |
| 291 | |
| 292 | if (kBuffer_GeometrySrcType == fGeometrySrc.fIndexSrc) { |
| 293 | GrAssert(NULL != fGeometrySrc.fIndexBuffer); |
| 294 | GrAssert(!fGeometrySrc.fIndexBuffer->isLocked()); |
| 295 | if (fHWGeometryState.fIndexBuffer != fGeometrySrc.fIndexBuffer) { |
| 296 | GrGLIndexBuffer* buf = |
| 297 | (GrGLIndexBuffer*)fGeometrySrc.fIndexBuffer; |
| 298 | GR_GL(BindBuffer(GL_ELEMENT_ARRAY_BUFFER, buf->bufferID())); |
| 299 | fHWGeometryState.fIndexBuffer = fGeometrySrc.fIndexBuffer; |
| 300 | } |
| 301 | } else if (NULL != fHWGeometryState.fIndexBuffer) { |
| 302 | GR_GL(BindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); |
| 303 | fHWGeometryState.fIndexBuffer = NULL; |
| 304 | } |
| 305 | |
| 306 | GLenum scalarType; |
| 307 | if (fGeometrySrc.fVertexLayout & kTextFormat_VertexLayoutBit) { |
| 308 | scalarType = GrGLTextType; |
| 309 | } else { |
| 310 | scalarType = GrGLType; |
| 311 | } |
| 312 | |
| 313 | bool baseChange = posPtr != fHWGeometryState.fPositionPtr; |
| 314 | bool scalarChange = |
| 315 | (GrGLTextType != GrGLType) && |
| 316 | (kTextFormat_VertexLayoutBit & |
| 317 | (fHWGeometryState.fVertexLayout ^ fGeometrySrc.fVertexLayout)); |
| 318 | bool strideChange = newStride != oldStride; |
| 319 | bool posChange = baseChange || scalarChange || strideChange; |
| 320 | |
| 321 | if (posChange) { |
| 322 | GR_GL(VertexPointer(2, scalarType, newStride, posPtr)); |
| 323 | fHWGeometryState.fPositionPtr = posPtr; |
| 324 | } |
| 325 | |
bsalomon@google.com | 8531c1c | 2011-01-13 19:52:45 +0000 | [diff] [blame^] | 326 | for (int s = 0; s < kNumStages; ++s) { |
| 327 | // need to enable array if tex coord offset is 0 |
| 328 | // (using positions as coords) |
| 329 | if (newTexCoordOffsets[s] >= 0) { |
| 330 | GLvoid* texCoordPtr = (int8_t*)posPtr + newTexCoordOffsets[s]; |
| 331 | if (oldTexCoordOffsets[s] < 0) { |
| 332 | GR_GL(ClientActiveTexture(GL_TEXTURE0+s)); |
| 333 | GR_GL(EnableClientState(GL_TEXTURE_COORD_ARRAY)); |
| 334 | } |
| 335 | if (posChange || newTexCoordOffsets[s] != oldTexCoordOffsets[s]) { |
| 336 | GR_GL(ClientActiveTexture(GL_TEXTURE0+s)); |
| 337 | GR_GL(TexCoordPointer(2, scalarType, newStride, texCoordPtr)); |
| 338 | } |
| 339 | } else if (oldTexCoordOffsets[s] >= 0) { |
| 340 | GR_GL(ClientActiveTexture(GL_TEXTURE0+s)); |
| 341 | GR_GL(DisableClientState(GL_TEXTURE_COORD_ARRAY)); |
reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 342 | } |
reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 343 | } |
| 344 | |
| 345 | if (newColorOffset > 0) { |
| 346 | GLvoid* colorPtr = (int8_t*)posPtr + newColorOffset; |
| 347 | if (oldColorOffset <= 0) { |
| 348 | GR_GL(EnableClientState(GL_COLOR_ARRAY)); |
| 349 | } |
| 350 | if (posChange || newColorOffset != oldColorOffset) { |
| 351 | GR_GL(ColorPointer(4, GL_UNSIGNED_BYTE, newStride, colorPtr)); |
| 352 | } |
| 353 | } else if (oldColorOffset > 0) { |
| 354 | GR_GL(DisableClientState(GL_COLOR_ARRAY)); |
| 355 | } |
| 356 | |
| 357 | fHWGeometryState.fVertexLayout = fGeometrySrc.fVertexLayout; |
| 358 | } |
| 359 | |
| 360 | #endif |
| 361 | |