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     if (fVk.fYcbcrConversionInfo.isValid()) {
85         fTextureType = GrTextureType::kExternal;
86     }
87 }
88 
getVkFormat() const89 const VkFormat* GrBackendFormat::getVkFormat() const {
90     if (this->isValid() && GrBackendApi::kVulkan == fBackend) {
91         return &fVk.fFormat;
92     }
93     return nullptr;
94 }
95 
getVkYcbcrConversionInfo() const96 const GrVkYcbcrConversionInfo* GrBackendFormat::getVkYcbcrConversionInfo() const {
97     if (this->isValid() && GrBackendApi::kVulkan == fBackend) {
98         return &fVk.fYcbcrConversionInfo;
99     }
100     return nullptr;
101 }
102 
103 #ifdef SK_METAL
GrBackendFormat(GrMTLPixelFormat mtlFormat)104 GrBackendFormat::GrBackendFormat(GrMTLPixelFormat mtlFormat)
105         : fBackend(GrBackendApi::kMetal)
106         , fValid(true)
107         , fMtlFormat(mtlFormat)
108         , fTextureType(GrTextureType::k2D) {
109 }
110 
getMtlFormat() const111 const GrMTLPixelFormat* GrBackendFormat::getMtlFormat() const {
112     if (this->isValid() && GrBackendApi::kMetal == fBackend) {
113         return &fMtlFormat;
114     }
115     return nullptr;
116 }
117 #endif
118 
GrBackendFormat(GrPixelConfig config)119 GrBackendFormat::GrBackendFormat(GrPixelConfig config)
120         : fBackend(GrBackendApi::kMock)
121         , fValid(true)
122         , fMockFormat(config)
123         , fTextureType(GrTextureType::k2D) {
124 }
125 
getMockFormat() const126 const GrPixelConfig* GrBackendFormat::getMockFormat() const {
127     if (this->isValid() && GrBackendApi::kMock == fBackend) {
128         return &fMockFormat;
129     }
130     return nullptr;
131 }
132 
makeTexture2D() const133 GrBackendFormat GrBackendFormat::makeTexture2D() const {
134     GrBackendFormat copy = *this;
135     if (const GrVkYcbcrConversionInfo* ycbcrInfo = this->getVkYcbcrConversionInfo()) {
136         if (ycbcrInfo->isValid()) {
137             // If we have a ycbcr we remove it from the backend format and set the VkFormat to
138             // R8G8B8A8_UNORM
139             SkASSERT(copy.fBackend == GrBackendApi::kVulkan);
140             copy.fVk.fYcbcrConversionInfo = GrVkYcbcrConversionInfo();
141             copy.fVk.fFormat = VK_FORMAT_R8G8B8A8_UNORM;
142         }
143     }
144     copy.fTextureType = GrTextureType::k2D;
145     return copy;
146 }
147 
operator ==(const GrBackendFormat & that) const148 bool GrBackendFormat::operator==(const GrBackendFormat& that) const {
149     // Invalid GrBackendFormats are never equal to anything.
150     if (!fValid || !that.fValid) {
151         return false;
152     }
153 
154     if (fBackend != that.fBackend) {
155         return false;
156     }
157 
158     switch (fBackend) {
159         case GrBackendApi::kOpenGL:
160             return fGLFormat == that.fGLFormat;
161         case GrBackendApi::kVulkan:
162 #ifdef SK_VULKAN
163             return fVk.fFormat == that.fVk.fFormat &&
164                    fVk.fYcbcrConversionInfo == that.fVk.fYcbcrConversionInfo;
165 #endif
166             break;
167 #ifdef SK_METAL
168         case GrBackendApi::kMetal:
169             return fMtlFormat == that.fMtlFormat;
170 #endif
171             break;
172         case GrBackendApi::kMock:
173             return fMockFormat == that.fMockFormat;
174         default:
175             SK_ABORT("Unknown GrBackend");
176     }
177     return false;
178 }
179 
GrBackendTexture(int width,int height,const GrVkImageInfo & vkInfo)180 GrBackendTexture::GrBackendTexture(int width,
181                                    int height,
182                                    const GrVkImageInfo& vkInfo)
183 #ifdef SK_VULKAN
184         : GrBackendTexture(width, height, vkInfo,
185                            sk_sp<GrVkImageLayout>(new GrVkImageLayout(vkInfo.fImageLayout))) {}
186 #else
187         : fIsValid(false) {}
188 #endif
189 
190 #ifdef SK_VULKAN
GrBackendTexture(int width,int height,const GrVkImageInfo & vkInfo,sk_sp<GrVkImageLayout> layout)191 GrBackendTexture::GrBackendTexture(int width,
192                                    int height,
193                                    const GrVkImageInfo& vkInfo,
194                                    sk_sp<GrVkImageLayout> layout)
195         : fIsValid(true)
196         , fWidth(width)
197         , fHeight(height)
198         , fConfig(kUnknown_GrPixelConfig)
199         , fMipMapped(GrMipMapped(vkInfo.fLevelCount > 1))
200         , fBackend(GrBackendApi::kVulkan)
201         , fVkInfo(vkInfo, layout.release()) {
202 }
203 #endif
204 
205 #ifdef SK_METAL
GrBackendTexture(int width,int height,GrMipMapped mipMapped,const GrMtlTextureInfo & mtlInfo)206 GrBackendTexture::GrBackendTexture(int width,
207                                    int height,
208                                    GrMipMapped mipMapped,
209                                    const GrMtlTextureInfo& mtlInfo)
210         : fIsValid(true)
211         , fWidth(width)
212         , fHeight(height)
213         , fConfig(GrPixelConfig::kUnknown_GrPixelConfig)
214         , fMipMapped(mipMapped)
215         , fBackend(GrBackendApi::kMetal)
216         , fMtlInfo(mtlInfo) {}
217 #endif
218 
GrBackendTexture(int width,int height,GrMipMapped mipMapped,const GrGLTextureInfo & glInfo)219 GrBackendTexture::GrBackendTexture(int width,
220                                    int height,
221                                    GrMipMapped mipMapped,
222                                    const GrGLTextureInfo& glInfo)
223         : fIsValid(true)
224         , fWidth(width)
225         , fHeight(height)
226         , fConfig(kUnknown_GrPixelConfig)
227         , fMipMapped(mipMapped)
228         , fBackend(GrBackendApi::kOpenGL)
229         , fGLInfo(glInfo) {}
230 
GrBackendTexture(int width,int height,GrMipMapped mipMapped,const GrMockTextureInfo & mockInfo)231 GrBackendTexture::GrBackendTexture(int width,
232                                    int height,
233                                    GrMipMapped mipMapped,
234                                    const GrMockTextureInfo& mockInfo)
235         : fIsValid(true)
236         , fWidth(width)
237         , fHeight(height)
238         , fConfig(mockInfo.fConfig)
239         , fMipMapped(mipMapped)
240         , fBackend(GrBackendApi::kMock)
241         , fMockInfo(mockInfo) {}
242 
~GrBackendTexture()243 GrBackendTexture::~GrBackendTexture() {
244     this->cleanup();
245 }
246 
cleanup()247 void GrBackendTexture::cleanup() {
248 #ifdef SK_VULKAN
249     if (this->isValid() && GrBackendApi::kVulkan == fBackend) {
250         fVkInfo.cleanup();
251     }
252 #endif
253 }
254 
GrBackendTexture(const GrBackendTexture & that)255 GrBackendTexture::GrBackendTexture(const GrBackendTexture& that) : fIsValid(false) {
256     *this = that;
257 }
258 
operator =(const GrBackendTexture & that)259 GrBackendTexture& GrBackendTexture::operator=(const GrBackendTexture& that) {
260     if (!that.isValid()) {
261         this->cleanup();
262         fIsValid = false;
263         return *this;
264     }
265     fWidth = that.fWidth;
266     fHeight = that.fHeight;
267     fConfig = that.fConfig;
268     fMipMapped = that.fMipMapped;
269     fBackend = that.fBackend;
270 
271     switch (that.fBackend) {
272         case GrBackendApi::kOpenGL:
273             fGLInfo = that.fGLInfo;
274             break;
275         case GrBackendApi::kVulkan:
276 #ifdef SK_VULKAN
277             fVkInfo.assign(that.fVkInfo, this->isValid());
278 #endif
279             break;
280 #ifdef SK_METAL
281         case GrBackendApi::kMetal:
282             fMtlInfo = that.fMtlInfo;
283             break;
284 #endif
285         case GrBackendApi::kMock:
286             fMockInfo = that.fMockInfo;
287             break;
288         default:
289             SK_ABORT("Unknown GrBackend");
290     }
291     fIsValid = that.fIsValid;
292     return *this;
293 }
294 
getVkImageInfo(GrVkImageInfo * outInfo) const295 bool GrBackendTexture::getVkImageInfo(GrVkImageInfo* outInfo) const {
296 #ifdef SK_VULKAN
297     if (this->isValid() && GrBackendApi::kVulkan == fBackend) {
298         *outInfo = fVkInfo.snapImageInfo();
299         return true;
300     }
301 #endif
302     return false;
303 }
304 
setVkImageLayout(VkImageLayout layout)305 void GrBackendTexture::setVkImageLayout(VkImageLayout layout) {
306 #ifdef SK_VULKAN
307     if (this->isValid() && GrBackendApi::kVulkan == fBackend) {
308         fVkInfo.setImageLayout(layout);
309     }
310 #endif
311 }
312 
313 // We need a stubbed version of GrVkImageLayout for non vulkan builds
314 #ifndef SK_VULKAN
315 class GrVkImageLayout : public SkRefCnt {
GrVkImageLayout(VkImageLayout layout)316     GrVkImageLayout(VkImageLayout layout) {}
317 };
318 #endif
319 
getGrVkImageLayout() const320 sk_sp<GrVkImageLayout> GrBackendTexture::getGrVkImageLayout() const {
321 #ifdef SK_VULKAN
322     if (this->isValid() && GrBackendApi::kVulkan == fBackend) {
323         return fVkInfo.getGrVkImageLayout();
324     }
325 #endif
326     return nullptr;
327 }
328 
329 #ifdef SK_METAL
getMtlTextureInfo(GrMtlTextureInfo * outInfo) const330 bool GrBackendTexture::getMtlTextureInfo(GrMtlTextureInfo* outInfo) const {
331     if (this->isValid() && GrBackendApi::kMetal == fBackend) {
332         *outInfo = fMtlInfo;
333         return true;
334     }
335     return false;
336 }
337 #endif
338 
getGLTextureInfo(GrGLTextureInfo * outInfo) const339 bool GrBackendTexture::getGLTextureInfo(GrGLTextureInfo* outInfo) const {
340     if (this->isValid() && GrBackendApi::kOpenGL == fBackend) {
341         *outInfo = fGLInfo;
342         return true;
343     }
344     return false;
345 }
346 
getMockTextureInfo(GrMockTextureInfo * outInfo) const347 bool GrBackendTexture::getMockTextureInfo(GrMockTextureInfo* outInfo) const {
348     if (this->isValid() && GrBackendApi::kMock == fBackend) {
349         *outInfo = fMockInfo;
350         return true;
351     }
352     return false;
353 }
354 
getBackendFormat() const355 GrBackendFormat GrBackendTexture::getBackendFormat() const {
356     if (!this->isValid()) {
357         return GrBackendFormat();
358     }
359     switch (fBackend) {
360         case GrBackendApi::kOpenGL:
361             return GrBackendFormat::MakeGL(fGLInfo.fFormat, fGLInfo.fTarget);
362 #ifdef SK_VULKAN
363         case GrBackendApi::kVulkan: {
364             auto info = fVkInfo.snapImageInfo();
365             if (info.fYcbcrConversionInfo.isValid()) {
366                 SkASSERT(info.fFormat == VK_FORMAT_UNDEFINED);
367                 return GrBackendFormat::MakeVk(info.fYcbcrConversionInfo);
368             }
369             return GrBackendFormat::MakeVk(info.fFormat);
370         }
371 #endif
372 #ifdef SK_METAL
373         case GrBackendApi::kMetal: {
374             GrMtlTextureInfo mtlInfo;
375             SkAssertResult(this->getMtlTextureInfo(&mtlInfo));
376             return GrBackendFormat::MakeMtl(GrGetMTLPixelFormatFromMtlTextureInfo(mtlInfo));
377         }
378 #endif
379         case GrBackendApi::kMock:
380             return GrBackendFormat::MakeMock(fMockInfo.fConfig);
381         default:
382             return GrBackendFormat();
383     }
384 }
385 
386 #if GR_TEST_UTILS
TestingOnly_Equals(const GrBackendTexture & t0,const GrBackendTexture & t1)387 bool GrBackendTexture::TestingOnly_Equals(const GrBackendTexture& t0, const GrBackendTexture& t1) {
388     if (!t0.isValid() || !t1.isValid()) {
389         return false; // two invalid backend textures are not considered equal
390     }
391 
392     if (t0.fWidth != t1.fWidth ||
393         t0.fHeight != t1.fHeight ||
394         t0.fConfig != t1.fConfig ||
395         t0.fMipMapped != t1.fMipMapped ||
396         t0.fBackend != t1.fBackend) {
397         return false;
398     }
399 
400     switch (t0.fBackend) {
401     case GrBackendApi::kOpenGL:
402         return t0.fGLInfo == t1.fGLInfo;
403     case GrBackendApi::kMock:
404         return t0.fMockInfo == t1.fMockInfo;
405     case GrBackendApi::kVulkan:
406 #ifdef SK_VULKAN
407         return t0.fVkInfo == t1.fVkInfo;
408 #else
409         // fall through
410 #endif
411     case GrBackendApi::kMetal:
412 #ifdef SK_METAL
413         return t0.fMtlInfo == t1.fMtlInfo;
414 #else
415         // fall through
416 #endif
417     default:
418         return false;
419     }
420 
421     SkASSERT(0);
422     return false;
423 }
424 #endif
425 
426 ////////////////////////////////////////////////////////////////////////////////////////////////////
427 
GrBackendRenderTarget(int width,int height,int sampleCnt,int stencilBits,const GrVkImageInfo & vkInfo)428 GrBackendRenderTarget::GrBackendRenderTarget(int width,
429                                              int height,
430                                              int sampleCnt,
431                                              int stencilBits,
432                                              const GrVkImageInfo& vkInfo)
433         : GrBackendRenderTarget(width, height, sampleCnt, vkInfo) {
434     // This is a deprecated constructor that takes a bogus stencil bits.
435     SkASSERT(0 == stencilBits);
436 }
437 
GrBackendRenderTarget(int width,int height,int sampleCnt,const GrVkImageInfo & vkInfo)438 GrBackendRenderTarget::GrBackendRenderTarget(int width,
439                                              int height,
440                                              int sampleCnt,
441                                              const GrVkImageInfo& vkInfo)
442 #ifdef SK_VULKAN
443         : GrBackendRenderTarget(width, height, sampleCnt, vkInfo,
444                                 sk_sp<GrVkImageLayout>(new GrVkImageLayout(vkInfo.fImageLayout))) {}
445 #else
446         : fIsValid(false) {}
447 #endif
448 
449 #ifdef SK_VULKAN
GrBackendRenderTarget(int width,int height,int sampleCnt,const GrVkImageInfo & vkInfo,sk_sp<GrVkImageLayout> layout)450 GrBackendRenderTarget::GrBackendRenderTarget(int width,
451                                              int height,
452                                              int sampleCnt,
453                                              const GrVkImageInfo& vkInfo,
454                                              sk_sp<GrVkImageLayout> layout)
455         : fIsValid(true)
456         , fWidth(width)
457         , fHeight(height)
458         , fSampleCnt(SkTMax(1, sampleCnt))
459         , fStencilBits(0)  // We always create stencil buffers internally for vulkan
460         , fConfig(kUnknown_GrPixelConfig)
461         , fBackend(GrBackendApi::kVulkan)
462         , fVkInfo(vkInfo, layout.release()) {}
463 #endif
464 
465 #ifdef SK_METAL
GrBackendRenderTarget(int width,int height,int sampleCnt,const GrMtlTextureInfo & mtlInfo)466 GrBackendRenderTarget::GrBackendRenderTarget(int width,
467                                              int height,
468                                              int sampleCnt,
469                                              const GrMtlTextureInfo& mtlInfo)
470         : fIsValid(true)
471         , fWidth(width)
472         , fHeight(height)
473         , fSampleCnt(SkTMax(1, sampleCnt))
474         , fStencilBits(0)
475         , fConfig(GrPixelConfig::kUnknown_GrPixelConfig)
476         , fBackend(GrBackendApi::kMetal)
477         , fMtlInfo(mtlInfo) {}
478 #endif
479 
GrBackendRenderTarget(int width,int height,int sampleCnt,int stencilBits,const GrGLFramebufferInfo & glInfo)480 GrBackendRenderTarget::GrBackendRenderTarget(int width,
481                                              int height,
482                                              int sampleCnt,
483                                              int stencilBits,
484                                              const GrGLFramebufferInfo& glInfo)
485         : fWidth(width)
486         , fHeight(height)
487         , fSampleCnt(SkTMax(1, sampleCnt))
488         , fStencilBits(stencilBits)
489         , fConfig(kUnknown_GrPixelConfig)
490         , fBackend(GrBackendApi::kOpenGL)
491         , fGLInfo(glInfo) {
492     fIsValid = SkToBool(glInfo.fFormat); // the glInfo must have a valid format
493 }
494 
GrBackendRenderTarget(int width,int height,int sampleCnt,int stencilBits,const GrMockRenderTargetInfo & mockInfo)495 GrBackendRenderTarget::GrBackendRenderTarget(int width,
496                                              int height,
497                                              int sampleCnt,
498                                              int stencilBits,
499                                              const GrMockRenderTargetInfo& mockInfo)
500         : fIsValid(true)
501         , fWidth(width)
502         , fHeight(height)
503         , fSampleCnt(SkTMax(1, sampleCnt))
504         , fStencilBits(stencilBits)
505         , fConfig(mockInfo.fConfig)
506         , fMockInfo(mockInfo) {}
507 
~GrBackendRenderTarget()508 GrBackendRenderTarget::~GrBackendRenderTarget() {
509     this->cleanup();
510 }
511 
cleanup()512 void GrBackendRenderTarget::cleanup() {
513 #ifdef SK_VULKAN
514     if (this->isValid() && GrBackendApi::kVulkan == fBackend) {
515         fVkInfo.cleanup();
516     }
517 #endif
518 }
519 
GrBackendRenderTarget(const GrBackendRenderTarget & that)520 GrBackendRenderTarget::GrBackendRenderTarget(const GrBackendRenderTarget& that) : fIsValid(false) {
521     *this = that;
522 }
523 
operator =(const GrBackendRenderTarget & that)524 GrBackendRenderTarget& GrBackendRenderTarget::operator=(const GrBackendRenderTarget& that) {
525     if (!that.isValid()) {
526         this->cleanup();
527         fIsValid = false;
528         return *this;
529     }
530     fWidth = that.fWidth;
531     fHeight = that.fHeight;
532     fSampleCnt = that.fSampleCnt;
533     fStencilBits = that.fStencilBits;
534     fConfig = that.fConfig;
535     fBackend = that.fBackend;
536 
537     switch (that.fBackend) {
538         case GrBackendApi::kOpenGL:
539             fGLInfo = that.fGLInfo;
540             break;
541         case GrBackendApi::kVulkan:
542 #ifdef SK_VULKAN
543             fVkInfo.assign(that.fVkInfo, this->isValid());
544 #endif
545             break;
546 #ifdef SK_METAL
547         case GrBackendApi::kMetal:
548             fMtlInfo = that.fMtlInfo;
549             break;
550 #endif
551         case GrBackendApi::kMock:
552             fMockInfo = that.fMockInfo;
553             break;
554         default:
555             SK_ABORT("Unknown GrBackend");
556     }
557     fIsValid = that.fIsValid;
558     return *this;
559 }
560 
getVkImageInfo(GrVkImageInfo * outInfo) const561 bool GrBackendRenderTarget::getVkImageInfo(GrVkImageInfo* outInfo) const {
562 #ifdef SK_VULKAN
563     if (this->isValid() && GrBackendApi::kVulkan == fBackend) {
564         *outInfo = fVkInfo.snapImageInfo();
565         return true;
566     }
567 #endif
568     return false;
569 }
570 
setVkImageLayout(VkImageLayout layout)571 void GrBackendRenderTarget::setVkImageLayout(VkImageLayout layout) {
572 #ifdef SK_VULKAN
573     if (this->isValid() && GrBackendApi::kVulkan == fBackend) {
574         fVkInfo.setImageLayout(layout);
575     }
576 #endif
577 }
578 
getGrVkImageLayout() const579 sk_sp<GrVkImageLayout> GrBackendRenderTarget::getGrVkImageLayout() const {
580 #ifdef SK_VULKAN
581     if (this->isValid() && GrBackendApi::kVulkan == fBackend) {
582         return fVkInfo.getGrVkImageLayout();
583     }
584 #endif
585     return nullptr;
586 }
587 
588 #ifdef SK_METAL
getMtlTextureInfo(GrMtlTextureInfo * outInfo) const589 bool GrBackendRenderTarget::getMtlTextureInfo(GrMtlTextureInfo* outInfo) const {
590     if (this->isValid() && GrBackendApi::kMetal == fBackend) {
591         *outInfo = fMtlInfo;
592         return true;
593     }
594     return false;
595 }
596 #endif
597 
getGLFramebufferInfo(GrGLFramebufferInfo * outInfo) const598 bool GrBackendRenderTarget::getGLFramebufferInfo(GrGLFramebufferInfo* outInfo) const {
599     if (this->isValid() && GrBackendApi::kOpenGL == fBackend) {
600         *outInfo = fGLInfo;
601         return true;
602     }
603     return false;
604 }
605 
getMockRenderTargetInfo(GrMockRenderTargetInfo * outInfo) const606 bool GrBackendRenderTarget::getMockRenderTargetInfo(GrMockRenderTargetInfo* outInfo) const {
607     if (this->isValid() && GrBackendApi::kMock == fBackend) {
608         *outInfo = fMockInfo;
609         return true;
610     }
611     return false;
612 }
613 
614 #if GR_TEST_UTILS
TestingOnly_Equals(const GrBackendRenderTarget & r0,const GrBackendRenderTarget & r1)615 bool GrBackendRenderTarget::TestingOnly_Equals(const GrBackendRenderTarget& r0,
616                                                const GrBackendRenderTarget& r1) {
617     if (!r0.isValid() || !r1.isValid()) {
618         return false; // two invalid backend rendertargets are not considered equal
619     }
620 
621     if (r0.fWidth != r1.fWidth ||
622         r0.fHeight != r1.fHeight ||
623         r0.fSampleCnt != r1.fSampleCnt ||
624         r0.fStencilBits != r1.fStencilBits ||
625         r0.fConfig != r1.fConfig ||
626         r0.fBackend != r1.fBackend) {
627         return false;
628     }
629 
630     switch (r0.fBackend) {
631     case GrBackendApi::kOpenGL:
632         return r0.fGLInfo == r1.fGLInfo;
633     case GrBackendApi::kMock:
634         return r0.fMockInfo == r1.fMockInfo;
635     case GrBackendApi::kVulkan:
636 #ifdef SK_VULKAN
637         return r0.fVkInfo == r1.fVkInfo;
638 #else
639         // fall through
640 #endif
641     case GrBackendApi::kMetal:
642 #ifdef SK_METAL
643         return r0.fMtlInfo == r1.fMtlInfo;
644 #else
645         // fall through
646 #endif
647     default:
648         return false;
649     }
650 
651     SkASSERT(0);
652     return false;
653 }
654 #endif
655