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 GrBackendSurface_DEFINED
9 #define GrBackendSurface_DEFINED
10 
11 #include "include/gpu/GrTypes.h"
12 #include "include/gpu/gl/GrGLTypes.h"
13 #include "include/gpu/mock/GrMockTypes.h"
14 #include "include/gpu/vk/GrVkTypes.h"
15 #include "include/private/GrGLTypesPriv.h"
16 #include "include/private/GrVkTypesPriv.h"
17 
18 #ifdef SK_DAWN
19 #include "include/gpu/dawn/GrDawnTypes.h"
20 #endif
21 
22 class GrVkImageLayout;
23 class GrGLTextureParameters;
24 
25 #ifdef SK_DAWN
26 #include "dawn/webgpu_cpp.h"
27 #endif
28 
29 #ifdef SK_METAL
30 #include "include/gpu/mtl/GrMtlTypes.h"
31 #endif
32 
33 #ifdef SK_DIRECT3D
34 #include "include/gpu/d3d/GrD3DTypesMinimal.h"
35 #include "include/private/GrD3DTypesPriv.h"
36 class GrD3DResourceState;
37 #endif
38 
39 #if GR_TEST_UTILS
40 class SkString;
41 #endif
42 
43 #if !SK_SUPPORT_GPU
44 
45 // SkSurfaceCharacterization always needs a minimal version of this
46 class SK_API GrBackendFormat {
47 public:
isValid()48     bool isValid() const { return false; }
49 };
50 
51 // SkSurface and SkImage rely on a minimal version of these always being available
52 class SK_API GrBackendTexture {
53 public:
GrBackendTexture()54     GrBackendTexture() {}
55 
isValid()56     bool isValid() const { return false; }
57 };
58 
59 class SK_API GrBackendRenderTarget {
60 public:
GrBackendRenderTarget()61     GrBackendRenderTarget() {}
62 
isValid()63     bool isValid() const { return false; }
isFramebufferOnly()64     bool isFramebufferOnly() const { return false; }
65 };
66 #else
67 
68 enum class GrGLFormat;
69 
70 class SK_API GrBackendFormat {
71 public:
72     // Creates an invalid backend format.
GrBackendFormat()73     GrBackendFormat() {}
74     GrBackendFormat(const GrBackendFormat&);
75     GrBackendFormat& operator=(const GrBackendFormat&);
76 
MakeGL(GrGLenum format,GrGLenum target)77     static GrBackendFormat MakeGL(GrGLenum format, GrGLenum target) {
78         return GrBackendFormat(format, target);
79     }
80 
MakeVk(VkFormat format)81     static GrBackendFormat MakeVk(VkFormat format) {
82         return GrBackendFormat(format, GrVkYcbcrConversionInfo());
83     }
84 
85     static GrBackendFormat MakeVk(const GrVkYcbcrConversionInfo& ycbcrInfo);
86 
87 #ifdef SK_DAWN
MakeDawn(wgpu::TextureFormat format)88     static GrBackendFormat MakeDawn(wgpu::TextureFormat format) {
89         return GrBackendFormat(format);
90     }
91 #endif
92 
93 #ifdef SK_METAL
MakeMtl(GrMTLPixelFormat format)94     static GrBackendFormat MakeMtl(GrMTLPixelFormat format) {
95         return GrBackendFormat(format);
96     }
97 #endif
98 
99 #ifdef SK_DIRECT3D
MakeDxgi(DXGI_FORMAT format)100     static GrBackendFormat MakeDxgi(DXGI_FORMAT format) {
101         return GrBackendFormat(format);
102     }
103 #endif
104 
105     static GrBackendFormat MakeMock(GrColorType colorType, SkImage::CompressionType compression);
106 
107     bool operator==(const GrBackendFormat& that) const;
108     bool operator!=(const GrBackendFormat& that) const { return !(*this == that); }
109 
backend()110     GrBackendApi backend() const { return fBackend; }
textureType()111     GrTextureType textureType() const { return fTextureType; }
112 
113     /**
114      * If the backend API is GL this gets the format as a GrGLFormat. Otherwise, returns
115      * GrGLFormat::kUnknown.
116      */
117     GrGLFormat asGLFormat() const;
118 
119     /**
120      * If the backend API is Vulkan this gets the format as a VkFormat and returns true. Otherwise,
121      * returns false.
122      */
123     bool asVkFormat(VkFormat*) const;
124 
125     const GrVkYcbcrConversionInfo* getVkYcbcrConversionInfo() const;
126 
127 #ifdef SK_DAWN
128     /**
129      * If the backend API is Dawn this gets the format as a wgpu::TextureFormat and returns true.
130      * Otherwise, returns false.
131      */
132     bool asDawnFormat(wgpu::TextureFormat*) const;
133 #endif
134 
135 #ifdef SK_METAL
136     /**
137      * If the backend API is Metal this gets the format as a GrMtlPixelFormat. Otherwise,
138      * Otherwise, returns MTLPixelFormatInvalid.
139      */
140     GrMTLPixelFormat asMtlFormat() const;
141 #endif
142 
143 #ifdef SK_DIRECT3D
144     /**
145      * If the backend API is Direct3D this gets the format as a DXGI_FORMAT and returns true.
146      * Otherwise, returns false.
147      */
148     bool asDxgiFormat(DXGI_FORMAT*) const;
149 #endif
150 
151     /**
152      * If the backend API is not Mock these two calls will return kUnknown and kNone, respectively.
153      * Otherwise, if the compression type is kNone then the GrColorType will be valid. If the
154      * compression type is anything other then kNone than the GrColorType will be kUnknown.
155      */
156     GrColorType asMockColorType() const;
157     SkImage::CompressionType asMockCompressionType() const;
158 
159     // If possible, copies the GrBackendFormat and forces the texture type to be Texture2D. If the
160     // GrBackendFormat was for Vulkan and it originally had a GrVkYcbcrConversionInfo, we will
161     // remove the conversion and set the format to be VK_FORMAT_R8G8B8A8_UNORM.
162     GrBackendFormat makeTexture2D() const;
163 
164     // Returns true if the backend format has been initialized.
isValid()165     bool isValid() const { return fValid; }
166 
167 #if GR_TEST_UTILS
168     SkString toStr() const;
169 #endif
170 
171 private:
172     GrBackendFormat(GrGLenum format, GrGLenum target);
173 
174     GrBackendFormat(const VkFormat vkFormat, const GrVkYcbcrConversionInfo&);
175 
176 #ifdef SK_DAWN
177     GrBackendFormat(wgpu::TextureFormat format);
178 #endif
179 
180 #ifdef SK_METAL
181     GrBackendFormat(const GrMTLPixelFormat mtlFormat);
182 #endif
183 
184 #ifdef SK_DIRECT3D
185     GrBackendFormat(DXGI_FORMAT dxgiFormat);
186 #endif
187 
188     GrBackendFormat(GrColorType, SkImage::CompressionType);
189 
190     GrBackendApi fBackend = GrBackendApi::kMock;
191     bool         fValid = false;
192 
193     union {
194         GrGLenum         fGLFormat; // the sized, internal format of the GL resource
195         struct {
196             VkFormat                 fFormat;
197             GrVkYcbcrConversionInfo  fYcbcrConversionInfo;
198         }                fVk;
199 #ifdef SK_DAWN
200         wgpu::TextureFormat fDawnFormat;
201 #endif
202 
203 #ifdef SK_METAL
204         GrMTLPixelFormat fMtlFormat;
205 #endif
206 
207 #ifdef SK_DIRECT3D
208         DXGI_FORMAT fDxgiFormat;
209 #endif
210         struct {
211             GrColorType              fColorType;
212             SkImage::CompressionType fCompressionType;
213         }                fMock;
214     };
215     GrTextureType fTextureType = GrTextureType::kNone;
216 };
217 
218 class SK_API GrBackendTexture {
219 public:
220     // Creates an invalid backend texture.
GrBackendTexture()221     GrBackendTexture() : fIsValid(false) {}
222 
223     // The GrGLTextureInfo must have a valid fFormat.
224     GrBackendTexture(int width,
225                      int height,
226                      GrMipMapped,
227                      const GrGLTextureInfo& glInfo);
228 
229     GrBackendTexture(int width,
230                      int height,
231                      const GrVkImageInfo& vkInfo);
232 
233 #ifdef SK_METAL
234     GrBackendTexture(int width,
235                      int height,
236                      GrMipMapped,
237                      const GrMtlTextureInfo& mtlInfo);
238 #endif
239 
240 #ifdef SK_DIRECT3D
241     GrBackendTexture(int width,
242                      int height,
243                      const GrD3DTextureResourceInfo& d3dInfo);
244 #endif
245 
246 #ifdef SK_DAWN
247     GrBackendTexture(int width,
248                      int height,
249                      const GrDawnTextureInfo& dawnInfo);
250 #endif
251 
252     GrBackendTexture(int width,
253                      int height,
254                      GrMipMapped,
255                      const GrMockTextureInfo& mockInfo);
256 
257     GrBackendTexture(const GrBackendTexture& that);
258 
259     ~GrBackendTexture();
260 
261     GrBackendTexture& operator=(const GrBackendTexture& that);
262 
dimensions()263     SkISize dimensions() const { return {fWidth, fHeight}; }
width()264     int width() const { return fWidth; }
height()265     int height() const { return fHeight; }
hasMipMaps()266     bool hasMipMaps() const { return GrMipMapped::kYes == fMipMapped; }
backend()267     GrBackendApi backend() const {return fBackend; }
268 
269     // If the backend API is GL, copies a snapshot of the GrGLTextureInfo struct into the passed in
270     // pointer and returns true. Otherwise returns false if the backend API is not GL.
271     bool getGLTextureInfo(GrGLTextureInfo*) const;
272 
273     // Call this to indicate that the texture parameters have been modified in the GL context
274     // externally to GrContext.
275     void glTextureParametersModified();
276 
277 #ifdef SK_DAWN
278     // If the backend API is Dawn, copies a snapshot of the GrDawnTextureInfo struct into the passed
279     // in pointer and returns true. Otherwise returns false if the backend API is not Dawn.
280     bool getDawnTextureInfo(GrDawnTextureInfo*) const;
281 #endif
282 
283     // If the backend API is Vulkan, copies a snapshot of the GrVkImageInfo struct into the passed
284     // in pointer and returns true. This snapshot will set the fImageLayout to the current layout
285     // state. Otherwise returns false if the backend API is not Vulkan.
286     bool getVkImageInfo(GrVkImageInfo*) const;
287 
288     // Anytime the client changes the VkImageLayout of the VkImage captured by this
289     // GrBackendTexture, they must call this function to notify Skia of the changed layout.
290     void setVkImageLayout(VkImageLayout);
291 
292 #ifdef SK_METAL
293     // If the backend API is Metal, copies a snapshot of the GrMtlTextureInfo struct into the passed
294     // in pointer and returns true. Otherwise returns false if the backend API is not Metal.
295     bool getMtlTextureInfo(GrMtlTextureInfo*) const;
296 #endif
297 
298 #ifdef SK_DIRECT3D
299     // If the backend API is Direct3D, copies a snapshot of the GrD3DTextureResourceInfo struct into
300     // the passed in pointer and returns true. This snapshot will set the fResourceState to the
301     // current resource state. Otherwise returns false if the backend API is not D3D.
302     bool getD3DTextureResourceInfo(GrD3DTextureResourceInfo*) const;
303 
304     // Anytime the client changes the D3D12_RESOURCE_STATES of the D3D12_RESOURCE captured by this
305     // GrBackendTexture, they must call this function to notify Skia of the changed layout.
306     void setD3DResourceState(GrD3DResourceStateEnum);
307 #endif
308 
309     // Get the GrBackendFormat for this texture (or an invalid format if this is not valid).
310     GrBackendFormat getBackendFormat() const;
311 
312     // If the backend API is Mock, copies a snapshot of the GrMockTextureInfo struct into the passed
313     // in pointer and returns true. Otherwise returns false if the backend API is not Mock.
314     bool getMockTextureInfo(GrMockTextureInfo*) const;
315 
316     // Returns true if we are working with protected content.
317     bool isProtected() const;
318 
319     // Returns true if the backend texture has been initialized.
isValid()320     bool isValid() const { return fIsValid; }
321 
322     // Returns true if both textures are valid and refer to the same API texture.
323     bool isSameTexture(const GrBackendTexture&);
324 
325 #if GR_TEST_UTILS
326     static bool TestingOnly_Equals(const GrBackendTexture& , const GrBackendTexture&);
327 #endif
328 
329 private:
330 
331 #ifdef SK_GL
332     friend class GrGLTexture;
333     friend class GrGLGpu;    // for getGLTextureParams
334     GrBackendTexture(int width,
335                      int height,
336                      GrMipMapped,
337                      const GrGLTextureInfo,
338                      sk_sp<GrGLTextureParameters>);
339     sk_sp<GrGLTextureParameters> getGLTextureParams() const;
340 #endif
341 
342 #ifdef SK_VULKAN
343     friend class GrVkTexture;
344     friend class GrVkGpu;    // for getGrVkImageLayout
345     GrBackendTexture(int width,
346                      int height,
347                      const GrVkImageInfo& vkInfo,
348                      sk_sp<GrVkImageLayout> layout);
349     sk_sp<GrVkImageLayout> getGrVkImageLayout() const;
350 #endif
351 
352 #ifdef SK_DIRECT3D
353     friend class GrD3DTexture;
354     friend class GrD3DGpu;     // for getGrD3DResourceState
355     GrBackendTexture(int width,
356                      int height,
357                      const GrD3DTextureResourceInfo& vkInfo,
358                      sk_sp<GrD3DResourceState> state);
359     sk_sp<GrD3DResourceState> getGrD3DResourceState() const;
360 #endif
361 
362     // Free and release and resources being held by the GrBackendTexture.
363     void cleanup();
364 
365     bool fIsValid;
366     int fWidth;         //<! width in pixels
367     int fHeight;        //<! height in pixels
368     GrMipMapped fMipMapped;
369     GrBackendApi fBackend;
370 
371     union {
372 #ifdef SK_GL
373         GrGLBackendTextureInfo fGLInfo;
374 #endif
375         GrVkBackendSurfaceInfo fVkInfo;
376         GrMockTextureInfo fMockInfo;
377 #ifdef SK_DIRECT3D
378         GrD3DBackendSurfaceInfo fD3DInfo;
379 #endif
380     };
381 #ifdef SK_METAL
382     GrMtlTextureInfo fMtlInfo;
383 #endif
384 #ifdef SK_DAWN
385     GrDawnTextureInfo fDawnInfo;
386 #endif
387 };
388 
389 class SK_API GrBackendRenderTarget {
390 public:
391     // Creates an invalid backend texture.
GrBackendRenderTarget()392     GrBackendRenderTarget() : fIsValid(false) {}
393 
394     // The GrGLTextureInfo must have a valid fFormat.
395     GrBackendRenderTarget(int width,
396                           int height,
397                           int sampleCnt,
398                           int stencilBits,
399                           const GrGLFramebufferInfo& glInfo);
400 
401 #ifdef SK_DAWN
402     GrBackendRenderTarget(int width,
403                           int height,
404                           int sampleCnt,
405                           int stencilBits,
406                           const GrDawnRenderTargetInfo& dawnInfo);
407 #endif
408 
409     /** Deprecated, use version that does not take stencil bits. */
410     GrBackendRenderTarget(int width,
411                           int height,
412                           int sampleCnt,
413                           int stencilBits,
414                           const GrVkImageInfo& vkInfo);
415     GrBackendRenderTarget(int width, int height, int sampleCnt, const GrVkImageInfo& vkInfo);
416 
417 #ifdef SK_METAL
418     GrBackendRenderTarget(int width,
419                           int height,
420                           int sampleCnt,
421                           const GrMtlTextureInfo& mtlInfo);
422 #endif
423 
424 #ifdef SK_DIRECT3D
425     GrBackendRenderTarget(int width,
426                           int height,
427                           int sampleCnt,
428                           const GrD3DTextureResourceInfo& d3dInfo);
429 #endif
430 
431     GrBackendRenderTarget(int width,
432                           int height,
433                           int sampleCnt,
434                           int stencilBits,
435                           const GrMockRenderTargetInfo& mockInfo);
436 
437     ~GrBackendRenderTarget();
438 
439     GrBackendRenderTarget(const GrBackendRenderTarget& that);
440     GrBackendRenderTarget& operator=(const GrBackendRenderTarget&);
441 
dimensions()442     SkISize dimensions() const { return {fWidth, fHeight}; }
width()443     int width() const { return fWidth; }
height()444     int height() const { return fHeight; }
sampleCnt()445     int sampleCnt() const { return fSampleCnt; }
stencilBits()446     int stencilBits() const { return fStencilBits; }
backend()447     GrBackendApi backend() const {return fBackend; }
isFramebufferOnly()448     bool isFramebufferOnly() const { return fFramebufferOnly; }
449 
450     // If the backend API is GL, copies a snapshot of the GrGLFramebufferInfo struct into the passed
451     // in pointer and returns true. Otherwise returns false if the backend API is not GL.
452     bool getGLFramebufferInfo(GrGLFramebufferInfo*) const;
453 
454 #ifdef SK_DAWN
455     // If the backend API is Dawn, copies a snapshot of the GrDawnRenderTargetInfo struct into the
456     // passed-in pointer and returns true. Otherwise returns false if the backend API is not Dawn.
457     bool getDawnRenderTargetInfo(GrDawnRenderTargetInfo*) const;
458 #endif
459 
460     // If the backend API is Vulkan, copies a snapshot of the GrVkImageInfo struct into the passed
461     // in pointer and returns true. This snapshot will set the fImageLayout to the current layout
462     // state. Otherwise returns false if the backend API is not Vulkan.
463     bool getVkImageInfo(GrVkImageInfo*) const;
464 
465     // Anytime the client changes the VkImageLayout of the VkImage captured by this
466     // GrBackendRenderTarget, they must call this function to notify Skia of the changed layout.
467     void setVkImageLayout(VkImageLayout);
468 
469 #ifdef SK_METAL
470     // If the backend API is Metal, copies a snapshot of the GrMtlTextureInfo struct into the passed
471     // in pointer and returns true. Otherwise returns false if the backend API is not Metal.
472     bool getMtlTextureInfo(GrMtlTextureInfo*) const;
473 #endif
474 
475 #ifdef SK_DIRECT3D
476     // If the backend API is Direct3D, copies a snapshot of the GrMtlTextureInfo struct into the
477     // passed in pointer and returns true. Otherwise returns false if the backend API is not D3D.
478     bool getD3DTextureResourceInfo(GrD3DTextureResourceInfo*) const;
479 
480     // Anytime the client changes the D3D12_RESOURCE_STATES of the D3D12_RESOURCE captured by this
481     // GrBackendTexture, they must call this function to notify Skia of the changed layout.
482     void setD3DResourceState(GrD3DResourceStateEnum);
483 #endif
484 
485     // Get the GrBackendFormat for this render target (or an invalid format if this is not valid).
486     GrBackendFormat getBackendFormat() const;
487 
488     // If the backend API is Mock, copies a snapshot of the GrMockTextureInfo struct into the passed
489     // in pointer and returns true. Otherwise returns false if the backend API is not Mock.
490     bool getMockRenderTargetInfo(GrMockRenderTargetInfo*) const;
491 
492     // Returns true if we are working with protected content.
493     bool isProtected() const;
494 
495     // Returns true if the backend texture has been initialized.
isValid()496     bool isValid() const { return fIsValid; }
497 
498 
499 #if GR_TEST_UTILS
500     static bool TestingOnly_Equals(const GrBackendRenderTarget&, const GrBackendRenderTarget&);
501 #endif
502 
503 private:
504     friend class GrVkGpu; // for getGrVkImageLayout
505     sk_sp<GrVkImageLayout> getGrVkImageLayout() const;
506 
507     friend class GrVkRenderTarget;
508     GrBackendRenderTarget(int width, int height, int sampleCnt, const GrVkImageInfo& vkInfo,
509                           sk_sp<GrVkImageLayout> layout);
510 #ifdef SK_DIRECT3D
511     friend class GrD3DGpu;
512     friend class GrD3DRenderTarget;
513     GrBackendRenderTarget(int width, int height, int sampleCnt,
514                           const GrD3DTextureResourceInfo& d3dInfo, sk_sp<GrD3DResourceState> state);
515     sk_sp<GrD3DResourceState> getGrD3DResourceState() const;
516 #endif
517 
518     // Free and release and resources being held by the GrBackendTexture.
519     void cleanup();
520 
521     bool fIsValid;
522     bool fFramebufferOnly = false;
523     int fWidth;         //<! width in pixels
524     int fHeight;        //<! height in pixels
525 
526     int fSampleCnt;
527     int fStencilBits;
528 
529     GrBackendApi fBackend;
530 
531     union {
532 #ifdef SK_GL
533         GrGLFramebufferInfo fGLInfo;
534 #endif
535         GrVkBackendSurfaceInfo fVkInfo;
536         GrMockRenderTargetInfo fMockInfo;
537 #ifdef SK_DIRECT3D
538         GrD3DBackendSurfaceInfo fD3DInfo;
539 #endif
540     };
541 #ifdef SK_METAL
542     GrMtlTextureInfo fMtlInfo;
543 #endif
544 #ifdef SK_DAWN
545     GrDawnRenderTargetInfo  fDawnInfo;
546 #endif
547 };
548 
549 #endif
550 
551 #endif
552 
553