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