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 #ifndef SkDeferredDisplayListRecorder_DEFINED
9 #define SkDeferredDisplayListRecorder_DEFINED
10 
11 #include "include/core/SkImageInfo.h"
12 #include "include/core/SkRefCnt.h"
13 #include "include/core/SkSurfaceCharacterization.h"
14 #include "include/core/SkTypes.h"
15 #include "include/private/SkDeferredDisplayList.h"
16 
17 class GrBackendFormat;
18 class GrBackendTexture;
19 class GrContext;
20 class SkCanvas;
21 class SkImage;
22 class SkPromiseImageTexture;
23 class SkSurface;
24 struct SkYUVAIndex;
25 struct SkYUVASizeInfo;
26 
27 /*
28  * This class is intended to be used as:
29  *   Get an SkSurfaceCharacterization representing the intended gpu-backed destination SkSurface
30  *   Create one of these (an SkDDLMaker) on the stack
31  *   Get the canvas and render into it
32  *   Snap off and hold on to an SkDeferredDisplayList
33  *   Once your app actually needs the pixels, call SkSurface::draw(SkDeferredDisplayList*)
34  *
35  * This class never accesses the GPU but performs all the cpu work it can. It
36  * is thread-safe (i.e., one can break a scene into tiles and perform their cpu-side
37  * work in parallel ahead of time).
38  */
39 class SK_API SkDeferredDisplayListRecorder {
40 public:
41     SkDeferredDisplayListRecorder(const SkSurfaceCharacterization&);
42     ~SkDeferredDisplayListRecorder();
43 
characterization()44     const SkSurfaceCharacterization& characterization() const {
45         return fCharacterization;
46     }
47 
48     // The backing canvas will become invalid (and this entry point will return
49     // null) once 'detach' is called.
50     // Note: ownership of the SkCanvas is not transferred via this call.
51     SkCanvas* getCanvas();
52 
53     std::unique_ptr<SkDeferredDisplayList> detach();
54 
55     using PromiseImageTextureContext = void*;
56     using PromiseImageTextureFulfillProc =
57             sk_sp<SkPromiseImageTexture> (*)(PromiseImageTextureContext);
58     using PromiseImageTextureReleaseProc = void (*)(PromiseImageTextureContext);
59     using PromiseImageTextureDoneProc = void (*)(PromiseImageTextureContext);
60 
61     enum class PromiseImageApiVersion { kLegacy, kNew };
62 
63     /**
64         Create a new SkImage that is very similar to an SkImage created by MakeFromTexture. The
65         difference is that the caller need not have created the texture nor populated it with the
66         image pixel data. Moreover, the SkImage may be created on a thread as the creation of the
67         image does not require access to the backend API or GrContext. Instead of passing a
68         GrBackendTexture the client supplies a description of the texture consisting of
69         GrBackendFormat, width, height, and GrMipMapped state. The resulting SkImage can be drawn
70         to a SkDeferredDisplayListRecorder or directly to a GPU-backed SkSurface.
71 
72         When the actual texture is required to perform a backend API draw, textureFulfillProc will
73         be called to receive a GrBackendTexture. The properties of the GrBackendTexture must match
74         those set during the SkImage creation, and it must refer to a valid existing texture in the
75         backend API context/device, and be populated with the image pixel data. The texture contents
76         cannot be modified until textureReleaseProc is called. The texture cannot be deleted until
77         textureDoneProc is called.
78 
79         When all the following are true:
80             * the promise SkImage is deleted,
81             * any SkDeferredDisplayLists that recorded draws referencing the image are deleted,
82             * and all draws referencing the texture have been flushed (via GrContext::flush or
83               SkSurface::flush)
84         the textureReleaseProc is called. When the following additional constraint is met
85            * the texture is safe to delete in the underlying API
86         the textureDoneProc is called. For some APIs (e.g. GL) the two states are equivalent.
87         However, for others (e.g. Vulkan) they are not as it is not legal to delete a texture until
88         the GPU work referencing it has completed.
89 
90         There is at most one call to each of textureFulfillProc, textureReleaseProc, and
91         textureDoneProc. textureDoneProc is always called even if image creation fails or if the
92         image is never fulfilled (e.g. it is never drawn or all draws are clipped out). If
93         textureFulfillProc is called then textureReleaseProc will always be called even if
94         textureFulfillProc failed.
95 
96         If 'version' is set to kLegacy then the textureReleaseProc call is delayed until the
97         conditions for textureDoneProc are met and then they are both called.
98 
99         This call is only valid if the SkDeferredDisplayListRecorder is backed by a GPU context.
100 
101         @param backendFormat       format of promised gpu texture
102         @param width               width of promised gpu texture
103         @param height              height of promised gpu texture
104         @param mipMapped           mip mapped state of promised gpu texture
105         @param origin              one of: kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin
106         @param colorType           one of: kUnknown_SkColorType, kAlpha_8_SkColorType,
107                                    kRGB_565_SkColorType, kARGB_4444_SkColorType,
108                                    kRGBA_8888_SkColorType, kBGRA_8888_SkColorType,
109                                    kGray_8_SkColorType, kRGBA_F16_SkColorType
110         @param alphaType           one of: kUnknown_SkAlphaType, kOpaque_SkAlphaType,
111                                    kPremul_SkAlphaType, kUnpremul_SkAlphaType
112         @param colorSpace          range of colors; may be nullptr
113         @param textureFulfillProc  function called to get actual gpu texture
114         @param textureReleaseProc  function called when texture can be released
115         @param textureDoneProc     function called when we will no longer call textureFulfillProc
116         @param textureContext      state passed to textureFulfillProc and textureReleaseProc
117         @param version             controls when textureReleaseProc is called
118         @return                    created SkImage, or nullptr
119      */
120     sk_sp<SkImage> makePromiseTexture(
121             const GrBackendFormat& backendFormat,
122             int width,
123             int height,
124             GrMipMapped mipMapped,
125             GrSurfaceOrigin origin,
126             SkColorType colorType,
127             SkAlphaType alphaType,
128             sk_sp<SkColorSpace> colorSpace,
129             PromiseImageTextureFulfillProc textureFulfillProc,
130             PromiseImageTextureReleaseProc textureReleaseProc,
131             PromiseImageTextureDoneProc textureDoneProc,
132             PromiseImageTextureContext textureContext,
133             PromiseImageApiVersion version = PromiseImageApiVersion::kLegacy);
134 
135     /**
136         This entry point operates like 'makePromiseTexture' but it is used to construct a SkImage
137         from YUV[A] data. The source data may be planar (i.e. spread across multiple textures). In
138         the extreme Y, U, V, and A are all in different planes and thus the image is specified by
139         four textures. 'yuvaIndices' specifies the mapping from texture color channels to Y, U, V,
140         and possibly A components. It therefore indicates how many unique textures compose the full
141         image. Separate textureFulfillProc, textureReleaseProc, and textureDoneProc calls are made
142         for each texture and each texture has its own PromiseImageTextureContext. 'yuvFormats',
143         'yuvaSizes', and 'textureContexts' have one entry for each of the up to four textures, as
144         indicated by 'yuvaIndices'.
145      */
146     sk_sp<SkImage> makeYUVAPromiseTexture(
147             SkYUVColorSpace yuvColorSpace,
148             const GrBackendFormat yuvaFormats[],
149             const SkISize yuvaSizes[],
150             const SkYUVAIndex yuvaIndices[4],
151             int imageWidth,
152             int imageHeight,
153             GrSurfaceOrigin imageOrigin,
154             sk_sp<SkColorSpace> imageColorSpace,
155             PromiseImageTextureFulfillProc textureFulfillProc,
156             PromiseImageTextureReleaseProc textureReleaseProc,
157             PromiseImageTextureDoneProc textureDoneProc,
158             PromiseImageTextureContext textureContexts[],
159             PromiseImageApiVersion version = PromiseImageApiVersion::kLegacy);
160 
161 private:
162     bool init();
163 
164     const SkSurfaceCharacterization             fCharacterization;
165 
166 #if SK_SUPPORT_GPU
167     sk_sp<GrContext>                            fContext;
168     sk_sp<SkDeferredDisplayList::LazyProxyData> fLazyProxyData;
169     sk_sp<SkSurface>                            fSurface;
170 #endif
171 };
172 
173 #endif
174