• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2010 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 
9 #include "GrGpu.h"
10 
11 #include "GrCaps.h"
12 #include "GrContext.h"
13 #include "GrGpuResourcePriv.h"
14 #include "GrIndexBuffer.h"
15 #include "GrPathRendering.h"
16 #include "GrPipeline.h"
17 #include "GrResourceCache.h"
18 #include "GrResourceProvider.h"
19 #include "GrRenderTargetPriv.h"
20 #include "GrStencilAttachment.h"
21 #include "GrSurfacePriv.h"
22 #include "GrTransferBuffer.h"
23 #include "GrVertexBuffer.h"
24 #include "GrVertices.h"
25 
operator =(const GrVertices & di)26 GrVertices& GrVertices::operator =(const GrVertices& di) {
27     fPrimitiveType  = di.fPrimitiveType;
28     fStartVertex    = di.fStartVertex;
29     fStartIndex     = di.fStartIndex;
30     fVertexCount    = di.fVertexCount;
31     fIndexCount     = di.fIndexCount;
32 
33     fInstanceCount          = di.fInstanceCount;
34     fVerticesPerInstance    = di.fVerticesPerInstance;
35     fIndicesPerInstance     = di.fIndicesPerInstance;
36     fMaxInstancesPerDraw    = di.fMaxInstancesPerDraw;
37 
38     fVertexBuffer.reset(di.vertexBuffer());
39     fIndexBuffer.reset(di.indexBuffer());
40 
41     return *this;
42 }
43 
44 ////////////////////////////////////////////////////////////////////////////////
45 
GrGpu(GrContext * context)46 GrGpu::GrGpu(GrContext* context)
47     : fResetTimestamp(kExpiredTimestamp+1)
48     , fResetBits(kAll_GrBackendState)
49     , fContext(context) {
50 }
51 
~GrGpu()52 GrGpu::~GrGpu() {}
53 
contextAbandoned()54 void GrGpu::contextAbandoned() {}
55 
56 ////////////////////////////////////////////////////////////////////////////////
57 
makeCopyForTextureParams(int width,int height,const GrTextureParams & textureParams,GrTextureProducer::CopyParams * copyParams) const58 bool GrGpu::makeCopyForTextureParams(int width, int height, const GrTextureParams& textureParams,
59                                      GrTextureProducer::CopyParams* copyParams) const {
60     const GrCaps& caps = *this->caps();
61     if (textureParams.isTiled() && !caps.npotTextureTileSupport() &&
62         (!SkIsPow2(width) || !SkIsPow2(height))) {
63         copyParams->fWidth = GrNextPow2(width);
64         copyParams->fHeight = GrNextPow2(height);
65         switch (textureParams.filterMode()) {
66             case GrTextureParams::kNone_FilterMode:
67                 copyParams->fFilter = GrTextureParams::kNone_FilterMode;
68                 break;
69             case GrTextureParams::kBilerp_FilterMode:
70             case GrTextureParams::kMipMap_FilterMode:
71                 // We are only ever scaling up so no reason to ever indicate kMipMap.
72                 copyParams->fFilter = GrTextureParams::kBilerp_FilterMode;
73                 break;
74         }
75         return true;
76     }
77     return false;
78 }
79 
resolve_origin(GrSurfaceOrigin origin,bool renderTarget)80 static GrSurfaceOrigin resolve_origin(GrSurfaceOrigin origin, bool renderTarget) {
81     // By default, GrRenderTargets are GL's normal orientation so that they
82     // can be drawn to by the outside world without the client having
83     // to render upside down.
84     if (kDefault_GrSurfaceOrigin == origin) {
85         return renderTarget ? kBottomLeft_GrSurfaceOrigin : kTopLeft_GrSurfaceOrigin;
86     } else {
87         return origin;
88     }
89 }
90 
createTexture(const GrSurfaceDesc & origDesc,SkBudgeted budgeted,const void * srcData,size_t rowBytes)91 GrTexture* GrGpu::createTexture(const GrSurfaceDesc& origDesc, SkBudgeted budgeted,
92                                 const void* srcData, size_t rowBytes) {
93     GrSurfaceDesc desc = origDesc;
94 
95     if (!this->caps()->isConfigTexturable(desc.fConfig)) {
96         return nullptr;
97     }
98 
99     bool isRT = SkToBool(desc.fFlags & kRenderTarget_GrSurfaceFlag);
100     if (isRT && !this->caps()->isConfigRenderable(desc.fConfig, desc.fSampleCnt > 0)) {
101         return nullptr;
102     }
103 
104     // We currently do not support multisampled textures
105     if (!isRT && desc.fSampleCnt > 0) {
106         return nullptr;
107     }
108 
109     GrTexture *tex = nullptr;
110 
111     if (isRT) {
112         int maxRTSize = this->caps()->maxRenderTargetSize();
113         if (desc.fWidth > maxRTSize || desc.fHeight > maxRTSize) {
114             return nullptr;
115         }
116     } else {
117         int maxSize = this->caps()->maxTextureSize();
118         if (desc.fWidth > maxSize || desc.fHeight > maxSize) {
119             return nullptr;
120         }
121     }
122 
123     GrGpuResource::LifeCycle lifeCycle = SkBudgeted::kYes == budgeted ?
124                                             GrGpuResource::kCached_LifeCycle :
125                                             GrGpuResource::kUncached_LifeCycle;
126 
127     desc.fSampleCnt = SkTMin(desc.fSampleCnt, this->caps()->maxSampleCount());
128     // Attempt to catch un- or wrongly initialized sample counts;
129     SkASSERT(desc.fSampleCnt >= 0 && desc.fSampleCnt <= 64);
130 
131     desc.fOrigin = resolve_origin(desc.fOrigin, isRT);
132 
133     if (GrPixelConfigIsCompressed(desc.fConfig)) {
134         // We shouldn't be rendering into this
135         SkASSERT(!isRT);
136         SkASSERT(0 == desc.fSampleCnt);
137 
138         if (!this->caps()->npotTextureTileSupport() &&
139             (!SkIsPow2(desc.fWidth) || !SkIsPow2(desc.fHeight))) {
140             return nullptr;
141         }
142 
143         this->handleDirtyContext();
144         tex = this->onCreateCompressedTexture(desc, lifeCycle, srcData);
145     } else {
146         this->handleDirtyContext();
147         tex = this->onCreateTexture(desc, lifeCycle, srcData, rowBytes);
148     }
149     if (!this->caps()->reuseScratchTextures() && !isRT) {
150         tex->resourcePriv().removeScratchKey();
151     }
152     if (tex) {
153         fStats.incTextureCreates();
154         if (srcData) {
155             fStats.incTextureUploads();
156         }
157     }
158     return tex;
159 }
160 
wrapBackendTexture(const GrBackendTextureDesc & desc,GrWrapOwnership ownership)161 GrTexture* GrGpu::wrapBackendTexture(const GrBackendTextureDesc& desc, GrWrapOwnership ownership) {
162     this->handleDirtyContext();
163     if (!this->caps()->isConfigTexturable(desc.fConfig)) {
164         return nullptr;
165     }
166     if ((desc.fFlags & kRenderTarget_GrBackendTextureFlag) &&
167         !this->caps()->isConfigRenderable(desc.fConfig, desc.fSampleCnt > 0)) {
168         return nullptr;
169     }
170     int maxSize = this->caps()->maxTextureSize();
171     if (desc.fWidth > maxSize || desc.fHeight > maxSize) {
172         return nullptr;
173     }
174     GrTexture* tex = this->onWrapBackendTexture(desc, ownership);
175     if (nullptr == tex) {
176         return nullptr;
177     }
178     // TODO: defer this and attach dynamically
179     GrRenderTarget* tgt = tex->asRenderTarget();
180     if (tgt && !fContext->resourceProvider()->attachStencilAttachment(tgt)) {
181         tex->unref();
182         return nullptr;
183     } else {
184         return tex;
185     }
186 }
187 
wrapBackendRenderTarget(const GrBackendRenderTargetDesc & desc,GrWrapOwnership ownership)188 GrRenderTarget* GrGpu::wrapBackendRenderTarget(const GrBackendRenderTargetDesc& desc,
189                                                GrWrapOwnership ownership) {
190     if (!this->caps()->isConfigRenderable(desc.fConfig, desc.fSampleCnt > 0)) {
191         return nullptr;
192     }
193     this->handleDirtyContext();
194     return this->onWrapBackendRenderTarget(desc, ownership);
195 }
196 
wrapBackendTextureAsRenderTarget(const GrBackendTextureDesc & desc,GrWrapOwnership ownership)197 GrRenderTarget* GrGpu::wrapBackendTextureAsRenderTarget(const GrBackendTextureDesc& desc,
198                                                         GrWrapOwnership ownership) {
199     this->handleDirtyContext();
200     if (!(desc.fFlags & kRenderTarget_GrBackendTextureFlag)) {
201       return nullptr;
202     }
203     if (!this->caps()->isConfigRenderable(desc.fConfig, desc.fSampleCnt > 0)) {
204         return nullptr;
205     }
206     int maxSize = this->caps()->maxTextureSize();
207     if (desc.fWidth > maxSize || desc.fHeight > maxSize) {
208         return nullptr;
209     }
210     return this->onWrapBackendTextureAsRenderTarget(desc, ownership);
211 }
212 
createVertexBuffer(size_t size,bool dynamic)213 GrVertexBuffer* GrGpu::createVertexBuffer(size_t size, bool dynamic) {
214     this->handleDirtyContext();
215     GrVertexBuffer* vb = this->onCreateVertexBuffer(size, dynamic);
216     if (!this->caps()->reuseScratchBuffers()) {
217         vb->resourcePriv().removeScratchKey();
218     }
219     return vb;
220 }
221 
createIndexBuffer(size_t size,bool dynamic)222 GrIndexBuffer* GrGpu::createIndexBuffer(size_t size, bool dynamic) {
223     this->handleDirtyContext();
224     GrIndexBuffer* ib = this->onCreateIndexBuffer(size, dynamic);
225     if (!this->caps()->reuseScratchBuffers()) {
226         ib->resourcePriv().removeScratchKey();
227     }
228     return ib;
229 }
230 
createTransferBuffer(size_t size,TransferType type)231 GrTransferBuffer* GrGpu::createTransferBuffer(size_t size, TransferType type) {
232     this->handleDirtyContext();
233     GrTransferBuffer* tb = this->onCreateTransferBuffer(size, type);
234     return tb;
235 }
236 
clear(const SkIRect & rect,GrColor color,GrRenderTarget * renderTarget)237 void GrGpu::clear(const SkIRect& rect,
238                   GrColor color,
239                   GrRenderTarget* renderTarget) {
240     SkASSERT(renderTarget);
241     SkASSERT(SkIRect::MakeWH(renderTarget->width(), renderTarget->height()).contains(rect));
242     this->handleDirtyContext();
243     this->onClear(renderTarget, rect, color);
244 }
245 
clearStencilClip(const SkIRect & rect,bool insideClip,GrRenderTarget * renderTarget)246 void GrGpu::clearStencilClip(const SkIRect& rect,
247                              bool insideClip,
248                              GrRenderTarget* renderTarget) {
249     SkASSERT(renderTarget);
250     this->handleDirtyContext();
251     this->onClearStencilClip(renderTarget, rect, insideClip);
252 }
253 
copySurface(GrSurface * dst,GrSurface * src,const SkIRect & srcRect,const SkIPoint & dstPoint)254 bool GrGpu::copySurface(GrSurface* dst,
255                         GrSurface* src,
256                         const SkIRect& srcRect,
257                         const SkIPoint& dstPoint) {
258     SkASSERT(dst && src);
259     this->handleDirtyContext();
260     return this->onCopySurface(dst, src, srcRect, dstPoint);
261 }
262 
getReadPixelsInfo(GrSurface * srcSurface,int width,int height,size_t rowBytes,GrPixelConfig readConfig,DrawPreference * drawPreference,ReadPixelTempDrawInfo * tempDrawInfo)263 bool GrGpu::getReadPixelsInfo(GrSurface* srcSurface, int width, int height, size_t rowBytes,
264                               GrPixelConfig readConfig, DrawPreference* drawPreference,
265                               ReadPixelTempDrawInfo* tempDrawInfo) {
266     SkASSERT(drawPreference);
267     SkASSERT(tempDrawInfo);
268     SkASSERT(kGpuPrefersDraw_DrawPreference != *drawPreference);
269 
270     // We currently do not support reading into a compressed buffer
271     if (GrPixelConfigIsCompressed(readConfig)) {
272         return false;
273     }
274 
275     if (!this->onGetReadPixelsInfo(srcSurface, width, height, rowBytes, readConfig, drawPreference,
276                                    tempDrawInfo)) {
277         return false;
278     }
279 
280     // Check to see if we're going to request that the caller draw when drawing is not possible.
281     if (!srcSurface->asTexture() ||
282         !this->caps()->isConfigRenderable(tempDrawInfo->fTempSurfaceDesc.fConfig, false)) {
283         // If we don't have a fallback to a straight read then fail.
284         if (kRequireDraw_DrawPreference == *drawPreference) {
285             return false;
286         }
287         *drawPreference = kNoDraw_DrawPreference;
288     }
289 
290     return true;
291 }
getWritePixelsInfo(GrSurface * dstSurface,int width,int height,GrPixelConfig srcConfig,DrawPreference * drawPreference,WritePixelTempDrawInfo * tempDrawInfo)292 bool GrGpu::getWritePixelsInfo(GrSurface* dstSurface, int width, int height,
293                                GrPixelConfig srcConfig, DrawPreference* drawPreference,
294                                WritePixelTempDrawInfo* tempDrawInfo) {
295     SkASSERT(drawPreference);
296     SkASSERT(tempDrawInfo);
297     SkASSERT(kGpuPrefersDraw_DrawPreference != *drawPreference);
298 
299     if (GrPixelConfigIsCompressed(dstSurface->desc().fConfig) &&
300         dstSurface->desc().fConfig != srcConfig) {
301         return false;
302     }
303 
304     if (SkToBool(dstSurface->asRenderTarget())) {
305         if (this->caps()->useDrawInsteadOfAllRenderTargetWrites()) {
306             ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
307         } else if (this->caps()->useDrawInsteadOfPartialRenderTargetWrite() &&
308                    (width < dstSurface->width() || height < dstSurface->height())) {
309             ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
310         }
311     }
312 
313     if (!this->onGetWritePixelsInfo(dstSurface, width, height, srcConfig, drawPreference,
314                                     tempDrawInfo)) {
315         return false;
316     }
317 
318     // Check to see if we're going to request that the caller draw when drawing is not possible.
319     if (!dstSurface->asRenderTarget() ||
320         !this->caps()->isConfigTexturable(tempDrawInfo->fTempSurfaceDesc.fConfig)) {
321         // If we don't have a fallback to a straight upload then fail.
322         if (kRequireDraw_DrawPreference == *drawPreference ||
323             !this->caps()->isConfigTexturable(srcConfig)) {
324             return false;
325         }
326         *drawPreference = kNoDraw_DrawPreference;
327     }
328     return true;
329 }
330 
readPixels(GrSurface * surface,int left,int top,int width,int height,GrPixelConfig config,void * buffer,size_t rowBytes)331 bool GrGpu::readPixels(GrSurface* surface,
332                        int left, int top, int width, int height,
333                        GrPixelConfig config, void* buffer,
334                        size_t rowBytes) {
335     this->handleDirtyContext();
336 
337     // We cannot read pixels into a compressed buffer
338     if (GrPixelConfigIsCompressed(config)) {
339         return false;
340     }
341 
342     size_t bpp = GrBytesPerPixel(config);
343     if (!GrSurfacePriv::AdjustReadPixelParams(surface->width(), surface->height(), bpp,
344                                               &left, &top, &width, &height,
345                                               &buffer,
346                                               &rowBytes)) {
347         return false;
348     }
349 
350     return this->onReadPixels(surface,
351                               left, top, width, height,
352                               config, buffer,
353                               rowBytes);
354 }
355 
writePixels(GrSurface * surface,int left,int top,int width,int height,GrPixelConfig config,const void * buffer,size_t rowBytes)356 bool GrGpu::writePixels(GrSurface* surface,
357                         int left, int top, int width, int height,
358                         GrPixelConfig config, const void* buffer,
359                         size_t rowBytes) {
360     if (!buffer || !surface) {
361         return false;
362     }
363 
364     this->handleDirtyContext();
365     if (this->onWritePixels(surface, left, top, width, height, config, buffer, rowBytes)) {
366         fStats.incTextureUploads();
367         return true;
368     }
369     return false;
370 }
371 
transferPixels(GrSurface * surface,int left,int top,int width,int height,GrPixelConfig config,GrTransferBuffer * buffer,size_t offset,size_t rowBytes)372 bool GrGpu::transferPixels(GrSurface* surface,
373                            int left, int top, int width, int height,
374                            GrPixelConfig config, GrTransferBuffer* buffer,
375                            size_t offset, size_t rowBytes) {
376     SkASSERT(buffer);
377 
378     this->handleDirtyContext();
379     if (this->onTransferPixels(surface, left, top, width, height, config,
380                                buffer, offset, rowBytes)) {
381         fStats.incTransfersToTexture();
382         return true;
383     }
384     return false;
385 }
386 
resolveRenderTarget(GrRenderTarget * target)387 void GrGpu::resolveRenderTarget(GrRenderTarget* target) {
388     SkASSERT(target);
389     this->handleDirtyContext();
390     this->onResolveRenderTarget(target);
391 }
392 
393 ////////////////////////////////////////////////////////////////////////////////
394 
draw(const DrawArgs & args,const GrVertices & vertices)395 void GrGpu::draw(const DrawArgs& args, const GrVertices& vertices) {
396     this->handleDirtyContext();
397     if (GrXferBarrierType barrierType = args.fPipeline->xferBarrierType(*this->caps())) {
398         this->xferBarrier(args.fPipeline->getRenderTarget(), barrierType);
399     }
400 
401     GrVertices::Iterator iter;
402     const GrNonInstancedVertices* verts = iter.init(vertices);
403     do {
404         this->onDraw(args, *verts);
405         fStats.incNumDraws();
406     } while ((verts = iter.next()));
407 }
408 
409