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 
     10 #if SK_SUPPORT_GPU
     11 #include "GrContextPriv.h"
     12 #include "GrProxyProvider.h"
     13 #include "GrTexture.h"
     14 
     15 #include "SkGpuDevice.h"
     16 #include "SkGr.h"
     17 #include "SkSurface_Gpu.h"
     18 #endif
     19 
     20 #include "SkCanvas.h" // TODO: remove
     21 #include "SkDeferredDisplayList.h"
     22 #include "SkSurface.h"
     23 #include "SkSurfaceCharacterization.h"
     24 
     25 SkDeferredDisplayListRecorder::SkDeferredDisplayListRecorder(
     26                     const SkSurfaceCharacterization& characterization)
     27         : fCharacterization(characterization) {
     28 }
     29 
     30 SkDeferredDisplayListRecorder::~SkDeferredDisplayListRecorder() {
     31 #if SK_SUPPORT_GPU && !defined(SK_RASTER_RECORDER_IMPLEMENTATION)
     32     auto proxyProvider = fContext->contextPriv().proxyProvider();
     33 
     34     // DDL TODO: Remove this. DDL contexts should allow for deletion while still having live
     35     // uniquely keyed proxies.
     36     proxyProvider->removeAllUniqueKeys();
     37 #endif
     38 }
     39 
     40 
     41 bool SkDeferredDisplayListRecorder::init() {
     42     SkASSERT(!fSurface);
     43 
     44     if (!fCharacterization.isValid()) {
     45         return false;
     46     }
     47 
     48 #ifdef SK_RASTER_RECORDER_IMPLEMENTATION
     49     // Use raster right now to allow threading
     50     const SkImageInfo ii = SkImageInfo::Make(fCharacterization.width(), fCharacterization.height(),
     51                                              kN32_SkColorType, kOpaque_SkAlphaType,
     52                                              fCharacterization.refColorSpace());
     53 
     54     fSurface = SkSurface::MakeRaster(ii, &fCharacterization.surfaceProps());
     55     return SkToBool(fSurface.get());
     56 #else
     57     SkASSERT(!fLazyProxyData);
     58 
     59 #if SK_SUPPORT_GPU
     60     if (!fContext) {
     61         fContext = GrContextPriv::MakeDDL(fCharacterization.refContextInfo());
     62         if (!fContext) {
     63             return false;
     64         }
     65     }
     66 
     67     fLazyProxyData = sk_sp<SkDeferredDisplayList::LazyProxyData>(
     68                                                     new SkDeferredDisplayList::LazyProxyData);
     69 
     70     auto proxyProvider = fContext->contextPriv().proxyProvider();
     71 
     72     GrSurfaceDesc desc;
     73     desc.fFlags = kRenderTarget_GrSurfaceFlag;
     74     desc.fOrigin = fCharacterization.origin();
     75     desc.fWidth = fCharacterization.width();
     76     desc.fHeight = fCharacterization.height();
     77     desc.fConfig = fCharacterization.config();
     78     desc.fSampleCnt = fCharacterization.stencilCount();
     79 
     80     sk_sp<SkDeferredDisplayList::LazyProxyData> lazyProxyData = fLazyProxyData;
     81 
     82     // What we're doing here is we're creating a lazy proxy to back the SkSurface. The lazy
     83     // proxy, when instantiated, will use the GrRenderTarget that backs the SkSurface that the
     84     // DDL is being replayed into.
     85 
     86     sk_sp<GrRenderTargetProxy> proxy = proxyProvider->createLazyRenderTargetProxy(
     87             [ lazyProxyData ] (GrResourceProvider* resourceProvider) {
     88                 if (!resourceProvider) {
     89                     return sk_sp<GrSurface>();
     90                 }
     91 
     92                 // The proxy backing the destination surface had better have been instantiated
     93                 // prior to the proxy backing the DLL's surface. Steal its GrRenderTarget.
     94                 SkASSERT(lazyProxyData->fReplayDest->priv().peekSurface());
     95                 return sk_ref_sp<GrSurface>(lazyProxyData->fReplayDest->priv().peekSurface());
     96             },
     97             desc,
     98             GrRenderTargetFlags::kNone,
     99             GrProxyProvider::Textureable(fCharacterization.isTextureable()),
    100             GrMipMapped::kNo,
    101             SkBackingFit::kExact,
    102             SkBudgeted::kYes);
    103 
    104     sk_sp<GrSurfaceContext> c = fContext->contextPriv().makeWrappedSurfaceContext(
    105                                                                  std::move(proxy),
    106                                                                  fCharacterization.refColorSpace(),
    107                                                                  &fCharacterization.surfaceProps());
    108     fSurface = SkSurface_Gpu::MakeWrappedRenderTarget(fContext.get(),
    109                                                       sk_ref_sp(c->asRenderTargetContext()));
    110     return SkToBool(fSurface.get());
    111 #else
    112     return false;
    113 #endif
    114 
    115 #endif
    116 }
    117 
    118 SkCanvas* SkDeferredDisplayListRecorder::getCanvas() {
    119     if (!fSurface) {
    120         if (!this->init()) {
    121             return nullptr;
    122         }
    123     }
    124 
    125     return fSurface->getCanvas();
    126 }
    127 
    128 std::unique_ptr<SkDeferredDisplayList> SkDeferredDisplayListRecorder::detach() {
    129 #ifdef SK_RASTER_RECORDER_IMPLEMENTATION
    130     sk_sp<SkImage> img = fSurface->makeImageSnapshot();
    131     fSurface.reset();
    132 
    133     // TODO: need to wrap the opLists associated with the deferred draws
    134     // in the SkDeferredDisplayList.
    135     return std::unique_ptr<SkDeferredDisplayList>(
    136                             new SkDeferredDisplayList(fCharacterization, std::move(img)));
    137 #else
    138 
    139 #if SK_SUPPORT_GPU
    140     auto ddl = std::unique_ptr<SkDeferredDisplayList>(
    141                            new SkDeferredDisplayList(fCharacterization, std::move(fLazyProxyData)));
    142 
    143     fContext->contextPriv().moveOpListsToDDL(ddl.get());
    144     return ddl;
    145 #else
    146     return nullptr;
    147 #endif
    148 
    149 #endif // SK_RASTER_RECORDER_IMPLEMENTATION
    150 
    151 }
    152 
    153