BackendAllocationTest.cpp 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818
  1. /*
  2. * Copyright 2019 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. #include "include/core/SkSurface.h"
  8. #include "include/core/SkSurfaceCharacterization.h"
  9. #include "include/gpu/GrContext.h"
  10. #include "src/core/SkAutoPixmapStorage.h"
  11. #include "src/gpu/GrContextPriv.h"
  12. #include "src/image/SkImage_Base.h"
  13. #include "tests/Test.h"
  14. #ifdef SK_GL
  15. #include "src/gpu/gl/GrGLGpu.h"
  16. #include "src/gpu/gl/GrGLUtil.h"
  17. #endif
  18. // Test wrapping of GrBackendObjects in SkSurfaces and SkImages
  19. void test_wrapping(GrContext* context, skiatest::Reporter* reporter,
  20. std::function<GrBackendTexture (GrContext*,
  21. GrMipMapped,
  22. GrRenderable)> create,
  23. SkColorType colorType, GrMipMapped mipMapped, GrRenderable renderable) {
  24. GrResourceCache* cache = context->priv().getResourceCache();
  25. const int initialCount = cache->getResourceCount();
  26. GrBackendTexture backendTex = create(context, mipMapped, renderable);
  27. if (!backendTex.isValid()) {
  28. ERRORF(reporter, "Couldn't create backendTexture for colorType %d renderable %s\n",
  29. colorType,
  30. GrRenderable::kYes == renderable ? "yes" : "no");
  31. return;
  32. }
  33. // Skia proper should know nothing about the new backend object
  34. REPORTER_ASSERT(reporter, initialCount == cache->getResourceCount());
  35. if (kUnknown_SkColorType == colorType) {
  36. context->deleteBackendTexture(backendTex);
  37. return;
  38. }
  39. if (GrRenderable::kYes == renderable) {
  40. sk_sp<SkSurface> surf = SkSurface::MakeFromBackendTexture(context,
  41. backendTex,
  42. kTopLeft_GrSurfaceOrigin,
  43. 0,
  44. colorType,
  45. nullptr, nullptr);
  46. if (!surf) {
  47. ERRORF(reporter, "Couldn't make surface from backendTexture for colorType %d\n",
  48. colorType);
  49. } else {
  50. REPORTER_ASSERT(reporter, initialCount+1 == cache->getResourceCount());
  51. }
  52. }
  53. {
  54. sk_sp<SkImage> img = SkImage::MakeFromTexture(context,
  55. backendTex,
  56. kTopLeft_GrSurfaceOrigin,
  57. colorType,
  58. kPremul_SkAlphaType,
  59. nullptr);
  60. if (!img) {
  61. ERRORF(reporter, "Couldn't make image from backendTexture for colorType %d\n",
  62. colorType);
  63. } else {
  64. SkImage_Base* ib = as_IB(img);
  65. GrTextureProxy* proxy = ib->peekProxy();
  66. REPORTER_ASSERT(reporter, proxy);
  67. REPORTER_ASSERT(reporter, mipMapped == proxy->proxyMipMapped());
  68. REPORTER_ASSERT(reporter, proxy->isInstantiated());
  69. REPORTER_ASSERT(reporter, mipMapped == proxy->mipMapped());
  70. REPORTER_ASSERT(reporter, initialCount+1 == cache->getResourceCount());
  71. }
  72. }
  73. REPORTER_ASSERT(reporter, initialCount == cache->getResourceCount());
  74. context->deleteBackendTexture(backendTex);
  75. }
  76. static bool colors_eq(SkColor colA, SkColor colB, int tol) {
  77. int maxDiff = 0;
  78. for (int i = 0; i < 4; ++i) {
  79. int diff = SkTAbs<int>((0xFF & (colA >> i*8)) - (0xFF & (colB >> i*8)));
  80. if (maxDiff < diff) {
  81. maxDiff = diff;
  82. }
  83. }
  84. return maxDiff <= tol;
  85. }
  86. static void compare_pixmaps(const SkPixmap& expected, const SkPixmap& actual,
  87. SkColorType colorType, skiatest::Reporter* reporter) {
  88. SkASSERT(expected.info() == actual.info());
  89. for (int y = 0; y < expected.height(); ++y) {
  90. for (int x = 0; x < expected.width(); ++x) {
  91. SkColor expectedCol = expected.getColor(x, y);
  92. SkColor actualCol = actual.getColor(x, y);
  93. // GPU and raster differ a bit on kGray_8_SkColorType and kRGBA_1010102_SkColorType
  94. if (colors_eq(actualCol, expectedCol, 12)) {
  95. continue;
  96. }
  97. ERRORF(reporter,
  98. "Mismatched pixels at %d %d ct: %d expected: 0x%x actual: 0x%x\n",
  99. x, y, colorType, expectedCol, actualCol);
  100. return;
  101. }
  102. }
  103. }
  104. // Test initialization of GrBackendObjects to a specific color
  105. void test_color_init(GrContext* context, skiatest::Reporter* reporter,
  106. std::function<GrBackendTexture (GrContext*,
  107. const SkColor4f&,
  108. GrMipMapped,
  109. GrRenderable)> create,
  110. SkColorType colorType, const SkColor4f& color,
  111. GrMipMapped mipMapped, GrRenderable renderable) {
  112. GrBackendTexture backendTex = create(context, color, mipMapped, renderable);
  113. if (!backendTex.isValid()) {
  114. // errors here should be reported by the test_wrapping test
  115. return;
  116. }
  117. if (kUnknown_SkColorType == colorType) {
  118. // TODO: burrow in and scrappily check that data was uploaded!
  119. context->deleteBackendTexture(backendTex);
  120. return;
  121. }
  122. SkAlphaType at = SkColorTypeIsAlwaysOpaque(colorType) ? kOpaque_SkAlphaType
  123. : kPremul_SkAlphaType;
  124. SkImageInfo ii = SkImageInfo::Make(32, 32, colorType, at);
  125. SkColor4f rasterColor = color;
  126. if (kGray_8_SkColorType == colorType) {
  127. // For the GPU backends, gray implies a single channel which is opaque.
  128. rasterColor.fR = color.fA;
  129. rasterColor.fG = color.fA;
  130. rasterColor.fB = color.fA;
  131. rasterColor.fA = 1.0f;
  132. } else if (kAlpha_8_SkColorType == colorType) {
  133. // For the GPU backends, alpha implies a single alpha channel.
  134. rasterColor.fR = 0;
  135. rasterColor.fG = 0;
  136. rasterColor.fB = 0;
  137. rasterColor.fA = color.fA;
  138. }
  139. SkAutoPixmapStorage expected;
  140. SkAssertResult(expected.tryAlloc(ii));
  141. expected.erase(rasterColor);
  142. SkAutoPixmapStorage actual;
  143. SkAssertResult(actual.tryAlloc(ii));
  144. actual.erase(SkColors::kTransparent);
  145. if (GrRenderable::kYes == renderable) {
  146. sk_sp<SkSurface> surf = SkSurface::MakeFromBackendTexture(context,
  147. backendTex,
  148. kTopLeft_GrSurfaceOrigin,
  149. 0,
  150. colorType,
  151. nullptr, nullptr);
  152. if (surf) {
  153. bool result = surf->readPixels(actual, 0, 0);
  154. REPORTER_ASSERT(reporter, result);
  155. compare_pixmaps(expected, actual, colorType, reporter);
  156. actual.erase(SkColors::kTransparent);
  157. }
  158. }
  159. {
  160. sk_sp<SkImage> img = SkImage::MakeFromTexture(context,
  161. backendTex,
  162. kTopLeft_GrSurfaceOrigin,
  163. colorType,
  164. at,
  165. nullptr);
  166. if (img) {
  167. // If possible, read back the pixels and check that they're correct
  168. {
  169. bool result = img->readPixels(actual, 0, 0);
  170. if (!result) {
  171. // TODO: we need a better way to tell a priori if readPixels will work for an
  172. // arbitrary colorType
  173. #if 0
  174. ERRORF(reporter, "Couldn't readback from SkImage for colorType: %d\n",
  175. colorType);
  176. #endif
  177. } else {
  178. compare_pixmaps(expected, actual, colorType, reporter);
  179. }
  180. }
  181. // Draw the wrapped image into an RGBA surface attempting to access all the
  182. // mipMap levels.
  183. {
  184. #ifdef SK_GL
  185. // skbug.com/9141 (RGBA_F32 mipmaps appear to be broken on some Mali devices)
  186. if (GrBackendApi::kOpenGL == context->backend()) {
  187. GrGLGpu* glGPU = static_cast<GrGLGpu*>(context->priv().getGpu());
  188. if (kRGBA_F32_SkColorType == colorType && GrMipMapped::kYes == mipMapped &&
  189. kGLES_GrGLStandard == glGPU->ctxInfo().standard()) {
  190. context->deleteBackendTexture(backendTex);
  191. return;
  192. }
  193. }
  194. #endif
  195. SkImageInfo newII = SkImageInfo::Make(32, 32, kRGBA_8888_SkColorType,
  196. kPremul_SkAlphaType);
  197. SkAutoPixmapStorage actual2;
  198. SkAssertResult(actual2.tryAlloc(newII));
  199. actual2.erase(SkColors::kTransparent);
  200. sk_sp<SkSurface> surf = SkSurface::MakeRenderTarget(context,
  201. SkBudgeted::kNo,
  202. newII, 1,
  203. kTopLeft_GrSurfaceOrigin,
  204. nullptr);
  205. if (!surf) {
  206. context->deleteBackendTexture(backendTex);
  207. return;
  208. }
  209. SkCanvas* canvas = surf->getCanvas();
  210. SkPaint p;
  211. p.setFilterQuality(kHigh_SkFilterQuality);
  212. int numMipLevels = (GrMipMapped::kYes == mipMapped) ? 6 : 1;
  213. for (int i = 0, rectSize = 32; i < numMipLevels; ++i, rectSize /= 2) {
  214. SkASSERT(rectSize >= 1);
  215. SkRect r = SkRect::MakeWH(rectSize, rectSize);
  216. canvas->clear(SK_ColorTRANSPARENT);
  217. canvas->drawImageRect(img, r, &p);
  218. bool result = surf->readPixels(actual2, 0, 0);
  219. REPORTER_ASSERT(reporter, result);
  220. SkColor actualColor = actual2.getColor(0, 0);
  221. if (!colors_eq(actualColor, rasterColor.toSkColor(), 1)) {
  222. ERRORF(reporter, "Pixel mismatch colorType %d: level: %d e: 0x%x a: 0x%x\n",
  223. colorType, i, rasterColor.toSkColor(), actualColor);
  224. }
  225. }
  226. }
  227. }
  228. }
  229. context->deleteBackendTexture(backendTex);
  230. }
  231. enum class VkLayout {
  232. kUndefined,
  233. kReadOnlyOptimal,
  234. kColorAttachmentOptimal
  235. };
  236. void check_vk_layout(const GrBackendTexture& backendTex, VkLayout layout) {
  237. #if defined(SK_VULKAN) && defined(SK_DEBUG)
  238. VkImageLayout expected;
  239. switch (layout) {
  240. case VkLayout::kUndefined:
  241. expected = VK_IMAGE_LAYOUT_UNDEFINED;
  242. break;
  243. case VkLayout::kReadOnlyOptimal:
  244. expected = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
  245. break;
  246. case VkLayout::kColorAttachmentOptimal:
  247. expected = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
  248. break;
  249. default:
  250. SkUNREACHABLE;
  251. }
  252. GrVkImageInfo vkII;
  253. if (backendTex.getVkImageInfo(&vkII)) {
  254. SkASSERT(expected == vkII.fImageLayout);
  255. SkASSERT(VK_IMAGE_TILING_OPTIMAL == vkII.fImageTiling);
  256. }
  257. #endif
  258. }
  259. ///////////////////////////////////////////////////////////////////////////////
  260. // This test is a bit different from the others in this file. It is mainly checking that, for any
  261. // SkSurface we can create in Ganesh, we can also create a backend texture that is compatible with
  262. // its characterization and then create a new surface that wraps that backend texture.
  263. DEF_GPUTEST_FOR_RENDERING_CONTEXTS(CharacterizationBackendAllocationTest, reporter, ctxInfo) {
  264. GrContext* context = ctxInfo.grContext();
  265. for (int ct = 0; ct <= kLastEnum_SkColorType; ++ct) {
  266. SkColorType colorType = static_cast<SkColorType>(ct);
  267. SkImageInfo ii = SkImageInfo::Make(32, 32, colorType, kPremul_SkAlphaType);
  268. for (auto origin : { kTopLeft_GrSurfaceOrigin, kBottomLeft_GrSurfaceOrigin } ) {
  269. for (bool mipMaps : { true, false } ) {
  270. for (int sampleCount : {1, 2}) {
  271. SkSurfaceCharacterization c;
  272. // Get a characterization, if possible
  273. {
  274. sk_sp<SkSurface> s = SkSurface::MakeRenderTarget(context, SkBudgeted::kNo,
  275. ii, sampleCount,
  276. origin, nullptr, mipMaps);
  277. if (!s) {
  278. continue;
  279. }
  280. if (!s->characterize(&c)) {
  281. continue;
  282. }
  283. REPORTER_ASSERT(reporter, s->isCompatible(c));
  284. }
  285. // Test out uninitialized path
  286. {
  287. GrBackendTexture backendTex = context->createBackendTexture(c);
  288. check_vk_layout(backendTex, VkLayout::kUndefined);
  289. REPORTER_ASSERT(reporter, backendTex.isValid());
  290. REPORTER_ASSERT(reporter, c.isCompatible(backendTex));
  291. sk_sp<SkSurface> s2 = SkSurface::MakeFromBackendTexture(context, c,
  292. backendTex);
  293. REPORTER_ASSERT(reporter, s2);
  294. REPORTER_ASSERT(reporter, s2->isCompatible(c));
  295. s2 = nullptr;
  296. context->deleteBackendTexture(backendTex);
  297. }
  298. // Test out color-initialized path
  299. {
  300. GrBackendTexture backendTex = context->createBackendTexture(c,
  301. SkColors::kRed);
  302. check_vk_layout(backendTex, VkLayout::kColorAttachmentOptimal);
  303. REPORTER_ASSERT(reporter, backendTex.isValid());
  304. REPORTER_ASSERT(reporter, c.isCompatible(backendTex));
  305. sk_sp<SkSurface> s2 = SkSurface::MakeFromBackendTexture(context, c,
  306. backendTex);
  307. REPORTER_ASSERT(reporter, s2);
  308. REPORTER_ASSERT(reporter, s2->isCompatible(c));
  309. s2 = nullptr;
  310. context->deleteBackendTexture(backendTex);
  311. }
  312. }
  313. }
  314. }
  315. }
  316. }
  317. ///////////////////////////////////////////////////////////////////////////////
  318. DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ColorTypeBackendAllocationTest, reporter, ctxInfo) {
  319. GrContext* context = ctxInfo.grContext();
  320. const GrCaps* caps = context->priv().caps();
  321. constexpr SkColor4f kTransCol { 0, 0.25f, 0.75f, 0.5f };
  322. constexpr SkColor4f kGrayCol { 0.75f, 0.75f, 0.75f, 0.75f };
  323. struct {
  324. SkColorType fColorType;
  325. GrPixelConfig fConfig;
  326. SkColor4f fColor;
  327. } combinations[] = {
  328. { kAlpha_8_SkColorType, kAlpha_8_GrPixelConfig, kTransCol },
  329. { kRGB_565_SkColorType, kRGB_565_GrPixelConfig, SkColors::kRed },
  330. { kARGB_4444_SkColorType, kRGBA_4444_GrPixelConfig, SkColors::kGreen },
  331. { kRGBA_8888_SkColorType, kRGBA_8888_GrPixelConfig, SkColors::kBlue },
  332. { kRGB_888x_SkColorType, kRGB_888_GrPixelConfig, SkColors::kCyan },
  333. // TODO: readback is busted when alpha = 0.5f (perhaps premul vs. unpremul)
  334. { kBGRA_8888_SkColorType, kBGRA_8888_GrPixelConfig, { 1, 0, 0, 1.0f } },
  335. // TODO: readback is busted when alpha = 0.5f (perhaps premul vs. unpremul)
  336. { kRGBA_1010102_SkColorType, kRGBA_1010102_GrPixelConfig, { 0.5f, 0, 0, 1.0f }},
  337. // The kRGB_101010x_SkColorType has no Ganesh correlate
  338. { kRGB_101010x_SkColorType, kUnknown_GrPixelConfig, { 0, 0.5f, 0, 0.5f }},
  339. { kGray_8_SkColorType, kGray_8_GrPixelConfig, kGrayCol },
  340. { kRGBA_F16Norm_SkColorType, kRGBA_half_Clamped_GrPixelConfig, SkColors::kLtGray },
  341. { kRGBA_F16_SkColorType, kRGBA_half_GrPixelConfig, SkColors::kYellow },
  342. { kRGBA_F32_SkColorType, kRGBA_float_GrPixelConfig, SkColors::kGray },
  343. };
  344. SkASSERT(kLastEnum_SkColorType == SK_ARRAY_COUNT(combinations));
  345. for (auto combo : combinations) {
  346. SkColorType colorType = combo.fColorType;
  347. if (!caps->isConfigTexturable(combo.fConfig)) {
  348. continue;
  349. }
  350. if (GrBackendApi::kMetal == context->backend()) {
  351. // skbug.com/9086 (Metal caps may not be handling RGBA32 correctly)
  352. if (kRGBA_F32_SkColorType == combo.fColorType) {
  353. continue;
  354. }
  355. }
  356. for (auto mipMapped : { GrMipMapped::kNo, GrMipMapped::kYes }) {
  357. if (GrMipMapped::kYes == mipMapped && !caps->mipMapSupport()) {
  358. continue;
  359. }
  360. for (auto renderable : { GrRenderable::kNo, GrRenderable::kYes }) {
  361. if (GrRenderable::kYes == renderable) {
  362. if (kRGB_888x_SkColorType == combo.fColorType) {
  363. // Ganesh can't perform the blends correctly when rendering this format
  364. continue;
  365. }
  366. if (!caps->isConfigRenderable(combo.fConfig)) {
  367. continue;
  368. }
  369. }
  370. {
  371. auto uninitCreateMtd = [colorType](GrContext* context,
  372. GrMipMapped mipMapped,
  373. GrRenderable renderable) {
  374. auto result = context->createBackendTexture(32, 32, colorType,
  375. mipMapped, renderable,
  376. GrProtected::kNo);
  377. check_vk_layout(result, VkLayout::kUndefined);
  378. return result;
  379. };
  380. test_wrapping(context, reporter, uninitCreateMtd,
  381. colorType, mipMapped, renderable);
  382. }
  383. {
  384. // GL has difficulties reading back from these combinations. In particular,
  385. // reading back kGray_8 is a mess.
  386. if (GrBackendApi::kOpenGL == context->backend()) {
  387. if (kAlpha_8_SkColorType == combo.fColorType ||
  388. kGray_8_SkColorType == combo.fColorType) {
  389. continue;
  390. }
  391. } else if (GrBackendApi::kMetal == context->backend()) {
  392. // Not yet implemented for Metal
  393. continue;
  394. }
  395. auto createWithColorMtd = [colorType](GrContext* context,
  396. const SkColor4f& color,
  397. GrMipMapped mipMapped,
  398. GrRenderable renderable) {
  399. auto result = context->createBackendTexture(32, 32, colorType, color,
  400. mipMapped, renderable,
  401. GrProtected::kNo);
  402. check_vk_layout(result, GrRenderable::kYes == renderable
  403. ? VkLayout::kColorAttachmentOptimal
  404. : VkLayout::kReadOnlyOptimal);
  405. return result;
  406. };
  407. test_color_init(context, reporter, createWithColorMtd,
  408. colorType, combo.fColor, mipMapped, renderable);
  409. }
  410. }
  411. }
  412. }
  413. }
  414. ///////////////////////////////////////////////////////////////////////////////
  415. #ifdef SK_GL
  416. #include "src/gpu/gl/GrGLCaps.h"
  417. #include "src/gpu/gl/GrGLDefines.h"
  418. DEF_GPUTEST_FOR_ALL_GL_CONTEXTS(GLBackendAllocationTest, reporter, ctxInfo) {
  419. sk_gpu_test::GLTestContext* glCtx = ctxInfo.glContext();
  420. GrGLStandard standard = glCtx->gl()->fStandard;
  421. GrContext* context = ctxInfo.grContext();
  422. const GrGLCaps* glCaps = static_cast<const GrGLCaps*>(context->priv().caps());
  423. constexpr SkColor4f kTransCol { 0, 0.25f, 0.75f, 0.5f };
  424. constexpr SkColor4f kGrayCol { 0.75f, 0.75f, 0.75f, 0.75f };
  425. struct {
  426. SkColorType fColorType;
  427. GrGLenum fFormat;
  428. // TODO: remove 'fConfig' and directly use 'fFormat' in GrGLCaps::isFormatTexturable
  429. GrPixelConfig fConfig;
  430. SkColor4f fColor;
  431. } combinations[] = {
  432. { kRGBA_8888_SkColorType, GR_GL_RGBA8,
  433. kRGBA_8888_GrPixelConfig, SkColors::kRed },
  434. { kRGBA_8888_SkColorType, GR_GL_SRGB8_ALPHA8,
  435. kSRGBA_8888_GrPixelConfig, SkColors::kRed },
  436. { kRGB_888x_SkColorType, GR_GL_RGBA8,
  437. kRGBA_8888_GrPixelConfig, SkColors::kYellow },
  438. { kRGB_888x_SkColorType, GR_GL_RGB8,
  439. kRGB_888_GrPixelConfig, SkColors::kCyan },
  440. { kBGRA_8888_SkColorType, GR_GL_RGBA8,
  441. kRGBA_8888_GrPixelConfig, SkColors::kBlue },
  442. { kBGRA_8888_SkColorType, GR_GL_BGRA8,
  443. kBGRA_8888_GrPixelConfig, SkColors::kBlue },
  444. { kRGBA_1010102_SkColorType, GR_GL_RGB10_A2,
  445. // TODO: readback is busted when alpha = 0.5f (perhaps premul vs. unpremul)
  446. kRGBA_1010102_GrPixelConfig, { 0.5f, 0, 0, 1.0f }},
  447. { kRGB_565_SkColorType, GR_GL_RGB565,
  448. kRGB_565_GrPixelConfig, SkColors::kRed },
  449. { kARGB_4444_SkColorType, GR_GL_RGBA4,
  450. kRGBA_4444_GrPixelConfig, SkColors::kGreen },
  451. { kAlpha_8_SkColorType, GR_GL_ALPHA8,
  452. kAlpha_8_as_Alpha_GrPixelConfig, kTransCol },
  453. { kAlpha_8_SkColorType, GR_GL_R8,
  454. kAlpha_8_as_Red_GrPixelConfig, kTransCol },
  455. { kGray_8_SkColorType, GR_GL_LUMINANCE8,
  456. kGray_8_as_Lum_GrPixelConfig, kGrayCol },
  457. { kGray_8_SkColorType, GR_GL_R8,
  458. kGray_8_as_Red_GrPixelConfig, kGrayCol },
  459. { kRGBA_F32_SkColorType, GR_GL_RGBA32F,
  460. kRGBA_float_GrPixelConfig, SkColors::kRed },
  461. { kRGBA_F16Norm_SkColorType, GR_GL_RGBA16F,
  462. kRGBA_half_Clamped_GrPixelConfig, SkColors::kLtGray },
  463. { kRGBA_F16_SkColorType, GR_GL_RGBA16F,
  464. kRGBA_half_GrPixelConfig, SkColors::kYellow },
  465. // These backend formats don't have SkColorType equivalents
  466. { kUnknown_SkColorType, GR_GL_RG8,
  467. kRG_88_GrPixelConfig, { 0.5f, 0.5f, 0, 0 }},
  468. { kUnknown_SkColorType, GR_GL_R16F,
  469. kAlpha_half_as_Red_GrPixelConfig, { 1.0f, 0, 0, 0.5f }},
  470. { kUnknown_SkColorType, GR_GL_LUMINANCE16F,
  471. kAlpha_half_as_Lum_GrPixelConfig, kGrayCol },
  472. { kUnknown_SkColorType, GR_GL_COMPRESSED_RGB8_ETC2,
  473. kRGB_ETC1_GrPixelConfig, SkColors::kRed },
  474. { kUnknown_SkColorType, GR_GL_COMPRESSED_ETC1_RGB8,
  475. kRGB_ETC1_GrPixelConfig, SkColors::kRed },
  476. { kUnknown_SkColorType, GR_GL_R16,
  477. kR_16_GrPixelConfig, SkColors::kRed },
  478. { kUnknown_SkColorType, GR_GL_RG16,
  479. kRG_1616_GrPixelConfig, SkColors::kYellow },
  480. // Experimental (for Y416 and mutant P016/P010)
  481. { kUnknown_SkColorType, GR_GL_RGBA16,
  482. kRGBA_16161616_GrPixelConfig, SkColors::kLtGray },
  483. { kUnknown_SkColorType, GR_GL_RG16F,
  484. kRG_half_GrPixelConfig, SkColors::kYellow },
  485. };
  486. for (auto combo : combinations) {
  487. if (kRGB_ETC1_GrPixelConfig == combo.fConfig) {
  488. // RGB8_ETC2/ETC1_RGB8 is an either/or situation
  489. GrGLenum supportedETC1Format = glCaps->configSizedInternalFormat(combo.fConfig);
  490. if (supportedETC1Format != combo.fFormat) {
  491. continue;
  492. }
  493. }
  494. GrBackendFormat format = GrBackendFormat::MakeGL(combo.fFormat, GR_GL_TEXTURE_2D);
  495. if (GR_GL_COMPRESSED_RGB8_ETC2 == combo.fFormat ||
  496. GR_GL_COMPRESSED_ETC1_RGB8 == combo.fFormat) {
  497. // We current disallow uninitialized ETC1 textures in the GL backend
  498. continue;
  499. }
  500. GrColorType grCT = SkColorTypeAndFormatToGrColorType(glCaps, combo.fColorType, format);
  501. if (GrColorType::kUnknown == grCT) {
  502. continue;
  503. }
  504. if (!glCaps->isFormatTexturable(grCT, format)) {
  505. continue;
  506. }
  507. if (kBGRA_8888_SkColorType == combo.fColorType) {
  508. if (GR_GL_RGBA8 == combo.fFormat && kGL_GrGLStandard != standard) {
  509. continue;
  510. }
  511. if (GR_GL_BGRA8 == combo.fFormat && kGL_GrGLStandard == standard) {
  512. continue;
  513. }
  514. }
  515. for (auto mipMapped : { GrMipMapped::kNo, GrMipMapped::kYes }) {
  516. if (GrMipMapped::kYes == mipMapped && !glCaps->mipMapSupport()) {
  517. continue;
  518. }
  519. for (auto renderable : { GrRenderable::kNo, GrRenderable::kYes }) {
  520. if (GrRenderable::kYes == renderable) {
  521. if (kRGB_888x_SkColorType == combo.fColorType) {
  522. // Ganesh can't perform the blends correctly when rendering this format
  523. continue;
  524. }
  525. if (!glCaps->isConfigRenderable(combo.fConfig)) {
  526. continue;
  527. }
  528. }
  529. {
  530. auto uninitCreateMtd = [format](GrContext* context,
  531. GrMipMapped mipMapped,
  532. GrRenderable renderable) {
  533. return context->createBackendTexture(32, 32, format,
  534. mipMapped, renderable,
  535. GrProtected::kNo);
  536. };
  537. test_wrapping(context, reporter, uninitCreateMtd,
  538. combo.fColorType, mipMapped, renderable);
  539. }
  540. {
  541. // GL has difficulties reading back from these combinations
  542. if (kAlpha_8_SkColorType == combo.fColorType) {
  543. continue;
  544. }
  545. if (GrRenderable::kYes != renderable) {
  546. continue;
  547. }
  548. auto createWithColorMtd = [format](GrContext* context,
  549. const SkColor4f& color,
  550. GrMipMapped mipMapped,
  551. GrRenderable renderable) {
  552. return context->createBackendTexture(32, 32, format, color,
  553. mipMapped, renderable,
  554. GrProtected::kNo);
  555. };
  556. test_color_init(context, reporter, createWithColorMtd,
  557. combo.fColorType, combo.fColor, mipMapped, renderable);
  558. }
  559. }
  560. }
  561. }
  562. }
  563. #endif
  564. ///////////////////////////////////////////////////////////////////////////////
  565. #ifdef SK_VULKAN
  566. #include "src/gpu/vk/GrVkCaps.h"
  567. DEF_GPUTEST_FOR_VULKAN_CONTEXT(VkBackendAllocationTest, reporter, ctxInfo) {
  568. GrContext* context = ctxInfo.grContext();
  569. const GrVkCaps* vkCaps = static_cast<const GrVkCaps*>(context->priv().caps());
  570. constexpr SkColor4f kTransCol { 0, 0.25f, 0.75f, 0.5f };
  571. constexpr SkColor4f kGrayCol { 0.75f, 0.75f, 0.75f, 0.75f };
  572. struct {
  573. SkColorType fColorType;
  574. VkFormat fFormat;
  575. SkColor4f fColor;
  576. } combinations[] = {
  577. { kRGBA_8888_SkColorType, VK_FORMAT_R8G8B8A8_UNORM, SkColors::kRed },
  578. { kRGBA_8888_SkColorType, VK_FORMAT_R8G8B8A8_SRGB, SkColors::kRed },
  579. // In this configuration (i.e., an RGB_888x colortype with an RGBA8 backing format),
  580. // there is nothing to tell Skia to make the provided color opaque. Clients will need
  581. // to provide an opaque initialization color in this case.
  582. { kRGB_888x_SkColorType, VK_FORMAT_R8G8B8A8_UNORM, SkColors::kYellow },
  583. { kRGB_888x_SkColorType, VK_FORMAT_R8G8B8_UNORM, SkColors::kCyan },
  584. { kBGRA_8888_SkColorType, VK_FORMAT_B8G8R8A8_UNORM, SkColors::kBlue },
  585. { kRGBA_1010102_SkColorType, VK_FORMAT_A2B10G10R10_UNORM_PACK32, { 0.5f, 0, 0, 1.0f } },
  586. { kRGB_565_SkColorType, VK_FORMAT_R5G6B5_UNORM_PACK16, SkColors::kRed },
  587. { kARGB_4444_SkColorType, VK_FORMAT_R4G4B4A4_UNORM_PACK16, SkColors::kCyan },
  588. { kARGB_4444_SkColorType, VK_FORMAT_B4G4R4A4_UNORM_PACK16, SkColors::kYellow },
  589. { kAlpha_8_SkColorType, VK_FORMAT_R8_UNORM, kTransCol },
  590. // In this config (i.e., a Gray8 color type with an R8 backing format), there is nothing
  591. // to tell Skia this isn't an Alpha8 color type (so it will initialize the texture with
  592. // the alpha channel of the color). Clients should, in general, fill all the channels
  593. // of the provided color with the same value in such cases.
  594. { kGray_8_SkColorType, VK_FORMAT_R8_UNORM, kGrayCol },
  595. { kRGBA_F32_SkColorType, VK_FORMAT_R32G32B32A32_SFLOAT, SkColors::kRed },
  596. { kRGBA_F16Norm_SkColorType, VK_FORMAT_R16G16B16A16_SFLOAT, SkColors::kLtGray },
  597. { kRGBA_F16_SkColorType, VK_FORMAT_R16G16B16A16_SFLOAT, SkColors::kYellow },
  598. // These backend formats don't have SkColorType equivalents
  599. { kUnknown_SkColorType, VK_FORMAT_R8G8_UNORM, { 0.5f, 0.5f, 0, 0 } },
  600. { kUnknown_SkColorType, VK_FORMAT_R16_SFLOAT, { 1.0f, 0, 0, 0.5f } },
  601. { kUnknown_SkColorType, VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK, SkColors::kRed },
  602. { kUnknown_SkColorType, VK_FORMAT_R16_UNORM, SkColors::kRed },
  603. { kUnknown_SkColorType, VK_FORMAT_R16G16_UNORM, SkColors::kYellow },
  604. // Experimental (for Y416 and mutant P016/P010)
  605. { kUnknown_SkColorType, VK_FORMAT_R16G16B16A16_UNORM, SkColors::kLtGray },
  606. { kUnknown_SkColorType, VK_FORMAT_R16G16_SFLOAT, SkColors::kYellow },
  607. };
  608. for (auto combo : combinations) {
  609. if (!vkCaps->isVkFormatTexturable(combo.fFormat)) {
  610. continue;
  611. }
  612. GrBackendFormat format = GrBackendFormat::MakeVk(combo.fFormat);
  613. for (auto mipMapped : { GrMipMapped::kNo, GrMipMapped::kYes }) {
  614. if (GrMipMapped::kYes == mipMapped && !vkCaps->mipMapSupport()) {
  615. continue;
  616. }
  617. for (auto renderable : { GrRenderable::kNo, GrRenderable::kYes }) {
  618. if (GrRenderable::kYes == renderable) {
  619. if (kRGB_888x_SkColorType == combo.fColorType) {
  620. // Ganesh can't perform the blends correctly when rendering this format
  621. continue;
  622. }
  623. if (!vkCaps->isFormatRenderable(combo.fFormat)) {
  624. continue;
  625. }
  626. }
  627. {
  628. auto uninitCreateMtd = [format](GrContext* context,
  629. GrMipMapped mipMapped,
  630. GrRenderable renderable) {
  631. GrBackendTexture beTex = context->createBackendTexture(32, 32, format,
  632. mipMapped,
  633. renderable,
  634. GrProtected::kNo);
  635. check_vk_layout(beTex, VkLayout::kUndefined);
  636. return beTex;
  637. };
  638. test_wrapping(context, reporter, uninitCreateMtd,
  639. combo.fColorType, mipMapped, renderable);
  640. }
  641. {
  642. // We're creating backend textures without specifying a color type "view" of
  643. // them at the public API level. Therefore, Ganesh will not apply any swizzles
  644. // before writing the color to the texture. However, our validation code does
  645. // rely on interpreting the texture contents via a SkColorType and therefore
  646. // swizzles may be applied during the read step.
  647. // Ideally we'd update our validation code to use a "raw" read that doesn't
  648. // impose a color type but for now we just munge the data we upload to match the
  649. // expectation.
  650. GrSwizzle swizzle;
  651. switch (combo.fColorType) {
  652. case kAlpha_8_SkColorType:
  653. SkASSERT(combo.fFormat == VK_FORMAT_R8_UNORM);
  654. swizzle = GrSwizzle("aaaa");
  655. break;
  656. case kARGB_4444_SkColorType:
  657. if (combo.fFormat == VK_FORMAT_B4G4R4A4_UNORM_PACK16) {
  658. swizzle = GrSwizzle("bgra");
  659. }
  660. break;
  661. default:
  662. swizzle = GrSwizzle("rgba");
  663. break;
  664. }
  665. auto createWithColorMtd = [format, swizzle](GrContext* context,
  666. const SkColor4f& color,
  667. GrMipMapped mipMapped,
  668. GrRenderable renderable) {
  669. auto swizzledColor = swizzle.applyTo(color);
  670. GrBackendTexture beTex = context->createBackendTexture(32, 32, format,
  671. swizzledColor,
  672. mipMapped,
  673. renderable,
  674. GrProtected::kNo);
  675. check_vk_layout(beTex, GrRenderable::kYes == renderable
  676. ? VkLayout::kColorAttachmentOptimal
  677. : VkLayout::kReadOnlyOptimal);
  678. return beTex;
  679. };
  680. test_color_init(context, reporter, createWithColorMtd,
  681. combo.fColorType, combo.fColor, mipMapped, renderable);
  682. }
  683. }
  684. }
  685. }
  686. }
  687. #endif