1 
2 /*
3  * Copyright 2010 Google Inc.
4  *
5  * Use of this source code is governed by a BSD-style license that can be
6  * found in the LICENSE file.
7  */
8 
9 
10 #include "GrGpu.h"
11 
12 #include "GrContext.h"
13 #include "GrDrawTargetCaps.h"
14 #include "GrGpuResourcePriv.h"
15 #include "GrIndexBuffer.h"
16 #include "GrResourceCache.h"
17 #include "GrRenderTargetPriv.h"
18 #include "GrStencilAttachment.h"
19 #include "GrVertexBuffer.h"
20 #include "GrVertices.h"
21 
operator =(const GrVertices & di)22 GrVertices& GrVertices::operator =(const GrVertices& di) {
23     fPrimitiveType  = di.fPrimitiveType;
24     fStartVertex    = di.fStartVertex;
25     fStartIndex     = di.fStartIndex;
26     fVertexCount    = di.fVertexCount;
27     fIndexCount     = di.fIndexCount;
28 
29     fInstanceCount          = di.fInstanceCount;
30     fVerticesPerInstance    = di.fVerticesPerInstance;
31     fIndicesPerInstance     = di.fIndicesPerInstance;
32     fMaxInstancesPerDraw    = di.fMaxInstancesPerDraw;
33 
34     fVertexBuffer.reset(di.vertexBuffer());
35     fIndexBuffer.reset(di.indexBuffer());
36 
37     return *this;
38 }
39 
40 ////////////////////////////////////////////////////////////////////////////////
41 
GrGpu(GrContext * context)42 GrGpu::GrGpu(GrContext* context)
43     : fResetTimestamp(kExpiredTimestamp+1)
44     , fResetBits(kAll_GrBackendState)
45     , fGpuTraceMarkerCount(0)
46     , fContext(context) {
47 }
48 
~GrGpu()49 GrGpu::~GrGpu() {}
50 
contextAbandoned()51 void GrGpu::contextAbandoned() {}
52 
53 ////////////////////////////////////////////////////////////////////////////////
54 
resolve_origin(GrSurfaceOrigin origin,bool renderTarget)55 static GrSurfaceOrigin resolve_origin(GrSurfaceOrigin origin, bool renderTarget) {
56     // By default, GrRenderTargets are GL's normal orientation so that they
57     // can be drawn to by the outside world without the client having
58     // to render upside down.
59     if (kDefault_GrSurfaceOrigin == origin) {
60         return renderTarget ? kBottomLeft_GrSurfaceOrigin : kTopLeft_GrSurfaceOrigin;
61     } else {
62         return origin;
63     }
64 }
65 
createTexture(const GrSurfaceDesc & origDesc,bool budgeted,const void * srcData,size_t rowBytes)66 GrTexture* GrGpu::createTexture(const GrSurfaceDesc& origDesc, bool budgeted,
67                                 const void* srcData, size_t rowBytes) {
68     GrSurfaceDesc desc = origDesc;
69 
70     if (!this->caps()->isConfigTexturable(desc.fConfig)) {
71         return NULL;
72     }
73 
74     bool isRT = SkToBool(desc.fFlags & kRenderTarget_GrSurfaceFlag);
75     if (isRT && !this->caps()->isConfigRenderable(desc.fConfig, desc.fSampleCnt > 0)) {
76         return NULL;
77     }
78 
79     // We currently not support multisampled textures
80     if (!isRT && desc.fSampleCnt > 0) {
81         return NULL;
82     }
83 
84     GrTexture *tex = NULL;
85 
86     if (isRT) {
87         int maxRTSize = this->caps()->maxRenderTargetSize();
88         if (desc.fWidth > maxRTSize || desc.fHeight > maxRTSize) {
89             return NULL;
90         }
91     } else {
92         int maxSize = this->caps()->maxTextureSize();
93         if (desc.fWidth > maxSize || desc.fHeight > maxSize) {
94             return NULL;
95         }
96     }
97 
98     GrGpuResource::LifeCycle lifeCycle = budgeted ? GrGpuResource::kCached_LifeCycle :
99                                                     GrGpuResource::kUncached_LifeCycle;
100 
101     desc.fSampleCnt = SkTMin(desc.fSampleCnt, this->caps()->maxSampleCount());
102     // Attempt to catch un- or wrongly initialized sample counts;
103     SkASSERT(desc.fSampleCnt >= 0 && desc.fSampleCnt <= 64);
104 
105     desc.fOrigin = resolve_origin(desc.fOrigin, isRT);
106 
107     if (GrPixelConfigIsCompressed(desc.fConfig)) {
108         // We shouldn't be rendering into this
109         SkASSERT(!isRT);
110         SkASSERT(0 == desc.fSampleCnt);
111 
112         if (!this->caps()->npotTextureTileSupport() &&
113             (!SkIsPow2(desc.fWidth) || !SkIsPow2(desc.fHeight))) {
114             return NULL;
115         }
116 
117         this->handleDirtyContext();
118         tex = this->onCreateCompressedTexture(desc, lifeCycle, srcData);
119     } else {
120         this->handleDirtyContext();
121         tex = this->onCreateTexture(desc, lifeCycle, srcData, rowBytes);
122     }
123     if (!this->caps()->reuseScratchTextures() && !isRT) {
124         tex->resourcePriv().removeScratchKey();
125     }
126     if (tex) {
127         fStats.incTextureCreates();
128         if (srcData) {
129             fStats.incTextureUploads();
130         }
131     }
132     return tex;
133 }
134 
attachStencilAttachmentToRenderTarget(GrRenderTarget * rt)135 bool GrGpu::attachStencilAttachmentToRenderTarget(GrRenderTarget* rt) {
136     SkASSERT(NULL == rt->renderTargetPriv().getStencilAttachment());
137     GrUniqueKey sbKey;
138 
139     int width = rt->width();
140     int height = rt->height();
141 #if 0
142     if (this->caps()->oversizedStencilSupport()) {
143         width  = SkNextPow2(width);
144         height = SkNextPow2(height);
145     }
146 #endif
147 
148     GrStencilAttachment::ComputeSharedStencilAttachmentKey(width, height, rt->numSamples(), &sbKey);
149     SkAutoTUnref<GrStencilAttachment> sb(static_cast<GrStencilAttachment*>(
150         this->getContext()->getResourceCache()->findAndRefUniqueResource(sbKey)));
151     if (sb) {
152         if (this->attachStencilAttachmentToRenderTarget(sb, rt)) {
153             rt->renderTargetPriv().didAttachStencilAttachment(sb);
154             return true;
155         }
156         return false;
157     }
158     if (this->createStencilAttachmentForRenderTarget(rt, width, height)) {
159         // Right now we're clearing the stencil buffer here after it is
160         // attached to an RT for the first time. When we start matching
161         // stencil buffers with smaller color targets this will no longer
162         // be correct because it won't be guaranteed to clear the entire
163         // sb.
164         // We used to clear down in the GL subclass using a special purpose
165         // FBO. But iOS doesn't allow a stencil-only FBO. It reports unsupported
166         // FBO status.
167         this->clearStencil(rt);
168         GrStencilAttachment* sb = rt->renderTargetPriv().getStencilAttachment();
169         sb->resourcePriv().setUniqueKey(sbKey);
170         return true;
171     } else {
172         return false;
173     }
174 }
175 
wrapBackendTexture(const GrBackendTextureDesc & desc)176 GrTexture* GrGpu::wrapBackendTexture(const GrBackendTextureDesc& desc) {
177     this->handleDirtyContext();
178     GrTexture* tex = this->onWrapBackendTexture(desc);
179     if (NULL == tex) {
180         return NULL;
181     }
182     // TODO: defer this and attach dynamically
183     GrRenderTarget* tgt = tex->asRenderTarget();
184     if (tgt && !this->attachStencilAttachmentToRenderTarget(tgt)) {
185         tex->unref();
186         return NULL;
187     } else {
188         return tex;
189     }
190 }
191 
wrapBackendRenderTarget(const GrBackendRenderTargetDesc & desc)192 GrRenderTarget* GrGpu::wrapBackendRenderTarget(const GrBackendRenderTargetDesc& desc) {
193     this->handleDirtyContext();
194     return this->onWrapBackendRenderTarget(desc);
195 }
196 
createVertexBuffer(size_t size,bool dynamic)197 GrVertexBuffer* GrGpu::createVertexBuffer(size_t size, bool dynamic) {
198     this->handleDirtyContext();
199     return this->onCreateVertexBuffer(size, dynamic);
200 }
201 
createIndexBuffer(size_t size,bool dynamic)202 GrIndexBuffer* GrGpu::createIndexBuffer(size_t size, bool dynamic) {
203     this->handleDirtyContext();
204     return this->onCreateIndexBuffer(size, dynamic);
205 }
206 
clear(const SkIRect * rect,GrColor color,bool canIgnoreRect,GrRenderTarget * renderTarget)207 void GrGpu::clear(const SkIRect* rect,
208                   GrColor color,
209                   bool canIgnoreRect,
210                   GrRenderTarget* renderTarget) {
211     SkASSERT(renderTarget);
212     this->handleDirtyContext();
213     this->onClear(renderTarget, rect, color, canIgnoreRect);
214 }
215 
clearStencilClip(const SkIRect & rect,bool insideClip,GrRenderTarget * renderTarget)216 void GrGpu::clearStencilClip(const SkIRect& rect,
217                              bool insideClip,
218                              GrRenderTarget* renderTarget) {
219     SkASSERT(renderTarget);
220     this->handleDirtyContext();
221     this->onClearStencilClip(renderTarget, rect, insideClip);
222 }
223 
readPixels(GrRenderTarget * target,int left,int top,int width,int height,GrPixelConfig config,void * buffer,size_t rowBytes)224 bool GrGpu::readPixels(GrRenderTarget* target,
225                        int left, int top, int width, int height,
226                        GrPixelConfig config, void* buffer,
227                        size_t rowBytes) {
228     this->handleDirtyContext();
229     return this->onReadPixels(target, left, top, width, height,
230                               config, buffer, rowBytes);
231 }
232 
writeTexturePixels(GrTexture * texture,int left,int top,int width,int height,GrPixelConfig config,const void * buffer,size_t rowBytes)233 bool GrGpu::writeTexturePixels(GrTexture* texture,
234                                int left, int top, int width, int height,
235                                GrPixelConfig config, const void* buffer,
236                                size_t rowBytes) {
237     this->handleDirtyContext();
238     if (this->onWriteTexturePixels(texture, left, top, width, height,
239                                    config, buffer, rowBytes)) {
240         fStats.incTextureUploads();
241         return true;
242     }
243     return false;
244 }
245 
resolveRenderTarget(GrRenderTarget * target)246 void GrGpu::resolveRenderTarget(GrRenderTarget* target) {
247     SkASSERT(target);
248     this->handleDirtyContext();
249     this->onResolveRenderTarget(target);
250 }
251 
252 typedef GrTraceMarkerSet::Iter TMIter;
saveActiveTraceMarkers()253 void GrGpu::saveActiveTraceMarkers() {
254     if (this->caps()->gpuTracingSupport()) {
255         SkASSERT(0 == fStoredTraceMarkers.count());
256         fStoredTraceMarkers.addSet(fActiveTraceMarkers);
257         for (TMIter iter = fStoredTraceMarkers.begin(); iter != fStoredTraceMarkers.end(); ++iter) {
258             this->removeGpuTraceMarker(&(*iter));
259         }
260     }
261 }
262 
restoreActiveTraceMarkers()263 void GrGpu::restoreActiveTraceMarkers() {
264     if (this->caps()->gpuTracingSupport()) {
265         SkASSERT(0 == fActiveTraceMarkers.count());
266         for (TMIter iter = fStoredTraceMarkers.begin(); iter != fStoredTraceMarkers.end(); ++iter) {
267             this->addGpuTraceMarker(&(*iter));
268         }
269         for (TMIter iter = fActiveTraceMarkers.begin(); iter != fActiveTraceMarkers.end(); ++iter) {
270             this->fStoredTraceMarkers.remove(*iter);
271         }
272     }
273 }
274 
addGpuTraceMarker(const GrGpuTraceMarker * marker)275 void GrGpu::addGpuTraceMarker(const GrGpuTraceMarker* marker) {
276     if (this->caps()->gpuTracingSupport()) {
277         SkASSERT(fGpuTraceMarkerCount >= 0);
278         this->fActiveTraceMarkers.add(*marker);
279         this->didAddGpuTraceMarker();
280         ++fGpuTraceMarkerCount;
281     }
282 }
283 
removeGpuTraceMarker(const GrGpuTraceMarker * marker)284 void GrGpu::removeGpuTraceMarker(const GrGpuTraceMarker* marker) {
285     if (this->caps()->gpuTracingSupport()) {
286         SkASSERT(fGpuTraceMarkerCount >= 1);
287         this->fActiveTraceMarkers.remove(*marker);
288         this->didRemoveGpuTraceMarker();
289         --fGpuTraceMarkerCount;
290     }
291 }
292 
293 ////////////////////////////////////////////////////////////////////////////////
294 
draw(const DrawArgs & args,const GrVertices & vertices)295 void GrGpu::draw(const DrawArgs& args, const GrVertices& vertices) {
296     this->handleDirtyContext();
297     GrVertices::Iterator iter;
298     const GrNonInstancedVertices* verts = iter.init(vertices);
299     do {
300         this->onDraw(args, *verts);
301     } while ((verts = iter.next()));
302 }
303 
stencilPath(const GrPath * path,const StencilPathState & state)304 void GrGpu::stencilPath(const GrPath* path, const StencilPathState& state) {
305     this->handleDirtyContext();
306     this->onStencilPath(path, state);
307 }
308 
drawPath(const DrawArgs & args,const GrPath * path,const GrStencilSettings & stencilSettings)309 void GrGpu::drawPath(const DrawArgs& args,
310                      const GrPath* path,
311                      const GrStencilSettings& stencilSettings) {
312     this->handleDirtyContext();
313     this->onDrawPath(args, path, stencilSettings);
314 }
315 
drawPaths(const DrawArgs & args,const GrPathRange * pathRange,const void * indices,GrDrawTarget::PathIndexType indexType,const float transformValues[],GrDrawTarget::PathTransformType transformType,int count,const GrStencilSettings & stencilSettings)316 void GrGpu::drawPaths(const DrawArgs& args,
317                       const GrPathRange* pathRange,
318                       const void* indices,
319                       GrDrawTarget::PathIndexType indexType,
320                       const float transformValues[],
321                       GrDrawTarget::PathTransformType transformType,
322                       int count,
323                       const GrStencilSettings& stencilSettings) {
324     this->handleDirtyContext();
325     pathRange->willDrawPaths(indices, indexType, count);
326     this->onDrawPaths(args, pathRange, indices, indexType, transformValues,
327                       transformType, count, stencilSettings);
328 }
329