offscr4bpp.c 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980
  1. //*****************************************************************************
  2. //
  3. // offscr4bpp.c - 4 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. // This is part of revision 6288 of the Stellaris Graphics Library.
  22. //
  23. //*****************************************************************************
  24. #include "debug.h"
  25. #include "grlib.h"
  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. GrOffScreen4BPPColorTranslate(void *pvDisplayData, unsigned int ulValue)
  51. {
  52. unsigned int ulIdx, ulDiff, ulMatchIdx, ulMatchDiff, ulR, ulG, ulB;
  53. unsigned char *pucPalette;
  54. //
  55. // Check the arguments.
  56. //
  57. ASSERT(pvDisplayData);
  58. //
  59. // Get a pointer to the palette for the off-screen buffer.
  60. //
  61. pucPalette = (unsigned char *)pvDisplayData + 6;
  62. //
  63. // Extract the red, green, and blue component from the input color.
  64. //
  65. ulR = (ulValue >> ClrRedShift) & 0xff;
  66. ulG = (ulValue >> ClrGreenShift) & 0xff;
  67. ulB = (ulValue >> ClrBlueShift) & 0xff;
  68. //
  69. // Set the match such that the first palette entry will be a better match.
  70. //
  71. ulMatchIdx = 0;
  72. ulMatchDiff = 0xffffffff;
  73. //
  74. // Loop through the colors in the palette.
  75. //
  76. for(ulIdx = 0; ulIdx < 16; ulIdx++, pucPalette += 3)
  77. {
  78. //
  79. // Compute the Cartesian distance between these two colors.
  80. //
  81. ulDiff = (((pucPalette[2] - ulR) * (pucPalette[2] - ulR)) +
  82. ((pucPalette[1] - ulG) * (pucPalette[1] - ulG)) +
  83. ((pucPalette[0] - ulB) * (pucPalette[0] - ulB)));
  84. //
  85. // See if this color is a closer match than any of the previous colors.
  86. //
  87. if(ulDiff < ulMatchDiff)
  88. {
  89. //
  90. // Save this color as the new best match.
  91. //
  92. ulMatchDiff = ulDiff;
  93. ulMatchIdx = ulIdx;
  94. }
  95. //
  96. // Stop looking if an exact match was found.
  97. //
  98. if(ulDiff == 0)
  99. {
  100. break;
  101. }
  102. }
  103. //
  104. // Return the index of the best match.
  105. //
  106. return(ulMatchIdx);
  107. }
  108. //*****************************************************************************
  109. //
  110. //! Draws a pixel on the screen.
  111. //!
  112. //! \param pvDisplayData is a pointer to the driver-specific data for this
  113. //! display driver.
  114. //! \param lX is the X coordinate of the pixel.
  115. //! \param lY is the Y coordinate of the pixel.
  116. //! \param ulValue is the color of the pixel.
  117. //!
  118. //! This function sets the given pixel to a particular color. The coordinates
  119. //! of the pixel are assumed to be within the extents of the display.
  120. //!
  121. //! \return None.
  122. //
  123. //*****************************************************************************
  124. static void
  125. GrOffScreen4BPPPixelDraw(void *pvDisplayData, int lX, int lY,
  126. unsigned int ulValue)
  127. {
  128. unsigned char *pucData;
  129. int lBytesPerRow;
  130. //
  131. // Check the arguments.
  132. //
  133. ASSERT(pvDisplayData);
  134. //
  135. // Create a character pointer for the display-specific data (which points
  136. // to the image buffer).
  137. //
  138. pucData = (unsigned char *)pvDisplayData;
  139. //
  140. // Compute the number of bytes per row in the image buffer.
  141. //
  142. lBytesPerRow = (*(unsigned short *)(pucData + 1) + 1) / 2;
  143. //
  144. // Get the offset to the byte of the image buffer that contains the pixel
  145. // in question.
  146. //
  147. pucData += (lBytesPerRow * lY) + (lX / 2) + 6 + (16 * 3);
  148. //
  149. // Determine how much to shift to get to the nibble that contains this
  150. // pixel.
  151. //
  152. lX = (1 - (lX & 1)) * 4;
  153. //
  154. // Write this pixel into the image buffer.
  155. //
  156. *pucData = (*pucData & ~(0xf << lX)) | (ulValue << lX);
  157. }
  158. //*****************************************************************************
  159. //
  160. //! Draws a horizontal sequence of pixels on the screen.
  161. //!
  162. //! \param pvDisplayData is a pointer to the driver-specific data for this
  163. //! display driver.
  164. //! \param lX is the X coordinate of the first pixel.
  165. //! \param lY is the Y coordinate of the first pixel.
  166. //! \param lX0 is sub-pixel offset within the pixel data, which is valid for 1
  167. //! or 4 bit per pixel formats.
  168. //! \param lCount is the number of pixels to draw.
  169. //! \param lBPP is the number of bits per pixel; must be 1, 4, or 8.
  170. //! \param pucData is a pointer to the pixel data. For 1 and 4 bit per pixel
  171. //! formats, the most significant bit(s) represent the left-most pixel.
  172. //! \param pucPalette is a pointer to the palette used to draw the pixels.
  173. //!
  174. //! This function draws a horizontal sequence of pixels on the screen, using
  175. //! the supplied palette. For 1 bit per pixel format, the palette contains
  176. //! pre-translated colors; for 4 and 8 bit per pixel formats, the palette
  177. //! contains 24-bit RGB values that must be translated before being written to
  178. //! the display.
  179. //!
  180. //! \return None.
  181. //
  182. //*****************************************************************************
  183. static void
  184. GrOffScreen4BPPPixelDrawMultiple(void *pvDisplayData, int lX, int lY,
  185. int lX0, int lCount, int lBPP,
  186. const unsigned char *pucData,
  187. const unsigned char *pucPalette)
  188. {
  189. unsigned char *pucPtr;
  190. unsigned int ulByte;
  191. int lBytesPerRow;
  192. //
  193. // Check the arguments.
  194. //
  195. ASSERT(pvDisplayData);
  196. ASSERT(pucData);
  197. ASSERT(pucPalette);
  198. //
  199. // Create a character pointer for the display-specific data (which points
  200. // to the image buffer).
  201. //
  202. pucPtr = (unsigned char *)pvDisplayData;
  203. //
  204. // Compute the number of bytes per row in the image buffer.
  205. //
  206. lBytesPerRow = (*(unsigned short *)(pucPtr + 1) + 1) / 2;
  207. //
  208. // Get the offset to the byte of the image buffer that contains the
  209. // starting pixel.
  210. //
  211. pucPtr += (lBytesPerRow * lY) + (lX / 2) + 6 + (16 * 3);
  212. //
  213. // Determine how much to shift to get to the nibble that contains this
  214. // pixel.
  215. //
  216. lX = (1 - (lX & 1)) * 4;
  217. //
  218. // Determine how to interpret the pixel data based on the number of bits
  219. // per pixel.
  220. //
  221. switch(lBPP)
  222. {
  223. //
  224. // The pixel data is in 1 bit per pixel format.
  225. //
  226. case 1:
  227. {
  228. //
  229. // Loop while there are more pixels to draw.
  230. //
  231. while(lCount)
  232. {
  233. //
  234. // Get the next byte of image data.
  235. //
  236. ulByte = *pucData++;
  237. //
  238. // Loop through the pixels in this byte of image data.
  239. //
  240. for(; (lX0 < 8) && lCount; lX0++, lCount--)
  241. {
  242. //
  243. // Draw this pixel in the appropriate color.
  244. //
  245. *pucPtr = ((*pucPtr & ~(0xf << lX)) |
  246. (((unsigned int *)pucPalette)[(ulByte >>
  247. (7 - lX0)) &
  248. 1] << lX));
  249. if(lX ^= 4)
  250. {
  251. pucPtr++;
  252. }
  253. }
  254. //
  255. // Start at the beginning of the next byte of image data.
  256. //
  257. lX0 = 0;
  258. }
  259. //
  260. // The image data has been drawn.
  261. //
  262. break;
  263. }
  264. //
  265. // The pixel data is in 4 bit per pixel format.
  266. //
  267. case 4:
  268. {
  269. //
  270. // Loop while there are more pixels to draw. "Duff's device" is
  271. // used to jump into the middle of the loop if the first nibble of
  272. // the pixel data should not be used. Duff's device makes use of
  273. // the fact that a case statement is legal anywhere within a
  274. // sub-block of a switch statement. See
  275. // http://en.wikipedia.org/wiki/Duff's_device for detailed
  276. // information about Duff's device.
  277. //
  278. switch(lX0 & 1)
  279. {
  280. case 0:
  281. while(lCount)
  282. {
  283. //
  284. // Get the upper nibble of the next byte of pixel data
  285. // and extract the corresponding entry from the
  286. // palette.
  287. //
  288. ulByte = (*pucData >> 4) * 3;
  289. ulByte = (*(unsigned int *)(pucPalette + ulByte) &
  290. 0x00ffffff);
  291. //
  292. // Translate this palette entry.
  293. //
  294. ulByte = GrOffScreen4BPPColorTranslate(pvDisplayData,
  295. ulByte);
  296. //
  297. // Write this pixel to the screen.
  298. //
  299. *pucPtr = (*pucPtr & ~(0xf << lX)) | (ulByte << lX);
  300. if(lX ^= 4)
  301. {
  302. pucPtr++;
  303. }
  304. //
  305. // Decrement the count of pixels to draw.
  306. //
  307. lCount--;
  308. //
  309. // See if there is another pixel to draw.
  310. //
  311. if(lCount)
  312. {
  313. case 1:
  314. //
  315. // Get the lower nibble of the next byte of pixel
  316. // data and extract the corresponding entry from
  317. // the palette.
  318. //
  319. ulByte = (*pucData++ & 15) * 3;
  320. ulByte = (*(unsigned int *)(pucPalette + ulByte) &
  321. 0x00ffffff);
  322. //
  323. // Translate this palette entry.
  324. //
  325. ulByte =
  326. GrOffScreen4BPPColorTranslate(pvDisplayData,
  327. ulByte);
  328. //
  329. // Write this pixel to the screen.
  330. //
  331. *pucPtr = ((*pucPtr & ~(0xf << lX)) |
  332. (ulByte << lX));
  333. if(lX ^= 4)
  334. {
  335. pucPtr++;
  336. }
  337. //
  338. // Decrement the count of pixels to draw.
  339. //
  340. lCount--;
  341. }
  342. }
  343. }
  344. //
  345. // The image data has been drawn.
  346. //
  347. break;
  348. }
  349. //
  350. // The pixel data is in 8 bit per pixel format.
  351. //
  352. case 8:
  353. {
  354. //
  355. // Loop while there are more pixels to draw.
  356. //
  357. while(lCount--)
  358. {
  359. //
  360. // Get the next byte of pixel data and extract the
  361. // corresponding entry from the palette.
  362. //
  363. ulByte = *pucData++ * 3;
  364. ulByte = *(unsigned int *)(pucPalette + ulByte) & 0x00ffffff;
  365. //
  366. // Translate this palette entry.
  367. //
  368. ulByte = GrOffScreen4BPPColorTranslate(pvDisplayData, ulByte);
  369. //
  370. // Write this pixel to the screen.
  371. //
  372. *pucPtr = (*pucPtr & ~(0xf << lX)) | (ulByte << lX);
  373. if(lX ^= 4)
  374. {
  375. pucPtr++;
  376. }
  377. }
  378. //
  379. // The image data has been drawn.
  380. //
  381. break;
  382. }
  383. }
  384. }
  385. //*****************************************************************************
  386. //
  387. //! Draws a horizontal line.
  388. //!
  389. //! \param pvDisplayData is a pointer to the driver-specific data for this
  390. //! display driver.
  391. //! \param lX1 is the X coordinate of the start of the line.
  392. //! \param lX2 is the X coordinate of the end of the line.
  393. //! \param lY is the Y coordinate of the line.
  394. //! \param ulValue is the color of the line.
  395. //!
  396. //! This function draws a horizontal line on the display. The coordinates of
  397. //! the line are assumed to be within the extents of the display.
  398. //!
  399. //! \return None.
  400. //
  401. //*****************************************************************************
  402. static void
  403. GrOffScreen4BPPLineDrawH(void *pvDisplayData, int lX1, int lX2, int lY,
  404. unsigned int ulValue)
  405. {
  406. unsigned char *pucData;
  407. int lBytesPerRow;
  408. //
  409. // Check the arguments.
  410. //
  411. ASSERT(pvDisplayData);
  412. //
  413. // Create a character pointer for the display-specific data (which points
  414. // to the image buffer).
  415. //
  416. pucData = (unsigned char *)pvDisplayData;
  417. //
  418. // Compute the number of bytes per row in the image buffer.
  419. //
  420. lBytesPerRow = (*(unsigned short *)(pucData + 1) + 1) / 2;
  421. //
  422. // Get the offset to the byte of the image buffer that contains the
  423. // starting pixel.
  424. //
  425. pucData += (lBytesPerRow * lY) + (lX1 / 2) + 6 + (16 * 3);
  426. //
  427. // Copy the pixel value into all 8 pixels of the unsigned int. This will
  428. // be used later to write multiple pixels into memory (as opposed to one at
  429. // a time).
  430. //
  431. ulValue = ((ulValue << 28) | (ulValue << 24) | (ulValue << 20) |
  432. (ulValue << 16) | (ulValue << 12) | (ulValue << 8) |
  433. (ulValue << 4) | ulValue);
  434. //
  435. // See if the second pixel in a byte is part of the line.
  436. //
  437. if(lX1 & 1)
  438. {
  439. //
  440. // Draw the second pixel in the byte.
  441. //
  442. *pucData = (*pucData & 0xf0) | (ulValue & 0x0f);
  443. pucData++;
  444. lX1++;
  445. }
  446. //
  447. // See if the buffer pointer is not half-word aligned and there are at
  448. // least two pixels left to draw.
  449. //
  450. if(((unsigned int)pucData & 1) && ((lX2 - lX1) > 0))
  451. {
  452. //
  453. // Draw two pixels to half-word align the buffer pointer.
  454. //
  455. *pucData++ = ulValue & 0xff;
  456. lX1 += 2;
  457. }
  458. //
  459. // See if the buffer pointer is not word aligned and there are at least
  460. // four pixels left to draw.
  461. //
  462. if(((unsigned int)pucData & 2) && ((lX2 - lX1) > 2))
  463. {
  464. //
  465. // Draw four pixels to word align the buffer pointer.
  466. //
  467. *(unsigned short *)pucData = ulValue & 0xffff;
  468. pucData += 2;
  469. lX1 += 4;
  470. }
  471. //
  472. // Loop while there are at least eight pixels left to draw.
  473. //
  474. while((lX1 + 7) <= lX2)
  475. {
  476. //
  477. // Draw eight pixels.
  478. //
  479. *(unsigned int *)pucData = ulValue;
  480. pucData += 4;
  481. lX1 += 8;
  482. }
  483. //
  484. // See if there are at least four pixels left to draw.
  485. //
  486. if((lX1 + 3) <= lX2)
  487. {
  488. //
  489. // Draw four pixels, leaving the buffer pointer half-word aligned.
  490. //
  491. *(unsigned short *)pucData = ulValue & 0xffff;
  492. pucData += 2;
  493. lX1 += 4;
  494. }
  495. //
  496. // See if there are at least two pixels left to draw.
  497. //
  498. if((lX1 + 1) <= lX2)
  499. {
  500. //
  501. // Draw two pixels, leaving the buffer pointer byte aligned.
  502. //
  503. *pucData++ = ulValue & 0xff;
  504. lX1 += 2;
  505. }
  506. //
  507. // See if there is one pixel left to draw.
  508. //
  509. if(lX1 == lX2)
  510. {
  511. //
  512. // Draw the final pixel.
  513. //
  514. *pucData = (*pucData & 0x0f) | (ulValue & 0xf0);
  515. }
  516. }
  517. //*****************************************************************************
  518. //
  519. //! Draws a vertical line.
  520. //!
  521. //! \param pvDisplayData is a pointer to the driver-specific data for this
  522. //! display driver.
  523. //! \param lX is the X coordinate of the line.
  524. //! \param lY1 is the Y coordinate of the start of the line.
  525. //! \param lY2 is the Y coordinate of the end of the line.
  526. //! \param ulValue is the color of the line.
  527. //!
  528. //! This function draws a vertical line on the display. The coordinates of the
  529. //! line are assumed to be within the extents of the display.
  530. //!
  531. //! \return None.
  532. //
  533. //*****************************************************************************
  534. static void
  535. GrOffScreen4BPPLineDrawV(void *pvDisplayData, int lX, int lY1, int lY2,
  536. unsigned int ulValue)
  537. {
  538. unsigned char *pucData;
  539. int lBytesPerRow;
  540. //
  541. // Check the arguments.
  542. //
  543. ASSERT(pvDisplayData);
  544. //
  545. // Create a character pointer for the display-specific data (which points
  546. // to the image buffer).
  547. //
  548. pucData = (unsigned char *)pvDisplayData;
  549. //
  550. // Compute the number of bytes per row in the image buffer.
  551. //
  552. lBytesPerRow = (*(unsigned short *)(pucData + 1) + 1) / 2;
  553. //
  554. // Get the offset to the byte of the image buffer that contains the
  555. // starting pixel.
  556. //
  557. pucData += (lBytesPerRow * lY1) + (lX / 2) + 6 + (16 * 3);
  558. //
  559. // See if the vertical line resides in the first or second nibble.
  560. //
  561. if(lX & 1)
  562. {
  563. //
  564. // The line resides in the second nibble. Loop over the rows of the
  565. // line.
  566. //
  567. while(lY1 <= lY2)
  568. {
  569. //
  570. // Draw this pixel of the line.
  571. //
  572. *pucData = (*pucData & 0xf0) | ulValue;
  573. pucData += lBytesPerRow;
  574. lY1++;
  575. }
  576. }
  577. else
  578. {
  579. //
  580. // The line resides in the first nibble. Loop over the rows of the
  581. // line.
  582. //
  583. ulValue <<= 4;
  584. while(lY1 <= lY2)
  585. {
  586. //
  587. // Draw this pixel of the line.
  588. //
  589. *pucData = (*pucData & 0x0f) | ulValue;
  590. pucData += lBytesPerRow;
  591. lY1++;
  592. }
  593. }
  594. }
  595. //*****************************************************************************
  596. //
  597. //! Fills a rectangle.
  598. //!
  599. //! \param pvDisplayData is a pointer to the driver-specific data for this
  600. //! display driver.
  601. //! \param pRect is a pointer to the structure describing the rectangle.
  602. //! \param ulValue is the color of the rectangle.
  603. //!
  604. //! This function fills a rectangle on the display. The coordinates of the
  605. //! rectangle are assumed to be within the extents of the display, and the
  606. //! rectangle specification is fully inclusive (in other words, both sXMin and
  607. //! sXMax are drawn, along with sYMin and sYMax).
  608. //!
  609. //! \return None.
  610. //
  611. //*****************************************************************************
  612. static void
  613. GrOffScreen4BPPRectFill(void *pvDisplayData, const tRectangle *pRect,
  614. unsigned int ulValue)
  615. {
  616. unsigned char *pucData, *pucColumn;
  617. int lBytesPerRow, lX, lY;
  618. //
  619. // Check the arguments.
  620. //
  621. ASSERT(pvDisplayData);
  622. ASSERT(pRect);
  623. //
  624. // Create a character pointer for the display-specific data (which points
  625. // to the image buffer).
  626. //
  627. pucData = (unsigned char *)pvDisplayData;
  628. //
  629. // Compute the number of bytes per row in the image buffer.
  630. //
  631. lBytesPerRow = (*(unsigned short *)(pucData + 1) + 1) / 2;
  632. //
  633. // Get the offset to the byte of the image buffer that contains the
  634. // starting pixel.
  635. //
  636. pucData += ((lBytesPerRow * pRect->sYMin) + (pRect->sXMin / 2) + 6 +
  637. (16 * 3));
  638. //
  639. // Copy the pixel value into all 8 pixels of the unsigned int. This will
  640. // be used later to write multiple pixels into memory (as opposed to one at
  641. // a time).
  642. //
  643. ulValue = ((ulValue << 28) | (ulValue << 24) | (ulValue << 20) |
  644. (ulValue << 16) | (ulValue << 12) | (ulValue << 8) |
  645. (ulValue << 4) | ulValue);
  646. //
  647. // Get the starting X coordinate of the rectangle.
  648. //
  649. lX = pRect->sXMin;
  650. //
  651. // See if the second pixel in a byte is part of the rectangle.
  652. //
  653. if(lX & 1)
  654. {
  655. //
  656. // Draw the second pixel of this column of the rectangle.
  657. //
  658. for(lY = pRect->sYMin, pucColumn = pucData; lY <= pRect->sYMax;
  659. lY++, pucColumn += lBytesPerRow)
  660. {
  661. *pucColumn = (*pucColumn & 0xf0) | (ulValue & 0x0f);
  662. }
  663. pucData++;
  664. lX++;
  665. }
  666. //
  667. // See if the buffer pointer is not half-word aligned and there are at
  668. // least two pixel columns left to draw.
  669. //
  670. if(((unsigned int)pucData & 1) && (pRect->sXMax - lX) > 0)
  671. {
  672. //
  673. // Draw two pixels in this column of the rectangle.
  674. //
  675. for(lY = pRect->sYMin, pucColumn = pucData; lY <= pRect->sYMax;
  676. lY++, pucColumn += lBytesPerRow)
  677. {
  678. *pucColumn = ulValue & 0xff;
  679. }
  680. pucData++;
  681. lX += 2;
  682. }
  683. //
  684. // See if the buffer pointer is not word aligned and there are at least
  685. // four pixel columns left to draw.
  686. //
  687. if(((unsigned int)pucData & 2) && ((pRect->sXMax - lX) > 2))
  688. {
  689. //
  690. // Draw four pixels in this column of the rectangle.
  691. //
  692. for(lY = pRect->sYMin, pucColumn = pucData; lY <= pRect->sYMax;
  693. lY++, pucColumn += lBytesPerRow)
  694. {
  695. *(unsigned short *)pucColumn = ulValue & 0xffff;
  696. }
  697. pucData += 2;
  698. lX += 4;
  699. }
  700. //
  701. // Loop while there are at least eight pixel columns left to draw.
  702. //
  703. while((lX + 7) <= pRect->sXMax)
  704. {
  705. //
  706. // Draw eight pixels in this column of the rectangle.
  707. //
  708. for(lY = pRect->sYMin, pucColumn = pucData; lY <= pRect->sYMax;
  709. lY++, pucColumn += lBytesPerRow)
  710. {
  711. *(unsigned int *)pucColumn = ulValue;
  712. }
  713. pucData += 4;
  714. lX += 8;
  715. }
  716. //
  717. // See if there are at least four pixel columns left to draw.
  718. //
  719. if((lX + 3) <= pRect->sXMax)
  720. {
  721. //
  722. // Draw four pixel columns, leaving the buffer pointer half-word
  723. // aligned.
  724. //
  725. ulValue &= 0xffff;
  726. for(lY = pRect->sYMin, pucColumn = pucData; lY <= pRect->sYMax;
  727. lY++, pucColumn += lBytesPerRow)
  728. {
  729. *(unsigned short *)pucColumn = ulValue;
  730. }
  731. pucData += 2;
  732. lX += 4;
  733. }
  734. //
  735. // See if there are at least two pixel columns left to draw.
  736. //
  737. if((lX + 1) <= pRect->sXMax)
  738. {
  739. //
  740. // Draw two pixel columns, leaving the buffer pointer byte aligned.
  741. //
  742. ulValue &= 0xff;
  743. for(lY = pRect->sYMin, pucColumn = pucData; lY <= pRect->sYMax;
  744. lY++, pucColumn += lBytesPerRow)
  745. {
  746. *pucColumn = ulValue;
  747. }
  748. pucData++;
  749. lX += 2;
  750. }
  751. //
  752. // See if there is one pixel column left to draw.
  753. //
  754. if(lX == pRect->sXMax)
  755. {
  756. //
  757. // Draw the final pixel column.
  758. //
  759. ulValue = ulValue & 0xf0;
  760. for(lY = pRect->sYMin; lY <= pRect->sYMax;
  761. lY++, pucData += lBytesPerRow)
  762. {
  763. *pucData = (*pucData & 0x0f) | ulValue;
  764. }
  765. }
  766. }
  767. //*****************************************************************************
  768. //
  769. //! Flushes any cached drawing operations.
  770. //!
  771. //! \param pvDisplayData is a pointer to the driver-specific data for this
  772. //! display driver.
  773. //!
  774. //! This functions flushes any cached drawing operations to the display. This
  775. //! is useful when a local frame buffer is used for drawing operations, and the
  776. //! flush would copy the local frame buffer to the display. For the off-screen
  777. //! display buffer driver, the flush is a no operation.
  778. //!
  779. //! \return None.
  780. //
  781. //*****************************************************************************
  782. static void
  783. GrOffScreen4BPPFlush(void *pvDisplayData)
  784. {
  785. //
  786. // Check the arguments.
  787. //
  788. ASSERT(pvDisplayData);
  789. }
  790. //*****************************************************************************
  791. //
  792. //! Initializes a 4 BPP off-screen buffer.
  793. //!
  794. //! \param pDisplay is a pointer to the display structure to be configured for
  795. //! the 4 BPP off-screen buffer.
  796. //! \param pucImage is a pointer to the image buffer to be used for the
  797. //! off-screen buffer.
  798. //! \param lWidth is the width of the image buffer in pixels.
  799. //! \param lHeight is the height of the image buffer in pixels.
  800. //!
  801. //! This function initializes a display structure, preparing it to draw into
  802. //! the supplied image buffer. The image buffer is assumed to be large enough
  803. //! to hold an image of the specified geometry.
  804. //!
  805. //! \return None.
  806. //
  807. //*****************************************************************************
  808. void
  809. GrOffScreen4BPPInit(tDisplay *pDisplay, unsigned char *pucImage, int lWidth,
  810. int lHeight)
  811. {
  812. //
  813. // Check the arguments.
  814. //
  815. ASSERT(pDisplay);
  816. ASSERT(pucImage);
  817. //
  818. // Initialize the display structure.
  819. //
  820. pDisplay->lSize = sizeof(tDisplay);
  821. pDisplay->pvDisplayData = pucImage;
  822. pDisplay->usWidth = lWidth;
  823. pDisplay->usHeight = lHeight;
  824. pDisplay->pfnPixelDraw = GrOffScreen4BPPPixelDraw;
  825. pDisplay->pfnPixelDrawMultiple = GrOffScreen4BPPPixelDrawMultiple;
  826. pDisplay->pfnLineDrawH = GrOffScreen4BPPLineDrawH;
  827. pDisplay->pfnLineDrawV = GrOffScreen4BPPLineDrawV;
  828. pDisplay->pfnRectFill = GrOffScreen4BPPRectFill;
  829. pDisplay->pfnColorTranslate = GrOffScreen4BPPColorTranslate;
  830. pDisplay->pfnFlush = GrOffScreen4BPPFlush;
  831. //
  832. // Initialize the image buffer.
  833. //
  834. pucImage[0] = IMAGE_FMT_4BPP_UNCOMP;
  835. *(unsigned short *)(pucImage + 1) = lWidth;
  836. *(unsigned short *)(pucImage + 3) = lHeight;
  837. pucImage[5] = 15;
  838. }
  839. //*****************************************************************************
  840. //
  841. //! Sets the palette of a 4 BPP off-screen buffer.
  842. //!
  843. //! \param pDisplay is a pointer to the display structure for the 4 BPP
  844. //! off-screen buffer.
  845. //! \param pulPalette is a pointer to the array of 24-bit RGB values to be
  846. //! placed into the palette.
  847. //! \param ulOffset is the starting offset into the image palette.
  848. //! \param ulCount is the number of palette entries to set.
  849. //!
  850. //! This function sets the entries of the palette used by the 4 BPP off-screen
  851. //! buffer. The palette is used to select colors for drawing via
  852. //! GrOffScreen4BPPColorTranslate(), and for the final rendering of the image
  853. //! to a real display via GrImageDraw().
  854. //!
  855. //! \return None.
  856. //
  857. //*****************************************************************************
  858. void
  859. GrOffScreen4BPPPaletteSet(tDisplay *pDisplay, unsigned int *pulPalette,
  860. unsigned int ulOffset, unsigned int ulCount)
  861. {
  862. unsigned char *pucData;
  863. //
  864. // Check the arguments.
  865. //
  866. ASSERT(pDisplay);
  867. ASSERT(pulPalette);
  868. ASSERT(ulOffset < 16);
  869. ASSERT((ulOffset + ulCount) <= 16);
  870. //
  871. // Get a pointer to the start of the image buffer's palette.
  872. //
  873. pucData = (unsigned char *)pDisplay->pvDisplayData + 6;
  874. //
  875. // Skip to the specified offset in the palette.
  876. //
  877. pucData += ulOffset * 3;
  878. //
  879. // Loop while there are more palette entries to add.
  880. //
  881. while(ulCount--)
  882. {
  883. //
  884. // Copy this palette entry to the image buffer's palette.
  885. //
  886. *pucData++ = (*pulPalette >> ClrBlueShift) & 0xff;
  887. *pucData++ = (*pulPalette >> ClrGreenShift) & 0xff;
  888. *pucData++ = (*pulPalette++ >> ClrRedShift) & 0xff;
  889. }
  890. }
  891. //*****************************************************************************
  892. //
  893. // Close the Doxygen group.
  894. //! @}
  895. //
  896. //*****************************************************************************