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 #include "include/gpu/GrBackendSurface.h"
9 
10 #include "src/gpu/GrBackendSurfaceMutableStateImpl.h"
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 #ifdef SK_DIRECT3D
28 #include "include/gpu/d3d/GrD3DTypes.h"
29 #include "src/gpu/d3d/GrD3DResourceState.h"
30 #include "src/gpu/d3d/GrD3DUtil.h"
31 #endif
32 
GrBackendFormat(const GrBackendFormat & that)33 GrBackendFormat::GrBackendFormat(const GrBackendFormat& that)
34         : fBackend(that.fBackend)
35         , fValid(that.fValid)
36         , fTextureType(that.fTextureType) {
37     if (!fValid) {
38         return;
39     }
40 
41     switch (fBackend) {
42 #ifdef SK_GL
43         case GrBackendApi::kOpenGL:
44             fGLFormat = that.fGLFormat;
45             break;
46 #endif
47 #ifdef SK_VULKAN
48         case GrBackendApi::kVulkan:
49             fVk = that.fVk;
50             break;
51 #endif
52 #ifdef SK_METAL
53         case GrBackendApi::kMetal:
54             fMtlFormat = that.fMtlFormat;
55             break;
56 #endif
57 #ifdef SK_DIRECT3D
58         case GrBackendApi::kDirect3D:
59             fDxgiFormat = that.fDxgiFormat;
60             break;
61 #endif
62 #ifdef SK_DAWN
63         case GrBackendApi::kDawn:
64             fDawnFormat = that.fDawnFormat;
65             break;
66 #endif
67         case GrBackendApi::kMock:
68             fMock = that.fMock;
69             break;
70         default:
71             SK_ABORT("Unknown GrBackend");
72     }
73 }
74 
operator =(const GrBackendFormat & that)75 GrBackendFormat& GrBackendFormat::operator=(const GrBackendFormat& that) {
76     if (this != &that) {
77         this->~GrBackendFormat();
78         new (this) GrBackendFormat(that);
79     }
80     return *this;
81 }
82 
83 #ifdef SK_GL
GrBackendFormat(GrGLenum format,GrGLenum target)84 GrBackendFormat::GrBackendFormat(GrGLenum format, GrGLenum target)
85         : fBackend(GrBackendApi::kOpenGL)
86         , fValid(true)
87         , fGLFormat(format) {
88     switch (target) {
89         case GR_GL_TEXTURE_NONE:
90             fTextureType = GrTextureType::kNone;
91             break;
92         case GR_GL_TEXTURE_2D:
93             fTextureType = GrTextureType::k2D;
94             break;
95         case GR_GL_TEXTURE_RECTANGLE:
96             fTextureType = GrTextureType::kRectangle;
97             break;
98         case GR_GL_TEXTURE_EXTERNAL:
99             fTextureType = GrTextureType::kExternal;
100             break;
101         default:
102             SK_ABORT("Unexpected texture target");
103     }
104 }
105 #endif
106 
asGLFormat() const107 GrGLFormat GrBackendFormat::asGLFormat() const {
108     if (this->isValid() && GrBackendApi::kOpenGL == fBackend) {
109         return GrGLFormatFromGLEnum(fGLFormat);
110     }
111     return GrGLFormat::kUnknown;
112 }
113 
MakeVk(const GrVkYcbcrConversionInfo & ycbcrInfo)114 GrBackendFormat GrBackendFormat::MakeVk(const GrVkYcbcrConversionInfo& ycbcrInfo) {
115     SkASSERT(ycbcrInfo.isValid());
116     return GrBackendFormat(ycbcrInfo.fFormat, ycbcrInfo);
117 }
118 
GrBackendFormat(VkFormat vkFormat,const GrVkYcbcrConversionInfo & ycbcrInfo)119 GrBackendFormat::GrBackendFormat(VkFormat vkFormat, const GrVkYcbcrConversionInfo& ycbcrInfo)
120         : fBackend(GrBackendApi::kVulkan)
121 #ifdef SK_VULKAN
122         , fValid(true)
123 #else
124         , fValid(false)
125 #endif
126         , fTextureType(GrTextureType::k2D) {
127     fVk.fFormat = vkFormat;
128     fVk.fYcbcrConversionInfo = ycbcrInfo;
129     if (fVk.fYcbcrConversionInfo.isValid() && fVk.fYcbcrConversionInfo.fExternalFormat) {
130         fTextureType = GrTextureType::kExternal;
131     }
132 }
133 
asVkFormat(VkFormat * format) const134 bool GrBackendFormat::asVkFormat(VkFormat* format) const {
135     SkASSERT(format);
136     if (this->isValid() && GrBackendApi::kVulkan == fBackend) {
137         *format = fVk.fFormat;
138         return true;
139     }
140     return false;
141 }
142 
getVkYcbcrConversionInfo() const143 const GrVkYcbcrConversionInfo* GrBackendFormat::getVkYcbcrConversionInfo() const {
144     if (this->isValid() && GrBackendApi::kVulkan == fBackend) {
145         return &fVk.fYcbcrConversionInfo;
146     }
147     return nullptr;
148 }
149 
150 #ifdef SK_DAWN
GrBackendFormat(wgpu::TextureFormat format)151 GrBackendFormat::GrBackendFormat(wgpu::TextureFormat format)
152         : fBackend(GrBackendApi::kDawn)
153         , fValid(true)
154         , fDawnFormat(format)
155         , fTextureType(GrTextureType::k2D) {
156 }
157 
asDawnFormat(wgpu::TextureFormat * format) const158 bool GrBackendFormat::asDawnFormat(wgpu::TextureFormat* format) const {
159     SkASSERT(format);
160     if (this->isValid() && GrBackendApi::kDawn == fBackend) {
161         *format = fDawnFormat;
162         return true;
163     }
164     return false;
165 }
166 #endif
167 
168 #ifdef SK_METAL
GrBackendFormat(GrMTLPixelFormat mtlFormat)169 GrBackendFormat::GrBackendFormat(GrMTLPixelFormat mtlFormat)
170         : fBackend(GrBackendApi::kMetal)
171         , fValid(true)
172         , fMtlFormat(mtlFormat)
173         , fTextureType(GrTextureType::k2D) {
174 }
175 
asMtlFormat() const176 GrMTLPixelFormat GrBackendFormat::asMtlFormat() const {
177     if (this->isValid() && GrBackendApi::kMetal == fBackend) {
178         return fMtlFormat;
179     }
180     // MTLPixelFormatInvalid == 0
181     return GrMTLPixelFormat(0);
182 }
183 #endif
184 
185 #ifdef SK_DIRECT3D
GrBackendFormat(DXGI_FORMAT dxgiFormat)186 GrBackendFormat::GrBackendFormat(DXGI_FORMAT dxgiFormat)
187     : fBackend(GrBackendApi::kDirect3D)
188     , fValid(true)
189     , fDxgiFormat(dxgiFormat)
190     , fTextureType(GrTextureType::k2D) {
191 }
192 
asDxgiFormat(DXGI_FORMAT * dxgiFormat) const193 bool GrBackendFormat::asDxgiFormat(DXGI_FORMAT* dxgiFormat) const {
194     if (this->isValid() && GrBackendApi::kDirect3D == fBackend) {
195         *dxgiFormat = fDxgiFormat;
196         return true;
197     }
198     return false;
199 }
200 #endif
201 
GrBackendFormat(GrColorType colorType,SkImage::CompressionType compression,bool isStencilFormat)202 GrBackendFormat::GrBackendFormat(GrColorType colorType, SkImage::CompressionType compression,
203                                  bool isStencilFormat)
204         : fBackend(GrBackendApi::kMock)
205         , fValid(true)
206         , fTextureType(GrTextureType::k2D) {
207     fMock.fColorType = colorType;
208     fMock.fCompressionType = compression;
209     fMock.fIsStencilFormat = isStencilFormat;
210     SkASSERT(this->validateMock());
211 }
212 
channelMask() const213 uint32_t GrBackendFormat::channelMask() const {
214     if (!this->isValid()) {
215         return 0;
216     }
217     switch (fBackend) {
218 #ifdef SK_GL
219         case GrBackendApi::kOpenGL:
220             return GrGLFormatChannels(GrGLFormatFromGLEnum(fGLFormat));
221 #endif
222 #ifdef SK_VULKAN
223         case GrBackendApi::kVulkan:
224             return GrVkFormatChannels(fVk.fFormat);
225 #endif
226 #ifdef SK_METAL
227         case GrBackendApi::kMetal:
228             return GrMtlFormatChannels(fMtlFormat);
229 #endif
230 #ifdef SK_DAWN
231         case GrBackendApi::kDawn:
232             return GrDawnFormatChannels(fDawnFormat);
233 #endif
234 #ifdef SK_DIRECT3D
235         case GrBackendApi::kDirect3D:
236             return GrDxgiFormatChannels(fDxgiFormat);
237 #endif
238         case GrBackendApi::kMock:
239             return GrColorTypeChannelFlags(fMock.fColorType);
240 
241         default:
242             return 0;
243     }
244 }
245 
246 #ifdef SK_DEBUG
validateMock() const247 bool GrBackendFormat::validateMock() const {
248     int trueStates = 0;
249     if (fMock.fCompressionType != SkImage::CompressionType::kNone) {
250         trueStates++;
251     }
252     if (fMock.fColorType != GrColorType::kUnknown) {
253         trueStates++;
254     }
255     if (fMock.fIsStencilFormat) {
256         trueStates++;
257     }
258     return trueStates == 1;
259 }
260 #endif
261 
asMockColorType() const262 GrColorType GrBackendFormat::asMockColorType() const {
263     if (this->isValid() && GrBackendApi::kMock == fBackend) {
264         SkASSERT(this->validateMock());
265         return fMock.fColorType;
266     }
267 
268     return GrColorType::kUnknown;
269 }
270 
asMockCompressionType() const271 SkImage::CompressionType GrBackendFormat::asMockCompressionType() const {
272     if (this->isValid() && GrBackendApi::kMock == fBackend) {
273         SkASSERT(this->validateMock());
274         return fMock.fCompressionType;
275     }
276 
277     return SkImage::CompressionType::kNone;
278 }
279 
isMockStencilFormat() const280 bool GrBackendFormat::isMockStencilFormat() const {
281     if (this->isValid() && GrBackendApi::kMock == fBackend) {
282         SkASSERT(this->validateMock());
283         return fMock.fIsStencilFormat;
284     }
285 
286     return false;
287 }
288 
makeTexture2D() const289 GrBackendFormat GrBackendFormat::makeTexture2D() const {
290     GrBackendFormat copy = *this;
291     if (const GrVkYcbcrConversionInfo* ycbcrInfo = this->getVkYcbcrConversionInfo()) {
292         if (ycbcrInfo->isValid()) {
293             // If we have a ycbcr we remove it from the backend format and set the VkFormat to
294             // R8G8B8A8_UNORM
295             SkASSERT(copy.fBackend == GrBackendApi::kVulkan);
296             copy.fVk.fYcbcrConversionInfo = GrVkYcbcrConversionInfo();
297             copy.fVk.fFormat = VK_FORMAT_R8G8B8A8_UNORM;
298         }
299     }
300     copy.fTextureType = GrTextureType::k2D;
301     return copy;
302 }
303 
MakeMock(GrColorType colorType,SkImage::CompressionType compression,bool isStencilFormat)304 GrBackendFormat GrBackendFormat::MakeMock(GrColorType colorType,
305                                           SkImage::CompressionType compression,
306                                           bool isStencilFormat) {
307     return GrBackendFormat(colorType, compression, isStencilFormat);
308 }
309 
operator ==(const GrBackendFormat & that) const310 bool GrBackendFormat::operator==(const GrBackendFormat& that) const {
311     // Invalid GrBackendFormats are never equal to anything.
312     if (!fValid || !that.fValid) {
313         return false;
314     }
315 
316     if (fBackend != that.fBackend) {
317         return false;
318     }
319 
320     switch (fBackend) {
321 #ifdef SK_GL
322         case GrBackendApi::kOpenGL:
323             return fGLFormat == that.fGLFormat;
324             break;
325 #endif
326 #ifdef SK_VULKAN
327         case GrBackendApi::kVulkan:
328             return fVk.fFormat == that.fVk.fFormat &&
329                    fVk.fYcbcrConversionInfo == that.fVk.fYcbcrConversionInfo;
330             break;
331 #endif
332 #ifdef SK_METAL
333         case GrBackendApi::kMetal:
334             return fMtlFormat == that.fMtlFormat;
335             break;
336 #endif
337 #ifdef SK_DAWN
338         case GrBackendApi::kDawn:
339             return fDawnFormat == that.fDawnFormat;
340             break;
341 #endif
342         case GrBackendApi::kMock:
343             return fMock.fColorType == that.fMock.fColorType &&
344                    fMock.fCompressionType == that.fMock.fCompressionType;
345 #ifdef SK_DIRECT3D
346         case GrBackendApi::kDirect3D:
347             return fDxgiFormat == that.fDxgiFormat;
348 #endif
349         default:
350             SK_ABORT("Unknown GrBackend");
351     }
352     return false;
353 }
354 
355 #if defined(SK_DEBUG) || GR_TEST_UTILS
356 #include "include/core/SkString.h"
357 
358 #ifdef SK_GL
359 #include "src/gpu/gl/GrGLUtil.h"
360 #endif
361 #ifdef SK_VULKAN
362 #include "src/gpu/vk/GrVkUtil.h"
363 #endif
364 
toStr() const365 SkString GrBackendFormat::toStr() const {
366     SkString str;
367 
368     if (!fValid) {
369         str.append("invalid");
370         return str;
371     }
372 
373     str.appendf("%s-", GrBackendApiToStr(fBackend));
374 
375     switch (fBackend) {
376         case GrBackendApi::kOpenGL:
377 #ifdef SK_GL
378             str.append(GrGLFormatToStr(fGLFormat));
379 #endif
380             break;
381         case GrBackendApi::kVulkan:
382 #ifdef SK_VULKAN
383             str.append(GrVkFormatToStr(fVk.fFormat));
384 #endif
385             break;
386         case GrBackendApi::kMetal:
387 #ifdef SK_METAL
388             str.append(GrMtlFormatToStr(fMtlFormat));
389 #endif
390             break;
391         case GrBackendApi::kDirect3D:
392 #ifdef SK_DIRECT3D
393             str.append(GrDxgiFormatToStr(fDxgiFormat));
394 #endif
395             break;
396         case GrBackendApi::kDawn:
397 #ifdef SK_DAWN
398             str.append(GrDawnFormatToStr(fDawnFormat));
399 #endif
400             break;
401         case GrBackendApi::kMock:
402             str.append(GrColorTypeToStr(fMock.fColorType));
403             str.appendf("-");
404             str.append(GrCompressionTypeToStr(fMock.fCompressionType));
405             break;
406     }
407 
408     return str;
409 }
410 #endif
411 
412 ///////////////////////////////////////////////////////////////////////////////////////////////////
GrBackendTexture()413 GrBackendTexture::GrBackendTexture() : fIsValid(false) {}
414 
415 #ifdef SK_DAWN
GrBackendTexture(int width,int height,const GrDawnTextureInfo & dawnInfo)416 GrBackendTexture::GrBackendTexture(int width,
417                                    int height,
418                                    const GrDawnTextureInfo& dawnInfo)
419         : fIsValid(true)
420         , fWidth(width)
421         , fHeight(height)
422         , fMipmapped(GrMipmapped(dawnInfo.fLevelCount > 1))
423         , fBackend(GrBackendApi::kDawn)
424         , fDawnInfo(dawnInfo) {}
425 #endif
426 
427 #ifdef SK_VULKAN
GrBackendTexture(int width,int height,const GrVkImageInfo & vkInfo)428 GrBackendTexture::GrBackendTexture(int width, int height, const GrVkImageInfo& vkInfo)
429         : GrBackendTexture(width, height, vkInfo,
430                            sk_sp<GrBackendSurfaceMutableStateImpl>(
431                                    new GrBackendSurfaceMutableStateImpl(
432                                         vkInfo.fImageLayout, vkInfo.fCurrentQueueFamily))) {}
433 
434 static const VkImageUsageFlags kDefaultUsageFlags =
435         VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
436 
437 // We don't know if the backend texture is made renderable or not, so we default the usage flags
438 // to include color attachment as well.
439 static const VkImageUsageFlags kDefaultTexRTUsageFlags =
440         kDefaultUsageFlags | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
441 
apply_default_usage_flags(const GrVkImageInfo & info,VkImageUsageFlags defaultFlags)442 static GrVkImageInfo apply_default_usage_flags(const GrVkImageInfo& info,
443                                                VkImageUsageFlags defaultFlags) {
444     if (info.fImageUsageFlags == 0) {
445         GrVkImageInfo newInfo = info;
446         newInfo.fImageUsageFlags = defaultFlags;
447         return newInfo;
448     }
449     return info;
450 }
451 
GrBackendTexture(int width,int height,const GrVkImageInfo & vkInfo,sk_sp<GrBackendSurfaceMutableStateImpl> mutableState)452 GrBackendTexture::GrBackendTexture(int width,
453                                    int height,
454                                    const GrVkImageInfo& vkInfo,
455                                    sk_sp<GrBackendSurfaceMutableStateImpl> mutableState)
456         : fIsValid(true)
457         , fWidth(width)
458         , fHeight(height)
459         , fMipmapped(GrMipmapped(vkInfo.fLevelCount > 1))
460         , fBackend(GrBackendApi::kVulkan)
461         , fVkInfo(apply_default_usage_flags(vkInfo, kDefaultTexRTUsageFlags))
462         , fMutableState(std::move(mutableState)) {}
463 #endif
464 
465 #ifdef SK_GL
GrBackendTexture(int width,int height,GrMipmapped mipmapped,const GrGLTextureInfo glInfo,sk_sp<GrGLTextureParameters> params)466 GrBackendTexture::GrBackendTexture(int width,
467                                    int height,
468                                    GrMipmapped mipmapped,
469                                    const GrGLTextureInfo glInfo,
470                                    sk_sp<GrGLTextureParameters> params)
471         : fIsValid(true)
472         , fWidth(width)
473         , fHeight(height)
474         , fMipmapped(mipmapped)
475         , fBackend(GrBackendApi::kOpenGL)
476         , fGLInfo(glInfo, params.release()) {}
477 
getGLTextureParams() const478 sk_sp<GrGLTextureParameters> GrBackendTexture::getGLTextureParams() const {
479     if (fBackend != GrBackendApi::kOpenGL) {
480         return nullptr;
481     }
482     return fGLInfo.refParameters();
483 }
484 #endif
485 
486 #ifdef SK_METAL
GrBackendTexture(int width,int height,GrMipmapped mipmapped,const GrMtlTextureInfo & mtlInfo)487 GrBackendTexture::GrBackendTexture(int width,
488                                    int height,
489                                    GrMipmapped mipmapped,
490                                    const GrMtlTextureInfo& mtlInfo)
491         : fIsValid(true)
492         , fWidth(width)
493         , fHeight(height)
494         , fMipmapped(mipmapped)
495         , fBackend(GrBackendApi::kMetal)
496         , fMtlInfo(mtlInfo) {}
497 #endif
498 
499 #ifdef SK_DIRECT3D
GrBackendTexture(int width,int height,const GrD3DTextureResourceInfo & d3dInfo)500 GrBackendTexture::GrBackendTexture(int width, int height, const GrD3DTextureResourceInfo& d3dInfo)
501         : GrBackendTexture(
502                 width, height, d3dInfo,
503                 sk_sp<GrD3DResourceState>(new GrD3DResourceState(
504                         static_cast<D3D12_RESOURCE_STATES>(d3dInfo.fResourceState)))) {}
505 
GrBackendTexture(int width,int height,const GrD3DTextureResourceInfo & d3dInfo,sk_sp<GrD3DResourceState> state)506 GrBackendTexture::GrBackendTexture(int width,
507                                    int height,
508                                    const GrD3DTextureResourceInfo& d3dInfo,
509                                    sk_sp<GrD3DResourceState> state)
510         : fIsValid(true)
511         , fWidth(width)
512         , fHeight(height)
513         , fMipmapped(GrMipmapped(d3dInfo.fLevelCount > 1))
514         , fBackend(GrBackendApi::kDirect3D)
515         , fD3DInfo(d3dInfo, state.release()) {}
516 #endif
517 
518 #ifdef SK_GL
GrBackendTexture(int width,int height,GrMipmapped mipmapped,const GrGLTextureInfo & glInfo)519 GrBackendTexture::GrBackendTexture(int width,
520                                    int height,
521                                    GrMipmapped mipmapped,
522                                    const GrGLTextureInfo& glInfo)
523         : GrBackendTexture(width, height, mipmapped, glInfo, sk_make_sp<GrGLTextureParameters>()) {
524     // Make no assumptions about client's texture's parameters.
525     this->glTextureParametersModified();
526 }
527 #endif
528 
GrBackendTexture(int width,int height,GrMipmapped mipmapped,const GrMockTextureInfo & mockInfo)529 GrBackendTexture::GrBackendTexture(int width,
530                                    int height,
531                                    GrMipmapped mipmapped,
532                                    const GrMockTextureInfo& mockInfo)
533         : fIsValid(true)
534         , fWidth(width)
535         , fHeight(height)
536         , fMipmapped(mipmapped)
537         , fBackend(GrBackendApi::kMock)
538         , fMockInfo(mockInfo) {}
539 
~GrBackendTexture()540 GrBackendTexture::~GrBackendTexture() {
541     this->cleanup();
542 }
543 
cleanup()544 void GrBackendTexture::cleanup() {
545 #ifdef SK_GL
546     if (this->isValid() && GrBackendApi::kOpenGL == fBackend) {
547         fGLInfo.cleanup();
548     }
549 #endif
550 #ifdef SK_VULKAN
551     if (this->isValid() && GrBackendApi::kVulkan == fBackend) {
552         fVkInfo.cleanup();
553     }
554 #endif
555 #ifdef SK_DIRECT3D
556     if (this->isValid() && GrBackendApi::kDirect3D == fBackend) {
557         fD3DInfo.cleanup();
558     }
559 #endif
560 }
561 
GrBackendTexture(const GrBackendTexture & that)562 GrBackendTexture::GrBackendTexture(const GrBackendTexture& that) : fIsValid(false) {
563     *this = that;
564 }
565 
operator =(const GrBackendTexture & that)566 GrBackendTexture& GrBackendTexture::operator=(const GrBackendTexture& that) {
567     if (!that.isValid()) {
568         this->cleanup();
569         fIsValid = false;
570         return *this;
571     } else if (fIsValid && this->fBackend != that.fBackend) {
572         this->cleanup();
573         fIsValid = false;
574     }
575     fWidth = that.fWidth;
576     fHeight = that.fHeight;
577     fMipmapped = that.fMipmapped;
578     fBackend = that.fBackend;
579 
580     switch (that.fBackend) {
581 #ifdef SK_GL
582         case GrBackendApi::kOpenGL:
583             fGLInfo.assign(that.fGLInfo, this->isValid());
584             break;
585 #endif
586 #ifdef SK_VULKAN
587         case GrBackendApi::kVulkan:
588             fVkInfo.assign(that.fVkInfo, this->isValid());
589             break;
590 #endif
591 #ifdef SK_METAL
592         case GrBackendApi::kMetal:
593             fMtlInfo = that.fMtlInfo;
594             break;
595 #endif
596 #ifdef SK_DIRECT3D
597         case GrBackendApi::kDirect3D:
598             fD3DInfo.assign(that.fD3DInfo, this->isValid());
599             break;
600 #endif
601 #ifdef SK_DAWN
602         case GrBackendApi::kDawn:
603             fDawnInfo = that.fDawnInfo;
604             break;
605 #endif
606         case GrBackendApi::kMock:
607             fMockInfo = that.fMockInfo;
608             break;
609         default:
610             SK_ABORT("Unknown GrBackend");
611     }
612     fMutableState = that.fMutableState;
613     fIsValid = true;
614     return *this;
615 }
616 
getMutableState() const617 sk_sp<GrBackendSurfaceMutableStateImpl> GrBackendTexture::getMutableState() const {
618     return fMutableState;
619 }
620 
621 #ifdef SK_DAWN
getDawnTextureInfo(GrDawnTextureInfo * outInfo) const622 bool GrBackendTexture::getDawnTextureInfo(GrDawnTextureInfo* outInfo) const {
623     if (this->isValid() && GrBackendApi::kDawn == fBackend) {
624         *outInfo = fDawnInfo;
625         return true;
626     }
627     return false;
628 }
629 #endif
630 
getVkImageInfo(GrVkImageInfo * outInfo) const631 bool GrBackendTexture::getVkImageInfo(GrVkImageInfo* outInfo) const {
632 #ifdef SK_VULKAN
633     if (this->isValid() && GrBackendApi::kVulkan == fBackend) {
634         *outInfo = fVkInfo.snapImageInfo(fMutableState.get());
635         return true;
636     }
637 #endif
638     return false;
639 }
640 
setVkImageLayout(VkImageLayout layout)641 void GrBackendTexture::setVkImageLayout(VkImageLayout layout) {
642 #ifdef SK_VULKAN
643     if (this->isValid() && GrBackendApi::kVulkan == fBackend) {
644         fMutableState->setImageLayout(layout);
645     }
646 #endif
647 }
648 
649 #ifdef SK_METAL
getMtlTextureInfo(GrMtlTextureInfo * outInfo) const650 bool GrBackendTexture::getMtlTextureInfo(GrMtlTextureInfo* outInfo) const {
651     if (this->isValid() && GrBackendApi::kMetal == fBackend) {
652         *outInfo = fMtlInfo;
653         return true;
654     }
655     return false;
656 }
657 #endif
658 
659 #ifdef SK_DIRECT3D
getD3DTextureResourceInfo(GrD3DTextureResourceInfo * outInfo) const660 bool GrBackendTexture::getD3DTextureResourceInfo(GrD3DTextureResourceInfo* outInfo) const {
661     if (this->isValid() && GrBackendApi::kDirect3D == fBackend) {
662         *outInfo = fD3DInfo.snapTextureResourceInfo();
663         return true;
664     }
665     return false;
666 }
667 
setD3DResourceState(GrD3DResourceStateEnum state)668 void GrBackendTexture::setD3DResourceState(GrD3DResourceStateEnum state) {
669     if (this->isValid() && GrBackendApi::kDirect3D == fBackend) {
670         fD3DInfo.setResourceState(state);
671     }
672 }
673 
getGrD3DResourceState() const674 sk_sp<GrD3DResourceState> GrBackendTexture::getGrD3DResourceState() const {
675     if (this->isValid() && GrBackendApi::kDirect3D == fBackend) {
676         return fD3DInfo.getGrD3DResourceState();
677     }
678     return nullptr;
679 }
680 #endif
681 
getGLTextureInfo(GrGLTextureInfo * outInfo) const682 bool GrBackendTexture::getGLTextureInfo(GrGLTextureInfo* outInfo) const {
683 #ifdef SK_GL
684     if (this->isValid() && GrBackendApi::kOpenGL == fBackend) {
685         *outInfo = fGLInfo.info();
686         return true;
687     } else if (this->isValid() && GrBackendApi::kMock == fBackend) {
688         // Hack! This allows some blink unit tests to work when using the Mock GrContext.
689         // Specifically, tests that rely on CanvasResourceProviderTextureGpuMemoryBuffer.
690         // If that code ever goes away (or ideally becomes backend-agnostic), this can go away.
691         *outInfo = GrGLTextureInfo{ GR_GL_TEXTURE_2D,
692                                     static_cast<GrGLuint>(fMockInfo.id()),
693                                     GR_GL_RGBA8 };
694         return true;
695     }
696 #endif
697     return false;
698 }
699 
glTextureParametersModified()700 void GrBackendTexture::glTextureParametersModified() {
701 #ifdef SK_GL
702     if (this->isValid() && fBackend == GrBackendApi::kOpenGL) {
703         fGLInfo.parameters()->invalidate();
704     }
705 #endif
706 }
707 
getMockTextureInfo(GrMockTextureInfo * outInfo) const708 bool GrBackendTexture::getMockTextureInfo(GrMockTextureInfo* outInfo) const {
709     if (this->isValid() && GrBackendApi::kMock == fBackend) {
710         *outInfo = fMockInfo;
711         return true;
712     }
713     return false;
714 }
715 
setMutableState(const GrBackendSurfaceMutableState & state)716 void GrBackendTexture::setMutableState(const GrBackendSurfaceMutableState& state) {
717     fMutableState->set(state);
718 }
719 
isProtected() const720 bool GrBackendTexture::isProtected() const {
721     if (!this->isValid() || this->backend() != GrBackendApi::kVulkan) {
722         return false;
723     }
724     return fVkInfo.isProtected();
725 }
726 
isSameTexture(const GrBackendTexture & that)727 bool GrBackendTexture::isSameTexture(const GrBackendTexture& that) {
728     if (!this->isValid() || !that.isValid()) {
729         return false;
730     }
731     if (fBackend != that.fBackend) {
732         return false;
733     }
734     switch (fBackend) {
735 #ifdef SK_GL
736         case GrBackendApi::kOpenGL:
737             return fGLInfo.info().fID == that.fGLInfo.info().fID;
738 #endif
739 #ifdef SK_VULKAN
740         case GrBackendApi::kVulkan:
741             return fVkInfo.snapImageInfo(fMutableState.get()).fImage ==
742                    that.fVkInfo.snapImageInfo(that.fMutableState.get()).fImage;
743 #endif
744 #ifdef SK_METAL
745         case GrBackendApi::kMetal:
746             return this->fMtlInfo.fTexture == that.fMtlInfo.fTexture;
747 #endif
748 #ifdef SK_DIRECT3D
749         case GrBackendApi::kDirect3D:
750             return fD3DInfo.snapTextureResourceInfo().fResource ==
751                     that.fD3DInfo.snapTextureResourceInfo().fResource;
752 #endif
753 #ifdef SK_DAWN
754         case GrBackendApi::kDawn: {
755             return this->fDawnInfo.fTexture.Get() == that.fDawnInfo.fTexture.Get();
756         }
757 #endif
758         case GrBackendApi::kMock:
759             return fMockInfo.id() == that.fMockInfo.id();
760         default:
761             return false;
762     }
763 }
764 
getBackendFormat() const765 GrBackendFormat GrBackendTexture::getBackendFormat() const {
766     if (!this->isValid()) {
767         return GrBackendFormat();
768     }
769     switch (fBackend) {
770 #ifdef SK_GL
771         case GrBackendApi::kOpenGL:
772             return GrBackendFormat::MakeGL(fGLInfo.info().fFormat, fGLInfo.info().fTarget);
773 #endif
774 #ifdef SK_VULKAN
775         case GrBackendApi::kVulkan: {
776             auto info = fVkInfo.snapImageInfo(fMutableState.get());
777             if (info.fYcbcrConversionInfo.isValid()) {
778                 SkASSERT(info.fFormat == info.fYcbcrConversionInfo.fFormat);
779                 return GrBackendFormat::MakeVk(info.fYcbcrConversionInfo);
780             }
781             return GrBackendFormat::MakeVk(info.fFormat);
782         }
783 #endif
784 #ifdef SK_METAL
785         case GrBackendApi::kMetal: {
786             GrMtlTextureInfo mtlInfo;
787             SkAssertResult(this->getMtlTextureInfo(&mtlInfo));
788             return GrBackendFormat::MakeMtl(GrGetMTLPixelFormatFromMtlTextureInfo(mtlInfo));
789         }
790 #endif
791 #ifdef SK_DIRECT3D
792         case GrBackendApi::kDirect3D: {
793             auto d3dInfo = fD3DInfo.snapTextureResourceInfo();
794             return GrBackendFormat::MakeDxgi(d3dInfo.fFormat);
795         }
796 #endif
797 #ifdef SK_DAWN
798         case GrBackendApi::kDawn: {
799             return GrBackendFormat::MakeDawn(fDawnInfo.fFormat);
800         }
801 #endif
802         case GrBackendApi::kMock:
803             return fMockInfo.getBackendFormat();
804         default:
805             return GrBackendFormat();
806     }
807 }
808 
809 #if GR_TEST_UTILS
TestingOnly_Equals(const GrBackendTexture & t0,const GrBackendTexture & t1)810 bool GrBackendTexture::TestingOnly_Equals(const GrBackendTexture& t0, const GrBackendTexture& t1) {
811     if (!t0.isValid() || !t1.isValid()) {
812         return false; // two invalid backend textures are not considered equal
813     }
814 
815     if (t0.fWidth != t1.fWidth ||
816         t0.fHeight != t1.fHeight ||
817         t0.fMipmapped != t1.fMipmapped ||
818         t0.fBackend != t1.fBackend) {
819         return false;
820     }
821 
822     // For our tests when checking equality we are assuming the both backendTexture objects will
823     // be using the same mutable state object.
824     if (t0.fMutableState != t1.fMutableState) {
825         return false;
826     }
827 
828     switch (t0.fBackend) {
829 #ifdef SK_GL
830         case GrBackendApi::kOpenGL:
831             return t0.fGLInfo.info() == t1.fGLInfo.info();
832 #endif
833         case GrBackendApi::kMock:
834             return t0.fMockInfo == t1.fMockInfo;
835 #ifdef SK_VULKAN
836         case GrBackendApi::kVulkan:
837             return t0.fVkInfo == t1.fVkInfo;
838 #endif
839 #ifdef SK_METAL
840         case GrBackendApi::kMetal:
841             return t0.fMtlInfo == t1.fMtlInfo;
842 #endif
843 #ifdef SK_DIRECT3D
844         case GrBackendApi::kDirect3D:
845             return t0.fD3DInfo == t1.fD3DInfo;
846 #endif
847 #ifdef SK_DAWN
848         case GrBackendApi::kDawn:
849             return t0.fDawnInfo == t1.fDawnInfo;
850 #endif
851         default:
852             return false;
853     }
854 }
855 #endif
856 
857 ////////////////////////////////////////////////////////////////////////////////////////////////////
858 
GrBackendRenderTarget()859 GrBackendRenderTarget::GrBackendRenderTarget() : fIsValid(false) {}
860 
861 
862 #ifdef SK_DAWN
GrBackendRenderTarget(int width,int height,int sampleCnt,int stencilBits,const GrDawnRenderTargetInfo & dawnInfo)863 GrBackendRenderTarget::GrBackendRenderTarget(int width,
864                                              int height,
865                                              int sampleCnt,
866                                              int stencilBits,
867                                              const GrDawnRenderTargetInfo& dawnInfo)
868         : fIsValid(true)
869         , fFramebufferOnly(true)
870         , fWidth(width)
871         , fHeight(height)
872         , fSampleCnt(sampleCnt)
873         , fStencilBits(stencilBits)
874         , fBackend(GrBackendApi::kDawn)
875         , fDawnInfo(dawnInfo) {}
876 #endif
877 
878 #ifdef SK_VULKAN
resolve_vkii_sample_count(const GrVkImageInfo & vkII,int sidebandSampleCnt)879 static GrVkImageInfo resolve_vkii_sample_count(const GrVkImageInfo& vkII, int sidebandSampleCnt) {
880     auto result = vkII;
881     result.fSampleCount = std::max({vkII.fSampleCount,
882                                     static_cast<uint32_t>(sidebandSampleCnt),
883                                     1U});
884     return result;
885 }
886 
GrBackendRenderTarget(int width,int height,int sampleCnt,const GrVkImageInfo & vkInfo)887 GrBackendRenderTarget::GrBackendRenderTarget(int width,
888                                              int height,
889                                              int sampleCnt,
890                                              const GrVkImageInfo& vkInfo)
891         : GrBackendRenderTarget(width, height, resolve_vkii_sample_count(vkInfo, sampleCnt)) {}
892 
GrBackendRenderTarget(int width,int height,const GrVkImageInfo & vkInfo)893 GrBackendRenderTarget::GrBackendRenderTarget(int width,
894                                              int height,
895                                              const GrVkImageInfo& vkInfo)
896         : GrBackendRenderTarget(width, height, vkInfo,
897                                 sk_sp<GrBackendSurfaceMutableStateImpl>(
898                                         new GrBackendSurfaceMutableStateImpl(
899                                                 vkInfo.fImageLayout, vkInfo.fCurrentQueueFamily))) {}
900 
901 static const VkImageUsageFlags kDefaultRTUsageFlags =
902         kDefaultUsageFlags | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
903 
GrBackendRenderTarget(int width,int height,const GrVkImageInfo & vkInfo,sk_sp<GrBackendSurfaceMutableStateImpl> mutableState)904 GrBackendRenderTarget::GrBackendRenderTarget(int width,
905                                              int height,
906                                              const GrVkImageInfo& vkInfo,
907                                              sk_sp<GrBackendSurfaceMutableStateImpl> mutableState)
908         : fIsValid(true)
909         , fWidth(width)
910         , fHeight(height)
911         , fSampleCnt(std::max(1U, vkInfo.fSampleCount))
912         , fStencilBits(0)  // We always create stencil buffers internally for vulkan
913         , fBackend(GrBackendApi::kVulkan)
914         , fVkInfo(apply_default_usage_flags(vkInfo, kDefaultRTUsageFlags))
915         , fMutableState(mutableState) {}
916 #endif
917 
918 #ifdef SK_METAL
GrBackendRenderTarget(int width,int height,const GrMtlTextureInfo & mtlInfo)919 GrBackendRenderTarget::GrBackendRenderTarget(int width, int height, const GrMtlTextureInfo& mtlInfo)
920         : fIsValid(true)
921         , fFramebufferOnly(false)  // TODO: set this from mtlInfo.fTexture->framebufferOnly
922         , fWidth(width)
923         , fHeight(height)
924         , fSampleCnt(std::max(1, GrMtlTextureInfoSampleCount(mtlInfo)))
925         , fStencilBits(0)
926         , fBackend(GrBackendApi::kMetal)
927         , fMtlInfo(mtlInfo) {}
928 
GrBackendRenderTarget(int width,int height,int sampleCount,const GrMtlTextureInfo & mtlInfo)929 GrBackendRenderTarget::GrBackendRenderTarget(int width, int height,
930                                              int sampleCount,
931                                              const GrMtlTextureInfo& mtlInfo)
932         : GrBackendRenderTarget(width, height, mtlInfo) {}
933 #endif
934 
935 #ifdef SK_DIRECT3D
GrBackendRenderTarget(int width,int height,const GrD3DTextureResourceInfo & d3dInfo)936 GrBackendRenderTarget::GrBackendRenderTarget(int width, int height,
937                                              const GrD3DTextureResourceInfo& d3dInfo)
938         : GrBackendRenderTarget(
939                 width, height, d3dInfo,
940                 sk_sp<GrD3DResourceState>(new GrD3DResourceState(
941                         static_cast<D3D12_RESOURCE_STATES>(d3dInfo.fResourceState)))) {}
942 
GrBackendRenderTarget(int width,int height,const GrD3DTextureResourceInfo & d3dInfo,sk_sp<GrD3DResourceState> state)943 GrBackendRenderTarget::GrBackendRenderTarget(int width,
944                                              int height,
945                                              const GrD3DTextureResourceInfo& d3dInfo,
946                                              sk_sp<GrD3DResourceState> state)
947         : fIsValid(true)
948         , fWidth(width)
949         , fHeight(height)
950         , fSampleCnt(std::max(1U, d3dInfo.fSampleCount))
951         , fStencilBits(0)
952         , fBackend(GrBackendApi::kDirect3D)
953         , fD3DInfo(d3dInfo, state.release()) {}
954 #endif
955 #ifdef SK_GL
GrBackendRenderTarget(int width,int height,int sampleCnt,int stencilBits,const GrGLFramebufferInfo & glInfo)956 GrBackendRenderTarget::GrBackendRenderTarget(int width,
957                                              int height,
958                                              int sampleCnt,
959                                              int stencilBits,
960                                              const GrGLFramebufferInfo& glInfo)
961         : fWidth(width)
962         , fHeight(height)
963         , fSampleCnt(std::max(1, sampleCnt))
964         , fStencilBits(stencilBits)
965         , fBackend(GrBackendApi::kOpenGL)
966         , fGLInfo(glInfo) {
967     fIsValid = SkToBool(glInfo.fFormat); // the glInfo must have a valid format
968 }
969 #endif
970 
GrBackendRenderTarget(int width,int height,int sampleCnt,int stencilBits,const GrMockRenderTargetInfo & mockInfo)971 GrBackendRenderTarget::GrBackendRenderTarget(int width,
972                                              int height,
973                                              int sampleCnt,
974                                              int stencilBits,
975                                              const GrMockRenderTargetInfo& mockInfo)
976         : fIsValid(true)
977         , fWidth(width)
978         , fHeight(height)
979         , fSampleCnt(std::max(1, sampleCnt))
980         , fStencilBits(stencilBits)
981         , fMockInfo(mockInfo) {}
982 
~GrBackendRenderTarget()983 GrBackendRenderTarget::~GrBackendRenderTarget() {
984     this->cleanup();
985 }
986 
cleanup()987 void GrBackendRenderTarget::cleanup() {
988 #ifdef SK_VULKAN
989     if (this->isValid() && GrBackendApi::kVulkan == fBackend) {
990         fVkInfo.cleanup();
991     }
992 #endif
993 #ifdef SK_DIRECT3D
994     if (this->isValid() && GrBackendApi::kDirect3D == fBackend) {
995         fD3DInfo.cleanup();
996     }
997 #endif
998 }
999 
GrBackendRenderTarget(const GrBackendRenderTarget & that)1000 GrBackendRenderTarget::GrBackendRenderTarget(const GrBackendRenderTarget& that) : fIsValid(false) {
1001     *this = that;
1002 }
1003 
operator =(const GrBackendRenderTarget & that)1004 GrBackendRenderTarget& GrBackendRenderTarget::operator=(const GrBackendRenderTarget& that) {
1005     if (!that.isValid()) {
1006         this->cleanup();
1007         fIsValid = false;
1008         return *this;
1009     } else if (fIsValid && this->fBackend != that.fBackend) {
1010         this->cleanup();
1011         fIsValid = false;
1012     }
1013     fWidth = that.fWidth;
1014     fHeight = that.fHeight;
1015     fSampleCnt = that.fSampleCnt;
1016     fStencilBits = that.fStencilBits;
1017     fBackend = that.fBackend;
1018 
1019     switch (that.fBackend) {
1020 #ifdef SK_GL
1021         case GrBackendApi::kOpenGL:
1022             fGLInfo = that.fGLInfo;
1023             break;
1024 #endif
1025 #ifdef SK_VULKAN
1026         case GrBackendApi::kVulkan:
1027             fVkInfo.assign(that.fVkInfo, this->isValid());
1028             break;
1029 #endif
1030 #ifdef SK_METAL
1031         case GrBackendApi::kMetal:
1032             fMtlInfo = that.fMtlInfo;
1033             break;
1034 #endif
1035 #ifdef SK_DIRECT3D
1036         case GrBackendApi::kDirect3D:
1037             fD3DInfo.assign(that.fD3DInfo, this->isValid());
1038             break;
1039 #endif
1040 #ifdef SK_DAWN
1041         case GrBackendApi::kDawn:
1042             fDawnInfo = that.fDawnInfo;
1043             break;
1044 #endif
1045         case GrBackendApi::kMock:
1046             fMockInfo = that.fMockInfo;
1047             break;
1048         default:
1049             SK_ABORT("Unknown GrBackend");
1050     }
1051     fMutableState = that.fMutableState;
1052     fIsValid = that.fIsValid;
1053     return *this;
1054 }
1055 
getMutableState() const1056 sk_sp<GrBackendSurfaceMutableStateImpl> GrBackendRenderTarget::getMutableState() const {
1057     return fMutableState;
1058 }
1059 
1060 #ifdef SK_DAWN
getDawnRenderTargetInfo(GrDawnRenderTargetInfo * outInfo) const1061 bool GrBackendRenderTarget::getDawnRenderTargetInfo(GrDawnRenderTargetInfo* outInfo) const {
1062     if (this->isValid() && GrBackendApi::kDawn == fBackend) {
1063         *outInfo = fDawnInfo;
1064         return true;
1065     }
1066     return false;
1067 }
1068 #endif
1069 
getVkImageInfo(GrVkImageInfo * outInfo) const1070 bool GrBackendRenderTarget::getVkImageInfo(GrVkImageInfo* outInfo) const {
1071 #ifdef SK_VULKAN
1072     if (this->isValid() && GrBackendApi::kVulkan == fBackend) {
1073         *outInfo = fVkInfo.snapImageInfo(fMutableState.get());
1074         return true;
1075     }
1076 #endif
1077     return false;
1078 }
1079 
setVkImageLayout(VkImageLayout layout)1080 void GrBackendRenderTarget::setVkImageLayout(VkImageLayout layout) {
1081 #ifdef SK_VULKAN
1082     if (this->isValid() && GrBackendApi::kVulkan == fBackend) {
1083         fMutableState->setImageLayout(layout);
1084     }
1085 #endif
1086 }
1087 
1088 #ifdef SK_METAL
getMtlTextureInfo(GrMtlTextureInfo * outInfo) const1089 bool GrBackendRenderTarget::getMtlTextureInfo(GrMtlTextureInfo* outInfo) const {
1090     if (this->isValid() && GrBackendApi::kMetal == fBackend) {
1091         *outInfo = fMtlInfo;
1092         return true;
1093     }
1094     return false;
1095 }
1096 #endif
1097 
1098 #ifdef SK_DIRECT3D
getD3DTextureResourceInfo(GrD3DTextureResourceInfo * outInfo) const1099 bool GrBackendRenderTarget::getD3DTextureResourceInfo(GrD3DTextureResourceInfo* outInfo) const {
1100     if (this->isValid() && GrBackendApi::kDirect3D == fBackend) {
1101         *outInfo = fD3DInfo.snapTextureResourceInfo();
1102         return true;
1103     }
1104     return false;
1105 }
1106 
setD3DResourceState(GrD3DResourceStateEnum state)1107 void GrBackendRenderTarget::setD3DResourceState(GrD3DResourceStateEnum state) {
1108     if (this->isValid() && GrBackendApi::kDirect3D == fBackend) {
1109         fD3DInfo.setResourceState(state);
1110     }
1111 }
1112 
getGrD3DResourceState() const1113 sk_sp<GrD3DResourceState> GrBackendRenderTarget::getGrD3DResourceState() const {
1114     if (this->isValid() && GrBackendApi::kDirect3D == fBackend) {
1115         return fD3DInfo.getGrD3DResourceState();
1116     }
1117     return nullptr;
1118 }
1119 #endif
1120 
1121 #ifdef SK_GL
getGLFramebufferInfo(GrGLFramebufferInfo * outInfo) const1122 bool GrBackendRenderTarget::getGLFramebufferInfo(GrGLFramebufferInfo* outInfo) const {
1123     if (this->isValid() && GrBackendApi::kOpenGL == fBackend) {
1124         *outInfo = fGLInfo;
1125         return true;
1126     }
1127     return false;
1128 }
1129 #endif
1130 
getBackendFormat() const1131 GrBackendFormat GrBackendRenderTarget::getBackendFormat() const {
1132     if (!this->isValid()) {
1133         return GrBackendFormat();
1134     }
1135     switch (fBackend) {
1136 #ifdef SK_GL
1137         case GrBackendApi::kOpenGL:
1138             return GrBackendFormat::MakeGL(fGLInfo.fFormat, GR_GL_TEXTURE_NONE);
1139 #endif
1140 #ifdef SK_VULKAN
1141         case GrBackendApi::kVulkan: {
1142             auto info = fVkInfo.snapImageInfo(fMutableState.get());
1143             if (info.fYcbcrConversionInfo.isValid()) {
1144                 SkASSERT(info.fFormat == info.fYcbcrConversionInfo.fFormat);
1145                 return GrBackendFormat::MakeVk(info.fYcbcrConversionInfo);
1146             }
1147             return GrBackendFormat::MakeVk(info.fFormat);
1148         }
1149 #endif
1150 #ifdef SK_METAL
1151         case GrBackendApi::kMetal: {
1152             GrMtlTextureInfo mtlInfo;
1153             SkAssertResult(this->getMtlTextureInfo(&mtlInfo));
1154             return GrBackendFormat::MakeMtl(GrGetMTLPixelFormatFromMtlTextureInfo(mtlInfo));
1155         }
1156 #endif
1157 #ifdef SK_DIRECT3D
1158         case GrBackendApi::kDirect3D: {
1159             auto info = fD3DInfo.snapTextureResourceInfo();
1160             return GrBackendFormat::MakeDxgi(info.fFormat);
1161         }
1162 #endif
1163 #ifdef SK_DAWN
1164         case GrBackendApi::kDawn: {
1165             GrDawnRenderTargetInfo dawnInfo;
1166             SkAssertResult(this->getDawnRenderTargetInfo(&dawnInfo));
1167             return GrBackendFormat::MakeDawn(dawnInfo.fFormat);
1168         }
1169 #endif
1170         case GrBackendApi::kMock:
1171             return fMockInfo.getBackendFormat();
1172         default:
1173             return GrBackendFormat();
1174     }
1175 }
1176 
getMockRenderTargetInfo(GrMockRenderTargetInfo * outInfo) const1177 bool GrBackendRenderTarget::getMockRenderTargetInfo(GrMockRenderTargetInfo* outInfo) const {
1178     if (this->isValid() && GrBackendApi::kMock == fBackend) {
1179         *outInfo = fMockInfo;
1180         return true;
1181     }
1182     return false;
1183 }
1184 
setMutableState(const GrBackendSurfaceMutableState & state)1185 void GrBackendRenderTarget::setMutableState(const GrBackendSurfaceMutableState& state) {
1186     fMutableState->set(state);
1187 }
1188 
isProtected() const1189 bool GrBackendRenderTarget::isProtected() const {
1190     if (!this->isValid() || this->backend() != GrBackendApi::kVulkan) {
1191         return false;
1192     }
1193     return fVkInfo.isProtected();
1194 }
1195 
1196 #if GR_TEST_UTILS
TestingOnly_Equals(const GrBackendRenderTarget & r0,const GrBackendRenderTarget & r1)1197 bool GrBackendRenderTarget::TestingOnly_Equals(const GrBackendRenderTarget& r0,
1198                                                const GrBackendRenderTarget& r1) {
1199     if (!r0.isValid() || !r1.isValid()) {
1200         return false; // two invalid backend rendertargets are not considered equal
1201     }
1202 
1203     if (r0.fWidth != r1.fWidth ||
1204         r0.fHeight != r1.fHeight ||
1205         r0.fSampleCnt != r1.fSampleCnt ||
1206         r0.fStencilBits != r1.fStencilBits ||
1207         r0.fBackend != r1.fBackend) {
1208         return false;
1209     }
1210 
1211     switch (r0.fBackend) {
1212 #ifdef SK_GL
1213         case GrBackendApi::kOpenGL:
1214             return r0.fGLInfo == r1.fGLInfo;
1215 #endif
1216         case GrBackendApi::kMock:
1217             return r0.fMockInfo == r1.fMockInfo;
1218 #ifdef SK_VULKAN
1219         case GrBackendApi::kVulkan:
1220             return r0.fVkInfo == r1.fVkInfo;
1221 #endif
1222 #ifdef SK_METAL
1223         case GrBackendApi::kMetal:
1224             return r0.fMtlInfo == r1.fMtlInfo;
1225 #endif
1226 #ifdef SK_DIRECT3D
1227         case GrBackendApi::kDirect3D:
1228             return r0.fD3DInfo == r1.fD3DInfo;
1229 #endif
1230 #ifdef SK_DAWN
1231         case GrBackendApi::kDawn:
1232             return r0.fDawnInfo == r1.fDawnInfo;
1233 #endif
1234         default:
1235             return false;
1236     }
1237 
1238     SkASSERT(0);
1239     return false;
1240 }
1241 #endif
1242