SDL_pixels.c 47 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532
  1. /*
  2. Simple DirectMedia Layer
  3. Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
  4. This software is provided 'as-is', without any express or implied
  5. warranty. In no event will the authors be held liable for any damages
  6. arising from the use of this software.
  7. Permission is granted to anyone to use this software for any purpose,
  8. including commercial applications, and to alter it and redistribute it
  9. freely, subject to the following restrictions:
  10. 1. The origin of this software must not be misrepresented; you must not
  11. claim that you wrote the original software. If you use this software
  12. in a product, an acknowledgment in the product documentation would be
  13. appreciated but is not required.
  14. 2. Altered source versions must be plainly marked as such, and must not be
  15. misrepresented as being the original software.
  16. 3. This notice may not be removed or altered from any source distribution.
  17. */
  18. #include "SDL_internal.h"
  19. // General (mostly internal) pixel/color manipulation routines for SDL
  20. #include "SDL_sysvideo.h"
  21. #include "SDL_pixels_c.h"
  22. #include "SDL_RLEaccel_c.h"
  23. // Lookup tables to expand partial bytes to the full 0..255 range
  24. static const Uint8 lookup_0[] = {
  25. 255
  26. };
  27. static const Uint8 lookup_1[] = {
  28. 0, 255
  29. };
  30. static const Uint8 lookup_2[] = {
  31. 0, 85, 170, 255
  32. };
  33. static const Uint8 lookup_3[] = {
  34. 0, 36, 72, 109, 145, 182, 218, 255
  35. };
  36. static const Uint8 lookup_4[] = {
  37. 0, 17, 34, 51, 68, 85, 102, 119, 136, 153, 170, 187, 204, 221, 238, 255
  38. };
  39. static const Uint8 lookup_5[] = {
  40. 0, 8, 16, 24, 32, 41, 49, 57, 65, 74, 82, 90, 98, 106, 115, 123, 131, 139, 148, 156, 164, 172, 180, 189, 197, 205, 213, 222, 230, 238, 246, 255
  41. };
  42. static const Uint8 lookup_6[] = {
  43. 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 64, 68, 72, 76, 80, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 170, 174, 178, 182, 186, 190, 194, 198, 202, 206, 210, 214, 218, 222, 226, 230, 234, 238, 242, 246, 250, 255
  44. };
  45. static const Uint8 lookup_7[] = {
  46. 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158, 160, 162, 164, 166, 168, 170, 172, 174, 176, 178, 180, 182, 184, 186, 188, 190, 192, 194, 196, 198, 200, 202, 204, 206, 208, 210, 212, 214, 216, 218, 220, 222, 224, 226, 228, 230, 232, 234, 236, 238, 240, 242, 244, 246, 248, 250, 252, 255
  47. };
  48. static const Uint8 lookup_8[] = {
  49. 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255
  50. };
  51. const Uint8 *SDL_expand_byte[9] = {
  52. lookup_0,
  53. lookup_1,
  54. lookup_2,
  55. lookup_3,
  56. lookup_4,
  57. lookup_5,
  58. lookup_6,
  59. lookup_7,
  60. lookup_8
  61. };
  62. // Lookup tables to expand 8 bit to 10 bit range
  63. const Uint16 SDL_expand_byte_10[] = {
  64. 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 64, 68, 72, 76, 80, 84, 88, 92, 96, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 148, 152, 156, 160, 164, 168, 173, 177, 181, 185, 189, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233, 237, 241, 245, 249, 253, 257, 261, 265, 269, 273, 277, 281, 285, 289, 293, 297, 301, 305, 309, 313, 317, 321, 325, 329, 333, 337, 341, 345, 349, 353, 357, 361, 365, 369, 373, 377, 381, 385, 389, 393, 397, 401, 405, 409, 413, 417, 421, 425, 429, 433, 437, 441, 445, 449, 453, 457, 461, 465, 469, 473, 477, 481, 485, 489, 493, 497, 501, 505, 509, 514, 518, 522, 526, 530, 534, 538, 542, 546, 550, 554, 558, 562, 566, 570, 574, 578, 582, 586, 590, 594, 598, 602, 606, 610, 614, 618, 622, 626, 630, 634, 638, 642, 646, 650, 654, 658, 662, 666, 670, 674, 678, 682, 686, 690, 694, 698, 702, 706, 710, 714, 718, 722, 726, 730, 734, 738, 742, 746, 750, 754, 758, 762, 766, 770, 774, 778, 782, 786, 790, 794, 798, 802, 806, 810, 814, 818, 822, 826, 830, 834, 838, 842, 846, 850, 855, 859, 863, 867, 871, 875, 879, 883, 887, 891, 895, 899, 903, 907, 911, 915, 919, 923, 927, 931, 935, 939, 943, 947, 951, 955, 959, 963, 967, 971, 975, 979, 983, 987, 991, 995, 999, 1003, 1007, 1011, 1015, 1019, 1023
  65. };
  66. SDL_COMPILE_TIME_ASSERT(SDL_expand_byte_10_size, SDL_arraysize(SDL_expand_byte_10) == (1 << 8));
  67. // Helper functions
  68. #define CASE(X) \
  69. case X: \
  70. return #X;
  71. const char *SDL_GetPixelFormatName(SDL_PixelFormat format)
  72. {
  73. switch (format) {
  74. CASE(SDL_PIXELFORMAT_INDEX1LSB)
  75. CASE(SDL_PIXELFORMAT_INDEX1MSB)
  76. CASE(SDL_PIXELFORMAT_INDEX2LSB)
  77. CASE(SDL_PIXELFORMAT_INDEX2MSB)
  78. CASE(SDL_PIXELFORMAT_INDEX4LSB)
  79. CASE(SDL_PIXELFORMAT_INDEX4MSB)
  80. CASE(SDL_PIXELFORMAT_INDEX8)
  81. CASE(SDL_PIXELFORMAT_RGB332)
  82. CASE(SDL_PIXELFORMAT_XRGB4444)
  83. CASE(SDL_PIXELFORMAT_XBGR4444)
  84. CASE(SDL_PIXELFORMAT_XRGB1555)
  85. CASE(SDL_PIXELFORMAT_XBGR1555)
  86. CASE(SDL_PIXELFORMAT_ARGB4444)
  87. CASE(SDL_PIXELFORMAT_RGBA4444)
  88. CASE(SDL_PIXELFORMAT_ABGR4444)
  89. CASE(SDL_PIXELFORMAT_BGRA4444)
  90. CASE(SDL_PIXELFORMAT_ARGB1555)
  91. CASE(SDL_PIXELFORMAT_RGBA5551)
  92. CASE(SDL_PIXELFORMAT_ABGR1555)
  93. CASE(SDL_PIXELFORMAT_BGRA5551)
  94. CASE(SDL_PIXELFORMAT_RGB565)
  95. CASE(SDL_PIXELFORMAT_BGR565)
  96. CASE(SDL_PIXELFORMAT_RGB24)
  97. CASE(SDL_PIXELFORMAT_BGR24)
  98. CASE(SDL_PIXELFORMAT_XRGB8888)
  99. CASE(SDL_PIXELFORMAT_RGBX8888)
  100. CASE(SDL_PIXELFORMAT_XBGR8888)
  101. CASE(SDL_PIXELFORMAT_BGRX8888)
  102. CASE(SDL_PIXELFORMAT_ARGB8888)
  103. CASE(SDL_PIXELFORMAT_RGBA8888)
  104. CASE(SDL_PIXELFORMAT_ABGR8888)
  105. CASE(SDL_PIXELFORMAT_BGRA8888)
  106. CASE(SDL_PIXELFORMAT_XRGB2101010)
  107. CASE(SDL_PIXELFORMAT_XBGR2101010)
  108. CASE(SDL_PIXELFORMAT_ARGB2101010)
  109. CASE(SDL_PIXELFORMAT_ABGR2101010)
  110. CASE(SDL_PIXELFORMAT_RGB48)
  111. CASE(SDL_PIXELFORMAT_BGR48)
  112. CASE(SDL_PIXELFORMAT_RGBA64)
  113. CASE(SDL_PIXELFORMAT_ARGB64)
  114. CASE(SDL_PIXELFORMAT_BGRA64)
  115. CASE(SDL_PIXELFORMAT_ABGR64)
  116. CASE(SDL_PIXELFORMAT_RGB48_FLOAT)
  117. CASE(SDL_PIXELFORMAT_BGR48_FLOAT)
  118. CASE(SDL_PIXELFORMAT_RGBA64_FLOAT)
  119. CASE(SDL_PIXELFORMAT_ARGB64_FLOAT)
  120. CASE(SDL_PIXELFORMAT_BGRA64_FLOAT)
  121. CASE(SDL_PIXELFORMAT_ABGR64_FLOAT)
  122. CASE(SDL_PIXELFORMAT_RGB96_FLOAT)
  123. CASE(SDL_PIXELFORMAT_BGR96_FLOAT)
  124. CASE(SDL_PIXELFORMAT_RGBA128_FLOAT)
  125. CASE(SDL_PIXELFORMAT_ARGB128_FLOAT)
  126. CASE(SDL_PIXELFORMAT_BGRA128_FLOAT)
  127. CASE(SDL_PIXELFORMAT_ABGR128_FLOAT)
  128. CASE(SDL_PIXELFORMAT_YV12)
  129. CASE(SDL_PIXELFORMAT_IYUV)
  130. CASE(SDL_PIXELFORMAT_YUY2)
  131. CASE(SDL_PIXELFORMAT_UYVY)
  132. CASE(SDL_PIXELFORMAT_YVYU)
  133. CASE(SDL_PIXELFORMAT_NV12)
  134. CASE(SDL_PIXELFORMAT_NV21)
  135. CASE(SDL_PIXELFORMAT_P010)
  136. CASE(SDL_PIXELFORMAT_EXTERNAL_OES)
  137. default:
  138. return "SDL_PIXELFORMAT_UNKNOWN";
  139. }
  140. }
  141. #undef CASE
  142. bool SDL_GetMasksForPixelFormat(SDL_PixelFormat format, int *bpp, Uint32 *Rmask, Uint32 *Gmask, Uint32 *Bmask, Uint32 *Amask)
  143. {
  144. Uint32 masks[4];
  145. #if SDL_HAVE_YUV
  146. // Partial support for SDL_Surface with FOURCC
  147. if (SDL_ISPIXELFORMAT_FOURCC(format)) {
  148. // Not a format that uses masks
  149. *Rmask = *Gmask = *Bmask = *Amask = 0;
  150. // however, some of these are packed formats, and can legit declare bits-per-pixel!
  151. switch (format) {
  152. case SDL_PIXELFORMAT_YUY2:
  153. case SDL_PIXELFORMAT_UYVY:
  154. case SDL_PIXELFORMAT_YVYU:
  155. *bpp = 32;
  156. break;
  157. default:
  158. *bpp = 0; // oh well.
  159. }
  160. return true;
  161. }
  162. #else
  163. if (SDL_ISPIXELFORMAT_FOURCC(format)) {
  164. return SDL_SetError("SDL not built with YUV support");
  165. }
  166. #endif
  167. // Initialize the values here
  168. if (SDL_BYTESPERPIXEL(format) <= 2) {
  169. *bpp = SDL_BITSPERPIXEL(format);
  170. } else {
  171. *bpp = SDL_BYTESPERPIXEL(format) * 8;
  172. }
  173. *Rmask = *Gmask = *Bmask = *Amask = 0;
  174. if (format == SDL_PIXELFORMAT_RGB24) {
  175. #if SDL_BYTEORDER == SDL_BIG_ENDIAN
  176. *Rmask = 0x00FF0000;
  177. *Gmask = 0x0000FF00;
  178. *Bmask = 0x000000FF;
  179. #else
  180. *Rmask = 0x000000FF;
  181. *Gmask = 0x0000FF00;
  182. *Bmask = 0x00FF0000;
  183. #endif
  184. return true;
  185. }
  186. if (format == SDL_PIXELFORMAT_BGR24) {
  187. #if SDL_BYTEORDER == SDL_BIG_ENDIAN
  188. *Rmask = 0x000000FF;
  189. *Gmask = 0x0000FF00;
  190. *Bmask = 0x00FF0000;
  191. #else
  192. *Rmask = 0x00FF0000;
  193. *Gmask = 0x0000FF00;
  194. *Bmask = 0x000000FF;
  195. #endif
  196. return true;
  197. }
  198. if (SDL_PIXELTYPE(format) != SDL_PIXELTYPE_PACKED8 &&
  199. SDL_PIXELTYPE(format) != SDL_PIXELTYPE_PACKED16 &&
  200. SDL_PIXELTYPE(format) != SDL_PIXELTYPE_PACKED32) {
  201. // Not a format that uses masks
  202. return true;
  203. }
  204. switch (SDL_PIXELLAYOUT(format)) {
  205. case SDL_PACKEDLAYOUT_332:
  206. masks[0] = 0x00000000;
  207. masks[1] = 0x000000E0;
  208. masks[2] = 0x0000001C;
  209. masks[3] = 0x00000003;
  210. break;
  211. case SDL_PACKEDLAYOUT_4444:
  212. masks[0] = 0x0000F000;
  213. masks[1] = 0x00000F00;
  214. masks[2] = 0x000000F0;
  215. masks[3] = 0x0000000F;
  216. break;
  217. case SDL_PACKEDLAYOUT_1555:
  218. masks[0] = 0x00008000;
  219. masks[1] = 0x00007C00;
  220. masks[2] = 0x000003E0;
  221. masks[3] = 0x0000001F;
  222. break;
  223. case SDL_PACKEDLAYOUT_5551:
  224. masks[0] = 0x0000F800;
  225. masks[1] = 0x000007C0;
  226. masks[2] = 0x0000003E;
  227. masks[3] = 0x00000001;
  228. break;
  229. case SDL_PACKEDLAYOUT_565:
  230. masks[0] = 0x00000000;
  231. masks[1] = 0x0000F800;
  232. masks[2] = 0x000007E0;
  233. masks[3] = 0x0000001F;
  234. break;
  235. case SDL_PACKEDLAYOUT_8888:
  236. masks[0] = 0xFF000000;
  237. masks[1] = 0x00FF0000;
  238. masks[2] = 0x0000FF00;
  239. masks[3] = 0x000000FF;
  240. break;
  241. case SDL_PACKEDLAYOUT_2101010:
  242. masks[0] = 0xC0000000;
  243. masks[1] = 0x3FF00000;
  244. masks[2] = 0x000FFC00;
  245. masks[3] = 0x000003FF;
  246. break;
  247. case SDL_PACKEDLAYOUT_1010102:
  248. masks[0] = 0xFFC00000;
  249. masks[1] = 0x003FF000;
  250. masks[2] = 0x00000FFC;
  251. masks[3] = 0x00000003;
  252. break;
  253. default:
  254. return SDL_SetError("Unknown pixel format");
  255. }
  256. switch (SDL_PIXELORDER(format)) {
  257. case SDL_PACKEDORDER_XRGB:
  258. *Rmask = masks[1];
  259. *Gmask = masks[2];
  260. *Bmask = masks[3];
  261. break;
  262. case SDL_PACKEDORDER_RGBX:
  263. *Rmask = masks[0];
  264. *Gmask = masks[1];
  265. *Bmask = masks[2];
  266. break;
  267. case SDL_PACKEDORDER_ARGB:
  268. *Amask = masks[0];
  269. *Rmask = masks[1];
  270. *Gmask = masks[2];
  271. *Bmask = masks[3];
  272. break;
  273. case SDL_PACKEDORDER_RGBA:
  274. *Rmask = masks[0];
  275. *Gmask = masks[1];
  276. *Bmask = masks[2];
  277. *Amask = masks[3];
  278. break;
  279. case SDL_PACKEDORDER_XBGR:
  280. *Bmask = masks[1];
  281. *Gmask = masks[2];
  282. *Rmask = masks[3];
  283. break;
  284. case SDL_PACKEDORDER_BGRX:
  285. *Bmask = masks[0];
  286. *Gmask = masks[1];
  287. *Rmask = masks[2];
  288. break;
  289. case SDL_PACKEDORDER_BGRA:
  290. *Bmask = masks[0];
  291. *Gmask = masks[1];
  292. *Rmask = masks[2];
  293. *Amask = masks[3];
  294. break;
  295. case SDL_PACKEDORDER_ABGR:
  296. *Amask = masks[0];
  297. *Bmask = masks[1];
  298. *Gmask = masks[2];
  299. *Rmask = masks[3];
  300. break;
  301. default:
  302. return SDL_SetError("Unknown pixel format");
  303. }
  304. return true;
  305. }
  306. SDL_PixelFormat SDL_GetPixelFormatForMasks(int bpp, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask)
  307. {
  308. switch (bpp) {
  309. case 1:
  310. // SDL defaults to MSB ordering
  311. return SDL_PIXELFORMAT_INDEX1MSB;
  312. case 2:
  313. // SDL defaults to MSB ordering
  314. return SDL_PIXELFORMAT_INDEX2MSB;
  315. case 4:
  316. // SDL defaults to MSB ordering
  317. return SDL_PIXELFORMAT_INDEX4MSB;
  318. case 8:
  319. if (Rmask == 0xE0 &&
  320. Gmask == 0x1C &&
  321. Bmask == 0x03 &&
  322. Amask == 0x00) {
  323. return SDL_PIXELFORMAT_RGB332;
  324. }
  325. return SDL_PIXELFORMAT_INDEX8;
  326. case 12:
  327. if (Rmask == 0) {
  328. return SDL_PIXELFORMAT_XRGB4444;
  329. }
  330. if (Rmask == 0x0F00 &&
  331. Gmask == 0x00F0 &&
  332. Bmask == 0x000F &&
  333. Amask == 0x0000) {
  334. return SDL_PIXELFORMAT_XRGB4444;
  335. }
  336. if (Rmask == 0x000F &&
  337. Gmask == 0x00F0 &&
  338. Bmask == 0x0F00 &&
  339. Amask == 0x0000) {
  340. return SDL_PIXELFORMAT_XBGR4444;
  341. }
  342. break;
  343. case 15:
  344. if (Rmask == 0) {
  345. return SDL_PIXELFORMAT_XRGB1555;
  346. }
  347. SDL_FALLTHROUGH;
  348. case 16:
  349. if (Rmask == 0) {
  350. return SDL_PIXELFORMAT_RGB565;
  351. }
  352. if (Rmask == 0x7C00 &&
  353. Gmask == 0x03E0 &&
  354. Bmask == 0x001F &&
  355. Amask == 0x0000) {
  356. return SDL_PIXELFORMAT_XRGB1555;
  357. }
  358. if (Rmask == 0x001F &&
  359. Gmask == 0x03E0 &&
  360. Bmask == 0x7C00 &&
  361. Amask == 0x0000) {
  362. return SDL_PIXELFORMAT_XBGR1555;
  363. }
  364. if (Rmask == 0x0F00 &&
  365. Gmask == 0x00F0 &&
  366. Bmask == 0x000F &&
  367. Amask == 0xF000) {
  368. return SDL_PIXELFORMAT_ARGB4444;
  369. }
  370. if (Rmask == 0xF000 &&
  371. Gmask == 0x0F00 &&
  372. Bmask == 0x00F0 &&
  373. Amask == 0x000F) {
  374. return SDL_PIXELFORMAT_RGBA4444;
  375. }
  376. if (Rmask == 0x000F &&
  377. Gmask == 0x00F0 &&
  378. Bmask == 0x0F00 &&
  379. Amask == 0xF000) {
  380. return SDL_PIXELFORMAT_ABGR4444;
  381. }
  382. if (Rmask == 0x00F0 &&
  383. Gmask == 0x0F00 &&
  384. Bmask == 0xF000 &&
  385. Amask == 0x000F) {
  386. return SDL_PIXELFORMAT_BGRA4444;
  387. }
  388. if (Rmask == 0x7C00 &&
  389. Gmask == 0x03E0 &&
  390. Bmask == 0x001F &&
  391. Amask == 0x8000) {
  392. return SDL_PIXELFORMAT_ARGB1555;
  393. }
  394. if (Rmask == 0xF800 &&
  395. Gmask == 0x07C0 &&
  396. Bmask == 0x003E &&
  397. Amask == 0x0001) {
  398. return SDL_PIXELFORMAT_RGBA5551;
  399. }
  400. if (Rmask == 0x001F &&
  401. Gmask == 0x03E0 &&
  402. Bmask == 0x7C00 &&
  403. Amask == 0x8000) {
  404. return SDL_PIXELFORMAT_ABGR1555;
  405. }
  406. if (Rmask == 0x003E &&
  407. Gmask == 0x07C0 &&
  408. Bmask == 0xF800 &&
  409. Amask == 0x0001) {
  410. return SDL_PIXELFORMAT_BGRA5551;
  411. }
  412. if (Rmask == 0xF800 &&
  413. Gmask == 0x07E0 &&
  414. Bmask == 0x001F &&
  415. Amask == 0x0000) {
  416. return SDL_PIXELFORMAT_RGB565;
  417. }
  418. if (Rmask == 0x001F &&
  419. Gmask == 0x07E0 &&
  420. Bmask == 0xF800 &&
  421. Amask == 0x0000) {
  422. return SDL_PIXELFORMAT_BGR565;
  423. }
  424. if (Rmask == 0x003F &&
  425. Gmask == 0x07C0 &&
  426. Bmask == 0xF800 &&
  427. Amask == 0x0000) {
  428. // Technically this would be BGR556, but Witek says this works in bug 3158
  429. return SDL_PIXELFORMAT_RGB565;
  430. }
  431. break;
  432. case 24:
  433. switch (Rmask) {
  434. case 0:
  435. case 0x00FF0000:
  436. #if SDL_BYTEORDER == SDL_BIG_ENDIAN
  437. return SDL_PIXELFORMAT_RGB24;
  438. #else
  439. return SDL_PIXELFORMAT_BGR24;
  440. #endif
  441. case 0x000000FF:
  442. #if SDL_BYTEORDER == SDL_BIG_ENDIAN
  443. return SDL_PIXELFORMAT_BGR24;
  444. #else
  445. return SDL_PIXELFORMAT_RGB24;
  446. #endif
  447. }
  448. break;
  449. case 30:
  450. if (Rmask == 0x3FF00000 &&
  451. Gmask == 0x000FFC00 &&
  452. Bmask == 0x000003FF &&
  453. Amask == 0x00000000) {
  454. return SDL_PIXELFORMAT_XRGB2101010;
  455. }
  456. if (Rmask == 0x000003FF &&
  457. Gmask == 0x000FFC00 &&
  458. Bmask == 0x3FF00000 &&
  459. Amask == 0x00000000) {
  460. return SDL_PIXELFORMAT_XBGR2101010;
  461. }
  462. break;
  463. case 32:
  464. if (Rmask == 0) {
  465. return SDL_PIXELFORMAT_XRGB8888;
  466. }
  467. if (Rmask == 0x00FF0000 &&
  468. Gmask == 0x0000FF00 &&
  469. Bmask == 0x000000FF &&
  470. Amask == 0x00000000) {
  471. return SDL_PIXELFORMAT_XRGB8888;
  472. }
  473. if (Rmask == 0xFF000000 &&
  474. Gmask == 0x00FF0000 &&
  475. Bmask == 0x0000FF00 &&
  476. Amask == 0x00000000) {
  477. return SDL_PIXELFORMAT_RGBX8888;
  478. }
  479. if (Rmask == 0x000000FF &&
  480. Gmask == 0x0000FF00 &&
  481. Bmask == 0x00FF0000 &&
  482. Amask == 0x00000000) {
  483. return SDL_PIXELFORMAT_XBGR8888;
  484. }
  485. if (Rmask == 0x0000FF00 &&
  486. Gmask == 0x00FF0000 &&
  487. Bmask == 0xFF000000 &&
  488. Amask == 0x00000000) {
  489. return SDL_PIXELFORMAT_BGRX8888;
  490. }
  491. if (Rmask == 0x00FF0000 &&
  492. Gmask == 0x0000FF00 &&
  493. Bmask == 0x000000FF &&
  494. Amask == 0xFF000000) {
  495. return SDL_PIXELFORMAT_ARGB8888;
  496. }
  497. if (Rmask == 0xFF000000 &&
  498. Gmask == 0x00FF0000 &&
  499. Bmask == 0x0000FF00 &&
  500. Amask == 0x000000FF) {
  501. return SDL_PIXELFORMAT_RGBA8888;
  502. }
  503. if (Rmask == 0x000000FF &&
  504. Gmask == 0x0000FF00 &&
  505. Bmask == 0x00FF0000 &&
  506. Amask == 0xFF000000) {
  507. return SDL_PIXELFORMAT_ABGR8888;
  508. }
  509. if (Rmask == 0x0000FF00 &&
  510. Gmask == 0x00FF0000 &&
  511. Bmask == 0xFF000000 &&
  512. Amask == 0x000000FF) {
  513. return SDL_PIXELFORMAT_BGRA8888;
  514. }
  515. if (Rmask == 0x3FF00000 &&
  516. Gmask == 0x000FFC00 &&
  517. Bmask == 0x000003FF &&
  518. Amask == 0x00000000) {
  519. return SDL_PIXELFORMAT_XRGB2101010;
  520. }
  521. if (Rmask == 0x000003FF &&
  522. Gmask == 0x000FFC00 &&
  523. Bmask == 0x3FF00000 &&
  524. Amask == 0x00000000) {
  525. return SDL_PIXELFORMAT_XBGR2101010;
  526. }
  527. if (Rmask == 0x3FF00000 &&
  528. Gmask == 0x000FFC00 &&
  529. Bmask == 0x000003FF &&
  530. Amask == 0xC0000000) {
  531. return SDL_PIXELFORMAT_ARGB2101010;
  532. }
  533. if (Rmask == 0x000003FF &&
  534. Gmask == 0x000FFC00 &&
  535. Bmask == 0x3FF00000 &&
  536. Amask == 0xC0000000) {
  537. return SDL_PIXELFORMAT_ABGR2101010;
  538. }
  539. break;
  540. }
  541. return SDL_PIXELFORMAT_UNKNOWN;
  542. }
  543. static SDL_HashTable *SDL_format_details;
  544. static SDL_Mutex *SDL_format_details_lock;
  545. static bool SDL_InitPixelFormatDetails(SDL_PixelFormatDetails *details, SDL_PixelFormat format)
  546. {
  547. int bpp;
  548. Uint32 Rmask, Gmask, Bmask, Amask;
  549. Uint32 mask;
  550. if (!SDL_GetMasksForPixelFormat(format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) {
  551. return false;
  552. }
  553. // Set up the format
  554. SDL_zerop(details);
  555. details->format = format;
  556. details->bits_per_pixel = (Uint8)bpp;
  557. details->bytes_per_pixel = (Uint8)((bpp + 7) / 8);
  558. details->Rmask = Rmask;
  559. details->Rshift = 0;
  560. details->Rbits = 0;
  561. if (Rmask) {
  562. for (mask = Rmask; !(mask & 0x01); mask >>= 1) {
  563. ++details->Rshift;
  564. }
  565. for (; (mask & 0x01); mask >>= 1) {
  566. ++details->Rbits;
  567. }
  568. }
  569. details->Gmask = Gmask;
  570. details->Gshift = 0;
  571. details->Gbits = 0;
  572. if (Gmask) {
  573. for (mask = Gmask; !(mask & 0x01); mask >>= 1) {
  574. ++details->Gshift;
  575. }
  576. for (; (mask & 0x01); mask >>= 1) {
  577. ++details->Gbits;
  578. }
  579. }
  580. details->Bmask = Bmask;
  581. details->Bshift = 0;
  582. details->Bbits = 0;
  583. if (Bmask) {
  584. for (mask = Bmask; !(mask & 0x01); mask >>= 1) {
  585. ++details->Bshift;
  586. }
  587. for (; (mask & 0x01); mask >>= 1) {
  588. ++details->Bbits;
  589. }
  590. }
  591. details->Amask = Amask;
  592. details->Ashift = 0;
  593. details->Abits = 0;
  594. if (Amask) {
  595. for (mask = Amask; !(mask & 0x01); mask >>= 1) {
  596. ++details->Ashift;
  597. }
  598. for (; (mask & 0x01); mask >>= 1) {
  599. ++details->Abits;
  600. }
  601. }
  602. return true;
  603. }
  604. const SDL_PixelFormatDetails *SDL_GetPixelFormatDetails(SDL_PixelFormat format)
  605. {
  606. SDL_PixelFormatDetails *details;
  607. if (!SDL_format_details_lock) {
  608. SDL_format_details_lock = SDL_CreateMutex();
  609. }
  610. SDL_LockMutex(SDL_format_details_lock);
  611. if (!SDL_format_details) {
  612. SDL_format_details = SDL_CreateHashTable(NULL, 8, SDL_HashID, SDL_KeyMatchID, SDL_NukeFreeValue, false);
  613. }
  614. if (SDL_FindInHashTable(SDL_format_details, (const void *)(uintptr_t)format, (const void **)&details)) {
  615. goto done;
  616. }
  617. // Allocate an empty pixel format structure, and initialize it
  618. details = (SDL_PixelFormatDetails *)SDL_malloc(sizeof(*details));
  619. if (!details) {
  620. goto done;
  621. }
  622. if (!SDL_InitPixelFormatDetails(details, format)) {
  623. SDL_free(details);
  624. details = NULL;
  625. goto done;
  626. }
  627. if (!SDL_InsertIntoHashTable(SDL_format_details, (const void *)(uintptr_t)format, (void *)details)) {
  628. SDL_free(details);
  629. details = NULL;
  630. goto done;
  631. }
  632. done:
  633. SDL_UnlockMutex(SDL_format_details_lock);
  634. return details;
  635. }
  636. void SDL_QuitPixelFormatDetails(void)
  637. {
  638. if (SDL_format_details) {
  639. SDL_DestroyHashTable(SDL_format_details);
  640. SDL_format_details = NULL;
  641. }
  642. if (SDL_format_details_lock) {
  643. SDL_DestroyMutex(SDL_format_details_lock);
  644. SDL_format_details_lock = NULL;
  645. }
  646. }
  647. SDL_Colorspace SDL_GetDefaultColorspaceForFormat(SDL_PixelFormat format)
  648. {
  649. if (SDL_ISPIXELFORMAT_FOURCC(format)) {
  650. if (format == SDL_PIXELFORMAT_P010) {
  651. return SDL_COLORSPACE_HDR10;
  652. } else {
  653. return SDL_COLORSPACE_YUV_DEFAULT;
  654. }
  655. } else if (SDL_ISPIXELFORMAT_FLOAT(format)) {
  656. return SDL_COLORSPACE_SRGB_LINEAR;
  657. } else if (SDL_ISPIXELFORMAT_10BIT(format)) {
  658. return SDL_COLORSPACE_HDR10;
  659. } else {
  660. return SDL_COLORSPACE_RGB_DEFAULT;
  661. }
  662. }
  663. float SDL_sRGBtoLinear(float v)
  664. {
  665. if (v <= 0.04045f) {
  666. v = (v / 12.92f);
  667. } else {
  668. v = SDL_powf((v + 0.055f) / 1.055f, 2.4f);
  669. }
  670. return v;
  671. }
  672. float SDL_sRGBfromLinear(float v)
  673. {
  674. if (v <= 0.0031308f) {
  675. v = (v * 12.92f);
  676. } else {
  677. v = (SDL_powf(v, 1.0f / 2.4f) * 1.055f - 0.055f);
  678. }
  679. return v;
  680. }
  681. float SDL_PQtoNits(float v)
  682. {
  683. const float c1 = 0.8359375f;
  684. const float c2 = 18.8515625f;
  685. const float c3 = 18.6875f;
  686. const float oo_m1 = 1.0f / 0.1593017578125f;
  687. const float oo_m2 = 1.0f / 78.84375f;
  688. float num = SDL_max(SDL_powf(v, oo_m2) - c1, 0.0f);
  689. float den = c2 - c3 * SDL_powf(v, oo_m2);
  690. return 10000.0f * SDL_powf(num / den, oo_m1);
  691. }
  692. float SDL_PQfromNits(float v)
  693. {
  694. const float c1 = 0.8359375f;
  695. const float c2 = 18.8515625f;
  696. const float c3 = 18.6875f;
  697. const float m1 = 0.1593017578125f;
  698. const float m2 = 78.84375f;
  699. float y = SDL_clamp(v / 10000.0f, 0.0f, 1.0f);
  700. float num = c1 + c2 * SDL_powf(y, m1);
  701. float den = 1.0f + c3 * SDL_powf(y, m1);
  702. return SDL_powf(num / den, m2);
  703. }
  704. /* This is a helpful tool for deriving these:
  705. * https://kdashg.github.io/misc/colors/from-coeffs.html
  706. */
  707. static const float mat_BT601_Limited_8bit[] = {
  708. -0.0627451017f, -0.501960814f, -0.501960814f, 0.0f, // offset
  709. 1.1644f, 0.0000f, 1.5960f, 0.0f, // Rcoeff
  710. 1.1644f, -0.3918f, -0.8130f, 0.0f, // Gcoeff
  711. 1.1644f, 2.0172f, 0.0000f, 0.0f, // Bcoeff
  712. };
  713. static const float mat_BT601_Full_8bit[] = {
  714. 0.0f, -0.501960814f, -0.501960814f, 0.0f, // offset
  715. 1.0000f, 0.0000f, 1.4075f, 0.0f, // Rcoeff
  716. 1.0000f, -0.3455f, -0.7169f, 0.0f, // Gcoeff
  717. 1.0000f, 1.7790f, 0.0000f, 0.0f, // Bcoeff
  718. };
  719. static const float mat_BT709_Limited_8bit[] = {
  720. -0.0627451017f, -0.501960814f, -0.501960814f, 0.0f, // offset
  721. 1.1644f, 0.0000f, 1.7927f, 0.0f, // Rcoeff
  722. 1.1644f, -0.2132f, -0.5329f, 0.0f, // Gcoeff
  723. 1.1644f, 2.1124f, 0.0000f, 0.0f, // Bcoeff
  724. };
  725. static const float mat_BT709_Full_8bit[] = {
  726. 0.0f, -0.501960814f, -0.501960814f, 0.0f, // offset
  727. 1.0000f, 0.0000f, 1.5810f, 0.0f, // Rcoeff
  728. 1.0000f, -0.1881f, -0.4700f, 0.0f, // Gcoeff
  729. 1.0000f, 1.8629f, 0.0000f, 0.0f, // Bcoeff
  730. };
  731. static const float mat_BT2020_Limited_10bit[] = {
  732. -0.062561095f, -0.500488759f, -0.500488759f, 0.0f, // offset
  733. 1.1678f, 0.0000f, 1.6836f, 0.0f, // Rcoeff
  734. 1.1678f, -0.1879f, -0.6523f, 0.0f, // Gcoeff
  735. 1.1678f, 2.1481f, 0.0000f, 0.0f, // Bcoeff
  736. };
  737. static const float mat_BT2020_Full_10bit[] = {
  738. 0.0f, -0.500488759f, -0.500488759f, 0.0f, // offset
  739. 1.0000f, 0.0000f, 1.4760f, 0.0f, // Rcoeff
  740. 1.0000f, -0.1647f, -0.5719f, 0.0f, // Gcoeff
  741. 1.0000f, 1.8832f, 0.0000f, 0.0f, // Bcoeff
  742. };
  743. static const float *SDL_GetBT601ConversionMatrix( SDL_Colorspace colorspace )
  744. {
  745. switch (SDL_COLORSPACERANGE(colorspace)) {
  746. case SDL_COLOR_RANGE_LIMITED:
  747. case SDL_COLOR_RANGE_UNKNOWN:
  748. return mat_BT601_Limited_8bit;
  749. case SDL_COLOR_RANGE_FULL:
  750. return mat_BT601_Full_8bit;
  751. default:
  752. break;
  753. }
  754. return NULL;
  755. }
  756. static const float *SDL_GetBT709ConversionMatrix(SDL_Colorspace colorspace)
  757. {
  758. switch (SDL_COLORSPACERANGE(colorspace)) {
  759. case SDL_COLOR_RANGE_LIMITED:
  760. case SDL_COLOR_RANGE_UNKNOWN:
  761. return mat_BT709_Limited_8bit;
  762. case SDL_COLOR_RANGE_FULL:
  763. return mat_BT709_Full_8bit;
  764. default:
  765. break;
  766. }
  767. return NULL;
  768. }
  769. static const float *SDL_GetBT2020ConversionMatrix(SDL_Colorspace colorspace)
  770. {
  771. switch (SDL_COLORSPACERANGE(colorspace)) {
  772. case SDL_COLOR_RANGE_LIMITED:
  773. case SDL_COLOR_RANGE_UNKNOWN:
  774. return mat_BT2020_Limited_10bit;
  775. case SDL_COLOR_RANGE_FULL:
  776. return mat_BT2020_Full_10bit;
  777. default:
  778. break;
  779. }
  780. return NULL;
  781. }
  782. const float *SDL_GetYCbCRtoRGBConversionMatrix(SDL_Colorspace colorspace, int w, int h, int bits_per_pixel)
  783. {
  784. const int YUV_SD_THRESHOLD = 576;
  785. switch (SDL_COLORSPACEMATRIX(colorspace)) {
  786. case SDL_MATRIX_COEFFICIENTS_BT601:
  787. case SDL_MATRIX_COEFFICIENTS_BT470BG:
  788. return SDL_GetBT601ConversionMatrix(colorspace);
  789. case SDL_MATRIX_COEFFICIENTS_BT709:
  790. return SDL_GetBT709ConversionMatrix(colorspace);
  791. case SDL_MATRIX_COEFFICIENTS_BT2020_NCL:
  792. return SDL_GetBT2020ConversionMatrix(colorspace);
  793. case SDL_MATRIX_COEFFICIENTS_UNSPECIFIED:
  794. switch (bits_per_pixel) {
  795. case 8:
  796. if (h <= YUV_SD_THRESHOLD) {
  797. return SDL_GetBT601ConversionMatrix(colorspace);
  798. } else {
  799. return SDL_GetBT709ConversionMatrix(colorspace);
  800. }
  801. case 10:
  802. case 16:
  803. return SDL_GetBT2020ConversionMatrix(colorspace);
  804. default:
  805. break;
  806. }
  807. break;
  808. default:
  809. break;
  810. }
  811. return NULL;
  812. }
  813. const float *SDL_GetColorPrimariesConversionMatrix(SDL_ColorPrimaries src, SDL_ColorPrimaries dst)
  814. {
  815. /* Conversion matrices generated using gamescope color helpers and the primaries definitions at:
  816. * https://www.itu.int/rec/T-REC-H.273-201612-S/en
  817. *
  818. * You can also generate these online using the RGB-XYZ matrix calculator, and then multiplying
  819. * XYZ_to_dst * src_to_XYZ to get the combined conversion matrix:
  820. * https://www.russellcottrell.com/photo/matrixCalculator.htm
  821. */
  822. static const float mat601to709[] = {
  823. 0.939542f, 0.050181f, 0.010277f,
  824. 0.017772f, 0.965793f, 0.016435f,
  825. -0.001622f, -0.004370f, 1.005991f,
  826. };
  827. static const float mat601to2020[] = {
  828. 0.595254f, 0.349314f, 0.055432f,
  829. 0.081244f, 0.891503f, 0.027253f,
  830. 0.015512f, 0.081912f, 0.902576f,
  831. };
  832. static const float mat709to601[] = {
  833. 1.065379f, -0.055401f, -0.009978f,
  834. -0.019633f, 1.036363f, -0.016731f,
  835. 0.001632f, 0.004412f, 0.993956f,
  836. };
  837. static const float mat709to2020[] = {
  838. 0.627404f, 0.329283f, 0.043313f,
  839. 0.069097f, 0.919541f, 0.011362f,
  840. 0.016391f, 0.088013f, 0.895595f,
  841. };
  842. static const float mat2020to601[] = {
  843. 1.776133f, -0.687820f, -0.088313f,
  844. -0.161376f, 1.187315f, -0.025940f,
  845. -0.015881f, -0.095931f, 1.111812f,
  846. };
  847. static const float mat2020to709[] = {
  848. 1.660496f, -0.587656f, -0.072840f,
  849. -0.124547f, 1.132895f, -0.008348f,
  850. -0.018154f, -0.100597f, 1.118751f
  851. };
  852. static const float matSMPTE431to709[] = {
  853. 1.120713f, -0.234649f, 0.000000f,
  854. -0.038478f, 1.087034f, 0.000000f,
  855. -0.017967f, -0.082030f, 0.954576f,
  856. };
  857. static const float matSMPTE431to2020[] = {
  858. 0.689691f, 0.207169f, 0.041346f,
  859. 0.041852f, 0.982426f, 0.010846f,
  860. -0.001107f, 0.018362f, 0.854914f,
  861. };
  862. static const float matSMPTE432to709[] = {
  863. 1.224940f, -0.224940f, -0.000000f,
  864. -0.042057f, 1.042057f, 0.000000f,
  865. -0.019638f, -0.078636f, 1.098273f,
  866. };
  867. static const float matSMPTE432to2020[] = {
  868. 0.753833f, 0.198597f, 0.047570f,
  869. 0.045744f, 0.941777f, 0.012479f,
  870. -0.001210f, 0.017602f, 0.983609f,
  871. };
  872. switch (dst) {
  873. case SDL_COLOR_PRIMARIES_BT601:
  874. case SDL_COLOR_PRIMARIES_SMPTE240:
  875. switch (src) {
  876. case SDL_COLOR_PRIMARIES_BT709:
  877. return mat709to601;
  878. case SDL_COLOR_PRIMARIES_BT2020:
  879. return mat2020to601;
  880. default:
  881. break;
  882. }
  883. break;
  884. case SDL_COLOR_PRIMARIES_BT709:
  885. switch (src) {
  886. case SDL_COLOR_PRIMARIES_BT601:
  887. case SDL_COLOR_PRIMARIES_SMPTE240:
  888. return mat601to709;
  889. case SDL_COLOR_PRIMARIES_BT2020:
  890. return mat2020to709;
  891. case SDL_COLOR_PRIMARIES_SMPTE431:
  892. return matSMPTE431to709;
  893. case SDL_COLOR_PRIMARIES_SMPTE432:
  894. return matSMPTE432to709;
  895. default:
  896. break;
  897. }
  898. break;
  899. case SDL_COLOR_PRIMARIES_BT2020:
  900. switch (src) {
  901. case SDL_COLOR_PRIMARIES_BT601:
  902. case SDL_COLOR_PRIMARIES_SMPTE240:
  903. return mat601to2020;
  904. case SDL_COLOR_PRIMARIES_BT709:
  905. return mat709to2020;
  906. case SDL_COLOR_PRIMARIES_SMPTE431:
  907. return matSMPTE431to2020;
  908. case SDL_COLOR_PRIMARIES_SMPTE432:
  909. return matSMPTE432to2020;
  910. default:
  911. break;
  912. }
  913. break;
  914. default:
  915. break;
  916. }
  917. return NULL;
  918. }
  919. void SDL_ConvertColorPrimaries(float *fR, float *fG, float *fB, const float *matrix)
  920. {
  921. float v[3];
  922. v[0] = *fR;
  923. v[1] = *fG;
  924. v[2] = *fB;
  925. *fR = matrix[0 * 3 + 0] * v[0] + matrix[0 * 3 + 1] * v[1] + matrix[0 * 3 + 2] * v[2];
  926. *fG = matrix[1 * 3 + 0] * v[0] + matrix[1 * 3 + 1] * v[1] + matrix[1 * 3 + 2] * v[2];
  927. *fB = matrix[2 * 3 + 0] * v[0] + matrix[2 * 3 + 1] * v[1] + matrix[2 * 3 + 2] * v[2];
  928. }
  929. SDL_Palette *SDL_CreatePalette(int ncolors)
  930. {
  931. SDL_Palette *palette;
  932. // Input validation
  933. if (ncolors < 1) {
  934. SDL_InvalidParamError("ncolors");
  935. return NULL;
  936. }
  937. palette = (SDL_Palette *)SDL_malloc(sizeof(*palette));
  938. if (!palette) {
  939. return NULL;
  940. }
  941. palette->colors = (SDL_Color *)SDL_malloc(ncolors * sizeof(*palette->colors));
  942. if (!palette->colors) {
  943. SDL_free(palette);
  944. return NULL;
  945. }
  946. palette->ncolors = ncolors;
  947. palette->version = 1;
  948. palette->refcount = 1;
  949. SDL_memset(palette->colors, 0xFF, ncolors * sizeof(*palette->colors));
  950. return palette;
  951. }
  952. bool SDL_SetPaletteColors(SDL_Palette *palette, const SDL_Color *colors, int firstcolor, int ncolors)
  953. {
  954. bool result = true;
  955. // Verify the parameters
  956. if (!palette) {
  957. return false;
  958. }
  959. if (ncolors > (palette->ncolors - firstcolor)) {
  960. ncolors = (palette->ncolors - firstcolor);
  961. result = false;
  962. }
  963. if (colors != (palette->colors + firstcolor)) {
  964. SDL_memcpy(palette->colors + firstcolor, colors,
  965. ncolors * sizeof(*colors));
  966. }
  967. ++palette->version;
  968. if (!palette->version) {
  969. palette->version = 1;
  970. }
  971. return result;
  972. }
  973. void SDL_DestroyPalette(SDL_Palette *palette)
  974. {
  975. if (!palette) {
  976. return;
  977. }
  978. if (--palette->refcount > 0) {
  979. return;
  980. }
  981. SDL_free(palette->colors);
  982. SDL_free(palette);
  983. }
  984. /*
  985. * Calculate an 8-bit (3 red, 3 green, 2 blue) dithered palette of colors
  986. */
  987. void SDL_DitherPalette(SDL_Palette *palette)
  988. {
  989. int i;
  990. if (palette->ncolors != 256) {
  991. return; // only 8bpp supported right now
  992. }
  993. for (i = 0; i < palette->ncolors; i++) {
  994. int r, g, b;
  995. /* map each bit field to the full [0, 255] interval,
  996. so 0 is mapped to (0, 0, 0) and 255 to (255, 255, 255) */
  997. r = i & 0xe0;
  998. r |= r >> 3 | r >> 6;
  999. palette->colors[i].r = (Uint8)r;
  1000. g = (i << 3) & 0xe0;
  1001. g |= g >> 3 | g >> 6;
  1002. palette->colors[i].g = (Uint8)g;
  1003. b = i & 0x3;
  1004. b |= b << 2;
  1005. b |= b << 4;
  1006. palette->colors[i].b = (Uint8)b;
  1007. palette->colors[i].a = SDL_ALPHA_OPAQUE;
  1008. }
  1009. }
  1010. /*
  1011. * Match an RGB value to a particular palette index
  1012. */
  1013. Uint8 SDL_FindColor(const SDL_Palette *pal, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
  1014. {
  1015. // Do colorspace distance matching
  1016. unsigned int smallest;
  1017. unsigned int distance;
  1018. int rd, gd, bd, ad;
  1019. int i;
  1020. Uint8 pixel = 0;
  1021. smallest = ~0U;
  1022. for (i = 0; i < pal->ncolors; ++i) {
  1023. rd = pal->colors[i].r - r;
  1024. gd = pal->colors[i].g - g;
  1025. bd = pal->colors[i].b - b;
  1026. ad = pal->colors[i].a - a;
  1027. distance = (rd * rd) + (gd * gd) + (bd * bd) + (ad * ad);
  1028. if (distance < smallest) {
  1029. pixel = (Uint8)i;
  1030. if (distance == 0) { // Perfect match!
  1031. break;
  1032. }
  1033. smallest = distance;
  1034. }
  1035. }
  1036. return pixel;
  1037. }
  1038. Uint8 SDL_LookupRGBAColor(SDL_HashTable *palette_map, Uint32 pixel, const SDL_Palette *pal)
  1039. {
  1040. Uint8 color_index = 0;
  1041. const void *value;
  1042. if (SDL_FindInHashTable(palette_map, (const void *)(uintptr_t)pixel, &value)) {
  1043. color_index = (Uint8)(uintptr_t)value;
  1044. } else {
  1045. Uint8 r = (Uint8)((pixel >> 24) & 0xFF);
  1046. Uint8 g = (Uint8)((pixel >> 16) & 0xFF);
  1047. Uint8 b = (Uint8)((pixel >> 8) & 0xFF);
  1048. Uint8 a = (Uint8)((pixel >> 0) & 0xFF);
  1049. color_index = SDL_FindColor(pal, r, g, b, a);
  1050. SDL_InsertIntoHashTable(palette_map, (const void *)(uintptr_t)pixel, (const void *)(uintptr_t)color_index);
  1051. }
  1052. return color_index;
  1053. }
  1054. // Tell whether palette is opaque, and if it has an alpha_channel
  1055. void SDL_DetectPalette(const SDL_Palette *pal, bool *is_opaque, bool *has_alpha_channel)
  1056. {
  1057. int i;
  1058. {
  1059. bool all_opaque = true;
  1060. for (i = 0; i < pal->ncolors; i++) {
  1061. Uint8 alpha_value = pal->colors[i].a;
  1062. if (alpha_value != SDL_ALPHA_OPAQUE) {
  1063. all_opaque = false;
  1064. break;
  1065. }
  1066. }
  1067. if (all_opaque) {
  1068. // Palette is opaque, with an alpha channel
  1069. *is_opaque = true;
  1070. *has_alpha_channel = true;
  1071. return;
  1072. }
  1073. }
  1074. {
  1075. bool all_transparent = true;
  1076. for (i = 0; i < pal->ncolors; i++) {
  1077. Uint8 alpha_value = pal->colors[i].a;
  1078. if (alpha_value != SDL_ALPHA_TRANSPARENT) {
  1079. all_transparent = false;
  1080. break;
  1081. }
  1082. }
  1083. if (all_transparent) {
  1084. // Palette is opaque, without an alpha channel
  1085. *is_opaque = true;
  1086. *has_alpha_channel = false;
  1087. return;
  1088. }
  1089. }
  1090. // Palette has alpha values
  1091. *is_opaque = false;
  1092. *has_alpha_channel = true;
  1093. }
  1094. // Find the opaque pixel value corresponding to an RGB triple
  1095. Uint32 SDL_MapRGB(const SDL_PixelFormatDetails *format, const SDL_Palette *palette, Uint8 r, Uint8 g, Uint8 b)
  1096. {
  1097. if (!format) {
  1098. SDL_InvalidParamError("format");
  1099. return 0;
  1100. }
  1101. if (SDL_ISPIXELFORMAT_INDEXED(format->format)) {
  1102. if (!palette) {
  1103. SDL_InvalidParamError("palette");
  1104. return 0;
  1105. }
  1106. return SDL_FindColor(palette, r, g, b, SDL_ALPHA_OPAQUE);
  1107. }
  1108. if (SDL_ISPIXELFORMAT_10BIT(format->format)) {
  1109. return (((Uint32)SDL_expand_byte_10[r]) << format->Rshift) |
  1110. (((Uint32)SDL_expand_byte_10[g]) << format->Gshift) |
  1111. (((Uint32)SDL_expand_byte_10[b]) << format->Bshift) |
  1112. format->Amask;
  1113. } else {
  1114. return ((Uint32)(r >> (8 - format->Rbits))) << format->Rshift |
  1115. ((Uint32)(g >> (8 - format->Gbits))) << format->Gshift |
  1116. ((Uint32)(b >> (8 - format->Bbits))) << format->Bshift |
  1117. format->Amask;
  1118. }
  1119. }
  1120. // Find the pixel value corresponding to an RGBA quadruple
  1121. Uint32 SDL_MapRGBA(const SDL_PixelFormatDetails *format, const SDL_Palette *palette, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
  1122. {
  1123. if (!format) {
  1124. SDL_InvalidParamError("format");
  1125. return 0;
  1126. }
  1127. if (SDL_ISPIXELFORMAT_INDEXED(format->format)) {
  1128. if (!palette) {
  1129. SDL_InvalidParamError("palette");
  1130. return 0;
  1131. }
  1132. return SDL_FindColor(palette, r, g, b, a);
  1133. }
  1134. if (SDL_ISPIXELFORMAT_10BIT(format->format)) {
  1135. return (((Uint32)SDL_expand_byte_10[r]) << format->Rshift) |
  1136. (((Uint32)SDL_expand_byte_10[g]) << format->Gshift) |
  1137. (((Uint32)SDL_expand_byte_10[b]) << format->Bshift) |
  1138. ((((Uint32)(a >> (8 - format->Abits))) << format->Ashift) & format->Amask);
  1139. } else {
  1140. return ((Uint32)(r >> (8 - format->Rbits))) << format->Rshift |
  1141. ((Uint32)(g >> (8 - format->Gbits))) << format->Gshift |
  1142. ((Uint32)(b >> (8 - format->Bbits))) << format->Bshift |
  1143. ((((Uint32)(a >> (8 - format->Abits))) << format->Ashift) & format->Amask);
  1144. }
  1145. }
  1146. void SDL_GetRGB(Uint32 pixel, const SDL_PixelFormatDetails *format, const SDL_Palette *palette, Uint8 *r, Uint8 *g, Uint8 *b)
  1147. {
  1148. Uint8 unused;
  1149. if (!r) {
  1150. r = &unused;
  1151. }
  1152. if (!g) {
  1153. g = &unused;
  1154. }
  1155. if (!b) {
  1156. b = &unused;
  1157. }
  1158. if (!format) {
  1159. *r = *g = *b = 0;
  1160. return;
  1161. }
  1162. if (SDL_ISPIXELFORMAT_INDEXED(format->format)) {
  1163. if (palette && pixel < (unsigned)palette->ncolors) {
  1164. *r = palette->colors[pixel].r;
  1165. *g = palette->colors[pixel].g;
  1166. *b = palette->colors[pixel].b;
  1167. } else {
  1168. *r = *g = *b = 0;
  1169. }
  1170. return;
  1171. }
  1172. if (SDL_ISPIXELFORMAT_10BIT(format->format)) {
  1173. unsigned v;
  1174. v = (pixel & format->Rmask) >> format->Rshift;
  1175. *r = (Uint8)(v >> 2);
  1176. v = (pixel & format->Gmask) >> format->Gshift;
  1177. *g = (Uint8)(v >> 2);
  1178. v = (pixel & format->Bmask) >> format->Bshift;
  1179. *b = (Uint8)(v >> 2);
  1180. } else {
  1181. unsigned v;
  1182. v = (pixel & format->Rmask) >> format->Rshift;
  1183. *r = SDL_expand_byte[format->Rbits][v];
  1184. v = (pixel & format->Gmask) >> format->Gshift;
  1185. *g = SDL_expand_byte[format->Gbits][v];
  1186. v = (pixel & format->Bmask) >> format->Bshift;
  1187. *b = SDL_expand_byte[format->Bbits][v];
  1188. }
  1189. }
  1190. void SDL_GetRGBA(Uint32 pixel, const SDL_PixelFormatDetails *format, const SDL_Palette *palette, Uint8 *r, Uint8 *g, Uint8 *b, Uint8 *a)
  1191. {
  1192. Uint8 unused;
  1193. if (!r) {
  1194. r = &unused;
  1195. }
  1196. if (!g) {
  1197. g = &unused;
  1198. }
  1199. if (!b) {
  1200. b = &unused;
  1201. }
  1202. if (!a) {
  1203. a = &unused;
  1204. }
  1205. if (!format) {
  1206. *r = *g = *b = *a = 0;
  1207. return;
  1208. }
  1209. if (SDL_ISPIXELFORMAT_INDEXED(format->format)) {
  1210. if (palette && pixel < (unsigned)palette->ncolors) {
  1211. *r = palette->colors[pixel].r;
  1212. *g = palette->colors[pixel].g;
  1213. *b = palette->colors[pixel].b;
  1214. *a = palette->colors[pixel].a;
  1215. } else {
  1216. *r = *g = *b = *a = 0;
  1217. }
  1218. return;
  1219. }
  1220. if (SDL_ISPIXELFORMAT_10BIT(format->format)) {
  1221. unsigned v;
  1222. v = (pixel & format->Rmask) >> format->Rshift;
  1223. *r = (Uint8)(v >> 2);
  1224. v = (pixel & format->Gmask) >> format->Gshift;
  1225. *g = (Uint8)(v >> 2);
  1226. v = (pixel & format->Bmask) >> format->Bshift;
  1227. *b = (Uint8)(v >> 2);
  1228. v = (pixel & format->Amask) >> format->Ashift;
  1229. *a = SDL_expand_byte[format->Abits][v];
  1230. } else {
  1231. unsigned v;
  1232. v = (pixel & format->Rmask) >> format->Rshift;
  1233. *r = SDL_expand_byte[format->Rbits][v];
  1234. v = (pixel & format->Gmask) >> format->Gshift;
  1235. *g = SDL_expand_byte[format->Gbits][v];
  1236. v = (pixel & format->Bmask) >> format->Bshift;
  1237. *b = SDL_expand_byte[format->Bbits][v];
  1238. v = (pixel & format->Amask) >> format->Ashift;
  1239. *a = SDL_expand_byte[format->Abits][v];
  1240. }
  1241. }
  1242. // Map from Palette to Palette
  1243. static Uint8 *Map1to1(const SDL_Palette *src, const SDL_Palette *dst, int *identical)
  1244. {
  1245. Uint8 *map;
  1246. int i;
  1247. if (identical) {
  1248. if (src->ncolors <= dst->ncolors) {
  1249. // If an identical palette, no need to map
  1250. if (src == dst ||
  1251. (SDL_memcmp(src->colors, dst->colors,
  1252. src->ncolors * sizeof(SDL_Color)) == 0)) {
  1253. *identical = 1;
  1254. return NULL;
  1255. }
  1256. }
  1257. *identical = 0;
  1258. }
  1259. map = (Uint8 *)SDL_calloc(256, sizeof(Uint8));
  1260. if (!map) {
  1261. return NULL;
  1262. }
  1263. for (i = 0; i < src->ncolors; ++i) {
  1264. map[i] = SDL_FindColor(dst,
  1265. src->colors[i].r, src->colors[i].g,
  1266. src->colors[i].b, src->colors[i].a);
  1267. }
  1268. return map;
  1269. }
  1270. // Map from Palette to BitField
  1271. static Uint8 *Map1toN(const SDL_Palette *pal, Uint8 Rmod, Uint8 Gmod, Uint8 Bmod, Uint8 Amod, const SDL_PixelFormatDetails *dst)
  1272. {
  1273. Uint8 *map;
  1274. int i;
  1275. int bpp;
  1276. if (!pal) {
  1277. SDL_SetError("src does not have a palette set");
  1278. return NULL;
  1279. }
  1280. bpp = ((SDL_BYTESPERPIXEL(dst->format) == 3) ? 4 : SDL_BYTESPERPIXEL(dst->format));
  1281. map = (Uint8 *)SDL_calloc(256, bpp);
  1282. if (!map) {
  1283. return NULL;
  1284. }
  1285. // We memory copy to the pixel map so the endianness is preserved
  1286. for (i = 0; i < pal->ncolors; ++i) {
  1287. Uint8 R = (Uint8)((pal->colors[i].r * Rmod) / 255);
  1288. Uint8 G = (Uint8)((pal->colors[i].g * Gmod) / 255);
  1289. Uint8 B = (Uint8)((pal->colors[i].b * Bmod) / 255);
  1290. Uint8 A = (Uint8)((pal->colors[i].a * Amod) / 255);
  1291. ASSEMBLE_RGBA(&map[i * bpp], SDL_BYTESPERPIXEL(dst->format), dst, (Uint32)R,
  1292. (Uint32)G, (Uint32)B, (Uint32)A);
  1293. }
  1294. return map;
  1295. }
  1296. bool SDL_ValidateMap(SDL_Surface *src, SDL_Surface *dst)
  1297. {
  1298. SDL_BlitMap *map = &src->map;
  1299. if (map->info.dst_fmt != dst->fmt ||
  1300. map->info.dst_pal != dst->palette ||
  1301. (dst->palette &&
  1302. map->dst_palette_version != dst->palette->version) ||
  1303. (src->palette &&
  1304. map->src_palette_version != src->palette->version)) {
  1305. if (!SDL_MapSurface(src, dst)) {
  1306. return false;
  1307. }
  1308. // just here for debugging
  1309. // printf
  1310. // ("src = 0x%08X src->flags = %08X map->info.flags = %08x\ndst = 0x%08X dst->flags = %08X dst->map.info.flags = %08X\nmap->blit = 0x%08x\n",
  1311. // src, dst->flags, map->info.flags, dst, dst->flags,
  1312. // dst->map.info.flags, map->blit);
  1313. } else {
  1314. map->info.dst_surface = dst;
  1315. }
  1316. return true;
  1317. }
  1318. void SDL_InvalidateMap(SDL_BlitMap *map)
  1319. {
  1320. map->info.dst_fmt = NULL;
  1321. map->info.dst_pal = NULL;
  1322. map->src_palette_version = 0;
  1323. map->dst_palette_version = 0;
  1324. if (map->info.table) {
  1325. SDL_free(map->info.table);
  1326. map->info.table = NULL;
  1327. }
  1328. if (map->info.palette_map) {
  1329. SDL_DestroyHashTable(map->info.palette_map);
  1330. map->info.palette_map = NULL;
  1331. }
  1332. }
  1333. bool SDL_MapSurface(SDL_Surface *src, SDL_Surface *dst)
  1334. {
  1335. const SDL_PixelFormatDetails *srcfmt;
  1336. const SDL_Palette *srcpal;
  1337. const SDL_PixelFormatDetails *dstfmt;
  1338. const SDL_Palette *dstpal;
  1339. SDL_BlitMap *map;
  1340. // Clear out any previous mapping
  1341. map = &src->map;
  1342. #if SDL_HAVE_RLE
  1343. if (src->internal_flags & SDL_INTERNAL_SURFACE_RLEACCEL) {
  1344. SDL_UnRLESurface(src, true);
  1345. }
  1346. #endif
  1347. SDL_InvalidateMap(map);
  1348. // Figure out what kind of mapping we're doing
  1349. map->identity = 0;
  1350. srcfmt = src->fmt;
  1351. srcpal = src->palette;
  1352. dstfmt = dst->fmt;
  1353. dstpal = dst->palette;
  1354. if (SDL_ISPIXELFORMAT_INDEXED(srcfmt->format)) {
  1355. if (SDL_ISPIXELFORMAT_INDEXED(dstfmt->format)) {
  1356. // Palette --> Palette
  1357. if (srcpal && dstpal) {
  1358. map->info.table = Map1to1(srcpal, dstpal, &map->identity);
  1359. } else {
  1360. map->identity = 1;
  1361. }
  1362. if (!map->identity) {
  1363. if (!map->info.table) {
  1364. return false;
  1365. }
  1366. }
  1367. if (srcfmt->bits_per_pixel != dstfmt->bits_per_pixel) {
  1368. map->identity = 0;
  1369. }
  1370. } else {
  1371. // Palette --> BitField
  1372. map->info.table =
  1373. Map1toN(srcpal, src->map.info.r, src->map.info.g,
  1374. src->map.info.b, src->map.info.a, dstfmt);
  1375. if (!map->info.table) {
  1376. return false;
  1377. }
  1378. }
  1379. } else {
  1380. if (SDL_ISPIXELFORMAT_INDEXED(dstfmt->format)) {
  1381. // BitField --> Palette
  1382. map->info.palette_map = SDL_CreateHashTable(NULL, 32, SDL_HashID, SDL_KeyMatchID, NULL, false);
  1383. } else {
  1384. // BitField --> BitField
  1385. if (srcfmt == dstfmt) {
  1386. map->identity = 1;
  1387. }
  1388. }
  1389. }
  1390. if (dstpal) {
  1391. map->dst_palette_version = dstpal->version;
  1392. } else {
  1393. map->dst_palette_version = 0;
  1394. }
  1395. if (srcpal) {
  1396. map->src_palette_version = srcpal->version;
  1397. } else {
  1398. map->src_palette_version = 0;
  1399. }
  1400. // Choose your blitters wisely
  1401. return SDL_CalculateBlit(src, dst);
  1402. }