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