GrGpuGL.cpp revision 11b2d8b8d2e0230ccacf6d635f7ab0be8b53ca8d
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright 2011 Google Inc. 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Use of this source code is governed by a BSD-style license that can be 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * found in the LICENSE file. 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "GrGpuGL.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "GrGLStencilBuffer.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "GrGLPath.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "GrTemplates.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "GrTypes.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "SkTemplates.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const GrGLuint GR_MAX_GLUINT = ~0U; 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const GrGLint GR_INVAL_GLINT = ~0; 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define GL_CALL(X) GR_GL_CALL(this->glInterface(), X) 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define GL_CALL_RET(RET, X) GR_GL_CALL_RET(this->glInterface(), RET, X) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// we use a spare texture unit to avoid 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// mucking with the state of any of the stages. 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int SPARE_TEX_UNIT = GrDrawState::kNumStages; 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define SKIP_CACHE_CHECK true 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if GR_GL_CHECK_ALLOC_WITH_GET_ERROR 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) #define CLEAR_ERROR_BEFORE_ALLOC(iface) GrGLClearErr(iface) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) #define GL_ALLOC_CALL(iface, call) GR_GL_CALL_NOERRCHECK(iface, call) 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) #define CHECK_ALLOC_ERROR(iface) GR_GL_GET_ERROR(iface) 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#else 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) #define CLEAR_ERROR_BEFORE_ALLOC(iface) 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) #define GL_ALLOC_CALL(iface, call) GR_GL_CALL(iface, call) 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) #define CHECK_ALLOC_ERROR(iface) GR_GL_NO_ERROR 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/////////////////////////////////////////////////////////////////////////////// 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const GrGLenum gXfermodeCoeff2Blend[] = { 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GR_GL_ZERO, 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GR_GL_ONE, 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GR_GL_SRC_COLOR, 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GR_GL_ONE_MINUS_SRC_COLOR, 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GR_GL_DST_COLOR, 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GR_GL_ONE_MINUS_DST_COLOR, 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GR_GL_SRC_ALPHA, 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GR_GL_ONE_MINUS_SRC_ALPHA, 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GR_GL_DST_ALPHA, 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GR_GL_ONE_MINUS_DST_ALPHA, 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GR_GL_CONSTANT_COLOR, 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GR_GL_ONE_MINUS_CONSTANT_COLOR, 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GR_GL_CONSTANT_ALPHA, 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GR_GL_ONE_MINUS_CONSTANT_ALPHA, 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // extended blend coeffs 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GR_GL_SRC1_COLOR, 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GR_GL_ONE_MINUS_SRC1_COLOR, 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GR_GL_SRC1_ALPHA, 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GR_GL_ONE_MINUS_SRC1_ALPHA, 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GrGpuGL::BlendCoeffReferencesConstant(GrBlendCoeff coeff) { 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const bool gCoeffReferencesBlendConst[] = { 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) false, 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) false, 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) false, 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) false, 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) false, 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) false, 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) false, 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) false, 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) false, 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) false, 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) true, 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) true, 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) true, 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) true, 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // extended blend coeffs 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) false, 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) false, 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) false, 852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) false, 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return gCoeffReferencesBlendConst[coeff]; 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GR_STATIC_ASSERT(kTotalGrBlendCoeffCount == 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GR_ARRAY_COUNT(gCoeffReferencesBlendConst)); 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GR_STATIC_ASSERT(0 == kZero_GrBlendCoeff); 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GR_STATIC_ASSERT(1 == kOne_GrBlendCoeff); 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GR_STATIC_ASSERT(2 == kSC_GrBlendCoeff); 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GR_STATIC_ASSERT(3 == kISC_GrBlendCoeff); 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GR_STATIC_ASSERT(4 == kDC_GrBlendCoeff); 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GR_STATIC_ASSERT(5 == kIDC_GrBlendCoeff); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GR_STATIC_ASSERT(6 == kSA_GrBlendCoeff); 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GR_STATIC_ASSERT(7 == kISA_GrBlendCoeff); 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GR_STATIC_ASSERT(8 == kDA_GrBlendCoeff); 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GR_STATIC_ASSERT(9 == kIDA_GrBlendCoeff); 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GR_STATIC_ASSERT(10 == kConstC_GrBlendCoeff); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GR_STATIC_ASSERT(11 == kIConstC_GrBlendCoeff); 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GR_STATIC_ASSERT(12 == kConstA_GrBlendCoeff); 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GR_STATIC_ASSERT(13 == kIConstA_GrBlendCoeff); 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GR_STATIC_ASSERT(14 == kS2C_GrBlendCoeff); 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GR_STATIC_ASSERT(15 == kIS2C_GrBlendCoeff); 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GR_STATIC_ASSERT(16 == kS2A_GrBlendCoeff); 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GR_STATIC_ASSERT(17 == kIS2A_GrBlendCoeff); 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // assertion for gXfermodeCoeff2Blend have to be in GrGpu scope 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GR_STATIC_ASSERT(kTotalGrBlendCoeffCount == 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GR_ARRAY_COUNT(gXfermodeCoeff2Blend)); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/////////////////////////////////////////////////////////////////////////////// 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool gPrintStartupSpew = GR_DEBUG; 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static bool fbo_test(const GrGLInterface* gl, int w, int h) { 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GR_GL_CALL(gl, ActiveTexture(GR_GL_TEXTURE0 + SPARE_TEX_UNIT)); 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GrGLuint testFBO; 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GR_GL_CALL(gl, GenFramebuffers(1, &testFBO)); 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GR_GL_CALL(gl, BindFramebuffer(GR_GL_FRAMEBUFFER, testFBO)); 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GrGLuint testRTTex; 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GR_GL_CALL(gl, GenTextures(1, &testRTTex)); 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GR_GL_CALL(gl, BindTexture(GR_GL_TEXTURE_2D, testRTTex)); 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // some implementations require texture to be mip-map complete before 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // FBO with level 0 bound as color attachment will be framebuffer complete. 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GR_GL_CALL(gl, TexParameteri(GR_GL_TEXTURE_2D, 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GR_GL_TEXTURE_MIN_FILTER, 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GR_GL_NEAREST)); 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GR_GL_CALL(gl, TexImage2D(GR_GL_TEXTURE_2D, 0, GR_GL_RGBA, w, h, 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, GR_GL_RGBA, GR_GL_UNSIGNED_BYTE, NULL)); 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GR_GL_CALL(gl, BindTexture(GR_GL_TEXTURE_2D, 0)); 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GR_GL_CALL(gl, FramebufferTexture2D(GR_GL_FRAMEBUFFER, 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GR_GL_COLOR_ATTACHMENT0, 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GR_GL_TEXTURE_2D, testRTTex, 0)); 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GrGLenum status; 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GR_GL_CALL_RET(gl, status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER)); 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GR_GL_CALL(gl, DeleteFramebuffers(1, &testFBO)); 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GR_GL_CALL(gl, DeleteTextures(1, &testRTTex)); 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return status == GR_GL_FRAMEBUFFER_COMPLETE; 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)GrGpuGL::GrGpuGL(const GrGLContextInfo& ctxInfo) : fGLContextInfo(ctxInfo) { 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GrAssert(ctxInfo.isInitialized()); 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fillInConfigRenderableTable(); 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) fPrintedCaps = false; 1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GrGLClearErr(fGLContextInfo.interface()); 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (gPrintStartupSpew) { 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GrGLubyte* ext; 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GL_CALL_RET(ext, GetString(GR_GL_EXTENSIONS)); 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GrGLubyte* vendor; 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GrGLubyte* renderer; 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GrGLubyte* version; 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GL_CALL_RET(vendor, GetString(GR_GL_VENDOR)); 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GL_CALL_RET(renderer, GetString(GR_GL_RENDERER)); 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GL_CALL_RET(version, GetString(GR_GL_VERSION)); 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GrPrintf("------------------------- create GrGpuGL %p --------------\n", 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this); 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GrPrintf("------ VENDOR %s\n", vendor); 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GrPrintf("------ RENDERER %s\n", renderer); 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GrPrintf("------ VERSION %s\n", version); 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GrPrintf("------ EXTENSIONS\n %s \n", ext); 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this->initCaps(); 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fProgramData = NULL; 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fProgramCache = new ProgramCache(this->glContextInfo()); 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fLastSuccessfulStencilFmtIdx = 0; 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fCanPreserveUnpremulRoundtrip = kUnknown_CanPreserveUnpremulRoundtrip; 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (false) { // avoid bit rot, suppress warning 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fbo_test(this->glInterface(), 0, 0); 1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GrGpuGL::~GrGpuGL() { 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (fProgramData && 0 != fHWProgramID) { 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // detach the current program so there is no confusion on OpenGL's part 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // that we want it to be deleted 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GrAssert(fHWProgramID == fProgramData->fProgramID); 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GL_CALL(UseProgram(0)); 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete fProgramCache; 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fProgramCache = NULL; 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fProgramData = NULL; 1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This must be called by before the GrDrawTarget destructor 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this->releaseGeometry(); 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This subclass must do this before the base class destructor runs 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // since we will unref the GrGLInterface. 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this->releaseResources(); 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/////////////////////////////////////////////////////////////////////////////// 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GrGpuGL::initCaps() { 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GrGLint maxTextureUnits; 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // check FS and fixed-function texture unit limits 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we only use textures in the fragment stage currently. 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // checks are > to make sure we have a spare unit. 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GrGLInterface* gl = this->glInterface(); 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GR_GL_GetIntegerv(gl, GR_GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureUnits); 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GrAssert(maxTextureUnits > GrDrawState::kNumStages); 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GrGLint numFormats; 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GR_GL_GetIntegerv(gl, GR_GL_NUM_COMPRESSED_TEXTURE_FORMATS, &numFormats); 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkAutoSTMalloc<10, GrGLint> formats(numFormats); 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GR_GL_GetIntegerv(gl, GR_GL_COMPRESSED_TEXTURE_FORMATS, formats); 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < numFormats; ++i) { 2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (formats[i] == GR_GL_PALETTE8_RGBA8) { 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fCaps.f8BitPaletteSupport = true; 2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (kDesktop_GrGLBinding == this->glBinding()) { 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we could also look for GL_ATI_separate_stencil extension or 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // GL_EXT_stencil_two_side but they use different function signatures 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // than GL2.0+ (and than each other). 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fCaps.fTwoSidedStencilSupport = (this->glVersion() >= GR_GL_VER(2,0)); 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // supported on GL 1.4 and higher or by extension 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fCaps.fStencilWrapOpsSupport = (this->glVersion() >= GR_GL_VER(1,4)) || 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this->hasExtension("GL_EXT_stencil_wrap"); 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ES 2 has two sided stencil and stencil wrap 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fCaps.fTwoSidedStencilSupport = true; 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fCaps.fStencilWrapOpsSupport = true; 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (kDesktop_GrGLBinding == this->glBinding()) { 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fCaps.fBufferLockSupport = true; // we require VBO support and the desktop VBO 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // extension includes glMapBuffer. 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fCaps.fBufferLockSupport = this->hasExtension("GL_OES_mapbuffer"); 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 249 250 if (kDesktop_GrGLBinding == this->glBinding()) { 251 if (this->glVersion() >= GR_GL_VER(2,0) || 252 this->hasExtension("GL_ARB_texture_non_power_of_two")) { 253 fCaps.fNPOTTextureTileSupport = true; 254 } else { 255 fCaps.fNPOTTextureTileSupport = false; 256 } 257 } else { 258 // Unextended ES2 supports NPOT textures with clamp_to_edge and non-mip filters only 259 fCaps.fNPOTTextureTileSupport = this->hasExtension("GL_OES_texture_npot"); 260 } 261 262 fCaps.fHWAALineSupport = (kDesktop_GrGLBinding == this->glBinding()); 263 264 GR_GL_GetIntegerv(gl, GR_GL_MAX_TEXTURE_SIZE, &fCaps.fMaxTextureSize); 265 GR_GL_GetIntegerv(gl, GR_GL_MAX_RENDERBUFFER_SIZE, &fCaps.fMaxRenderTargetSize); 266 // Our render targets are always created with textures as the color 267 // attachment, hence this min: 268 fCaps.fMaxRenderTargetSize = GrMin(fCaps.fMaxTextureSize, fCaps.fMaxRenderTargetSize); 269 270 fCaps.fFSAASupport = GrGLCaps::kNone_MSFBOType != this->glCaps().msFBOType(); 271 fCaps.fPathStencilingSupport = GR_GL_USE_NV_PATH_RENDERING && 272 this->hasExtension("GL_NV_path_rendering"); 273 274 // Enable supported shader-related caps 275 if (kDesktop_GrGLBinding == this->glBinding()) { 276 fCaps.fDualSourceBlendingSupport = 277 this->glVersion() >= GR_GL_VER(3,3) || 278 this->hasExtension("GL_ARB_blend_func_extended"); 279 fCaps.fShaderDerivativeSupport = true; 280 // we don't support GL_ARB_geometry_shader4, just GL 3.2+ GS 281 fCaps.fGeometryShaderSupport = 282 this->glVersion() >= GR_GL_VER(3,2) && 283 this->glslGeneration() >= k150_GrGLSLGeneration; 284 } else { 285 fCaps.fShaderDerivativeSupport = 286 this->hasExtension("GL_OES_standard_derivatives"); 287 } 288} 289 290void GrGpuGL::fillInConfigRenderableTable() { 291 292 // OpenGL < 3.0 293 // no support for render targets unless the GL_ARB_framebuffer_object 294 // extension is supported (in which case we get ALPHA, RED, RG, RGB, 295 // RGBA (ALPHA8, RGBA4, RGBA8) for OpenGL > 1.1). Note that we 296 // probably don't get R8 in this case. 297 298 // OpenGL 3.0 299 // base color renderable: ALPHA, RED, RG, RGB, and RGBA 300 // sized derivatives: ALPHA8, R8, RGBA4, RGBA8 301 302 // >= OpenGL 3.1 303 // base color renderable: RED, RG, RGB, and RGBA 304 // sized derivatives: R8, RGBA4, RGBA8 305 // if the GL_ARB_compatibility extension is supported then we get back 306 // support for GL_ALPHA and ALPHA8 307 308 // GL_EXT_bgra adds BGRA render targets to any version 309 310 // ES 2.0 311 // color renderable: RGBA4, RGB5_A1, RGB565 312 // GL_EXT_texture_rg adds support for R8 as a color render target 313 // GL_OES_rgb8_rgba8 and/or GL_ARM_rgba8 adds support for RGBA8 314 // GL_EXT_texture_format_BGRA8888 and/or GL_APPLE_texture_format_BGRA8888 315 // added BGRA support 316 317 if (kDesktop_GrGLBinding == this->glBinding()) { 318 // Post 3.0 we will get R8 319 // Prior to 3.0 we will get ALPHA8 (with GL_ARB_framebuffer_object) 320 if (this->glVersion() >= GR_GL_VER(3,0) || 321 this->hasExtension("GL_ARB_framebuffer_object")) { 322 fConfigRenderSupport[kAlpha_8_GrPixelConfig] = true; 323 } 324 } else { 325 // On ES we can only hope for R8 326 fConfigRenderSupport[kAlpha_8_GrPixelConfig] = 327 this->glCaps().textureRedSupport(); 328 } 329 330 if (kDesktop_GrGLBinding != this->glBinding()) { 331 // only available in ES 332 fConfigRenderSupport[kRGB_565_GrPixelConfig] = true; 333 } 334 335 // Pre 3.0, Ganesh relies on either GL_ARB_framebuffer_object or 336 // GL_EXT_framebuffer_object for FBO support. Both of these 337 // allow RGBA4 render targets so this is always supported. 338 fConfigRenderSupport[kRGBA_4444_GrPixelConfig] = true; 339 340 if (this->glCaps().rgba8RenderbufferSupport()) { 341 fConfigRenderSupport[kRGBA_8888_PM_GrPixelConfig] = true; 342 } 343 344 if (this->glCaps().bgraFormatSupport()) { 345 fConfigRenderSupport[kBGRA_8888_PM_GrPixelConfig] = true; 346 } 347 348 // the un-premultiplied formats just inherit the premultiplied setting 349 fConfigRenderSupport[kRGBA_8888_UPM_GrPixelConfig] = 350 fConfigRenderSupport[kRGBA_8888_PM_GrPixelConfig]; 351 fConfigRenderSupport[kBGRA_8888_UPM_GrPixelConfig] = 352 fConfigRenderSupport[kBGRA_8888_PM_GrPixelConfig]; 353} 354 355bool GrGpuGL::canPreserveReadWriteUnpremulPixels() { 356 if (kUnknown_CanPreserveUnpremulRoundtrip == 357 fCanPreserveUnpremulRoundtrip) { 358 359 SkAutoTMalloc<uint32_t> data(256 * 256 * 3); 360 uint32_t* srcData = data.get(); 361 uint32_t* firstRead = data.get() + 256 * 256; 362 uint32_t* secondRead = data.get() + 2 * 256 * 256; 363 364 for (int y = 0; y < 256; ++y) { 365 for (int x = 0; x < 256; ++x) { 366 uint8_t* color = reinterpret_cast<uint8_t*>(&srcData[256*y + x]); 367 color[3] = y; 368 color[2] = x; 369 color[1] = x; 370 color[0] = x; 371 } 372 } 373 374 // We have broader support for read/write pixels on render targets 375 // than on textures. 376 GrTextureDesc dstDesc; 377 dstDesc.fFlags = kRenderTarget_GrTextureFlagBit | 378 kNoStencil_GrTextureFlagBit; 379 dstDesc.fWidth = 256; 380 dstDesc.fHeight = 256; 381 dstDesc.fConfig = kRGBA_8888_PM_GrPixelConfig; 382 383 SkAutoTUnref<GrTexture> dstTex(this->createTexture(dstDesc, NULL, 0)); 384 if (!dstTex.get()) { 385 return false; 386 } 387 GrRenderTarget* rt = dstTex.get()->asRenderTarget(); 388 GrAssert(NULL != rt); 389 390 bool failed = true; 391 static const UnpremulConversion gMethods[] = { 392 kUpOnWrite_DownOnRead_UnpremulConversion, 393 kDownOnWrite_UpOnRead_UnpremulConversion, 394 }; 395 396 // pretend that we can do the roundtrip to avoid recursive calls to 397 // this function 398 fCanPreserveUnpremulRoundtrip = kYes_CanPreserveUnpremulRoundtrip; 399 for (size_t i = 0; i < GR_ARRAY_COUNT(gMethods) && failed; ++i) { 400 fUnpremulConversion = gMethods[i]; 401 rt->writePixels(0, 0, 402 256, 256, 403 kRGBA_8888_UPM_GrPixelConfig, srcData, 0); 404 rt->readPixels(0, 0, 405 256, 256, 406 kRGBA_8888_UPM_GrPixelConfig, firstRead, 0); 407 rt->writePixels(0, 0, 408 256, 256, 409 kRGBA_8888_UPM_GrPixelConfig, firstRead, 0); 410 rt->readPixels(0, 0, 411 256, 256, 412 kRGBA_8888_UPM_GrPixelConfig, secondRead, 0); 413 failed = false; 414 for (int j = 0; j < 256 * 256; ++j) { 415 if (firstRead[j] != secondRead[j]) { 416 failed = true; 417 break; 418 } 419 } 420 } 421 fCanPreserveUnpremulRoundtrip = failed ? 422 kNo_CanPreserveUnpremulRoundtrip : 423 kYes_CanPreserveUnpremulRoundtrip; 424 } 425 426 if (kYes_CanPreserveUnpremulRoundtrip == fCanPreserveUnpremulRoundtrip) { 427 return true; 428 } else { 429 return false; 430 } 431} 432 433GrPixelConfig GrGpuGL::preferredReadPixelsConfig(GrPixelConfig config) const { 434 if (GR_GL_RGBA_8888_PIXEL_OPS_SLOW && GrPixelConfigIsRGBA8888(config)) { 435 return GrPixelConfigSwapRAndB(config); 436 } else { 437 return config; 438 } 439} 440 441GrPixelConfig GrGpuGL::preferredWritePixelsConfig(GrPixelConfig config) const { 442 if (GR_GL_RGBA_8888_PIXEL_OPS_SLOW && GrPixelConfigIsRGBA8888(config)) { 443 return GrPixelConfigSwapRAndB(config); 444 } else { 445 return config; 446 } 447} 448 449bool GrGpuGL::fullReadPixelsIsFasterThanPartial() const { 450 return SkToBool(GR_GL_FULL_READPIXELS_FASTER_THAN_PARTIAL); 451} 452 453void GrGpuGL::onResetContext() { 454 if (gPrintStartupSpew && !fPrintedCaps) { 455 fPrintedCaps = true; 456 this->getCaps().print(); 457 this->glCaps().print(); 458 } 459 460 // we don't use the zb at all 461 GL_CALL(Disable(GR_GL_DEPTH_TEST)); 462 GL_CALL(DepthMask(GR_GL_FALSE)); 463 464 fHWDrawFace = GrDrawState::kInvalid_DrawFace; 465 fHWDitherEnabled = kUnknown_TriState; 466 467 if (kDesktop_GrGLBinding == this->glBinding()) { 468 // Desktop-only state that we never change 469 GL_CALL(Disable(GR_GL_POINT_SMOOTH)); 470 GL_CALL(Disable(GR_GL_LINE_SMOOTH)); 471 GL_CALL(Disable(GR_GL_POLYGON_SMOOTH)); 472 GL_CALL(Disable(GR_GL_POLYGON_STIPPLE)); 473 GL_CALL(Disable(GR_GL_COLOR_LOGIC_OP)); 474 if (this->glCaps().imagingSupport()) { 475 GL_CALL(Disable(GR_GL_COLOR_TABLE)); 476 } 477 GL_CALL(Disable(GR_GL_INDEX_LOGIC_OP)); 478 GL_CALL(Disable(GR_GL_POLYGON_OFFSET_FILL)); 479 // Since ES doesn't support glPointSize at all we always use the VS to 480 // set the point size 481 GL_CALL(Enable(GR_GL_VERTEX_PROGRAM_POINT_SIZE)); 482 483 // We should set glPolygonMode(FRONT_AND_BACK,FILL) here, too. It isn't 484 // currently part of our gl interface. There are probably others as 485 // well. 486 } 487 fHWAAState.invalidate(); 488 fHWWriteToColor = kUnknown_TriState; 489 490 // we only ever use lines in hairline mode 491 GL_CALL(LineWidth(1)); 492 493 // invalid 494 fHWActiveTextureUnitIdx = -1; 495 496 fHWBlendState.invalidate(); 497 498 for (int s = 0; s < GrDrawState::kNumStages; ++s) { 499 fHWBoundTextures[s] = NULL; 500 } 501 502 fHWScissorSettings.invalidate(); 503 504 fHWViewport.invalidate(); 505 506 fHWStencilSettings.invalidate(); 507 fHWStencilTestEnabled = kUnknown_TriState; 508 509 fHWGeometryState.fIndexBuffer = NULL; 510 fHWGeometryState.fVertexBuffer = NULL; 511 512 fHWGeometryState.fArrayPtrsDirty = true; 513 514 fHWBoundRenderTarget = NULL; 515 516 fHWPathMatrixState.invalidate(); 517 if (fCaps.fPathStencilingSupport) { 518 // we don't use the model view matrix. 519 GL_CALL(MatrixMode(GR_GL_MODELVIEW)); 520 GL_CALL(LoadIdentity()); 521 } 522 523 // we assume these values 524 if (this->glCaps().unpackRowLengthSupport()) { 525 GL_CALL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH, 0)); 526 } 527 if (this->glCaps().packRowLengthSupport()) { 528 GL_CALL(PixelStorei(GR_GL_PACK_ROW_LENGTH, 0)); 529 } 530 if (this->glCaps().unpackFlipYSupport()) { 531 GL_CALL(PixelStorei(GR_GL_UNPACK_FLIP_Y, GR_GL_FALSE)); 532 } 533 if (this->glCaps().packFlipYSupport()) { 534 GL_CALL(PixelStorei(GR_GL_PACK_REVERSE_ROW_ORDER, GR_GL_FALSE)); 535 } 536 537 fHWGeometryState.fVertexOffset = ~0U; 538 539 // Third party GL code may have left vertex attributes enabled. Some GL 540 // implementations (osmesa) may read vetex attributes that are not required 541 // by the current shader. Therefore, we have to ensure that only the 542 // attributes we require for the current draw are enabled or we may cause an 543 // invalid read. 544 545 // Disable all vertex layout bits so that next flush will assume all 546 // optional vertex attributes are disabled. 547 fHWGeometryState.fVertexLayout = 0; 548 549 // We always use the this attribute and assume it is always enabled. 550 int posAttrIdx = GrGLProgram::PositionAttributeIdx(); 551 GL_CALL(EnableVertexAttribArray(posAttrIdx)); 552 // Disable all other vertex attributes. 553 for (int va = 0; va < this->glCaps().maxVertexAttributes(); ++va) { 554 if (va != posAttrIdx) { 555 GL_CALL(DisableVertexAttribArray(va)); 556 } 557 } 558 559 fHWProgramID = 0; 560 fHWConstAttribColor = GrColor_ILLEGAL; 561 fHWConstAttribCoverage = GrColor_ILLEGAL; 562} 563 564GrTexture* GrGpuGL::onCreatePlatformTexture(const GrPlatformTextureDesc& desc) { 565 GrGLTexture::Desc glTexDesc; 566 if (!configToGLFormats(desc.fConfig, false, NULL, NULL, NULL)) { 567 return NULL; 568 } 569 570 // next line relies on PlatformTextureDesc's flags matching GrTexture's 571 glTexDesc.fFlags = (GrTextureFlags) desc.fFlags; 572 glTexDesc.fWidth = desc.fWidth; 573 glTexDesc.fHeight = desc.fHeight; 574 glTexDesc.fConfig = desc.fConfig; 575 glTexDesc.fSampleCnt = desc.fSampleCnt; 576 glTexDesc.fTextureID = static_cast<GrGLuint>(desc.fTextureHandle); 577 glTexDesc.fOwnsID = false; 578 glTexDesc.fOrientation = GrGLTexture::kBottomUp_Orientation; 579 580 GrGLTexture* texture = NULL; 581 if (desc.fFlags & kRenderTarget_GrPlatformTextureFlag) { 582 GrGLRenderTarget::Desc glRTDesc; 583 glRTDesc.fRTFBOID = 0; 584 glRTDesc.fTexFBOID = 0; 585 glRTDesc.fMSColorRenderbufferID = 0; 586 glRTDesc.fOwnIDs = true; 587 glRTDesc.fConfig = desc.fConfig; 588 glRTDesc.fSampleCnt = desc.fSampleCnt; 589 if (!this->createRenderTargetObjects(glTexDesc.fWidth, 590 glTexDesc.fHeight, 591 glTexDesc.fTextureID, 592 &glRTDesc)) { 593 return NULL; 594 } 595 texture = new GrGLTexture(this, glTexDesc, glRTDesc); 596 } else { 597 texture = new GrGLTexture(this, glTexDesc); 598 } 599 if (NULL == texture) { 600 return NULL; 601 } 602 603 this->setSpareTextureUnit(); 604 return texture; 605} 606 607GrRenderTarget* GrGpuGL::onCreatePlatformRenderTarget(const GrPlatformRenderTargetDesc& desc) { 608 GrGLRenderTarget::Desc glDesc; 609 glDesc.fConfig = desc.fConfig; 610 glDesc.fRTFBOID = static_cast<GrGLuint>(desc.fRenderTargetHandle); 611 glDesc.fMSColorRenderbufferID = 0; 612 glDesc.fTexFBOID = GrGLRenderTarget::kUnresolvableFBOID; 613 glDesc.fSampleCnt = desc.fSampleCnt; 614 glDesc.fOwnIDs = false; 615 GrGLIRect viewport; 616 viewport.fLeft = 0; 617 viewport.fBottom = 0; 618 viewport.fWidth = desc.fWidth; 619 viewport.fHeight = desc.fHeight; 620 621 GrRenderTarget* tgt = new GrGLRenderTarget(this, glDesc, viewport); 622 if (desc.fStencilBits) { 623 GrGLStencilBuffer::Format format; 624 format.fInternalFormat = GrGLStencilBuffer::kUnknownInternalFormat; 625 format.fPacked = false; 626 format.fStencilBits = desc.fStencilBits; 627 format.fTotalBits = desc.fStencilBits; 628 GrGLStencilBuffer* sb = new GrGLStencilBuffer(this, 629 0, 630 desc.fWidth, 631 desc.fHeight, 632 desc.fSampleCnt, 633 format); 634 tgt->setStencilBuffer(sb); 635 sb->unref(); 636 } 637 return tgt; 638} 639 640//////////////////////////////////////////////////////////////////////////////// 641 642void GrGpuGL::onWriteTexturePixels(GrTexture* texture, 643 int left, int top, int width, int height, 644 GrPixelConfig config, const void* buffer, 645 size_t rowBytes) { 646 if (NULL == buffer) { 647 return; 648 } 649 GrGLTexture* glTex = static_cast<GrGLTexture*>(texture); 650 651 this->setSpareTextureUnit(); 652 GL_CALL(BindTexture(GR_GL_TEXTURE_2D, glTex->textureID())); 653 GrGLTexture::Desc desc; 654 desc.fFlags = glTex->desc().fFlags; 655 desc.fWidth = glTex->width(); 656 desc.fHeight = glTex->height(); 657 desc.fConfig = glTex->config(); 658 desc.fSampleCnt = glTex->desc().fSampleCnt; 659 desc.fTextureID = glTex->textureID(); 660 desc.fOrientation = glTex->orientation(); 661 662 this->uploadTexData(desc, false, 663 left, top, width, height, 664 config, buffer, rowBytes); 665} 666 667namespace { 668bool adjust_pixel_ops_params(int surfaceWidth, 669 int surfaceHeight, 670 size_t bpp, 671 int* left, int* top, int* width, int* height, 672 const void** data, 673 size_t* rowBytes) { 674 if (!*rowBytes) { 675 *rowBytes = *width * bpp; 676 } 677 678 GrIRect subRect = GrIRect::MakeXYWH(*left, *top, *width, *height); 679 GrIRect bounds = GrIRect::MakeWH(surfaceWidth, surfaceHeight); 680 681 if (!subRect.intersect(bounds)) { 682 return false; 683 } 684 *data = reinterpret_cast<const void*>(reinterpret_cast<intptr_t>(*data) + 685 (subRect.fTop - *top) * *rowBytes + (subRect.fLeft - *left) * bpp); 686 687 *left = subRect.fLeft; 688 *top = subRect.fTop; 689 *width = subRect.width(); 690 *height = subRect.height(); 691 return true; 692} 693} 694 695bool GrGpuGL::uploadTexData(const GrGLTexture::Desc& desc, 696 bool isNewTexture, 697 int left, int top, int width, int height, 698 GrPixelConfig dataConfig, 699 const void* data, 700 size_t rowBytes) { 701 GrAssert(NULL != data || isNewTexture); 702 703 size_t bpp = GrBytesPerPixel(dataConfig); 704 if (!adjust_pixel_ops_params(desc.fWidth, desc.fHeight, bpp, &left, &top, 705 &width, &height, &data, &rowBytes)) { 706 return false; 707 } 708 size_t trimRowBytes = width * bpp; 709 710 // in case we need a temporary, trimmed copy of the src pixels 711 SkAutoSMalloc<128 * 128> tempStorage; 712 713 bool useTexStorage = isNewTexture && 714 this->glCaps().texStorageSupport(); 715 if (useTexStorage) { 716 if (kDesktop_GrGLBinding == this->glBinding()) { 717 // 565 is not a sized internal format on desktop GL. So on desktop 718 // with 565 we always use an unsized internal format to let the 719 // system pick the best sized format to convert the 565 data to. 720 // Since glTexStorage only allows sized internal formats we will 721 // instead fallback to glTexImage2D. 722 useTexStorage = desc.fConfig != kRGB_565_GrPixelConfig; 723 } else { 724 // ES doesn't allow paletted textures to be used with tex storage 725 useTexStorage = desc.fConfig != kIndex_8_GrPixelConfig; 726 } 727 } 728 729 GrGLenum internalFormat; 730 GrGLenum externalFormat; 731 GrGLenum externalType; 732 // glTexStorage requires sized internal formats on both desktop and ES. ES 733 // glTexImage requires an unsized format. 734 if (!this->configToGLFormats(dataConfig, useTexStorage, &internalFormat, 735 &externalFormat, &externalType)) { 736 return false; 737 } 738 739 if (!isNewTexture && GR_GL_PALETTE8_RGBA8 == internalFormat) { 740 // paletted textures cannot be updated 741 return false; 742 } 743 744 /* 745 * check whether to allocate a temporary buffer for flipping y or 746 * because our srcData has extra bytes past each row. If so, we need 747 * to trim those off here, since GL ES may not let us specify 748 * GL_UNPACK_ROW_LENGTH. 749 */ 750 bool restoreGLRowLength = false; 751 bool swFlipY = false; 752 bool glFlipY = false; 753 if (NULL != data) { 754 if (GrGLTexture::kBottomUp_Orientation == desc.fOrientation) { 755 if (this->glCaps().unpackFlipYSupport()) { 756 glFlipY = true; 757 } else { 758 swFlipY = true; 759 } 760 } 761 if (this->glCaps().unpackRowLengthSupport() && !swFlipY) { 762 // can't use this for flipping, only non-neg values allowed. :( 763 if (rowBytes != trimRowBytes) { 764 GrGLint rowLength = static_cast<GrGLint>(rowBytes / bpp); 765 GL_CALL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH, rowLength)); 766 restoreGLRowLength = true; 767 } 768 } else { 769 if (trimRowBytes != rowBytes || swFlipY) { 770 // copy data into our new storage, skipping the trailing bytes 771 size_t trimSize = height * trimRowBytes; 772 const char* src = (const char*)data; 773 if (swFlipY) { 774 src += (height - 1) * rowBytes; 775 } 776 char* dst = (char*)tempStorage.reset(trimSize); 777 for (int y = 0; y < height; y++) { 778 memcpy(dst, src, trimRowBytes); 779 if (swFlipY) { 780 src -= rowBytes; 781 } else { 782 src += rowBytes; 783 } 784 dst += trimRowBytes; 785 } 786 // now point data to our copied version 787 data = tempStorage.get(); 788 } 789 } 790 if (glFlipY) { 791 GL_CALL(PixelStorei(GR_GL_UNPACK_FLIP_Y, GR_GL_TRUE)); 792 } 793 GL_CALL(PixelStorei(GR_GL_UNPACK_ALIGNMENT, static_cast<GrGLint>(bpp))); 794 } 795 bool succeeded = true; 796 if (isNewTexture && 797 0 == left && 0 == top && 798 desc.fWidth == width && desc.fHeight == height) { 799 CLEAR_ERROR_BEFORE_ALLOC(this->glInterface()); 800 if (useTexStorage) { 801 // We never resize or change formats of textures. We don't use 802 // mipmaps currently. 803 GL_ALLOC_CALL(this->glInterface(), 804 TexStorage2D(GR_GL_TEXTURE_2D, 805 1, // levels 806 internalFormat, 807 desc.fWidth, desc.fHeight)); 808 } else { 809 if (GR_GL_PALETTE8_RGBA8 == internalFormat) { 810 GrGLsizei imageSize = desc.fWidth * desc.fHeight + 811 kGrColorTableSize; 812 GL_ALLOC_CALL(this->glInterface(), 813 CompressedTexImage2D(GR_GL_TEXTURE_2D, 814 0, // level 815 internalFormat, 816 desc.fWidth, desc.fHeight, 817 0, // border 818 imageSize, 819 data)); 820 } else { 821 GL_ALLOC_CALL(this->glInterface(), 822 TexImage2D(GR_GL_TEXTURE_2D, 823 0, // level 824 internalFormat, 825 desc.fWidth, desc.fHeight, 826 0, // border 827 externalFormat, externalType, 828 data)); 829 } 830 } 831 GrGLenum error = CHECK_ALLOC_ERROR(this->glInterface()); 832 if (error != GR_GL_NO_ERROR) { 833 succeeded = false; 834 } else { 835 // if we have data and we used TexStorage to create the texture, we 836 // now upload with TexSubImage. 837 if (NULL != data && useTexStorage) { 838 GL_CALL(TexSubImage2D(GR_GL_TEXTURE_2D, 839 0, // level 840 left, top, 841 width, height, 842 externalFormat, externalType, 843 data)); 844 } 845 } 846 } else { 847 if (swFlipY || glFlipY) { 848 top = desc.fHeight - (top + height); 849 } 850 GL_CALL(TexSubImage2D(GR_GL_TEXTURE_2D, 851 0, // level 852 left, top, 853 width, height, 854 externalFormat, externalType, data)); 855 } 856 857 if (restoreGLRowLength) { 858 GrAssert(this->glCaps().unpackRowLengthSupport()); 859 GL_CALL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH, 0)); 860 } 861 if (glFlipY) { 862 GL_CALL(PixelStorei(GR_GL_UNPACK_FLIP_Y, GR_GL_FALSE)); 863 } 864 return succeeded; 865} 866 867namespace { 868bool renderbuffer_storage_msaa(GrGLContextInfo& ctxInfo, 869 int sampleCount, 870 GrGLenum format, 871 int width, int height) { 872 CLEAR_ERROR_BEFORE_ALLOC(ctxInfo.interface()); 873 GrAssert(GrGLCaps::kNone_MSFBOType != ctxInfo.caps().msFBOType()); 874 bool created = false; 875 if (GrGLCaps::kNVDesktop_CoverageAAType == 876 ctxInfo.caps().coverageAAType()) { 877 const GrGLCaps::MSAACoverageMode& mode = 878 ctxInfo.caps().getMSAACoverageMode(sampleCount); 879 GL_ALLOC_CALL(ctxInfo.interface(), 880 RenderbufferStorageMultisampleCoverage(GR_GL_RENDERBUFFER, 881 mode.fCoverageSampleCnt, 882 mode.fColorSampleCnt, 883 format, 884 width, height)); 885 created = (GR_GL_NO_ERROR == CHECK_ALLOC_ERROR(ctxInfo.interface())); 886 } 887 if (!created) { 888 // glRBMS will fail if requested samples is > max samples. 889 sampleCount = GrMin(sampleCount, ctxInfo.caps().maxSampleCount()); 890 GL_ALLOC_CALL(ctxInfo.interface(), 891 RenderbufferStorageMultisample(GR_GL_RENDERBUFFER, 892 sampleCount, 893 format, 894 width, height)); 895 created = (GR_GL_NO_ERROR == CHECK_ALLOC_ERROR(ctxInfo.interface())); 896 } 897 return created; 898} 899} 900 901bool GrGpuGL::createRenderTargetObjects(int width, int height, 902 GrGLuint texID, 903 GrGLRenderTarget::Desc* desc) { 904 desc->fMSColorRenderbufferID = 0; 905 desc->fRTFBOID = 0; 906 desc->fTexFBOID = 0; 907 desc->fOwnIDs = true; 908 909 GrGLenum status; 910 911 GrGLenum msColorFormat = 0; // suppress warning 912 913 GL_CALL(GenFramebuffers(1, &desc->fTexFBOID)); 914 if (!desc->fTexFBOID) { 915 goto FAILED; 916 } 917 918 919 // If we are using multisampling we will create two FBOS. We render 920 // to one and then resolve to the texture bound to the other. 921 if (desc->fSampleCnt > 0) { 922 if (GrGLCaps::kNone_MSFBOType == this->glCaps().msFBOType()) { 923 goto FAILED; 924 } 925 GL_CALL(GenFramebuffers(1, &desc->fRTFBOID)); 926 GL_CALL(GenRenderbuffers(1, &desc->fMSColorRenderbufferID)); 927 if (!desc->fRTFBOID || 928 !desc->fMSColorRenderbufferID || 929 !this->configToGLFormats(desc->fConfig, 930 // GLES requires sized internal formats 931 kES2_GrGLBinding == this->glBinding(), 932 &msColorFormat, NULL, NULL)) { 933 goto FAILED; 934 } 935 } else { 936 desc->fRTFBOID = desc->fTexFBOID; 937 } 938 939 // below here we may bind the FBO 940 fHWBoundRenderTarget = NULL; 941 if (desc->fRTFBOID != desc->fTexFBOID) { 942 GrAssert(desc->fSampleCnt > 1); 943 GL_CALL(BindRenderbuffer(GR_GL_RENDERBUFFER, 944 desc->fMSColorRenderbufferID)); 945 if (!renderbuffer_storage_msaa(fGLContextInfo, 946 desc->fSampleCnt, 947 msColorFormat, 948 width, height)) { 949 goto FAILED; 950 } 951 GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, desc->fRTFBOID)); 952 GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER, 953 GR_GL_COLOR_ATTACHMENT0, 954 GR_GL_RENDERBUFFER, 955 desc->fMSColorRenderbufferID)); 956 if (!this->glCaps().isConfigVerifiedColorAttachment(desc->fConfig)) { 957 GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER)); 958 if (status != GR_GL_FRAMEBUFFER_COMPLETE) { 959 goto FAILED; 960 } 961 fGLContextInfo.caps().markConfigAsValidColorAttachment( 962 desc->fConfig); 963 } 964 } 965 GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, desc->fTexFBOID)); 966 967 GL_CALL(FramebufferTexture2D(GR_GL_FRAMEBUFFER, 968 GR_GL_COLOR_ATTACHMENT0, 969 GR_GL_TEXTURE_2D, 970 texID, 0)); 971 if (!this->glCaps().isConfigVerifiedColorAttachment(desc->fConfig)) { 972 GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER)); 973 if (status != GR_GL_FRAMEBUFFER_COMPLETE) { 974 goto FAILED; 975 } 976 fGLContextInfo.caps().markConfigAsValidColorAttachment(desc->fConfig); 977 } 978 979 return true; 980 981FAILED: 982 if (desc->fMSColorRenderbufferID) { 983 GL_CALL(DeleteRenderbuffers(1, &desc->fMSColorRenderbufferID)); 984 } 985 if (desc->fRTFBOID != desc->fTexFBOID) { 986 GL_CALL(DeleteFramebuffers(1, &desc->fRTFBOID)); 987 } 988 if (desc->fTexFBOID) { 989 GL_CALL(DeleteFramebuffers(1, &desc->fTexFBOID)); 990 } 991 return false; 992} 993 994// good to set a break-point here to know when createTexture fails 995static GrTexture* return_null_texture() { 996// GrAssert(!"null texture"); 997 return NULL; 998} 999 1000#if 0 && GR_DEBUG 1001static size_t as_size_t(int x) { 1002 return x; 1003} 1004#endif 1005 1006GrTexture* GrGpuGL::onCreateTexture(const GrTextureDesc& desc, 1007 const void* srcData, 1008 size_t rowBytes) { 1009 1010 GrGLTexture::Desc glTexDesc; 1011 GrGLRenderTarget::Desc glRTDesc; 1012 1013 // Attempt to catch un- or wrongly initialized sample counts; 1014 GrAssert(desc.fSampleCnt >= 0 && desc.fSampleCnt <= 64); 1015 1016 glTexDesc.fFlags = desc.fFlags; 1017 glTexDesc.fWidth = desc.fWidth; 1018 glTexDesc.fHeight = desc.fHeight; 1019 glTexDesc.fConfig = desc.fConfig; 1020 glTexDesc.fSampleCnt = desc.fSampleCnt; 1021 glTexDesc.fClientCacheID = desc.fClientCacheID; 1022 1023 glTexDesc.fOwnsID = true; 1024 1025 glRTDesc.fMSColorRenderbufferID = 0; 1026 glRTDesc.fRTFBOID = 0; 1027 glRTDesc.fTexFBOID = 0; 1028 glRTDesc.fOwnIDs = true; 1029 glRTDesc.fConfig = glTexDesc.fConfig; 1030 1031 bool renderTarget = 0 != (desc.fFlags & kRenderTarget_GrTextureFlagBit); 1032 1033 const Caps& caps = this->getCaps(); 1034 1035 // We keep GrRenderTargets in GL's normal orientation so that they 1036 // can be drawn to by the outside world without the client having 1037 // to render upside down. 1038 glTexDesc.fOrientation = renderTarget ? GrGLTexture::kBottomUp_Orientation : 1039 GrGLTexture::kTopDown_Orientation; 1040 1041 glRTDesc.fSampleCnt = desc.fSampleCnt; 1042 if (GrGLCaps::kNone_MSFBOType == this->glCaps().msFBOType() && 1043 desc.fSampleCnt) { 1044 //GrPrintf("MSAA RT requested but not supported on this platform."); 1045 return return_null_texture(); 1046 } 1047 1048 if (renderTarget) { 1049 if (glTexDesc.fWidth > caps.fMaxRenderTargetSize || 1050 glTexDesc.fHeight > caps.fMaxRenderTargetSize) { 1051 return return_null_texture(); 1052 } 1053 } 1054 1055 GL_CALL(GenTextures(1, &glTexDesc.fTextureID)); 1056 if (renderTarget && this->glCaps().textureUsageSupport()) { 1057 // provides a hint about how this texture will be used 1058 GL_CALL(TexParameteri(GR_GL_TEXTURE_2D, 1059 GR_GL_TEXTURE_USAGE, 1060 GR_GL_FRAMEBUFFER_ATTACHMENT)); 1061 } 1062 if (!glTexDesc.fTextureID) { 1063 return return_null_texture(); 1064 } 1065 1066 this->setSpareTextureUnit(); 1067 GL_CALL(BindTexture(GR_GL_TEXTURE_2D, glTexDesc.fTextureID)); 1068 1069 // Some drivers like to know filter/wrap before seeing glTexImage2D. Some 1070 // drivers have a bug where an FBO won't be complete if it includes a 1071 // texture that is not mipmap complete (considering the filter in use). 1072 GrGLTexture::TexParams initialTexParams; 1073 // we only set a subset here so invalidate first 1074 initialTexParams.invalidate(); 1075 initialTexParams.fFilter = GR_GL_NEAREST; 1076 initialTexParams.fWrapS = GR_GL_CLAMP_TO_EDGE; 1077 initialTexParams.fWrapT = GR_GL_CLAMP_TO_EDGE; 1078 GL_CALL(TexParameteri(GR_GL_TEXTURE_2D, 1079 GR_GL_TEXTURE_MAG_FILTER, 1080 initialTexParams.fFilter)); 1081 GL_CALL(TexParameteri(GR_GL_TEXTURE_2D, 1082 GR_GL_TEXTURE_MIN_FILTER, 1083 initialTexParams.fFilter)); 1084 GL_CALL(TexParameteri(GR_GL_TEXTURE_2D, 1085 GR_GL_TEXTURE_WRAP_S, 1086 initialTexParams.fWrapS)); 1087 GL_CALL(TexParameteri(GR_GL_TEXTURE_2D, 1088 GR_GL_TEXTURE_WRAP_T, 1089 initialTexParams.fWrapT)); 1090 if (!this->uploadTexData(glTexDesc, true, 0, 0, 1091 glTexDesc.fWidth, glTexDesc.fHeight, 1092 desc.fConfig, srcData, rowBytes)) { 1093 GL_CALL(DeleteTextures(1, &glTexDesc.fTextureID)); 1094 return return_null_texture(); 1095 } 1096 1097 GrGLTexture* tex; 1098 if (renderTarget) { 1099 // unbind the texture from the texture unit before binding it to the frame buffer 1100 GL_CALL(BindTexture(GR_GL_TEXTURE_2D, 0)); 1101 1102 if (!this->createRenderTargetObjects(glTexDesc.fWidth, 1103 glTexDesc.fHeight, 1104 glTexDesc.fTextureID, 1105 &glRTDesc)) { 1106 GL_CALL(DeleteTextures(1, &glTexDesc.fTextureID)); 1107 return return_null_texture(); 1108 } 1109 tex = new GrGLTexture(this, glTexDesc, glRTDesc); 1110 } else { 1111 tex = new GrGLTexture(this, glTexDesc); 1112 } 1113 tex->setCachedTexParams(initialTexParams, this->getResetTimestamp()); 1114#ifdef TRACE_TEXTURE_CREATION 1115 GrPrintf("--- new texture [%d] size=(%d %d) config=%d\n", 1116 glTexDesc.fTextureID, desc.fWidth, desc.fHeight, desc.fConfig); 1117#endif 1118 return tex; 1119} 1120 1121namespace { 1122 1123const GrGLuint kUnknownBitCount = GrGLStencilBuffer::kUnknownBitCount; 1124 1125void inline get_stencil_rb_sizes(const GrGLInterface* gl, 1126 GrGLuint rb, 1127 GrGLStencilBuffer::Format* format) { 1128 // we shouldn't ever know one size and not the other 1129 GrAssert((kUnknownBitCount == format->fStencilBits) == 1130 (kUnknownBitCount == format->fTotalBits)); 1131 if (kUnknownBitCount == format->fStencilBits) { 1132 GR_GL_GetRenderbufferParameteriv(gl, GR_GL_RENDERBUFFER, 1133 GR_GL_RENDERBUFFER_STENCIL_SIZE, 1134 (GrGLint*)&format->fStencilBits); 1135 if (format->fPacked) { 1136 GR_GL_GetRenderbufferParameteriv(gl, GR_GL_RENDERBUFFER, 1137 GR_GL_RENDERBUFFER_DEPTH_SIZE, 1138 (GrGLint*)&format->fTotalBits); 1139 format->fTotalBits += format->fStencilBits; 1140 } else { 1141 format->fTotalBits = format->fStencilBits; 1142 } 1143 } 1144} 1145} 1146 1147bool GrGpuGL::createStencilBufferForRenderTarget(GrRenderTarget* rt, 1148 int width, int height) { 1149 1150 // All internally created RTs are also textures. We don't create 1151 // SBs for a client's standalone RT (that is RT that isnt also a texture). 1152 GrAssert(rt->asTexture()); 1153 GrAssert(width >= rt->width()); 1154 GrAssert(height >= rt->height()); 1155 1156 int samples = rt->numSamples(); 1157 GrGLuint sbID; 1158 GL_CALL(GenRenderbuffers(1, &sbID)); 1159 if (!sbID) { 1160 return false; 1161 } 1162 1163 GrGLStencilBuffer* sb = NULL; 1164 1165 int stencilFmtCnt = this->glCaps().stencilFormats().count(); 1166 for (int i = 0; i < stencilFmtCnt; ++i) { 1167 GL_CALL(BindRenderbuffer(GR_GL_RENDERBUFFER, sbID)); 1168 // we start with the last stencil format that succeeded in hopes 1169 // that we won't go through this loop more than once after the 1170 // first (painful) stencil creation. 1171 int sIdx = (i + fLastSuccessfulStencilFmtIdx) % stencilFmtCnt; 1172 const GrGLCaps::StencilFormat& sFmt = 1173 this->glCaps().stencilFormats()[sIdx]; 1174 CLEAR_ERROR_BEFORE_ALLOC(this->glInterface()); 1175 // we do this "if" so that we don't call the multisample 1176 // version on a GL that doesn't have an MSAA extension. 1177 bool created; 1178 if (samples > 0) { 1179 created = renderbuffer_storage_msaa(fGLContextInfo, 1180 samples, 1181 sFmt.fInternalFormat, 1182 width, height); 1183 } else { 1184 GL_ALLOC_CALL(this->glInterface(), 1185 RenderbufferStorage(GR_GL_RENDERBUFFER, 1186 sFmt.fInternalFormat, 1187 width, height)); 1188 created = 1189 (GR_GL_NO_ERROR == CHECK_ALLOC_ERROR(this->glInterface())); 1190 } 1191 if (created) { 1192 // After sized formats we attempt an unsized format and take 1193 // whatever sizes GL gives us. In that case we query for the size. 1194 GrGLStencilBuffer::Format format = sFmt; 1195 get_stencil_rb_sizes(this->glInterface(), sbID, &format); 1196 sb = new GrGLStencilBuffer(this, sbID, width, height, 1197 samples, format); 1198 if (this->attachStencilBufferToRenderTarget(sb, rt)) { 1199 fLastSuccessfulStencilFmtIdx = sIdx; 1200 rt->setStencilBuffer(sb); 1201 sb->unref(); 1202 return true; 1203 } 1204 sb->abandon(); // otherwise we lose sbID 1205 sb->unref(); 1206 } 1207 } 1208 GL_CALL(DeleteRenderbuffers(1, &sbID)); 1209 return false; 1210} 1211 1212bool GrGpuGL::attachStencilBufferToRenderTarget(GrStencilBuffer* sb, 1213 GrRenderTarget* rt) { 1214 GrGLRenderTarget* glrt = (GrGLRenderTarget*) rt; 1215 1216 GrGLuint fbo = glrt->renderFBOID(); 1217 1218 if (NULL == sb) { 1219 if (NULL != rt->getStencilBuffer()) { 1220 GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER, 1221 GR_GL_STENCIL_ATTACHMENT, 1222 GR_GL_RENDERBUFFER, 0)); 1223 GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER, 1224 GR_GL_DEPTH_ATTACHMENT, 1225 GR_GL_RENDERBUFFER, 0)); 1226#if GR_DEBUG 1227 GrGLenum status; 1228 GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER)); 1229 GrAssert(GR_GL_FRAMEBUFFER_COMPLETE == status); 1230#endif 1231 } 1232 return true; 1233 } else { 1234 GrGLStencilBuffer* glsb = (GrGLStencilBuffer*) sb; 1235 GrGLuint rb = glsb->renderbufferID(); 1236 1237 fHWBoundRenderTarget = NULL; 1238 GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, fbo)); 1239 GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER, 1240 GR_GL_STENCIL_ATTACHMENT, 1241 GR_GL_RENDERBUFFER, rb)); 1242 if (glsb->format().fPacked) { 1243 GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER, 1244 GR_GL_DEPTH_ATTACHMENT, 1245 GR_GL_RENDERBUFFER, rb)); 1246 } else { 1247 GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER, 1248 GR_GL_DEPTH_ATTACHMENT, 1249 GR_GL_RENDERBUFFER, 0)); 1250 } 1251 1252 GrGLenum status; 1253 if (!this->glCaps().isColorConfigAndStencilFormatVerified(rt->config(), 1254 glsb->format())) { 1255 GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER)); 1256 if (status != GR_GL_FRAMEBUFFER_COMPLETE) { 1257 GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER, 1258 GR_GL_STENCIL_ATTACHMENT, 1259 GR_GL_RENDERBUFFER, 0)); 1260 if (glsb->format().fPacked) { 1261 GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER, 1262 GR_GL_DEPTH_ATTACHMENT, 1263 GR_GL_RENDERBUFFER, 0)); 1264 } 1265 return false; 1266 } else { 1267 fGLContextInfo.caps().markColorConfigAndStencilFormatAsVerified( 1268 rt->config(), 1269 glsb->format()); 1270 } 1271 } 1272 return true; 1273 } 1274} 1275 1276//////////////////////////////////////////////////////////////////////////////// 1277 1278GrVertexBuffer* GrGpuGL::onCreateVertexBuffer(uint32_t size, bool dynamic) { 1279 GrGLuint id; 1280 GL_CALL(GenBuffers(1, &id)); 1281 if (id) { 1282 GL_CALL(BindBuffer(GR_GL_ARRAY_BUFFER, id)); 1283 fHWGeometryState.fArrayPtrsDirty = true; 1284 CLEAR_ERROR_BEFORE_ALLOC(this->glInterface()); 1285 // make sure driver can allocate memory for this buffer 1286 GL_ALLOC_CALL(this->glInterface(), 1287 BufferData(GR_GL_ARRAY_BUFFER, 1288 size, 1289 NULL, // data ptr 1290 dynamic ? GR_GL_DYNAMIC_DRAW : 1291 GR_GL_STATIC_DRAW)); 1292 if (CHECK_ALLOC_ERROR(this->glInterface()) != GR_GL_NO_ERROR) { 1293 GL_CALL(DeleteBuffers(1, &id)); 1294 // deleting bound buffer does implicit bind to 0 1295 fHWGeometryState.fVertexBuffer = NULL; 1296 return NULL; 1297 } 1298 GrGLVertexBuffer* vertexBuffer = new GrGLVertexBuffer(this, id, 1299 size, dynamic); 1300 fHWGeometryState.fVertexBuffer = vertexBuffer; 1301 return vertexBuffer; 1302 } 1303 return NULL; 1304} 1305 1306GrIndexBuffer* GrGpuGL::onCreateIndexBuffer(uint32_t size, bool dynamic) { 1307 GrGLuint id; 1308 GL_CALL(GenBuffers(1, &id)); 1309 if (id) { 1310 GL_CALL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, id)); 1311 CLEAR_ERROR_BEFORE_ALLOC(this->glInterface()); 1312 // make sure driver can allocate memory for this buffer 1313 GL_ALLOC_CALL(this->glInterface(), 1314 BufferData(GR_GL_ELEMENT_ARRAY_BUFFER, 1315 size, 1316 NULL, // data ptr 1317 dynamic ? GR_GL_DYNAMIC_DRAW : 1318 GR_GL_STATIC_DRAW)); 1319 if (CHECK_ALLOC_ERROR(this->glInterface()) != GR_GL_NO_ERROR) { 1320 GL_CALL(DeleteBuffers(1, &id)); 1321 // deleting bound buffer does implicit bind to 0 1322 fHWGeometryState.fIndexBuffer = NULL; 1323 return NULL; 1324 } 1325 GrIndexBuffer* indexBuffer = new GrGLIndexBuffer(this, id, 1326 size, dynamic); 1327 fHWGeometryState.fIndexBuffer = indexBuffer; 1328 return indexBuffer; 1329 } 1330 return NULL; 1331} 1332 1333GrPath* GrGpuGL::onCreatePath(const SkPath& inPath) { 1334 GrAssert(fCaps.fPathStencilingSupport); 1335 return new GrGLPath(this, inPath); 1336} 1337 1338void GrGpuGL::flushScissor() { 1339 const GrDrawState& drawState = this->getDrawState(); 1340 const GrGLRenderTarget* rt = 1341 static_cast<const GrGLRenderTarget*>(drawState.getRenderTarget()); 1342 1343 GrAssert(NULL != rt); 1344 const GrGLIRect& vp = rt->getViewport(); 1345 1346 if (fScissorState.fEnabled) { 1347 GrGLIRect scissor; 1348 scissor.setRelativeTo(vp, 1349 fScissorState.fRect.fLeft, 1350 fScissorState.fRect.fTop, 1351 fScissorState.fRect.width(), 1352 fScissorState.fRect.height()); 1353 // if the scissor fully contains the viewport then we fall through and 1354 // disable the scissor test. 1355 if (!scissor.contains(vp)) { 1356 if (fHWScissorSettings.fRect != scissor) { 1357 scissor.pushToGLScissor(this->glInterface()); 1358 fHWScissorSettings.fRect = scissor; 1359 } 1360 if (kYes_TriState != fHWScissorSettings.fEnabled) { 1361 GL_CALL(Enable(GR_GL_SCISSOR_TEST)); 1362 fHWScissorSettings.fEnabled = kYes_TriState; 1363 } 1364 return; 1365 } 1366 } 1367 if (kNo_TriState != fHWScissorSettings.fEnabled) { 1368 GL_CALL(Disable(GR_GL_SCISSOR_TEST)); 1369 fHWScissorSettings.fEnabled = kNo_TriState; 1370 return; 1371 } 1372} 1373 1374void GrGpuGL::onClear(const GrIRect* rect, GrColor color) { 1375 const GrDrawState& drawState = this->getDrawState(); 1376 const GrRenderTarget* rt = drawState.getRenderTarget(); 1377 // parent class should never let us get here with no RT 1378 GrAssert(NULL != rt); 1379 1380 GrIRect clippedRect; 1381 if (NULL != rect) { 1382 // flushScissor expects rect to be clipped to the target. 1383 clippedRect = *rect; 1384 GrIRect rtRect = SkIRect::MakeWH(rt->width(), rt->height()); 1385 if (clippedRect.intersect(rtRect)) { 1386 rect = &clippedRect; 1387 } else { 1388 return; 1389 } 1390 } 1391 this->flushRenderTarget(rect); 1392 GrAutoTRestore<ScissorState> asr(&fScissorState); 1393 fScissorState.fEnabled = (NULL != rect); 1394 if (fScissorState.fEnabled) { 1395 fScissorState.fRect = *rect; 1396 } 1397 this->flushScissor(); 1398 1399 GrGLfloat r, g, b, a; 1400 static const GrGLfloat scale255 = 1.f / 255.f; 1401 a = GrColorUnpackA(color) * scale255; 1402 GrGLfloat scaleRGB = scale255; 1403 if (GrPixelConfigIsUnpremultiplied(rt->config())) { 1404 scaleRGB *= a; 1405 } 1406 r = GrColorUnpackR(color) * scaleRGB; 1407 g = GrColorUnpackG(color) * scaleRGB; 1408 b = GrColorUnpackB(color) * scaleRGB; 1409 1410 GL_CALL(ColorMask(GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE)); 1411 fHWWriteToColor = kYes_TriState; 1412 GL_CALL(ClearColor(r, g, b, a)); 1413 GL_CALL(Clear(GR_GL_COLOR_BUFFER_BIT)); 1414} 1415 1416void GrGpuGL::clearStencil() { 1417 if (NULL == this->getDrawState().getRenderTarget()) { 1418 return; 1419 } 1420 1421 this->flushRenderTarget(&GrIRect::EmptyIRect()); 1422 1423 GrAutoTRestore<ScissorState> asr(&fScissorState); 1424 fScissorState.fEnabled = false; 1425 this->flushScissor(); 1426 1427 GL_CALL(StencilMask(0xffffffff)); 1428 GL_CALL(ClearStencil(0)); 1429 GL_CALL(Clear(GR_GL_STENCIL_BUFFER_BIT)); 1430 fHWStencilSettings.invalidate(); 1431} 1432 1433void GrGpuGL::clearStencilClip(const GrIRect& rect, bool insideClip) { 1434 const GrDrawState& drawState = this->getDrawState(); 1435 const GrRenderTarget* rt = drawState.getRenderTarget(); 1436 GrAssert(NULL != rt); 1437 1438 // this should only be called internally when we know we have a 1439 // stencil buffer. 1440 GrAssert(NULL != rt->getStencilBuffer()); 1441 GrGLint stencilBitCount = rt->getStencilBuffer()->bits(); 1442#if 0 1443 GrAssert(stencilBitCount > 0); 1444 GrGLint clipStencilMask = (1 << (stencilBitCount - 1)); 1445#else 1446 // we could just clear the clip bit but when we go through 1447 // ANGLE a partial stencil mask will cause clears to be 1448 // turned into draws. Our contract on GrDrawTarget says that 1449 // changing the clip between stencil passes may or may not 1450 // zero the client's clip bits. So we just clear the whole thing. 1451 static const GrGLint clipStencilMask = ~0; 1452#endif 1453 GrGLint value; 1454 if (insideClip) { 1455 value = (1 << (stencilBitCount - 1)); 1456 } else { 1457 value = 0; 1458 } 1459 this->flushRenderTarget(&GrIRect::EmptyIRect()); 1460 1461 GrAutoTRestore<ScissorState> asr(&fScissorState); 1462 fScissorState.fEnabled = true; 1463 fScissorState.fRect = rect; 1464 this->flushScissor(); 1465 1466 GL_CALL(StencilMask((uint32_t) clipStencilMask)); 1467 GL_CALL(ClearStencil(value)); 1468 GL_CALL(Clear(GR_GL_STENCIL_BUFFER_BIT)); 1469 fHWStencilSettings.invalidate(); 1470} 1471 1472void GrGpuGL::onForceRenderTargetFlush() { 1473 this->flushRenderTarget(&GrIRect::EmptyIRect()); 1474} 1475 1476bool GrGpuGL::readPixelsWillPayForYFlip(GrRenderTarget* renderTarget, 1477 int left, int top, 1478 int width, int height, 1479 GrPixelConfig config, 1480 size_t rowBytes) const { 1481 // if GL can do the flip then we'll never pay for it. 1482 if (this->glCaps().packFlipYSupport()) { 1483 return false; 1484 } 1485 1486 // If we have to do memcpy to handle non-trim rowBytes then we 1487 // get the flip for free. Otherwise it costs. 1488 if (this->glCaps().packRowLengthSupport()) { 1489 return true; 1490 } 1491 // If we have to do memcpys to handle rowBytes then y-flip is free 1492 // Note the rowBytes might be tight to the passed in data, but if data 1493 // gets clipped in x to the target the rowBytes will no longer be tight. 1494 if (left >= 0 && (left + width) < renderTarget->width()) { 1495 return 0 == rowBytes || 1496 GrBytesPerPixel(config) * width == rowBytes; 1497 } else { 1498 return false; 1499 } 1500} 1501 1502bool GrGpuGL::onReadPixels(GrRenderTarget* target, 1503 int left, int top, 1504 int width, int height, 1505 GrPixelConfig config, 1506 void* buffer, 1507 size_t rowBytes, 1508 bool invertY) { 1509 GrGLenum format; 1510 GrGLenum type; 1511 if (!this->configToGLFormats(config, false, NULL, &format, &type)) { 1512 return false; 1513 } 1514 size_t bpp = GrBytesPerPixel(config); 1515 if (!adjust_pixel_ops_params(target->width(), target->height(), bpp, 1516 &left, &top, &width, &height, 1517 const_cast<const void**>(&buffer), 1518 &rowBytes)) { 1519 return false; 1520 } 1521 1522 // resolve the render target if necessary 1523 GrGLRenderTarget* tgt = static_cast<GrGLRenderTarget*>(target); 1524 GrDrawState::AutoRenderTargetRestore artr; 1525 switch (tgt->getResolveType()) { 1526 case GrGLRenderTarget::kCantResolve_ResolveType: 1527 return false; 1528 case GrGLRenderTarget::kAutoResolves_ResolveType: 1529 artr.set(this->drawState(), target); 1530 this->flushRenderTarget(&GrIRect::EmptyIRect()); 1531 break; 1532 case GrGLRenderTarget::kCanResolve_ResolveType: 1533 this->onResolveRenderTarget(tgt); 1534 // we don't track the state of the READ FBO ID. 1535 GL_CALL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER, 1536 tgt->textureFBOID())); 1537 break; 1538 default: 1539 GrCrash("Unknown resolve type"); 1540 } 1541 1542 const GrGLIRect& glvp = tgt->getViewport(); 1543 1544 // the read rect is viewport-relative 1545 GrGLIRect readRect; 1546 readRect.setRelativeTo(glvp, left, top, width, height); 1547 1548 size_t tightRowBytes = bpp * width; 1549 if (0 == rowBytes) { 1550 rowBytes = tightRowBytes; 1551 } 1552 size_t readDstRowBytes = tightRowBytes; 1553 void* readDst = buffer; 1554 1555 // determine if GL can read using the passed rowBytes or if we need 1556 // a scratch buffer. 1557 SkAutoSMalloc<32 * sizeof(GrColor)> scratch; 1558 if (rowBytes != tightRowBytes) { 1559 if (this->glCaps().packRowLengthSupport()) { 1560 GrAssert(!(rowBytes % sizeof(GrColor))); 1561 GL_CALL(PixelStorei(GR_GL_PACK_ROW_LENGTH, rowBytes / sizeof(GrColor))); 1562 readDstRowBytes = rowBytes; 1563 } else { 1564 scratch.reset(tightRowBytes * height); 1565 readDst = scratch.get(); 1566 } 1567 } 1568 if (!invertY && this->glCaps().packFlipYSupport()) { 1569 GL_CALL(PixelStorei(GR_GL_PACK_REVERSE_ROW_ORDER, 1)); 1570 } 1571 GL_CALL(ReadPixels(readRect.fLeft, readRect.fBottom, 1572 readRect.fWidth, readRect.fHeight, 1573 format, type, readDst)); 1574 if (readDstRowBytes != tightRowBytes) { 1575 GrAssert(this->glCaps().packRowLengthSupport()); 1576 GL_CALL(PixelStorei(GR_GL_PACK_ROW_LENGTH, 0)); 1577 } 1578 if (!invertY && this->glCaps().packFlipYSupport()) { 1579 GL_CALL(PixelStorei(GR_GL_PACK_REVERSE_ROW_ORDER, 0)); 1580 invertY = true; 1581 } 1582 1583 // now reverse the order of the rows, since GL's are bottom-to-top, but our 1584 // API presents top-to-bottom. We must preserve the padding contents. Note 1585 // that the above readPixels did not overwrite the padding. 1586 if (readDst == buffer) { 1587 GrAssert(rowBytes == readDstRowBytes); 1588 if (!invertY) { 1589 scratch.reset(tightRowBytes); 1590 void* tmpRow = scratch.get(); 1591 // flip y in-place by rows 1592 const int halfY = height >> 1; 1593 char* top = reinterpret_cast<char*>(buffer); 1594 char* bottom = top + (height - 1) * rowBytes; 1595 for (int y = 0; y < halfY; y++) { 1596 memcpy(tmpRow, top, tightRowBytes); 1597 memcpy(top, bottom, tightRowBytes); 1598 memcpy(bottom, tmpRow, tightRowBytes); 1599 top += rowBytes; 1600 bottom -= rowBytes; 1601 } 1602 } 1603 } else { 1604 GrAssert(readDst != buffer); GrAssert(rowBytes != tightRowBytes); 1605 // copy from readDst to buffer while flipping y 1606 // const int halfY = height >> 1; 1607 const char* src = reinterpret_cast<const char*>(readDst); 1608 char* dst = reinterpret_cast<char*>(buffer); 1609 if (!invertY) { 1610 dst += (height-1) * rowBytes; 1611 } 1612 for (int y = 0; y < height; y++) { 1613 memcpy(dst, src, tightRowBytes); 1614 src += readDstRowBytes; 1615 if (invertY) { 1616 dst += rowBytes; 1617 } else { 1618 dst -= rowBytes; 1619 } 1620 } 1621 } 1622 return true; 1623} 1624 1625void GrGpuGL::flushRenderTarget(const GrIRect* bound) { 1626 1627 GrGLRenderTarget* rt = 1628 static_cast<GrGLRenderTarget*>(this->drawState()->getRenderTarget()); 1629 GrAssert(NULL != rt); 1630 1631 if (fHWBoundRenderTarget != rt) { 1632 GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, rt->renderFBOID())); 1633 #if GR_DEBUG 1634 GrGLenum status; 1635 GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER)); 1636 if (status != GR_GL_FRAMEBUFFER_COMPLETE) { 1637 GrPrintf("GrGpuGL::flushRenderTarget glCheckFramebufferStatus %x\n", status); 1638 } 1639 #endif 1640 fHWBoundRenderTarget = rt; 1641 const GrGLIRect& vp = rt->getViewport(); 1642 if (fHWViewport != vp) { 1643 vp.pushToGLViewport(this->glInterface()); 1644 fHWViewport = vp; 1645 } 1646 } 1647 if (NULL == bound || !bound->isEmpty()) { 1648 rt->flagAsNeedingResolve(bound); 1649 } 1650} 1651 1652GrGLenum gPrimitiveType2GLMode[] = { 1653 GR_GL_TRIANGLES, 1654 GR_GL_TRIANGLE_STRIP, 1655 GR_GL_TRIANGLE_FAN, 1656 GR_GL_POINTS, 1657 GR_GL_LINES, 1658 GR_GL_LINE_STRIP 1659}; 1660 1661#define SWAP_PER_DRAW 0 1662 1663#if SWAP_PER_DRAW 1664 #if GR_MAC_BUILD 1665 #include <AGL/agl.h> 1666 #elif GR_WIN32_BUILD 1667 #include <gl/GL.h> 1668 void SwapBuf() { 1669 DWORD procID = GetCurrentProcessId(); 1670 HWND hwnd = GetTopWindow(GetDesktopWindow()); 1671 while(hwnd) { 1672 DWORD wndProcID = 0; 1673 GetWindowThreadProcessId(hwnd, &wndProcID); 1674 if(wndProcID == procID) { 1675 SwapBuffers(GetDC(hwnd)); 1676 } 1677 hwnd = GetNextWindow(hwnd, GW_HWNDNEXT); 1678 } 1679 } 1680 #endif 1681#endif 1682 1683void GrGpuGL::onGpuDrawIndexed(GrPrimitiveType type, 1684 uint32_t startVertex, 1685 uint32_t startIndex, 1686 uint32_t vertexCount, 1687 uint32_t indexCount) { 1688 GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode)); 1689 1690 GrGLvoid* indices = (GrGLvoid*)(sizeof(uint16_t) * startIndex); 1691 1692 GrAssert(NULL != fHWGeometryState.fIndexBuffer); 1693 GrAssert(NULL != fHWGeometryState.fVertexBuffer); 1694 1695 // our setupGeometry better have adjusted this to zero since 1696 // DrawElements always draws from the begining of the arrays for idx 0. 1697 GrAssert(0 == startVertex); 1698 1699 GL_CALL(DrawElements(gPrimitiveType2GLMode[type], indexCount, 1700 GR_GL_UNSIGNED_SHORT, indices)); 1701#if SWAP_PER_DRAW 1702 glFlush(); 1703 #if GR_MAC_BUILD 1704 aglSwapBuffers(aglGetCurrentContext()); 1705 int set_a_break_pt_here = 9; 1706 aglSwapBuffers(aglGetCurrentContext()); 1707 #elif GR_WIN32_BUILD 1708 SwapBuf(); 1709 int set_a_break_pt_here = 9; 1710 SwapBuf(); 1711 #endif 1712#endif 1713} 1714 1715void GrGpuGL::onGpuDrawNonIndexed(GrPrimitiveType type, 1716 uint32_t startVertex, 1717 uint32_t vertexCount) { 1718 GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode)); 1719 1720 GrAssert(NULL != fHWGeometryState.fVertexBuffer); 1721 1722 // our setupGeometry better have adjusted this to zero. 1723 // DrawElements doesn't take an offset so we always adjus the startVertex. 1724 GrAssert(0 == startVertex); 1725 1726 // pass 0 for parameter first. We have to adjust gl*Pointer() to 1727 // account for startVertex in the DrawElements case. So we always 1728 // rely on setupGeometry to have accounted for startVertex. 1729 GL_CALL(DrawArrays(gPrimitiveType2GLMode[type], 0, vertexCount)); 1730#if SWAP_PER_DRAW 1731 glFlush(); 1732 #if GR_MAC_BUILD 1733 aglSwapBuffers(aglGetCurrentContext()); 1734 int set_a_break_pt_here = 9; 1735 aglSwapBuffers(aglGetCurrentContext()); 1736 #elif GR_WIN32_BUILD 1737 SwapBuf(); 1738 int set_a_break_pt_here = 9; 1739 SwapBuf(); 1740 #endif 1741#endif 1742} 1743 1744namespace { 1745const GrStencilSettings& winding_nv_path_stencil_settings() { 1746 GR_STATIC_CONST_SAME_STENCIL_STRUCT(gSettings, 1747 kIncClamp_StencilOp, 1748 kIncClamp_StencilOp, 1749 kAlwaysIfInClip_StencilFunc, 1750 ~0, ~0, ~0); 1751 return *GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(&gSettings); 1752} 1753const GrStencilSettings& even_odd_nv_path_stencil_settings() { 1754 GR_STATIC_CONST_SAME_STENCIL_STRUCT(gSettings, 1755 kInvert_StencilOp, 1756 kInvert_StencilOp, 1757 kAlwaysIfInClip_StencilFunc, 1758 ~0, ~0, ~0); 1759 return *GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(&gSettings); 1760} 1761} 1762 1763 1764void GrGpuGL::setStencilPathSettings(const GrPath&, 1765 GrPathFill fill, 1766 GrStencilSettings* settings) { 1767 switch (fill) { 1768 case kEvenOdd_GrPathFill: 1769 *settings = even_odd_nv_path_stencil_settings(); 1770 return; 1771 case kWinding_GrPathFill: 1772 *settings = winding_nv_path_stencil_settings(); 1773 return; 1774 default: 1775 GrCrash("Unexpected path fill."); 1776 } 1777} 1778 1779void GrGpuGL::onGpuStencilPath(const GrPath* path, GrPathFill fill) { 1780 GrAssert(fCaps.fPathStencilingSupport); 1781 1782 GrGLuint id = static_cast<const GrGLPath*>(path)->pathID(); 1783 GrDrawState* drawState = this->drawState(); 1784 GrAssert(NULL != drawState->getRenderTarget()); 1785 if (NULL == drawState->getRenderTarget()->getStencilBuffer()) { 1786 return; 1787 } 1788 1789 // Decide how to manipulate the stencil buffer based on the fill rule. 1790 // Also, assert that the stencil settings we set in setStencilPathSettings 1791 // are present. 1792 GrAssert(!fStencilSettings.isTwoSided()); 1793 GrGLenum fillMode; 1794 switch (fill) { 1795 case kWinding_GrPathFill: 1796 fillMode = GR_GL_COUNT_UP; 1797 GrAssert(kIncClamp_StencilOp == 1798 fStencilSettings.passOp(GrStencilSettings::kFront_Face)); 1799 GrAssert(kIncClamp_StencilOp == 1800 fStencilSettings.failOp(GrStencilSettings::kFront_Face)); 1801 break; 1802 case kEvenOdd_GrPathFill: 1803 fillMode = GR_GL_INVERT; 1804 GrAssert(kInvert_StencilOp == 1805 fStencilSettings.passOp(GrStencilSettings::kFront_Face)); 1806 GrAssert(kInvert_StencilOp == 1807 fStencilSettings.failOp(GrStencilSettings::kFront_Face)); 1808 break; 1809 default: 1810 // Only the above two fill rules are allowed. 1811 GrCrash("Unexpected path fill."); 1812 } 1813 GrGLint writeMask = fStencilSettings.writeMask(GrStencilSettings::kFront_Face); 1814 GL_CALL(StencilFillPath(id, fillMode, writeMask)); 1815 //GrPrintf("\tStencilFillPath ID: %d\n", id); 1816} 1817 1818void GrGpuGL::onResolveRenderTarget(GrRenderTarget* target) { 1819 1820 GrGLRenderTarget* rt = static_cast<GrGLRenderTarget*>(target); 1821 1822 if (rt->needsResolve()) { 1823 GrAssert(GrGLCaps::kNone_MSFBOType != this->glCaps().msFBOType()); 1824 GrAssert(rt->textureFBOID() != rt->renderFBOID()); 1825 GL_CALL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER, 1826 rt->renderFBOID())); 1827 GL_CALL(BindFramebuffer(GR_GL_DRAW_FRAMEBUFFER, 1828 rt->textureFBOID())); 1829 // make sure we go through flushRenderTarget() since we've modified 1830 // the bound DRAW FBO ID. 1831 fHWBoundRenderTarget = NULL; 1832 const GrGLIRect& vp = rt->getViewport(); 1833 const GrIRect dirtyRect = rt->getResolveRect(); 1834 GrGLIRect r; 1835 r.setRelativeTo(vp, dirtyRect.fLeft, dirtyRect.fTop, 1836 dirtyRect.width(), dirtyRect.height()); 1837 1838 GrAutoTRestore<ScissorState> asr; 1839 if (GrGLCaps::kAppleES_MSFBOType == this->glCaps().msFBOType()) { 1840 // Apple's extension uses the scissor as the blit bounds. 1841 asr.reset(&fScissorState); 1842 fScissorState.fEnabled = true; 1843 fScissorState.fRect = dirtyRect; 1844 this->flushScissor(); 1845 GL_CALL(ResolveMultisampleFramebuffer()); 1846 } else { 1847 if (GrGLCaps::kDesktopARB_MSFBOType != this->glCaps().msFBOType()) { 1848 // this respects the scissor during the blit, so disable it. 1849 GrAssert(GrGLCaps::kDesktopEXT_MSFBOType == 1850 this->glCaps().msFBOType()); 1851 asr.reset(&fScissorState); 1852 fScissorState.fEnabled = false; 1853 this->flushScissor(); 1854 } 1855 int right = r.fLeft + r.fWidth; 1856 int top = r.fBottom + r.fHeight; 1857 GL_CALL(BlitFramebuffer(r.fLeft, r.fBottom, right, top, 1858 r.fLeft, r.fBottom, right, top, 1859 GR_GL_COLOR_BUFFER_BIT, GR_GL_NEAREST)); 1860 } 1861 rt->flagAsResolved(); 1862 } 1863} 1864 1865namespace { 1866 1867GrGLenum gr_to_gl_stencil_func(GrStencilFunc basicFunc) { 1868 static const GrGLenum gTable[] = { 1869 GR_GL_ALWAYS, // kAlways_StencilFunc 1870 GR_GL_NEVER, // kNever_StencilFunc 1871 GR_GL_GREATER, // kGreater_StencilFunc 1872 GR_GL_GEQUAL, // kGEqual_StencilFunc 1873 GR_GL_LESS, // kLess_StencilFunc 1874 GR_GL_LEQUAL, // kLEqual_StencilFunc, 1875 GR_GL_EQUAL, // kEqual_StencilFunc, 1876 GR_GL_NOTEQUAL, // kNotEqual_StencilFunc, 1877 }; 1878 GR_STATIC_ASSERT(GR_ARRAY_COUNT(gTable) == kBasicStencilFuncCount); 1879 GR_STATIC_ASSERT(0 == kAlways_StencilFunc); 1880 GR_STATIC_ASSERT(1 == kNever_StencilFunc); 1881 GR_STATIC_ASSERT(2 == kGreater_StencilFunc); 1882 GR_STATIC_ASSERT(3 == kGEqual_StencilFunc); 1883 GR_STATIC_ASSERT(4 == kLess_StencilFunc); 1884 GR_STATIC_ASSERT(5 == kLEqual_StencilFunc); 1885 GR_STATIC_ASSERT(6 == kEqual_StencilFunc); 1886 GR_STATIC_ASSERT(7 == kNotEqual_StencilFunc); 1887 GrAssert((unsigned) basicFunc < kBasicStencilFuncCount); 1888 1889 return gTable[basicFunc]; 1890} 1891 1892GrGLenum gr_to_gl_stencil_op(GrStencilOp op) { 1893 static const GrGLenum gTable[] = { 1894 GR_GL_KEEP, // kKeep_StencilOp 1895 GR_GL_REPLACE, // kReplace_StencilOp 1896 GR_GL_INCR_WRAP, // kIncWrap_StencilOp 1897 GR_GL_INCR, // kIncClamp_StencilOp 1898 GR_GL_DECR_WRAP, // kDecWrap_StencilOp 1899 GR_GL_DECR, // kDecClamp_StencilOp 1900 GR_GL_ZERO, // kZero_StencilOp 1901 GR_GL_INVERT, // kInvert_StencilOp 1902 }; 1903 GR_STATIC_ASSERT(GR_ARRAY_COUNT(gTable) == kStencilOpCount); 1904 GR_STATIC_ASSERT(0 == kKeep_StencilOp); 1905 GR_STATIC_ASSERT(1 == kReplace_StencilOp); 1906 GR_STATIC_ASSERT(2 == kIncWrap_StencilOp); 1907 GR_STATIC_ASSERT(3 == kIncClamp_StencilOp); 1908 GR_STATIC_ASSERT(4 == kDecWrap_StencilOp); 1909 GR_STATIC_ASSERT(5 == kDecClamp_StencilOp); 1910 GR_STATIC_ASSERT(6 == kZero_StencilOp); 1911 GR_STATIC_ASSERT(7 == kInvert_StencilOp); 1912 GrAssert((unsigned) op < kStencilOpCount); 1913 return gTable[op]; 1914} 1915 1916void set_gl_stencil(const GrGLInterface* gl, 1917 const GrStencilSettings& settings, 1918 GrGLenum glFace, 1919 GrStencilSettings::Face grFace) { 1920 GrGLenum glFunc = gr_to_gl_stencil_func(settings.func(grFace)); 1921 GrGLenum glFailOp = gr_to_gl_stencil_op(settings.failOp(grFace)); 1922 GrGLenum glPassOp = gr_to_gl_stencil_op(settings.passOp(grFace)); 1923 1924 GrGLint ref = settings.funcRef(grFace); 1925 GrGLint mask = settings.funcMask(grFace); 1926 GrGLint writeMask = settings.writeMask(grFace); 1927 1928 if (GR_GL_FRONT_AND_BACK == glFace) { 1929 // we call the combined func just in case separate stencil is not 1930 // supported. 1931 GR_GL_CALL(gl, StencilFunc(glFunc, ref, mask)); 1932 GR_GL_CALL(gl, StencilMask(writeMask)); 1933 GR_GL_CALL(gl, StencilOp(glFailOp, glPassOp, glPassOp)); 1934 } else { 1935 GR_GL_CALL(gl, StencilFuncSeparate(glFace, glFunc, ref, mask)); 1936 GR_GL_CALL(gl, StencilMaskSeparate(glFace, writeMask)); 1937 GR_GL_CALL(gl, StencilOpSeparate(glFace, glFailOp, glPassOp, glPassOp)); 1938 } 1939} 1940} 1941 1942void GrGpuGL::flushStencil(DrawType type) { 1943 if (kStencilPath_DrawType == type) { 1944 GrAssert(!fStencilSettings.isTwoSided()); 1945 // Just the func, ref, and mask is set here. The op and write mask are params to the call 1946 // that draws the path to the SB (glStencilFillPath) 1947 GrGLenum func = 1948 gr_to_gl_stencil_func(fStencilSettings.func(GrStencilSettings::kFront_Face)); 1949 GL_CALL(PathStencilFunc(func, 1950 fStencilSettings.funcRef(GrStencilSettings::kFront_Face), 1951 fStencilSettings.funcMask(GrStencilSettings::kFront_Face))); 1952 } else if (fHWStencilSettings != fStencilSettings) { 1953 if (fStencilSettings.isDisabled()) { 1954 if (kNo_TriState != fHWStencilTestEnabled) { 1955 GL_CALL(Disable(GR_GL_STENCIL_TEST)); 1956 fHWStencilTestEnabled = kNo_TriState; 1957 } 1958 } else { 1959 if (kYes_TriState != fHWStencilTestEnabled) { 1960 GL_CALL(Enable(GR_GL_STENCIL_TEST)); 1961 fHWStencilTestEnabled = kYes_TriState; 1962 } 1963 } 1964 if (!fStencilSettings.isDisabled()) { 1965 if (this->getCaps().fTwoSidedStencilSupport) { 1966 set_gl_stencil(this->glInterface(), 1967 fStencilSettings, 1968 GR_GL_FRONT, 1969 GrStencilSettings::kFront_Face); 1970 set_gl_stencil(this->glInterface(), 1971 fStencilSettings, 1972 GR_GL_BACK, 1973 GrStencilSettings::kBack_Face); 1974 } else { 1975 set_gl_stencil(this->glInterface(), 1976 fStencilSettings, 1977 GR_GL_FRONT_AND_BACK, 1978 GrStencilSettings::kFront_Face); 1979 } 1980 } 1981 fHWStencilSettings = fStencilSettings; 1982 } 1983} 1984 1985void GrGpuGL::flushAAState(DrawType type) { 1986 const GrRenderTarget* rt = this->getDrawState().getRenderTarget(); 1987 if (kDesktop_GrGLBinding == this->glBinding()) { 1988 // ES doesn't support toggling GL_MULTISAMPLE and doesn't have 1989 // smooth lines. 1990 // we prefer smooth lines over multisampled lines 1991 bool smoothLines = false; 1992 1993 if (kDrawLines_DrawType == type) { 1994 smoothLines = this->willUseHWAALines(); 1995 if (smoothLines) { 1996 if (kYes_TriState != fHWAAState.fSmoothLineEnabled) { 1997 GL_CALL(Enable(GR_GL_LINE_SMOOTH)); 1998 fHWAAState.fSmoothLineEnabled = kYes_TriState; 1999 // must disable msaa to use line smoothing 2000 if (rt->isMultisampled() && 2001 kNo_TriState != fHWAAState.fMSAAEnabled) { 2002 GL_CALL(Disable(GR_GL_MULTISAMPLE)); 2003 fHWAAState.fMSAAEnabled = kNo_TriState; 2004 } 2005 } 2006 } else { 2007 if (kNo_TriState != fHWAAState.fSmoothLineEnabled) { 2008 GL_CALL(Disable(GR_GL_LINE_SMOOTH)); 2009 fHWAAState.fSmoothLineEnabled = kNo_TriState; 2010 } 2011 } 2012 } 2013 if (!smoothLines && rt->isMultisampled()) { 2014 // FIXME: GL_NV_pr doesn't seem to like MSAA disabled. The paths 2015 // convex hulls of each segment appear to get filled. 2016 bool enableMSAA = kStencilPath_DrawType == type || 2017 this->getDrawState().isHWAntialiasState(); 2018 if (enableMSAA) { 2019 if (kYes_TriState != fHWAAState.fMSAAEnabled) { 2020 GL_CALL(Enable(GR_GL_MULTISAMPLE)); 2021 fHWAAState.fMSAAEnabled = kYes_TriState; 2022 } 2023 } else { 2024 if (kNo_TriState != fHWAAState.fMSAAEnabled) { 2025 GL_CALL(Disable(GR_GL_MULTISAMPLE)); 2026 fHWAAState.fMSAAEnabled = kNo_TriState; 2027 } 2028 } 2029 } 2030 } 2031} 2032 2033void GrGpuGL::flushBlend(bool isLines, 2034 GrBlendCoeff srcCoeff, 2035 GrBlendCoeff dstCoeff) { 2036 if (isLines && this->willUseHWAALines()) { 2037 if (kYes_TriState != fHWBlendState.fEnabled) { 2038 GL_CALL(Enable(GR_GL_BLEND)); 2039 fHWBlendState.fEnabled = kYes_TriState; 2040 } 2041 if (kSA_GrBlendCoeff != fHWBlendState.fSrcCoeff || 2042 kISA_GrBlendCoeff != fHWBlendState.fDstCoeff) { 2043 GL_CALL(BlendFunc(gXfermodeCoeff2Blend[kSA_GrBlendCoeff], 2044 gXfermodeCoeff2Blend[kISA_GrBlendCoeff])); 2045 fHWBlendState.fSrcCoeff = kSA_GrBlendCoeff; 2046 fHWBlendState.fDstCoeff = kISA_GrBlendCoeff; 2047 } 2048 } else { 2049 // any optimization to disable blending should 2050 // have already been applied and tweaked the coeffs 2051 // to (1, 0). 2052 bool blendOff = kOne_GrBlendCoeff == srcCoeff && 2053 kZero_GrBlendCoeff == dstCoeff; 2054 if (blendOff) { 2055 if (kNo_TriState != fHWBlendState.fEnabled) { 2056 GL_CALL(Disable(GR_GL_BLEND)); 2057 fHWBlendState.fEnabled = kNo_TriState; 2058 } 2059 } else { 2060 if (kYes_TriState != fHWBlendState.fEnabled) { 2061 GL_CALL(Enable(GR_GL_BLEND)); 2062 fHWBlendState.fEnabled = kYes_TriState; 2063 } 2064 if (fHWBlendState.fSrcCoeff != srcCoeff || 2065 fHWBlendState.fDstCoeff != dstCoeff) { 2066 GL_CALL(BlendFunc(gXfermodeCoeff2Blend[srcCoeff], 2067 gXfermodeCoeff2Blend[dstCoeff])); 2068 fHWBlendState.fSrcCoeff = srcCoeff; 2069 fHWBlendState.fDstCoeff = dstCoeff; 2070 } 2071 GrColor blendConst = this->getDrawState().getBlendConstant(); 2072 if ((BlendCoeffReferencesConstant(srcCoeff) || 2073 BlendCoeffReferencesConstant(dstCoeff)) && 2074 (!fHWBlendState.fConstColorValid || 2075 fHWBlendState.fConstColor != blendConst)) { 2076 2077 float c[] = { 2078 GrColorUnpackR(blendConst) / 255.f, 2079 GrColorUnpackG(blendConst) / 255.f, 2080 GrColorUnpackB(blendConst) / 255.f, 2081 GrColorUnpackA(blendConst) / 255.f 2082 }; 2083 GL_CALL(BlendColor(c[0], c[1], c[2], c[3])); 2084 fHWBlendState.fConstColor = blendConst; 2085 fHWBlendState.fConstColorValid = true; 2086 } 2087 } 2088 } 2089} 2090namespace { 2091 2092unsigned gr_to_gl_filter(GrSamplerState::Filter filter) { 2093 switch (filter) { 2094 case GrSamplerState::kBilinear_Filter: 2095 return GR_GL_LINEAR; 2096 case GrSamplerState::kNearest_Filter: 2097 return GR_GL_NEAREST; 2098 default: 2099 GrAssert(!"Unknown filter type"); 2100 return GR_GL_LINEAR; 2101 } 2102} 2103 2104// get_swizzle is only called from this .cpp so it is OK to inline it here 2105inline const GrGLenum* get_swizzle(GrPixelConfig config, 2106 const GrSamplerState& sampler, 2107 const GrGLCaps& glCaps) { 2108 if (GrPixelConfigIsAlphaOnly(config)) { 2109 if (glCaps.textureRedSupport()) { 2110 static const GrGLenum gRedSmear[] = { GR_GL_RED, GR_GL_RED, 2111 GR_GL_RED, GR_GL_RED }; 2112 return gRedSmear; 2113 } else { 2114 static const GrGLenum gAlphaSmear[] = { GR_GL_ALPHA, GR_GL_ALPHA, 2115 GR_GL_ALPHA, GR_GL_ALPHA }; 2116 return gAlphaSmear; 2117 } 2118 } else if (sampler.swapsRAndB()) { 2119 static const GrGLenum gRedBlueSwap[] = { GR_GL_BLUE, GR_GL_GREEN, 2120 GR_GL_RED, GR_GL_ALPHA }; 2121 return gRedBlueSwap; 2122 } else { 2123 static const GrGLenum gStraight[] = { GR_GL_RED, GR_GL_GREEN, 2124 GR_GL_BLUE, GR_GL_ALPHA }; 2125 return gStraight; 2126 } 2127} 2128 2129void set_tex_swizzle(GrGLenum swizzle[4], const GrGLInterface* gl) { 2130 GR_GL_CALL(gl, TexParameteriv(GR_GL_TEXTURE_2D, 2131 GR_GL_TEXTURE_SWIZZLE_RGBA, 2132 reinterpret_cast<const GrGLint*>(swizzle))); 2133} 2134} 2135 2136void GrGpuGL::flushBoundTextureAndParams(int stage) { 2137 GrDrawState* drawState = this->drawState(); 2138 2139 GrGLTexture* nextTexture = 2140 static_cast<GrGLTexture*>(drawState->getTexture(stage)); 2141 2142 // true for now, but maybe not with GrEffect. 2143 GrAssert(NULL != nextTexture); 2144 // if we created a rt/tex and rendered to it without using a 2145 // texture and now we're texturing from the rt it will still be 2146 // the last bound texture, but it needs resolving. So keep this 2147 // out of the "last != next" check. 2148 GrGLRenderTarget* texRT = 2149 static_cast<GrGLRenderTarget*>(nextTexture->asRenderTarget()); 2150 if (NULL != texRT) { 2151 this->onResolveRenderTarget(texRT); 2152 } 2153 2154 if (fHWBoundTextures[stage] != nextTexture) { 2155 this->setTextureUnit(stage); 2156 GL_CALL(BindTexture(GR_GL_TEXTURE_2D, nextTexture->textureID())); 2157 //GrPrintf("---- bindtexture %d\n", nextTexture->textureID()); 2158 fHWBoundTextures[stage] = nextTexture; 2159 } 2160 2161 const GrSamplerState& sampler = drawState->getSampler(stage); 2162 ResetTimestamp timestamp; 2163 const GrGLTexture::TexParams& oldTexParams = 2164 nextTexture->getCachedTexParams(×tamp); 2165 bool setAll = timestamp < this->getResetTimestamp(); 2166 GrGLTexture::TexParams newTexParams; 2167 2168 newTexParams.fFilter = gr_to_gl_filter(sampler.getFilter()); 2169 2170 const GrGLenum* wraps = GrGLTexture::WrapMode2GLWrap(); 2171 newTexParams.fWrapS = wraps[sampler.getWrapX()]; 2172 newTexParams.fWrapT = wraps[sampler.getWrapY()]; 2173 memcpy(newTexParams.fSwizzleRGBA, 2174 get_swizzle(nextTexture->config(), sampler, this->glCaps()), 2175 sizeof(newTexParams.fSwizzleRGBA)); 2176 if (setAll || newTexParams.fFilter != oldTexParams.fFilter) { 2177 this->setTextureUnit(stage); 2178 GL_CALL(TexParameteri(GR_GL_TEXTURE_2D, 2179 GR_GL_TEXTURE_MAG_FILTER, 2180 newTexParams.fFilter)); 2181 GL_CALL(TexParameteri(GR_GL_TEXTURE_2D, 2182 GR_GL_TEXTURE_MIN_FILTER, 2183 newTexParams.fFilter)); 2184 } 2185 if (setAll || newTexParams.fWrapS != oldTexParams.fWrapS) { 2186 this->setTextureUnit(stage); 2187 GL_CALL(TexParameteri(GR_GL_TEXTURE_2D, 2188 GR_GL_TEXTURE_WRAP_S, 2189 newTexParams.fWrapS)); 2190 } 2191 if (setAll || newTexParams.fWrapT != oldTexParams.fWrapT) { 2192 this->setTextureUnit(stage); 2193 GL_CALL(TexParameteri(GR_GL_TEXTURE_2D, 2194 GR_GL_TEXTURE_WRAP_T, 2195 newTexParams.fWrapT)); 2196 } 2197 if (this->glCaps().textureSwizzleSupport() && 2198 (setAll || memcmp(newTexParams.fSwizzleRGBA, 2199 oldTexParams.fSwizzleRGBA, 2200 sizeof(newTexParams.fSwizzleRGBA)))) { 2201 this->setTextureUnit(stage); 2202 set_tex_swizzle(newTexParams.fSwizzleRGBA, 2203 this->glInterface()); 2204 } 2205 nextTexture->setCachedTexParams(newTexParams, 2206 this->getResetTimestamp()); 2207} 2208 2209void GrGpuGL::flushMiscFixedFunctionState() { 2210 2211 const GrDrawState& drawState = this->getDrawState(); 2212 2213 if (drawState.isDitherState()) { 2214 if (kYes_TriState != fHWDitherEnabled) { 2215 GL_CALL(Enable(GR_GL_DITHER)); 2216 fHWDitherEnabled = kYes_TriState; 2217 } 2218 } else { 2219 if (kNo_TriState != fHWDitherEnabled) { 2220 GL_CALL(Disable(GR_GL_DITHER)); 2221 fHWDitherEnabled = kNo_TriState; 2222 } 2223 } 2224 2225 if (drawState.isColorWriteDisabled()) { 2226 if (kNo_TriState != fHWWriteToColor) { 2227 GL_CALL(ColorMask(GR_GL_FALSE, GR_GL_FALSE, 2228 GR_GL_FALSE, GR_GL_FALSE)); 2229 fHWWriteToColor = kNo_TriState; 2230 } 2231 } else { 2232 if (kYes_TriState != fHWWriteToColor) { 2233 GL_CALL(ColorMask(GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE)); 2234 fHWWriteToColor = kYes_TriState; 2235 } 2236 } 2237 2238 if (fHWDrawFace != drawState.getDrawFace()) { 2239 switch (this->getDrawState().getDrawFace()) { 2240 case GrDrawState::kCCW_DrawFace: 2241 GL_CALL(Enable(GR_GL_CULL_FACE)); 2242 GL_CALL(CullFace(GR_GL_BACK)); 2243 break; 2244 case GrDrawState::kCW_DrawFace: 2245 GL_CALL(Enable(GR_GL_CULL_FACE)); 2246 GL_CALL(CullFace(GR_GL_FRONT)); 2247 break; 2248 case GrDrawState::kBoth_DrawFace: 2249 GL_CALL(Disable(GR_GL_CULL_FACE)); 2250 break; 2251 default: 2252 GrCrash("Unknown draw face."); 2253 } 2254 fHWDrawFace = drawState.getDrawFace(); 2255 } 2256} 2257 2258void GrGpuGL::notifyVertexBufferBind(const GrGLVertexBuffer* buffer) { 2259 if (fHWGeometryState.fVertexBuffer != buffer) { 2260 fHWGeometryState.fArrayPtrsDirty = true; 2261 fHWGeometryState.fVertexBuffer = buffer; 2262 } 2263} 2264 2265void GrGpuGL::notifyVertexBufferDelete(const GrGLVertexBuffer* buffer) { 2266 if (fHWGeometryState.fVertexBuffer == buffer) { 2267 // deleting bound buffer does implied bind to 0 2268 fHWGeometryState.fVertexBuffer = NULL; 2269 fHWGeometryState.fArrayPtrsDirty = true; 2270 } 2271} 2272 2273void GrGpuGL::notifyIndexBufferBind(const GrGLIndexBuffer* buffer) { 2274 fHWGeometryState.fIndexBuffer = buffer; 2275} 2276 2277void GrGpuGL::notifyIndexBufferDelete(const GrGLIndexBuffer* buffer) { 2278 if (fHWGeometryState.fIndexBuffer == buffer) { 2279 // deleting bound buffer does implied bind to 0 2280 fHWGeometryState.fIndexBuffer = NULL; 2281 } 2282} 2283 2284void GrGpuGL::notifyRenderTargetDelete(GrRenderTarget* renderTarget) { 2285 GrAssert(NULL != renderTarget); 2286 if (fHWBoundRenderTarget == renderTarget) { 2287 fHWBoundRenderTarget = NULL; 2288 } 2289} 2290 2291void GrGpuGL::notifyTextureDelete(GrGLTexture* texture) { 2292 for (int s = 0; s < GrDrawState::kNumStages; ++s) { 2293 if (fHWBoundTextures[s] == texture) { 2294 // deleting bound texture does implied bind to 0 2295 fHWBoundTextures[s] = NULL; 2296 } 2297 } 2298} 2299 2300bool GrGpuGL::configToGLFormats(GrPixelConfig config, 2301 bool getSizedInternalFormat, 2302 GrGLenum* internalFormat, 2303 GrGLenum* externalFormat, 2304 GrGLenum* externalType) { 2305 GrGLenum dontCare; 2306 if (NULL == internalFormat) { 2307 internalFormat = &dontCare; 2308 } 2309 if (NULL == externalFormat) { 2310 externalFormat = &dontCare; 2311 } 2312 if (NULL == externalType) { 2313 externalType = &dontCare; 2314 } 2315 2316 switch (config) { 2317 case kRGBA_8888_PM_GrPixelConfig: 2318 case kRGBA_8888_UPM_GrPixelConfig: 2319 *internalFormat = GR_GL_RGBA; 2320 *externalFormat = GR_GL_RGBA; 2321 if (getSizedInternalFormat) { 2322 *internalFormat = GR_GL_RGBA8; 2323 } else { 2324 *internalFormat = GR_GL_RGBA; 2325 } 2326 *externalType = GR_GL_UNSIGNED_BYTE; 2327 break; 2328 case kBGRA_8888_PM_GrPixelConfig: 2329 case kBGRA_8888_UPM_GrPixelConfig: 2330 if (!this->glCaps().bgraFormatSupport()) { 2331 return false; 2332 } 2333 if (this->glCaps().bgraIsInternalFormat()) { 2334 if (getSizedInternalFormat) { 2335 *internalFormat = GR_GL_BGRA8; 2336 } else { 2337 *internalFormat = GR_GL_BGRA; 2338 } 2339 } else { 2340 if (getSizedInternalFormat) { 2341 *internalFormat = GR_GL_RGBA8; 2342 } else { 2343 *internalFormat = GR_GL_RGBA; 2344 } 2345 } 2346 *externalFormat = GR_GL_BGRA; 2347 *externalType = GR_GL_UNSIGNED_BYTE; 2348 break; 2349 case kRGB_565_GrPixelConfig: 2350 *internalFormat = GR_GL_RGB; 2351 *externalFormat = GR_GL_RGB; 2352 if (getSizedInternalFormat) { 2353 if (this->glBinding() == kDesktop_GrGLBinding) { 2354 return false; 2355 } else { 2356 *internalFormat = GR_GL_RGB565; 2357 } 2358 } else { 2359 *internalFormat = GR_GL_RGB; 2360 } 2361 *externalType = GR_GL_UNSIGNED_SHORT_5_6_5; 2362 break; 2363 case kRGBA_4444_GrPixelConfig: 2364 *internalFormat = GR_GL_RGBA; 2365 *externalFormat = GR_GL_RGBA; 2366 if (getSizedInternalFormat) { 2367 *internalFormat = GR_GL_RGBA4; 2368 } else { 2369 *internalFormat = GR_GL_RGBA; 2370 } 2371 *externalType = GR_GL_UNSIGNED_SHORT_4_4_4_4; 2372 break; 2373 case kIndex_8_GrPixelConfig: 2374 if (this->getCaps().f8BitPaletteSupport) { 2375 *internalFormat = GR_GL_PALETTE8_RGBA8; 2376 // glCompressedTexImage doesn't take external params 2377 *externalFormat = GR_GL_PALETTE8_RGBA8; 2378 // no sized/unsized internal format distinction here 2379 *internalFormat = GR_GL_PALETTE8_RGBA8; 2380 // unused with CompressedTexImage 2381 *externalType = GR_GL_UNSIGNED_BYTE; 2382 } else { 2383 return false; 2384 } 2385 break; 2386 case kAlpha_8_GrPixelConfig: 2387 if (this->glCaps().textureRedSupport()) { 2388 *internalFormat = GR_GL_RED; 2389 *externalFormat = GR_GL_RED; 2390 if (getSizedInternalFormat) { 2391 *internalFormat = GR_GL_R8; 2392 } else { 2393 *internalFormat = GR_GL_RED; 2394 } 2395 *externalType = GR_GL_UNSIGNED_BYTE; 2396 } else { 2397 *internalFormat = GR_GL_ALPHA; 2398 *externalFormat = GR_GL_ALPHA; 2399 if (getSizedInternalFormat) { 2400 *internalFormat = GR_GL_ALPHA8; 2401 } else { 2402 *internalFormat = GR_GL_ALPHA; 2403 } 2404 *externalType = GR_GL_UNSIGNED_BYTE; 2405 } 2406 break; 2407 default: 2408 return false; 2409 } 2410 return true; 2411} 2412 2413void GrGpuGL::setTextureUnit(int unit) { 2414 GrAssert(unit >= 0 && unit < GrDrawState::kNumStages); 2415 if (fHWActiveTextureUnitIdx != unit) { 2416 GL_CALL(ActiveTexture(GR_GL_TEXTURE0 + unit)); 2417 fHWActiveTextureUnitIdx = unit; 2418 } 2419} 2420 2421void GrGpuGL::setSpareTextureUnit() { 2422 if (fHWActiveTextureUnitIdx != (GR_GL_TEXTURE0 + SPARE_TEX_UNIT)) { 2423 GL_CALL(ActiveTexture(GR_GL_TEXTURE0 + SPARE_TEX_UNIT)); 2424 fHWActiveTextureUnitIdx = SPARE_TEX_UNIT; 2425 } 2426} 2427 2428void GrGpuGL::setBuffers(bool indexed, 2429 int* extraVertexOffset, 2430 int* extraIndexOffset) { 2431 2432 GrAssert(NULL != extraVertexOffset); 2433 2434 const GeometryPoolState& geoPoolState = this->getGeomPoolState(); 2435 2436 GrGLVertexBuffer* vbuf; 2437 switch (this->getGeomSrc().fVertexSrc) { 2438 case kBuffer_GeometrySrcType: 2439 *extraVertexOffset = 0; 2440 vbuf = (GrGLVertexBuffer*) this->getGeomSrc().fVertexBuffer; 2441 break; 2442 case kArray_GeometrySrcType: 2443 case kReserved_GeometrySrcType: 2444 this->finalizeReservedVertices(); 2445 *extraVertexOffset = geoPoolState.fPoolStartVertex; 2446 vbuf = (GrGLVertexBuffer*) geoPoolState.fPoolVertexBuffer; 2447 break; 2448 default: 2449 vbuf = NULL; // suppress warning 2450 GrCrash("Unknown geometry src type!"); 2451 } 2452 2453 GrAssert(NULL != vbuf); 2454 GrAssert(!vbuf->isLocked()); 2455 if (fHWGeometryState.fVertexBuffer != vbuf) { 2456 GL_CALL(BindBuffer(GR_GL_ARRAY_BUFFER, vbuf->bufferID())); 2457 fHWGeometryState.fArrayPtrsDirty = true; 2458 fHWGeometryState.fVertexBuffer = vbuf; 2459 } 2460 2461 if (indexed) { 2462 GrAssert(NULL != extraIndexOffset); 2463 2464 GrGLIndexBuffer* ibuf; 2465 switch (this->getGeomSrc().fIndexSrc) { 2466 case kBuffer_GeometrySrcType: 2467 *extraIndexOffset = 0; 2468 ibuf = (GrGLIndexBuffer*)this->getGeomSrc().fIndexBuffer; 2469 break; 2470 case kArray_GeometrySrcType: 2471 case kReserved_GeometrySrcType: 2472 this->finalizeReservedIndices(); 2473 *extraIndexOffset = geoPoolState.fPoolStartIndex; 2474 ibuf = (GrGLIndexBuffer*) geoPoolState.fPoolIndexBuffer; 2475 break; 2476 default: 2477 ibuf = NULL; // suppress warning 2478 GrCrash("Unknown geometry src type!"); 2479 } 2480 2481 GrAssert(NULL != ibuf); 2482 GrAssert(!ibuf->isLocked()); 2483 if (fHWGeometryState.fIndexBuffer != ibuf) { 2484 GL_CALL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, ibuf->bufferID())); 2485 fHWGeometryState.fIndexBuffer = ibuf; 2486 } 2487 } 2488} 2489 2490