gfx/skia/trunk/src/gpu/gl/GrGpuGL_program.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

michael@0 1 /*
michael@0 2 * Copyright 2011 Google Inc.
michael@0 3 *
michael@0 4 * Use of this source code is governed by a BSD-style license that can be
michael@0 5 * found in the LICENSE file.
michael@0 6 */
michael@0 7
michael@0 8 #include "GrGpuGL.h"
michael@0 9
michael@0 10 #include "GrEffect.h"
michael@0 11 #include "GrGLEffect.h"
michael@0 12 #include "SkRTConf.h"
michael@0 13 #include "SkTSearch.h"
michael@0 14
michael@0 15 #ifdef PROGRAM_CACHE_STATS
michael@0 16 SK_CONF_DECLARE(bool, c_DisplayCache, "gpu.displayCache", false,
michael@0 17 "Display program cache usage.");
michael@0 18 #endif
michael@0 19
michael@0 20 typedef GrGLUniformManager::UniformHandle UniformHandle;
michael@0 21
michael@0 22 struct GrGpuGL::ProgramCache::Entry {
michael@0 23 SK_DECLARE_INST_COUNT_ROOT(Entry);
michael@0 24 Entry() : fProgram(NULL), fLRUStamp(0) {}
michael@0 25
michael@0 26 SkAutoTUnref<GrGLProgram> fProgram;
michael@0 27 unsigned int fLRUStamp;
michael@0 28 };
michael@0 29
michael@0 30 struct GrGpuGL::ProgramCache::ProgDescLess {
michael@0 31 bool operator() (const GrGLProgramDesc& desc, const Entry* entry) {
michael@0 32 SkASSERT(NULL != entry->fProgram.get());
michael@0 33 return GrGLProgramDesc::Less(desc, entry->fProgram->getDesc());
michael@0 34 }
michael@0 35
michael@0 36 bool operator() (const Entry* entry, const GrGLProgramDesc& desc) {
michael@0 37 SkASSERT(NULL != entry->fProgram.get());
michael@0 38 return GrGLProgramDesc::Less(entry->fProgram->getDesc(), desc);
michael@0 39 }
michael@0 40 };
michael@0 41
michael@0 42 GrGpuGL::ProgramCache::ProgramCache(GrGpuGL* gpu)
michael@0 43 : fCount(0)
michael@0 44 , fCurrLRUStamp(0)
michael@0 45 , fGpu(gpu)
michael@0 46 #ifdef PROGRAM_CACHE_STATS
michael@0 47 , fTotalRequests(0)
michael@0 48 , fCacheMisses(0)
michael@0 49 , fHashMisses(0)
michael@0 50 #endif
michael@0 51 {
michael@0 52 for (int i = 0; i < 1 << kHashBits; ++i) {
michael@0 53 fHashTable[i] = NULL;
michael@0 54 }
michael@0 55 }
michael@0 56
michael@0 57 GrGpuGL::ProgramCache::~ProgramCache() {
michael@0 58 for (int i = 0; i < fCount; ++i){
michael@0 59 SkDELETE(fEntries[i]);
michael@0 60 }
michael@0 61 // dump stats
michael@0 62 #ifdef PROGRAM_CACHE_STATS
michael@0 63 if (c_DisplayCache) {
michael@0 64 SkDebugf("--- Program Cache ---\n");
michael@0 65 SkDebugf("Total requests: %d\n", fTotalRequests);
michael@0 66 SkDebugf("Cache misses: %d\n", fCacheMisses);
michael@0 67 SkDebugf("Cache miss %%: %f\n", (fTotalRequests > 0) ?
michael@0 68 100.f * fCacheMisses / fTotalRequests :
michael@0 69 0.f);
michael@0 70 int cacheHits = fTotalRequests - fCacheMisses;
michael@0 71 SkDebugf("Hash miss %%: %f\n", (cacheHits > 0) ? 100.f * fHashMisses / cacheHits : 0.f);
michael@0 72 SkDebugf("---------------------\n");
michael@0 73 }
michael@0 74 #endif
michael@0 75 }
michael@0 76
michael@0 77 void GrGpuGL::ProgramCache::abandon() {
michael@0 78 for (int i = 0; i < fCount; ++i) {
michael@0 79 SkASSERT(NULL != fEntries[i]->fProgram.get());
michael@0 80 fEntries[i]->fProgram->abandon();
michael@0 81 fEntries[i]->fProgram.reset(NULL);
michael@0 82 }
michael@0 83 fCount = 0;
michael@0 84 }
michael@0 85
michael@0 86 int GrGpuGL::ProgramCache::search(const GrGLProgramDesc& desc) const {
michael@0 87 ProgDescLess less;
michael@0 88 return SkTSearch(fEntries, fCount, desc, sizeof(Entry*), less);
michael@0 89 }
michael@0 90
michael@0 91 GrGLProgram* GrGpuGL::ProgramCache::getProgram(const GrGLProgramDesc& desc,
michael@0 92 const GrEffectStage* colorStages[],
michael@0 93 const GrEffectStage* coverageStages[]) {
michael@0 94 #ifdef PROGRAM_CACHE_STATS
michael@0 95 ++fTotalRequests;
michael@0 96 #endif
michael@0 97
michael@0 98 Entry* entry = NULL;
michael@0 99
michael@0 100 uint32_t hashIdx = desc.getChecksum();
michael@0 101 hashIdx ^= hashIdx >> 16;
michael@0 102 if (kHashBits <= 8) {
michael@0 103 hashIdx ^= hashIdx >> 8;
michael@0 104 }
michael@0 105 hashIdx &=((1 << kHashBits) - 1);
michael@0 106 Entry* hashedEntry = fHashTable[hashIdx];
michael@0 107 if (NULL != hashedEntry && hashedEntry->fProgram->getDesc() == desc) {
michael@0 108 SkASSERT(NULL != hashedEntry->fProgram);
michael@0 109 entry = hashedEntry;
michael@0 110 }
michael@0 111
michael@0 112 int entryIdx;
michael@0 113 if (NULL == entry) {
michael@0 114 entryIdx = this->search(desc);
michael@0 115 if (entryIdx >= 0) {
michael@0 116 entry = fEntries[entryIdx];
michael@0 117 #ifdef PROGRAM_CACHE_STATS
michael@0 118 ++fHashMisses;
michael@0 119 #endif
michael@0 120 }
michael@0 121 }
michael@0 122
michael@0 123 if (NULL == entry) {
michael@0 124 // We have a cache miss
michael@0 125 #ifdef PROGRAM_CACHE_STATS
michael@0 126 ++fCacheMisses;
michael@0 127 #endif
michael@0 128 GrGLProgram* program = GrGLProgram::Create(fGpu, desc, colorStages, coverageStages);
michael@0 129 if (NULL == program) {
michael@0 130 return NULL;
michael@0 131 }
michael@0 132 int purgeIdx = 0;
michael@0 133 if (fCount < kMaxEntries) {
michael@0 134 entry = SkNEW(Entry);
michael@0 135 purgeIdx = fCount++;
michael@0 136 fEntries[purgeIdx] = entry;
michael@0 137 } else {
michael@0 138 SkASSERT(fCount == kMaxEntries);
michael@0 139 purgeIdx = 0;
michael@0 140 for (int i = 1; i < kMaxEntries; ++i) {
michael@0 141 if (fEntries[i]->fLRUStamp < fEntries[purgeIdx]->fLRUStamp) {
michael@0 142 purgeIdx = i;
michael@0 143 }
michael@0 144 }
michael@0 145 entry = fEntries[purgeIdx];
michael@0 146 int purgedHashIdx = entry->fProgram->getDesc().getChecksum() & ((1 << kHashBits) - 1);
michael@0 147 if (fHashTable[purgedHashIdx] == entry) {
michael@0 148 fHashTable[purgedHashIdx] = NULL;
michael@0 149 }
michael@0 150 }
michael@0 151 SkASSERT(fEntries[purgeIdx] == entry);
michael@0 152 entry->fProgram.reset(program);
michael@0 153 // We need to shift fEntries around so that the entry currently at purgeIdx is placed
michael@0 154 // just before the entry at ~entryIdx (in order to keep fEntries sorted by descriptor).
michael@0 155 entryIdx = ~entryIdx;
michael@0 156 if (entryIdx < purgeIdx) {
michael@0 157 // Let E and P be the entries at index entryIdx and purgeIdx, respectively.
michael@0 158 // If the entries array looks like this:
michael@0 159 // aaaaEbbbbbPccccc
michael@0 160 // we rearrange it to look like this:
michael@0 161 // aaaaPEbbbbbccccc
michael@0 162 size_t copySize = (purgeIdx - entryIdx) * sizeof(Entry*);
michael@0 163 memmove(fEntries + entryIdx + 1, fEntries + entryIdx, copySize);
michael@0 164 fEntries[entryIdx] = entry;
michael@0 165 } else if (purgeIdx < entryIdx) {
michael@0 166 // If the entries array looks like this:
michael@0 167 // aaaaPbbbbbEccccc
michael@0 168 // we rearrange it to look like this:
michael@0 169 // aaaabbbbbPEccccc
michael@0 170 size_t copySize = (entryIdx - purgeIdx - 1) * sizeof(Entry*);
michael@0 171 memmove(fEntries + purgeIdx, fEntries + purgeIdx + 1, copySize);
michael@0 172 fEntries[entryIdx - 1] = entry;
michael@0 173 }
michael@0 174 #ifdef SK_DEBUG
michael@0 175 SkASSERT(NULL != fEntries[0]->fProgram.get());
michael@0 176 for (int i = 0; i < fCount - 1; ++i) {
michael@0 177 SkASSERT(NULL != fEntries[i + 1]->fProgram.get());
michael@0 178 const GrGLProgramDesc& a = fEntries[i]->fProgram->getDesc();
michael@0 179 const GrGLProgramDesc& b = fEntries[i + 1]->fProgram->getDesc();
michael@0 180 SkASSERT(GrGLProgramDesc::Less(a, b));
michael@0 181 SkASSERT(!GrGLProgramDesc::Less(b, a));
michael@0 182 }
michael@0 183 #endif
michael@0 184 }
michael@0 185
michael@0 186 fHashTable[hashIdx] = entry;
michael@0 187 entry->fLRUStamp = fCurrLRUStamp;
michael@0 188
michael@0 189 if (SK_MaxU32 == fCurrLRUStamp) {
michael@0 190 // wrap around! just trash our LRU, one time hit.
michael@0 191 for (int i = 0; i < fCount; ++i) {
michael@0 192 fEntries[i]->fLRUStamp = 0;
michael@0 193 }
michael@0 194 }
michael@0 195 ++fCurrLRUStamp;
michael@0 196 return entry->fProgram;
michael@0 197 }
michael@0 198
michael@0 199 ////////////////////////////////////////////////////////////////////////////////
michael@0 200
michael@0 201 void GrGpuGL::abandonResources(){
michael@0 202 INHERITED::abandonResources();
michael@0 203 fProgramCache->abandon();
michael@0 204 fHWProgramID = 0;
michael@0 205 }
michael@0 206
michael@0 207 ////////////////////////////////////////////////////////////////////////////////
michael@0 208
michael@0 209 #define GL_CALL(X) GR_GL_CALL(this->glInterface(), X)
michael@0 210
michael@0 211 bool GrGpuGL::flushGraphicsState(DrawType type, const GrDeviceCoordTexture* dstCopy) {
michael@0 212 const GrDrawState& drawState = this->getDrawState();
michael@0 213
michael@0 214 // GrGpu::setupClipAndFlushState should have already checked this and bailed if not true.
michael@0 215 SkASSERT(NULL != drawState.getRenderTarget());
michael@0 216
michael@0 217 if (kStencilPath_DrawType == type) {
michael@0 218 const GrRenderTarget* rt = this->getDrawState().getRenderTarget();
michael@0 219 SkISize size;
michael@0 220 size.set(rt->width(), rt->height());
michael@0 221 this->setProjectionMatrix(drawState.getViewMatrix(), size, rt->origin());
michael@0 222 } else {
michael@0 223 this->flushMiscFixedFunctionState();
michael@0 224
michael@0 225 GrBlendCoeff srcCoeff;
michael@0 226 GrBlendCoeff dstCoeff;
michael@0 227 GrDrawState::BlendOptFlags blendOpts = drawState.getBlendOpts(false, &srcCoeff, &dstCoeff);
michael@0 228 if (GrDrawState::kSkipDraw_BlendOptFlag & blendOpts) {
michael@0 229 return false;
michael@0 230 }
michael@0 231
michael@0 232 SkSTArray<8, const GrEffectStage*, true> colorStages;
michael@0 233 SkSTArray<8, const GrEffectStage*, true> coverageStages;
michael@0 234 GrGLProgramDesc desc;
michael@0 235 GrGLProgramDesc::Build(this->getDrawState(),
michael@0 236 kDrawPoints_DrawType == type,
michael@0 237 blendOpts,
michael@0 238 srcCoeff,
michael@0 239 dstCoeff,
michael@0 240 this,
michael@0 241 dstCopy,
michael@0 242 &colorStages,
michael@0 243 &coverageStages,
michael@0 244 &desc);
michael@0 245
michael@0 246 fCurrentProgram.reset(fProgramCache->getProgram(desc,
michael@0 247 colorStages.begin(),
michael@0 248 coverageStages.begin()));
michael@0 249 if (NULL == fCurrentProgram.get()) {
michael@0 250 SkDEBUGFAIL("Failed to create program!");
michael@0 251 return false;
michael@0 252 }
michael@0 253
michael@0 254 SkASSERT(kDrawPath_DrawType != type || !fCurrentProgram->hasVertexShader());
michael@0 255
michael@0 256 fCurrentProgram.get()->ref();
michael@0 257
michael@0 258 GrGLuint programID = fCurrentProgram->programID();
michael@0 259 if (fHWProgramID != programID) {
michael@0 260 GL_CALL(UseProgram(programID));
michael@0 261 fHWProgramID = programID;
michael@0 262 }
michael@0 263
michael@0 264 fCurrentProgram->overrideBlend(&srcCoeff, &dstCoeff);
michael@0 265 this->flushBlend(kDrawLines_DrawType == type, srcCoeff, dstCoeff);
michael@0 266
michael@0 267 fCurrentProgram->setData(blendOpts,
michael@0 268 colorStages.begin(),
michael@0 269 coverageStages.begin(),
michael@0 270 dstCopy,
michael@0 271 &fSharedGLProgramState);
michael@0 272 }
michael@0 273 this->flushStencil(type);
michael@0 274 this->flushScissor();
michael@0 275 this->flushAAState(type);
michael@0 276
michael@0 277 SkIRect* devRect = NULL;
michael@0 278 SkIRect devClipBounds;
michael@0 279 if (drawState.isClipState()) {
michael@0 280 this->getClip()->getConservativeBounds(drawState.getRenderTarget(), &devClipBounds);
michael@0 281 devRect = &devClipBounds;
michael@0 282 }
michael@0 283 // This must come after textures are flushed because a texture may need
michael@0 284 // to be msaa-resolved (which will modify bound FBO state).
michael@0 285 this->flushRenderTarget(devRect);
michael@0 286
michael@0 287 return true;
michael@0 288 }
michael@0 289
michael@0 290 void GrGpuGL::setupGeometry(const DrawInfo& info, size_t* indexOffsetInBytes) {
michael@0 291
michael@0 292 GrGLsizei stride = static_cast<GrGLsizei>(this->getDrawState().getVertexSize());
michael@0 293
michael@0 294 size_t vertexOffsetInBytes = stride * info.startVertex();
michael@0 295
michael@0 296 const GeometryPoolState& geoPoolState = this->getGeomPoolState();
michael@0 297
michael@0 298 GrGLVertexBuffer* vbuf;
michael@0 299 switch (this->getGeomSrc().fVertexSrc) {
michael@0 300 case kBuffer_GeometrySrcType:
michael@0 301 vbuf = (GrGLVertexBuffer*) this->getGeomSrc().fVertexBuffer;
michael@0 302 break;
michael@0 303 case kArray_GeometrySrcType:
michael@0 304 case kReserved_GeometrySrcType:
michael@0 305 this->finalizeReservedVertices();
michael@0 306 vertexOffsetInBytes += geoPoolState.fPoolStartVertex * this->getGeomSrc().fVertexSize;
michael@0 307 vbuf = (GrGLVertexBuffer*) geoPoolState.fPoolVertexBuffer;
michael@0 308 break;
michael@0 309 default:
michael@0 310 vbuf = NULL; // suppress warning
michael@0 311 GrCrash("Unknown geometry src type!");
michael@0 312 }
michael@0 313
michael@0 314 SkASSERT(NULL != vbuf);
michael@0 315 SkASSERT(!vbuf->isLocked());
michael@0 316 vertexOffsetInBytes += vbuf->baseOffset();
michael@0 317
michael@0 318 GrGLIndexBuffer* ibuf = NULL;
michael@0 319 if (info.isIndexed()) {
michael@0 320 SkASSERT(NULL != indexOffsetInBytes);
michael@0 321
michael@0 322 switch (this->getGeomSrc().fIndexSrc) {
michael@0 323 case kBuffer_GeometrySrcType:
michael@0 324 *indexOffsetInBytes = 0;
michael@0 325 ibuf = (GrGLIndexBuffer*)this->getGeomSrc().fIndexBuffer;
michael@0 326 break;
michael@0 327 case kArray_GeometrySrcType:
michael@0 328 case kReserved_GeometrySrcType:
michael@0 329 this->finalizeReservedIndices();
michael@0 330 *indexOffsetInBytes = geoPoolState.fPoolStartIndex * sizeof(GrGLushort);
michael@0 331 ibuf = (GrGLIndexBuffer*) geoPoolState.fPoolIndexBuffer;
michael@0 332 break;
michael@0 333 default:
michael@0 334 ibuf = NULL; // suppress warning
michael@0 335 GrCrash("Unknown geometry src type!");
michael@0 336 }
michael@0 337
michael@0 338 SkASSERT(NULL != ibuf);
michael@0 339 SkASSERT(!ibuf->isLocked());
michael@0 340 *indexOffsetInBytes += ibuf->baseOffset();
michael@0 341 }
michael@0 342 GrGLAttribArrayState* attribState =
michael@0 343 fHWGeometryState.bindArrayAndBuffersToDraw(this, vbuf, ibuf);
michael@0 344
michael@0 345 if (!fCurrentProgram->hasVertexShader()) {
michael@0 346 int posIdx = this->getDrawState().positionAttributeIndex();
michael@0 347 const GrVertexAttrib* vertexAttrib = this->getDrawState().getVertexAttribs() + posIdx;
michael@0 348 GrVertexAttribType attribType = vertexAttrib->fType;
michael@0 349 SkASSERT(!GrGLAttribTypeToLayout(attribType).fNormalized);
michael@0 350 SkASSERT(GrGLAttribTypeToLayout(attribType).fCount == 2);
michael@0 351
michael@0 352 // Attrib at location 0 is defined to be bound to vertex in fixed-function pipe. Asserts
michael@0 353 // above should make sure position attribute goes to location 0 when below code is executed.
michael@0 354
michael@0 355 attribState->set(this,
michael@0 356 0,
michael@0 357 vbuf,
michael@0 358 GrGLAttribTypeToLayout(attribType).fCount,
michael@0 359 GrGLAttribTypeToLayout(attribType).fType,
michael@0 360 GrGLAttribTypeToLayout(attribType).fNormalized,
michael@0 361 stride,
michael@0 362 reinterpret_cast<GrGLvoid*>(
michael@0 363 vertexOffsetInBytes + vertexAttrib->fOffset));
michael@0 364 attribState->disableUnusedArrays(this, 1);
michael@0 365 } else {
michael@0 366 int vertexAttribCount = this->getDrawState().getVertexAttribCount();
michael@0 367 uint32_t usedAttribArraysMask = 0;
michael@0 368 const GrVertexAttrib* vertexAttrib = this->getDrawState().getVertexAttribs();
michael@0 369
michael@0 370 for (int vertexAttribIndex = 0; vertexAttribIndex < vertexAttribCount;
michael@0 371 ++vertexAttribIndex, ++vertexAttrib) {
michael@0 372
michael@0 373 usedAttribArraysMask |= (1 << vertexAttribIndex);
michael@0 374 GrVertexAttribType attribType = vertexAttrib->fType;
michael@0 375 attribState->set(this,
michael@0 376 vertexAttribIndex,
michael@0 377 vbuf,
michael@0 378 GrGLAttribTypeToLayout(attribType).fCount,
michael@0 379 GrGLAttribTypeToLayout(attribType).fType,
michael@0 380 GrGLAttribTypeToLayout(attribType).fNormalized,
michael@0 381 stride,
michael@0 382 reinterpret_cast<GrGLvoid*>(
michael@0 383 vertexOffsetInBytes + vertexAttrib->fOffset));
michael@0 384 }
michael@0 385 attribState->disableUnusedArrays(this, usedAttribArraysMask);
michael@0 386 }
michael@0 387 }

mercurial