• 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_DAWN
53         case GrBackendApi::kDawn:
54             fDawnFormat = that.fDawnFormat;
55             break;
56 #endif
57         case GrBackendApi::kMock:
58             fMockColorType = that.fMockColorType;
59             break;
60         default:
61             SK_ABORT("Unknown GrBackend");
62     }
63 }
64 
GrBackendFormat(GrGLenum format,GrGLenum target)65 GrBackendFormat::GrBackendFormat(GrGLenum format, GrGLenum target)
66         : fBackend(GrBackendApi::kOpenGL)
67         , fValid(true)
68         , fGLFormat(format) {
69     switch (target) {
70         case GR_GL_TEXTURE_NONE:
71             fTextureType = GrTextureType::kNone;
72             break;
73         case GR_GL_TEXTURE_2D:
74             fTextureType = GrTextureType::k2D;
75             break;
76         case GR_GL_TEXTURE_RECTANGLE:
77             fTextureType = GrTextureType::kRectangle;
78             break;
79         case GR_GL_TEXTURE_EXTERNAL:
80             fTextureType = GrTextureType::kExternal;
81             break;
82         default:
83             SK_ABORT("Unexpected texture target");
84     }
85 }
86 
asGLFormat() const87 GrGLFormat GrBackendFormat::asGLFormat() const {
88     if (this->isValid() && GrBackendApi::kOpenGL == fBackend) {
89         return GrGLFormatFromGLEnum(fGLFormat);
90     }
91     return GrGLFormat::kUnknown;
92 }
93 
MakeVk(const GrVkYcbcrConversionInfo & ycbcrInfo)94 GrBackendFormat GrBackendFormat::MakeVk(const GrVkYcbcrConversionInfo& ycbcrInfo) {
95     SkASSERT(ycbcrInfo.isValid());
96     return GrBackendFormat(ycbcrInfo.fFormat, ycbcrInfo);
97 }
98 
GrBackendFormat(VkFormat vkFormat,const GrVkYcbcrConversionInfo & ycbcrInfo)99 GrBackendFormat::GrBackendFormat(VkFormat vkFormat, const GrVkYcbcrConversionInfo& ycbcrInfo)
100         : fBackend(GrBackendApi::kVulkan)
101 #ifdef SK_VULKAN
102         , fValid(true)
103 #else
104         , fValid(false)
105 #endif
106         , fTextureType(GrTextureType::k2D) {
107     fVk.fFormat = vkFormat;
108     fVk.fYcbcrConversionInfo = ycbcrInfo;
109     if (fVk.fYcbcrConversionInfo.isValid() && fVk.fYcbcrConversionInfo.fExternalFormat) {
110         fTextureType = GrTextureType::kExternal;
111     }
112 }
113 
asVkFormat(VkFormat * format) const114 bool GrBackendFormat::asVkFormat(VkFormat* format) const {
115     SkASSERT(format);
116     if (this->isValid() && GrBackendApi::kVulkan == fBackend) {
117         *format = fVk.fFormat;
118         return true;
119     }
120     return false;
121 }
122 
getVkYcbcrConversionInfo() const123 const GrVkYcbcrConversionInfo* GrBackendFormat::getVkYcbcrConversionInfo() const {
124     if (this->isValid() && GrBackendApi::kVulkan == fBackend) {
125         return &fVk.fYcbcrConversionInfo;
126     }
127     return nullptr;
128 }
129 
130 #ifdef SK_DAWN
GrBackendFormat(dawn::TextureFormat format)131 GrBackendFormat::GrBackendFormat(dawn::TextureFormat format)
132         : fBackend(GrBackendApi::kDawn)
133         , fValid(true)
134         , fDawnFormat(format)
135         , fTextureType(GrTextureType::k2D) {
136 }
137 
asDawnFormat(dawn::TextureFormat * format) const138 bool GrBackendFormat::asDawnFormat(dawn::TextureFormat* format) const {
139     SkASSERT(format);
140     if (this->isValid() && GrBackendApi::kDawn == fBackend) {
141         *format = fDawnFormat;
142         return true;
143     }
144     return false;
145 }
146 #endif
147 
148 #ifdef SK_METAL
GrBackendFormat(GrMTLPixelFormat mtlFormat)149 GrBackendFormat::GrBackendFormat(GrMTLPixelFormat mtlFormat)
150         : fBackend(GrBackendApi::kMetal)
151         , fValid(true)
152         , fMtlFormat(mtlFormat)
153         , fTextureType(GrTextureType::k2D) {
154 }
155 
asMtlFormat() const156 GrMTLPixelFormat GrBackendFormat::asMtlFormat() const {
157     if (this->isValid() && GrBackendApi::kMetal == fBackend) {
158         return fMtlFormat;
159     }
160     // MTLPixelFormatInvalid == 0
161     return GrMTLPixelFormat(0);
162 }
163 #endif
164 
GrBackendFormat(GrColorType colorType)165 GrBackendFormat::GrBackendFormat(GrColorType colorType)
166         : fBackend(GrBackendApi::kMock)
167         , fValid(true)
168         , fTextureType(GrTextureType::k2D) {
169     fMockColorType = colorType;
170 }
171 
asMockColorType() const172 GrColorType GrBackendFormat::asMockColorType() const {
173     if (this->isValid() && GrBackendApi::kMock == fBackend) {
174         return fMockColorType;
175     }
176     return GrColorType::kUnknown;
177 }
178 
makeTexture2D() const179 GrBackendFormat GrBackendFormat::makeTexture2D() const {
180     GrBackendFormat copy = *this;
181     if (const GrVkYcbcrConversionInfo* ycbcrInfo = this->getVkYcbcrConversionInfo()) {
182         if (ycbcrInfo->isValid()) {
183             // If we have a ycbcr we remove it from the backend format and set the VkFormat to
184             // R8G8B8A8_UNORM
185             SkASSERT(copy.fBackend == GrBackendApi::kVulkan);
186             copy.fVk.fYcbcrConversionInfo = GrVkYcbcrConversionInfo();
187             copy.fVk.fFormat = VK_FORMAT_R8G8B8A8_UNORM;
188         }
189     }
190     copy.fTextureType = GrTextureType::k2D;
191     return copy;
192 }
193 
operator ==(const GrBackendFormat & that) const194 bool GrBackendFormat::operator==(const GrBackendFormat& that) const {
195     // Invalid GrBackendFormats are never equal to anything.
196     if (!fValid || !that.fValid) {
197         return false;
198     }
199 
200     if (fBackend != that.fBackend) {
201         return false;
202     }
203 
204     switch (fBackend) {
205         case GrBackendApi::kOpenGL:
206             return fGLFormat == that.fGLFormat;
207         case GrBackendApi::kVulkan:
208 #ifdef SK_VULKAN
209             return fVk.fFormat == that.fVk.fFormat &&
210                    fVk.fYcbcrConversionInfo == that.fVk.fYcbcrConversionInfo;
211 #endif
212             break;
213 #ifdef SK_METAL
214         case GrBackendApi::kMetal:
215             return fMtlFormat == that.fMtlFormat;
216 #endif
217             break;
218         case GrBackendApi::kDawn:
219 #ifdef SK_DAWN
220             return fDawnFormat == that.fDawnFormat;
221 #endif
222             break;
223         case GrBackendApi::kMock:
224             return fMockColorType == that.fMockColorType;
225         default:
226             SK_ABORT("Unknown GrBackend");
227     }
228     return false;
229 }
230 
231 #if GR_TEST_UTILS
232 #include "include/core/SkString.h"
233 #include "src/gpu/GrTestUtils.h"
234 
235 #ifdef SK_GL
236 #include "src/gpu/gl/GrGLUtil.h"
237 #endif
238 #ifdef SK_VULKAN
239 #include "src/gpu/vk/GrVkUtil.h"
240 #endif
241 
toStr() const242 SkString GrBackendFormat::toStr() const {
243     SkString str;
244 
245     if (!fValid) {
246         str.append("invalid");
247         return str;
248     }
249 
250     str.appendf("%s-", GrBackendApiToStr(fBackend));
251 
252     switch (fBackend) {
253         case GrBackendApi::kOpenGL:
254 #ifdef SK_GL
255             str.append(GrGLFormatToStr(fGLFormat));
256 #endif
257             break;
258         case GrBackendApi::kVulkan:
259 #ifdef SK_VULKAN
260             str.append(GrVkFormatToStr(fVk.fFormat));
261 #endif
262             break;
263         case GrBackendApi::kMetal:
264 #ifdef SK_METAL
265             str.append(GrMtlFormatToStr(fMtlFormat));
266 #endif
267             break;
268         case GrBackendApi::kDawn:
269 #ifdef SK_DAWN
270             str.append(GrDawnFormatToStr(fDawnFormat));
271 #endif
272             break;
273         case GrBackendApi::kMock:
274             str.append(GrColorTypeToStr(fMockColorType));
275             break;
276     }
277 
278     return str;
279 }
280 #endif
281 
282 ///////////////////////////////////////////////////////////////////////////////////////////////////
283 #ifdef SK_DAWN
GrBackendTexture(int width,int height,const GrDawnImageInfo & dawnInfo)284 GrBackendTexture::GrBackendTexture(int width,
285                                    int height,
286                                    const GrDawnImageInfo& dawnInfo)
287         : fIsValid(true)
288         , fWidth(width)
289         , fHeight(height)
290         , fMipMapped(GrMipMapped(dawnInfo.fLevelCount > 1))
291         , fBackend(GrBackendApi::kDawn)
292         , fDawnInfo(dawnInfo) {}
293 #endif
294 
GrBackendTexture(int width,int height,const GrVkImageInfo & vkInfo)295 GrBackendTexture::GrBackendTexture(int width, int height, const GrVkImageInfo& vkInfo)
296 #ifdef SK_VULKAN
297         : GrBackendTexture(width, height, vkInfo,
298                            sk_sp<GrVkImageLayout>(new GrVkImageLayout(vkInfo.fImageLayout))) {}
299 #else
300         : fIsValid(false) {}
301 #endif
302 
303 #ifdef SK_GL
GrBackendTexture(int width,int height,GrMipMapped mipMapped,const GrGLTextureInfo glInfo,sk_sp<GrGLTextureParameters> params)304 GrBackendTexture::GrBackendTexture(int width,
305                                    int height,
306                                    GrMipMapped mipMapped,
307                                    const GrGLTextureInfo glInfo,
308                                    sk_sp<GrGLTextureParameters> params)
309         : fIsValid(true)
310         , fWidth(width)
311         , fHeight(height)
312         , fMipMapped(mipMapped)
313         , fBackend(GrBackendApi::kOpenGL)
314         , fGLInfo(glInfo, params.release()) {}
315 
getGLTextureParams() const316 sk_sp<GrGLTextureParameters> GrBackendTexture::getGLTextureParams() const {
317     if (fBackend != GrBackendApi::kOpenGL) {
318         return nullptr;
319     }
320     return fGLInfo.refParameters();
321 }
322 #endif
323 
324 #ifdef SK_VULKAN
GrBackendTexture(int width,int height,const GrVkImageInfo & vkInfo,sk_sp<GrVkImageLayout> layout)325 GrBackendTexture::GrBackendTexture(int width,
326                                    int height,
327                                    const GrVkImageInfo& vkInfo,
328                                    sk_sp<GrVkImageLayout> layout)
329         : fIsValid(true)
330         , fWidth(width)
331         , fHeight(height)
332         , fMipMapped(GrMipMapped(vkInfo.fLevelCount > 1))
333         , fBackend(GrBackendApi::kVulkan)
334         , fVkInfo(vkInfo, layout.release()) {}
335 #endif
336 
337 #ifdef SK_METAL
GrBackendTexture(int width,int height,GrMipMapped mipMapped,const GrMtlTextureInfo & mtlInfo)338 GrBackendTexture::GrBackendTexture(int width,
339                                    int height,
340                                    GrMipMapped mipMapped,
341                                    const GrMtlTextureInfo& mtlInfo)
342         : fIsValid(true)
343         , fWidth(width)
344         , fHeight(height)
345         , fMipMapped(mipMapped)
346         , fBackend(GrBackendApi::kMetal)
347         , fMtlInfo(mtlInfo) {}
348 #endif
349 
GrBackendTexture(int width,int height,GrMipMapped mipMapped,const GrGLTextureInfo & glInfo)350 GrBackendTexture::GrBackendTexture(int width,
351                                    int height,
352                                    GrMipMapped mipMapped,
353                                    const GrGLTextureInfo& glInfo)
354         : GrBackendTexture(width, height, mipMapped, glInfo, sk_make_sp<GrGLTextureParameters>()) {
355     // Make no assumptions about client's texture's parameters.
356     this->glTextureParametersModified();
357 }
358 
GrBackendTexture(int width,int height,GrMipMapped mipMapped,const GrMockTextureInfo & mockInfo)359 GrBackendTexture::GrBackendTexture(int width,
360                                    int height,
361                                    GrMipMapped mipMapped,
362                                    const GrMockTextureInfo& mockInfo)
363         : fIsValid(true)
364         , fWidth(width)
365         , fHeight(height)
366         , fMipMapped(mipMapped)
367         , fBackend(GrBackendApi::kMock)
368         , fMockInfo(mockInfo) {}
369 
~GrBackendTexture()370 GrBackendTexture::~GrBackendTexture() {
371     this->cleanup();
372 }
373 
cleanup()374 void GrBackendTexture::cleanup() {
375 #ifdef SK_GL
376     if (this->isValid() && GrBackendApi::kOpenGL == fBackend) {
377         fGLInfo.cleanup();
378     }
379 #endif
380 #ifdef SK_VULKAN
381     if (this->isValid() && GrBackendApi::kVulkan == fBackend) {
382         fVkInfo.cleanup();
383     }
384 #endif
385 }
386 
GrBackendTexture(const GrBackendTexture & that)387 GrBackendTexture::GrBackendTexture(const GrBackendTexture& that) : fIsValid(false) {
388     *this = that;
389 }
390 
operator =(const GrBackendTexture & that)391 GrBackendTexture& GrBackendTexture::operator=(const GrBackendTexture& that) {
392     if (!that.isValid()) {
393         this->cleanup();
394         fIsValid = false;
395         return *this;
396     } else if (fIsValid && this->fBackend != that.fBackend) {
397         this->cleanup();
398         fIsValid = false;
399     }
400     fWidth = that.fWidth;
401     fHeight = that.fHeight;
402     fMipMapped = that.fMipMapped;
403     fBackend = that.fBackend;
404 
405     switch (that.fBackend) {
406 #ifdef SK_GL
407         case GrBackendApi::kOpenGL:
408             fGLInfo.assign(that.fGLInfo, this->isValid());
409             break;
410 #endif
411 #ifdef SK_VULKAN
412         case GrBackendApi::kVulkan:
413             fVkInfo.assign(that.fVkInfo, this->isValid());
414             break;
415 #endif
416 #ifdef SK_METAL
417         case GrBackendApi::kMetal:
418             fMtlInfo = that.fMtlInfo;
419             break;
420 #endif
421 #ifdef SK_DAWN
422         case GrBackendApi::kDawn:
423             fDawnInfo = that.fDawnInfo;
424             break;
425 #endif
426         case GrBackendApi::kMock:
427             fMockInfo = that.fMockInfo;
428             break;
429         default:
430             SK_ABORT("Unknown GrBackend");
431     }
432     fIsValid = true;
433     return *this;
434 }
435 
436 #ifdef SK_DAWN
getDawnImageInfo(GrDawnImageInfo * outInfo) const437 bool GrBackendTexture::getDawnImageInfo(GrDawnImageInfo* outInfo) const {
438     if (this->isValid() && GrBackendApi::kDawn == fBackend) {
439         *outInfo = fDawnInfo;
440         return true;
441     }
442     return false;
443 }
444 #endif
445 
getVkImageInfo(GrVkImageInfo * outInfo) const446 bool GrBackendTexture::getVkImageInfo(GrVkImageInfo* outInfo) const {
447 #ifdef SK_VULKAN
448     if (this->isValid() && GrBackendApi::kVulkan == fBackend) {
449         *outInfo = fVkInfo.snapImageInfo();
450         return true;
451     }
452 #endif
453     return false;
454 }
455 
setVkImageLayout(VkImageLayout layout)456 void GrBackendTexture::setVkImageLayout(VkImageLayout layout) {
457 #ifdef SK_VULKAN
458     if (this->isValid() && GrBackendApi::kVulkan == fBackend) {
459         fVkInfo.setImageLayout(layout);
460     }
461 #endif
462 }
463 
464 #ifdef SK_VULKAN
getGrVkImageLayout() const465 sk_sp<GrVkImageLayout> GrBackendTexture::getGrVkImageLayout() const {
466     if (this->isValid() && GrBackendApi::kVulkan == fBackend) {
467         return fVkInfo.getGrVkImageLayout();
468     }
469     return nullptr;
470 }
471 #endif
472 
473 #ifdef SK_METAL
getMtlTextureInfo(GrMtlTextureInfo * outInfo) const474 bool GrBackendTexture::getMtlTextureInfo(GrMtlTextureInfo* outInfo) const {
475     if (this->isValid() && GrBackendApi::kMetal == fBackend) {
476         *outInfo = fMtlInfo;
477         return true;
478     }
479     return false;
480 }
481 #endif
482 
getGLTextureInfo(GrGLTextureInfo * outInfo) const483 bool GrBackendTexture::getGLTextureInfo(GrGLTextureInfo* outInfo) const {
484 #ifdef SK_GL
485     if (this->isValid() && GrBackendApi::kOpenGL == fBackend) {
486         *outInfo = fGLInfo.info();
487         return true;
488     } else if (this->isValid() && GrBackendApi::kMock == fBackend) {
489         // Hack! This allows some blink unit tests to work when using the Mock GrContext.
490         // Specifically, tests that rely on CanvasResourceProviderTextureGpuMemoryBuffer.
491         // If that code ever goes away (or ideally becomes backend-agnostic), this can go away.
492         *outInfo = GrGLTextureInfo{ GR_GL_TEXTURE_2D,
493                                     static_cast<GrGLuint>(fMockInfo.fID),
494                                     GR_GL_RGBA8 };
495         return true;
496     }
497 #endif
498     return false;
499 }
500 
glTextureParametersModified()501 void GrBackendTexture::glTextureParametersModified() {
502 #ifdef SK_GL
503     if (this->isValid() && fBackend == GrBackendApi::kOpenGL) {
504         fGLInfo.parameters()->invalidate();
505     }
506 #endif
507 }
508 
getMockTextureInfo(GrMockTextureInfo * outInfo) const509 bool GrBackendTexture::getMockTextureInfo(GrMockTextureInfo* outInfo) const {
510     if (this->isValid() && GrBackendApi::kMock == fBackend) {
511         *outInfo = fMockInfo;
512         return true;
513     }
514     return false;
515 }
516 
isProtected() const517 bool GrBackendTexture::isProtected() const {
518     if (!this->isValid() || this->backend() != GrBackendApi::kVulkan) {
519         return false;
520     }
521     return fVkInfo.isProtected();
522 }
523 
isSameTexture(const GrBackendTexture & that)524 bool GrBackendTexture::isSameTexture(const GrBackendTexture& that) {
525     if (!this->isValid() || !that.isValid()) {
526         return false;
527     }
528     if (fBackend != that.fBackend) {
529         return false;
530     }
531     switch (fBackend) {
532 #ifdef SK_GL
533         case GrBackendApi::kOpenGL:
534             return fGLInfo.info().fID == that.fGLInfo.info().fID;
535 #endif
536 #ifdef SK_VULKAN
537         case GrBackendApi::kVulkan:
538             return fVkInfo.snapImageInfo().fImage == that.fVkInfo.snapImageInfo().fImage;
539 #endif
540 #ifdef SK_METAL
541         case GrBackendApi::kMetal:
542             return this->fMtlInfo.fTexture == that.fMtlInfo.fTexture;
543 #endif
544         case GrBackendApi::kMock:
545             return fMockInfo.fID == that.fMockInfo.fID;
546         default:
547             return false;
548     }
549 }
550 
getBackendFormat() const551 GrBackendFormat GrBackendTexture::getBackendFormat() const {
552     if (!this->isValid()) {
553         return GrBackendFormat();
554     }
555     switch (fBackend) {
556 #ifdef SK_GL
557         case GrBackendApi::kOpenGL:
558             return GrBackendFormat::MakeGL(fGLInfo.info().fFormat, fGLInfo.info().fTarget);
559 #endif
560 #ifdef SK_VULKAN
561         case GrBackendApi::kVulkan: {
562             auto info = fVkInfo.snapImageInfo();
563             if (info.fYcbcrConversionInfo.isValid()) {
564                 SkASSERT(info.fFormat == info.fYcbcrConversionInfo.fFormat);
565                 return GrBackendFormat::MakeVk(info.fYcbcrConversionInfo);
566             }
567             return GrBackendFormat::MakeVk(info.fFormat);
568         }
569 #endif
570 #ifdef SK_DAWN
571         case GrBackendApi::kDawn: {
572             return GrBackendFormat::MakeDawn(fDawnInfo.fFormat);
573         }
574 #endif
575 #ifdef SK_METAL
576         case GrBackendApi::kMetal: {
577             GrMtlTextureInfo mtlInfo;
578             SkAssertResult(this->getMtlTextureInfo(&mtlInfo));
579             return GrBackendFormat::MakeMtl(GrGetMTLPixelFormatFromMtlTextureInfo(mtlInfo));
580         }
581 #endif
582         case GrBackendApi::kMock:
583             return fMockInfo.getBackendFormat();
584         default:
585             return GrBackendFormat();
586     }
587 }
588 
589 #if GR_TEST_UTILS
TestingOnly_Equals(const GrBackendTexture & t0,const GrBackendTexture & t1)590 bool GrBackendTexture::TestingOnly_Equals(const GrBackendTexture& t0, const GrBackendTexture& t1) {
591     if (!t0.isValid() || !t1.isValid()) {
592         return false; // two invalid backend textures are not considered equal
593     }
594 
595     if (t0.fWidth != t1.fWidth ||
596         t0.fHeight != t1.fHeight ||
597         t0.fMipMapped != t1.fMipMapped ||
598         t0.fBackend != t1.fBackend) {
599         return false;
600     }
601 
602     switch (t0.fBackend) {
603 #ifdef SK_GL
604         case GrBackendApi::kOpenGL:
605             return t0.fGLInfo.info() == t1.fGLInfo.info();
606 #endif
607         case GrBackendApi::kMock:
608             return t0.fMockInfo == t1.fMockInfo;
609 #ifdef SK_VULKAN
610         case GrBackendApi::kVulkan:
611             return t0.fVkInfo == t1.fVkInfo;
612 #endif
613 #ifdef SK_METAL
614         case GrBackendApi::kMetal:
615             return t0.fMtlInfo == t1.fMtlInfo;
616 #endif
617 #ifdef SK_DAWN
618         case GrBackendApi::kDawn:
619             return t0.fDawnInfo == t1.fDawnInfo;
620 #endif
621         default:
622             return false;
623     }
624 }
625 #endif
626 
627 ////////////////////////////////////////////////////////////////////////////////////////////////////
628 
629 #ifdef SK_DAWN
GrBackendRenderTarget(int width,int height,int sampleCnt,int stencilBits,const GrDawnImageInfo & dawnInfo)630 GrBackendRenderTarget::GrBackendRenderTarget(int width,
631                                              int height,
632                                              int sampleCnt,
633                                              int stencilBits,
634                                              const GrDawnImageInfo& dawnInfo)
635         : fIsValid(true)
636         , fWidth(width)
637         , fHeight(height)
638         , fSampleCnt(sampleCnt)
639         , fStencilBits(stencilBits)
640         , fBackend(GrBackendApi::kDawn)
641         , fDawnInfo(dawnInfo) {}
642 #endif
643 
GrBackendRenderTarget(int width,int height,int sampleCnt,int stencilBits,const GrVkImageInfo & vkInfo)644 GrBackendRenderTarget::GrBackendRenderTarget(int width,
645                                              int height,
646                                              int sampleCnt,
647                                              int stencilBits,
648                                              const GrVkImageInfo& vkInfo)
649         : GrBackendRenderTarget(width, height, sampleCnt, vkInfo) {
650     // This is a deprecated constructor that takes a bogus stencil bits.
651     SkASSERT(0 == stencilBits);
652 }
653 
GrBackendRenderTarget(int width,int height,int sampleCnt,const GrVkImageInfo & vkInfo)654 GrBackendRenderTarget::GrBackendRenderTarget(int width,
655                                              int height,
656                                              int sampleCnt,
657                                              const GrVkImageInfo& vkInfo)
658 #ifdef SK_VULKAN
659         : GrBackendRenderTarget(width, height, sampleCnt, vkInfo,
660                                 sk_sp<GrVkImageLayout>(new GrVkImageLayout(vkInfo.fImageLayout))) {}
661 #else
662         : fIsValid(false) {}
663 #endif
664 
665 #ifdef SK_VULKAN
GrBackendRenderTarget(int width,int height,int sampleCnt,const GrVkImageInfo & vkInfo,sk_sp<GrVkImageLayout> layout)666 GrBackendRenderTarget::GrBackendRenderTarget(int width,
667                                              int height,
668                                              int sampleCnt,
669                                              const GrVkImageInfo& vkInfo,
670                                              sk_sp<GrVkImageLayout> layout)
671         : fIsValid(true)
672         , fWidth(width)
673         , fHeight(height)
674         , fSampleCnt(SkTMax(1, sampleCnt))
675         , fStencilBits(0)  // We always create stencil buffers internally for vulkan
676         , fBackend(GrBackendApi::kVulkan)
677         , fVkInfo(vkInfo, layout.release()) {}
678 #endif
679 
680 #ifdef SK_METAL
GrBackendRenderTarget(int width,int height,int sampleCnt,const GrMtlTextureInfo & mtlInfo)681 GrBackendRenderTarget::GrBackendRenderTarget(int width,
682                                              int height,
683                                              int sampleCnt,
684                                              const GrMtlTextureInfo& mtlInfo)
685         : fIsValid(true)
686         , fWidth(width)
687         , fHeight(height)
688         , fSampleCnt(SkTMax(1, sampleCnt))
689         , fStencilBits(0)
690         , fBackend(GrBackendApi::kMetal)
691         , fMtlInfo(mtlInfo) {}
692 #endif
693 
GrBackendRenderTarget(int width,int height,int sampleCnt,int stencilBits,const GrGLFramebufferInfo & glInfo)694 GrBackendRenderTarget::GrBackendRenderTarget(int width,
695                                              int height,
696                                              int sampleCnt,
697                                              int stencilBits,
698                                              const GrGLFramebufferInfo& glInfo)
699         : fWidth(width)
700         , fHeight(height)
701         , fSampleCnt(SkTMax(1, sampleCnt))
702         , fStencilBits(stencilBits)
703         , fBackend(GrBackendApi::kOpenGL)
704         , fGLInfo(glInfo) {
705     fIsValid = SkToBool(glInfo.fFormat); // the glInfo must have a valid format
706 }
707 
GrBackendRenderTarget(int width,int height,int sampleCnt,int stencilBits,const GrMockRenderTargetInfo & mockInfo)708 GrBackendRenderTarget::GrBackendRenderTarget(int width,
709                                              int height,
710                                              int sampleCnt,
711                                              int stencilBits,
712                                              const GrMockRenderTargetInfo& mockInfo)
713         : fIsValid(true)
714         , fWidth(width)
715         , fHeight(height)
716         , fSampleCnt(SkTMax(1, sampleCnt))
717         , fStencilBits(stencilBits)
718         , fMockInfo(mockInfo) {}
719 
~GrBackendRenderTarget()720 GrBackendRenderTarget::~GrBackendRenderTarget() {
721     this->cleanup();
722 }
723 
cleanup()724 void GrBackendRenderTarget::cleanup() {
725 #ifdef SK_VULKAN
726     if (this->isValid() && GrBackendApi::kVulkan == fBackend) {
727         fVkInfo.cleanup();
728     }
729 #endif
730 }
731 
GrBackendRenderTarget(const GrBackendRenderTarget & that)732 GrBackendRenderTarget::GrBackendRenderTarget(const GrBackendRenderTarget& that) : fIsValid(false) {
733     *this = that;
734 }
735 
operator =(const GrBackendRenderTarget & that)736 GrBackendRenderTarget& GrBackendRenderTarget::operator=(const GrBackendRenderTarget& that) {
737     if (!that.isValid()) {
738         this->cleanup();
739         fIsValid = false;
740         return *this;
741     } else if (fIsValid && this->fBackend != that.fBackend) {
742         this->cleanup();
743         fIsValid = false;
744     }
745     fWidth = that.fWidth;
746     fHeight = that.fHeight;
747     fSampleCnt = that.fSampleCnt;
748     fStencilBits = that.fStencilBits;
749     fBackend = that.fBackend;
750 
751     switch (that.fBackend) {
752         case GrBackendApi::kOpenGL:
753             fGLInfo = that.fGLInfo;
754             break;
755         case GrBackendApi::kVulkan:
756 #ifdef SK_VULKAN
757             fVkInfo.assign(that.fVkInfo, this->isValid());
758 #endif
759             break;
760 #ifdef SK_DAWN
761         case GrBackendApi::kDawn:
762             fDawnInfo = that.fDawnInfo;
763             break;
764 #endif
765 #ifdef SK_METAL
766         case GrBackendApi::kMetal:
767             fMtlInfo = that.fMtlInfo;
768             break;
769 #endif
770         case GrBackendApi::kMock:
771             fMockInfo = that.fMockInfo;
772             break;
773         default:
774             SK_ABORT("Unknown GrBackend");
775     }
776     fIsValid = that.fIsValid;
777     return *this;
778 }
779 
780 #ifdef SK_DAWN
getDawnImageInfo(GrDawnImageInfo * outInfo) const781 bool GrBackendRenderTarget::getDawnImageInfo(GrDawnImageInfo* outInfo) const {
782     if (this->isValid() && GrBackendApi::kDawn == fBackend) {
783         *outInfo = fDawnInfo;
784         return true;
785     }
786     return false;
787 }
788 #endif
789 
getVkImageInfo(GrVkImageInfo * outInfo) const790 bool GrBackendRenderTarget::getVkImageInfo(GrVkImageInfo* outInfo) const {
791 #ifdef SK_VULKAN
792     if (this->isValid() && GrBackendApi::kVulkan == fBackend) {
793         *outInfo = fVkInfo.snapImageInfo();
794         return true;
795     }
796 #endif
797     return false;
798 }
799 
setVkImageLayout(VkImageLayout layout)800 void GrBackendRenderTarget::setVkImageLayout(VkImageLayout layout) {
801 #ifdef SK_VULKAN
802     if (this->isValid() && GrBackendApi::kVulkan == fBackend) {
803         fVkInfo.setImageLayout(layout);
804     }
805 #endif
806 }
807 
808 #ifdef SK_VULKAN
getGrVkImageLayout() const809 sk_sp<GrVkImageLayout> GrBackendRenderTarget::getGrVkImageLayout() const {
810     if (this->isValid() && GrBackendApi::kVulkan == fBackend) {
811         return fVkInfo.getGrVkImageLayout();
812     }
813     return nullptr;
814 }
815 #endif
816 
817 #ifdef SK_METAL
getMtlTextureInfo(GrMtlTextureInfo * outInfo) const818 bool GrBackendRenderTarget::getMtlTextureInfo(GrMtlTextureInfo* outInfo) const {
819     if (this->isValid() && GrBackendApi::kMetal == fBackend) {
820         *outInfo = fMtlInfo;
821         return true;
822     }
823     return false;
824 }
825 #endif
826 
getGLFramebufferInfo(GrGLFramebufferInfo * outInfo) const827 bool GrBackendRenderTarget::getGLFramebufferInfo(GrGLFramebufferInfo* outInfo) const {
828     if (this->isValid() && GrBackendApi::kOpenGL == fBackend) {
829         *outInfo = fGLInfo;
830         return true;
831     }
832     return false;
833 }
834 
getBackendFormat() const835 GrBackendFormat GrBackendRenderTarget::getBackendFormat() const {
836     if (!this->isValid()) {
837         return GrBackendFormat();
838     }
839     switch (fBackend) {
840 #ifdef SK_GL
841         case GrBackendApi::kOpenGL:
842             return GrBackendFormat::MakeGL(fGLInfo.fFormat, GR_GL_TEXTURE_NONE);
843 #endif
844 #ifdef SK_VULKAN
845         case GrBackendApi::kVulkan: {
846             auto info = fVkInfo.snapImageInfo();
847             if (info.fYcbcrConversionInfo.isValid()) {
848                 SkASSERT(info.fFormat == info.fYcbcrConversionInfo.fFormat);
849                 return GrBackendFormat::MakeVk(info.fYcbcrConversionInfo);
850             }
851             return GrBackendFormat::MakeVk(info.fFormat);
852         }
853 #endif
854 #ifdef SK_METAL
855         case GrBackendApi::kMetal: {
856             GrMtlTextureInfo mtlInfo;
857             SkAssertResult(this->getMtlTextureInfo(&mtlInfo));
858             return GrBackendFormat::MakeMtl(GrGetMTLPixelFormatFromMtlTextureInfo(mtlInfo));
859         }
860 #endif
861         case GrBackendApi::kMock:
862             return fMockInfo.getBackendFormat();
863         default:
864             return GrBackendFormat();
865     }
866 }
867 
getMockRenderTargetInfo(GrMockRenderTargetInfo * outInfo) const868 bool GrBackendRenderTarget::getMockRenderTargetInfo(GrMockRenderTargetInfo* outInfo) const {
869     if (this->isValid() && GrBackendApi::kMock == fBackend) {
870         *outInfo = fMockInfo;
871         return true;
872     }
873     return false;
874 }
875 
isProtected() const876 bool GrBackendRenderTarget::isProtected() const {
877     if (!this->isValid() || this->backend() != GrBackendApi::kVulkan) {
878         return false;
879     }
880     return fVkInfo.isProtected();
881 }
882 
883 #if GR_TEST_UTILS
TestingOnly_Equals(const GrBackendRenderTarget & r0,const GrBackendRenderTarget & r1)884 bool GrBackendRenderTarget::TestingOnly_Equals(const GrBackendRenderTarget& r0,
885                                                const GrBackendRenderTarget& r1) {
886     if (!r0.isValid() || !r1.isValid()) {
887         return false; // two invalid backend rendertargets are not considered equal
888     }
889 
890     if (r0.fWidth != r1.fWidth ||
891         r0.fHeight != r1.fHeight ||
892         r0.fSampleCnt != r1.fSampleCnt ||
893         r0.fStencilBits != r1.fStencilBits ||
894         r0.fBackend != r1.fBackend) {
895         return false;
896     }
897 
898     switch (r0.fBackend) {
899 #ifdef SK_GL
900         case GrBackendApi::kOpenGL:
901             return r0.fGLInfo == r1.fGLInfo;
902 #endif
903         case GrBackendApi::kMock:
904             return r0.fMockInfo == r1.fMockInfo;
905 #ifdef SK_VULKAN
906         case GrBackendApi::kVulkan:
907             return r0.fVkInfo == r1.fVkInfo;
908 #endif
909 #ifdef SK_METAL
910         case GrBackendApi::kMetal:
911             return r0.fMtlInfo == r1.fMtlInfo;
912 #endif
913 #ifdef SK_DAWN
914         case GrBackendApi::kDawn:
915             return r0.fDawnInfo == r1.fDawnInfo;
916 #endif
917         default:
918             return false;
919     }
920 
921     SkASSERT(0);
922     return false;
923 }
924 #endif
925