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