1 /*
2 * Copyright 2011 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include "GrGLGpu.h"
9
10 #include "builders/GrGLProgramBuilder.h"
11 #include "GrProcessor.h"
12 #include "GrProgramDesc.h"
13 #include "GrGLPathRendering.h"
14 #include "glsl/GrGLSLFragmentProcessor.h"
15 #include "glsl/GrGLSLProgramDataManager.h"
16 #include "SkTSearch.h"
17
18 #ifdef PROGRAM_CACHE_STATS
19 // Display program cache usage
20 static const bool c_DisplayCache{false};
21 #endif
22
23 typedef GrGLSLProgramDataManager::UniformHandle UniformHandle;
24
25 struct GrGLGpu::ProgramCache::Entry {
EntryGrGLGpu::ProgramCache::Entry26 Entry(sk_sp<GrGLProgram> program) : fProgram(std::move(program)) {}
27
28 sk_sp<GrGLProgram> fProgram;
29 };
30
ProgramCache(GrGLGpu * gpu)31 GrGLGpu::ProgramCache::ProgramCache(GrGLGpu* gpu)
32 : fMap(kMaxEntries)
33 , fGpu(gpu)
34 #ifdef PROGRAM_CACHE_STATS
35 , fTotalRequests(0)
36 , fCacheMisses(0)
37 , fHashMisses(0)
38 #endif
39 {}
40
~ProgramCache()41 GrGLGpu::ProgramCache::~ProgramCache() {
42 // dump stats
43 #ifdef PROGRAM_CACHE_STATS
44 if (c_DisplayCache) {
45 SkDebugf("--- Program Cache ---\n");
46 SkDebugf("Total requests: %d\n", fTotalRequests);
47 SkDebugf("Cache misses: %d\n", fCacheMisses);
48 SkDebugf("Cache miss %%: %f\n", (fTotalRequests > 0) ?
49 100.f * fCacheMisses / fTotalRequests :
50 0.f);
51 int cacheHits = fTotalRequests - fCacheMisses;
52 SkDebugf("Hash miss %%: %f\n", (cacheHits > 0) ? 100.f * fHashMisses / cacheHits : 0.f);
53 SkDebugf("---------------------\n");
54 }
55 #endif
56 }
57
abandon()58 void GrGLGpu::ProgramCache::abandon() {
59 #ifdef PROGRAM_CACHE_STATS
60 fTotalRequests = 0;
61 fCacheMisses = 0;
62 fHashMisses = 0;
63 #endif
64
65 fMap.foreach([](std::unique_ptr<Entry>* e) {
66 (*e)->fProgram->abandon();
67 });
68 fMap.reset();
69 }
70
refProgram(GrGLGpu * gpu,GrRenderTarget * renderTarget,GrSurfaceOrigin origin,const GrPrimitiveProcessor & primProc,const GrTextureProxy * const primProcProxies[],const GrPipeline & pipeline,bool isPoints)71 GrGLProgram* GrGLGpu::ProgramCache::refProgram(GrGLGpu* gpu,
72 GrRenderTarget* renderTarget,
73 GrSurfaceOrigin origin,
74 const GrPrimitiveProcessor& primProc,
75 const GrTextureProxy* const primProcProxies[],
76 const GrPipeline& pipeline,
77 bool isPoints) {
78 #ifdef PROGRAM_CACHE_STATS
79 ++fTotalRequests;
80 #endif
81
82 // Get GrGLProgramDesc
83 GrProgramDesc desc;
84 if (!GrProgramDesc::Build(&desc, renderTarget, primProc, isPoints, pipeline, gpu)) {
85 GrCapsDebugf(gpu->caps(), "Failed to gl program descriptor!\n");
86 return nullptr;
87 }
88 std::unique_ptr<Entry>* entry = fMap.find(desc);
89 if (!entry) {
90 // Didn't find an origin-independent version, check with the specific origin
91 desc.setSurfaceOriginKey(GrGLSLFragmentShaderBuilder::KeyForSurfaceOrigin(origin));
92 entry = fMap.find(desc);
93 }
94 if (!entry) {
95 // We have a cache miss
96 #ifdef PROGRAM_CACHE_STATS
97 ++fCacheMisses;
98 #endif
99 GrGLProgram* program = GrGLProgramBuilder::CreateProgram(renderTarget, origin,
100 primProc, primProcProxies,
101 pipeline, &desc, fGpu);
102 if (nullptr == program) {
103 return nullptr;
104 }
105 entry = fMap.insert(desc, std::unique_ptr<Entry>(new Entry(sk_sp<GrGLProgram>(program))));
106 }
107
108 return SkRef((*entry)->fProgram.get());
109 }
110