LCOV - code coverage report
Current view: top level - gfx/skia/skia/src/gpu - GrGpu.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 279 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 25 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13