Home | History | Annotate | Download | only in gpu
      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 
     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 
     42 GrGpu::GrGpu(GrContext* context)
     43     : fResetTimestamp(kExpiredTimestamp+1)
     44     , fResetBits(kAll_GrBackendState)
     45     , fGpuTraceMarkerCount(0)
     46     , fContext(context) {
     47 }
     48 
     49 GrGpu::~GrGpu() {}
     50 
     51 void GrGpu::contextAbandoned() {}
     52 
     53 ////////////////////////////////////////////////////////////////////////////////
     54 
     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 
     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 
    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 
    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 
    192 GrRenderTarget* GrGpu::wrapBackendRenderTarget(const GrBackendRenderTargetDesc& desc) {
    193     this->handleDirtyContext();
    194     return this->onWrapBackendRenderTarget(desc);
    195 }
    196 
    197 GrVertexBuffer* GrGpu::createVertexBuffer(size_t size, bool dynamic) {
    198     this->handleDirtyContext();
    199     return this->onCreateVertexBuffer(size, dynamic);
    200 }
    201 
    202 GrIndexBuffer* GrGpu::createIndexBuffer(size_t size, bool dynamic) {
    203     this->handleDirtyContext();
    204     return this->onCreateIndexBuffer(size, dynamic);
    205 }
    206 
    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 
    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 
    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 
    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 
    246 void GrGpu::resolveRenderTarget(GrRenderTarget* target) {
    247     SkASSERT(target);
    248     this->handleDirtyContext();
    249     this->onResolveRenderTarget(target);
    250 }
    251 
    252 typedef GrTraceMarkerSet::Iter TMIter;
    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 
    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 
    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 
    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 
    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 
    304 void GrGpu::stencilPath(const GrPath* path, const StencilPathState& state) {
    305     this->handleDirtyContext();
    306     this->onStencilPath(path, state);
    307 }
    308 
    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 
    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