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