Home | History | Annotate | Download | only in core
      1 /*
      2  * Copyright 2017 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 #include "SkDeferredDisplayListRecorder.h"
      9 #include "SkMessageBus.h"
     10 #include "SkDeferredDisplayList.h"
     11 #include "SkSurface.h"
     12 #include "SkSurfaceCharacterization.h"
     13 
     14 #if !SK_SUPPORT_GPU
     15 SkDeferredDisplayListRecorder::SkDeferredDisplayListRecorder(const SkSurfaceCharacterization&) {}
     16 
     17 SkDeferredDisplayListRecorder::~SkDeferredDisplayListRecorder() {}
     18 
     19 bool SkDeferredDisplayListRecorder::init() { return false; }
     20 
     21 SkCanvas* SkDeferredDisplayListRecorder::getCanvas() { return nullptr; }
     22 
     23 std::unique_ptr<SkDeferredDisplayList> SkDeferredDisplayListRecorder::detach() { return nullptr; }
     24 
     25 sk_sp<SkImage> SkDeferredDisplayListRecorder::makePromiseTexture(
     26         const GrBackendFormat& backendFormat,
     27         int width,
     28         int height,
     29         GrMipMapped mipMapped,
     30         GrSurfaceOrigin origin,
     31         SkColorType colorType,
     32         SkAlphaType alphaType,
     33         sk_sp<SkColorSpace> colorSpace,
     34         PromiseImageTextureFulfillProc textureFulfillProc,
     35         PromiseImageTextureReleaseProc textureReleaseProc,
     36         PromiseImageTextureDoneProc textureDoneProc,
     37         PromiseImageTextureContext textureContext,
     38         DelayReleaseCallback delayReleaseCallback) {
     39     return nullptr;
     40 }
     41 
     42 sk_sp<SkImage> SkDeferredDisplayListRecorder::makeYUVAPromiseTexture(
     43         SkYUVColorSpace yuvColorSpace,
     44         const GrBackendFormat yuvaFormats[],
     45         const SkISize yuvaSizes[],
     46         const SkYUVAIndex yuvaIndices[4],
     47         int imageWidth,
     48         int imageHeight,
     49         GrSurfaceOrigin imageOrigin,
     50         sk_sp<SkColorSpace> imageColorSpace,
     51         PromiseImageTextureFulfillProc textureFulfillProc,
     52         PromiseImageTextureReleaseProc textureReleaseProc,
     53         PromiseImageTextureDoneProc textureDoneProc,
     54         PromiseImageTextureContext textureContexts[],
     55         DelayReleaseCallback delayReleaseCallback) {
     56     return nullptr;
     57 }
     58 
     59 #else
     60 
     61 #include "GrContextPriv.h"
     62 #include "GrProxyProvider.h"
     63 #include "GrRenderTargetContext.h"
     64 #include "GrTexture.h"
     65 #include "SkGr.h"
     66 #include "SkImage_Gpu.h"
     67 #include "SkImage_GpuYUVA.h"
     68 #include "SkMakeUnique.h"
     69 #include "SkPromiseImageTexture.h"
     70 #include "SkSurface_Gpu.h"
     71 #include "SkYUVASizeInfo.h"
     72 
     73 SkDeferredDisplayListRecorder::SkDeferredDisplayListRecorder(const SkSurfaceCharacterization& c)
     74         : fCharacterization(c) {
     75     if (fCharacterization.isValid()) {
     76         fContext = GrContextPriv::MakeDDL(fCharacterization.refContextInfo());
     77     }
     78 }
     79 
     80 SkDeferredDisplayListRecorder::~SkDeferredDisplayListRecorder() {
     81     if (fContext) {
     82         auto proxyProvider = fContext->contextPriv().proxyProvider();
     83 
     84         // This allows the uniquely keyed proxies to keep their keys but removes their back
     85         // pointer to the about-to-be-deleted proxy provider. The proxies will use their
     86         // unique key to reattach to cached versions of themselves or to appropriately tag new
     87         // resources (if a cached version was not found). This system operates independent of
     88         // the replaying context's proxy provider (i.e., these uniquely keyed proxies will not
     89         // appear in the replaying proxy providers uniquely keyed proxy map). This should be fine
     90         // since no one else should be trying to reconnect to the orphaned proxies and orphaned
     91         // proxies from different DDLs that share the same key should simply reconnect to the
     92         // same cached resource.
     93         proxyProvider->orphanAllUniqueKeys();
     94     }
     95 }
     96 
     97 
     98 bool SkDeferredDisplayListRecorder::init() {
     99     SkASSERT(fContext);
    100     SkASSERT(!fLazyProxyData);
    101     SkASSERT(!fSurface);
    102 
    103     if (!fCharacterization.isValid()) {
    104         return false;
    105     }
    106 
    107     fLazyProxyData = sk_sp<SkDeferredDisplayList::LazyProxyData>(
    108                                                     new SkDeferredDisplayList::LazyProxyData);
    109 
    110     auto proxyProvider = fContext->contextPriv().proxyProvider();
    111 
    112     bool usesGLFBO0 = fCharacterization.usesGLFBO0();
    113     if (usesGLFBO0) {
    114         if (GrBackendApi::kOpenGL != fContext->backend() ||
    115             fCharacterization.isTextureable()) {
    116             return false;
    117         }
    118     }
    119 
    120     GrSurfaceDesc desc;
    121     desc.fFlags = kRenderTarget_GrSurfaceFlag;
    122     desc.fWidth = fCharacterization.width();
    123     desc.fHeight = fCharacterization.height();
    124     desc.fConfig = fCharacterization.config();
    125     desc.fSampleCnt = fCharacterization.stencilCount();
    126 
    127     sk_sp<SkDeferredDisplayList::LazyProxyData> lazyProxyData = fLazyProxyData;
    128 
    129     // What we're doing here is we're creating a lazy proxy to back the SkSurface. The lazy
    130     // proxy, when instantiated, will use the GrRenderTarget that backs the SkSurface that the
    131     // DDL is being replayed into.
    132 
    133     GrInternalSurfaceFlags surfaceFlags = GrInternalSurfaceFlags::kNone;
    134     if (fContext->contextPriv().caps()->usesMixedSamples() && desc.fSampleCnt > 1 && !usesGLFBO0) {
    135         // In GL, FBO 0 never supports mixed samples
    136         surfaceFlags |= GrInternalSurfaceFlags::kMixedSampled;
    137     }
    138     if (usesGLFBO0) {
    139         surfaceFlags |= GrInternalSurfaceFlags::kGLRTFBOIDIs0;
    140     }
    141     static constexpr GrProxyProvider::TextureInfo kTextureInfo{GrMipMapped::kNo,
    142                                                                GrTextureType::k2D};
    143     const GrProxyProvider::TextureInfo* optionalTextureInfo = nullptr;
    144     if (fCharacterization.isTextureable()) {
    145         optionalTextureInfo = &kTextureInfo;
    146     }
    147 
    148     const GrBackendFormat format = fContext->contextPriv().caps()->getBackendFormatFromColorType(
    149             fCharacterization.colorType());
    150 
    151     sk_sp<GrRenderTargetProxy> proxy = proxyProvider->createLazyRenderTargetProxy(
    152             [lazyProxyData](GrResourceProvider* resourceProvider) {
    153                 if (!resourceProvider) {
    154                     return sk_sp<GrSurface>();
    155                 }
    156 
    157                 // The proxy backing the destination surface had better have been instantiated
    158                 // prior to the proxy backing the DLL's surface. Steal its GrRenderTarget.
    159                 SkASSERT(lazyProxyData->fReplayDest->peekSurface());
    160                 return sk_ref_sp<GrSurface>(lazyProxyData->fReplayDest->peekSurface());
    161             },
    162             format,
    163             desc,
    164             fCharacterization.origin(),
    165             surfaceFlags,
    166             optionalTextureInfo,
    167             SkBackingFit::kExact,
    168             SkBudgeted::kYes);
    169 
    170     sk_sp<GrSurfaceContext> c = fContext->contextPriv().makeWrappedSurfaceContext(
    171                                                                  std::move(proxy),
    172                                                                  fCharacterization.refColorSpace(),
    173                                                                  &fCharacterization.surfaceProps());
    174     fSurface = SkSurface_Gpu::MakeWrappedRenderTarget(fContext.get(),
    175                                                       sk_ref_sp(c->asRenderTargetContext()));
    176     return SkToBool(fSurface.get());
    177 }
    178 
    179 SkCanvas* SkDeferredDisplayListRecorder::getCanvas() {
    180     if (!fContext) {
    181         return nullptr;
    182     }
    183 
    184     if (!fSurface && !this->init()) {
    185         return nullptr;
    186     }
    187 
    188     return fSurface->getCanvas();
    189 }
    190 
    191 std::unique_ptr<SkDeferredDisplayList> SkDeferredDisplayListRecorder::detach() {
    192     if (!fContext) {
    193         return nullptr;
    194     }
    195 
    196     if (fSurface) {
    197         SkCanvas* canvas = fSurface->getCanvas();
    198 
    199         canvas->restoreToCount(0);
    200     }
    201 
    202     auto ddl = std::unique_ptr<SkDeferredDisplayList>(
    203                            new SkDeferredDisplayList(fCharacterization, std::move(fLazyProxyData)));
    204 
    205     fContext->contextPriv().moveOpListsToDDL(ddl.get());
    206 
    207     // We want a new lazy proxy target for each recorded DDL so force the (lazy proxy-backed)
    208     // SkSurface to be regenerated for each DDL.
    209     fSurface = nullptr;
    210     return ddl;
    211 }
    212 
    213 sk_sp<SkImage> SkDeferredDisplayListRecorder::makePromiseTexture(
    214         const GrBackendFormat& backendFormat,
    215         int width,
    216         int height,
    217         GrMipMapped mipMapped,
    218         GrSurfaceOrigin origin,
    219         SkColorType colorType,
    220         SkAlphaType alphaType,
    221         sk_sp<SkColorSpace> colorSpace,
    222         PromiseImageTextureFulfillProc textureFulfillProc,
    223         PromiseImageTextureReleaseProc textureReleaseProc,
    224         PromiseImageTextureDoneProc textureDoneProc,
    225         PromiseImageTextureContext textureContext,
    226         DelayReleaseCallback delayReleaseCallback) {
    227     if (!fContext) {
    228         return nullptr;
    229     }
    230 
    231     return SkImage_Gpu::MakePromiseTexture(fContext.get(),
    232                                            backendFormat,
    233                                            width,
    234                                            height,
    235                                            mipMapped,
    236                                            origin,
    237                                            colorType,
    238                                            alphaType,
    239                                            std::move(colorSpace),
    240                                            textureFulfillProc,
    241                                            textureReleaseProc,
    242                                            textureDoneProc,
    243                                            textureContext,
    244                                            delayReleaseCallback);
    245 }
    246 
    247 sk_sp<SkImage> SkDeferredDisplayListRecorder::makeYUVAPromiseTexture(
    248         SkYUVColorSpace yuvColorSpace,
    249         const GrBackendFormat yuvaFormats[],
    250         const SkISize yuvaSizes[],
    251         const SkYUVAIndex yuvaIndices[4],
    252         int imageWidth,
    253         int imageHeight,
    254         GrSurfaceOrigin imageOrigin,
    255         sk_sp<SkColorSpace> imageColorSpace,
    256         PromiseImageTextureFulfillProc textureFulfillProc,
    257         PromiseImageTextureReleaseProc textureReleaseProc,
    258         PromiseImageTextureDoneProc textureDoneProc,
    259         PromiseImageTextureContext textureContexts[],
    260         DelayReleaseCallback delayReleaseCallback) {
    261     if (!fContext) {
    262         return nullptr;
    263     }
    264 
    265     return SkImage_GpuYUVA::MakePromiseYUVATexture(fContext.get(),
    266                                                    yuvColorSpace,
    267                                                    yuvaFormats,
    268                                                    yuvaSizes,
    269                                                    yuvaIndices,
    270                                                    imageWidth,
    271                                                    imageHeight,
    272                                                    imageOrigin,
    273                                                    std::move(imageColorSpace),
    274                                                    textureFulfillProc,
    275                                                    textureReleaseProc,
    276                                                    textureDoneProc,
    277                                                    textureContexts,
    278                                                    delayReleaseCallback);
    279 }
    280 
    281 #endif
    282