offscr24bpp.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631
  1. //*****************************************************************************
  2. //
  3. // offscr16bpp.c - 16 BPP off-screen display buffer driver.
  4. //
  5. // Copyright (c) 2008-2010 Texas Instruments Incorporated. All rights reserved.
  6. // Software License Agreement
  7. //
  8. // Texas Instruments (TI) is supplying this software for use solely and
  9. // exclusively on TI's microcontroller products. The software is owned by
  10. // TI and/or its suppliers, and is protected under applicable copyright
  11. // laws. You may not combine this software with "viral" open-source
  12. // software in order to form a larger program.
  13. //
  14. // THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
  15. // NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
  16. // NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  17. // A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
  18. // CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
  19. // DAMAGES, FOR ANY REASON WHATSOEVER.
  20. //
  21. //
  22. //*****************************************************************************
  23. #include "debug.h"
  24. #include "grlib.h"
  25. unsigned short offset;
  26. //*****************************************************************************
  27. //
  28. //! \addtogroup primitives_api
  29. //! @{
  30. //
  31. //*****************************************************************************
  32. //*****************************************************************************
  33. //
  34. //! Translates a 24-bit RGB color to a display driver-specific color.
  35. //!
  36. //! \param pvDisplayData is a pointer to the driver-specific data for this
  37. //! display driver.
  38. //! \param ulValue is the 24-bit RGB color. The least-significant byte is the
  39. //! blue channel, the next byte is the green channel, and the third byte is the
  40. //! red channel.
  41. //!
  42. //! This function translates a 24-bit RGB color into a value that can be
  43. //! written into the display's frame buffer in order to reproduce that color,
  44. //! or the closest possible approximation of that color.
  45. //!
  46. //! \return Returns the display-driver specific color.
  47. //
  48. //*****************************************************************************
  49. static unsigned int
  50. GrOffScreen24BPPColorTranslate(void *pvDisplayData, unsigned int ulValue)
  51. {
  52. return ulValue;
  53. }
  54. //*****************************************************************************
  55. //
  56. //! Fills a rectangle.
  57. //!
  58. //! \param pvDisplayData is a pointer to the driver-specific data for this
  59. //! display driver.
  60. //! \param pRect is a pointer to the structure describing the rectangle.
  61. //! \param ulValue is the color of the rectangle.
  62. //!
  63. //! This function fills a rectangle on the display. The coordinates of the
  64. //! rectangle are assumed to be within the extents of the display, and the
  65. //! rectangle specification is fully inclusive (in other words, both sXMin and
  66. //! sXMax are drawn, along with sYMin and sYMax).
  67. //!
  68. //! \return None.
  69. //
  70. //*****************************************************************************
  71. static void
  72. GrOffScreen24BPPRectFill(void *pvDisplayData, const tRectangle *pRect,
  73. unsigned int ulValue)
  74. {
  75. unsigned char *pucData, *pucColumn;
  76. int lBytesPerRow, lX, lY;
  77. //
  78. // Check the arguments.
  79. //
  80. ASSERT(pvDisplayData);
  81. ASSERT(pRect);
  82. //
  83. // Create a character pointer for the display-specific data (which points
  84. // to the image buffer).
  85. //
  86. pucData = (unsigned char *)pvDisplayData;
  87. //
  88. // Compute the number of bytes per row in the image buffer.
  89. //
  90. lBytesPerRow = (*(unsigned short *)(pucData)) * 4;
  91. //
  92. // Get the offset to the byte of the image buffer that contains the
  93. // starting pixel.
  94. //
  95. pucData += 4 + (16 * 2) + ((lBytesPerRow * pRect->sYMin) + (pRect->sXMin * 4));
  96. //
  97. // Get the starting X and Y coordinate of the rectangle.
  98. // Also, get the number of pixels per line and the number of lines
  99. //
  100. lX = pRect->sXMin;
  101. //
  102. // Now we are at a 4 byte aligned address. We can copy word wise. We start at
  103. // the first row and fill the entire column (this offset for each row)
  104. //
  105. while((lX) <= pRect->sXMax)
  106. {
  107. for(lY = pRect->sYMin, pucColumn = pucData; lY < pRect->sYMax; lY++, pucColumn += lBytesPerRow)
  108. {
  109. *(unsigned int *)pucColumn = ulValue;
  110. }
  111. pucData += 4;
  112. lX += 1;
  113. }
  114. }
  115. //*****************************************************************************
  116. //
  117. //! Draws a horizontal line.
  118. //!
  119. //! \param pvDisplayData is a pointer to the driver-specific data for this
  120. //! display driver.
  121. //! \param lX1 is the X coordinate of the start of the line.
  122. //! \param lX2 is the X coordinate of the end of the line.
  123. //! \param lY is the Y coordinate of the line.
  124. //! \param ulValue is the color of the line.
  125. //!
  126. //! This function draws a horizontal line on the display. The coordinates of
  127. //! the line are assumed to be within the extents of the display.
  128. //!
  129. //! \return None.
  130. //
  131. //*****************************************************************************
  132. static void
  133. GrOffScreen24BPPLineDrawH(void *pvDisplayData, int lX1, int lX2, int lY,
  134. unsigned int ulValue)
  135. {
  136. unsigned char *pucData;
  137. int lBytesPerRow;
  138. //
  139. // Check the arguments.
  140. //
  141. ASSERT(pvDisplayData);
  142. //
  143. // Create a character pointer for the display-specific data (which points
  144. // to the image buffer).
  145. //
  146. pucData = (unsigned char *)pvDisplayData;
  147. //
  148. // Get the offset to the byte of the image buffer that contains the
  149. // starting pixel.
  150. //
  151. lBytesPerRow = (*(unsigned short *)(pucData)) * 4;
  152. //
  153. // Get the offset to the byte of the image buffer that contains the
  154. // starting pixel.
  155. //
  156. pucData += ((lBytesPerRow * lY) + (lX1 * 4) + 4 + (16*2));
  157. //
  158. // Now we are at a 4 byte aligned address. We can copy word wise. We start at
  159. //
  160. while((lX1) <= lX2)
  161. {
  162. //
  163. // Draw 1 pixel
  164. //
  165. *(unsigned int *)pucData = ulValue;
  166. pucData += 4;
  167. lX1 += 1;
  168. }
  169. }
  170. //*****************************************************************************
  171. //
  172. //! Draws a vertical line.
  173. //!
  174. //! \param pvDisplayData is a pointer to the driver-specific data for this
  175. //! display driver.
  176. //! \param lX is the X coordinate of the line.
  177. //! \param lY1 is the Y coordinate of the start of the line.
  178. //! \param lY2 is the Y coordinate of the end of the line.
  179. //! \param ulValue is the color of the line.
  180. //!
  181. //! This function draws a vertical line on the display. The coordinates of the
  182. //! line are assumed to be within the extents of the display.
  183. //!
  184. //! \return None.
  185. //
  186. //*****************************************************************************
  187. static void
  188. GrOffScreen24BPPLineDrawV(void *pvDisplayData, int lX, int lY1, int lY2,
  189. unsigned int ulValue)
  190. {
  191. unsigned char *pucData;
  192. int lBytesPerRow;
  193. //
  194. // Check the arguments.
  195. //
  196. ASSERT(pvDisplayData);
  197. //
  198. // Create a character pointer for the display-specific data (which points
  199. // to the image buffer).
  200. //
  201. pucData = (unsigned char *)pvDisplayData;
  202. //
  203. // Compute the number of bytes per row in the image buffer.
  204. //
  205. lBytesPerRow = (*(unsigned short *)(pucData)) * 4;
  206. //
  207. // Get the offset to the byte of the image buffer that contains the
  208. // starting pixel.
  209. //
  210. pucData += ((lBytesPerRow * lY1) + (lX * 4) + 4 + (16*2));
  211. //
  212. // Loop over the rows of the line.
  213. //
  214. for(; lY1 <= lY2; lY1++)
  215. {
  216. *(unsigned int *)pucData = ulValue;
  217. pucData += lBytesPerRow;
  218. }
  219. }
  220. //*****************************************************************************
  221. //
  222. //! Draws a pixel on the screen.
  223. //!
  224. //! \param pvDisplayData is a pointer to the driver-specific data for this
  225. //! display driver.
  226. //! \param lX is the X coordinate of the pixel.
  227. //! \param lY is the Y coordinate of the pixel.
  228. //! \param ulValue is the color of the pixel.
  229. //!
  230. //! This function sets the given pixel to a particular color. The coordinates
  231. //! of the pixel are assumed to be within the extents of the display.
  232. //!
  233. //! \return None.
  234. //
  235. //*****************************************************************************
  236. static void
  237. GrOffScreen24BPPPixelDraw(void *pvDisplayData, int lX, int lY,
  238. unsigned int ulValue)
  239. {
  240. unsigned char *pucData;
  241. int lBytesPerRow;
  242. //
  243. // Check the arguments.
  244. //
  245. ASSERT(pvDisplayData);
  246. //
  247. // Create a character pointer for the display-specific data (which points
  248. // to the image buffer).
  249. //
  250. pucData = (unsigned char *)pvDisplayData;
  251. //
  252. // Get the offset to the byte of the image buffer that contains the pixel
  253. // in question.
  254. //
  255. lBytesPerRow = (*(unsigned short *)(pucData)) * 4;
  256. //
  257. // Get the offset to the byte of the image buffer that contains the
  258. // starting pixel.
  259. //
  260. pucData += (lBytesPerRow * lY) + (lX * 4) + 4 + (16*2);
  261. //pucData += (*(unsigned short *)(pucData + 1) * lY * 2) + (lX * 2) + 4 + (16*2);
  262. //
  263. // Write this pixel into the image buffer.
  264. //
  265. *(unsigned int *)pucData = ulValue;
  266. }
  267. //*****************************************************************************
  268. //
  269. //! Draws a horizontal sequence of pixels on the screen.
  270. //!
  271. //! \param pvDisplayData is a pointer to the driver-specific data for this
  272. //! display driver.
  273. //! \param lX is the X coordinate of the first pixel.
  274. //! \param lY is the Y coordinate of the first pixel.
  275. //! \param lX0 is sub-pixel offset within the pixel data, which is valid for 1
  276. //! or 4 bit per pixel formats.
  277. //! \param lCount is the number of pixels to draw.
  278. //! \param lBPP is the number of bits per pixel; must be 1, 4, 8, 16, or 24.
  279. //! \param pucData is a pointer to the pixel data. For 1 and 4 bit per pixel
  280. //! formats, the most significant bit(s) represent the left-most pixel.
  281. //! \param pucPalette is a pointer to the palette used to draw the pixels.
  282. //!
  283. //! This function draws a horizontal sequence of pixels on the screen, using
  284. //! the supplied palette. For 1 bit per pixel format, the palette contains
  285. //! pre-translated colors; for 4 and 8 bit per pixel formats, the palette
  286. //! contains 24-bit RGB values that must be translated before being written to
  287. //! the display.
  288. //!
  289. //! \return None.
  290. //
  291. //*****************************************************************************
  292. static void
  293. GrOffScreen24BPPPixelDrawMultiple(void *pvDisplayData, int lX, int lY,
  294. int lX0, int lCount, int lBPP,
  295. const unsigned char *pucData,
  296. const unsigned char *pucPalette)
  297. {
  298. unsigned int ulByte;
  299. int lBytesPerRow;
  300. unsigned char *pucPtr;
  301. //
  302. // Check the arguments.
  303. //
  304. ASSERT(pvDisplayData);
  305. ASSERT(pucData);
  306. ASSERT(pucPalette);
  307. //
  308. // Create a character pointer for the display-specific data (which points
  309. // to the image buffer).
  310. //
  311. pucPtr = (unsigned char *)pvDisplayData;
  312. //
  313. // Compute the number of bytes per row in the image buffer.
  314. //
  315. lBytesPerRow = (*(unsigned short *)(pucPtr)) * 4;
  316. //
  317. // Get the offset to the byte of the image buffer that contains the
  318. // starting pixel.
  319. //
  320. pucPtr += (lBytesPerRow * lY) + (lX * 4) + 4 + (16*2);
  321. //
  322. // Determine how much to shift to get to the nibble that contains this
  323. // pixel.
  324. //
  325. lX = (1 - (lX & 1)) * 4;
  326. //
  327. // Determine how to interpret the pixel data based on the number of bits
  328. // per pixel.
  329. //
  330. switch(lBPP)
  331. {
  332. //
  333. // The pixel data is in 1 bit per pixel format.
  334. //
  335. case 1:
  336. {
  337. //
  338. // Loop while there are more pixels to draw.
  339. //
  340. while(lCount)
  341. {
  342. //
  343. // Get the next byte of image data.
  344. //
  345. ulByte = *pucData++;
  346. //
  347. // Loop through the pixels in this byte of image data.
  348. //
  349. for(; (lX0 < 8) && lCount; lX0++, lCount--)
  350. {
  351. //
  352. // Draw this pixel in the appropriate color.
  353. //
  354. ulByte = ((*pucPtr & ~(0xf << lX)) |
  355. (((unsigned int *)pucPalette)[(ulByte >>
  356. (7 - lX0)) &
  357. 1] << lX));
  358. //
  359. // Write this pixel to the screen.
  360. //
  361. *pucPtr++ = (ulByte & 0x00FF);
  362. *pucPtr++ = (ulByte & 0xFF00) >> 8;
  363. }
  364. //
  365. // Start at the beginning of the next byte of image data.
  366. //
  367. lX0 = 0;
  368. }
  369. //
  370. // The image data has been drawn.
  371. //
  372. break;
  373. }
  374. //
  375. // The pixel data is in 4 bit per pixel format.
  376. //
  377. case 4:
  378. {
  379. //
  380. // Loop while there are more pixels to draw. "Duff's device" is
  381. // used to jump into the middle of the loop if the first nibble of
  382. // the pixel data should not be used. Duff's device makes use of
  383. // the fact that a case statement is legal anywhere within a
  384. // sub-block of a switch statement. See
  385. // http://en.wikipedia.org/wiki/Duff's_device for detailed
  386. // information about Duff's device.
  387. //
  388. switch(lX0 & 1)
  389. {
  390. case 0:
  391. while(lCount)
  392. {
  393. //
  394. // Get the upper nibble of the next byte of pixel data
  395. // and extract the corresponding entry from the
  396. // palette.
  397. //
  398. #ifdef SUPPORT_UNALIGNED
  399. ulByte = (*pucData >> 4) * 3;
  400. #else
  401. offset = (*pucData >> 4) * 3;
  402. ulByte = (*(unsigned char *)(pucPalette + offset));
  403. ulByte |= (*((unsigned char *)(pucPalette + offset) + 1)) << 8;
  404. ulByte |= *((unsigned char *)(pucPalette + offset) + 2) << 16;
  405. #endif
  406. //
  407. // Write this pixel to the screen.
  408. //
  409. *(unsigned int *)pucPtr = (*(unsigned int *)(pucPalette + ulByte) & 0x00ffffff);
  410. pucPtr+=4;
  411. //
  412. // Decrement the count of pixels to draw.
  413. //
  414. lCount--;
  415. //
  416. // See if there is another pixel to draw.
  417. //
  418. if(lCount)
  419. {
  420. case 1:
  421. //
  422. // Get the lower nibble of the next byte of pixel
  423. // data and extract the corresponding entry from
  424. // the palette.
  425. //
  426. #ifdef SUPPORT_UNALIGNED
  427. ulByte = (*pucData++ & 15) * 3;
  428. #else
  429. offset = (*pucData++ & 15) * 3;
  430. ulByte = (*(unsigned char *)(pucPalette + offset));
  431. ulByte |= (*((unsigned char *)(pucPalette + offset) + 1)) << 8;
  432. ulByte |= *((unsigned char *)(pucPalette + offset) + 2) << 16;
  433. #endif
  434. //
  435. // Write this pixel to the screen.
  436. //
  437. *(unsigned int *)pucPtr = (*(unsigned int *)(pucPalette + ulByte) & 0x00ffffff);
  438. pucPtr+=4;
  439. //
  440. // Decrement the count of pixels to draw.
  441. //
  442. lCount--;
  443. }
  444. }
  445. }
  446. //
  447. // The image data has been drawn.
  448. //
  449. break;
  450. }
  451. //
  452. // The pixel data is in 8 bit per pixel format.
  453. //
  454. case 8:
  455. {
  456. //
  457. // Loop while there are more pixels to draw.
  458. //
  459. while(lCount--)
  460. {
  461. //
  462. // Get the next byte of pixel data and extract the
  463. // corresponding entry from the palette.
  464. //
  465. #ifdef SUPPORT_UNALIGNED
  466. ulByte = *pucData++ * 3;
  467. ulByte = *(unsigned int *)(pucPalette + ulByte) & 0x00ffffff;
  468. #else
  469. offset = *pucData++ * 3;
  470. ulByte = (*(unsigned char *)(pucPalette + offset));
  471. ulByte |= (*((unsigned char *)(pucPalette + offset) + 1)) << 8;
  472. ulByte |= *((unsigned char *)(pucPalette + offset) + 2) << 16;
  473. #endif
  474. //
  475. // Translate this palette entry.
  476. //
  477. ulByte = GrOffScreen24BPPColorTranslate(pvDisplayData, ulByte);
  478. //
  479. // Write this pixel to the screen.
  480. //
  481. *pucPtr++ = (ulByte & 0x00FF);
  482. *pucPtr++ = (ulByte & 0xFF00) >> 8;
  483. }
  484. //
  485. // The image data has been drawn.
  486. //
  487. break;
  488. }
  489. case 16:
  490. {
  491. unsigned short pixColor = 0; /* 16bpp */
  492. pucData++;
  493. while(lCount--)
  494. {
  495. pixColor = *(pucData+1);
  496. pixColor |= (*(pucData)) << 8;
  497. *pucPtr++ = (pixColor & 0x1F) << 3; /* Blue */
  498. *pucPtr++ = (pixColor & 0x07E0) >> 3; /* Green */
  499. *pucPtr++ = (pixColor & 0x0000F800) >> 8; /* Red */
  500. *pucPtr++ = 0x0; /* Alpha */
  501. pucData += 2;
  502. }
  503. break;
  504. }
  505. case 32: /* 24bpp with 1-byte hole */
  506. {
  507. //pucData++;
  508. while(lCount--)
  509. {
  510. *pucPtr++ = *(pucData+3);
  511. *pucPtr++ = *(pucData+2);
  512. *pucPtr++ = *(pucData+1);
  513. *pucPtr++ = *(pucData+0);
  514. pucData += 4;
  515. }
  516. break;
  517. }
  518. }
  519. }
  520. //*****************************************************************************
  521. //
  522. //! Initializes a 24 BPP off-screen buffer.
  523. //!
  524. //! \param pDisplay is a pointer to the display structure to be configured for
  525. //! the 24 BPP off-screen buffer.
  526. //! \param pucImage is a pointer to the image buffer to be used for the
  527. //! off-screen buffer.
  528. //! \param lWidth is the width of the image buffer in pixels.
  529. //! \param lHeight is the height of the image buffer in pixels.
  530. //!
  531. //! This function initializes a display structure, preparing it to draw into
  532. //! the supplied image buffer. The image buffer is assumed to be large enough
  533. //! to hold an image of the specified geometry.
  534. //!
  535. //! \return None.
  536. //
  537. //*****************************************************************************
  538. void
  539. GrOffScreen24BPPInit(tDisplay *pDisplay, unsigned char *pucImage, int lWidth,
  540. int lHeight)
  541. {
  542. //
  543. // Initialize the display structure.
  544. //
  545. pDisplay->lSize = sizeof(tDisplay);
  546. pDisplay->pvDisplayData = pucImage;
  547. pDisplay->usWidth = lWidth;
  548. pDisplay->usHeight = lHeight;
  549. pDisplay->pfnPixelDraw = GrOffScreen24BPPPixelDraw;
  550. pDisplay->pfnPixelDrawMultiple = GrOffScreen24BPPPixelDrawMultiple;
  551. pDisplay->pfnLineDrawH = GrOffScreen24BPPLineDrawH;
  552. pDisplay->pfnLineDrawV = GrOffScreen24BPPLineDrawV;
  553. pDisplay->pfnRectFill = GrOffScreen24BPPRectFill;
  554. pDisplay->pfnColorTranslate = GrOffScreen24BPPColorTranslate;
  555. //pDisplay->pfnFlush = GrOffScreen24BPPFlush;
  556. /* IMAGE FORMAT */
  557. *(unsigned short *)(pucImage + 0) = lWidth;
  558. *(unsigned short *)(pucImage + 2) = lHeight;
  559. }
  560. //*****************************************************************************
  561. //
  562. // Close the Doxygen group.
  563. //! @}
  564. //
  565. //*****************************************************************************