1 
2 /*
3  * Copyright 2013 Google Inc.
4  *
5  * Use of this source code is governed by a BSD-style license that can be
6  * found in the LICENSE file.
7  */
8 
9 #include "GrTest.h"
10 
11 #include "GrGpuResourceCacheAccess.h"
12 #include "GrInOrderDrawBuffer.h"
13 #include "GrResourceCache.h"
14 #include "SkString.h"
15 
init(GrContext * ctx,GrDrawTarget * target)16 void GrTestTarget::init(GrContext* ctx, GrDrawTarget* target) {
17     SkASSERT(!fContext);
18 
19     fContext.reset(SkRef(ctx));
20     fDrawTarget.reset(SkRef(target));
21 }
22 
getTestTarget(GrTestTarget * tar)23 void GrContext::getTestTarget(GrTestTarget* tar) {
24     this->flush();
25     // We could create a proxy GrDrawTarget that passes through to fGpu until ~GrTextTarget() and
26     // then disconnects. This would help prevent test writers from mixing using the returned
27     // GrDrawTarget and regular drawing. We could also assert or fail in GrContext drawing methods
28     // until ~GrTestTarget().
29     tar->init(this, fDrawBuffer);
30 }
31 
32 ///////////////////////////////////////////////////////////////////////////////
33 
setMaxTextureSizeOverride(int maxTextureSizeOverride)34 void GrContext::setMaxTextureSizeOverride(int maxTextureSizeOverride) {
35     fMaxTextureSizeOverride = maxTextureSizeOverride;
36 }
37 
purgeAllUnlockedResources()38 void GrContext::purgeAllUnlockedResources() {
39     fResourceCache->purgeAllUnlocked();
40 }
41 
dumpCacheStats(SkString * out) const42 void GrContext::dumpCacheStats(SkString* out) const {
43 #if GR_CACHE_STATS
44     fResourceCache->dumpStats(out);
45 #endif
46 }
47 
printCacheStats() const48 void GrContext::printCacheStats() const {
49     SkString out;
50     this->dumpCacheStats(&out);
51     SkDebugf("%s", out.c_str());
52 }
53 
dumpGpuStats(SkString * out) const54 void GrContext::dumpGpuStats(SkString* out) const {
55 #if GR_GPU_STATS
56     return fGpu->stats()->dump(out);
57 #endif
58 }
59 
printGpuStats() const60 void GrContext::printGpuStats() const {
61     SkString out;
62     this->dumpGpuStats(&out);
63     SkDebugf("%s", out.c_str());
64 }
65 
66 #if GR_GPU_STATS
dump(SkString * out)67 void GrGpu::Stats::dump(SkString* out) {
68     out->appendf("Render Target Binds: %d\n", fRenderTargetBinds);
69     out->appendf("Shader Compilations: %d\n", fShaderCompilations);
70     out->appendf("Textures Created: %d\n", fTextureCreates);
71     out->appendf("Texture Uploads: %d\n", fTextureUploads);
72     out->appendf("Stencil Buffer Creates: %d\n", fStencilAttachmentCreates);
73 }
74 #endif
75 
76 #if GR_CACHE_STATS
dumpStats(SkString * out) const77 void GrResourceCache::dumpStats(SkString* out) const {
78     this->validate();
79 
80     int locked = fNonpurgeableResources.count();
81 
82     struct Stats {
83         int fScratch;
84         int fWrapped;
85         size_t fUnbudgetedSize;
86 
87         Stats() : fScratch(0), fWrapped(0), fUnbudgetedSize(0) {}
88 
89         void update(GrGpuResource* resource) {
90             if (resource->cacheAccess().isScratch()) {
91                 ++fScratch;
92             }
93             if (resource->cacheAccess().isWrapped()) {
94                 ++fWrapped;
95             }
96             if (!resource->resourcePriv().isBudgeted()) {
97                 fUnbudgetedSize += resource->gpuMemorySize();
98             }
99         }
100     };
101 
102     Stats stats;
103 
104     for (int i = 0; i < fNonpurgeableResources.count(); ++i) {
105         stats.update(fNonpurgeableResources[i]);
106     }
107     for (int i = 0; i < fPurgeableQueue.count(); ++i) {
108         stats.update(fPurgeableQueue.at(i));
109     }
110 
111     float countUtilization = (100.f * fBudgetedCount) / fMaxCount;
112     float byteUtilization = (100.f * fBudgetedBytes) / fMaxBytes;
113 
114     out->appendf("Budget: %d items %d bytes\n", fMaxCount, (int)fMaxBytes);
115     out->appendf("\t\tEntry Count: current %d"
116                  " (%d budgeted, %d wrapped, %d locked, %d scratch %.2g%% full), high %d\n",
117                  this->getResourceCount(), fBudgetedCount, stats.fWrapped, locked, stats.fScratch,
118                  countUtilization, fHighWaterCount);
119     out->appendf("\t\tEntry Bytes: current %d (budgeted %d, %.2g%% full, %d unbudgeted) high %d\n",
120                  SkToInt(fBytes), SkToInt(fBudgetedBytes), byteUtilization,
121                  SkToInt(stats.fUnbudgetedSize), SkToInt(fHighWaterBytes));
122 }
123 
124 #endif
125 
126 ///////////////////////////////////////////////////////////////////////////////
127 
changeTimestamp(uint32_t newTimestamp)128 void GrResourceCache::changeTimestamp(uint32_t newTimestamp) { fTimestamp = newTimestamp; }
129 
130 ///////////////////////////////////////////////////////////////////////////////
131 // Code for the mock context. It's built on a mock GrGpu class that does nothing.
132 ////
133 
134 #include "GrInOrderDrawBuffer.h"
135 #include "GrGpu.h"
136 
137 class GrPipeline;
138 
139 class MockGpu : public GrGpu {
140 public:
MockGpu(GrContext * context)141     MockGpu(GrContext* context) : INHERITED(context) { fCaps.reset(SkNEW(GrDrawTargetCaps)); }
~MockGpu()142     ~MockGpu() override {}
canWriteTexturePixels(const GrTexture *,GrPixelConfig srcConfig) const143     bool canWriteTexturePixels(const GrTexture*, GrPixelConfig srcConfig) const override {
144         return true;
145     }
146 
readPixelsWillPayForYFlip(GrRenderTarget * renderTarget,int left,int top,int width,int height,GrPixelConfig config,size_t rowBytes) const147     bool readPixelsWillPayForYFlip(GrRenderTarget* renderTarget,
148                                    int left, int top,
149                                    int width, int height,
150                                    GrPixelConfig config,
151                                    size_t rowBytes) const override { return false; }
buildProgramDesc(GrProgramDesc *,const GrPrimitiveProcessor &,const GrPipeline &,const GrBatchTracker &) const152     void buildProgramDesc(GrProgramDesc*,const GrPrimitiveProcessor&,
153                           const GrPipeline&,
154                           const GrBatchTracker&) const override {}
155 
discard(GrRenderTarget *)156     void discard(GrRenderTarget*) override {}
157 
canCopySurface(const GrSurface * dst,const GrSurface * src,const SkIRect & srcRect,const SkIPoint & dstPoint)158     bool canCopySurface(const GrSurface* dst,
159                         const GrSurface* src,
160                         const SkIRect& srcRect,
161                         const SkIPoint& dstPoint) override { return false; };
162 
copySurface(GrSurface * dst,GrSurface * src,const SkIRect & srcRect,const SkIPoint & dstPoint)163     bool copySurface(GrSurface* dst,
164                      GrSurface* src,
165                      const SkIRect& srcRect,
166                      const SkIPoint& dstPoint) override { return false; };
167 
initCopySurfaceDstDesc(const GrSurface * src,GrSurfaceDesc * desc)168     bool initCopySurfaceDstDesc(const GrSurface* src, GrSurfaceDesc* desc) override {
169         return false;
170     }
171 
xferBarrier(GrRenderTarget *,GrXferBarrierType)172     void xferBarrier(GrRenderTarget*, GrXferBarrierType) override {}
173 
174 private:
onResetContext(uint32_t resetBits)175     void onResetContext(uint32_t resetBits) override {}
176 
onCreateTexture(const GrSurfaceDesc & desc,GrGpuResource::LifeCycle lifeCycle,const void * srcData,size_t rowBytes)177     GrTexture* onCreateTexture(const GrSurfaceDesc& desc, GrGpuResource::LifeCycle lifeCycle,
178                                const void* srcData, size_t rowBytes) override {
179         return NULL;
180     }
181 
onCreateCompressedTexture(const GrSurfaceDesc & desc,GrGpuResource::LifeCycle,const void * srcData)182     GrTexture* onCreateCompressedTexture(const GrSurfaceDesc& desc, GrGpuResource::LifeCycle,
183                                          const void* srcData) override {
184         return NULL;
185     }
186 
onWrapBackendTexture(const GrBackendTextureDesc &)187     GrTexture* onWrapBackendTexture(const GrBackendTextureDesc&) override { return NULL; }
188 
onWrapBackendRenderTarget(const GrBackendRenderTargetDesc &)189     GrRenderTarget* onWrapBackendRenderTarget(const GrBackendRenderTargetDesc&) override {
190         return NULL;
191     }
192 
onCreateVertexBuffer(size_t size,bool dynamic)193     GrVertexBuffer* onCreateVertexBuffer(size_t size, bool dynamic) override { return NULL; }
194 
onCreateIndexBuffer(size_t size,bool dynamic)195     GrIndexBuffer* onCreateIndexBuffer(size_t size, bool dynamic) override { return NULL; }
196 
onClear(GrRenderTarget *,const SkIRect * rect,GrColor color,bool canIgnoreRect)197     void onClear(GrRenderTarget*, const SkIRect* rect, GrColor color,
198                          bool canIgnoreRect) override {}
199 
onClearStencilClip(GrRenderTarget *,const SkIRect & rect,bool insideClip)200     void onClearStencilClip(GrRenderTarget*, const SkIRect& rect, bool insideClip) override {}
201 
onDraw(const DrawArgs &,const GrNonInstancedVertices &)202     void onDraw(const DrawArgs&, const GrNonInstancedVertices&) override {}
203 
onStencilPath(const GrPath * path,const StencilPathState & state)204     void onStencilPath(const GrPath* path, const StencilPathState& state) override {}
205 
onDrawPath(const DrawArgs &,const GrPath *,const GrStencilSettings &)206     void onDrawPath(const DrawArgs&, const GrPath*, const GrStencilSettings&) override {}
207 
onDrawPaths(const DrawArgs &,const GrPathRange *,const void * indices,GrDrawTarget::PathIndexType,const float transformValues[],GrDrawTarget::PathTransformType,int count,const GrStencilSettings &)208     void onDrawPaths(const DrawArgs&,
209                      const GrPathRange*,
210                      const void* indices,
211                      GrDrawTarget::PathIndexType,
212                      const float transformValues[],
213                      GrDrawTarget::PathTransformType,
214                      int count,
215                      const GrStencilSettings&) override {}
216 
onReadPixels(GrRenderTarget * target,int left,int top,int width,int height,GrPixelConfig,void * buffer,size_t rowBytes)217     bool onReadPixels(GrRenderTarget* target,
218                       int left, int top, int width, int height,
219                       GrPixelConfig,
220                       void* buffer,
221                       size_t rowBytes) override {
222         return false;
223     }
224 
onWriteTexturePixels(GrTexture * texture,int left,int top,int width,int height,GrPixelConfig config,const void * buffer,size_t rowBytes)225     bool onWriteTexturePixels(GrTexture* texture,
226                               int left, int top, int width, int height,
227                               GrPixelConfig config, const void* buffer,
228                               size_t rowBytes) override {
229         return false;
230     }
231 
onResolveRenderTarget(GrRenderTarget * target)232     void onResolveRenderTarget(GrRenderTarget* target) override { return; }
233 
createStencilAttachmentForRenderTarget(GrRenderTarget *,int width,int height)234     bool createStencilAttachmentForRenderTarget(GrRenderTarget*, int width, int height) override {
235         return false;
236     }
237 
attachStencilAttachmentToRenderTarget(GrStencilAttachment *,GrRenderTarget *)238     bool attachStencilAttachmentToRenderTarget(GrStencilAttachment*, GrRenderTarget*) override {
239         return false;
240     }
241 
clearStencil(GrRenderTarget * target)242     void clearStencil(GrRenderTarget* target) override  {}
243 
didAddGpuTraceMarker()244     void didAddGpuTraceMarker() override {}
245 
didRemoveGpuTraceMarker()246     void didRemoveGpuTraceMarker() override {}
247 
248     typedef GrGpu INHERITED;
249 };
250 
CreateMockContext()251 GrContext* GrContext::CreateMockContext() {
252     GrContext* context = SkNEW_ARGS(GrContext, (Options()));
253 
254     context->initMockContext();
255     return context;
256 }
257 
initMockContext()258 void GrContext::initMockContext() {
259     SkASSERT(NULL == fGpu);
260     fGpu = SkNEW_ARGS(MockGpu, (this));
261     SkASSERT(fGpu);
262     this->initCommon();
263 
264     // We delete these because we want to test the cache starting with zero resources. Also, none of
265     // these objects are required for any of tests that use this context. TODO: make stop allocating
266     // resources in the buffer pools.
267     SkDELETE(fDrawBuffer);
268     fDrawBuffer = NULL;
269 
270 }
271