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 #include "GrGpuGLFixed.h" 21 #include "GrGpuVertex.h" 22 23 #define SKIP_CACHE_CHECK true 24 25 struct GrGpuMatrix { 26 GrGLfloat fMat[16]; 27 28 void reset() { 29 Gr_bzero(fMat, sizeof(fMat)); 30 fMat[0] = fMat[5] = fMat[10] = fMat[15] = GR_Scalar1; 31 } 32 33 void set(const GrMatrix& m) { 34 Gr_bzero(fMat, sizeof(fMat)); 35 fMat[0] = GrScalarToFloat(m[GrMatrix::kMScaleX]); 36 fMat[4] = GrScalarToFloat(m[GrMatrix::kMSkewX]); 37 fMat[12] = GrScalarToFloat(m[GrMatrix::kMTransX]); 38 39 fMat[1] = GrScalarToFloat(m[GrMatrix::kMSkewY]); 40 fMat[5] = GrScalarToFloat(m[GrMatrix::kMScaleY]); 41 fMat[13] = GrScalarToFloat(m[GrMatrix::kMTransY]); 42 43 fMat[3] = GrScalarToFloat(m[GrMatrix::kMPersp0]); 44 fMat[7] = GrScalarToFloat(m[GrMatrix::kMPersp1]); 45 fMat[15] = GrScalarToFloat(m[GrMatrix::kMPersp2]); 46 47 fMat[10] = 1.f; // z-scale 48 } 49 }; 50 51 // these must match the order in the corresponding enum in GrGpu.h 52 static const GrGLenum gMatrixMode2Enum[] = { 53 GR_GL_MODELVIEW, GR_GL_TEXTURE 54 }; 55 56 /////////////////////////////////////////////////////////////////////////////// 57 58 GrGpuGLFixed::GrGpuGLFixed() { 59 f4X4DownsampleFilterSupport = false; 60 fDualSourceBlendingSupport = false; 61 } 62 63 GrGpuGLFixed::~GrGpuGLFixed() { 64 } 65 66 void GrGpuGLFixed::resetContext() { 67 INHERITED::resetContext(); 68 69 GR_GL(Disable(GR_GL_TEXTURE_2D)); 70 71 for (int s = 0; s < kNumStages; ++s) { 72 setTextureUnit(s); 73 GR_GL(EnableClientState(GR_GL_VERTEX_ARRAY)); 74 GR_GL(TexEnvi(GR_GL_TEXTURE_ENV, GR_GL_TEXTURE_ENV_MODE, GR_GL_COMBINE)); 75 GR_GL(TexEnvi(GR_GL_TEXTURE_ENV, GR_GL_COMBINE_RGB, GR_GL_MODULATE)); 76 GR_GL(TexEnvi(GR_GL_TEXTURE_ENV, GR_GL_SRC0_RGB, GR_GL_TEXTURE0+s)); 77 GR_GL(TexEnvi(GR_GL_TEXTURE_ENV, GR_GL_SRC1_RGB, GR_GL_PREVIOUS)); 78 GR_GL(TexEnvi(GR_GL_TEXTURE_ENV, GR_GL_OPERAND1_RGB, GR_GL_SRC_COLOR)); 79 80 GR_GL(TexEnvi(GR_GL_TEXTURE_ENV, GR_GL_COMBINE_ALPHA, GR_GL_MODULATE)); 81 GR_GL(TexEnvi(GR_GL_TEXTURE_ENV, GR_GL_SRC0_ALPHA, GR_GL_TEXTURE0+s)); 82 GR_GL(TexEnvi(GR_GL_TEXTURE_ENV, GR_GL_OPERAND0_ALPHA, GR_GL_SRC_ALPHA)); 83 GR_GL(TexEnvi(GR_GL_TEXTURE_ENV, GR_GL_SRC1_ALPHA, GR_GL_PREVIOUS)); 84 GR_GL(TexEnvi(GR_GL_TEXTURE_ENV, GR_GL_OPERAND1_ALPHA, GR_GL_SRC_ALPHA)); 85 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 88 // texture, e.g.: 89 //glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR); 90 fHWRGBOperand0[s] = (TextureEnvRGBOperands) -1; 91 } 92 93 fHWGeometryState.fVertexLayout = 0; 94 fHWGeometryState.fVertexOffset = ~0; 95 GR_GL(EnableClientState(GR_GL_VERTEX_ARRAY)); 96 GR_GL(DisableClientState(GR_GL_TEXTURE_COORD_ARRAY)); 97 GR_GL(ShadeModel(GR_GL_FLAT)); 98 GR_GL(DisableClientState(GR_GL_COLOR_ARRAY)); 99 100 GR_GL(PointSize(1.f)); 101 102 GrGLClearErr(); 103 fTextVerts = false; 104 105 fBaseVertex = 0xffffffff; 106 } 107 108 109 void GrGpuGLFixed::flushProjectionMatrix() { 110 float mat[16]; 111 Gr_bzero(mat, sizeof(mat)); 112 113 GrAssert(NULL != fCurrDrawState.fRenderTarget); 114 115 mat[0] = 2.f / fCurrDrawState.fRenderTarget->width(); 116 mat[5] = -2.f / fCurrDrawState.fRenderTarget->height(); 117 mat[10] = -1.f; 118 mat[15] = 1; 119 120 mat[12] = -1.f; 121 mat[13] = 1.f; 122 123 GR_GL(MatrixMode(GR_GL_PROJECTION)); 124 GR_GL(LoadMatrixf(mat)); 125 } 126 127 bool GrGpuGLFixed::flushGraphicsState(GrPrimitiveType type) { 128 129 bool usingTextures[kNumStages]; 130 131 for (int s = 0; s < kNumStages; ++s) { 132 usingTextures[s] = this->isStageEnabled(s); 133 if (usingTextures[s] && fCurrDrawState.fSamplerStates[s].isGradient()) { 134 unimpl("Fixed pipe doesn't support radial/sweep gradients"); 135 return false; 136 } 137 } 138 139 if (GR_GL_SUPPORT_ES1) { 140 if (BlendCoeffReferencesConstant(fCurrDrawState.fSrcBlend) || 141 BlendCoeffReferencesConstant(fCurrDrawState.fDstBlend)) { 142 unimpl("ES1 doesn't support blend constant"); 143 return false; 144 } 145 } 146 147 if (!flushGLStateCommon(type)) { 148 return false; 149 } 150 151 this->flushBlend(type, fCurrDrawState.fSrcBlend, fCurrDrawState.fDstBlend); 152 153 if (fDirtyFlags.fRenderTargetChanged) { 154 flushProjectionMatrix(); 155 } 156 157 for (int s = 0; s < kNumStages; ++s) { 158 bool wasUsingTexture = StageWillBeUsed(s, fHWGeometryState.fVertexLayout, fHWDrawState); 159 if (usingTextures[s] != wasUsingTexture) { 160 setTextureUnit(s); 161 if (usingTextures[s]) { 162 GR_GL(Enable(GR_GL_TEXTURE_2D)); 163 } else { 164 GR_GL(Disable(GR_GL_TEXTURE_2D)); 165 } 166 } 167 } 168 169 uint32_t vertColor = (fGeometrySrc.fVertexLayout & kColor_VertexLayoutBit); 170 uint32_t prevVertColor = (fHWGeometryState.fVertexLayout & 171 kColor_VertexLayoutBit); 172 173 if (vertColor != prevVertColor) { 174 if (vertColor) { 175 GR_GL(ShadeModel(GR_GL_SMOOTH)); 176 // invalidate the immediate mode color 177 fHWDrawState.fColor = GrColor_ILLEGAL; 178 } else { 179 GR_GL(ShadeModel(GR_GL_FLAT)); 180 } 181 } 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. 193 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 (GrPixelConfigIsAlphaOnly(texture->config())) ? 199 kAlpha_TextureEnvRGBOperand : 200 kColor_TextureEnvRGBOperand; 201 if (fHWRGBOperand0[s] != nextRGBOperand0) { 202 setTextureUnit(s); 203 GR_GL(TexEnvi(GR_GL_TEXTURE_ENV, 204 GR_GL_OPERAND0_RGB, 205 (nextRGBOperand0==kAlpha_TextureEnvRGBOperand) ? 206 GR_GL_SRC_ALPHA : 207 GR_GL_SRC_COLOR)); 208 fHWRGBOperand0[s] = nextRGBOperand0; 209 } 210 211 if (((1 << s) & fDirtyFlags.fTextureChangedMask) || 212 (fHWDrawState.fSamplerStates[s].getMatrix() != 213 getSamplerMatrix(s))) { 214 215 GrMatrix texMat = getSamplerMatrix(s); 216 AdjustTextureMatrix(texture, 217 GrSamplerState::kNormal_SampleMode, 218 &texMat); 219 GrGpuMatrix glm; 220 glm.set(texMat); 221 setTextureUnit(s); 222 GR_GL(MatrixMode(GR_GL_TEXTURE)); 223 GR_GL(LoadMatrixf(glm.fMat)); 224 recordHWSamplerMatrix(s, getSamplerMatrix(s)); 225 } 226 } else { 227 GrAssert(!"Rendering with texture vert flag set but no bound texture"); 228 return false; 229 } 230 } 231 } 232 233 if (fHWDrawState.fViewMatrix != fCurrDrawState.fViewMatrix) { 234 GrGpuMatrix glm; 235 glm.set(fCurrDrawState.fViewMatrix); 236 GR_GL(MatrixMode(GR_GL_MODELVIEW)); 237 GR_GL(LoadMatrixf(glm.fMat)); 238 fHWDrawState.fViewMatrix = 239 fCurrDrawState.fViewMatrix; 240 } 241 resetDirtyFlags(); 242 return true; 243 } 244 245 void GrGpuGLFixed::setupGeometry(int* startVertex, 246 int* startIndex, 247 int vertexCount, 248 int indexCount) { 249 250 int newColorOffset; 251 int newTexCoordOffsets[kNumStages]; 252 253 GrGLsizei newStride = VertexSizeAndOffsetsByStage(fGeometrySrc.fVertexLayout, 254 newTexCoordOffsets, 255 &newColorOffset); 256 int oldColorOffset; 257 int oldTexCoordOffsets[kNumStages]; 258 GrGLsizei oldStride = VertexSizeAndOffsetsByStage(fHWGeometryState.fVertexLayout, 259 oldTexCoordOffsets, 260 &oldColorOffset); 261 262 bool indexed = NULL != startIndex; 263 264 int extraVertexOffset; 265 int extraIndexOffset; 266 setBuffers(indexed, &extraVertexOffset, &extraIndexOffset); 267 268 GrGLenum scalarType; 269 if (fGeometrySrc.fVertexLayout & kTextFormat_VertexLayoutBit) { 270 scalarType = GrGLTextType; 271 } else { 272 scalarType = GrGLType; 273 } 274 275 size_t vertexOffset = (*startVertex + extraVertexOffset) * newStride; 276 *startVertex = 0; 277 if (indexed) { 278 *startIndex += extraIndexOffset; 279 } 280 281 // all the Pointers must be set if any of these are true 282 bool allOffsetsChange = fHWGeometryState.fArrayPtrsDirty || 283 vertexOffset != fHWGeometryState.fVertexOffset || 284 newStride != oldStride; 285 286 // position and tex coord offsets change if above conditions are true 287 // or the type changed based on text vs nontext type coords. 288 bool posAndTexChange = allOffsetsChange || 289 ((GrGLTextType != GrGLType) && 290 (kTextFormat_VertexLayoutBit & 291 (fHWGeometryState.fVertexLayout ^ 292 fGeometrySrc.fVertexLayout))); 293 294 if (posAndTexChange) { 295 GR_GL(VertexPointer(2, scalarType, newStride, (GrGLvoid*)vertexOffset)); 296 fHWGeometryState.fVertexOffset = vertexOffset; 297 } 298 299 for (int s = 0; s < kNumStages; ++s) { 300 // need to enable array if tex coord offset is 0 301 // (using positions as coords) 302 if (newTexCoordOffsets[s] >= 0) { 303 GrGLvoid* texCoordOffset = (GrGLvoid*)(vertexOffset + newTexCoordOffsets[s]); 304 if (oldTexCoordOffsets[s] < 0) { 305 GR_GL(ClientActiveTexture(GR_GL_TEXTURE0+s)); 306 GR_GL(EnableClientState(GR_GL_TEXTURE_COORD_ARRAY)); 307 GR_GL(TexCoordPointer(2, scalarType, newStride, texCoordOffset)); 308 } else if (posAndTexChange || 309 newTexCoordOffsets[s] != oldTexCoordOffsets[s]) { 310 GR_GL(ClientActiveTexture(GR_GL_TEXTURE0+s)); 311 GR_GL(TexCoordPointer(2, scalarType, newStride, texCoordOffset)); 312 } 313 } else if (oldTexCoordOffsets[s] >= 0) { 314 GR_GL(ClientActiveTexture(GR_GL_TEXTURE0+s)); 315 GR_GL(DisableClientState(GR_GL_TEXTURE_COORD_ARRAY)); 316 } 317 } 318 319 if (newColorOffset > 0) { 320 GrGLvoid* colorOffset = (GrGLvoid*)(vertexOffset + newColorOffset); 321 if (oldColorOffset <= 0) { 322 GR_GL(EnableClientState(GR_GL_COLOR_ARRAY)); 323 GR_GL(ColorPointer(4, GR_GL_UNSIGNED_BYTE, newStride, colorOffset)); 324 } else if (allOffsetsChange || newColorOffset != oldColorOffset) { 325 GR_GL(ColorPointer(4, GR_GL_UNSIGNED_BYTE, newStride, colorOffset)); 326 } 327 } else if (oldColorOffset > 0) { 328 GR_GL(DisableClientState(GR_GL_COLOR_ARRAY)); 329 } 330 331 fHWGeometryState.fVertexLayout = fGeometrySrc.fVertexLayout; 332 fHWGeometryState.fArrayPtrsDirty = false; 333 } 334