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