Home | History | Annotate | Download | only in gpu
      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 "GrBuffer.h"
     12 #include "GrCaps.h"
     13 #include "GrContext.h"
     14 #include "GrGpuResourcePriv.h"
     15 #include "GrMesh.h"
     16 #include "GrPathRendering.h"
     17 #include "GrPipeline.h"
     18 #include "GrResourceCache.h"
     19 #include "GrResourceProvider.h"
     20 #include "GrRenderTargetPriv.h"
     21 #include "GrStencilAttachment.h"
     22 #include "GrStencilSettings.h"
     23 #include "GrSurfacePriv.h"
     24 #include "GrTexturePriv.h"
     25 #include "SkMathPriv.h"
     26 
     27 GrMesh& GrMesh::operator =(const GrMesh& di) {
     28     fPrimitiveType  = di.fPrimitiveType;
     29     fStartVertex    = di.fStartVertex;
     30     fStartIndex     = di.fStartIndex;
     31     fVertexCount    = di.fVertexCount;
     32     fIndexCount     = di.fIndexCount;
     33 
     34     fInstanceCount          = di.fInstanceCount;
     35     fVerticesPerInstance    = di.fVerticesPerInstance;
     36     fIndicesPerInstance     = di.fIndicesPerInstance;
     37     fMaxInstancesPerDraw    = di.fMaxInstancesPerDraw;
     38 
     39     fVertexBuffer.reset(di.vertexBuffer());
     40     fIndexBuffer.reset(di.indexBuffer());
     41 
     42     return *this;
     43 }
     44 
     45 ////////////////////////////////////////////////////////////////////////////////
     46 
     47 GrGpu::GrGpu(GrContext* context)
     48     : fResetTimestamp(kExpiredTimestamp+1)
     49     , fResetBits(kAll_GrBackendState)
     50     , fContext(context) {
     51     fMultisampleSpecs.emplace_back(0, 0, nullptr); // Index 0 is an invalid unique id.
     52 }
     53 
     54 GrGpu::~GrGpu() {}
     55 
     56 void GrGpu::disconnect(DisconnectType) {}
     57 
     58 ////////////////////////////////////////////////////////////////////////////////
     59 
     60 bool GrGpu::isACopyNeededForTextureParams(int width, int height,
     61                                           const GrSamplerParams& textureParams,
     62                                           GrTextureProducer::CopyParams* copyParams,
     63                                           SkScalar scaleAdjust[2]) const {
     64     const GrCaps& caps = *this->caps();
     65     if (textureParams.isTiled() && !caps.npotTextureTileSupport() &&
     66         (!SkIsPow2(width) || !SkIsPow2(height))) {
     67         SkASSERT(scaleAdjust);
     68         copyParams->fWidth = GrNextPow2(width);
     69         copyParams->fHeight = GrNextPow2(height);
     70         scaleAdjust[0] = ((SkScalar) copyParams->fWidth) / width;
     71         scaleAdjust[1] = ((SkScalar) copyParams->fHeight) / height;
     72         switch (textureParams.filterMode()) {
     73             case GrSamplerParams::kNone_FilterMode:
     74                 copyParams->fFilter = GrSamplerParams::kNone_FilterMode;
     75                 break;
     76             case GrSamplerParams::kBilerp_FilterMode:
     77             case GrSamplerParams::kMipMap_FilterMode:
     78                 // We are only ever scaling up so no reason to ever indicate kMipMap.
     79                 copyParams->fFilter = GrSamplerParams::kBilerp_FilterMode;
     80                 break;
     81         }
     82         return true;
     83     }
     84     return false;
     85 }
     86 
     87 static GrSurfaceOrigin resolve_origin(GrSurfaceOrigin origin, bool renderTarget) {
     88     // By default, GrRenderTargets are GL's normal orientation so that they
     89     // can be drawn to by the outside world without the client having
     90     // to render upside down.
     91     if (kDefault_GrSurfaceOrigin == origin) {
     92         return renderTarget ? kBottomLeft_GrSurfaceOrigin : kTopLeft_GrSurfaceOrigin;
     93     } else {
     94         return origin;
     95     }
     96 }
     97 
     98 /**
     99  * Prior to creating a texture, make sure the type of texture being created is
    100  * supported by calling check_texture_creation_params.
    101  *
    102  * @param caps The capabilities of the GL device.
    103  * @param desc The descriptor of the texture to create.
    104  * @param isRT Indicates if the texture can be a render target.
    105  */
    106 static bool check_texture_creation_params(const GrCaps& caps, const GrSurfaceDesc& desc,
    107                                           bool* isRT, const SkTArray<GrMipLevel>& texels) {
    108     if (!caps.isConfigTexturable(desc.fConfig)) {
    109         return false;
    110     }
    111 
    112     if (GrPixelConfigIsSint(desc.fConfig) && texels.count() > 1) {
    113         return false;
    114     }
    115 
    116     *isRT = SkToBool(desc.fFlags & kRenderTarget_GrSurfaceFlag);
    117     if (*isRT && !caps.isConfigRenderable(desc.fConfig, desc.fSampleCnt > 0)) {
    118         return false;
    119     }
    120 
    121     // We currently do not support multisampled textures
    122     if (!*isRT && desc.fSampleCnt > 0) {
    123         return false;
    124     }
    125 
    126     if (*isRT) {
    127         int maxRTSize = caps.maxRenderTargetSize();
    128         if (desc.fWidth > maxRTSize || desc.fHeight > maxRTSize) {
    129             return false;
    130         }
    131     } else {
    132         int maxSize = caps.maxTextureSize();
    133         if (desc.fWidth > maxSize || desc.fHeight > maxSize) {
    134             return false;
    135         }
    136     }
    137 
    138     for (int i = 0; i < texels.count(); ++i) {
    139         if (!texels[i].fPixels) {
    140             return false;
    141         }
    142     }
    143     return true;
    144 }
    145 
    146 GrTexture* GrGpu::createTexture(const GrSurfaceDesc& origDesc, SkBudgeted budgeted,
    147                                 const SkTArray<GrMipLevel>& texels) {
    148     GrSurfaceDesc desc = origDesc;
    149 
    150     const GrCaps* caps = this->caps();
    151     bool isRT = false;
    152     bool textureCreationParamsValid = check_texture_creation_params(*caps, desc, &isRT, texels);
    153     if (!textureCreationParamsValid) {
    154         return nullptr;
    155     }
    156 
    157     desc.fSampleCnt = SkTMin(desc.fSampleCnt, caps->maxSampleCount());
    158     // Attempt to catch un- or wrongly intialized sample counts;
    159     SkASSERT(desc.fSampleCnt >= 0 && desc.fSampleCnt <= 64);
    160 
    161     desc.fOrigin = resolve_origin(desc.fOrigin, isRT);
    162 
    163     GrTexture* tex = nullptr;
    164 
    165     if (GrPixelConfigIsCompressed(desc.fConfig)) {
    166         // We shouldn't be rendering into this
    167         SkASSERT(!isRT);
    168         SkASSERT(0 == desc.fSampleCnt);
    169 
    170         if (!caps->npotTextureTileSupport() &&
    171             (!SkIsPow2(desc.fWidth) || !SkIsPow2(desc.fHeight))) {
    172             return nullptr;
    173         }
    174 
    175         this->handleDirtyContext();
    176         tex = this->onCreateCompressedTexture(desc, budgeted, texels);
    177     } else {
    178         this->handleDirtyContext();
    179         tex = this->onCreateTexture(desc, budgeted, texels);
    180     }
    181     if (tex) {
    182         if (!caps->reuseScratchTextures() && !isRT) {
    183             tex->resourcePriv().removeScratchKey();
    184         }
    185         fStats.incTextureCreates();
    186         if (!texels.empty()) {
    187             if (texels[0].fPixels) {
    188                 fStats.incTextureUploads();
    189             }
    190         }
    191         // This is a current work around to get discards into newly created textures. Once we are in
    192         // MDB world, we should remove this code a rely on the draw target having specified load
    193         // operations.
    194         if (isRT && texels.empty()) {
    195             GrRenderTarget* rt = tex->asRenderTarget();
    196             SkASSERT(rt);
    197             rt->discard();
    198         }
    199     }
    200     return tex;
    201 }
    202 
    203 sk_sp<GrTexture> GrGpu::wrapBackendTexture(const GrBackendTextureDesc& desc,
    204                                            GrWrapOwnership ownership) {
    205     this->handleDirtyContext();
    206     if (!this->caps()->isConfigTexturable(desc.fConfig)) {
    207         return nullptr;
    208     }
    209     if ((desc.fFlags & kRenderTarget_GrBackendTextureFlag) &&
    210         !this->caps()->isConfigRenderable(desc.fConfig, desc.fSampleCnt > 0)) {
    211         return nullptr;
    212     }
    213     int maxSize = this->caps()->maxTextureSize();
    214     if (desc.fWidth > maxSize || desc.fHeight > maxSize) {
    215         return nullptr;
    216     }
    217     sk_sp<GrTexture> tex = this->onWrapBackendTexture(desc, ownership);
    218     if (!tex) {
    219         return nullptr;
    220     }
    221     // TODO: defer this and attach dynamically
    222     GrRenderTarget* tgt = tex->asRenderTarget();
    223     if (tgt && !fContext->resourceProvider()->attachStencilAttachment(tgt)) {
    224         return nullptr;
    225     }
    226     return tex;
    227 }
    228 
    229 sk_sp<GrRenderTarget> GrGpu::wrapBackendRenderTarget(const GrBackendRenderTargetDesc& desc) {
    230     if (!this->caps()->isConfigRenderable(desc.fConfig, desc.fSampleCnt > 0)) {
    231         return nullptr;
    232     }
    233     this->handleDirtyContext();
    234     return this->onWrapBackendRenderTarget(desc);
    235 }
    236 
    237 sk_sp<GrRenderTarget> GrGpu::wrapBackendTextureAsRenderTarget(const GrBackendTextureDesc& desc) {
    238     this->handleDirtyContext();
    239     if (!(desc.fFlags & kRenderTarget_GrBackendTextureFlag)) {
    240       return nullptr;
    241     }
    242     if (!this->caps()->isConfigRenderable(desc.fConfig, desc.fSampleCnt > 0)) {
    243         return nullptr;
    244     }
    245     int maxSize = this->caps()->maxTextureSize();
    246     if (desc.fWidth > maxSize || desc.fHeight > maxSize) {
    247         return nullptr;
    248     }
    249     return this->onWrapBackendTextureAsRenderTarget(desc);
    250 }
    251 
    252 GrBuffer* GrGpu::createBuffer(size_t size, GrBufferType intendedType,
    253                               GrAccessPattern accessPattern, const void* data) {
    254     this->handleDirtyContext();
    255     GrBuffer* buffer = this->onCreateBuffer(size, intendedType, accessPattern, data);
    256     if (!this->caps()->reuseScratchBuffers()) {
    257         buffer->resourcePriv().removeScratchKey();
    258     }
    259     return buffer;
    260 }
    261 
    262 gr_instanced::InstancedRendering* GrGpu::createInstancedRendering() {
    263     SkASSERT(GrCaps::InstancedSupport::kNone != this->caps()->instancedSupport());
    264     return this->onCreateInstancedRendering();
    265 }
    266 
    267 bool GrGpu::copySurface(GrSurface* dst,
    268                         GrSurface* src,
    269                         const SkIRect& srcRect,
    270                         const SkIPoint& dstPoint) {
    271     SkASSERT(dst && src);
    272     this->handleDirtyContext();
    273     // We don't allow conversion between integer configs and float/fixed configs.
    274     if (GrPixelConfigIsSint(dst->config()) != GrPixelConfigIsSint(src->config())) {
    275         return false;
    276     }
    277     if (GrPixelConfigIsCompressed(dst->config())) {
    278         return false;
    279     }
    280     return this->onCopySurface(dst, src, srcRect, dstPoint);
    281 }
    282 
    283 bool GrGpu::getReadPixelsInfo(GrSurface* srcSurface, int width, int height, size_t rowBytes,
    284                               GrPixelConfig readConfig, DrawPreference* drawPreference,
    285                               ReadPixelTempDrawInfo* tempDrawInfo) {
    286     SkASSERT(drawPreference);
    287     SkASSERT(tempDrawInfo);
    288     SkASSERT(srcSurface);
    289     SkASSERT(kGpuPrefersDraw_DrawPreference != *drawPreference);
    290 
    291     // We don't allow conversion between integer configs and float/fixed configs.
    292     if (GrPixelConfigIsSint(srcSurface->config()) != GrPixelConfigIsSint(readConfig)) {
    293         return false;
    294     }
    295 
    296     // We currently do not support reading into a compressed buffer
    297     if (GrPixelConfigIsCompressed(readConfig)) {
    298         return false;
    299     }
    300 
    301     // We currently do not support reading into the packed formats 565 or 4444 as they are not
    302     // required to have read back support on all devices and backends.
    303     if (kRGB_565_GrPixelConfig == readConfig || kRGBA_4444_GrPixelConfig == readConfig) {
    304         return false;
    305     }
    306 
    307     if (!this->onGetReadPixelsInfo(srcSurface, width, height, rowBytes, readConfig, drawPreference,
    308                                    tempDrawInfo)) {
    309         return false;
    310     }
    311 
    312     // Check to see if we're going to request that the caller draw when drawing is not possible.
    313     if (!srcSurface->asTexture() ||
    314         !this->caps()->isConfigRenderable(tempDrawInfo->fTempSurfaceDesc.fConfig, false)) {
    315         // If we don't have a fallback to a straight read then fail.
    316         if (kRequireDraw_DrawPreference == *drawPreference) {
    317             return false;
    318         }
    319         *drawPreference = kNoDraw_DrawPreference;
    320     }
    321 
    322     return true;
    323 }
    324 bool GrGpu::getWritePixelsInfo(GrSurface* dstSurface, int width, int height,
    325                                GrPixelConfig srcConfig, DrawPreference* drawPreference,
    326                                WritePixelTempDrawInfo* tempDrawInfo) {
    327     SkASSERT(drawPreference);
    328     SkASSERT(tempDrawInfo);
    329     SkASSERT(dstSurface);
    330     SkASSERT(kGpuPrefersDraw_DrawPreference != *drawPreference);
    331 
    332     if (GrPixelConfigIsCompressed(dstSurface->desc().fConfig) &&
    333         dstSurface->desc().fConfig != srcConfig) {
    334         return false;
    335     }
    336 
    337     // We don't allow conversion between integer configs and float/fixed configs.
    338     if (GrPixelConfigIsSint(dstSurface->config()) != GrPixelConfigIsSint(srcConfig)) {
    339         return false;
    340     }
    341 
    342     if (SkToBool(dstSurface->asRenderTarget())) {
    343         if (this->caps()->useDrawInsteadOfAllRenderTargetWrites()) {
    344             ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
    345         } else if (this->caps()->useDrawInsteadOfPartialRenderTargetWrite() &&
    346                    (width < dstSurface->width() || height < dstSurface->height())) {
    347             ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
    348         }
    349     }
    350 
    351     if (!this->onGetWritePixelsInfo(dstSurface, width, height, srcConfig, drawPreference,
    352                                     tempDrawInfo)) {
    353         return false;
    354     }
    355 
    356     // Check to see if we're going to request that the caller draw when drawing is not possible.
    357     if (!dstSurface->asRenderTarget() ||
    358         !this->caps()->isConfigTexturable(tempDrawInfo->fTempSurfaceDesc.fConfig)) {
    359         // If we don't have a fallback to a straight upload then fail.
    360         if (kRequireDraw_DrawPreference == *drawPreference ||
    361             !this->caps()->isConfigTexturable(srcConfig)) {
    362             return false;
    363         }
    364         *drawPreference = kNoDraw_DrawPreference;
    365     }
    366     return true;
    367 }
    368 
    369 bool GrGpu::readPixels(GrSurface* surface,
    370                        int left, int top, int width, int height,
    371                        GrPixelConfig config, void* buffer,
    372                        size_t rowBytes) {
    373     SkASSERT(surface);
    374 
    375     // We don't allow conversion between integer configs and float/fixed configs.
    376     if (GrPixelConfigIsSint(surface->config()) != GrPixelConfigIsSint(config)) {
    377         return false;
    378     }
    379 
    380     // We cannot read pixels into a compressed buffer
    381     if (GrPixelConfigIsCompressed(config)) {
    382         return false;
    383     }
    384 
    385     size_t bpp = GrBytesPerPixel(config);
    386     if (!GrSurfacePriv::AdjustReadPixelParams(surface->width(), surface->height(), bpp,
    387                                               &left, &top, &width, &height,
    388                                               &buffer,
    389                                               &rowBytes)) {
    390         return false;
    391     }
    392 
    393     this->handleDirtyContext();
    394 
    395     return this->onReadPixels(surface,
    396                               left, top, width, height,
    397                               config, buffer,
    398                               rowBytes);
    399 }
    400 
    401 bool GrGpu::writePixels(GrSurface* surface,
    402                         int left, int top, int width, int height,
    403                         GrPixelConfig config, const SkTArray<GrMipLevel>& texels) {
    404     SkASSERT(surface);
    405     for (int currentMipLevel = 0; currentMipLevel < texels.count(); currentMipLevel++) {
    406         if (!texels[currentMipLevel].fPixels ) {
    407             return false;
    408         }
    409     }
    410 
    411     // We don't allow conversion between integer configs and float/fixed configs.
    412     if (GrPixelConfigIsSint(surface->config()) != GrPixelConfigIsSint(config)) {
    413         return false;
    414     }
    415 
    416     this->handleDirtyContext();
    417     if (this->onWritePixels(surface, left, top, width, height, config, texels)) {
    418         SkIRect rect = SkIRect::MakeXYWH(left, top, width, height);
    419         this->didWriteToSurface(surface, &rect, texels.count());
    420         fStats.incTextureUploads();
    421         return true;
    422     }
    423     return false;
    424 }
    425 
    426 bool GrGpu::writePixels(GrSurface* surface,
    427                         int left, int top, int width, int height,
    428                         GrPixelConfig config, const void* buffer,
    429                         size_t rowBytes) {
    430     GrMipLevel mipLevel;
    431     mipLevel.fPixels = buffer;
    432     mipLevel.fRowBytes = rowBytes;
    433     SkSTArray<1, GrMipLevel> texels;
    434     texels.push_back(mipLevel);
    435 
    436     return this->writePixels(surface, left, top, width, height, config, texels);
    437 }
    438 
    439 bool GrGpu::transferPixels(GrSurface* surface,
    440                            int left, int top, int width, int height,
    441                            GrPixelConfig config, GrBuffer* transferBuffer,
    442                            size_t offset, size_t rowBytes, GrFence* fence) {
    443     SkASSERT(transferBuffer);
    444     SkASSERT(fence);
    445 
    446     // We don't allow conversion between integer configs and float/fixed configs.
    447     if (GrPixelConfigIsSint(surface->config()) != GrPixelConfigIsSint(config)) {
    448         return false;
    449     }
    450 
    451     this->handleDirtyContext();
    452     if (this->onTransferPixels(surface, left, top, width, height, config,
    453                                transferBuffer, offset, rowBytes)) {
    454         SkIRect rect = SkIRect::MakeXYWH(left, top, width, height);
    455         this->didWriteToSurface(surface, &rect);
    456         fStats.incTransfersToTexture();
    457 
    458         if (*fence) {
    459             this->deleteFence(*fence);
    460         }
    461         *fence = this->insertFence();
    462 
    463         return true;
    464     }
    465     return false;
    466 }
    467 
    468 void GrGpu::resolveRenderTarget(GrRenderTarget* target) {
    469     SkASSERT(target);
    470     this->handleDirtyContext();
    471     this->onResolveRenderTarget(target);
    472 }
    473 
    474 void GrGpu::didWriteToSurface(GrSurface* surface, const SkIRect* bounds, uint32_t mipLevels) const {
    475     SkASSERT(surface);
    476     // Mark any MIP chain and resolve buffer as dirty if and only if there is a non-empty bounds.
    477     if (nullptr == bounds || !bounds->isEmpty()) {
    478         if (GrRenderTarget* target = surface->asRenderTarget()) {
    479             target->flagAsNeedingResolve(bounds);
    480         }
    481         GrTexture* texture = surface->asTexture();
    482         if (texture && 1 == mipLevels) {
    483             texture->texturePriv().dirtyMipMaps(true);
    484         }
    485     }
    486 }
    487 
    488 const GrGpu::MultisampleSpecs& GrGpu::queryMultisampleSpecs(const GrPipeline& pipeline) {
    489     GrRenderTarget* rt = pipeline.getRenderTarget();
    490     SkASSERT(rt->desc().fSampleCnt > 1);
    491 
    492     GrStencilSettings stencil;
    493     if (pipeline.isStencilEnabled()) {
    494         // TODO: attach stencil and create settings during render target flush.
    495         SkASSERT(rt->renderTargetPriv().getStencilAttachment());
    496         stencil.reset(*pipeline.getUserStencil(), pipeline.hasStencilClip(),
    497                       rt->renderTargetPriv().numStencilBits());
    498     }
    499 
    500     int effectiveSampleCnt;
    501     SkSTArray<16, SkPoint, true> pattern;
    502     this->onQueryMultisampleSpecs(rt, stencil, &effectiveSampleCnt, &pattern);
    503     SkASSERT(effectiveSampleCnt >= rt->desc().fSampleCnt);
    504 
    505     uint8_t id;
    506     if (this->caps()->sampleLocationsSupport()) {
    507         SkASSERT(pattern.count() == effectiveSampleCnt);
    508         const auto& insertResult = fMultisampleSpecsIdMap.insert(
    509             MultisampleSpecsIdMap::value_type(pattern, SkTMin(fMultisampleSpecs.count(), 255)));
    510         id = insertResult.first->second;
    511         if (insertResult.second) {
    512             // This means the insert did not find the pattern in the map already, and therefore an
    513             // actual insertion took place. (We don't expect to see many unique sample patterns.)
    514             const SkPoint* sampleLocations = insertResult.first->first.begin();
    515             SkASSERT(id == fMultisampleSpecs.count());
    516             fMultisampleSpecs.emplace_back(id, effectiveSampleCnt, sampleLocations);
    517         }
    518     } else {
    519         id = effectiveSampleCnt;
    520         for (int i = fMultisampleSpecs.count(); i <= id; ++i) {
    521             fMultisampleSpecs.emplace_back(i, i, nullptr);
    522         }
    523     }
    524     SkASSERT(id > 0);
    525 
    526     return fMultisampleSpecs[id];
    527 }
    528 
    529 bool GrGpu::SamplePatternComparator::operator()(const SamplePattern& a,
    530                                                 const SamplePattern& b) const {
    531     if (a.count() != b.count()) {
    532         return a.count() < b.count();
    533     }
    534     for (int i = 0; i < a.count(); ++i) {
    535         // This doesn't have geometric meaning. We just need to define an ordering for std::map.
    536         if (a[i].x() != b[i].x()) {
    537             return a[i].x() < b[i].x();
    538         }
    539         if (a[i].y() != b[i].y()) {
    540             return a[i].y() < b[i].y();
    541         }
    542     }
    543     return false; // Equal.
    544 }
    545