• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
9 #include "include/gpu/GrBackendSurface.h"
10 
11 #include "src/gpu/gl/GrGLUtil.h"
12 
13 #ifdef SK_DAWN
14 #include "include/gpu/dawn/GrDawnTypes.h"
15 #include "src/gpu/dawn/GrDawnUtil.h"
16 #endif
17 
18 #ifdef SK_VULKAN
19 #include "include/gpu/vk/GrVkTypes.h"
20 #include "src/gpu/vk/GrVkImageLayout.h"
21 #include "src/gpu/vk/GrVkUtil.h"
22 #endif
23 #ifdef SK_METAL
24 #include "include/gpu/mtl/GrMtlTypes.h"
25 #include "src/gpu/mtl/GrMtlCppUtil.h"
26 #endif
27 
GrBackendFormat(const GrBackendFormat & that)28 GrBackendFormat::GrBackendFormat(const GrBackendFormat& that)
29         : fBackend(that.fBackend)
30         , fValid(that.fValid)
31         , fTextureType(that.fTextureType) {
32     if (!fValid) {
33         return;
34     }
35 
36     switch (fBackend) {
37 #ifdef SK_GL
38         case GrBackendApi::kOpenGL:
39             fGLFormat = that.fGLFormat;
40             break;
41 #endif
42 #ifdef SK_VULKAN
43         case GrBackendApi::kVulkan:
44             fVk = that.fVk;
45             break;
46 #endif
47 #ifdef SK_METAL
48         case GrBackendApi::kMetal:
49             fMtlFormat = that.fMtlFormat;
50             break;
51 #endif
52 #ifdef SK_DIRECT3D
53         case GrBackendApi::kDirect3D:
54             //TODO fD3DFormat = that.fD3DFormat;
55             break;
56 #endif
57 #ifdef SK_DAWN
58         case GrBackendApi::kDawn:
59             fDawnFormat = that.fDawnFormat;
60             break;
61 #endif
62         case GrBackendApi::kMock:
63             fMock = that.fMock;
64             break;
65         default:
66             SK_ABORT("Unknown GrBackend");
67     }
68 }
69 
70 #ifdef SK_GL
GrBackendFormat(GrGLenum format,GrGLenum target)71 GrBackendFormat::GrBackendFormat(GrGLenum format, GrGLenum target)
72         : fBackend(GrBackendApi::kOpenGL)
73         , fValid(true)
74         , fGLFormat(format) {
75     switch (target) {
76         case GR_GL_TEXTURE_NONE:
77             fTextureType = GrTextureType::kNone;
78             break;
79         case GR_GL_TEXTURE_2D:
80             fTextureType = GrTextureType::k2D;
81             break;
82         case GR_GL_TEXTURE_RECTANGLE:
83             fTextureType = GrTextureType::kRectangle;
84             break;
85         case GR_GL_TEXTURE_EXTERNAL:
86             fTextureType = GrTextureType::kExternal;
87             break;
88         default:
89             SK_ABORT("Unexpected texture target");
90     }
91 }
92 
asGLFormat() const93 GrGLFormat GrBackendFormat::asGLFormat() const {
94     if (this->isValid() && GrBackendApi::kOpenGL == fBackend) {
95         return GrGLFormatFromGLEnum(fGLFormat);
96     }
97     return GrGLFormat::kUnknown;
98 }
99 #endif
100 
MakeVk(const GrVkYcbcrConversionInfo & ycbcrInfo)101 GrBackendFormat GrBackendFormat::MakeVk(const GrVkYcbcrConversionInfo& ycbcrInfo) {
102     SkASSERT(ycbcrInfo.isValid());
103     return GrBackendFormat(ycbcrInfo.fFormat, ycbcrInfo);
104 }
105 
GrBackendFormat(VkFormat vkFormat,const GrVkYcbcrConversionInfo & ycbcrInfo)106 GrBackendFormat::GrBackendFormat(VkFormat vkFormat, const GrVkYcbcrConversionInfo& ycbcrInfo)
107         : fBackend(GrBackendApi::kVulkan)
108 #ifdef SK_VULKAN
109         , fValid(true)
110 #else
111         , fValid(false)
112 #endif
113         , fTextureType(GrTextureType::k2D) {
114     fVk.fFormat = vkFormat;
115     fVk.fYcbcrConversionInfo = ycbcrInfo;
116     if (fVk.fYcbcrConversionInfo.isValid() && fVk.fYcbcrConversionInfo.fExternalFormat) {
117         fTextureType = GrTextureType::kExternal;
118     }
119 }
120 
asVkFormat(VkFormat * format) const121 bool GrBackendFormat::asVkFormat(VkFormat* format) const {
122     SkASSERT(format);
123     if (this->isValid() && GrBackendApi::kVulkan == fBackend) {
124         *format = fVk.fFormat;
125         return true;
126     }
127     return false;
128 }
129 
getVkYcbcrConversionInfo() const130 const GrVkYcbcrConversionInfo* GrBackendFormat::getVkYcbcrConversionInfo() const {
131     if (this->isValid() && GrBackendApi::kVulkan == fBackend) {
132         return &fVk.fYcbcrConversionInfo;
133     }
134     return nullptr;
135 }
136 
137 #ifdef SK_DAWN
GrBackendFormat(wgpu::TextureFormat format)138 GrBackendFormat::GrBackendFormat(wgpu::TextureFormat format)
139         : fBackend(GrBackendApi::kDawn)
140         , fValid(true)
141         , fDawnFormat(format)
142         , fTextureType(GrTextureType::k2D) {
143 }
144 
asDawnFormat(wgpu::TextureFormat * format) const145 bool GrBackendFormat::asDawnFormat(wgpu::TextureFormat* format) const {
146     SkASSERT(format);
147     if (this->isValid() && GrBackendApi::kDawn == fBackend) {
148         *format = fDawnFormat;
149         return true;
150     }
151     return false;
152 }
153 #endif
154 
155 #ifdef SK_METAL
GrBackendFormat(GrMTLPixelFormat mtlFormat)156 GrBackendFormat::GrBackendFormat(GrMTLPixelFormat mtlFormat)
157         : fBackend(GrBackendApi::kMetal)
158         , fValid(true)
159         , fMtlFormat(mtlFormat)
160         , fTextureType(GrTextureType::k2D) {
161 }
162 
asMtlFormat() const163 GrMTLPixelFormat GrBackendFormat::asMtlFormat() const {
164     if (this->isValid() && GrBackendApi::kMetal == fBackend) {
165         return fMtlFormat;
166     }
167     // MTLPixelFormatInvalid == 0
168     return GrMTLPixelFormat(0);
169 }
170 #endif
171 
GrBackendFormat(GrColorType colorType,SkImage::CompressionType compression)172 GrBackendFormat::GrBackendFormat(GrColorType colorType, SkImage::CompressionType compression)
173         : fBackend(GrBackendApi::kMock)
174         , fValid(true)
175         , fTextureType(GrTextureType::k2D) {
176     fMock.fColorType = colorType;
177     fMock.fCompressionType = compression;
178 }
179 
asMockColorType() const180 GrColorType GrBackendFormat::asMockColorType() const {
181     if (this->isValid() && GrBackendApi::kMock == fBackend) {
182         SkASSERT(fMock.fCompressionType == SkImage::CompressionType::kNone ||
183                  fMock.fColorType == GrColorType::kUnknown);
184 
185         return fMock.fColorType;
186     }
187 
188     return GrColorType::kUnknown;
189 }
190 
asMockCompressionType() const191 SkImage::CompressionType GrBackendFormat::asMockCompressionType() const {
192     if (this->isValid() && GrBackendApi::kMock == fBackend) {
193         SkASSERT(fMock.fCompressionType == SkImage::CompressionType::kNone ||
194                  fMock.fColorType == GrColorType::kUnknown);
195 
196         return fMock.fCompressionType;
197     }
198 
199     return SkImage::CompressionType::kNone;
200 }
201 
202 
makeTexture2D() const203 GrBackendFormat GrBackendFormat::makeTexture2D() const {
204     GrBackendFormat copy = *this;
205     if (const GrVkYcbcrConversionInfo* ycbcrInfo = this->getVkYcbcrConversionInfo()) {
206         if (ycbcrInfo->isValid()) {
207             // If we have a ycbcr we remove it from the backend format and set the VkFormat to
208             // R8G8B8A8_UNORM
209             SkASSERT(copy.fBackend == GrBackendApi::kVulkan);
210             copy.fVk.fYcbcrConversionInfo = GrVkYcbcrConversionInfo();
211             copy.fVk.fFormat = VK_FORMAT_R8G8B8A8_UNORM;
212         }
213     }
214     copy.fTextureType = GrTextureType::k2D;
215     return copy;
216 }
217 
MakeMock(GrColorType colorType,SkImage::CompressionType compression)218 GrBackendFormat GrBackendFormat::MakeMock(GrColorType colorType,
219                                           SkImage::CompressionType compression) {
220     return GrBackendFormat(colorType, compression);
221 }
222 
operator ==(const GrBackendFormat & that) const223 bool GrBackendFormat::operator==(const GrBackendFormat& that) const {
224     // Invalid GrBackendFormats are never equal to anything.
225     if (!fValid || !that.fValid) {
226         return false;
227     }
228 
229     if (fBackend != that.fBackend) {
230         return false;
231     }
232 
233     switch (fBackend) {
234 #ifdef SK_GL
235         case GrBackendApi::kOpenGL:
236             return fGLFormat == that.fGLFormat;
237             break;
238 #endif
239 #ifdef SK_VULKAN
240         case GrBackendApi::kVulkan:
241             return fVk.fFormat == that.fVk.fFormat &&
242                    fVk.fYcbcrConversionInfo == that.fVk.fYcbcrConversionInfo;
243             break;
244 #endif
245 #ifdef SK_METAL
246         case GrBackendApi::kMetal:
247             return fMtlFormat == that.fMtlFormat;
248             break;
249 #endif
250 #ifdef SK_DAWN
251         case GrBackendApi::kDawn:
252             return fDawnFormat == that.fDawnFormat;
253             break;
254 #endif
255         case GrBackendApi::kMock:
256             return fMock.fColorType == that.fMock.fColorType &&
257                    fMock.fCompressionType == that.fMock.fCompressionType;
258         default:
259             SK_ABORT("Unknown GrBackend");
260     }
261     return false;
262 }
263 
264 #if GR_TEST_UTILS
265 #include "include/core/SkString.h"
266 #include "src/gpu/GrTestUtils.h"
267 
268 #ifdef SK_GL
269 #include "src/gpu/gl/GrGLUtil.h"
270 #endif
271 #ifdef SK_VULKAN
272 #include "src/gpu/vk/GrVkUtil.h"
273 #endif
274 
toStr() const275 SkString GrBackendFormat::toStr() const {
276     SkString str;
277 
278     if (!fValid) {
279         str.append("invalid");
280         return str;
281     }
282 
283     str.appendf("%s-", GrBackendApiToStr(fBackend));
284 
285     switch (fBackend) {
286         case GrBackendApi::kOpenGL:
287 #ifdef SK_GL
288             str.append(GrGLFormatToStr(fGLFormat));
289 #endif
290             break;
291         case GrBackendApi::kVulkan:
292 #ifdef SK_VULKAN
293             str.append(GrVkFormatToStr(fVk.fFormat));
294 #endif
295             break;
296         case GrBackendApi::kMetal:
297 #ifdef SK_METAL
298             str.append(GrMtlFormatToStr(fMtlFormat));
299 #endif
300             break;
301         case GrBackendApi::kDirect3D:
302 #ifdef SK_DIRECT3D
303             //TODO str.append(GrD3DFormatToStr(fD3DFormat));
304 #endif
305             break;
306         case GrBackendApi::kDawn:
307 #ifdef SK_DAWN
308             str.append(GrDawnFormatToStr(fDawnFormat));
309 #endif
310             break;
311         case GrBackendApi::kMock:
312             str.append(GrColorTypeToStr(fMock.fColorType));
313             str.appendf("-");
314             str.append(GrCompressionTypeToStr(fMock.fCompressionType));
315             break;
316     }
317 
318     return str;
319 }
320 #endif
321 
322 ///////////////////////////////////////////////////////////////////////////////////////////////////
323 #ifdef SK_DAWN
GrBackendTexture(int width,int height,const GrDawnTextureInfo & dawnInfo)324 GrBackendTexture::GrBackendTexture(int width,
325                                    int height,
326                                    const GrDawnTextureInfo& dawnInfo)
327         : fIsValid(true)
328         , fWidth(width)
329         , fHeight(height)
330         , fMipMapped(GrMipMapped(dawnInfo.fLevelCount > 1))
331         , fBackend(GrBackendApi::kDawn)
332         , fDawnInfo(dawnInfo) {}
333 #endif
334 
GrBackendTexture(int width,int height,const GrVkImageInfo & vkInfo)335 GrBackendTexture::GrBackendTexture(int width, int height, const GrVkImageInfo& vkInfo)
336 #ifdef SK_VULKAN
337         : GrBackendTexture(width, height, vkInfo,
338                            sk_sp<GrVkImageLayout>(new GrVkImageLayout(vkInfo.fImageLayout))) {}
339 #else
340         : fIsValid(false) {}
341 #endif
342 
343 #ifdef SK_GL
GrBackendTexture(int width,int height,GrMipMapped mipMapped,const GrGLTextureInfo glInfo,sk_sp<GrGLTextureParameters> params)344 GrBackendTexture::GrBackendTexture(int width,
345                                    int height,
346                                    GrMipMapped mipMapped,
347                                    const GrGLTextureInfo glInfo,
348                                    sk_sp<GrGLTextureParameters> params)
349         : fIsValid(true)
350         , fWidth(width)
351         , fHeight(height)
352         , fMipMapped(mipMapped)
353         , fBackend(GrBackendApi::kOpenGL)
354         , fGLInfo(glInfo, params.release()) {}
355 
getGLTextureParams() const356 sk_sp<GrGLTextureParameters> GrBackendTexture::getGLTextureParams() const {
357     if (fBackend != GrBackendApi::kOpenGL) {
358         return nullptr;
359     }
360     return fGLInfo.refParameters();
361 }
362 #endif
363 
364 #ifdef SK_VULKAN
GrBackendTexture(int width,int height,const GrVkImageInfo & vkInfo,sk_sp<GrVkImageLayout> layout)365 GrBackendTexture::GrBackendTexture(int width,
366                                    int height,
367                                    const GrVkImageInfo& vkInfo,
368                                    sk_sp<GrVkImageLayout> layout)
369         : fIsValid(true)
370         , fWidth(width)
371         , fHeight(height)
372         , fMipMapped(GrMipMapped(vkInfo.fLevelCount > 1))
373         , fBackend(GrBackendApi::kVulkan)
374         , fVkInfo(vkInfo, layout.release()) {}
375 #endif
376 
377 #ifdef SK_METAL
GrBackendTexture(int width,int height,GrMipMapped mipMapped,const GrMtlTextureInfo & mtlInfo)378 GrBackendTexture::GrBackendTexture(int width,
379                                    int height,
380                                    GrMipMapped mipMapped,
381                                    const GrMtlTextureInfo& mtlInfo)
382         : fIsValid(true)
383         , fWidth(width)
384         , fHeight(height)
385         , fMipMapped(mipMapped)
386         , fBackend(GrBackendApi::kMetal)
387         , fMtlInfo(mtlInfo) {}
388 #endif
389 
390 #ifdef SK_GL
GrBackendTexture(int width,int height,GrMipMapped mipMapped,const GrGLTextureInfo & glInfo)391 GrBackendTexture::GrBackendTexture(int width,
392                                    int height,
393                                    GrMipMapped mipMapped,
394                                    const GrGLTextureInfo& glInfo)
395         : GrBackendTexture(width, height, mipMapped, glInfo, sk_make_sp<GrGLTextureParameters>()) {
396     // Make no assumptions about client's texture's parameters.
397     this->glTextureParametersModified();
398 }
399 #endif
400 
GrBackendTexture(int width,int height,GrMipMapped mipMapped,const GrMockTextureInfo & mockInfo)401 GrBackendTexture::GrBackendTexture(int width,
402                                    int height,
403                                    GrMipMapped mipMapped,
404                                    const GrMockTextureInfo& mockInfo)
405         : fIsValid(true)
406         , fWidth(width)
407         , fHeight(height)
408         , fMipMapped(mipMapped)
409         , fBackend(GrBackendApi::kMock)
410         , fMockInfo(mockInfo) {}
411 
~GrBackendTexture()412 GrBackendTexture::~GrBackendTexture() {
413     this->cleanup();
414 }
415 
cleanup()416 void GrBackendTexture::cleanup() {
417 #ifdef SK_GL
418     if (this->isValid() && GrBackendApi::kOpenGL == fBackend) {
419         fGLInfo.cleanup();
420     }
421 #endif
422 #ifdef SK_VULKAN
423     if (this->isValid() && GrBackendApi::kVulkan == fBackend) {
424         fVkInfo.cleanup();
425     }
426 #endif
427 }
428 
GrBackendTexture(const GrBackendTexture & that)429 GrBackendTexture::GrBackendTexture(const GrBackendTexture& that) : fIsValid(false) {
430     *this = that;
431 }
432 
operator =(const GrBackendTexture & that)433 GrBackendTexture& GrBackendTexture::operator=(const GrBackendTexture& that) {
434     if (!that.isValid()) {
435         this->cleanup();
436         fIsValid = false;
437         return *this;
438     } else if (fIsValid && this->fBackend != that.fBackend) {
439         this->cleanup();
440         fIsValid = false;
441     }
442     fWidth = that.fWidth;
443     fHeight = that.fHeight;
444     fMipMapped = that.fMipMapped;
445     fBackend = that.fBackend;
446 
447     switch (that.fBackend) {
448 #ifdef SK_GL
449         case GrBackendApi::kOpenGL:
450             fGLInfo.assign(that.fGLInfo, this->isValid());
451             break;
452 #endif
453 #ifdef SK_VULKAN
454         case GrBackendApi::kVulkan:
455             fVkInfo.assign(that.fVkInfo, this->isValid());
456             break;
457 #endif
458 #ifdef SK_METAL
459         case GrBackendApi::kMetal:
460             fMtlInfo = that.fMtlInfo;
461             break;
462 #endif
463 #ifdef SK_DIRECT3D
464         case GrBackendApi::kDirect3D:
465             // TODO fD3DInfo = that.fD3DInfo;
466             break;
467 #endif
468 #ifdef SK_DAWN
469         case GrBackendApi::kDawn:
470             fDawnInfo = that.fDawnInfo;
471             break;
472 #endif
473         case GrBackendApi::kMock:
474             fMockInfo = that.fMockInfo;
475             break;
476         default:
477             SK_ABORT("Unknown GrBackend");
478     }
479     fIsValid = true;
480     return *this;
481 }
482 
483 #ifdef SK_DAWN
getDawnTextureInfo(GrDawnTextureInfo * outInfo) const484 bool GrBackendTexture::getDawnTextureInfo(GrDawnTextureInfo* outInfo) const {
485     if (this->isValid() && GrBackendApi::kDawn == fBackend) {
486         *outInfo = fDawnInfo;
487         return true;
488     }
489     return false;
490 }
491 #endif
492 
getVkImageInfo(GrVkImageInfo * outInfo) const493 bool GrBackendTexture::getVkImageInfo(GrVkImageInfo* outInfo) const {
494 #ifdef SK_VULKAN
495     if (this->isValid() && GrBackendApi::kVulkan == fBackend) {
496         *outInfo = fVkInfo.snapImageInfo();
497         return true;
498     }
499 #endif
500     return false;
501 }
502 
setVkImageLayout(VkImageLayout layout)503 void GrBackendTexture::setVkImageLayout(VkImageLayout layout) {
504 #ifdef SK_VULKAN
505     if (this->isValid() && GrBackendApi::kVulkan == fBackend) {
506         fVkInfo.setImageLayout(layout);
507     }
508 #endif
509 }
510 
511 #ifdef SK_VULKAN
getGrVkImageLayout() const512 sk_sp<GrVkImageLayout> GrBackendTexture::getGrVkImageLayout() const {
513     if (this->isValid() && GrBackendApi::kVulkan == fBackend) {
514         return fVkInfo.getGrVkImageLayout();
515     }
516     return nullptr;
517 }
518 #endif
519 
520 #ifdef SK_METAL
getMtlTextureInfo(GrMtlTextureInfo * outInfo) const521 bool GrBackendTexture::getMtlTextureInfo(GrMtlTextureInfo* outInfo) const {
522     if (this->isValid() && GrBackendApi::kMetal == fBackend) {
523         *outInfo = fMtlInfo;
524         return true;
525     }
526     return false;
527 }
528 #endif
529 
getGLTextureInfo(GrGLTextureInfo * outInfo) const530 bool GrBackendTexture::getGLTextureInfo(GrGLTextureInfo* outInfo) const {
531 #ifdef SK_GL
532     if (this->isValid() && GrBackendApi::kOpenGL == fBackend) {
533         *outInfo = fGLInfo.info();
534         return true;
535     } else if (this->isValid() && GrBackendApi::kMock == fBackend) {
536         // Hack! This allows some blink unit tests to work when using the Mock GrContext.
537         // Specifically, tests that rely on CanvasResourceProviderTextureGpuMemoryBuffer.
538         // If that code ever goes away (or ideally becomes backend-agnostic), this can go away.
539         *outInfo = GrGLTextureInfo{ GR_GL_TEXTURE_2D,
540                                     static_cast<GrGLuint>(fMockInfo.id()),
541                                     GR_GL_RGBA8 };
542         return true;
543     }
544 #endif
545     return false;
546 }
547 
glTextureParametersModified()548 void GrBackendTexture::glTextureParametersModified() {
549 #ifdef SK_GL
550     if (this->isValid() && fBackend == GrBackendApi::kOpenGL) {
551         fGLInfo.parameters()->invalidate();
552     }
553 #endif
554 }
555 
getMockTextureInfo(GrMockTextureInfo * outInfo) const556 bool GrBackendTexture::getMockTextureInfo(GrMockTextureInfo* outInfo) const {
557     if (this->isValid() && GrBackendApi::kMock == fBackend) {
558         *outInfo = fMockInfo;
559         return true;
560     }
561     return false;
562 }
563 
isProtected() const564 bool GrBackendTexture::isProtected() const {
565     if (!this->isValid() || this->backend() != GrBackendApi::kVulkan) {
566         return false;
567     }
568     return fVkInfo.isProtected();
569 }
570 
isSameTexture(const GrBackendTexture & that)571 bool GrBackendTexture::isSameTexture(const GrBackendTexture& that) {
572     if (!this->isValid() || !that.isValid()) {
573         return false;
574     }
575     if (fBackend != that.fBackend) {
576         return false;
577     }
578     switch (fBackend) {
579 #ifdef SK_GL
580         case GrBackendApi::kOpenGL:
581             return fGLInfo.info().fID == that.fGLInfo.info().fID;
582 #endif
583 #ifdef SK_VULKAN
584         case GrBackendApi::kVulkan:
585             return fVkInfo.snapImageInfo().fImage == that.fVkInfo.snapImageInfo().fImage;
586 #endif
587 #ifdef SK_METAL
588         case GrBackendApi::kMetal:
589             return this->fMtlInfo.fTexture == that.fMtlInfo.fTexture;
590 #endif
591 #ifdef SK_DIRECT3D
592         case GrBackendApi::kDirect3D:
593             return false; //TODO
594 #endif
595         case GrBackendApi::kMock:
596             return fMockInfo.id() == that.fMockInfo.id();
597         default:
598             return false;
599     }
600 }
601 
getBackendFormat() const602 GrBackendFormat GrBackendTexture::getBackendFormat() const {
603     if (!this->isValid()) {
604         return GrBackendFormat();
605     }
606     switch (fBackend) {
607 #ifdef SK_GL
608         case GrBackendApi::kOpenGL:
609             return GrBackendFormat::MakeGL(fGLInfo.info().fFormat, fGLInfo.info().fTarget);
610 #endif
611 #ifdef SK_VULKAN
612         case GrBackendApi::kVulkan: {
613             auto info = fVkInfo.snapImageInfo();
614             if (info.fYcbcrConversionInfo.isValid()) {
615                 SkASSERT(info.fFormat == info.fYcbcrConversionInfo.fFormat);
616                 return GrBackendFormat::MakeVk(info.fYcbcrConversionInfo);
617             }
618             return GrBackendFormat::MakeVk(info.fFormat);
619         }
620 #endif
621 #ifdef SK_METAL
622         case GrBackendApi::kMetal: {
623             GrMtlTextureInfo mtlInfo;
624             SkAssertResult(this->getMtlTextureInfo(&mtlInfo));
625             return GrBackendFormat::MakeMtl(GrGetMTLPixelFormatFromMtlTextureInfo(mtlInfo));
626         }
627 #endif
628 #ifdef SK_DIRECT3D
629         case GrBackendApi::kDirect3D: {
630             return GrBackendFormat(); // TODO
631         }
632 #endif
633 #ifdef SK_DAWN
634         case GrBackendApi::kDawn: {
635             return GrBackendFormat::MakeDawn(fDawnInfo.fFormat);
636         }
637 #endif
638         case GrBackendApi::kMock:
639             return fMockInfo.getBackendFormat();
640         default:
641             return GrBackendFormat();
642     }
643 }
644 
645 #if GR_TEST_UTILS
TestingOnly_Equals(const GrBackendTexture & t0,const GrBackendTexture & t1)646 bool GrBackendTexture::TestingOnly_Equals(const GrBackendTexture& t0, const GrBackendTexture& t1) {
647     if (!t0.isValid() || !t1.isValid()) {
648         return false; // two invalid backend textures are not considered equal
649     }
650 
651     if (t0.fWidth != t1.fWidth ||
652         t0.fHeight != t1.fHeight ||
653         t0.fMipMapped != t1.fMipMapped ||
654         t0.fBackend != t1.fBackend) {
655         return false;
656     }
657 
658     switch (t0.fBackend) {
659 #ifdef SK_GL
660         case GrBackendApi::kOpenGL:
661             return t0.fGLInfo.info() == t1.fGLInfo.info();
662 #endif
663         case GrBackendApi::kMock:
664             return t0.fMockInfo == t1.fMockInfo;
665 #ifdef SK_VULKAN
666         case GrBackendApi::kVulkan:
667             return t0.fVkInfo == t1.fVkInfo;
668 #endif
669 #ifdef SK_METAL
670         case GrBackendApi::kMetal:
671             return t0.fMtlInfo == t1.fMtlInfo;
672 #endif
673 #ifdef SK_DIRECT3D
674         case GrBackendApi::kDirect3D:
675             return false;
676 #endif
677 #ifdef SK_DAWN
678         case GrBackendApi::kDawn:
679             return t0.fDawnInfo == t1.fDawnInfo;
680 #endif
681         default:
682             return false;
683     }
684 }
685 #endif
686 
687 ////////////////////////////////////////////////////////////////////////////////////////////////////
688 
689 #ifdef SK_DAWN
GrBackendRenderTarget(int width,int height,int sampleCnt,int stencilBits,const GrDawnRenderTargetInfo & dawnInfo)690 GrBackendRenderTarget::GrBackendRenderTarget(int width,
691                                              int height,
692                                              int sampleCnt,
693                                              int stencilBits,
694                                              const GrDawnRenderTargetInfo& dawnInfo)
695         : fIsValid(true)
696         , fFramebufferOnly(true)
697         , fWidth(width)
698         , fHeight(height)
699         , fSampleCnt(sampleCnt)
700         , fStencilBits(stencilBits)
701         , fBackend(GrBackendApi::kDawn)
702         , fDawnInfo(dawnInfo) {}
703 #endif
704 
GrBackendRenderTarget(int width,int height,int sampleCnt,int stencilBits,const GrVkImageInfo & vkInfo)705 GrBackendRenderTarget::GrBackendRenderTarget(int width,
706                                              int height,
707                                              int sampleCnt,
708                                              int stencilBits,
709                                              const GrVkImageInfo& vkInfo)
710         : GrBackendRenderTarget(width, height, sampleCnt, vkInfo) {
711     // This is a deprecated constructor that takes a bogus stencil bits.
712     SkASSERT(0 == stencilBits);
713 }
714 
GrBackendRenderTarget(int width,int height,int sampleCnt,const GrVkImageInfo & vkInfo)715 GrBackendRenderTarget::GrBackendRenderTarget(int width,
716                                              int height,
717                                              int sampleCnt,
718                                              const GrVkImageInfo& vkInfo)
719 #ifdef SK_VULKAN
720         : GrBackendRenderTarget(width, height, sampleCnt, vkInfo,
721                                 sk_sp<GrVkImageLayout>(new GrVkImageLayout(vkInfo.fImageLayout))) {}
722 #else
723         : fIsValid(false) {}
724 #endif
725 
726 #ifdef SK_VULKAN
GrBackendRenderTarget(int width,int height,int sampleCnt,const GrVkImageInfo & vkInfo,sk_sp<GrVkImageLayout> layout)727 GrBackendRenderTarget::GrBackendRenderTarget(int width,
728                                              int height,
729                                              int sampleCnt,
730                                              const GrVkImageInfo& vkInfo,
731                                              sk_sp<GrVkImageLayout> layout)
732         : fIsValid(true)
733         , fWidth(width)
734         , fHeight(height)
735         , fSampleCnt(std::max(1, sampleCnt))
736         , fStencilBits(0)  // We always create stencil buffers internally for vulkan
737         , fBackend(GrBackendApi::kVulkan)
738         , fVkInfo(vkInfo, layout.release()) {}
739 #endif
740 
741 #ifdef SK_METAL
GrBackendRenderTarget(int width,int height,int sampleCnt,const GrMtlTextureInfo & mtlInfo)742 GrBackendRenderTarget::GrBackendRenderTarget(int width,
743                                              int height,
744                                              int sampleCnt,
745                                              const GrMtlTextureInfo& mtlInfo)
746         : fIsValid(true)
747         , fFramebufferOnly(false) // TODO: set this from mtlInfo.fTexture->framebufferOnly
748         , fWidth(width)
749         , fHeight(height)
750         , fSampleCnt(std::max(1, sampleCnt))
751         , fStencilBits(0)
752         , fBackend(GrBackendApi::kMetal)
753         , fMtlInfo(mtlInfo) {}
754 #endif
755 
756 #ifdef SK_GL
GrBackendRenderTarget(int width,int height,int sampleCnt,int stencilBits,const GrGLFramebufferInfo & glInfo)757 GrBackendRenderTarget::GrBackendRenderTarget(int width,
758                                              int height,
759                                              int sampleCnt,
760                                              int stencilBits,
761                                              const GrGLFramebufferInfo& glInfo)
762         : fWidth(width)
763         , fHeight(height)
764         , fSampleCnt(std::max(1, sampleCnt))
765         , fStencilBits(stencilBits)
766         , fBackend(GrBackendApi::kOpenGL)
767         , fGLInfo(glInfo) {
768     fIsValid = SkToBool(glInfo.fFormat); // the glInfo must have a valid format
769 }
770 #endif
771 
GrBackendRenderTarget(int width,int height,int sampleCnt,int stencilBits,const GrMockRenderTargetInfo & mockInfo)772 GrBackendRenderTarget::GrBackendRenderTarget(int width,
773                                              int height,
774                                              int sampleCnt,
775                                              int stencilBits,
776                                              const GrMockRenderTargetInfo& mockInfo)
777         : fIsValid(true)
778         , fWidth(width)
779         , fHeight(height)
780         , fSampleCnt(std::max(1, sampleCnt))
781         , fStencilBits(stencilBits)
782         , fMockInfo(mockInfo) {}
783 
~GrBackendRenderTarget()784 GrBackendRenderTarget::~GrBackendRenderTarget() {
785     this->cleanup();
786 }
787 
cleanup()788 void GrBackendRenderTarget::cleanup() {
789 #ifdef SK_VULKAN
790     if (this->isValid() && GrBackendApi::kVulkan == fBackend) {
791         fVkInfo.cleanup();
792     }
793 #endif
794 }
795 
GrBackendRenderTarget(const GrBackendRenderTarget & that)796 GrBackendRenderTarget::GrBackendRenderTarget(const GrBackendRenderTarget& that) : fIsValid(false) {
797     *this = that;
798 }
799 
operator =(const GrBackendRenderTarget & that)800 GrBackendRenderTarget& GrBackendRenderTarget::operator=(const GrBackendRenderTarget& that) {
801     if (!that.isValid()) {
802         this->cleanup();
803         fIsValid = false;
804         return *this;
805     } else if (fIsValid && this->fBackend != that.fBackend) {
806         this->cleanup();
807         fIsValid = false;
808     }
809     fWidth = that.fWidth;
810     fHeight = that.fHeight;
811     fSampleCnt = that.fSampleCnt;
812     fStencilBits = that.fStencilBits;
813     fBackend = that.fBackend;
814 
815     switch (that.fBackend) {
816 #ifdef SK_GL
817         case GrBackendApi::kOpenGL:
818             fGLInfo = that.fGLInfo;
819             break;
820 #endif
821 #ifdef SK_VULKAN
822         case GrBackendApi::kVulkan:
823             fVkInfo.assign(that.fVkInfo, this->isValid());
824             break;
825 #endif
826 #ifdef SK_METAL
827         case GrBackendApi::kMetal:
828             fMtlInfo = that.fMtlInfo;
829             break;
830 #endif
831 #ifdef SK_DIRECT3D
832         case GrBackendApi::kDirect3D:
833             // TODO fD3DInfo = that.fD3DInfo;
834             break;
835 #endif
836 #ifdef SK_DAWN
837         case GrBackendApi::kDawn:
838             fDawnInfo = that.fDawnInfo;
839             break;
840 #endif
841         case GrBackendApi::kMock:
842             fMockInfo = that.fMockInfo;
843             break;
844         default:
845             SK_ABORT("Unknown GrBackend");
846     }
847     fIsValid = that.fIsValid;
848     return *this;
849 }
850 
851 #ifdef SK_DAWN
getDawnRenderTargetInfo(GrDawnRenderTargetInfo * outInfo) const852 bool GrBackendRenderTarget::getDawnRenderTargetInfo(GrDawnRenderTargetInfo* outInfo) const {
853     if (this->isValid() && GrBackendApi::kDawn == fBackend) {
854         *outInfo = fDawnInfo;
855         return true;
856     }
857     return false;
858 }
859 #endif
860 
getVkImageInfo(GrVkImageInfo * outInfo) const861 bool GrBackendRenderTarget::getVkImageInfo(GrVkImageInfo* outInfo) const {
862 #ifdef SK_VULKAN
863     if (this->isValid() && GrBackendApi::kVulkan == fBackend) {
864         *outInfo = fVkInfo.snapImageInfo();
865         return true;
866     }
867 #endif
868     return false;
869 }
870 
setVkImageLayout(VkImageLayout layout)871 void GrBackendRenderTarget::setVkImageLayout(VkImageLayout layout) {
872 #ifdef SK_VULKAN
873     if (this->isValid() && GrBackendApi::kVulkan == fBackend) {
874         fVkInfo.setImageLayout(layout);
875     }
876 #endif
877 }
878 
879 #ifdef SK_VULKAN
getGrVkImageLayout() const880 sk_sp<GrVkImageLayout> GrBackendRenderTarget::getGrVkImageLayout() const {
881     if (this->isValid() && GrBackendApi::kVulkan == fBackend) {
882         return fVkInfo.getGrVkImageLayout();
883     }
884     return nullptr;
885 }
886 #endif
887 
888 #ifdef SK_METAL
getMtlTextureInfo(GrMtlTextureInfo * outInfo) const889 bool GrBackendRenderTarget::getMtlTextureInfo(GrMtlTextureInfo* outInfo) const {
890     if (this->isValid() && GrBackendApi::kMetal == fBackend) {
891         *outInfo = fMtlInfo;
892         return true;
893     }
894     return false;
895 }
896 #endif
897 
898 #ifdef SK_GL
getGLFramebufferInfo(GrGLFramebufferInfo * outInfo) const899 bool GrBackendRenderTarget::getGLFramebufferInfo(GrGLFramebufferInfo* outInfo) const {
900     if (this->isValid() && GrBackendApi::kOpenGL == fBackend) {
901         *outInfo = fGLInfo;
902         return true;
903     }
904     return false;
905 }
906 #endif
907 
getBackendFormat() const908 GrBackendFormat GrBackendRenderTarget::getBackendFormat() const {
909     if (!this->isValid()) {
910         return GrBackendFormat();
911     }
912     switch (fBackend) {
913 #ifdef SK_GL
914         case GrBackendApi::kOpenGL:
915             return GrBackendFormat::MakeGL(fGLInfo.fFormat, GR_GL_TEXTURE_NONE);
916 #endif
917 #ifdef SK_VULKAN
918         case GrBackendApi::kVulkan: {
919             auto info = fVkInfo.snapImageInfo();
920             if (info.fYcbcrConversionInfo.isValid()) {
921                 SkASSERT(info.fFormat == info.fYcbcrConversionInfo.fFormat);
922                 return GrBackendFormat::MakeVk(info.fYcbcrConversionInfo);
923             }
924             return GrBackendFormat::MakeVk(info.fFormat);
925         }
926 #endif
927 #ifdef SK_METAL
928         case GrBackendApi::kMetal: {
929             GrMtlTextureInfo mtlInfo;
930             SkAssertResult(this->getMtlTextureInfo(&mtlInfo));
931             return GrBackendFormat::MakeMtl(GrGetMTLPixelFormatFromMtlTextureInfo(mtlInfo));
932         }
933 #endif
934 #ifdef SK_DIRECT3D
935         case GrBackendApi::kDirect3D: {
936             // TODO
937             return GrBackendFormat();
938         }
939 #endif
940 #ifdef SK_DAWN
941         case GrBackendApi::kDawn: {
942             GrDawnRenderTargetInfo dawnInfo;
943             SkAssertResult(this->getDawnRenderTargetInfo(&dawnInfo));
944             return GrBackendFormat::MakeDawn(dawnInfo.fFormat);
945         }
946 #endif
947         case GrBackendApi::kMock:
948             return fMockInfo.getBackendFormat();
949         default:
950             return GrBackendFormat();
951     }
952 }
953 
getMockRenderTargetInfo(GrMockRenderTargetInfo * outInfo) const954 bool GrBackendRenderTarget::getMockRenderTargetInfo(GrMockRenderTargetInfo* outInfo) const {
955     if (this->isValid() && GrBackendApi::kMock == fBackend) {
956         *outInfo = fMockInfo;
957         return true;
958     }
959     return false;
960 }
961 
isProtected() const962 bool GrBackendRenderTarget::isProtected() const {
963     if (!this->isValid() || this->backend() != GrBackendApi::kVulkan) {
964         return false;
965     }
966     return fVkInfo.isProtected();
967 }
968 
969 #if GR_TEST_UTILS
TestingOnly_Equals(const GrBackendRenderTarget & r0,const GrBackendRenderTarget & r1)970 bool GrBackendRenderTarget::TestingOnly_Equals(const GrBackendRenderTarget& r0,
971                                                const GrBackendRenderTarget& r1) {
972     if (!r0.isValid() || !r1.isValid()) {
973         return false; // two invalid backend rendertargets are not considered equal
974     }
975 
976     if (r0.fWidth != r1.fWidth ||
977         r0.fHeight != r1.fHeight ||
978         r0.fSampleCnt != r1.fSampleCnt ||
979         r0.fStencilBits != r1.fStencilBits ||
980         r0.fBackend != r1.fBackend) {
981         return false;
982     }
983 
984     switch (r0.fBackend) {
985 #ifdef SK_GL
986         case GrBackendApi::kOpenGL:
987             return r0.fGLInfo == r1.fGLInfo;
988 #endif
989         case GrBackendApi::kMock:
990             return r0.fMockInfo == r1.fMockInfo;
991 #ifdef SK_VULKAN
992         case GrBackendApi::kVulkan:
993             return r0.fVkInfo == r1.fVkInfo;
994 #endif
995 #ifdef SK_METAL
996         case GrBackendApi::kMetal:
997             return r0.fMtlInfo == r1.fMtlInfo;
998 #endif
999 #ifdef SK_DIRECT3D
1000         case GrBackendApi::kDirect3D:
1001             return false; // TODO r0.fD3DInfo == r1.fD3DInfo;
1002 #endif
1003 #ifdef SK_DAWN
1004         case GrBackendApi::kDawn:
1005             return r0.fDawnInfo == r1.fDawnInfo;
1006 #endif
1007         default:
1008             return false;
1009     }
1010 
1011     SkASSERT(0);
1012     return false;
1013 }
1014 #endif
1015