SDL_gfxBlitFunc.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637
  1. /*
  2. SDL_gfxBlitFunc.c: custom blitters
  3. Copyright (C) 2001-2012 Andreas Schiffler
  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
  17. distribution.
  18. Andreas Schiffler -- aschiffler at ferzkopp dot net
  19. */
  20. #include "SDL_gfxBlitFunc.h"
  21. /*!
  22. \brief Alpha adjustment table for custom blitter.
  23. The table provides values for a modified, non-linear
  24. transfer function which maintain brightness.
  25. */
  26. const unsigned int GFX_ALPHA_ADJUST_ARRAY[256] = {
  27. 0, /* 0 */
  28. 15, /* 1 */
  29. 22, /* 2 */
  30. 27, /* 3 */
  31. 31, /* 4 */
  32. 35, /* 5 */
  33. 39, /* 6 */
  34. 42, /* 7 */
  35. 45, /* 8 */
  36. 47, /* 9 */
  37. 50, /* 10 */
  38. 52, /* 11 */
  39. 55, /* 12 */
  40. 57, /* 13 */
  41. 59, /* 14 */
  42. 61, /* 15 */
  43. 63, /* 16 */
  44. 65, /* 17 */
  45. 67, /* 18 */
  46. 69, /* 19 */
  47. 71, /* 20 */
  48. 73, /* 21 */
  49. 74, /* 22 */
  50. 76, /* 23 */
  51. 78, /* 24 */
  52. 79, /* 25 */
  53. 81, /* 26 */
  54. 82, /* 27 */
  55. 84, /* 28 */
  56. 85, /* 29 */
  57. 87, /* 30 */
  58. 88, /* 31 */
  59. 90, /* 32 */
  60. 91, /* 33 */
  61. 93, /* 34 */
  62. 94, /* 35 */
  63. 95, /* 36 */
  64. 97, /* 37 */
  65. 98, /* 38 */
  66. 99, /* 39 */
  67. 100, /* 40 */
  68. 102, /* 41 */
  69. 103, /* 42 */
  70. 104, /* 43 */
  71. 105, /* 44 */
  72. 107, /* 45 */
  73. 108, /* 46 */
  74. 109, /* 47 */
  75. 110, /* 48 */
  76. 111, /* 49 */
  77. 112, /* 50 */
  78. 114, /* 51 */
  79. 115, /* 52 */
  80. 116, /* 53 */
  81. 117, /* 54 */
  82. 118, /* 55 */
  83. 119, /* 56 */
  84. 120, /* 57 */
  85. 121, /* 58 */
  86. 122, /* 59 */
  87. 123, /* 60 */
  88. 124, /* 61 */
  89. 125, /* 62 */
  90. 126, /* 63 */
  91. 127, /* 64 */
  92. 128, /* 65 */
  93. 129, /* 66 */
  94. 130, /* 67 */
  95. 131, /* 68 */
  96. 132, /* 69 */
  97. 133, /* 70 */
  98. 134, /* 71 */
  99. 135, /* 72 */
  100. 136, /* 73 */
  101. 137, /* 74 */
  102. 138, /* 75 */
  103. 139, /* 76 */
  104. 140, /* 77 */
  105. 141, /* 78 */
  106. 141, /* 79 */
  107. 142, /* 80 */
  108. 143, /* 81 */
  109. 144, /* 82 */
  110. 145, /* 83 */
  111. 146, /* 84 */
  112. 147, /* 85 */
  113. 148, /* 86 */
  114. 148, /* 87 */
  115. 149, /* 88 */
  116. 150, /* 89 */
  117. 151, /* 90 */
  118. 152, /* 91 */
  119. 153, /* 92 */
  120. 153, /* 93 */
  121. 154, /* 94 */
  122. 155, /* 95 */
  123. 156, /* 96 */
  124. 157, /* 97 */
  125. 158, /* 98 */
  126. 158, /* 99 */
  127. 159, /* 100 */
  128. 160, /* 101 */
  129. 161, /* 102 */
  130. 162, /* 103 */
  131. 162, /* 104 */
  132. 163, /* 105 */
  133. 164, /* 106 */
  134. 165, /* 107 */
  135. 165, /* 108 */
  136. 166, /* 109 */
  137. 167, /* 110 */
  138. 168, /* 111 */
  139. 168, /* 112 */
  140. 169, /* 113 */
  141. 170, /* 114 */
  142. 171, /* 115 */
  143. 171, /* 116 */
  144. 172, /* 117 */
  145. 173, /* 118 */
  146. 174, /* 119 */
  147. 174, /* 120 */
  148. 175, /* 121 */
  149. 176, /* 122 */
  150. 177, /* 123 */
  151. 177, /* 124 */
  152. 178, /* 125 */
  153. 179, /* 126 */
  154. 179, /* 127 */
  155. 180, /* 128 */
  156. 181, /* 129 */
  157. 182, /* 130 */
  158. 182, /* 131 */
  159. 183, /* 132 */
  160. 184, /* 133 */
  161. 184, /* 134 */
  162. 185, /* 135 */
  163. 186, /* 136 */
  164. 186, /* 137 */
  165. 187, /* 138 */
  166. 188, /* 139 */
  167. 188, /* 140 */
  168. 189, /* 141 */
  169. 190, /* 142 */
  170. 190, /* 143 */
  171. 191, /* 144 */
  172. 192, /* 145 */
  173. 192, /* 146 */
  174. 193, /* 147 */
  175. 194, /* 148 */
  176. 194, /* 149 */
  177. 195, /* 150 */
  178. 196, /* 151 */
  179. 196, /* 152 */
  180. 197, /* 153 */
  181. 198, /* 154 */
  182. 198, /* 155 */
  183. 199, /* 156 */
  184. 200, /* 157 */
  185. 200, /* 158 */
  186. 201, /* 159 */
  187. 201, /* 160 */
  188. 202, /* 161 */
  189. 203, /* 162 */
  190. 203, /* 163 */
  191. 204, /* 164 */
  192. 205, /* 165 */
  193. 205, /* 166 */
  194. 206, /* 167 */
  195. 206, /* 168 */
  196. 207, /* 169 */
  197. 208, /* 170 */
  198. 208, /* 171 */
  199. 209, /* 172 */
  200. 210, /* 173 */
  201. 210, /* 174 */
  202. 211, /* 175 */
  203. 211, /* 176 */
  204. 212, /* 177 */
  205. 213, /* 178 */
  206. 213, /* 179 */
  207. 214, /* 180 */
  208. 214, /* 181 */
  209. 215, /* 182 */
  210. 216, /* 183 */
  211. 216, /* 184 */
  212. 217, /* 185 */
  213. 217, /* 186 */
  214. 218, /* 187 */
  215. 218, /* 188 */
  216. 219, /* 189 */
  217. 220, /* 190 */
  218. 220, /* 191 */
  219. 221, /* 192 */
  220. 221, /* 193 */
  221. 222, /* 194 */
  222. 222, /* 195 */
  223. 223, /* 196 */
  224. 224, /* 197 */
  225. 224, /* 198 */
  226. 225, /* 199 */
  227. 225, /* 200 */
  228. 226, /* 201 */
  229. 226, /* 202 */
  230. 227, /* 203 */
  231. 228, /* 204 */
  232. 228, /* 205 */
  233. 229, /* 206 */
  234. 229, /* 207 */
  235. 230, /* 208 */
  236. 230, /* 209 */
  237. 231, /* 210 */
  238. 231, /* 211 */
  239. 232, /* 212 */
  240. 233, /* 213 */
  241. 233, /* 214 */
  242. 234, /* 215 */
  243. 234, /* 216 */
  244. 235, /* 217 */
  245. 235, /* 218 */
  246. 236, /* 219 */
  247. 236, /* 220 */
  248. 237, /* 221 */
  249. 237, /* 222 */
  250. 238, /* 223 */
  251. 238, /* 224 */
  252. 239, /* 225 */
  253. 240, /* 226 */
  254. 240, /* 227 */
  255. 241, /* 228 */
  256. 241, /* 229 */
  257. 242, /* 230 */
  258. 242, /* 231 */
  259. 243, /* 232 */
  260. 243, /* 233 */
  261. 244, /* 234 */
  262. 244, /* 235 */
  263. 245, /* 236 */
  264. 245, /* 237 */
  265. 246, /* 238 */
  266. 246, /* 239 */
  267. 247, /* 240 */
  268. 247, /* 241 */
  269. 248, /* 242 */
  270. 248, /* 243 */
  271. 249, /* 244 */
  272. 249, /* 245 */
  273. 250, /* 246 */
  274. 250, /* 247 */
  275. 251, /* 248 */
  276. 251, /* 249 */
  277. 252, /* 250 */
  278. 252, /* 251 */
  279. 253, /* 252 */
  280. 253, /* 253 */
  281. 254, /* 254 */
  282. 255 /* 255 */
  283. };
  284. /*!
  285. \brief Internal blitter using adjusted destination alpha during RGBA->RGBA blits.
  286. Performs the blit based on the 'info' structure and applies the transfer function
  287. to the destination 'a' values.
  288. \param info The blit info to use.
  289. */
  290. void _SDL_gfxBlitBlitterRGBA(SDL_gfxBlitInfo *info) {
  291. int width = info->d_width;
  292. int height = info->d_height;
  293. Uint8 *src = info->s_pixels;
  294. int srcskip = info->s_skip;
  295. Uint8 *dst = info->d_pixels;
  296. int dstskip = info->d_skip;
  297. SDL_PixelFormat *srcfmt = info->src;
  298. SDL_PixelFormat *dstfmt = info->dst;
  299. Uint8 srcbpp = srcfmt->BytesPerPixel;
  300. Uint8 dstbpp = dstfmt->BytesPerPixel;
  301. while (height--) {
  302. GFX_DUFFS_LOOP4({
  303. Uint32 pixel;
  304. unsigned sR;
  305. unsigned sG;
  306. unsigned sB;
  307. unsigned sA;
  308. unsigned dR;
  309. unsigned dG;
  310. unsigned dB;
  311. unsigned dA;
  312. unsigned sAA;
  313. GFX_DISASSEMBLE_RGBA(src, srcbpp, srcfmt, pixel, sR, sG, sB, sA);
  314. GFX_DISASSEMBLE_RGBA(dst, dstbpp, dstfmt, pixel, dR, dG, dB, dA);
  315. sAA = GFX_ALPHA_ADJUST_ARRAY[sA & 255];
  316. GFX_ALPHA_BLEND(sR, sG, sB, sAA, dR, dG, dB);
  317. dA |= sAA;
  318. GFX_ASSEMBLE_RGBA(dst, dstbpp, dstfmt, dR, dG, dB, dA);
  319. src += srcbpp;
  320. dst += dstbpp;
  321. }, width);
  322. src += srcskip;
  323. dst += dstskip;
  324. }
  325. }
  326. /*!
  327. \brief Internal blitter setup wrapper for RGBA->RGBA blits.
  328. Sets up the blitter info based on the 'src' and 'dst' surfaces and rectangles.
  329. \param src The source surface.
  330. \param srcrect The source rectangle.
  331. \param dst The destination surface.
  332. \param dstrect The destination rectangle.
  333. \returns Returns 1 if blit was performed, 0 otherwise.
  334. */
  335. int _SDL_gfxBlitRGBACall(SDL_Surface *src, SDL_Rect *srcrect, SDL_Surface *dst, SDL_Rect *dstrect) {
  336. /*
  337. * Set up source and destination buffer pointers, then blit
  338. */
  339. if (srcrect->w && srcrect->h) {
  340. SDL_gfxBlitInfo info;
  341. /*
  342. * Set up the blit information
  343. */
  344. #if (SDL_MINOR_VERSION == 3)
  345. info.s_pixels = (Uint8 *) src->pixels + (Uint16) srcrect->y * src->pitch + (Uint16) srcrect->x * src->format->BytesPerPixel;
  346. #else
  347. info.s_pixels = (Uint8 *) src->pixels + src->offset + (Uint16) srcrect->y * src->pitch +
  348. (Uint16) srcrect->x * src->format->BytesPerPixel;
  349. #endif
  350. info.s_width = srcrect->w;
  351. info.s_height = srcrect->h;
  352. info.s_skip = (int) (src->pitch - info.s_width * src->format->BytesPerPixel);
  353. #if (SDL_MINOR_VERSION == 3)
  354. info.d_pixels = (Uint8 *) dst->pixels + (Uint16) dstrect->y * dst->pitch + (Uint16) dstrect->x * dst->format->BytesPerPixel;
  355. #else
  356. info.d_pixels = (Uint8 *) dst->pixels + dst->offset + (Uint16) dstrect->y * dst->pitch +
  357. (Uint16) dstrect->x * dst->format->BytesPerPixel;
  358. #endif
  359. info.d_width = dstrect->w;
  360. info.d_height = dstrect->h;
  361. info.d_skip = (int) (dst->pitch - info.d_width * dst->format->BytesPerPixel);
  362. info.aux_data = NULL;
  363. info.src = src->format;
  364. info.table = NULL;
  365. info.dst = dst->format;
  366. /*
  367. * Run the actual software blitter
  368. */
  369. _SDL_gfxBlitBlitterRGBA(&info);
  370. return 1;
  371. }
  372. return (0);
  373. }
  374. /*!
  375. \brief Blitter for RGBA->RGBA blits with alpha adjustment.
  376. Verifies the input 'src' and 'dst' surfaces and rectangles and performs blit.
  377. The destination clip rectangle is honored.
  378. \param src The source surface.
  379. \param srcrect The source rectangle.
  380. \param dst The destination surface.
  381. \param dstrect The destination rectangle.
  382. \returns Returns 1 if blit was performed, 0 otherwise, or -1 if an error occured.
  383. */
  384. int SDL_gfxBlitRGBA(SDL_Surface *src, SDL_Rect *srcrect, SDL_Surface *dst, SDL_Rect *dstrect) {
  385. SDL_Rect sr, dr;
  386. int srcx, srcy, w, h;
  387. /*
  388. * Make sure the surfaces aren't locked
  389. */
  390. if (!src || !dst) {
  391. SDL_SetError("SDL_UpperBlit: passed a NULL surface");
  392. return (-1);
  393. }
  394. if ((src->locked) || (dst->locked)) {
  395. SDL_SetError("Surfaces must not be locked during blit");
  396. return (-1);
  397. }
  398. /*
  399. * If the destination rectangle is NULL, use the entire dest surface
  400. */
  401. if (dstrect == NULL) {
  402. dr.x = dr.y = 0;
  403. dr.w = dst->w;
  404. dr.h = dst->h;
  405. } else {
  406. dr = *dstrect;
  407. }
  408. /*
  409. * Clip the source rectangle to the source surface
  410. */
  411. if (srcrect) {
  412. int maxw, maxh;
  413. srcx = srcrect->x;
  414. w = srcrect->w;
  415. if (srcx < 0) {
  416. w += srcx;
  417. dr.x -= srcx;
  418. srcx = 0;
  419. }
  420. maxw = src->w - srcx;
  421. if (maxw < w)
  422. w = maxw;
  423. srcy = srcrect->y;
  424. h = srcrect->h;
  425. if (srcy < 0) {
  426. h += srcy;
  427. dr.y -= srcy;
  428. srcy = 0;
  429. }
  430. maxh = src->h - srcy;
  431. if (maxh < h)
  432. h = maxh;
  433. } else {
  434. srcx = srcy = 0;
  435. w = src->w;
  436. h = src->h;
  437. }
  438. /*
  439. * Clip the destination rectangle against the clip rectangle
  440. */
  441. {
  442. SDL_Rect *clip = &dst->clip_rect;
  443. int dx, dy;
  444. dx = clip->x - dr.x;
  445. if (dx > 0) {
  446. w -= dx;
  447. dr.x += dx;
  448. srcx += dx;
  449. }
  450. dx = dr.x + w - clip->x - clip->w;
  451. if (dx > 0)
  452. w -= dx;
  453. dy = clip->y - dr.y;
  454. if (dy > 0) {
  455. h -= dy;
  456. dr.y += dy;
  457. srcy += dy;
  458. }
  459. dy = dr.y + h - clip->y - clip->h;
  460. if (dy > 0)
  461. h -= dy;
  462. }
  463. if (w > 0 && h > 0) {
  464. sr.x = srcx;
  465. sr.y = srcy;
  466. sr.w = dr.w = w;
  467. sr.h = dr.h = h;
  468. return (_SDL_gfxBlitRGBACall(src, &sr, dst, &dr));
  469. }
  470. return 0;
  471. }
  472. /*!
  473. \brief Sets the alpha channel in a 32 bit surface.
  474. Helper function that sets the alpha channel in a 32 bit surface
  475. to a constant value.
  476. Only 32 bit surfaces can be used with this function.
  477. \param src Pointer to the target surface to change.
  478. \param a The alpha value to set.
  479. \return Returns 1 if alpha was changed, -1 otherwise.
  480. */
  481. int SDL_gfxSetAlpha(SDL_Surface *src, Uint8 a) {
  482. #if SDL_BYTEORDER == SDL_BIG_ENDIAN
  483. const int alpha_offset = 0;
  484. #else
  485. const int alpha_offset = 3;
  486. #endif
  487. int i, j, row_skip;
  488. Uint8 *pixels;
  489. /* Check if we have a 32bit surface */
  490. if ((src == NULL) ||
  491. (src->format == NULL) ||
  492. (src->format->BytesPerPixel != 4)) {
  493. SDL_SetError("SDL_gfxSetAlpha: Invalid input surface.");
  494. return -1;
  495. }
  496. /*
  497. * Lock the surface
  498. */
  499. if (SDL_MUSTLOCK(src)) {
  500. if (SDL_LockSurface(src) < 0) {
  501. return (-1);
  502. }
  503. }
  504. /* Process */
  505. pixels = (Uint8 *) src->pixels;
  506. row_skip = (src->pitch - (4 * src->w));
  507. pixels += alpha_offset;
  508. for (i = 0; i < src->h; i++) {
  509. for (j = 0; j < src->w; j++) {
  510. *pixels = a;
  511. pixels += 4;
  512. }
  513. pixels += row_skip;
  514. }
  515. /*
  516. * Unlock surface
  517. */
  518. if (SDL_MUSTLOCK(src)) {
  519. SDL_UnlockSurface(src);
  520. }
  521. return 1;
  522. }
  523. /*!
  524. \brief Multiply the alpha channel in a 32bit surface.
  525. Helper function that multiplies the alpha channel in a 32 bit surface
  526. with a constant value. The final alpha is always scaled to the range
  527. 0-255 (i.e. the factor is a/256).
  528. Only 32 bit surfaces can be used with this function.
  529. \param src Pointer to the target surface to change.
  530. \param a The alpha value to multiply with. When a is 255, this function is a NoOp.
  531. \return Returns 1 if alpha was changed, 0 otherwise. Returns -1 if input surface is invalid.
  532. */
  533. int SDL_gfxMultiplyAlpha(SDL_Surface *src, Uint8 a) {
  534. #if SDL_BYTEORDER == SDL_BIG_ENDIAN
  535. const int alpha_offset = 0;
  536. #else
  537. const int alpha_offset = 3;
  538. #endif
  539. int i, j, row_skip;
  540. Uint8 *pixels;
  541. /* Check if we have a 32bit surface */
  542. if ((src == NULL) ||
  543. (src->format == NULL) ||
  544. (src->format->BytesPerPixel != 4)) {
  545. SDL_SetError("SDL_gfxMultiplyAlpha: Invalid input surface.");
  546. return -1;
  547. }
  548. /* Check if multiplication is needed */
  549. if (a == 255) {
  550. return 0;
  551. }
  552. /*
  553. * Lock the surface
  554. */
  555. if (SDL_MUSTLOCK(src)) {
  556. if (SDL_LockSurface(src) < 0) {
  557. return (-1);
  558. }
  559. }
  560. /* Process */
  561. pixels = (Uint8 *) src->pixels;
  562. row_skip = (src->pitch - (4 * src->w));
  563. pixels += alpha_offset;
  564. for (i = 0; i < src->h; i++) {
  565. for (j = 0; j < src->w; j++) {
  566. *pixels = (Uint8) (((int) (*pixels) * a) >> 8);
  567. pixels += 4;
  568. }
  569. pixels += row_skip;
  570. }
  571. /*
  572. * Unlock surface
  573. */
  574. if (SDL_MUSTLOCK(src)) {
  575. SDL_UnlockSurface(src);
  576. }
  577. return 1;
  578. }