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