1 2 /* 3 * Copyright 2011 Google Inc. 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9 10 #include "GrGpuGL.h" 11 #include "GrGLStencilBuffer.h" 12 #include "GrTypes.h" 13 #include "SkTemplates.h" 14 15 static const GrGLuint GR_MAX_GLUINT = ~0; 16 static const GrGLint GR_INVAL_GLINT = ~0; 17 18 #define GL_CALL(X) GR_GL_CALL(this->glInterface(), X) 19 #define GL_CALL_RET(RET, X) GR_GL_CALL_RET(this->glInterface(), RET, X) 20 21 // we use a spare texture unit to avoid 22 // mucking with the state of any of the stages. 23 static const int SPARE_TEX_UNIT = GrDrawState::kNumStages; 24 25 #define SKIP_CACHE_CHECK true 26 27 #if GR_GL_CHECK_ALLOC_WITH_GET_ERROR 28 #define CLEAR_ERROR_BEFORE_ALLOC(iface) GrGLClearErr(iface) 29 #define GL_ALLOC_CALL(iface, call) GR_GL_CALL_NOERRCHECK(iface, call) 30 #define CHECK_ALLOC_ERROR(iface) GR_GL_GET_ERROR(iface) 31 #else 32 #define CLEAR_ERROR_BEFORE_ALLOC(iface) 33 #define GL_ALLOC_CALL(iface, call) GR_GL_CALL(iface, call) 34 #define CHECK_ALLOC_ERROR(iface) GR_GL_NO_ERROR 35 #endif 36 37 38 /////////////////////////////////////////////////////////////////////////////// 39 40 static const GrGLenum gXfermodeCoeff2Blend[] = { 41 GR_GL_ZERO, 42 GR_GL_ONE, 43 GR_GL_SRC_COLOR, 44 GR_GL_ONE_MINUS_SRC_COLOR, 45 GR_GL_DST_COLOR, 46 GR_GL_ONE_MINUS_DST_COLOR, 47 GR_GL_SRC_ALPHA, 48 GR_GL_ONE_MINUS_SRC_ALPHA, 49 GR_GL_DST_ALPHA, 50 GR_GL_ONE_MINUS_DST_ALPHA, 51 GR_GL_CONSTANT_COLOR, 52 GR_GL_ONE_MINUS_CONSTANT_COLOR, 53 GR_GL_CONSTANT_ALPHA, 54 GR_GL_ONE_MINUS_CONSTANT_ALPHA, 55 56 // extended blend coeffs 57 GR_GL_SRC1_COLOR, 58 GR_GL_ONE_MINUS_SRC1_COLOR, 59 GR_GL_SRC1_ALPHA, 60 GR_GL_ONE_MINUS_SRC1_ALPHA, 61 }; 62 63 bool GrGpuGL::BlendCoeffReferencesConstant(GrBlendCoeff coeff) { 64 static const bool gCoeffReferencesBlendConst[] = { 65 false, 66 false, 67 false, 68 false, 69 false, 70 false, 71 false, 72 false, 73 false, 74 false, 75 true, 76 true, 77 true, 78 true, 79 80 // extended blend coeffs 81 false, 82 false, 83 false, 84 false, 85 }; 86 return gCoeffReferencesBlendConst[coeff]; 87 GR_STATIC_ASSERT(kTotalBlendCoeffCount == GR_ARRAY_COUNT(gCoeffReferencesBlendConst)); 88 89 GR_STATIC_ASSERT(0 == kZero_BlendCoeff); 90 GR_STATIC_ASSERT(1 == kOne_BlendCoeff); 91 GR_STATIC_ASSERT(2 == kSC_BlendCoeff); 92 GR_STATIC_ASSERT(3 == kISC_BlendCoeff); 93 GR_STATIC_ASSERT(4 == kDC_BlendCoeff); 94 GR_STATIC_ASSERT(5 == kIDC_BlendCoeff); 95 GR_STATIC_ASSERT(6 == kSA_BlendCoeff); 96 GR_STATIC_ASSERT(7 == kISA_BlendCoeff); 97 GR_STATIC_ASSERT(8 == kDA_BlendCoeff); 98 GR_STATIC_ASSERT(9 == kIDA_BlendCoeff); 99 GR_STATIC_ASSERT(10 == kConstC_BlendCoeff); 100 GR_STATIC_ASSERT(11 == kIConstC_BlendCoeff); 101 GR_STATIC_ASSERT(12 == kConstA_BlendCoeff); 102 GR_STATIC_ASSERT(13 == kIConstA_BlendCoeff); 103 104 GR_STATIC_ASSERT(14 == kS2C_BlendCoeff); 105 GR_STATIC_ASSERT(15 == kIS2C_BlendCoeff); 106 GR_STATIC_ASSERT(16 == kS2A_BlendCoeff); 107 GR_STATIC_ASSERT(17 == kIS2A_BlendCoeff); 108 109 // assertion for gXfermodeCoeff2Blend have to be in GrGpu scope 110 GR_STATIC_ASSERT(kTotalBlendCoeffCount == GR_ARRAY_COUNT(gXfermodeCoeff2Blend)); 111 } 112 113 /////////////////////////////////////////////////////////////////////////////// 114 115 void GrGpuGL::AdjustTextureMatrix(const GrGLTexture* texture, 116 GrSamplerState::SampleMode mode, 117 GrMatrix* matrix) { 118 GrAssert(NULL != texture); 119 GrAssert(NULL != matrix); 120 GrGLTexture::Orientation orientation = texture->orientation(); 121 if (GrGLTexture::kBottomUp_Orientation == orientation) { 122 GrMatrix invY; 123 invY.setAll(GR_Scalar1, 0, 0, 124 0, -GR_Scalar1, GR_Scalar1, 125 0, 0, GrMatrix::I()[8]); 126 matrix->postConcat(invY); 127 } else { 128 GrAssert(GrGLTexture::kTopDown_Orientation == orientation); 129 } 130 } 131 132 bool GrGpuGL::TextureMatrixIsIdentity(const GrGLTexture* texture, 133 const GrSamplerState& sampler) { 134 GrAssert(NULL != texture); 135 if (!sampler.getMatrix().isIdentity()) { 136 return false; 137 } 138 GrGLTexture::Orientation orientation = texture->orientation(); 139 if (GrGLTexture::kBottomUp_Orientation == orientation) { 140 return false; 141 } else { 142 GrAssert(GrGLTexture::kTopDown_Orientation == orientation); 143 } 144 return true; 145 } 146 147 /////////////////////////////////////////////////////////////////////////////// 148 149 static bool gPrintStartupSpew; 150 151 static bool fbo_test(const GrGLInterface* gl, int w, int h) { 152 153 GR_GL_CALL(gl, ActiveTexture(GR_GL_TEXTURE0 + SPARE_TEX_UNIT)); 154 155 GrGLuint testFBO; 156 GR_GL_CALL(gl, GenFramebuffers(1, &testFBO)); 157 GR_GL_CALL(gl, BindFramebuffer(GR_GL_FRAMEBUFFER, testFBO)); 158 GrGLuint testRTTex; 159 GR_GL_CALL(gl, GenTextures(1, &testRTTex)); 160 GR_GL_CALL(gl, BindTexture(GR_GL_TEXTURE_2D, testRTTex)); 161 // some implementations require texture to be mip-map complete before 162 // FBO with level 0 bound as color attachment will be framebuffer complete. 163 GR_GL_CALL(gl, TexParameteri(GR_GL_TEXTURE_2D, 164 GR_GL_TEXTURE_MIN_FILTER, 165 GR_GL_NEAREST)); 166 GR_GL_CALL(gl, TexImage2D(GR_GL_TEXTURE_2D, 0, GR_GL_RGBA, w, h, 167 0, GR_GL_RGBA, GR_GL_UNSIGNED_BYTE, NULL)); 168 GR_GL_CALL(gl, BindTexture(GR_GL_TEXTURE_2D, 0)); 169 GR_GL_CALL(gl, FramebufferTexture2D(GR_GL_FRAMEBUFFER, 170 GR_GL_COLOR_ATTACHMENT0, 171 GR_GL_TEXTURE_2D, testRTTex, 0)); 172 GrGLenum status; 173 GR_GL_CALL_RET(gl, status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER)); 174 GR_GL_CALL(gl, DeleteFramebuffers(1, &testFBO)); 175 GR_GL_CALL(gl, DeleteTextures(1, &testRTTex)); 176 177 return status == GR_GL_FRAMEBUFFER_COMPLETE; 178 } 179 180 GrGpuGL::GrGpuGL(const GrGLContextInfo& ctxInfo) : fGLContextInfo(ctxInfo) { 181 182 GrAssert(ctxInfo.isInitialized()); 183 184 fPrintedCaps = false; 185 186 GrGLClearErr(fGLContextInfo.interface()); 187 188 if (gPrintStartupSpew) { 189 const GrGLubyte* ext; 190 GL_CALL_RET(ext, GetString(GR_GL_EXTENSIONS)); 191 const GrGLubyte* vendor; 192 const GrGLubyte* renderer; 193 const GrGLubyte* version; 194 GL_CALL_RET(vendor, GetString(GR_GL_VENDOR)); 195 GL_CALL_RET(renderer, GetString(GR_GL_RENDERER)); 196 GL_CALL_RET(version, GetString(GR_GL_VERSION)); 197 GrPrintf("------------------------- create GrGpuGL %p --------------\n", 198 this); 199 GrPrintf("------ VENDOR %s\n", vendor); 200 GrPrintf("------ RENDERER %s\n", renderer); 201 GrPrintf("------ VERSION %s\n", version); 202 GrPrintf("------ EXTENSIONS\n %s \n", ext); 203 } 204 205 this->resetDirtyFlags(); 206 207 this->initCaps(); 208 209 fLastSuccessfulStencilFmtIdx = 0; 210 fCanPreserveUnpremulRoundtrip = kUnknown_CanPreserveUnpremulRoundtrip; 211 } 212 213 GrGpuGL::~GrGpuGL() { 214 // This must be called by before the GrDrawTarget destructor 215 this->releaseGeometry(); 216 // This subclass must do this before the base class destructor runs 217 // since we will unref the GrGLInterface. 218 this->releaseResources(); 219 } 220 221 /////////////////////////////////////////////////////////////////////////////// 222 223 void GrGpuGL::initCaps() { 224 GrGLint maxTextureUnits; 225 // check FS and fixed-function texture unit limits 226 // we only use textures in the fragment stage currently. 227 // checks are > to make sure we have a spare unit. 228 const GrGLInterface* gl = this->glInterface(); 229 GR_GL_GetIntegerv(gl, GR_GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureUnits); 230 GrAssert(maxTextureUnits > GrDrawState::kNumStages); 231 if (kES2_GrGLBinding != this->glBinding()) { 232 GR_GL_GetIntegerv(gl, GR_GL_MAX_TEXTURE_UNITS, &maxTextureUnits); 233 GrAssert(maxTextureUnits > GrDrawState::kNumStages); 234 } 235 236 GrGLint numFormats; 237 GR_GL_GetIntegerv(gl, GR_GL_NUM_COMPRESSED_TEXTURE_FORMATS, &numFormats); 238 SkAutoSTMalloc<10, GrGLint> formats(numFormats); 239 GR_GL_GetIntegerv(gl, GR_GL_COMPRESSED_TEXTURE_FORMATS, formats); 240 for (int i = 0; i < numFormats; ++i) { 241 if (formats[i] == GR_GL_PALETTE8_RGBA8) { 242 fCaps.f8BitPaletteSupport = true; 243 break; 244 } 245 } 246 247 if (kDesktop_GrGLBinding == this->glBinding()) { 248 // we could also look for GL_ATI_separate_stencil extension or 249 // GL_EXT_stencil_two_side but they use different function signatures 250 // than GL2.0+ (and than each other). 251 fCaps.fTwoSidedStencilSupport = (this->glVersion() >= GR_GL_VER(2,0)); 252 // supported on GL 1.4 and higher or by extension 253 fCaps.fStencilWrapOpsSupport = (this->glVersion() >= GR_GL_VER(1,4)) || 254 this->hasExtension("GL_EXT_stencil_wrap"); 255 } else { 256 // ES 2 has two sided stencil and stencil wrap 257 fCaps.fTwoSidedStencilSupport = true; 258 fCaps.fStencilWrapOpsSupport = true; 259 } 260 261 if (kDesktop_GrGLBinding == this->glBinding()) { 262 fCaps.fBufferLockSupport = true; // we require VBO support and the desktop VBO 263 // extension includes glMapBuffer. 264 } else { 265 fCaps.fBufferLockSupport = this->hasExtension("GL_OES_mapbuffer"); 266 } 267 268 if (kDesktop_GrGLBinding == this->glBinding()) { 269 if (this->glVersion() >= GR_GL_VER(2,0) || 270 this->hasExtension("GL_ARB_texture_non_power_of_two")) { 271 fCaps.fNPOTTextureTileSupport = true; 272 } else { 273 fCaps.fNPOTTextureTileSupport = false; 274 } 275 } else { 276 // Unextended ES2 supports NPOT textures with clamp_to_edge and non-mip filters only 277 fCaps.fNPOTTextureTileSupport = this->hasExtension("GL_OES_texture_npot"); 278 } 279 280 fCaps.fHWAALineSupport = (kDesktop_GrGLBinding == this->glBinding()); 281 282 //////////////////////////////////////////////////////////////////////////// 283 // Experiments to determine limitations that can't be queried. 284 // TODO: Make these a preprocess that generate some compile time constants. 285 // TODO: probe once at startup, rather than once per context creation. 286 287 GR_GL_GetIntegerv(gl, GR_GL_MAX_TEXTURE_SIZE, &fCaps.fMaxTextureSize); 288 GR_GL_GetIntegerv(gl, GR_GL_MAX_RENDERBUFFER_SIZE, &fCaps.fMaxRenderTargetSize); 289 // Our render targets are always created with textures as the color 290 // attachment, hence this min: 291 fCaps.fMaxRenderTargetSize = GrMin(fCaps.fMaxTextureSize, fCaps.fMaxRenderTargetSize); 292 293 fCaps.fFSAASupport = GrGLCaps::kNone_MSFBOType != this->glCaps().msFBOType(); 294 } 295 296 bool GrGpuGL::canPreserveReadWriteUnpremulPixels() { 297 if (kUnknown_CanPreserveUnpremulRoundtrip == 298 fCanPreserveUnpremulRoundtrip) { 299 300 SkAutoTMalloc<uint32_t> data(256 * 256 * 3); 301 uint32_t* srcData = data.get(); 302 uint32_t* firstRead = data.get() + 256 * 256; 303 uint32_t* secondRead = data.get() + 2 * 256 * 256; 304 305 for (int y = 0; y < 256; ++y) { 306 for (int x = 0; x < 256; ++x) { 307 uint8_t* color = reinterpret_cast<uint8_t*>(&srcData[256*y + x]); 308 color[3] = y; 309 color[2] = x; 310 color[1] = x; 311 color[0] = x; 312 } 313 } 314 315 // We have broader support for read/write pixels on render targets 316 // than on textures. 317 GrTextureDesc dstDesc; 318 dstDesc.fFlags = kRenderTarget_GrTextureFlagBit | 319 kNoStencil_GrTextureFlagBit; 320 dstDesc.fWidth = 256; 321 dstDesc.fHeight = 256; 322 dstDesc.fConfig = kRGBA_8888_GrPixelConfig; 323 dstDesc.fSampleCnt = 0; 324 325 SkAutoTUnref<GrTexture> dstTex(this->createTexture(dstDesc, NULL, 0)); 326 if (!dstTex.get()) { 327 return false; 328 } 329 GrRenderTarget* rt = dstTex.get()->asRenderTarget(); 330 GrAssert(NULL != rt); 331 332 bool failed = true; 333 static const UnpremulConversion gMethods[] = { 334 kUpOnWrite_DownOnRead_UnpremulConversion, 335 kDownOnWrite_UpOnRead_UnpremulConversion, 336 }; 337 338 // pretend that we can do the roundtrip to avoid recursive calls to 339 // this function 340 fCanPreserveUnpremulRoundtrip = kYes_CanPreserveUnpremulRoundtrip; 341 for (size_t i = 0; i < GR_ARRAY_COUNT(gMethods) && failed; ++i) { 342 fUnpremulConversion = gMethods[i]; 343 rt->writePixels(0, 0, 344 256, 256, 345 kRGBA_8888_UPM_GrPixelConfig, srcData, 0); 346 rt->readPixels(0, 0, 347 256, 256, 348 kRGBA_8888_UPM_GrPixelConfig, firstRead, 0); 349 rt->writePixels(0, 0, 350 256, 256, 351 kRGBA_8888_UPM_GrPixelConfig, firstRead, 0); 352 rt->readPixels(0, 0, 353 256, 256, 354 kRGBA_8888_UPM_GrPixelConfig, secondRead, 0); 355 failed = false; 356 for (int j = 0; j < 256 * 256; ++j) { 357 if (firstRead[j] != secondRead[j]) { 358 failed = true; 359 break; 360 } 361 } 362 } 363 fCanPreserveUnpremulRoundtrip = failed ? 364 kNo_CanPreserveUnpremulRoundtrip : 365 kYes_CanPreserveUnpremulRoundtrip; 366 } 367 368 if (kYes_CanPreserveUnpremulRoundtrip == fCanPreserveUnpremulRoundtrip) { 369 return true; 370 } else { 371 return false; 372 } 373 } 374 375 GrPixelConfig GrGpuGL::preferredReadPixelsConfig(GrPixelConfig config) const { 376 if (GR_GL_RGBA_8888_PIXEL_OPS_SLOW && GrPixelConfigIsRGBA8888(config)) { 377 return GrPixelConfigSwapRAndB(config); 378 } else { 379 return config; 380 } 381 } 382 383 GrPixelConfig GrGpuGL::preferredWritePixelsConfig(GrPixelConfig config) const { 384 if (GR_GL_RGBA_8888_PIXEL_OPS_SLOW && GrPixelConfigIsRGBA8888(config)) { 385 return GrPixelConfigSwapRAndB(config); 386 } else { 387 return config; 388 } 389 } 390 391 bool GrGpuGL::fullReadPixelsIsFasterThanPartial() const { 392 return SkToBool(GR_GL_FULL_READPIXELS_FASTER_THAN_PARTIAL); 393 } 394 395 void GrGpuGL::onResetContext() { 396 if (gPrintStartupSpew && !fPrintedCaps) { 397 fPrintedCaps = true; 398 this->getCaps().print(); 399 this->glCaps().print(); 400 } 401 402 // We detect cases when blending is effectively off 403 fHWBlendDisabled = false; 404 GL_CALL(Enable(GR_GL_BLEND)); 405 406 // we don't use the zb at all 407 GL_CALL(Disable(GR_GL_DEPTH_TEST)); 408 GL_CALL(DepthMask(GR_GL_FALSE)); 409 410 GL_CALL(Disable(GR_GL_CULL_FACE)); 411 GL_CALL(FrontFace(GR_GL_CCW)); 412 fHWDrawState.setDrawFace(GrDrawState::kBoth_DrawFace); 413 414 GL_CALL(Disable(GR_GL_DITHER)); 415 if (kDesktop_GrGLBinding == this->glBinding()) { 416 GL_CALL(Disable(GR_GL_LINE_SMOOTH)); 417 GL_CALL(Disable(GR_GL_POINT_SMOOTH)); 418 GL_CALL(Disable(GR_GL_MULTISAMPLE)); 419 fHWAAState.fMSAAEnabled = false; 420 fHWAAState.fSmoothLineEnabled = false; 421 } 422 423 GL_CALL(ColorMask(GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE)); 424 fHWDrawState.resetStateFlags(); 425 426 // we only ever use lines in hairline mode 427 GL_CALL(LineWidth(1)); 428 429 // invalid 430 fActiveTextureUnitIdx = -1; 431 432 // illegal values 433 fHWDrawState.setBlendFunc((GrBlendCoeff)0xFF, (GrBlendCoeff)0xFF); 434 435 fHWDrawState.setBlendConstant(0x00000000); 436 GL_CALL(BlendColor(0,0,0,0)); 437 438 fHWDrawState.setColor(GrColor_ILLEGAL); 439 440 fHWDrawState.setViewMatrix(GrMatrix::InvalidMatrix()); 441 442 for (int s = 0; s < GrDrawState::kNumStages; ++s) { 443 fHWDrawState.setTexture(s, NULL); 444 fHWDrawState.sampler(s)->setRadial2Params(-GR_ScalarMax, 445 -GR_ScalarMax, 446 true); 447 *fHWDrawState.sampler(s)->matrix() = GrMatrix::InvalidMatrix(); 448 fHWDrawState.sampler(s)->setConvolutionParams(0, NULL); 449 } 450 451 fHWBounds.fScissorRect.invalidate(); 452 fHWBounds.fScissorEnabled = false; 453 GL_CALL(Disable(GR_GL_SCISSOR_TEST)); 454 fHWBounds.fViewportRect.invalidate(); 455 456 fHWDrawState.stencil()->invalidate(); 457 fHWStencilClip = false; 458 fClipInStencil = false; 459 460 fHWGeometryState.fIndexBuffer = NULL; 461 fHWGeometryState.fVertexBuffer = NULL; 462 463 fHWGeometryState.fArrayPtrsDirty = true; 464 465 GL_CALL(ColorMask(GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE)); 466 fHWDrawState.setRenderTarget(NULL); 467 468 // we assume these values 469 if (this->glCaps().unpackRowLengthSupport()) { 470 GL_CALL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH, 0)); 471 } 472 if (this->glCaps().packRowLengthSupport()) { 473 GL_CALL(PixelStorei(GR_GL_PACK_ROW_LENGTH, 0)); 474 } 475 if (this->glCaps().unpackFlipYSupport()) { 476 GL_CALL(PixelStorei(GR_GL_UNPACK_FLIP_Y, GR_GL_FALSE)); 477 } 478 if (this->glCaps().packFlipYSupport()) { 479 GL_CALL(PixelStorei(GR_GL_PACK_REVERSE_ROW_ORDER, GR_GL_FALSE)); 480 } 481 } 482 483 GrTexture* GrGpuGL::onCreatePlatformTexture(const GrPlatformTextureDesc& desc) { 484 GrGLTexture::Desc glTexDesc; 485 if (!configToGLFormats(desc.fConfig, false, NULL, NULL, NULL)) { 486 return NULL; 487 } 488 489 glTexDesc.fWidth = desc.fWidth; 490 glTexDesc.fHeight = desc.fHeight; 491 glTexDesc.fConfig = desc.fConfig; 492 glTexDesc.fTextureID = static_cast<GrGLuint>(desc.fTextureHandle); 493 glTexDesc.fOwnsID = false; 494 glTexDesc.fOrientation = GrGLTexture::kBottomUp_Orientation; 495 496 GrGLTexture* texture = NULL; 497 if (desc.fFlags & kRenderTarget_GrPlatformTextureFlag) { 498 GrGLRenderTarget::Desc glRTDesc; 499 glRTDesc.fRTFBOID = 0; 500 glRTDesc.fTexFBOID = 0; 501 glRTDesc.fMSColorRenderbufferID = 0; 502 glRTDesc.fOwnIDs = true; 503 glRTDesc.fConfig = desc.fConfig; 504 glRTDesc.fSampleCnt = desc.fSampleCnt; 505 if (!this->createRenderTargetObjects(glTexDesc.fWidth, 506 glTexDesc.fHeight, 507 glTexDesc.fTextureID, 508 &glRTDesc)) { 509 return NULL; 510 } 511 texture = new GrGLTexture(this, glTexDesc, glRTDesc); 512 } else { 513 texture = new GrGLTexture(this, glTexDesc); 514 } 515 if (NULL == texture) { 516 return NULL; 517 } 518 519 this->setSpareTextureUnit(); 520 return texture; 521 } 522 523 GrRenderTarget* GrGpuGL::onCreatePlatformRenderTarget(const GrPlatformRenderTargetDesc& desc) { 524 GrGLRenderTarget::Desc glDesc; 525 glDesc.fConfig = desc.fConfig; 526 glDesc.fRTFBOID = static_cast<GrGLuint>(desc.fRenderTargetHandle); 527 glDesc.fMSColorRenderbufferID = 0; 528 glDesc.fTexFBOID = GrGLRenderTarget::kUnresolvableFBOID; 529 glDesc.fSampleCnt = desc.fSampleCnt; 530 glDesc.fOwnIDs = false; 531 GrGLIRect viewport; 532 viewport.fLeft = 0; 533 viewport.fBottom = 0; 534 viewport.fWidth = desc.fWidth; 535 viewport.fHeight = desc.fHeight; 536 537 GrRenderTarget* tgt = new GrGLRenderTarget(this, glDesc, viewport); 538 if (desc.fStencilBits) { 539 GrGLStencilBuffer::Format format; 540 format.fInternalFormat = GrGLStencilBuffer::kUnknownInternalFormat; 541 format.fPacked = false; 542 format.fStencilBits = desc.fStencilBits; 543 format.fTotalBits = desc.fStencilBits; 544 GrGLStencilBuffer* sb = new GrGLStencilBuffer(this, 545 0, 546 desc.fWidth, 547 desc.fHeight, 548 desc.fSampleCnt, 549 format); 550 tgt->setStencilBuffer(sb); 551 sb->unref(); 552 } 553 return tgt; 554 } 555 556 //////////////////////////////////////////////////////////////////////////////// 557 558 void GrGpuGL::onWriteTexturePixels(GrTexture* texture, 559 int left, int top, int width, int height, 560 GrPixelConfig config, const void* buffer, 561 size_t rowBytes) { 562 if (NULL == buffer) { 563 return; 564 } 565 GrGLTexture* glTex = static_cast<GrGLTexture*>(texture); 566 567 this->setSpareTextureUnit(); 568 GL_CALL(BindTexture(GR_GL_TEXTURE_2D, glTex->textureID())); 569 GrGLTexture::Desc desc; 570 desc.fConfig = glTex->config(); 571 desc.fWidth = glTex->width(); 572 desc.fHeight = glTex->height(); 573 desc.fOrientation = glTex->orientation(); 574 desc.fTextureID = glTex->textureID(); 575 576 this->uploadTexData(desc, false, 577 left, top, width, height, 578 config, buffer, rowBytes); 579 } 580 581 namespace { 582 bool adjust_pixel_ops_params(int surfaceWidth, 583 int surfaceHeight, 584 size_t bpp, 585 int* left, int* top, int* width, int* height, 586 const void** data, 587 size_t* rowBytes) { 588 if (!*rowBytes) { 589 *rowBytes = *width * bpp; 590 } 591 592 GrIRect subRect = GrIRect::MakeXYWH(*left, *top, *width, *height); 593 GrIRect bounds = GrIRect::MakeWH(surfaceWidth, surfaceHeight); 594 595 if (!subRect.intersect(bounds)) { 596 return false; 597 } 598 *data = reinterpret_cast<const void*>(reinterpret_cast<intptr_t>(*data) + 599 (subRect.fTop - *top) * *rowBytes + (subRect.fLeft - *left) * bpp); 600 601 *left = subRect.fLeft; 602 *top = subRect.fTop; 603 *width = subRect.width(); 604 *height = subRect.height(); 605 return true; 606 } 607 } 608 609 bool GrGpuGL::uploadTexData(const GrGLTexture::Desc& desc, 610 bool isNewTexture, 611 int left, int top, int width, int height, 612 GrPixelConfig dataConfig, 613 const void* data, 614 size_t rowBytes) { 615 GrAssert(NULL != data || isNewTexture); 616 617 size_t bpp = GrBytesPerPixel(dataConfig); 618 if (!adjust_pixel_ops_params(desc.fWidth, desc.fHeight, bpp, &left, &top, 619 &width, &height, &data, &rowBytes)) { 620 return false; 621 } 622 size_t trimRowBytes = width * bpp; 623 624 // in case we need a temporary, trimmed copy of the src pixels 625 SkAutoSMalloc<128 * 128> tempStorage; 626 627 bool useTexStorage = isNewTexture && 628 this->glCaps().texStorageSupport(); 629 if (useTexStorage) { 630 if (kDesktop_GrGLBinding == this->glBinding()) { 631 // 565 is not a sized internal format on desktop GL. So on desktop 632 // with 565 we always use an unsized internal format to let the 633 // system pick the best sized format to convert the 565 data to. 634 // Since glTexStorage only allows sized internal formats we will 635 // instead fallback to glTexImage2D. 636 useTexStorage = desc.fConfig != kRGB_565_GrPixelConfig; 637 } else { 638 // ES doesn't allow paletted textures to be used with tex storage 639 useTexStorage = desc.fConfig != kIndex_8_GrPixelConfig; 640 } 641 } 642 643 GrGLenum internalFormat; 644 GrGLenum externalFormat; 645 GrGLenum externalType; 646 // glTexStorage requires sized internal formats on both desktop and ES. ES 647 // glTexImage requires an unsized format. 648 if (!this->configToGLFormats(dataConfig, useTexStorage, &internalFormat, 649 &externalFormat, &externalType)) { 650 return false; 651 } 652 653 if (!isNewTexture && GR_GL_PALETTE8_RGBA8 == internalFormat) { 654 // paletted textures cannot be updated 655 return false; 656 } 657 658 /* 659 * check whether to allocate a temporary buffer for flipping y or 660 * because our srcData has extra bytes past each row. If so, we need 661 * to trim those off here, since GL ES may not let us specify 662 * GL_UNPACK_ROW_LENGTH. 663 */ 664 bool restoreGLRowLength = false; 665 bool swFlipY = false; 666 bool glFlipY = false; 667 if (NULL != data) { 668 if (GrGLTexture::kBottomUp_Orientation == desc.fOrientation) { 669 if (this->glCaps().unpackFlipYSupport()) { 670 glFlipY = true; 671 } else { 672 swFlipY = true; 673 } 674 } 675 if (this->glCaps().unpackRowLengthSupport() && !swFlipY) { 676 // can't use this for flipping, only non-neg values allowed. :( 677 if (rowBytes != trimRowBytes) { 678 GrGLint rowLength = static_cast<GrGLint>(rowBytes / bpp); 679 GL_CALL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH, rowLength)); 680 restoreGLRowLength = true; 681 } 682 } else { 683 if (trimRowBytes != rowBytes || swFlipY) { 684 // copy data into our new storage, skipping the trailing bytes 685 size_t trimSize = height * trimRowBytes; 686 const char* src = (const char*)data; 687 if (swFlipY) { 688 src += (height - 1) * rowBytes; 689 } 690 char* dst = (char*)tempStorage.reset(trimSize); 691 for (int y = 0; y < height; y++) { 692 memcpy(dst, src, trimRowBytes); 693 if (swFlipY) { 694 src -= rowBytes; 695 } else { 696 src += rowBytes; 697 } 698 dst += trimRowBytes; 699 } 700 // now point data to our copied version 701 data = tempStorage.get(); 702 } 703 } 704 if (glFlipY) { 705 GL_CALL(PixelStorei(GR_GL_UNPACK_FLIP_Y, GR_GL_TRUE)); 706 } 707 GL_CALL(PixelStorei(GR_GL_UNPACK_ALIGNMENT, static_cast<GrGLint>(bpp))); 708 } 709 bool succeeded = true; 710 if (isNewTexture && 711 0 == left && 0 == top && 712 desc.fWidth == width && desc.fHeight == height) { 713 CLEAR_ERROR_BEFORE_ALLOC(this->glInterface()); 714 if (useTexStorage) { 715 // We never resize or change formats of textures. We don't use 716 // mipmaps currently. 717 GL_ALLOC_CALL(this->glInterface(), 718 TexStorage2D(GR_GL_TEXTURE_2D, 719 1, // levels 720 internalFormat, 721 desc.fWidth, desc.fHeight)); 722 } else { 723 if (GR_GL_PALETTE8_RGBA8 == internalFormat) { 724 GrGLsizei imageSize = desc.fWidth * desc.fHeight + 725 kGrColorTableSize; 726 GL_ALLOC_CALL(this->glInterface(), 727 CompressedTexImage2D(GR_GL_TEXTURE_2D, 728 0, // level 729 internalFormat, 730 desc.fWidth, desc.fHeight, 731 0, // border 732 imageSize, 733 data)); 734 } else { 735 GL_ALLOC_CALL(this->glInterface(), 736 TexImage2D(GR_GL_TEXTURE_2D, 737 0, // level 738 internalFormat, 739 desc.fWidth, desc.fHeight, 740 0, // border 741 externalFormat, externalType, 742 data)); 743 } 744 } 745 GrGLenum error = CHECK_ALLOC_ERROR(this->glInterface()); 746 if (error != GR_GL_NO_ERROR) { 747 succeeded = false; 748 } else { 749 // if we have data and we used TexStorage to create the texture, we 750 // now upload with TexSubImage. 751 if (NULL != data && useTexStorage) { 752 GL_CALL(TexSubImage2D(GR_GL_TEXTURE_2D, 753 0, // level 754 left, top, 755 width, height, 756 externalFormat, externalType, 757 data)); 758 } 759 } 760 } else { 761 if (swFlipY || glFlipY) { 762 top = desc.fHeight - (top + height); 763 } 764 GL_CALL(TexSubImage2D(GR_GL_TEXTURE_2D, 765 0, // level 766 left, top, 767 width, height, 768 externalFormat, externalType, data)); 769 } 770 771 if (restoreGLRowLength) { 772 GrAssert(this->glCaps().unpackRowLengthSupport()); 773 GL_CALL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH, 0)); 774 } 775 if (glFlipY) { 776 GL_CALL(PixelStorei(GR_GL_UNPACK_FLIP_Y, GR_GL_FALSE)); 777 } 778 return succeeded; 779 } 780 781 bool GrGpuGL::createRenderTargetObjects(int width, int height, 782 GrGLuint texID, 783 GrGLRenderTarget::Desc* desc) { 784 desc->fMSColorRenderbufferID = 0; 785 desc->fRTFBOID = 0; 786 desc->fTexFBOID = 0; 787 desc->fOwnIDs = true; 788 789 GrGLenum status; 790 GrGLint err; 791 792 GrGLenum msColorFormat = 0; // suppress warning 793 794 GL_CALL(GenFramebuffers(1, &desc->fTexFBOID)); 795 if (!desc->fTexFBOID) { 796 goto FAILED; 797 } 798 799 800 // If we are using multisampling we will create two FBOS. We render 801 // to one and then resolve to the texture bound to the other. 802 if (desc->fSampleCnt > 0) { 803 if (GrGLCaps::kNone_MSFBOType == this->glCaps().msFBOType()) { 804 goto FAILED; 805 } 806 GL_CALL(GenFramebuffers(1, &desc->fRTFBOID)); 807 GL_CALL(GenRenderbuffers(1, &desc->fMSColorRenderbufferID)); 808 if (!desc->fRTFBOID || 809 !desc->fMSColorRenderbufferID || 810 !this->configToGLFormats(desc->fConfig, 811 // GLES requires sized internal formats 812 kES2_GrGLBinding == this->glBinding(), 813 &msColorFormat, NULL, NULL)) { 814 goto FAILED; 815 } 816 } else { 817 desc->fRTFBOID = desc->fTexFBOID; 818 } 819 820 // below here we may bind the FBO 821 fHWDrawState.setRenderTarget(NULL); 822 if (desc->fRTFBOID != desc->fTexFBOID) { 823 GrAssert(desc->fSampleCnt > 1); 824 GL_CALL(BindRenderbuffer(GR_GL_RENDERBUFFER, 825 desc->fMSColorRenderbufferID)); 826 CLEAR_ERROR_BEFORE_ALLOC(this->glInterface()); 827 GL_ALLOC_CALL(this->glInterface(), 828 RenderbufferStorageMultisample(GR_GL_RENDERBUFFER, 829 desc->fSampleCnt, 830 msColorFormat, 831 width, height)); 832 err = CHECK_ALLOC_ERROR(this->glInterface()); 833 if (err != GR_GL_NO_ERROR) { 834 goto FAILED; 835 } 836 GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, desc->fRTFBOID)); 837 GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER, 838 GR_GL_COLOR_ATTACHMENT0, 839 GR_GL_RENDERBUFFER, 840 desc->fMSColorRenderbufferID)); 841 if (!this->glCaps().isConfigVerifiedColorAttachment(desc->fConfig)) { 842 GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER)); 843 if (status != GR_GL_FRAMEBUFFER_COMPLETE) { 844 goto FAILED; 845 } 846 fGLContextInfo.caps().markConfigAsValidColorAttachment( 847 desc->fConfig); 848 } 849 } 850 GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, desc->fTexFBOID)); 851 852 GL_CALL(FramebufferTexture2D(GR_GL_FRAMEBUFFER, 853 GR_GL_COLOR_ATTACHMENT0, 854 GR_GL_TEXTURE_2D, 855 texID, 0)); 856 if (!this->glCaps().isConfigVerifiedColorAttachment(desc->fConfig)) { 857 GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER)); 858 if (status != GR_GL_FRAMEBUFFER_COMPLETE) { 859 goto FAILED; 860 } 861 fGLContextInfo.caps().markConfigAsValidColorAttachment(desc->fConfig); 862 } 863 864 return true; 865 866 FAILED: 867 if (desc->fMSColorRenderbufferID) { 868 GL_CALL(DeleteRenderbuffers(1, &desc->fMSColorRenderbufferID)); 869 } 870 if (desc->fRTFBOID != desc->fTexFBOID) { 871 GL_CALL(DeleteFramebuffers(1, &desc->fRTFBOID)); 872 } 873 if (desc->fTexFBOID) { 874 GL_CALL(DeleteFramebuffers(1, &desc->fTexFBOID)); 875 } 876 return false; 877 } 878 879 // good to set a break-point here to know when createTexture fails 880 static GrTexture* return_null_texture() { 881 // GrAssert(!"null texture"); 882 return NULL; 883 } 884 885 #if GR_DEBUG 886 static size_t as_size_t(int x) { 887 return x; 888 } 889 #endif 890 891 GrTexture* GrGpuGL::onCreateTexture(const GrTextureDesc& desc, 892 const void* srcData, 893 size_t rowBytes) { 894 895 #if GR_COLLECT_STATS 896 ++fStats.fTextureCreateCnt; 897 #endif 898 899 GrGLTexture::Desc glTexDesc; 900 GrGLRenderTarget::Desc glRTDesc; 901 902 // Attempt to catch un- or wrongly initialized sample counts; 903 GrAssert(desc.fSampleCnt >= 0 && desc.fSampleCnt <= 64); 904 905 glTexDesc.fWidth = desc.fWidth; 906 glTexDesc.fHeight = desc.fHeight; 907 glTexDesc.fConfig = desc.fConfig; 908 glTexDesc.fOwnsID = true; 909 910 glRTDesc.fMSColorRenderbufferID = 0; 911 glRTDesc.fRTFBOID = 0; 912 glRTDesc.fTexFBOID = 0; 913 glRTDesc.fOwnIDs = true; 914 glRTDesc.fConfig = glTexDesc.fConfig; 915 916 bool renderTarget = 0 != (desc.fFlags & kRenderTarget_GrTextureFlagBit); 917 918 const Caps& caps = this->getCaps(); 919 920 // We keep GrRenderTargets in GL's normal orientation so that they 921 // can be drawn to by the outside world without the client having 922 // to render upside down. 923 glTexDesc.fOrientation = renderTarget ? GrGLTexture::kBottomUp_Orientation : 924 GrGLTexture::kTopDown_Orientation; 925 926 glRTDesc.fSampleCnt = desc.fSampleCnt; 927 if (GrGLCaps::kNone_MSFBOType == this->glCaps().msFBOType() && 928 desc.fSampleCnt) { 929 GrPrintf("MSAA RT requested but not supported on this platform."); 930 } 931 932 if (renderTarget) { 933 if (glTexDesc.fWidth > caps.fMaxRenderTargetSize || 934 glTexDesc.fHeight > caps.fMaxRenderTargetSize) { 935 return return_null_texture(); 936 } 937 } 938 939 GL_CALL(GenTextures(1, &glTexDesc.fTextureID)); 940 if (renderTarget && this->glCaps().textureUsageSupport()) { 941 // provides a hint about how this texture will be used 942 GL_CALL(TexParameteri(GR_GL_TEXTURE_2D, 943 GR_GL_TEXTURE_USAGE, 944 GR_GL_FRAMEBUFFER_ATTACHMENT)); 945 } 946 if (!glTexDesc.fTextureID) { 947 return return_null_texture(); 948 } 949 950 this->setSpareTextureUnit(); 951 GL_CALL(BindTexture(GR_GL_TEXTURE_2D, glTexDesc.fTextureID)); 952 953 // Some drivers like to know filter/wrap before seeing glTexImage2D. Some 954 // drivers have a bug where an FBO won't be complete if it includes a 955 // texture that is not mipmap complete (considering the filter in use). 956 GrGLTexture::TexParams initialTexParams; 957 // we only set a subset here so invalidate first 958 initialTexParams.invalidate(); 959 initialTexParams.fFilter = GR_GL_NEAREST; 960 initialTexParams.fWrapS = GR_GL_CLAMP_TO_EDGE; 961 initialTexParams.fWrapT = GR_GL_CLAMP_TO_EDGE; 962 GL_CALL(TexParameteri(GR_GL_TEXTURE_2D, 963 GR_GL_TEXTURE_MAG_FILTER, 964 initialTexParams.fFilter)); 965 GL_CALL(TexParameteri(GR_GL_TEXTURE_2D, 966 GR_GL_TEXTURE_MIN_FILTER, 967 initialTexParams.fFilter)); 968 GL_CALL(TexParameteri(GR_GL_TEXTURE_2D, 969 GR_GL_TEXTURE_WRAP_S, 970 initialTexParams.fWrapS)); 971 GL_CALL(TexParameteri(GR_GL_TEXTURE_2D, 972 GR_GL_TEXTURE_WRAP_T, 973 initialTexParams.fWrapT)); 974 if (!this->uploadTexData(glTexDesc, true, 0, 0, 975 glTexDesc.fWidth, glTexDesc.fHeight, 976 desc.fConfig, srcData, rowBytes)) { 977 GL_CALL(DeleteTextures(1, &glTexDesc.fTextureID)); 978 return return_null_texture(); 979 } 980 981 GrGLTexture* tex; 982 if (renderTarget) { 983 #if GR_COLLECT_STATS 984 ++fStats.fRenderTargetCreateCnt; 985 #endif 986 if (!this->createRenderTargetObjects(glTexDesc.fWidth, 987 glTexDesc.fHeight, 988 glTexDesc.fTextureID, 989 &glRTDesc)) { 990 GL_CALL(DeleteTextures(1, &glTexDesc.fTextureID)); 991 return return_null_texture(); 992 } 993 tex = new GrGLTexture(this, glTexDesc, glRTDesc); 994 } else { 995 tex = new GrGLTexture(this, glTexDesc); 996 } 997 tex->setCachedTexParams(initialTexParams, this->getResetTimestamp()); 998 #ifdef TRACE_TEXTURE_CREATION 999 GrPrintf("--- new texture [%d] size=(%d %d) config=%d\n", 1000 glTexDesc.fTextureID, desc.fWidth, desc.fHeight, desc.fConfig); 1001 #endif 1002 return tex; 1003 } 1004 1005 namespace { 1006 1007 const GrGLuint kUnknownBitCount = GrGLStencilBuffer::kUnknownBitCount; 1008 1009 void inline get_stencil_rb_sizes(const GrGLInterface* gl, 1010 GrGLuint rb, 1011 GrGLStencilBuffer::Format* format) { 1012 // we shouldn't ever know one size and not the other 1013 GrAssert((kUnknownBitCount == format->fStencilBits) == 1014 (kUnknownBitCount == format->fTotalBits)); 1015 if (kUnknownBitCount == format->fStencilBits) { 1016 GR_GL_GetRenderbufferParameteriv(gl, GR_GL_RENDERBUFFER, 1017 GR_GL_RENDERBUFFER_STENCIL_SIZE, 1018 (GrGLint*)&format->fStencilBits); 1019 if (format->fPacked) { 1020 GR_GL_GetRenderbufferParameteriv(gl, GR_GL_RENDERBUFFER, 1021 GR_GL_RENDERBUFFER_DEPTH_SIZE, 1022 (GrGLint*)&format->fTotalBits); 1023 format->fTotalBits += format->fStencilBits; 1024 } else { 1025 format->fTotalBits = format->fStencilBits; 1026 } 1027 } 1028 } 1029 } 1030 1031 bool GrGpuGL::createStencilBufferForRenderTarget(GrRenderTarget* rt, 1032 int width, int height) { 1033 1034 // All internally created RTs are also textures. We don't create 1035 // SBs for a client's standalone RT (that is RT that isnt also a texture). 1036 GrAssert(rt->asTexture()); 1037 GrAssert(width >= rt->width()); 1038 GrAssert(height >= rt->height()); 1039 1040 int samples = rt->numSamples(); 1041 GrGLuint sbID; 1042 GL_CALL(GenRenderbuffers(1, &sbID)); 1043 if (!sbID) { 1044 return false; 1045 } 1046 1047 GrGLStencilBuffer* sb = NULL; 1048 1049 int stencilFmtCnt = this->glCaps().stencilFormats().count(); 1050 for (int i = 0; i < stencilFmtCnt; ++i) { 1051 GL_CALL(BindRenderbuffer(GR_GL_RENDERBUFFER, sbID)); 1052 // we start with the last stencil format that succeeded in hopes 1053 // that we won't go through this loop more than once after the 1054 // first (painful) stencil creation. 1055 int sIdx = (i + fLastSuccessfulStencilFmtIdx) % stencilFmtCnt; 1056 const GrGLCaps::StencilFormat& sFmt = 1057 this->glCaps().stencilFormats()[sIdx]; 1058 CLEAR_ERROR_BEFORE_ALLOC(this->glInterface()); 1059 // we do this "if" so that we don't call the multisample 1060 // version on a GL that doesn't have an MSAA extension. 1061 if (samples > 1) { 1062 GL_ALLOC_CALL(this->glInterface(), 1063 RenderbufferStorageMultisample(GR_GL_RENDERBUFFER, 1064 samples, 1065 sFmt.fInternalFormat, 1066 width, height)); 1067 } else { 1068 GL_ALLOC_CALL(this->glInterface(), 1069 RenderbufferStorage(GR_GL_RENDERBUFFER, 1070 sFmt.fInternalFormat, 1071 width, height)); 1072 } 1073 1074 GrGLenum err = CHECK_ALLOC_ERROR(this->glInterface()); 1075 if (err == GR_GL_NO_ERROR) { 1076 // After sized formats we attempt an unsized format and take whatever 1077 // sizes GL gives us. In that case we query for the size. 1078 GrGLStencilBuffer::Format format = sFmt; 1079 get_stencil_rb_sizes(this->glInterface(), sbID, &format); 1080 sb = new GrGLStencilBuffer(this, sbID, width, height, 1081 samples, format); 1082 if (this->attachStencilBufferToRenderTarget(sb, rt)) { 1083 fLastSuccessfulStencilFmtIdx = sIdx; 1084 rt->setStencilBuffer(sb); 1085 sb->unref(); 1086 return true; 1087 } 1088 sb->abandon(); // otherwise we lose sbID 1089 sb->unref(); 1090 } 1091 } 1092 GL_CALL(DeleteRenderbuffers(1, &sbID)); 1093 return false; 1094 } 1095 1096 bool GrGpuGL::attachStencilBufferToRenderTarget(GrStencilBuffer* sb, 1097 GrRenderTarget* rt) { 1098 GrGLRenderTarget* glrt = (GrGLRenderTarget*) rt; 1099 1100 GrGLuint fbo = glrt->renderFBOID(); 1101 1102 if (NULL == sb) { 1103 if (NULL != rt->getStencilBuffer()) { 1104 GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER, 1105 GR_GL_STENCIL_ATTACHMENT, 1106 GR_GL_RENDERBUFFER, 0)); 1107 GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER, 1108 GR_GL_DEPTH_ATTACHMENT, 1109 GR_GL_RENDERBUFFER, 0)); 1110 #if GR_DEBUG 1111 GrGLenum status; 1112 GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER)); 1113 GrAssert(GR_GL_FRAMEBUFFER_COMPLETE == status); 1114 #endif 1115 } 1116 return true; 1117 } else { 1118 GrGLStencilBuffer* glsb = (GrGLStencilBuffer*) sb; 1119 GrGLuint rb = glsb->renderbufferID(); 1120 1121 fHWDrawState.setRenderTarget(NULL); 1122 GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, fbo)); 1123 GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER, 1124 GR_GL_STENCIL_ATTACHMENT, 1125 GR_GL_RENDERBUFFER, rb)); 1126 if (glsb->format().fPacked) { 1127 GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER, 1128 GR_GL_DEPTH_ATTACHMENT, 1129 GR_GL_RENDERBUFFER, rb)); 1130 } else { 1131 GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER, 1132 GR_GL_DEPTH_ATTACHMENT, 1133 GR_GL_RENDERBUFFER, 0)); 1134 } 1135 1136 GrGLenum status; 1137 if (!this->glCaps().isColorConfigAndStencilFormatVerified(rt->config(), 1138 glsb->format())) { 1139 GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER)); 1140 if (status != GR_GL_FRAMEBUFFER_COMPLETE) { 1141 GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER, 1142 GR_GL_STENCIL_ATTACHMENT, 1143 GR_GL_RENDERBUFFER, 0)); 1144 if (glsb->format().fPacked) { 1145 GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER, 1146 GR_GL_DEPTH_ATTACHMENT, 1147 GR_GL_RENDERBUFFER, 0)); 1148 } 1149 return false; 1150 } else { 1151 fGLContextInfo.caps().markColorConfigAndStencilFormatAsVerified( 1152 rt->config(), 1153 glsb->format()); 1154 } 1155 } 1156 return true; 1157 } 1158 } 1159 1160 //////////////////////////////////////////////////////////////////////////////// 1161 1162 GrVertexBuffer* GrGpuGL::onCreateVertexBuffer(uint32_t size, bool dynamic) { 1163 GrGLuint id; 1164 GL_CALL(GenBuffers(1, &id)); 1165 if (id) { 1166 GL_CALL(BindBuffer(GR_GL_ARRAY_BUFFER, id)); 1167 fHWGeometryState.fArrayPtrsDirty = true; 1168 CLEAR_ERROR_BEFORE_ALLOC(this->glInterface()); 1169 // make sure driver can allocate memory for this buffer 1170 GL_ALLOC_CALL(this->glInterface(), 1171 BufferData(GR_GL_ARRAY_BUFFER, 1172 size, 1173 NULL, // data ptr 1174 dynamic ? GR_GL_DYNAMIC_DRAW : 1175 GR_GL_STATIC_DRAW)); 1176 if (CHECK_ALLOC_ERROR(this->glInterface()) != GR_GL_NO_ERROR) { 1177 GL_CALL(DeleteBuffers(1, &id)); 1178 // deleting bound buffer does implicit bind to 0 1179 fHWGeometryState.fVertexBuffer = NULL; 1180 return NULL; 1181 } 1182 GrGLVertexBuffer* vertexBuffer = new GrGLVertexBuffer(this, id, 1183 size, dynamic); 1184 fHWGeometryState.fVertexBuffer = vertexBuffer; 1185 return vertexBuffer; 1186 } 1187 return NULL; 1188 } 1189 1190 GrIndexBuffer* GrGpuGL::onCreateIndexBuffer(uint32_t size, bool dynamic) { 1191 GrGLuint id; 1192 GL_CALL(GenBuffers(1, &id)); 1193 if (id) { 1194 GL_CALL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, id)); 1195 CLEAR_ERROR_BEFORE_ALLOC(this->glInterface()); 1196 // make sure driver can allocate memory for this buffer 1197 GL_ALLOC_CALL(this->glInterface(), 1198 BufferData(GR_GL_ELEMENT_ARRAY_BUFFER, 1199 size, 1200 NULL, // data ptr 1201 dynamic ? GR_GL_DYNAMIC_DRAW : 1202 GR_GL_STATIC_DRAW)); 1203 if (CHECK_ALLOC_ERROR(this->glInterface()) != GR_GL_NO_ERROR) { 1204 GL_CALL(DeleteBuffers(1, &id)); 1205 // deleting bound buffer does implicit bind to 0 1206 fHWGeometryState.fIndexBuffer = NULL; 1207 return NULL; 1208 } 1209 GrIndexBuffer* indexBuffer = new GrGLIndexBuffer(this, id, 1210 size, dynamic); 1211 fHWGeometryState.fIndexBuffer = indexBuffer; 1212 return indexBuffer; 1213 } 1214 return NULL; 1215 } 1216 1217 void GrGpuGL::flushScissor(const GrIRect* rect) { 1218 const GrDrawState& drawState = this->getDrawState(); 1219 const GrGLRenderTarget* rt = 1220 static_cast<const GrGLRenderTarget*>(drawState.getRenderTarget()); 1221 1222 GrAssert(NULL != rt); 1223 const GrGLIRect& vp = rt->getViewport(); 1224 1225 GrGLIRect scissor; 1226 if (NULL != rect) { 1227 scissor.setRelativeTo(vp, rect->fLeft, rect->fTop, 1228 rect->width(), rect->height()); 1229 if (scissor.contains(vp)) { 1230 rect = NULL; 1231 } 1232 } 1233 1234 if (NULL != rect) { 1235 if (fHWBounds.fScissorRect != scissor) { 1236 scissor.pushToGLScissor(this->glInterface()); 1237 fHWBounds.fScissorRect = scissor; 1238 } 1239 if (!fHWBounds.fScissorEnabled) { 1240 GL_CALL(Enable(GR_GL_SCISSOR_TEST)); 1241 fHWBounds.fScissorEnabled = true; 1242 } 1243 } else { 1244 if (fHWBounds.fScissorEnabled) { 1245 GL_CALL(Disable(GR_GL_SCISSOR_TEST)); 1246 fHWBounds.fScissorEnabled = false; 1247 } 1248 } 1249 } 1250 1251 void GrGpuGL::onClear(const GrIRect* rect, GrColor color) { 1252 const GrDrawState& drawState = this->getDrawState(); 1253 const GrRenderTarget* rt = drawState.getRenderTarget(); 1254 // parent class should never let us get here with no RT 1255 GrAssert(NULL != rt); 1256 1257 GrIRect clippedRect; 1258 if (NULL != rect) { 1259 // flushScissor expects rect to be clipped to the target. 1260 clippedRect = *rect; 1261 GrIRect rtRect = SkIRect::MakeWH(rt->width(), rt->height()); 1262 if (clippedRect.intersect(rtRect)) { 1263 rect = &clippedRect; 1264 } else { 1265 return; 1266 } 1267 } 1268 this->flushRenderTarget(rect); 1269 this->flushScissor(rect); 1270 1271 GrGLfloat r, g, b, a; 1272 static const GrGLfloat scale255 = 1.f / 255.f; 1273 a = GrColorUnpackA(color) * scale255; 1274 GrGLfloat scaleRGB = scale255; 1275 if (GrPixelConfigIsUnpremultiplied(rt->config())) { 1276 scaleRGB *= a; 1277 } 1278 r = GrColorUnpackR(color) * scaleRGB; 1279 g = GrColorUnpackG(color) * scaleRGB; 1280 b = GrColorUnpackB(color) * scaleRGB; 1281 1282 GL_CALL(ColorMask(GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE)); 1283 fHWDrawState.disableState(GrDrawState::kNoColorWrites_StateBit); 1284 GL_CALL(ClearColor(r, g, b, a)); 1285 GL_CALL(Clear(GR_GL_COLOR_BUFFER_BIT)); 1286 } 1287 1288 void GrGpuGL::clearStencil() { 1289 if (NULL == this->getDrawState().getRenderTarget()) { 1290 return; 1291 } 1292 1293 this->flushRenderTarget(&GrIRect::EmptyIRect()); 1294 1295 if (fHWBounds.fScissorEnabled) { 1296 GL_CALL(Disable(GR_GL_SCISSOR_TEST)); 1297 fHWBounds.fScissorEnabled = false; 1298 } 1299 GL_CALL(StencilMask(0xffffffff)); 1300 GL_CALL(ClearStencil(0)); 1301 GL_CALL(Clear(GR_GL_STENCIL_BUFFER_BIT)); 1302 fHWDrawState.stencil()->invalidate(); 1303 } 1304 1305 void GrGpuGL::clearStencilClip(const GrIRect& rect, bool insideClip) { 1306 const GrDrawState& drawState = this->getDrawState(); 1307 const GrRenderTarget* rt = drawState.getRenderTarget(); 1308 GrAssert(NULL != rt); 1309 1310 // this should only be called internally when we know we have a 1311 // stencil buffer. 1312 GrAssert(NULL != rt->getStencilBuffer()); 1313 GrGLint stencilBitCount = rt->getStencilBuffer()->bits(); 1314 #if 0 1315 GrAssert(stencilBitCount > 0); 1316 GrGLint clipStencilMask = (1 << (stencilBitCount - 1)); 1317 #else 1318 // we could just clear the clip bit but when we go through 1319 // ANGLE a partial stencil mask will cause clears to be 1320 // turned into draws. Our contract on GrDrawTarget says that 1321 // changing the clip between stencil passes may or may not 1322 // zero the client's clip bits. So we just clear the whole thing. 1323 static const GrGLint clipStencilMask = ~0; 1324 #endif 1325 GrGLint value; 1326 if (insideClip) { 1327 value = (1 << (stencilBitCount - 1)); 1328 } else { 1329 value = 0; 1330 } 1331 this->flushRenderTarget(&GrIRect::EmptyIRect()); 1332 this->flushScissor(&rect); 1333 GL_CALL(StencilMask(clipStencilMask)); 1334 GL_CALL(ClearStencil(value)); 1335 GL_CALL(Clear(GR_GL_STENCIL_BUFFER_BIT)); 1336 fHWDrawState.stencil()->invalidate(); 1337 } 1338 1339 void GrGpuGL::onForceRenderTargetFlush() { 1340 this->flushRenderTarget(&GrIRect::EmptyIRect()); 1341 } 1342 1343 bool GrGpuGL::readPixelsWillPayForYFlip(GrRenderTarget* renderTarget, 1344 int left, int top, 1345 int width, int height, 1346 GrPixelConfig config, 1347 size_t rowBytes) const { 1348 // if GL can do the flip then we'll never pay for it. 1349 if (this->glCaps().packFlipYSupport()) { 1350 return false; 1351 } 1352 1353 // If we have to do memcpy to handle non-trim rowBytes then we 1354 // get the flip for free. Otherwise it costs. 1355 if (this->glCaps().packRowLengthSupport()) { 1356 return true; 1357 } 1358 // If we have to do memcpys to handle rowBytes then y-flip is free 1359 // Note the rowBytes might be tight to the passed in data, but if data 1360 // gets clipped in x to the target the rowBytes will no longer be tight. 1361 if (left >= 0 && (left + width) < renderTarget->width()) { 1362 return 0 == rowBytes || 1363 GrBytesPerPixel(config) * width == rowBytes; 1364 } else { 1365 return false; 1366 } 1367 } 1368 1369 bool GrGpuGL::onReadPixels(GrRenderTarget* target, 1370 int left, int top, 1371 int width, int height, 1372 GrPixelConfig config, 1373 void* buffer, 1374 size_t rowBytes, 1375 bool invertY) { 1376 GrGLenum format; 1377 GrGLenum type; 1378 if (!this->configToGLFormats(config, false, NULL, &format, &type)) { 1379 return false; 1380 } 1381 size_t bpp = GrBytesPerPixel(config); 1382 if (!adjust_pixel_ops_params(target->width(), target->height(), bpp, 1383 &left, &top, &width, &height, 1384 const_cast<const void**>(&buffer), 1385 &rowBytes)) { 1386 return false; 1387 } 1388 1389 // resolve the render target if necessary 1390 GrGLRenderTarget* tgt = static_cast<GrGLRenderTarget*>(target); 1391 GrDrawState::AutoRenderTargetRestore artr; 1392 switch (tgt->getResolveType()) { 1393 case GrGLRenderTarget::kCantResolve_ResolveType: 1394 return false; 1395 case GrGLRenderTarget::kAutoResolves_ResolveType: 1396 artr.set(this->drawState(), target); 1397 this->flushRenderTarget(&GrIRect::EmptyIRect()); 1398 break; 1399 case GrGLRenderTarget::kCanResolve_ResolveType: 1400 this->onResolveRenderTarget(tgt); 1401 // we don't track the state of the READ FBO ID. 1402 GL_CALL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER, 1403 tgt->textureFBOID())); 1404 break; 1405 default: 1406 GrCrash("Unknown resolve type"); 1407 } 1408 1409 const GrGLIRect& glvp = tgt->getViewport(); 1410 1411 // the read rect is viewport-relative 1412 GrGLIRect readRect; 1413 readRect.setRelativeTo(glvp, left, top, width, height); 1414 1415 size_t tightRowBytes = bpp * width; 1416 if (0 == rowBytes) { 1417 rowBytes = tightRowBytes; 1418 } 1419 size_t readDstRowBytes = tightRowBytes; 1420 void* readDst = buffer; 1421 1422 // determine if GL can read using the passed rowBytes or if we need 1423 // a scratch buffer. 1424 SkAutoSMalloc<32 * sizeof(GrColor)> scratch; 1425 if (rowBytes != tightRowBytes) { 1426 if (this->glCaps().packRowLengthSupport()) { 1427 GrAssert(!(rowBytes % sizeof(GrColor))); 1428 GL_CALL(PixelStorei(GR_GL_PACK_ROW_LENGTH, rowBytes / sizeof(GrColor))); 1429 readDstRowBytes = rowBytes; 1430 } else { 1431 scratch.reset(tightRowBytes * height); 1432 readDst = scratch.get(); 1433 } 1434 } 1435 if (!invertY && this->glCaps().packFlipYSupport()) { 1436 GL_CALL(PixelStorei(GR_GL_PACK_REVERSE_ROW_ORDER, 1)); 1437 } 1438 GL_CALL(ReadPixels(readRect.fLeft, readRect.fBottom, 1439 readRect.fWidth, readRect.fHeight, 1440 format, type, readDst)); 1441 if (readDstRowBytes != tightRowBytes) { 1442 GrAssert(this->glCaps().packRowLengthSupport()); 1443 GL_CALL(PixelStorei(GR_GL_PACK_ROW_LENGTH, 0)); 1444 } 1445 if (!invertY && this->glCaps().packFlipYSupport()) { 1446 GL_CALL(PixelStorei(GR_GL_PACK_REVERSE_ROW_ORDER, 0)); 1447 invertY = true; 1448 } 1449 1450 // now reverse the order of the rows, since GL's are bottom-to-top, but our 1451 // API presents top-to-bottom. We must preserve the padding contents. Note 1452 // that the above readPixels did not overwrite the padding. 1453 if (readDst == buffer) { 1454 GrAssert(rowBytes == readDstRowBytes); 1455 if (!invertY) { 1456 scratch.reset(tightRowBytes); 1457 void* tmpRow = scratch.get(); 1458 // flip y in-place by rows 1459 const int halfY = height >> 1; 1460 char* top = reinterpret_cast<char*>(buffer); 1461 char* bottom = top + (height - 1) * rowBytes; 1462 for (int y = 0; y < halfY; y++) { 1463 memcpy(tmpRow, top, tightRowBytes); 1464 memcpy(top, bottom, tightRowBytes); 1465 memcpy(bottom, tmpRow, tightRowBytes); 1466 top += rowBytes; 1467 bottom -= rowBytes; 1468 } 1469 } 1470 } else { 1471 GrAssert(readDst != buffer); GrAssert(rowBytes != tightRowBytes); 1472 // copy from readDst to buffer while flipping y 1473 const int halfY = height >> 1; 1474 const char* src = reinterpret_cast<const char*>(readDst); 1475 char* dst = reinterpret_cast<char*>(buffer); 1476 if (!invertY) { 1477 dst += (height-1) * rowBytes; 1478 } 1479 for (int y = 0; y < height; y++) { 1480 memcpy(dst, src, tightRowBytes); 1481 src += readDstRowBytes; 1482 if (invertY) { 1483 dst += rowBytes; 1484 } else { 1485 dst -= rowBytes; 1486 } 1487 } 1488 } 1489 return true; 1490 } 1491 1492 void GrGpuGL::flushRenderTarget(const GrIRect* bound) { 1493 1494 GrGLRenderTarget* rt = 1495 static_cast<GrGLRenderTarget*>(this->drawState()->getRenderTarget()); 1496 GrAssert(NULL != rt); 1497 1498 if (fHWDrawState.getRenderTarget() != rt) { 1499 GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, rt->renderFBOID())); 1500 #if GR_COLLECT_STATS 1501 ++fStats.fRenderTargetChngCnt; 1502 #endif 1503 #if GR_DEBUG 1504 GrGLenum status; 1505 GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER)); 1506 if (status != GR_GL_FRAMEBUFFER_COMPLETE) { 1507 GrPrintf("GrGpuGL::flushRenderTarget glCheckFramebufferStatus %x\n", status); 1508 } 1509 #endif 1510 fDirtyFlags.fRenderTargetChanged = true; 1511 fHWDrawState.setRenderTarget(rt); 1512 const GrGLIRect& vp = rt->getViewport(); 1513 if (fHWBounds.fViewportRect != vp) { 1514 vp.pushToGLViewport(this->glInterface()); 1515 fHWBounds.fViewportRect = vp; 1516 } 1517 } 1518 if (NULL == bound || !bound->isEmpty()) { 1519 rt->flagAsNeedingResolve(bound); 1520 } 1521 } 1522 1523 GrGLenum gPrimitiveType2GLMode[] = { 1524 GR_GL_TRIANGLES, 1525 GR_GL_TRIANGLE_STRIP, 1526 GR_GL_TRIANGLE_FAN, 1527 GR_GL_POINTS, 1528 GR_GL_LINES, 1529 GR_GL_LINE_STRIP 1530 }; 1531 1532 #define SWAP_PER_DRAW 0 1533 1534 #if SWAP_PER_DRAW 1535 #if GR_MAC_BUILD 1536 #include <AGL/agl.h> 1537 #elif GR_WIN32_BUILD 1538 void SwapBuf() { 1539 DWORD procID = GetCurrentProcessId(); 1540 HWND hwnd = GetTopWindow(GetDesktopWindow()); 1541 while(hwnd) { 1542 DWORD wndProcID = 0; 1543 GetWindowThreadProcessId(hwnd, &wndProcID); 1544 if(wndProcID == procID) { 1545 SwapBuffers(GetDC(hwnd)); 1546 } 1547 hwnd = GetNextWindow(hwnd, GW_HWNDNEXT); 1548 } 1549 } 1550 #endif 1551 #endif 1552 1553 void GrGpuGL::onGpuDrawIndexed(GrPrimitiveType type, 1554 uint32_t startVertex, 1555 uint32_t startIndex, 1556 uint32_t vertexCount, 1557 uint32_t indexCount) { 1558 GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode)); 1559 1560 GrGLvoid* indices = (GrGLvoid*)(sizeof(uint16_t) * startIndex); 1561 1562 GrAssert(NULL != fHWGeometryState.fIndexBuffer); 1563 GrAssert(NULL != fHWGeometryState.fVertexBuffer); 1564 1565 // our setupGeometry better have adjusted this to zero since 1566 // DrawElements always draws from the begining of the arrays for idx 0. 1567 GrAssert(0 == startVertex); 1568 1569 GL_CALL(DrawElements(gPrimitiveType2GLMode[type], indexCount, 1570 GR_GL_UNSIGNED_SHORT, indices)); 1571 #if SWAP_PER_DRAW 1572 glFlush(); 1573 #if GR_MAC_BUILD 1574 aglSwapBuffers(aglGetCurrentContext()); 1575 int set_a_break_pt_here = 9; 1576 aglSwapBuffers(aglGetCurrentContext()); 1577 #elif GR_WIN32_BUILD 1578 SwapBuf(); 1579 int set_a_break_pt_here = 9; 1580 SwapBuf(); 1581 #endif 1582 #endif 1583 } 1584 1585 void GrGpuGL::onGpuDrawNonIndexed(GrPrimitiveType type, 1586 uint32_t startVertex, 1587 uint32_t vertexCount) { 1588 GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode)); 1589 1590 GrAssert(NULL != fHWGeometryState.fVertexBuffer); 1591 1592 // our setupGeometry better have adjusted this to zero. 1593 // DrawElements doesn't take an offset so we always adjus the startVertex. 1594 GrAssert(0 == startVertex); 1595 1596 // pass 0 for parameter first. We have to adjust gl*Pointer() to 1597 // account for startVertex in the DrawElements case. So we always 1598 // rely on setupGeometry to have accounted for startVertex. 1599 GL_CALL(DrawArrays(gPrimitiveType2GLMode[type], 0, vertexCount)); 1600 #if SWAP_PER_DRAW 1601 glFlush(); 1602 #if GR_MAC_BUILD 1603 aglSwapBuffers(aglGetCurrentContext()); 1604 int set_a_break_pt_here = 9; 1605 aglSwapBuffers(aglGetCurrentContext()); 1606 #elif GR_WIN32_BUILD 1607 SwapBuf(); 1608 int set_a_break_pt_here = 9; 1609 SwapBuf(); 1610 #endif 1611 #endif 1612 } 1613 1614 void GrGpuGL::onResolveRenderTarget(GrRenderTarget* target) { 1615 1616 GrGLRenderTarget* rt = static_cast<GrGLRenderTarget*>(target); 1617 1618 if (rt->needsResolve()) { 1619 GrAssert(GrGLCaps::kNone_MSFBOType != this->glCaps().msFBOType()); 1620 GrAssert(rt->textureFBOID() != rt->renderFBOID()); 1621 GL_CALL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER, 1622 rt->renderFBOID())); 1623 GL_CALL(BindFramebuffer(GR_GL_DRAW_FRAMEBUFFER, 1624 rt->textureFBOID())); 1625 #if GR_COLLECT_STATS 1626 ++fStats.fRenderTargetChngCnt; 1627 #endif 1628 // make sure we go through flushRenderTarget() since we've modified 1629 // the bound DRAW FBO ID. 1630 fHWDrawState.setRenderTarget(NULL); 1631 const GrGLIRect& vp = rt->getViewport(); 1632 const GrIRect dirtyRect = rt->getResolveRect(); 1633 GrGLIRect r; 1634 r.setRelativeTo(vp, dirtyRect.fLeft, dirtyRect.fTop, 1635 dirtyRect.width(), dirtyRect.height()); 1636 1637 if (GrGLCaps::kAppleES_MSFBOType == this->glCaps().msFBOType()) { 1638 // Apple's extension uses the scissor as the blit bounds. 1639 GL_CALL(Enable(GR_GL_SCISSOR_TEST)); 1640 GL_CALL(Scissor(r.fLeft, r.fBottom, 1641 r.fWidth, r.fHeight)); 1642 GL_CALL(ResolveMultisampleFramebuffer()); 1643 fHWBounds.fScissorRect.invalidate(); 1644 fHWBounds.fScissorEnabled = true; 1645 } else { 1646 if (GrGLCaps::kDesktopARB_MSFBOType != this->glCaps().msFBOType()) { 1647 // this respects the scissor during the blit, so disable it. 1648 GrAssert(GrGLCaps::kDesktopEXT_MSFBOType == 1649 this->glCaps().msFBOType()); 1650 this->flushScissor(NULL); 1651 } 1652 int right = r.fLeft + r.fWidth; 1653 int top = r.fBottom + r.fHeight; 1654 GL_CALL(BlitFramebuffer(r.fLeft, r.fBottom, right, top, 1655 r.fLeft, r.fBottom, right, top, 1656 GR_GL_COLOR_BUFFER_BIT, GR_GL_NEAREST)); 1657 } 1658 rt->flagAsResolved(); 1659 } 1660 } 1661 1662 static const GrGLenum grToGLStencilFunc[] = { 1663 GR_GL_ALWAYS, // kAlways_StencilFunc 1664 GR_GL_NEVER, // kNever_StencilFunc 1665 GR_GL_GREATER, // kGreater_StencilFunc 1666 GR_GL_GEQUAL, // kGEqual_StencilFunc 1667 GR_GL_LESS, // kLess_StencilFunc 1668 GR_GL_LEQUAL, // kLEqual_StencilFunc, 1669 GR_GL_EQUAL, // kEqual_StencilFunc, 1670 GR_GL_NOTEQUAL, // kNotEqual_StencilFunc, 1671 }; 1672 GR_STATIC_ASSERT(GR_ARRAY_COUNT(grToGLStencilFunc) == kBasicStencilFuncCount); 1673 GR_STATIC_ASSERT(0 == kAlways_StencilFunc); 1674 GR_STATIC_ASSERT(1 == kNever_StencilFunc); 1675 GR_STATIC_ASSERT(2 == kGreater_StencilFunc); 1676 GR_STATIC_ASSERT(3 == kGEqual_StencilFunc); 1677 GR_STATIC_ASSERT(4 == kLess_StencilFunc); 1678 GR_STATIC_ASSERT(5 == kLEqual_StencilFunc); 1679 GR_STATIC_ASSERT(6 == kEqual_StencilFunc); 1680 GR_STATIC_ASSERT(7 == kNotEqual_StencilFunc); 1681 1682 static const GrGLenum grToGLStencilOp[] = { 1683 GR_GL_KEEP, // kKeep_StencilOp 1684 GR_GL_REPLACE, // kReplace_StencilOp 1685 GR_GL_INCR_WRAP, // kIncWrap_StencilOp 1686 GR_GL_INCR, // kIncClamp_StencilOp 1687 GR_GL_DECR_WRAP, // kDecWrap_StencilOp 1688 GR_GL_DECR, // kDecClamp_StencilOp 1689 GR_GL_ZERO, // kZero_StencilOp 1690 GR_GL_INVERT, // kInvert_StencilOp 1691 }; 1692 GR_STATIC_ASSERT(GR_ARRAY_COUNT(grToGLStencilOp) == kStencilOpCount); 1693 GR_STATIC_ASSERT(0 == kKeep_StencilOp); 1694 GR_STATIC_ASSERT(1 == kReplace_StencilOp); 1695 GR_STATIC_ASSERT(2 == kIncWrap_StencilOp); 1696 GR_STATIC_ASSERT(3 == kIncClamp_StencilOp); 1697 GR_STATIC_ASSERT(4 == kDecWrap_StencilOp); 1698 GR_STATIC_ASSERT(5 == kDecClamp_StencilOp); 1699 GR_STATIC_ASSERT(6 == kZero_StencilOp); 1700 GR_STATIC_ASSERT(7 == kInvert_StencilOp); 1701 1702 void GrGpuGL::flushStencil() { 1703 const GrDrawState& drawState = this->getDrawState(); 1704 1705 const GrStencilSettings* settings = &drawState.getStencil(); 1706 1707 // use stencil for clipping if clipping is enabled and the clip 1708 // has been written into the stencil. 1709 bool stencilClip = fClipInStencil && drawState.isClipState(); 1710 bool drawClipToStencil = 1711 drawState.isStateFlagEnabled(kModifyStencilClip_StateBit); 1712 bool stencilChange = (fHWDrawState.getStencil() != *settings) || 1713 (fHWStencilClip != stencilClip) || 1714 (fHWDrawState.isStateFlagEnabled(kModifyStencilClip_StateBit) != 1715 drawClipToStencil); 1716 1717 if (stencilChange) { 1718 1719 // we can't simultaneously perform stencil-clipping and 1720 // modify the stencil clip 1721 GrAssert(!stencilClip || !drawClipToStencil); 1722 1723 if (settings->isDisabled()) { 1724 if (stencilClip) { 1725 settings = GetClipStencilSettings(); 1726 } 1727 } 1728 1729 if (settings->isDisabled()) { 1730 GL_CALL(Disable(GR_GL_STENCIL_TEST)); 1731 } else { 1732 GL_CALL(Enable(GR_GL_STENCIL_TEST)); 1733 #if GR_DEBUG 1734 if (!this->getCaps().fStencilWrapOpsSupport) { 1735 GrAssert(settings->frontPassOp() != kIncWrap_StencilOp); 1736 GrAssert(settings->frontPassOp() != kDecWrap_StencilOp); 1737 GrAssert(settings->frontFailOp() != kIncWrap_StencilOp); 1738 GrAssert(settings->backFailOp() != kDecWrap_StencilOp); 1739 GrAssert(settings->backPassOp() != kIncWrap_StencilOp); 1740 GrAssert(settings->backPassOp() != kDecWrap_StencilOp); 1741 GrAssert(settings->backFailOp() != kIncWrap_StencilOp); 1742 GrAssert(settings->frontFailOp() != kDecWrap_StencilOp); 1743 } 1744 #endif 1745 int stencilBits = 0; 1746 GrStencilBuffer* stencilBuffer = 1747 drawState.getRenderTarget()->getStencilBuffer(); 1748 if (NULL != stencilBuffer) { 1749 stencilBits = stencilBuffer->bits(); 1750 } 1751 // TODO: dynamically attach a stencil buffer 1752 GrAssert(stencilBits || settings->isDisabled()); 1753 1754 GrGLuint clipStencilMask = 0; 1755 GrGLuint userStencilMask = ~0; 1756 if (stencilBits > 0) { 1757 clipStencilMask = 1 << (stencilBits - 1); 1758 userStencilMask = clipStencilMask - 1; 1759 } 1760 1761 unsigned int frontRef = settings->frontFuncRef(); 1762 unsigned int frontMask = settings->frontFuncMask(); 1763 unsigned int frontWriteMask = settings->frontWriteMask(); 1764 GrGLenum frontFunc; 1765 1766 if (drawClipToStencil) { 1767 GrAssert(settings->frontFunc() < kBasicStencilFuncCount); 1768 frontFunc = grToGLStencilFunc[settings->frontFunc()]; 1769 } else { 1770 frontFunc = grToGLStencilFunc[ConvertStencilFunc( 1771 stencilClip, settings->frontFunc())]; 1772 1773 ConvertStencilFuncAndMask(settings->frontFunc(), 1774 stencilClip, 1775 clipStencilMask, 1776 userStencilMask, 1777 &frontRef, 1778 &frontMask); 1779 frontWriteMask &= userStencilMask; 1780 } 1781 GrAssert((size_t) 1782 settings->frontFailOp() < GR_ARRAY_COUNT(grToGLStencilOp)); 1783 GrAssert((size_t) 1784 settings->frontPassOp() < GR_ARRAY_COUNT(grToGLStencilOp)); 1785 GrAssert((size_t) 1786 settings->backFailOp() < GR_ARRAY_COUNT(grToGLStencilOp)); 1787 GrAssert((size_t) 1788 settings->backPassOp() < GR_ARRAY_COUNT(grToGLStencilOp)); 1789 if (this->getCaps().fTwoSidedStencilSupport) { 1790 GrGLenum backFunc; 1791 1792 unsigned int backRef = settings->backFuncRef(); 1793 unsigned int backMask = settings->backFuncMask(); 1794 unsigned int backWriteMask = settings->backWriteMask(); 1795 1796 1797 if (drawClipToStencil) { 1798 GrAssert(settings->backFunc() < kBasicStencilFuncCount); 1799 backFunc = grToGLStencilFunc[settings->backFunc()]; 1800 } else { 1801 backFunc = grToGLStencilFunc[ConvertStencilFunc( 1802 stencilClip, settings->backFunc())]; 1803 ConvertStencilFuncAndMask(settings->backFunc(), 1804 stencilClip, 1805 clipStencilMask, 1806 userStencilMask, 1807 &backRef, 1808 &backMask); 1809 backWriteMask &= userStencilMask; 1810 } 1811 1812 GL_CALL(StencilFuncSeparate(GR_GL_FRONT, frontFunc, 1813 frontRef, frontMask)); 1814 GL_CALL(StencilMaskSeparate(GR_GL_FRONT, frontWriteMask)); 1815 GL_CALL(StencilFuncSeparate(GR_GL_BACK, backFunc, 1816 backRef, backMask)); 1817 GL_CALL(StencilMaskSeparate(GR_GL_BACK, backWriteMask)); 1818 GL_CALL(StencilOpSeparate(GR_GL_FRONT, 1819 grToGLStencilOp[settings->frontFailOp()], 1820 grToGLStencilOp[settings->frontPassOp()], 1821 grToGLStencilOp[settings->frontPassOp()])); 1822 1823 GL_CALL(StencilOpSeparate(GR_GL_BACK, 1824 grToGLStencilOp[settings->backFailOp()], 1825 grToGLStencilOp[settings->backPassOp()], 1826 grToGLStencilOp[settings->backPassOp()])); 1827 } else { 1828 GL_CALL(StencilFunc(frontFunc, frontRef, frontMask)); 1829 GL_CALL(StencilMask(frontWriteMask)); 1830 GL_CALL(StencilOp(grToGLStencilOp[settings->frontFailOp()], 1831 grToGLStencilOp[settings->frontPassOp()], 1832 grToGLStencilOp[settings->frontPassOp()])); 1833 } 1834 } 1835 *fHWDrawState.stencil() = *settings; 1836 fHWStencilClip = stencilClip; 1837 } 1838 } 1839 1840 void GrGpuGL::flushAAState(GrPrimitiveType type) { 1841 const GrRenderTarget* rt = this->getDrawState().getRenderTarget(); 1842 if (kDesktop_GrGLBinding == this->glBinding()) { 1843 // ES doesn't support toggling GL_MULTISAMPLE and doesn't have 1844 // smooth lines. 1845 1846 // we prefer smooth lines over multisampled lines 1847 // msaa should be disabled if drawing smooth lines. 1848 if (GrIsPrimTypeLines(type)) { 1849 bool smooth = this->willUseHWAALines(); 1850 if (!fHWAAState.fSmoothLineEnabled && smooth) { 1851 GL_CALL(Enable(GR_GL_LINE_SMOOTH)); 1852 fHWAAState.fSmoothLineEnabled = true; 1853 } else if (fHWAAState.fSmoothLineEnabled && !smooth) { 1854 GL_CALL(Disable(GR_GL_LINE_SMOOTH)); 1855 fHWAAState.fSmoothLineEnabled = false; 1856 } 1857 if (rt->isMultisampled() && 1858 fHWAAState.fMSAAEnabled) { 1859 GL_CALL(Disable(GR_GL_MULTISAMPLE)); 1860 fHWAAState.fMSAAEnabled = false; 1861 } 1862 } else if (rt->isMultisampled() && 1863 this->getDrawState().isHWAntialiasState() != 1864 fHWAAState.fMSAAEnabled) { 1865 if (fHWAAState.fMSAAEnabled) { 1866 GL_CALL(Disable(GR_GL_MULTISAMPLE)); 1867 fHWAAState.fMSAAEnabled = false; 1868 } else { 1869 GL_CALL(Enable(GR_GL_MULTISAMPLE)); 1870 fHWAAState.fMSAAEnabled = true; 1871 } 1872 } 1873 } 1874 } 1875 1876 void GrGpuGL::flushBlend(GrPrimitiveType type, 1877 GrBlendCoeff srcCoeff, 1878 GrBlendCoeff dstCoeff) { 1879 if (GrIsPrimTypeLines(type) && this->willUseHWAALines()) { 1880 if (fHWBlendDisabled) { 1881 GL_CALL(Enable(GR_GL_BLEND)); 1882 fHWBlendDisabled = false; 1883 } 1884 if (kSA_BlendCoeff != fHWDrawState.getSrcBlendCoeff() || 1885 kISA_BlendCoeff != fHWDrawState.getDstBlendCoeff()) { 1886 GL_CALL(BlendFunc(gXfermodeCoeff2Blend[kSA_BlendCoeff], 1887 gXfermodeCoeff2Blend[kISA_BlendCoeff])); 1888 fHWDrawState.setBlendFunc(kSA_BlendCoeff, kISA_BlendCoeff); 1889 } 1890 } else { 1891 // any optimization to disable blending should 1892 // have already been applied and tweaked the coeffs 1893 // to (1, 0). 1894 bool blendOff = kOne_BlendCoeff == srcCoeff && 1895 kZero_BlendCoeff == dstCoeff; 1896 if (fHWBlendDisabled != blendOff) { 1897 if (blendOff) { 1898 GL_CALL(Disable(GR_GL_BLEND)); 1899 } else { 1900 GL_CALL(Enable(GR_GL_BLEND)); 1901 } 1902 fHWBlendDisabled = blendOff; 1903 } 1904 if (!blendOff) { 1905 if (fHWDrawState.getSrcBlendCoeff() != srcCoeff || 1906 fHWDrawState.getDstBlendCoeff() != dstCoeff) { 1907 GL_CALL(BlendFunc(gXfermodeCoeff2Blend[srcCoeff], 1908 gXfermodeCoeff2Blend[dstCoeff])); 1909 fHWDrawState.setBlendFunc(srcCoeff, dstCoeff); 1910 } 1911 GrColor blendConst = fCurrDrawState.getBlendConstant(); 1912 if ((BlendCoeffReferencesConstant(srcCoeff) || 1913 BlendCoeffReferencesConstant(dstCoeff)) && 1914 fHWDrawState.getBlendConstant() != blendConst) { 1915 1916 float c[] = { 1917 GrColorUnpackR(blendConst) / 255.f, 1918 GrColorUnpackG(blendConst) / 255.f, 1919 GrColorUnpackB(blendConst) / 255.f, 1920 GrColorUnpackA(blendConst) / 255.f 1921 }; 1922 GL_CALL(BlendColor(c[0], c[1], c[2], c[3])); 1923 fHWDrawState.setBlendConstant(blendConst); 1924 } 1925 } 1926 } 1927 } 1928 1929 namespace { 1930 1931 unsigned gr_to_gl_filter(GrSamplerState::Filter filter) { 1932 switch (filter) { 1933 case GrSamplerState::kBilinear_Filter: 1934 case GrSamplerState::k4x4Downsample_Filter: 1935 return GR_GL_LINEAR; 1936 case GrSamplerState::kNearest_Filter: 1937 case GrSamplerState::kConvolution_Filter: 1938 case GrSamplerState::kErode_Filter: 1939 case GrSamplerState::kDilate_Filter: 1940 return GR_GL_NEAREST; 1941 default: 1942 GrAssert(!"Unknown filter type"); 1943 return GR_GL_LINEAR; 1944 } 1945 } 1946 1947 const GrGLenum* get_swizzle(GrPixelConfig config, 1948 const GrSamplerState& sampler) { 1949 if (GrPixelConfigIsAlphaOnly(config)) { 1950 static const GrGLenum gAlphaSmear[] = { GR_GL_ALPHA, GR_GL_ALPHA, 1951 GR_GL_ALPHA, GR_GL_ALPHA }; 1952 return gAlphaSmear; 1953 } else if (sampler.swapsRAndB()) { 1954 static const GrGLenum gRedBlueSwap[] = { GR_GL_BLUE, GR_GL_GREEN, 1955 GR_GL_RED, GR_GL_ALPHA }; 1956 return gRedBlueSwap; 1957 } else { 1958 static const GrGLenum gStraight[] = { GR_GL_RED, GR_GL_GREEN, 1959 GR_GL_BLUE, GR_GL_ALPHA }; 1960 return gStraight; 1961 } 1962 } 1963 1964 void set_tex_swizzle(GrGLenum swizzle[4], const GrGLInterface* gl) { 1965 // should add texparameteri to interface to make 1 instead of 4 calls here 1966 GR_GL_CALL(gl, TexParameteri(GR_GL_TEXTURE_2D, 1967 GR_GL_TEXTURE_SWIZZLE_R, 1968 swizzle[0])); 1969 GR_GL_CALL(gl, TexParameteri(GR_GL_TEXTURE_2D, 1970 GR_GL_TEXTURE_SWIZZLE_G, 1971 swizzle[1])); 1972 GR_GL_CALL(gl, TexParameteri(GR_GL_TEXTURE_2D, 1973 GR_GL_TEXTURE_SWIZZLE_B, 1974 swizzle[2])); 1975 GR_GL_CALL(gl, TexParameteri(GR_GL_TEXTURE_2D, 1976 GR_GL_TEXTURE_SWIZZLE_A, 1977 swizzle[3])); 1978 } 1979 } 1980 1981 bool GrGpuGL::flushGLStateCommon(GrPrimitiveType type) { 1982 1983 GrDrawState* drawState = this->drawState(); 1984 // GrGpu::setupClipAndFlushState should have already checked this 1985 // and bailed if not true. 1986 GrAssert(NULL != drawState->getRenderTarget()); 1987 1988 for (int s = 0; s < GrDrawState::kNumStages; ++s) { 1989 // bind texture and set sampler state 1990 if (this->isStageEnabled(s)) { 1991 GrGLTexture* nextTexture = 1992 static_cast<GrGLTexture*>(drawState->getTexture(s)); 1993 1994 // true for now, but maybe not with GrEffect. 1995 GrAssert(NULL != nextTexture); 1996 // if we created a rt/tex and rendered to it without using a 1997 // texture and now we're texuring from the rt it will still be 1998 // the last bound texture, but it needs resolving. So keep this 1999 // out of the "last != next" check. 2000 GrGLRenderTarget* texRT = 2001 static_cast<GrGLRenderTarget*>(nextTexture->asRenderTarget()); 2002 if (NULL != texRT) { 2003 this->onResolveRenderTarget(texRT); 2004 } 2005 2006 if (fHWDrawState.getTexture(s) != nextTexture) { 2007 setTextureUnit(s); 2008 GL_CALL(BindTexture(GR_GL_TEXTURE_2D, nextTexture->textureID())); 2009 #if GR_COLLECT_STATS 2010 ++fStats.fTextureChngCnt; 2011 #endif 2012 //GrPrintf("---- bindtexture %d\n", nextTexture->textureID()); 2013 fHWDrawState.setTexture(s, nextTexture); 2014 // The texture matrix has to compensate for texture width/height 2015 // and NPOT-embedded-in-POT 2016 fDirtyFlags.fTextureChangedMask |= (1 << s); 2017 } 2018 2019 const GrSamplerState& sampler = drawState->getSampler(s); 2020 ResetTimestamp timestamp; 2021 const GrGLTexture::TexParams& oldTexParams = 2022 nextTexture->getCachedTexParams(×tamp); 2023 bool setAll = timestamp < this->getResetTimestamp(); 2024 GrGLTexture::TexParams newTexParams; 2025 2026 newTexParams.fFilter = gr_to_gl_filter(sampler.getFilter()); 2027 2028 const GrGLenum* wraps = GrGLTexture::WrapMode2GLWrap(); 2029 newTexParams.fWrapS = wraps[sampler.getWrapX()]; 2030 newTexParams.fWrapT = wraps[sampler.getWrapY()]; 2031 memcpy(newTexParams.fSwizzleRGBA, 2032 get_swizzle(nextTexture->config(), sampler), 2033 sizeof(newTexParams.fSwizzleRGBA)); 2034 if (setAll || newTexParams.fFilter != oldTexParams.fFilter) { 2035 setTextureUnit(s); 2036 GL_CALL(TexParameteri(GR_GL_TEXTURE_2D, 2037 GR_GL_TEXTURE_MAG_FILTER, 2038 newTexParams.fFilter)); 2039 GL_CALL(TexParameteri(GR_GL_TEXTURE_2D, 2040 GR_GL_TEXTURE_MIN_FILTER, 2041 newTexParams.fFilter)); 2042 } 2043 if (setAll || newTexParams.fWrapS != oldTexParams.fWrapS) { 2044 setTextureUnit(s); 2045 GL_CALL(TexParameteri(GR_GL_TEXTURE_2D, 2046 GR_GL_TEXTURE_WRAP_S, 2047 newTexParams.fWrapS)); 2048 } 2049 if (setAll || newTexParams.fWrapT != oldTexParams.fWrapT) { 2050 setTextureUnit(s); 2051 GL_CALL(TexParameteri(GR_GL_TEXTURE_2D, 2052 GR_GL_TEXTURE_WRAP_T, 2053 newTexParams.fWrapT)); 2054 } 2055 if (this->glCaps().textureSwizzleSupport() && 2056 (setAll || 2057 memcmp(newTexParams.fSwizzleRGBA, 2058 oldTexParams.fSwizzleRGBA, 2059 sizeof(newTexParams.fSwizzleRGBA)))) { 2060 setTextureUnit(s); 2061 set_tex_swizzle(newTexParams.fSwizzleRGBA, 2062 this->glInterface()); 2063 } 2064 nextTexture->setCachedTexParams(newTexParams, 2065 this->getResetTimestamp()); 2066 } 2067 } 2068 2069 GrIRect* rect = NULL; 2070 GrIRect clipBounds; 2071 if (drawState->isClipState() && 2072 fClip.hasConservativeBounds()) { 2073 fClip.getConservativeBounds().roundOut(&clipBounds); 2074 rect = &clipBounds; 2075 } 2076 this->flushRenderTarget(rect); 2077 this->flushAAState(type); 2078 2079 if (drawState->isDitherState() != fHWDrawState.isDitherState()) { 2080 if (drawState->isDitherState()) { 2081 GL_CALL(Enable(GR_GL_DITHER)); 2082 } else { 2083 GL_CALL(Disable(GR_GL_DITHER)); 2084 } 2085 } 2086 2087 if (drawState->isColorWriteDisabled() != 2088 fHWDrawState.isColorWriteDisabled()) { 2089 GrGLenum mask; 2090 if (drawState->isColorWriteDisabled()) { 2091 mask = GR_GL_FALSE; 2092 } else { 2093 mask = GR_GL_TRUE; 2094 } 2095 GL_CALL(ColorMask(mask, mask, mask, mask)); 2096 } 2097 2098 if (fHWDrawState.getDrawFace() != drawState->getDrawFace()) { 2099 switch (fCurrDrawState.getDrawFace()) { 2100 case GrDrawState::kCCW_DrawFace: 2101 GL_CALL(Enable(GR_GL_CULL_FACE)); 2102 GL_CALL(CullFace(GR_GL_BACK)); 2103 break; 2104 case GrDrawState::kCW_DrawFace: 2105 GL_CALL(Enable(GR_GL_CULL_FACE)); 2106 GL_CALL(CullFace(GR_GL_FRONT)); 2107 break; 2108 case GrDrawState::kBoth_DrawFace: 2109 GL_CALL(Disable(GR_GL_CULL_FACE)); 2110 break; 2111 default: 2112 GrCrash("Unknown draw face."); 2113 } 2114 fHWDrawState.setDrawFace(drawState->getDrawFace()); 2115 } 2116 2117 #if GR_DEBUG 2118 // check for circular rendering 2119 for (int s = 0; s < GrDrawState::kNumStages; ++s) { 2120 GrAssert(!this->isStageEnabled(s) || 2121 NULL == drawState->getRenderTarget() || 2122 NULL == drawState->getTexture(s) || 2123 drawState->getTexture(s)->asRenderTarget() != 2124 drawState->getRenderTarget()); 2125 } 2126 #endif 2127 2128 this->flushStencil(); 2129 2130 // This copy must happen after flushStencil() is called. flushStencil() 2131 // relies on detecting when the kModifyStencilClip_StateBit state has 2132 // changed since the last draw. 2133 fHWDrawState.copyStateFlags(*drawState); 2134 return true; 2135 } 2136 2137 void GrGpuGL::notifyVertexBufferBind(const GrGLVertexBuffer* buffer) { 2138 if (fHWGeometryState.fVertexBuffer != buffer) { 2139 fHWGeometryState.fArrayPtrsDirty = true; 2140 fHWGeometryState.fVertexBuffer = buffer; 2141 } 2142 } 2143 2144 void GrGpuGL::notifyVertexBufferDelete(const GrGLVertexBuffer* buffer) { 2145 if (fHWGeometryState.fVertexBuffer == buffer) { 2146 // deleting bound buffer does implied bind to 0 2147 fHWGeometryState.fVertexBuffer = NULL; 2148 fHWGeometryState.fArrayPtrsDirty = true; 2149 } 2150 } 2151 2152 void GrGpuGL::notifyIndexBufferBind(const GrGLIndexBuffer* buffer) { 2153 fHWGeometryState.fIndexBuffer = buffer; 2154 } 2155 2156 void GrGpuGL::notifyIndexBufferDelete(const GrGLIndexBuffer* buffer) { 2157 if (fHWGeometryState.fIndexBuffer == buffer) { 2158 // deleting bound buffer does implied bind to 0 2159 fHWGeometryState.fIndexBuffer = NULL; 2160 } 2161 } 2162 2163 void GrGpuGL::notifyRenderTargetDelete(GrRenderTarget* renderTarget) { 2164 GrAssert(NULL != renderTarget); 2165 GrDrawState* drawState = this->drawState(); 2166 if (drawState->getRenderTarget() == renderTarget) { 2167 drawState->setRenderTarget(NULL); 2168 } 2169 if (fHWDrawState.getRenderTarget() == renderTarget) { 2170 fHWDrawState.setRenderTarget(NULL); 2171 } 2172 } 2173 2174 void GrGpuGL::notifyTextureDelete(GrGLTexture* texture) { 2175 for (int s = 0; s < GrDrawState::kNumStages; ++s) { 2176 GrDrawState* drawState = this->drawState(); 2177 if (drawState->getTexture(s) == texture) { 2178 fCurrDrawState.setTexture(s, NULL); 2179 } 2180 if (fHWDrawState.getTexture(s) == texture) { 2181 // deleting bound texture does implied bind to 0 2182 fHWDrawState.setTexture(s, NULL); 2183 } 2184 } 2185 } 2186 2187 bool GrGpuGL::configToGLFormats(GrPixelConfig config, 2188 bool getSizedInternalFormat, 2189 GrGLenum* internalFormat, 2190 GrGLenum* externalFormat, 2191 GrGLenum* externalType) { 2192 GrGLenum dontCare; 2193 if (NULL == internalFormat) { 2194 internalFormat = &dontCare; 2195 } 2196 if (NULL == externalFormat) { 2197 externalFormat = &dontCare; 2198 } 2199 if (NULL == externalType) { 2200 externalType = &dontCare; 2201 } 2202 2203 switch (config) { 2204 case kRGBA_8888_PM_GrPixelConfig: 2205 case kRGBA_8888_UPM_GrPixelConfig: 2206 *internalFormat = GR_GL_RGBA; 2207 *externalFormat = GR_GL_RGBA; 2208 if (getSizedInternalFormat) { 2209 *internalFormat = GR_GL_RGBA8; 2210 } else { 2211 *internalFormat = GR_GL_RGBA; 2212 } 2213 *externalType = GR_GL_UNSIGNED_BYTE; 2214 break; 2215 case kBGRA_8888_PM_GrPixelConfig: 2216 case kBGRA_8888_UPM_GrPixelConfig: 2217 if (!this->glCaps().bgraFormatSupport()) { 2218 return false; 2219 } 2220 if (this->glCaps().bgraIsInternalFormat()) { 2221 if (getSizedInternalFormat) { 2222 *internalFormat = GR_GL_BGRA8; 2223 } else { 2224 *internalFormat = GR_GL_BGRA; 2225 } 2226 } else { 2227 if (getSizedInternalFormat) { 2228 *internalFormat = GR_GL_RGBA8; 2229 } else { 2230 *internalFormat = GR_GL_RGBA; 2231 } 2232 } 2233 *externalFormat = GR_GL_BGRA; 2234 *externalType = GR_GL_UNSIGNED_BYTE; 2235 break; 2236 case kRGB_565_GrPixelConfig: 2237 *internalFormat = GR_GL_RGB; 2238 *externalFormat = GR_GL_RGB; 2239 if (getSizedInternalFormat) { 2240 if (this->glBinding() == kDesktop_GrGLBinding) { 2241 return false; 2242 } else { 2243 *internalFormat = GR_GL_RGB565; 2244 } 2245 } else { 2246 *internalFormat = GR_GL_RGB; 2247 } 2248 *externalType = GR_GL_UNSIGNED_SHORT_5_6_5; 2249 break; 2250 case kRGBA_4444_GrPixelConfig: 2251 *internalFormat = GR_GL_RGBA; 2252 *externalFormat = GR_GL_RGBA; 2253 if (getSizedInternalFormat) { 2254 *internalFormat = GR_GL_RGBA4; 2255 } else { 2256 *internalFormat = GR_GL_RGBA; 2257 } 2258 *externalType = GR_GL_UNSIGNED_SHORT_4_4_4_4; 2259 break; 2260 case kIndex_8_GrPixelConfig: 2261 if (this->getCaps().f8BitPaletteSupport) { 2262 *internalFormat = GR_GL_PALETTE8_RGBA8; 2263 // glCompressedTexImage doesn't take external params 2264 *externalFormat = GR_GL_PALETTE8_RGBA8; 2265 // no sized/unsized internal format distinction here 2266 *internalFormat = GR_GL_PALETTE8_RGBA8; 2267 // unused with CompressedTexImage 2268 *externalType = GR_GL_UNSIGNED_BYTE; 2269 } else { 2270 return false; 2271 } 2272 break; 2273 case kAlpha_8_GrPixelConfig: 2274 *internalFormat = GR_GL_ALPHA; 2275 *externalFormat = GR_GL_ALPHA; 2276 if (getSizedInternalFormat) { 2277 *internalFormat = GR_GL_ALPHA8; 2278 } else { 2279 *internalFormat = GR_GL_ALPHA; 2280 } 2281 *externalType = GR_GL_UNSIGNED_BYTE; 2282 break; 2283 default: 2284 return false; 2285 } 2286 return true; 2287 } 2288 2289 void GrGpuGL::setTextureUnit(int unit) { 2290 GrAssert(unit >= 0 && unit < GrDrawState::kNumStages); 2291 if (fActiveTextureUnitIdx != unit) { 2292 GL_CALL(ActiveTexture(GR_GL_TEXTURE0 + unit)); 2293 fActiveTextureUnitIdx = unit; 2294 } 2295 } 2296 2297 void GrGpuGL::setSpareTextureUnit() { 2298 if (fActiveTextureUnitIdx != (GR_GL_TEXTURE0 + SPARE_TEX_UNIT)) { 2299 GL_CALL(ActiveTexture(GR_GL_TEXTURE0 + SPARE_TEX_UNIT)); 2300 fActiveTextureUnitIdx = SPARE_TEX_UNIT; 2301 } 2302 } 2303 2304 void GrGpuGL::resetDirtyFlags() { 2305 Gr_bzero(&fDirtyFlags, sizeof(fDirtyFlags)); 2306 } 2307 2308 void GrGpuGL::setBuffers(bool indexed, 2309 int* extraVertexOffset, 2310 int* extraIndexOffset) { 2311 2312 GrAssert(NULL != extraVertexOffset); 2313 2314 const GeometryPoolState& geoPoolState = this->getGeomPoolState(); 2315 2316 GrGLVertexBuffer* vbuf; 2317 switch (this->getGeomSrc().fVertexSrc) { 2318 case kBuffer_GeometrySrcType: 2319 *extraVertexOffset = 0; 2320 vbuf = (GrGLVertexBuffer*) this->getGeomSrc().fVertexBuffer; 2321 break; 2322 case kArray_GeometrySrcType: 2323 case kReserved_GeometrySrcType: 2324 this->finalizeReservedVertices(); 2325 *extraVertexOffset = geoPoolState.fPoolStartVertex; 2326 vbuf = (GrGLVertexBuffer*) geoPoolState.fPoolVertexBuffer; 2327 break; 2328 default: 2329 vbuf = NULL; // suppress warning 2330 GrCrash("Unknown geometry src type!"); 2331 } 2332 2333 GrAssert(NULL != vbuf); 2334 GrAssert(!vbuf->isLocked()); 2335 if (fHWGeometryState.fVertexBuffer != vbuf) { 2336 GL_CALL(BindBuffer(GR_GL_ARRAY_BUFFER, vbuf->bufferID())); 2337 fHWGeometryState.fArrayPtrsDirty = true; 2338 fHWGeometryState.fVertexBuffer = vbuf; 2339 } 2340 2341 if (indexed) { 2342 GrAssert(NULL != extraIndexOffset); 2343 2344 GrGLIndexBuffer* ibuf; 2345 switch (this->getGeomSrc().fIndexSrc) { 2346 case kBuffer_GeometrySrcType: 2347 *extraIndexOffset = 0; 2348 ibuf = (GrGLIndexBuffer*)this->getGeomSrc().fIndexBuffer; 2349 break; 2350 case kArray_GeometrySrcType: 2351 case kReserved_GeometrySrcType: 2352 this->finalizeReservedIndices(); 2353 *extraIndexOffset = geoPoolState.fPoolStartIndex; 2354 ibuf = (GrGLIndexBuffer*) geoPoolState.fPoolIndexBuffer; 2355 break; 2356 default: 2357 ibuf = NULL; // suppress warning 2358 GrCrash("Unknown geometry src type!"); 2359 } 2360 2361 GrAssert(NULL != ibuf); 2362 GrAssert(!ibuf->isLocked()); 2363 if (fHWGeometryState.fIndexBuffer != ibuf) { 2364 GL_CALL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, ibuf->bufferID())); 2365 fHWGeometryState.fIndexBuffer = ibuf; 2366 } 2367 } 2368 } 2369 2370 int GrGpuGL::getMaxEdges() const { 2371 // FIXME: This is a pessimistic estimate based on how many other things 2372 // want to add uniforms. This should be centralized somewhere. 2373 return GR_CT_MIN(this->glCaps().maxFragmentUniformVectors() - 8, 2374 GrDrawState::kMaxEdges); 2375 } 2376 2377