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