1d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon/*
2d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon * Copyright 2015 Google Inc.
3d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon *
4d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon * Use of this source code is governed by a BSD-style license that can be
5d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon * found in the LICENSE file.
6d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon */
7d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon
8d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon#include "GrTextureProvider.h"
9d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon#include "GrTexturePriv.h"
10d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon#include "GrResourceCache.h"
11d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon#include "GrGpu.h"
126d0872d9bd97de5301214a258e141dd5fbeecffcjoshualitt#include "../private/GrSingleOwner.h"
136d0872d9bd97de5301214a258e141dd5fbeecffcjoshualitt
146d0872d9bd97de5301214a258e141dd5fbeecffcjoshualitt#define ASSERT_SINGLE_OWNER \
156d0872d9bd97de5301214a258e141dd5fbeecffcjoshualitt    SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fSingleOwner);)
16d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon
17d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomonenum ScratchTextureFlags {
18d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon    kExact_ScratchTextureFlag           = 0x1,
19d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon    kNoPendingIO_ScratchTextureFlag     = 0x2,
20d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon    kNoCreate_ScratchTextureFlag        = 0x4,
21d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon};
22d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon
236d0872d9bd97de5301214a258e141dd5fbeecffcjoshualittGrTextureProvider::GrTextureProvider(GrGpu* gpu, GrResourceCache* cache, GrSingleOwner* singleOwner)
246d0872d9bd97de5301214a258e141dd5fbeecffcjoshualitt    : fCache(cache)
256d0872d9bd97de5301214a258e141dd5fbeecffcjoshualitt    , fGpu(gpu)
266d0872d9bd97de5301214a258e141dd5fbeecffcjoshualitt#ifdef SK_DEBUG
276d0872d9bd97de5301214a258e141dd5fbeecffcjoshualitt    , fSingleOwner(singleOwner)
286d0872d9bd97de5301214a258e141dd5fbeecffcjoshualitt#endif
296d0872d9bd97de5301214a258e141dd5fbeecffcjoshualitt    {
306d0872d9bd97de5301214a258e141dd5fbeecffcjoshualitt}
316d0872d9bd97de5301214a258e141dd5fbeecffcjoshualitt
325ec26ae9bfca635ccc98283aad5deda11519d826bsalomonGrTexture* GrTextureProvider::createTexture(const GrSurfaceDesc& desc, SkBudgeted budgeted,
33d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon                                            const void* srcData, size_t rowBytes) {
346d0872d9bd97de5301214a258e141dd5fbeecffcjoshualitt    ASSERT_SINGLE_OWNER
35d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon    if (this->isAbandoned()) {
3696fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
37d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon    }
38d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon    if ((desc.fFlags & kRenderTarget_GrSurfaceFlag) &&
39d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon        !fGpu->caps()->isConfigRenderable(desc.fConfig, desc.fSampleCnt > 0)) {
4096fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
41d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon    }
429a1ed5d81dbfc7d5b67b568dfe12b4033a9af154erikchen    if (!GrPixelConfigIsCompressed(desc.fConfig) &&
439a1ed5d81dbfc7d5b67b568dfe12b4033a9af154erikchen        !desc.fTextureStorageAllocator.fAllocateTextureStorage) {
44d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon        static const uint32_t kFlags = kExact_ScratchTextureFlag |
45d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon                                       kNoCreate_ScratchTextureFlag;
46eae6200acbec2255ac00ab363ffbe16758ec9076bsalomon        if (GrTexture* texture = this->refScratchTexture(desc, kFlags)) {
47d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon            if (!srcData || texture->writePixels(0, 0, desc.fWidth, desc.fHeight, desc.fConfig,
48d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon                                                 srcData, rowBytes)) {
495ec26ae9bfca635ccc98283aad5deda11519d826bsalomon                if (SkBudgeted::kNo == budgeted) {
50d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon                    texture->resourcePriv().makeUnbudgeted();
51d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon                }
52d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon                return texture;
53d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon            }
54d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon            texture->unref();
55d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon        }
56d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon    }
57d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon    return fGpu->createTexture(desc, budgeted, srcData, rowBytes);
58d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon}
59d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon
60eae6200acbec2255ac00ab363ffbe16758ec9076bsalomonGrTexture* GrTextureProvider::createApproxTexture(const GrSurfaceDesc& desc) {
616d0872d9bd97de5301214a258e141dd5fbeecffcjoshualitt    ASSERT_SINGLE_OWNER
62eae6200acbec2255ac00ab363ffbe16758ec9076bsalomon    return this->internalCreateApproxTexture(desc, 0);
63eae6200acbec2255ac00ab363ffbe16758ec9076bsalomon}
64eae6200acbec2255ac00ab363ffbe16758ec9076bsalomon
65eae6200acbec2255ac00ab363ffbe16758ec9076bsalomonGrTexture* GrTextureProvider::internalCreateApproxTexture(const GrSurfaceDesc& desc,
66eae6200acbec2255ac00ab363ffbe16758ec9076bsalomon                                                          uint32_t scratchFlags) {
676d0872d9bd97de5301214a258e141dd5fbeecffcjoshualitt    ASSERT_SINGLE_OWNER
68d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon    if (this->isAbandoned()) {
6996fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
70d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon    }
71d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon    // Currently we don't recycle compressed textures as scratch.
72d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon    if (GrPixelConfigIsCompressed(desc.fConfig)) {
7396fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
74d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon    } else {
75eae6200acbec2255ac00ab363ffbe16758ec9076bsalomon        return this->refScratchTexture(desc, scratchFlags);
76d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon    }
77d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon}
78d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon
79eae6200acbec2255ac00ab363ffbe16758ec9076bsalomonGrTexture* GrTextureProvider::refScratchTexture(const GrSurfaceDesc& inDesc,
807b77ac100e98f1037ae907c8830b808361f211e1brucedawson                                                uint32_t flags) {
816d0872d9bd97de5301214a258e141dd5fbeecffcjoshualitt    ASSERT_SINGLE_OWNER
82d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon    SkASSERT(!this->isAbandoned());
83d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon    SkASSERT(!GrPixelConfigIsCompressed(inDesc.fConfig));
84d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon
85d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon    SkTCopyOnFirstWrite<GrSurfaceDesc> desc(inDesc);
86d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon
87d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon    if (fGpu->caps()->reuseScratchTextures() || (desc->fFlags & kRenderTarget_GrSurfaceFlag)) {
887b77ac100e98f1037ae907c8830b808361f211e1brucedawson        if (!(kExact_ScratchTextureFlag & flags)) {
89d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon            // bin by pow2 with a reasonable min
90100b8f8c079510a6b7572f9ed8058c1d4a2bfebabsalomon            const int kMinSize = 16;
91d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon            GrSurfaceDesc* wdesc = desc.writable();
92100b8f8c079510a6b7572f9ed8058c1d4a2bfebabsalomon            wdesc->fWidth  = SkTMax(kMinSize, GrNextPow2(desc->fWidth));
93100b8f8c079510a6b7572f9ed8058c1d4a2bfebabsalomon            wdesc->fHeight = SkTMax(kMinSize, GrNextPow2(desc->fHeight));
94d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon        }
95d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon
96d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon        GrScratchKey key;
97d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon        GrTexturePriv::ComputeScratchKey(*desc, &key);
98d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon        uint32_t scratchFlags = 0;
997b77ac100e98f1037ae907c8830b808361f211e1brucedawson        if (kNoPendingIO_ScratchTextureFlag & flags) {
100d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon            scratchFlags = GrResourceCache::kRequireNoPendingIO_ScratchFlag;
101d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon        } else  if (!(desc->fFlags & kRenderTarget_GrSurfaceFlag)) {
102d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon            // If it is not a render target then it will most likely be populated by
103d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon            // writePixels() which will trigger a flush if the texture has pending IO.
104d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon            scratchFlags = GrResourceCache::kPreferNoPendingIO_ScratchFlag;
105d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon        }
1066e83ac778f8f90939abe3aee3ea865428dff592frobertphillips        GrGpuResource* resource = fCache->findAndRefScratchResource(key,
1076e83ac778f8f90939abe3aee3ea865428dff592frobertphillips                                                                   GrSurface::WorseCaseSize(*desc),
1086e83ac778f8f90939abe3aee3ea865428dff592frobertphillips                                                                   scratchFlags);
109d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon        if (resource) {
110d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon            GrSurface* surface = static_cast<GrSurface*>(resource);
111d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon            GrRenderTarget* rt = surface->asRenderTarget();
112d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon            if (rt && fGpu->caps()->discardRenderTargetSupport()) {
113d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon                rt->discard();
114d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon            }
115d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon            return surface->asTexture();
116d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon        }
117d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon    }
118d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon
1197b77ac100e98f1037ae907c8830b808361f211e1brucedawson    if (!(kNoCreate_ScratchTextureFlag & flags)) {
1205ec26ae9bfca635ccc98283aad5deda11519d826bsalomon        return fGpu->createTexture(*desc, SkBudgeted::kYes, nullptr, 0);
121d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon    }
122d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon
12396fcdcc219d2a0d3579719b84b28bede76efba64halcanary    return nullptr;
124d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon}
125d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon
1266dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomonGrTexture* GrTextureProvider::wrapBackendTexture(const GrBackendTextureDesc& desc,
1276dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon                                                 GrWrapOwnership ownership) {
1286d0872d9bd97de5301214a258e141dd5fbeecffcjoshualitt    ASSERT_SINGLE_OWNER
129d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon    if (this->isAbandoned()) {
13096fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
131d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon    }
1326dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon    return fGpu->wrapBackendTexture(desc, ownership);
133d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon}
134d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon
135d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomonGrRenderTarget* GrTextureProvider::wrapBackendRenderTarget(const GrBackendRenderTargetDesc& desc) {
1366d0872d9bd97de5301214a258e141dd5fbeecffcjoshualitt    ASSERT_SINGLE_OWNER
13796fcdcc219d2a0d3579719b84b28bede76efba64halcanary    return this->isAbandoned() ? nullptr : fGpu->wrapBackendRenderTarget(desc,
1386d0872d9bd97de5301214a258e141dd5fbeecffcjoshualitt                                                                         kBorrow_GrWrapOwnership);
139d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon}
140d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon
141d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomonvoid GrTextureProvider::assignUniqueKeyToResource(const GrUniqueKey& key, GrGpuResource* resource) {
1426d0872d9bd97de5301214a258e141dd5fbeecffcjoshualitt    ASSERT_SINGLE_OWNER
143d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon    if (this->isAbandoned() || !resource) {
144d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon        return;
145d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon    }
146d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon    resource->resourcePriv().setUniqueKey(key);
147d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon}
148d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon
149d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomonbool GrTextureProvider::existsResourceWithUniqueKey(const GrUniqueKey& key) const {
1506d0872d9bd97de5301214a258e141dd5fbeecffcjoshualitt    ASSERT_SINGLE_OWNER
151d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon    return this->isAbandoned() ? false : fCache->hasUniqueKey(key);
152d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon}
153d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon
154d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomonGrGpuResource* GrTextureProvider::findAndRefResourceByUniqueKey(const GrUniqueKey& key) {
1556d0872d9bd97de5301214a258e141dd5fbeecffcjoshualitt    ASSERT_SINGLE_OWNER
15696fcdcc219d2a0d3579719b84b28bede76efba64halcanary    return this->isAbandoned() ? nullptr : fCache->findAndRefUniqueResource(key);
157d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon}
1586d0872d9bd97de5301214a258e141dd5fbeecffcjoshualitt
1596d0872d9bd97de5301214a258e141dd5fbeecffcjoshualittGrTexture* GrTextureProvider::findAndRefTextureByUniqueKey(const GrUniqueKey& key) {
1606d0872d9bd97de5301214a258e141dd5fbeecffcjoshualitt    ASSERT_SINGLE_OWNER
1616d0872d9bd97de5301214a258e141dd5fbeecffcjoshualitt    GrGpuResource* resource = this->findAndRefResourceByUniqueKey(key);
1626d0872d9bd97de5301214a258e141dd5fbeecffcjoshualitt    if (resource) {
1636d0872d9bd97de5301214a258e141dd5fbeecffcjoshualitt        GrTexture* texture = static_cast<GrSurface*>(resource)->asTexture();
1646d0872d9bd97de5301214a258e141dd5fbeecffcjoshualitt        SkASSERT(texture);
1656d0872d9bd97de5301214a258e141dd5fbeecffcjoshualitt        return texture;
1666d0872d9bd97de5301214a258e141dd5fbeecffcjoshualitt    }
1676d0872d9bd97de5301214a258e141dd5fbeecffcjoshualitt    return NULL;
1686d0872d9bd97de5301214a258e141dd5fbeecffcjoshualitt}
169