• 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 "GrBackendSurface.h"
10 
11 #include "gl/GrGLUtil.h"
12 
13 #ifdef SK_VULKAN
14 #include "vk/GrVkImageLayout.h"
15 #include "vk/GrVkTypes.h"
16 #include "vk/GrVkUtil.h"
17 #endif
18 #ifdef SK_METAL
19 #include "mtl/GrMtlTypes.h"
20 #include "mtl/GrMtlCppUtil.h"
21 #endif
22 
GrBackendFormat(GrGLenum format,GrGLenum target)23 GrBackendFormat::GrBackendFormat(GrGLenum format, GrGLenum target)
24         : fBackend(GrBackendApi::kOpenGL)
25         , fValid(true)
26         , fGLFormat(format) {
27     switch (target) {
28         case GR_GL_TEXTURE_2D:
29             fTextureType = GrTextureType::k2D;
30             break;
31         case GR_GL_TEXTURE_RECTANGLE:
32             fTextureType = GrTextureType::kRectangle;
33             break;
34         case GR_GL_TEXTURE_EXTERNAL:
35             fTextureType = GrTextureType::kExternal;
36             break;
37         default:
38             SK_ABORT("Unexpected texture target");
39     }
40 }
41 
getGLFormat() const42 const GrGLenum* GrBackendFormat::getGLFormat() const {
43     if (this->isValid() && GrBackendApi::kOpenGL == fBackend) {
44         return &fGLFormat;
45     }
46     return nullptr;
47 }
48 
getGLTarget() const49 const GrGLenum* GrBackendFormat::getGLTarget() const {
50     if (this->isValid() && GrBackendApi::kOpenGL == fBackend) {
51         static constexpr GrGLenum k2D = GR_GL_TEXTURE_2D;
52         static constexpr GrGLenum kRect = GR_GL_TEXTURE_RECTANGLE;
53         static constexpr GrGLenum kExternal = GR_GL_TEXTURE_EXTERNAL;
54         switch (fTextureType) {
55             case GrTextureType::k2D:
56                 return &k2D;
57             case GrTextureType::kRectangle:
58                 return &kRect;
59             case GrTextureType::kExternal:
60                 return &kExternal;
61         }
62     }
63     return nullptr;
64 }
65 
MakeVk(const GrVkYcbcrConversionInfo & ycbcrInfo)66 GrBackendFormat GrBackendFormat::MakeVk(const GrVkYcbcrConversionInfo& ycbcrInfo) {
67 #ifdef SK_BUILD_FOR_ANDROID
68     return GrBackendFormat(VK_FORMAT_UNDEFINED, ycbcrInfo);
69 #else
70     return GrBackendFormat();
71 #endif
72 }
73 
GrBackendFormat(VkFormat vkFormat,const GrVkYcbcrConversionInfo & ycbcrInfo)74 GrBackendFormat::GrBackendFormat(VkFormat vkFormat, const GrVkYcbcrConversionInfo& ycbcrInfo)
75         : fBackend(GrBackendApi::kVulkan)
76 #ifdef SK_VULKAN
77         , fValid(true)
78 #else
79         , fValid(false)
80 #endif
81         , fTextureType(GrTextureType::k2D) {
82     fVk.fFormat = vkFormat;
83     fVk.fYcbcrConversionInfo = ycbcrInfo;
84 }
85 
getVkFormat() const86 const VkFormat* GrBackendFormat::getVkFormat() const {
87     if (this->isValid() && GrBackendApi::kVulkan == fBackend) {
88         return &fVk.fFormat;
89     }
90     return nullptr;
91 }
92 
getVkYcbcrConversionInfo() const93 const GrVkYcbcrConversionInfo* GrBackendFormat::getVkYcbcrConversionInfo() const {
94     if (this->isValid() && GrBackendApi::kVulkan == fBackend) {
95         return &fVk.fYcbcrConversionInfo;
96     }
97     return nullptr;
98 }
99 
100 #ifdef SK_METAL
GrBackendFormat(GrMTLPixelFormat mtlFormat)101 GrBackendFormat::GrBackendFormat(GrMTLPixelFormat mtlFormat)
102         : fBackend(GrBackendApi::kMetal)
103         , fValid(true)
104         , fMtlFormat(mtlFormat)
105         , fTextureType(GrTextureType::k2D) {
106 }
107 
getMtlFormat() const108 const GrMTLPixelFormat* GrBackendFormat::getMtlFormat() const {
109     if (this->isValid() && GrBackendApi::kMetal == fBackend) {
110         return &fMtlFormat;
111     }
112     return nullptr;
113 }
114 #endif
115 
GrBackendFormat(GrPixelConfig config)116 GrBackendFormat::GrBackendFormat(GrPixelConfig config)
117         : fBackend(GrBackendApi::kMock)
118         , fValid(true)
119         , fMockFormat(config)
120         , fTextureType(GrTextureType::k2D) {
121 }
122 
getMockFormat() const123 const GrPixelConfig* GrBackendFormat::getMockFormat() const {
124     if (this->isValid() && GrBackendApi::kMock == fBackend) {
125         return &fMockFormat;
126     }
127     return nullptr;
128 }
129 
makeTexture2D() const130 GrBackendFormat GrBackendFormat::makeTexture2D() const {
131     // TODO: once we support ycbcr conversions in Vulkan we need to check if we are using an
132     // external format since they will not be able to be made into a Texture2D.
133     GrBackendFormat copy = *this;
134     copy.fTextureType = GrTextureType::k2D;
135     return copy;
136 }
137 
operator ==(const GrBackendFormat & that) const138 bool GrBackendFormat::operator==(const GrBackendFormat& that) const {
139     // Invalid GrBackendFormats are never equal to anything.
140     if (!fValid || !that.fValid) {
141         return false;
142     }
143 
144     if (fBackend != that.fBackend) {
145         return false;
146     }
147 
148     switch (fBackend) {
149         case GrBackendApi::kOpenGL:
150             return fGLFormat == that.fGLFormat;
151         case GrBackendApi::kVulkan:
152 #ifdef SK_VULKAN
153             return fVk.fFormat == that.fVk.fFormat &&
154                    fVk.fYcbcrConversionInfo == that.fVk.fYcbcrConversionInfo;
155 #endif
156             break;
157 #ifdef SK_METAL
158         case GrBackendApi::kMetal:
159             return fMtlFormat == that.fMtlFormat;
160 #endif
161             break;
162         case GrBackendApi::kMock:
163             return fMockFormat == that.fMockFormat;
164         default:
165             SK_ABORT("Unknown GrBackend");
166     }
167     return false;
168 }
169 
GrBackendTexture(int width,int height,const GrVkImageInfo & vkInfo)170 GrBackendTexture::GrBackendTexture(int width,
171                                    int height,
172                                    const GrVkImageInfo& vkInfo)
173 #ifdef SK_VULKAN
174         : GrBackendTexture(width, height, vkInfo,
175                            sk_sp<GrVkImageLayout>(new GrVkImageLayout(vkInfo.fImageLayout))) {}
176 #else
177         : fIsValid(false) {}
178 #endif
179 
180 #ifdef SK_VULKAN
GrBackendTexture(int width,int height,const GrVkImageInfo & vkInfo,sk_sp<GrVkImageLayout> layout)181 GrBackendTexture::GrBackendTexture(int width,
182                                    int height,
183                                    const GrVkImageInfo& vkInfo,
184                                    sk_sp<GrVkImageLayout> layout)
185         : fIsValid(true)
186         , fWidth(width)
187         , fHeight(height)
188         , fConfig(kUnknown_GrPixelConfig)
189         , fMipMapped(GrMipMapped(vkInfo.fLevelCount > 1))
190         , fBackend(GrBackendApi::kVulkan)
191         , fVkInfo(vkInfo, layout.release()) {
192 }
193 #endif
194 
195 #ifdef SK_METAL
GrBackendTexture(int width,int height,GrMipMapped mipMapped,const GrMtlTextureInfo & mtlInfo)196 GrBackendTexture::GrBackendTexture(int width,
197                                    int height,
198                                    GrMipMapped mipMapped,
199                                    const GrMtlTextureInfo& mtlInfo)
200         : fIsValid(true)
201         , fWidth(width)
202         , fHeight(height)
203         , fConfig(GrPixelConfig::kUnknown_GrPixelConfig)
204         , fMipMapped(mipMapped)
205         , fBackend(GrBackendApi::kMetal)
206         , fMtlInfo(mtlInfo) {}
207 #endif
208 
GrBackendTexture(int width,int height,GrMipMapped mipMapped,const GrGLTextureInfo & glInfo)209 GrBackendTexture::GrBackendTexture(int width,
210                                    int height,
211                                    GrMipMapped mipMapped,
212                                    const GrGLTextureInfo& glInfo)
213         : fIsValid(true)
214         , fWidth(width)
215         , fHeight(height)
216         , fConfig(kUnknown_GrPixelConfig)
217         , fMipMapped(mipMapped)
218         , fBackend(GrBackendApi::kOpenGL)
219         , fGLInfo(glInfo) {}
220 
GrBackendTexture(int width,int height,GrMipMapped mipMapped,const GrMockTextureInfo & mockInfo)221 GrBackendTexture::GrBackendTexture(int width,
222                                    int height,
223                                    GrMipMapped mipMapped,
224                                    const GrMockTextureInfo& mockInfo)
225         : fIsValid(true)
226         , fWidth(width)
227         , fHeight(height)
228         , fConfig(mockInfo.fConfig)
229         , fMipMapped(mipMapped)
230         , fBackend(GrBackendApi::kMock)
231         , fMockInfo(mockInfo) {}
232 
~GrBackendTexture()233 GrBackendTexture::~GrBackendTexture() {
234     this->cleanup();
235 }
236 
cleanup()237 void GrBackendTexture::cleanup() {
238 #ifdef SK_VULKAN
239     if (this->isValid() && GrBackendApi::kVulkan == fBackend) {
240         fVkInfo.cleanup();
241     }
242 #endif
243 }
244 
GrBackendTexture(const GrBackendTexture & that)245 GrBackendTexture::GrBackendTexture(const GrBackendTexture& that) : fIsValid(false) {
246     *this = that;
247 }
248 
operator =(const GrBackendTexture & that)249 GrBackendTexture& GrBackendTexture::operator=(const GrBackendTexture& that) {
250     if (!that.isValid()) {
251         this->cleanup();
252         fIsValid = false;
253         return *this;
254     }
255     fWidth = that.fWidth;
256     fHeight = that.fHeight;
257     fConfig = that.fConfig;
258     fMipMapped = that.fMipMapped;
259     fBackend = that.fBackend;
260 
261     switch (that.fBackend) {
262         case GrBackendApi::kOpenGL:
263             fGLInfo = that.fGLInfo;
264             break;
265         case GrBackendApi::kVulkan:
266 #ifdef SK_VULKAN
267             fVkInfo.assign(that.fVkInfo, this->isValid());
268 #endif
269             break;
270 #ifdef SK_METAL
271         case GrBackendApi::kMetal:
272             fMtlInfo = that.fMtlInfo;
273             break;
274 #endif
275         case GrBackendApi::kMock:
276             fMockInfo = that.fMockInfo;
277             break;
278         default:
279             SK_ABORT("Unknown GrBackend");
280     }
281     fIsValid = that.fIsValid;
282     return *this;
283 }
284 
getVkImageInfo(GrVkImageInfo * outInfo) const285 bool GrBackendTexture::getVkImageInfo(GrVkImageInfo* outInfo) const {
286 #ifdef SK_VULKAN
287     if (this->isValid() && GrBackendApi::kVulkan == fBackend) {
288         *outInfo = fVkInfo.snapImageInfo();
289         return true;
290     }
291 #endif
292     return false;
293 }
294 
setVkImageLayout(VkImageLayout layout)295 void GrBackendTexture::setVkImageLayout(VkImageLayout layout) {
296 #ifdef SK_VULKAN
297     if (this->isValid() && GrBackendApi::kVulkan == fBackend) {
298         fVkInfo.setImageLayout(layout);
299     }
300 #endif
301 }
302 
303 // We need a stubbed version of GrVkImageLayout for non vulkan builds
304 #ifndef SK_VULKAN
305 class GrVkImageLayout : public SkRefCnt {
GrVkImageLayout(VkImageLayout layout)306     GrVkImageLayout(VkImageLayout layout) {}
307 };
308 #endif
309 
getGrVkImageLayout() const310 sk_sp<GrVkImageLayout> GrBackendTexture::getGrVkImageLayout() const {
311 #ifdef SK_VULKAN
312     if (this->isValid() && GrBackendApi::kVulkan == fBackend) {
313         return fVkInfo.getGrVkImageLayout();
314     }
315 #endif
316     return nullptr;
317 }
318 
319 #ifdef SK_METAL
getMtlTextureInfo(GrMtlTextureInfo * outInfo) const320 bool GrBackendTexture::getMtlTextureInfo(GrMtlTextureInfo* outInfo) const {
321     if (this->isValid() && GrBackendApi::kMetal == fBackend) {
322         *outInfo = fMtlInfo;
323         return true;
324     }
325     return false;
326 }
327 #endif
328 
getGLTextureInfo(GrGLTextureInfo * outInfo) const329 bool GrBackendTexture::getGLTextureInfo(GrGLTextureInfo* outInfo) const {
330     if (this->isValid() && GrBackendApi::kOpenGL == fBackend) {
331         *outInfo = fGLInfo;
332         return true;
333     }
334     return false;
335 }
336 
getMockTextureInfo(GrMockTextureInfo * outInfo) const337 bool GrBackendTexture::getMockTextureInfo(GrMockTextureInfo* outInfo) const {
338     if (this->isValid() && GrBackendApi::kMock == fBackend) {
339         *outInfo = fMockInfo;
340         return true;
341     }
342     return false;
343 }
344 
getBackendFormat() const345 GrBackendFormat GrBackendTexture::getBackendFormat() const {
346     if (!this->isValid()) {
347         return GrBackendFormat();
348     }
349     switch (fBackend) {
350         case GrBackendApi::kOpenGL:
351             return GrBackendFormat::MakeGL(fGLInfo.fFormat, fGLInfo.fTarget);
352 #ifdef SK_VULKAN
353         case GrBackendApi::kVulkan: {
354             auto info = fVkInfo.snapImageInfo();
355             if (info.fYcbcrConversionInfo.isValid()) {
356                 SkASSERT(info.fFormat == VK_FORMAT_UNDEFINED);
357                 return GrBackendFormat::MakeVk(info.fYcbcrConversionInfo);
358             }
359             return GrBackendFormat::MakeVk(info.fFormat);
360         }
361 #endif
362 #ifdef SK_METAL
363         case GrBackendApi::kMetal: {
364             GrMtlTextureInfo mtlInfo;
365             SkAssertResult(this->getMtlTextureInfo(&mtlInfo));
366             return GrBackendFormat::MakeMtl(GrGetMTLPixelFormatFromMtlTextureInfo(mtlInfo));
367         }
368 #endif
369         case GrBackendApi::kMock:
370             return GrBackendFormat::MakeMock(fMockInfo.fConfig);
371         default:
372             return GrBackendFormat();
373     }
374 }
375 
376 #if GR_TEST_UTILS
TestingOnly_Equals(const GrBackendTexture & t0,const GrBackendTexture & t1)377 bool GrBackendTexture::TestingOnly_Equals(const GrBackendTexture& t0, const GrBackendTexture& t1) {
378     if (!t0.isValid() || !t1.isValid()) {
379         return false; // two invalid backend textures are not considered equal
380     }
381 
382     if (t0.fWidth != t1.fWidth ||
383         t0.fHeight != t1.fHeight ||
384         t0.fConfig != t1.fConfig ||
385         t0.fMipMapped != t1.fMipMapped ||
386         t0.fBackend != t1.fBackend) {
387         return false;
388     }
389 
390     switch (t0.fBackend) {
391     case GrBackendApi::kOpenGL:
392         return t0.fGLInfo == t1.fGLInfo;
393     case GrBackendApi::kMock:
394         return t0.fMockInfo == t1.fMockInfo;
395     case GrBackendApi::kVulkan:
396 #ifdef SK_VULKAN
397         return t0.fVkInfo == t1.fVkInfo;
398 #else
399         // fall through
400 #endif
401     case GrBackendApi::kMetal:
402 #ifdef SK_METAL
403         return t0.fMtlInfo == t1.fMtlInfo;
404 #else
405         // fall through
406 #endif
407     default:
408         return false;
409     }
410 
411     SkASSERT(0);
412     return false;
413 }
414 #endif
415 
416 ////////////////////////////////////////////////////////////////////////////////////////////////////
417 
GrBackendRenderTarget(int width,int height,int sampleCnt,int stencilBits,const GrVkImageInfo & vkInfo)418 GrBackendRenderTarget::GrBackendRenderTarget(int width,
419                                              int height,
420                                              int sampleCnt,
421                                              int stencilBits,
422                                              const GrVkImageInfo& vkInfo)
423         : GrBackendRenderTarget(width, height, sampleCnt, vkInfo) {
424     // This is a deprecated constructor that takes a bogus stencil bits.
425     SkASSERT(0 == stencilBits);
426 }
427 
GrBackendRenderTarget(int width,int height,int sampleCnt,const GrVkImageInfo & vkInfo)428 GrBackendRenderTarget::GrBackendRenderTarget(int width,
429                                              int height,
430                                              int sampleCnt,
431                                              const GrVkImageInfo& vkInfo)
432 #ifdef SK_VULKAN
433         : GrBackendRenderTarget(width, height, sampleCnt, vkInfo,
434                                 sk_sp<GrVkImageLayout>(new GrVkImageLayout(vkInfo.fImageLayout))) {}
435 #else
436         : fIsValid(false) {}
437 #endif
438 
439 #ifdef SK_VULKAN
GrBackendRenderTarget(int width,int height,int sampleCnt,const GrVkImageInfo & vkInfo,sk_sp<GrVkImageLayout> layout)440 GrBackendRenderTarget::GrBackendRenderTarget(int width,
441                                              int height,
442                                              int sampleCnt,
443                                              const GrVkImageInfo& vkInfo,
444                                              sk_sp<GrVkImageLayout> layout)
445         : fIsValid(true)
446         , fWidth(width)
447         , fHeight(height)
448         , fSampleCnt(SkTMax(1, sampleCnt))
449         , fStencilBits(0)  // We always create stencil buffers internally for vulkan
450         , fConfig(kUnknown_GrPixelConfig)
451         , fBackend(GrBackendApi::kVulkan)
452         , fVkInfo(vkInfo, layout.release()) {}
453 #endif
454 
455 #ifdef SK_METAL
GrBackendRenderTarget(int width,int height,int sampleCnt,const GrMtlTextureInfo & mtlInfo)456 GrBackendRenderTarget::GrBackendRenderTarget(int width,
457                                              int height,
458                                              int sampleCnt,
459                                              const GrMtlTextureInfo& mtlInfo)
460         : fIsValid(true)
461         , fWidth(width)
462         , fHeight(height)
463         , fSampleCnt(SkTMax(1, sampleCnt))
464         , fStencilBits(0)
465         , fConfig(GrPixelConfig::kUnknown_GrPixelConfig)
466         , fBackend(GrBackendApi::kMetal)
467         , fMtlInfo(mtlInfo) {}
468 #endif
469 
GrBackendRenderTarget(int width,int height,int sampleCnt,int stencilBits,const GrGLFramebufferInfo & glInfo)470 GrBackendRenderTarget::GrBackendRenderTarget(int width,
471                                              int height,
472                                              int sampleCnt,
473                                              int stencilBits,
474                                              const GrGLFramebufferInfo& glInfo)
475         : fWidth(width)
476         , fHeight(height)
477         , fSampleCnt(SkTMax(1, sampleCnt))
478         , fStencilBits(stencilBits)
479         , fConfig(kUnknown_GrPixelConfig)
480         , fBackend(GrBackendApi::kOpenGL)
481         , fGLInfo(glInfo) {
482     fIsValid = SkToBool(glInfo.fFormat); // the glInfo must have a valid format
483 }
484 
GrBackendRenderTarget(int width,int height,int sampleCnt,int stencilBits,const GrMockRenderTargetInfo & mockInfo)485 GrBackendRenderTarget::GrBackendRenderTarget(int width,
486                                              int height,
487                                              int sampleCnt,
488                                              int stencilBits,
489                                              const GrMockRenderTargetInfo& mockInfo)
490         : fIsValid(true)
491         , fWidth(width)
492         , fHeight(height)
493         , fSampleCnt(SkTMax(1, sampleCnt))
494         , fStencilBits(stencilBits)
495         , fConfig(mockInfo.fConfig)
496         , fMockInfo(mockInfo) {}
497 
~GrBackendRenderTarget()498 GrBackendRenderTarget::~GrBackendRenderTarget() {
499     this->cleanup();
500 }
501 
cleanup()502 void GrBackendRenderTarget::cleanup() {
503 #ifdef SK_VULKAN
504     if (this->isValid() && GrBackendApi::kVulkan == fBackend) {
505         fVkInfo.cleanup();
506     }
507 #endif
508 }
509 
GrBackendRenderTarget(const GrBackendRenderTarget & that)510 GrBackendRenderTarget::GrBackendRenderTarget(const GrBackendRenderTarget& that) : fIsValid(false) {
511     *this = that;
512 }
513 
operator =(const GrBackendRenderTarget & that)514 GrBackendRenderTarget& GrBackendRenderTarget::operator=(const GrBackendRenderTarget& that) {
515     if (!that.isValid()) {
516         this->cleanup();
517         fIsValid = false;
518         return *this;
519     }
520     fWidth = that.fWidth;
521     fHeight = that.fHeight;
522     fSampleCnt = that.fSampleCnt;
523     fStencilBits = that.fStencilBits;
524     fConfig = that.fConfig;
525     fBackend = that.fBackend;
526 
527     switch (that.fBackend) {
528         case GrBackendApi::kOpenGL:
529             fGLInfo = that.fGLInfo;
530             break;
531         case GrBackendApi::kVulkan:
532 #ifdef SK_VULKAN
533             fVkInfo.assign(that.fVkInfo, this->isValid());
534 #endif
535             break;
536 #ifdef SK_METAL
537         case GrBackendApi::kMetal:
538             fMtlInfo = that.fMtlInfo;
539             break;
540 #endif
541         case GrBackendApi::kMock:
542             fMockInfo = that.fMockInfo;
543             break;
544         default:
545             SK_ABORT("Unknown GrBackend");
546     }
547     fIsValid = that.fIsValid;
548     return *this;
549 }
550 
getVkImageInfo(GrVkImageInfo * outInfo) const551 bool GrBackendRenderTarget::getVkImageInfo(GrVkImageInfo* outInfo) const {
552 #ifdef SK_VULKAN
553     if (this->isValid() && GrBackendApi::kVulkan == fBackend) {
554         *outInfo = fVkInfo.snapImageInfo();
555         return true;
556     }
557 #endif
558     return false;
559 }
560 
setVkImageLayout(VkImageLayout layout)561 void GrBackendRenderTarget::setVkImageLayout(VkImageLayout layout) {
562 #ifdef SK_VULKAN
563     if (this->isValid() && GrBackendApi::kVulkan == fBackend) {
564         fVkInfo.setImageLayout(layout);
565     }
566 #endif
567 }
568 
getGrVkImageLayout() const569 sk_sp<GrVkImageLayout> GrBackendRenderTarget::getGrVkImageLayout() const {
570 #ifdef SK_VULKAN
571     if (this->isValid() && GrBackendApi::kVulkan == fBackend) {
572         return fVkInfo.getGrVkImageLayout();
573     }
574 #endif
575     return nullptr;
576 }
577 
578 #ifdef SK_METAL
getMtlTextureInfo(GrMtlTextureInfo * outInfo) const579 bool GrBackendRenderTarget::getMtlTextureInfo(GrMtlTextureInfo* outInfo) const {
580     if (this->isValid() && GrBackendApi::kMetal == fBackend) {
581         *outInfo = fMtlInfo;
582         return true;
583     }
584     return false;
585 }
586 #endif
587 
getGLFramebufferInfo(GrGLFramebufferInfo * outInfo) const588 bool GrBackendRenderTarget::getGLFramebufferInfo(GrGLFramebufferInfo* outInfo) const {
589     if (this->isValid() && GrBackendApi::kOpenGL == fBackend) {
590         *outInfo = fGLInfo;
591         return true;
592     }
593     return false;
594 }
595 
getMockRenderTargetInfo(GrMockRenderTargetInfo * outInfo) const596 bool GrBackendRenderTarget::getMockRenderTargetInfo(GrMockRenderTargetInfo* outInfo) const {
597     if (this->isValid() && GrBackendApi::kMock == fBackend) {
598         *outInfo = fMockInfo;
599         return true;
600     }
601     return false;
602 }
603 
604 #if GR_TEST_UTILS
TestingOnly_Equals(const GrBackendRenderTarget & r0,const GrBackendRenderTarget & r1)605 bool GrBackendRenderTarget::TestingOnly_Equals(const GrBackendRenderTarget& r0,
606                                                const GrBackendRenderTarget& r1) {
607     if (!r0.isValid() || !r1.isValid()) {
608         return false; // two invalid backend rendertargets are not considered equal
609     }
610 
611     if (r0.fWidth != r1.fWidth ||
612         r0.fHeight != r1.fHeight ||
613         r0.fSampleCnt != r1.fSampleCnt ||
614         r0.fStencilBits != r1.fStencilBits ||
615         r0.fConfig != r1.fConfig ||
616         r0.fBackend != r1.fBackend) {
617         return false;
618     }
619 
620     switch (r0.fBackend) {
621     case GrBackendApi::kOpenGL:
622         return r0.fGLInfo == r1.fGLInfo;
623     case GrBackendApi::kMock:
624         return r0.fMockInfo == r1.fMockInfo;
625     case GrBackendApi::kVulkan:
626 #ifdef SK_VULKAN
627         return r0.fVkInfo == r1.fVkInfo;
628 #else
629         // fall through
630 #endif
631     case GrBackendApi::kMetal:
632 #ifdef SK_METAL
633         return r0.fMtlInfo == r1.fMtlInfo;
634 #else
635         // fall through
636 #endif
637     default:
638         return false;
639     }
640 
641     SkASSERT(0);
642     return false;
643 }
644 #endif
645