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