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