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