GrDataUtils.cpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600
  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 "src/gpu/GrDataUtils.h"
  8. #include "src/core/SkColorSpaceXformSteps.h"
  9. #include "src/core/SkTLazy.h"
  10. #include "src/core/SkTraceEvent.h"
  11. #include "src/core/SkUtils.h"
  12. #include "src/gpu/GrColor.h"
  13. struct ETC1Block {
  14. uint32_t fHigh;
  15. uint32_t fLow;
  16. };
  17. static const int kNumModifierTables = 8;
  18. static const int kNumPixelIndices = 4;
  19. // The index of each row in this table is the ETC1 table codeword
  20. // The index of each column in this table is the ETC1 pixel index value
  21. static const int kModifierTables[kNumModifierTables][kNumPixelIndices] = {
  22. /* 0 */ { 2, 8, -2, -8 },
  23. /* 1 */ { 5, 17, -5, -17 },
  24. /* 2 */ { 9, 29, -9, -29 },
  25. /* 3 */ { 13, 42, -13, -42 },
  26. /* 4 */ { 18, 60, -18, -60 },
  27. /* 5 */ { 24, 80, -24, -80 },
  28. /* 6 */ { 33, 106, -33, -106 },
  29. /* 7 */ { 47, 183, -47, -183 }
  30. };
  31. static inline int convert_5To8(int b) {
  32. int c = b & 0x1f;
  33. return (c << 3) | (c >> 2);
  34. }
  35. // Evaluate one of the entries in 'kModifierTables' to see how close it can get (r8,g8,b8) to
  36. // the original color (rOrig, gOrib, bOrig).
  37. static int test_table_entry(int rOrig, int gOrig, int bOrig,
  38. int r8, int g8, int b8,
  39. int table, int offset) {
  40. SkASSERT(0 <= table && table < 8);
  41. SkASSERT(0 <= offset && offset < 4);
  42. r8 = SkTPin<uint8_t>(r8 + kModifierTables[table][offset], 0, 255);
  43. g8 = SkTPin<uint8_t>(g8 + kModifierTables[table][offset], 0, 255);
  44. b8 = SkTPin<uint8_t>(b8 + kModifierTables[table][offset], 0, 255);
  45. return SkTAbs(rOrig - r8) + SkTAbs(gOrig - g8) + SkTAbs(bOrig - b8);
  46. }
  47. // Create an ETC1 compressed block that is filled with 'col'
  48. static void create_etc1_block(SkColor col, ETC1Block* block) {
  49. block->fHigh = 0;
  50. block->fLow = 0;
  51. int rOrig = SkColorGetR(col);
  52. int gOrig = SkColorGetG(col);
  53. int bOrig = SkColorGetB(col);
  54. int r5 = SkMulDiv255Round(31, rOrig);
  55. int g5 = SkMulDiv255Round(31, gOrig);
  56. int b5 = SkMulDiv255Round(31, bOrig);
  57. int r8 = convert_5To8(r5);
  58. int g8 = convert_5To8(g5);
  59. int b8 = convert_5To8(b5);
  60. // We always encode solid color textures as 555 + zero diffs
  61. block->fHigh |= (r5 << 27) | (g5 << 19) | (b5 << 11) | 0x2;
  62. int bestTableIndex = 0, bestPixelIndex = 0;
  63. int bestSoFar = 1024;
  64. for (int tableIndex = 0; tableIndex < kNumModifierTables; ++tableIndex) {
  65. for (int pixelIndex = 0; pixelIndex < kNumPixelIndices; ++pixelIndex) {
  66. int score = test_table_entry(rOrig, gOrig, bOrig, r8, g8, b8,
  67. tableIndex, pixelIndex);
  68. if (bestSoFar > score) {
  69. bestSoFar = score;
  70. bestTableIndex = tableIndex;
  71. bestPixelIndex = pixelIndex;
  72. }
  73. }
  74. }
  75. block->fHigh |= (bestTableIndex << 5) | (bestTableIndex << 2);
  76. for (int i = 0; i < 16; ++i) {
  77. block->fLow |= bestPixelIndex << 2*i;
  78. }
  79. }
  80. static int num_ETC1_blocks(int w, int h) {
  81. if (w < 4) {
  82. w = 1;
  83. } else {
  84. SkASSERT((w & 3) == 0);
  85. w >>= 2;
  86. }
  87. if (h < 4) {
  88. h = 1;
  89. } else {
  90. SkASSERT((h & 3) == 0);
  91. h >>= 2;
  92. }
  93. return w * h;
  94. }
  95. size_t GrCompressedDataSize(SkImage::CompressionType type, int width, int height) {
  96. switch (type) {
  97. case SkImage::kETC1_CompressionType:
  98. int numBlocks = num_ETC1_blocks(width, height);
  99. return numBlocks * sizeof(ETC1Block);
  100. }
  101. SK_ABORT("Unexpected compression type");
  102. return 0;
  103. }
  104. // Fill in 'dest' with ETC1 blocks derived from 'colorf'
  105. static void fillin_ETC1_with_color(int width, int height, const SkColor4f& colorf, void* dest) {
  106. SkColor color = colorf.toSkColor();
  107. ETC1Block block;
  108. create_etc1_block(color, &block);
  109. int numBlocks = num_ETC1_blocks(width, height);
  110. for (int i = 0; i < numBlocks; ++i) {
  111. ((ETC1Block*)dest)[i] = block;
  112. }
  113. }
  114. // Fill in the width x height 'dest' with the munged version of 'colorf' that matches 'config'
  115. static bool fill_buffer_with_color(GrPixelConfig config, int width, int height,
  116. const SkColor4f& colorf, void* dest) {
  117. SkASSERT(kRGB_ETC1_GrPixelConfig != config);
  118. GrColor color = colorf.toBytes_RGBA();
  119. uint8_t r = GrColorUnpackR(color);
  120. uint8_t g = GrColorUnpackG(color);
  121. uint8_t b = GrColorUnpackB(color);
  122. uint8_t a = GrColorUnpackA(color);
  123. switch (config) {
  124. case kAlpha_8_GrPixelConfig: // fall through
  125. case kAlpha_8_as_Alpha_GrPixelConfig: // fall through
  126. case kAlpha_8_as_Red_GrPixelConfig: {
  127. memset(dest, a, width * height);
  128. break;
  129. }
  130. case kGray_8_GrPixelConfig: // fall through
  131. case kGray_8_as_Lum_GrPixelConfig: // fall through
  132. case kGray_8_as_Red_GrPixelConfig: {
  133. uint8_t gray8 = SkComputeLuminance(r, g, b);
  134. memset(dest, gray8, width * height);
  135. break;
  136. }
  137. case kRGB_565_GrPixelConfig: {
  138. uint16_t rgb565 = SkPack888ToRGB16(r, g, b);
  139. sk_memset16((uint16_t*) dest, rgb565, width * height);
  140. break;
  141. }
  142. case kRGBA_4444_GrPixelConfig: {
  143. uint8_t r4 = (r >> 4) & 0xF;
  144. uint8_t g4 = (g >> 4) & 0xF;
  145. uint8_t b4 = (b >> 4) & 0xF;
  146. uint8_t a4 = (a >> 4) & 0xF;
  147. uint16_t rgba4444 = r4 << SK_R4444_SHIFT | g4 << SK_G4444_SHIFT |
  148. b4 << SK_B4444_SHIFT | a4 << SK_A4444_SHIFT;
  149. sk_memset16((uint16_t*) dest, rgba4444, width * height);
  150. break;
  151. }
  152. case kRGBA_8888_GrPixelConfig: {
  153. sk_memset32((uint32_t *) dest, color, width * height);
  154. break;
  155. }
  156. case kRGB_888_GrPixelConfig: {
  157. uint8_t* dest8 = (uint8_t*) dest;
  158. for (int i = 0; i < width * height; ++i, dest8 += 3) {
  159. dest8[0] = r;
  160. dest8[1] = g;
  161. dest8[2] = b;
  162. }
  163. break;
  164. }
  165. case kRGB_888X_GrPixelConfig: {
  166. GrColor opaque = GrColorPackRGBA(r, g, b, 0xFF);
  167. sk_memset32((uint32_t *) dest, opaque, width * height);
  168. break;
  169. }
  170. case kRG_88_GrPixelConfig: {
  171. uint16_t rg88 = (r << 8) | g;
  172. sk_memset16((uint16_t*) dest, rg88, width * height);
  173. break;
  174. }
  175. case kBGRA_8888_GrPixelConfig: {
  176. GrColor swizzled = GrColorPackRGBA(b, g, r, a);
  177. sk_memset32((uint32_t *) dest, swizzled, width * height);
  178. break;
  179. }
  180. case kSRGBA_8888_GrPixelConfig: {
  181. sk_memset32((uint32_t *) dest, color, width * height);
  182. break;
  183. }
  184. case kRGBA_1010102_GrPixelConfig: {
  185. uint32_t r10 = SkScalarRoundToInt(colorf.fR * 1023.0f);
  186. uint32_t g10 = SkScalarRoundToInt(colorf.fG * 1023.0f);
  187. uint32_t b10 = SkScalarRoundToInt(colorf.fB * 1023.0f);
  188. uint8_t a2 = SkScalarRoundToInt(colorf.fA * 3.0f);
  189. uint32_t rgba1010102 = a2 << 30 | b10 << 20 | g10 << 10 | r10;
  190. sk_memset32((uint32_t *) dest, rgba1010102, width * height);
  191. break;
  192. }
  193. case kRGBA_float_GrPixelConfig: {
  194. SkColor4f* destColor = (SkColor4f*) dest;
  195. for (int i = 0; i < width * height; ++i) {
  196. destColor[i] = colorf;
  197. }
  198. break;
  199. }
  200. case kAlpha_half_as_Lum_GrPixelConfig: // fall through
  201. case kAlpha_half_as_Red_GrPixelConfig: // fall through
  202. case kAlpha_half_GrPixelConfig: {
  203. SkHalf alphaHalf = SkFloatToHalf(colorf.fA);
  204. sk_memset16((uint16_t *) dest, alphaHalf, width * height);
  205. break;
  206. }
  207. case kRGBA_half_GrPixelConfig: // fall through
  208. case kRGBA_half_Clamped_GrPixelConfig: {
  209. uint64_t rHalf = SkFloatToHalf(colorf.fR);
  210. uint64_t gHalf = SkFloatToHalf(colorf.fG);
  211. uint64_t bHalf = SkFloatToHalf(colorf.fB);
  212. uint64_t aHalf = SkFloatToHalf(colorf.fA);
  213. uint64_t rgbaHalf = (aHalf << 48) | (bHalf << 32) | (gHalf << 16) | rHalf;
  214. sk_memset64((uint64_t *) dest, rgbaHalf, width * height);
  215. break;
  216. }
  217. case kR_16_GrPixelConfig: {
  218. uint16_t r16 = SkScalarRoundToInt(colorf.fR * 65535.0f);
  219. sk_memset16((uint16_t*) dest, r16, width * height);
  220. break;
  221. }
  222. case kRG_1616_GrPixelConfig: {
  223. uint16_t r16 = SkScalarRoundToInt(colorf.fR * 65535.0f);
  224. uint16_t g16 = SkScalarRoundToInt(colorf.fG * 65535.0f);
  225. uint32_t rg1616 = r16 << 16 | g16;
  226. sk_memset32((uint32_t*) dest, rg1616, width * height);
  227. break;
  228. }
  229. // Experimental (for Y416 and mutant P016/P010)
  230. case kRGBA_16161616_GrPixelConfig: {
  231. uint64_t r16 = SkScalarRoundToInt(colorf.fR * 65535.0f);
  232. uint64_t g16 = SkScalarRoundToInt(colorf.fG * 65535.0f);
  233. uint64_t b16 = SkScalarRoundToInt(colorf.fB * 65535.0f);
  234. uint64_t a16 = SkScalarRoundToInt(colorf.fA * 65535.0f);
  235. uint64_t rgba16161616 = (a16 << 48) | (b16 << 32) | (g16 << 16) | r16;
  236. sk_memset64((uint64_t*) dest, rgba16161616, width * height);
  237. break;
  238. }
  239. case kRG_half_GrPixelConfig: {
  240. uint32_t rHalf = SkFloatToHalf(colorf.fR);
  241. uint32_t gHalf = SkFloatToHalf(colorf.fG);
  242. uint32_t rgHalf = (rHalf << 16) | gHalf;
  243. sk_memset32((uint32_t *) dest, rgHalf, width * height);
  244. break;
  245. }
  246. default:
  247. return false;
  248. break;
  249. }
  250. return true;
  251. }
  252. size_t GrComputeTightCombinedBufferSize(size_t bytesPerPixel, int baseWidth, int baseHeight,
  253. SkTArray<size_t>* individualMipOffsets, int mipLevelCount) {
  254. SkASSERT(individualMipOffsets && !individualMipOffsets->count());
  255. SkASSERT(mipLevelCount >= 1);
  256. individualMipOffsets->push_back(0);
  257. size_t combinedBufferSize = baseWidth * bytesPerPixel * baseHeight;
  258. int currentWidth = baseWidth;
  259. int currentHeight = baseHeight;
  260. // The Vulkan spec for copying a buffer to an image requires that the alignment must be at
  261. // least 4 bytes and a multiple of the bytes per pixel of the image config.
  262. SkASSERT(bytesPerPixel == 1 || bytesPerPixel == 2 || bytesPerPixel == 3 ||
  263. bytesPerPixel == 4 || bytesPerPixel == 8 || bytesPerPixel == 16);
  264. int desiredAlignment = (bytesPerPixel == 3) ? 12 : (bytesPerPixel > 4 ? bytesPerPixel : 4);
  265. for (int currentMipLevel = 1; currentMipLevel < mipLevelCount; ++currentMipLevel) {
  266. currentWidth = SkTMax(1, currentWidth / 2);
  267. currentHeight = SkTMax(1, currentHeight / 2);
  268. size_t trimmedSize = currentWidth * bytesPerPixel * currentHeight;
  269. const size_t alignmentDiff = combinedBufferSize % desiredAlignment;
  270. if (alignmentDiff != 0) {
  271. combinedBufferSize += desiredAlignment - alignmentDiff;
  272. }
  273. SkASSERT((0 == combinedBufferSize % 4) && (0 == combinedBufferSize % bytesPerPixel));
  274. individualMipOffsets->push_back(combinedBufferSize);
  275. combinedBufferSize += trimmedSize;
  276. }
  277. SkASSERT(individualMipOffsets->count() == mipLevelCount);
  278. return combinedBufferSize;
  279. }
  280. void GrFillInData(GrPixelConfig config, int baseWidth, int baseHeight,
  281. const SkTArray<size_t>& individualMipOffsets, char* dstPixels,
  282. const SkColor4f& colorf) {
  283. TRACE_EVENT0("skia.gpu", TRACE_FUNC);
  284. SkASSERT(!GrPixelConfigIsCompressed(config));
  285. int mipLevels = individualMipOffsets.count();
  286. int currentWidth = baseWidth;
  287. int currentHeight = baseHeight;
  288. for (int currentMipLevel = 0; currentMipLevel < mipLevels; ++currentMipLevel) {
  289. size_t offset = individualMipOffsets[currentMipLevel];
  290. fill_buffer_with_color(config, currentWidth, currentHeight, colorf, &(dstPixels[offset]));
  291. currentWidth = SkTMax(1, currentWidth / 2);
  292. currentHeight = SkTMax(1, currentHeight / 2);
  293. }
  294. }
  295. void GrFillInCompressedData(SkImage::CompressionType type, int baseWidth, int baseHeight,
  296. char* dstPixels, const SkColor4f& colorf) {
  297. TRACE_EVENT0("skia.gpu", TRACE_FUNC);
  298. int currentWidth = baseWidth;
  299. int currentHeight = baseHeight;
  300. if (SkImage::kETC1_CompressionType == type) {
  301. fillin_ETC1_with_color(currentWidth, currentHeight, colorf, dstPixels);
  302. }
  303. }
  304. static GrSwizzle get_load_and_get_swizzle(GrColorType ct, SkRasterPipeline::StockStage* load,
  305. bool* isNormalized, bool* isSRGB) {
  306. GrSwizzle swizzle("rgba");
  307. *isNormalized = true;
  308. *isSRGB = false;
  309. switch (ct) {
  310. case GrColorType::kAlpha_8: *load = SkRasterPipeline::load_a8; break;
  311. case GrColorType::kBGR_565: *load = SkRasterPipeline::load_565; break;
  312. case GrColorType::kABGR_4444: *load = SkRasterPipeline::load_4444; break;
  313. case GrColorType::kRGBA_8888: *load = SkRasterPipeline::load_8888; break;
  314. case GrColorType::kRG_88: *load = SkRasterPipeline::load_rg88; break;
  315. case GrColorType::kRGBA_1010102: *load = SkRasterPipeline::load_1010102; break;
  316. case GrColorType::kAlpha_F16: *load = SkRasterPipeline::load_af16; break;
  317. case GrColorType::kRGBA_F16_Clamped: *load = SkRasterPipeline::load_f16; break;
  318. case GrColorType::kRG_1616: *load = SkRasterPipeline::load_rg1616; break;
  319. case GrColorType::kRGBA_16161616: *load = SkRasterPipeline::load_16161616; break;
  320. case GrColorType::kRGBA_8888_SRGB: *load = SkRasterPipeline::load_8888;
  321. *isSRGB = true;
  322. break;
  323. case GrColorType::kRG_F16: *load = SkRasterPipeline::load_rgf16;
  324. *isNormalized = false;
  325. break;
  326. case GrColorType::kRGBA_F16: *load = SkRasterPipeline::load_f16;
  327. *isNormalized = false;
  328. break;
  329. case GrColorType::kRGBA_F32: *load = SkRasterPipeline::load_f32;
  330. *isNormalized = false;
  331. break;
  332. case GrColorType::kR_16: *load = SkRasterPipeline::load_a16;
  333. swizzle = GrSwizzle("a001");
  334. break;
  335. case GrColorType::kGray_8: *load = SkRasterPipeline::load_a8;
  336. swizzle = GrSwizzle("aaa1");
  337. break;
  338. case GrColorType::kBGRA_8888: *load = SkRasterPipeline::load_8888;
  339. swizzle = GrSwizzle("bgra");
  340. break;
  341. case GrColorType::kRGB_888x: *load = SkRasterPipeline::load_8888;
  342. swizzle = GrSwizzle("rgb1");
  343. break;
  344. case GrColorType::kUnknown:
  345. SK_ABORT("unexpected CT");
  346. }
  347. return swizzle;
  348. }
  349. static GrSwizzle get_dst_swizzle_and_store(GrColorType ct, SkRasterPipeline::StockStage* store,
  350. bool* isNormalized, bool* isSRGB) {
  351. GrSwizzle swizzle("rgba");
  352. *isNormalized = true;
  353. *isSRGB = false;
  354. switch (ct) {
  355. case GrColorType::kAlpha_8: *store = SkRasterPipeline::store_a8; break;
  356. case GrColorType::kBGR_565: *store = SkRasterPipeline::store_565; break;
  357. case GrColorType::kABGR_4444: *store = SkRasterPipeline::store_4444; break;
  358. case GrColorType::kRGBA_8888: *store = SkRasterPipeline::store_8888; break;
  359. case GrColorType::kRG_88: *store = SkRasterPipeline::store_rg88; break;
  360. case GrColorType::kRGBA_1010102: *store = SkRasterPipeline::store_1010102; break;
  361. case GrColorType::kRGBA_F16_Clamped: *store = SkRasterPipeline::store_f16; break;
  362. case GrColorType::kRG_1616: *store = SkRasterPipeline::store_rg1616; break;
  363. case GrColorType::kRGBA_16161616: *store = SkRasterPipeline::store_16161616; break;
  364. case GrColorType::kRGBA_8888_SRGB: *store = SkRasterPipeline::store_8888;
  365. *isSRGB = true;
  366. break;
  367. case GrColorType::kRG_F16: *store = SkRasterPipeline::store_rgf16;
  368. *isNormalized = false;
  369. break;
  370. case GrColorType::kAlpha_F16: *store = SkRasterPipeline::store_af16;
  371. *isNormalized = false;
  372. break;
  373. case GrColorType::kRGBA_F16: *store = SkRasterPipeline::store_f16;
  374. *isNormalized = false;
  375. break;
  376. case GrColorType::kRGBA_F32: *store = SkRasterPipeline::store_f32;
  377. *isNormalized = false;
  378. break;
  379. case GrColorType::kR_16: swizzle = GrSwizzle("000r");
  380. *store = SkRasterPipeline::store_a16;
  381. break;
  382. case GrColorType::kBGRA_8888: swizzle = GrSwizzle("bgra");
  383. *store = SkRasterPipeline::store_8888;
  384. break;
  385. case GrColorType::kRGB_888x: swizzle = GrSwizzle("rgb1");
  386. *store = SkRasterPipeline::store_8888;
  387. break;
  388. case GrColorType::kGray_8: // not currently supported as output
  389. case GrColorType::kUnknown:
  390. SK_ABORT("unexpected CT");
  391. }
  392. return swizzle;
  393. }
  394. static inline void append_clamp_gamut(SkRasterPipeline* pipeline) {
  395. // SkRasterPipeline may not know our color type and also doesn't like caller to directly
  396. // append clamp_gamut. Fake it out.
  397. static SkImageInfo fakeII = SkImageInfo::MakeN32Premul(1, 1);
  398. pipeline->append_gamut_clamp_if_normalized(fakeII);
  399. }
  400. bool GrConvertPixels(const GrPixelInfo& dstInfo, void* dst, size_t dstRB,
  401. const GrPixelInfo& srcInfo, const void* src, size_t srcRB,
  402. bool flipY, GrSwizzle swizzle) {
  403. TRACE_EVENT0("skia.gpu", TRACE_FUNC);
  404. if (!srcInfo.isValid() || !dstInfo.isValid()) {
  405. return false;
  406. }
  407. if (!src || !dst) {
  408. return false;
  409. }
  410. if (dstInfo.width() != srcInfo.width() || srcInfo.height() != dstInfo.height()) {
  411. return false;
  412. }
  413. if (GrColorTypeComponentFlags(dstInfo.colorType()) & kGray_SkColorTypeComponentFlag) {
  414. // We don't currently support conversion to Gray.
  415. return false;
  416. }
  417. if (dstRB < dstInfo.minRowBytes() || srcRB < srcInfo.minRowBytes()) {
  418. return false;
  419. }
  420. size_t srcBpp = srcInfo.bpp();
  421. size_t dstBpp = dstInfo.bpp();
  422. // SkRasterPipeline operates on row-pixels not row-bytes.
  423. SkASSERT(dstRB % dstBpp == 0);
  424. SkASSERT(srcRB % srcBpp == 0);
  425. SkRasterPipeline::StockStage load;
  426. bool srcIsNormalized;
  427. bool srcIsSRGB;
  428. auto loadSwizzle = get_load_and_get_swizzle(srcInfo.colorType(), &load, &srcIsNormalized,
  429. &srcIsSRGB);
  430. loadSwizzle = GrSwizzle::Concat(loadSwizzle, swizzle);
  431. SkRasterPipeline::StockStage store;
  432. bool dstIsNormalized;
  433. bool dstIsSRGB;
  434. auto storeSwizzle = get_dst_swizzle_and_store(dstInfo.colorType(), &store, &dstIsNormalized,
  435. &dstIsSRGB);
  436. bool premul = srcInfo.alphaType() == kUnpremul_SkAlphaType &&
  437. dstInfo.alphaType() == kPremul_SkAlphaType;
  438. bool unpremul = srcInfo.alphaType() == kPremul_SkAlphaType &&
  439. dstInfo.alphaType() == kUnpremul_SkAlphaType;
  440. bool alphaOrCSConversion =
  441. premul || unpremul || !SkColorSpace::Equals(srcInfo.colorSpace(), dstInfo.colorSpace());
  442. bool clampGamut;
  443. SkTLazy<SkColorSpaceXformSteps> steps;
  444. GrSwizzle loadStoreSwizzle;
  445. if (alphaOrCSConversion) {
  446. steps.init(srcInfo.colorSpace(), srcInfo.alphaType(),
  447. dstInfo.colorSpace(), dstInfo.alphaType());
  448. clampGamut = dstIsNormalized && dstInfo.alphaType() == kPremul_SkAlphaType;
  449. } else {
  450. clampGamut =
  451. dstIsNormalized && !srcIsNormalized && dstInfo.alphaType() == kPremul_SkAlphaType;
  452. if (!clampGamut) {
  453. loadStoreSwizzle = GrSwizzle::Concat(loadSwizzle, storeSwizzle);
  454. }
  455. }
  456. int cnt = 1;
  457. int height = srcInfo.height();
  458. SkRasterPipeline_MemoryCtx srcCtx{const_cast<void*>(src), SkToInt(srcRB / srcBpp)},
  459. dstCtx{ dst , SkToInt(dstRB / dstBpp)};
  460. if (flipY) {
  461. // It *almost* works to point the src at the last row and negate the stride and run the
  462. // whole rectangle. However, SkRasterPipeline::run()'s control loop uses size_t loop
  463. // variables so it winds up relying on unsigned overflow math. It works out in practice
  464. // but UBSAN says "no!" as it's technically undefined and in theory a compiler could emit
  465. // code that didn't do what is intended. So we go one row at a time. :(
  466. srcCtx.pixels = static_cast<char*>(srcCtx.pixels) + srcRB * (height - 1);
  467. std::swap(cnt, height);
  468. }
  469. bool hasConversion = alphaOrCSConversion || clampGamut;
  470. if (srcIsSRGB && dstIsSRGB && !hasConversion) {
  471. // No need to convert from srgb if we are just going to immediately convert it back.
  472. srcIsSRGB = dstIsSRGB = false;
  473. }
  474. hasConversion = hasConversion || srcIsSRGB || dstIsSRGB;
  475. for (int i = 0; i < cnt; ++i) {
  476. SkRasterPipeline_<256> pipeline;
  477. pipeline.append(load, &srcCtx);
  478. if (hasConversion) {
  479. loadSwizzle.apply(&pipeline);
  480. if (srcIsSRGB) {
  481. pipeline.append(SkRasterPipeline::from_srgb);
  482. }
  483. if (alphaOrCSConversion) {
  484. steps->apply(&pipeline, srcIsNormalized);
  485. }
  486. if (clampGamut) {
  487. append_clamp_gamut(&pipeline);
  488. }
  489. // If we add support for storing to Gray we would add a luminance to alpha conversion
  490. // here. We also wouldn't then need a to_srgb stage after since it would have not effect
  491. // on the alpha channel. It would also mean we have an SRGB Gray color type which
  492. // doesn't exist currently.
  493. if (dstIsSRGB) {
  494. pipeline.append(SkRasterPipeline::to_srgb);
  495. }
  496. storeSwizzle.apply(&pipeline);
  497. } else {
  498. loadStoreSwizzle.apply(&pipeline);
  499. }
  500. pipeline.append(store, &dstCtx);
  501. pipeline.run(0, 0, srcInfo.width(), height);
  502. srcCtx.pixels = static_cast<char*>(srcCtx.pixels) - srcRB;
  503. dstCtx.pixels = static_cast<char*>(dstCtx.pixels) + dstRB;
  504. }
  505. return true;
  506. }
  507. GrColorType SkColorTypeAndFormatToGrColorType(const GrCaps* caps,
  508. SkColorType skCT,
  509. const GrBackendFormat& format) {
  510. GrColorType grCT = SkColorTypeToGrColorType(skCT);
  511. // Until we support SRGB in the SkColorType we have to do this manual check here to make sure
  512. // we use the correct GrColorType.
  513. if (caps->isFormatSRGB(format)) {
  514. if (grCT != GrColorType::kRGBA_8888) {
  515. return GrColorType::kUnknown;
  516. }
  517. grCT = GrColorType::kRGBA_8888_SRGB;
  518. }
  519. return grCT;
  520. }