Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

807 lines
21 KiB

4 years ago
  1. /*
  2. * xlate.c
  3. *
  4. * 32-bit Video Capture driver
  5. * format translation code (YUV->RGB 8, 16, 24)
  6. *
  7. *
  8. *
  9. * Geraint Davies, Feb 93
  10. */
  11. #include <vckernel.h>
  12. #include <bravado.h>
  13. #include "hardware.h"
  14. #include "vidcio.h"
  15. #include "profile.h"
  16. #if DBG
  17. extern profiling prf_line;
  18. #endif
  19. /*
  20. * the frame buffer is in YUV411 format. There is one 7 bit Luma sample
  21. * per pixel, and 1 each 7-bit U and V sample averaged over 4 pixels,
  22. * in the following layout:
  23. *
  24. * 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
  25. * Word 0 u6 u5 v6 v5 y6 y5 y4 y3 y2 y1 y0
  26. *
  27. * Word 1 u4 u3 v4 v3 y6 y5 y4 y3 y2 y1 y0
  28. *
  29. * Word 2 u2 u1 v2 v1 y6 y5 y4 y3 y2 y1 y0
  30. *
  31. * Word 3 u0 v0 y6 y5 y4 y3 y2 y1 y0
  32. *
  33. * The 7-bit y values are unsigned (0..127), whereas the 7-bit
  34. * u and V values are signed (-64..+63).
  35. *
  36. * We support four possible destination formats:
  37. *
  38. * YUV: we copy the data as is, 16 bits per pixel.
  39. *
  40. * RGB24: we convert (as we copy) into 24-bpp rgb format.
  41. *
  42. * RGB555: we truncate the YUV into a 15-bit format and use a prepared
  43. * lookup table to convert the 15-bit YUV into a 15-bit RGB value.
  44. *
  45. * 8-bit Pal: we truncate the YUV into a 15-bit format and use a prepared
  46. * lookup table to convert the 15-bit YUV into an 8-bit palette entry.
  47. *
  48. * The (64 kbyte) rgb555 lookup table is built by BuildYUVToRGB555 whenever
  49. * the destination format is set to RGB555.
  50. *
  51. * The (32 kbyte) palette lookup table is built whenever the format is set to
  52. * FmtPal8 or the palette is changed. We are not given a palette here - we are
  53. * given a rgb555-to-palette lookup table, and we build from it
  54. * a yuv-to-palette lookup
  55. *
  56. * Since the translation tables are allocated from non-paged memory, we
  57. * only hold one at once (in pHw->pXlate). Thus switching between
  58. * RGB555 and Pal-8 may be slower than the original windows driver (where
  59. * they kept both tables around). If this proves to be an issue it is
  60. * straightforward to fix.
  61. */
  62. /*
  63. * the YUV xlate tables use 5-bits per component with y in the ms bits, and
  64. * v in the ls bits. To convert from the above layout, look up the nibbles
  65. * containing the chroma bits in these tables and or together the result to
  66. * get a word with a 5-bit V component in bits 0..4, and a 5-bit
  67. * U component in bits 5..9. Note you only need three lookups since
  68. * we discard chroma bits 0 and 1.
  69. */
  70. WORD ChromaBits65[] = {
  71. 0x000, 0x008, 0x010, 0x018,
  72. 0x100, 0x108, 0x110, 0x118,
  73. 0x200, 0x208, 0x210, 0x218,
  74. 0x300, 0x308, 0x310, 0x318
  75. };
  76. WORD ChromaBits43[] = {
  77. 0x000, 0x002, 0x004, 0x006,
  78. 0x040, 0x042, 0x044, 0x046,
  79. 0x080, 0x082, 0x084, 0x086,
  80. 0x0c0, 0x0c2, 0x0c4, 0x0c6
  81. };
  82. WORD ChromaBits2[] = {
  83. 0x000, 0x000, 0x001, 0x001,
  84. 0x000, 0x000, 0x001, 0x001,
  85. 0x020, 0x020, 0x021, 0x021,
  86. 0x020, 0x020, 0x021, 0x021
  87. };
  88. /*
  89. * force x to be in the range lo to hi
  90. */
  91. #define RANGE(x, lo, hi) max(lo, min(hi, x))
  92. /*
  93. * Convert a YUV colour into a 15-bit RGB colour.
  94. *
  95. * The input Y is in the range 16..235; the input U and V components
  96. * are in the range -128..+127. The conversion equations for this are
  97. * (according to CCIR 601):
  98. *
  99. * R = Y + 1.371 V
  100. * G = Y - 0.698 V - 0.336 U
  101. * B = Y + 1.732 U
  102. *
  103. * To avoid floating point, we scale all values by 1024.
  104. *
  105. * The resulting RGB values are in the range 16..235: we truncate these to
  106. * 5 bits each. and return a WORD containing 5-bits each for R, G and B
  107. * with bit 15 set to 0.
  108. */
  109. WORD
  110. YUVToRGB15(int y, int u, int v)
  111. {
  112. int ScaledY = RANGE(y, 16, 235) * 1024;
  113. int red, green, blue;
  114. red = RANGE((ScaledY + (1404 * v)) / 1024, 0, 255);
  115. green = RANGE( (ScaledY - (715 * v) - (344 * u)) / 1024, 0, 255);
  116. blue = RANGE( (ScaledY + (1774 * u)) / 1024, 0, 255);
  117. return (WORD) (((red & 0xf8) << 7) | ((green & 0xf8) << 2) | ((blue & 0xf8) >>3) );
  118. }
  119. /*
  120. * build a translation table to translate between YUV and RGB555.
  121. *
  122. * This builds a lookup table with 32k 1-word entries: truncate the YUV
  123. * to 15bits and look-up in this xlate table to produce the 15-bit rgb value.
  124. */
  125. BOOLEAN
  126. HW_BuildYUVToRGB555(PDEVICE_INFO pDevInfo, PHWINFO pHw)
  127. {
  128. LPWORD pWord;
  129. UINT w;
  130. /* check that there is not already some form of translation */
  131. if (pHw->pXlate != NULL) {
  132. dprintf(("xlate table contention"));
  133. return(FALSE);
  134. }
  135. pHw->ulSizeXlate = 64 * 1024; /* enough for 32k 16-bit values */
  136. pHw->pXlate = VC_AllocMem(pDevInfo, pHw->ulSizeXlate);
  137. if (pHw->pXlate == NULL) {
  138. dprintf(("failed to alloc xlate memory"));
  139. return(FALSE);
  140. }
  141. pWord = (LPWORD) pHw->pXlate;
  142. /*
  143. * build a 15-bit yuv lookup table by stepping through each entry,
  144. * converting the yuv index to rgb and storing at that index. The index
  145. * to this table is a 15-bit value with the y component in bits 14..10,
  146. * u in bits 9..5 and v in bits 4..0. Note that the y component is unsigned,
  147. * whereas the u and v components are signed.
  148. */
  149. for (w = 0; w < 32*1024; w++) {
  150. /*
  151. * the YUVtoRGB55 conversion function takes values 0..255 for y,
  152. * and -128..+127 for u and v. Pick out the relevant bits of the
  153. * index for this cell, and shift to get values in this range.
  154. * Remember the cast to ensure sign-extension of these (8-bit) values -
  155. * and don't assume that chars are signed (they're not on MIPS).
  156. */
  157. *pWord++ = YUVToRGB15(
  158. (w & 0x7c00) >> 7,
  159. (signed char) ((w & 0x3e0) >> 2),
  160. (signed char) ((w & 0x1f) << 3)
  161. );
  162. }
  163. return(TRUE);
  164. }
  165. /*
  166. * build a palette translation table.
  167. *
  168. * User-level code has already converted the palette into a translation
  169. * table with one entry for each 15-bit RGB value, giving the relevant
  170. * 8-bit palette entry. We are passed a pointer to this table (protected
  171. * by VC_AccessData, so we need not worry about access violations).
  172. *
  173. * we step through 32 possible values for each y, u and v component, and for
  174. * each resulting 15-bit YUV value, we convert to an RGB value, and then
  175. * store in our lookup table the 8-bit palette entry for that RGB value,
  176. * thus giving us a one-step yuv to palette translation table.
  177. *
  178. * The palette table we are passed in is user-mode memory: we create
  179. * our yuv->pal lookup in non-paged memory so we can use it at interrupt time.
  180. *
  181. * We are called via VC_AccessData: this passes us a PVOID context pointer that
  182. * is not used.
  183. */
  184. BOOLEAN
  185. HW_BuildYuvToPal(
  186. PDEVICE_INFO pDevInfo,
  187. PUCHAR pBuffer,
  188. ULONG Length,
  189. PVOID pContext
  190. )
  191. {
  192. PHWINFO pHw = VC_GetHWInfo(pDevInfo);
  193. int wRGB;
  194. PUCHAR pXlate;
  195. UINT w;
  196. /* check that the length of the palette xlate table is good */
  197. if (Length < (32 * 1024)) {
  198. dprintf(("bad palette xlate table length"));
  199. return (FALSE);
  200. }
  201. /* check there is not already some form of xlate table */
  202. if (pHw->pXlate != NULL) {
  203. dprintf(("xlate table contention"));
  204. return(FALSE);
  205. }
  206. /* allocate our non-paged xlate table */
  207. pHw->ulSizeXlate = 32 * 1024; /* enough for 32k 1-byte entries */
  208. pHw->pXlate = VC_AllocMem(pDevInfo, pHw->ulSizeXlate);
  209. if (pHw->pXlate == NULL) {
  210. dprintf(("failed to allocate xlate table memory"));
  211. return(FALSE);
  212. } else {
  213. pXlate = pHw->pXlate;
  214. }
  215. /*
  216. * build a 15-bit yuv lookup table by stepping through each entry,
  217. * converting the yuv index to rgb and then to a palette index. The index
  218. * to this table is a 15-bit value with the y component in bits 14..10,
  219. * u in bits 9..5 and v in bits 4..0. Note that the y component is unsigned,
  220. * whereas the u and v components are signed.
  221. */
  222. for (w = 0; w < 32*1024; w++) {
  223. /*
  224. * the YUVtoRGB55 conversion function takes values 0..255 for y,
  225. * and -128..+127 for u and v. Pick out the relevant bits of the
  226. * index for this cell, and shift to get values in this range.
  227. * Remember the cast to ensure sign-extension of these (8-bit) values -
  228. * and don't assume that chars are signed (they're not on MIPS).
  229. */
  230. wRGB = YUVToRGB15(
  231. (w & 0x7c00) >> 7,
  232. (signed char) ((w & 0x3e0) >> 2),
  233. (signed char) ((w & 0x1f) << 3)
  234. );
  235. /*
  236. * having got the RGB555 value for this YUV index value, we can
  237. * use the passed-in table to convert rgb555 to pal-index and
  238. * store that as the conversion for this yuv value
  239. */
  240. *pXlate++ = pBuffer[wRGB];
  241. }
  242. dprintf2(("xlate table copied"));
  243. return(TRUE);
  244. }
  245. /*
  246. * build a translation table from YUV to a default palette
  247. * containing 64 grey levels only.
  248. */
  249. BOOLEAN
  250. HW_BuildDefaultXlate(PDEVICE_INFO pDevInfo, PHWINFO pHw)
  251. {
  252. PUCHAR pXlate;
  253. UINT w;
  254. /* allocate our non-paged xlate table */
  255. pHw->ulSizeXlate = 32 * 1024; /* enough for 32k 1-byte entries */
  256. pHw->pXlate = VC_AllocMem(pDevInfo, pHw->ulSizeXlate);
  257. if (pHw->pXlate == NULL) {
  258. dprintf(("failed to allocate xlate table memory"));
  259. return(FALSE);
  260. } else {
  261. pXlate = pHw->pXlate;
  262. }
  263. /*
  264. * each entry in the table contains the palette entry for a given
  265. * YUV value. The palette grey levels are 64 levels in order of
  266. * increasing luminance, thus making the mapping straightforward.
  267. */
  268. for (w = 0; w < 0x8000; w++) {
  269. *pXlate++ = (BYTE) (UINT) ( (UINT) w / ((UINT) 0x8000 / 64));
  270. }
  271. return(TRUE);
  272. }
  273. /*
  274. * translate YUV into RGB555 copying from pDst to pSrc.
  275. *
  276. * Width and Height are the dimensions of the copy rectangle in
  277. * pixels. WidthBytes is the width of the source line in bytes.
  278. *
  279. * pXlate is a pointer to an array of words, one for each
  280. * 15-bit YUV value, giving the corresponding RGB555 value.
  281. *
  282. * This routine also flips the image vertically into a DIB format
  283. */
  284. VOID
  285. CopyYUVToRGB555(
  286. PUCHAR pDst, /* destination pixels */
  287. PUCHAR pSrc, /* source pixels */
  288. LPWORD pXlate, /* translation table yuv-15 to rgb-15 */
  289. DWORD Width, /* width of copy rect in pixels */
  290. DWORD Height, /* height of copy rect in lines */
  291. DWORD WidthBytes /* width of one entire source line in bytes */
  292. )
  293. {
  294. int RowInc;
  295. int i, j;
  296. DWORD Luma01, Luma23;
  297. DWORD Chroma;
  298. /* force the copy width to 4-pixel alignment */
  299. if (Width & 3) {
  300. dprintf(("non-4 aligned copy "));
  301. Width &= ~3;
  302. }
  303. /*
  304. * adjust the source to point to the start of the last line,
  305. * and work upwards (to flip vertically into DIB format)
  306. */
  307. pSrc += (Height - 1) * WidthBytes;
  308. /*
  309. * calculate the amount to adjust pSrc by at the end of one line
  310. * of copying. At this point we are at the end of line N. We need
  311. * to move to the start of line N-1.
  312. */
  313. RowInc = WidthBytes + (Width * 2);
  314. /* loop copying each scanline */
  315. for (i = 0; i < (int) Height; i++) {
  316. /* loop copying four pixels at a time */
  317. for (j = 0; j < (int) Width; j += 4) {
  318. /*
  319. * get four pixels and convert to 15-bpp YUV
  320. */
  321. /* get luma for first 2 pixels + higher chroma bits */
  322. Luma01 = VC_ReadIOMemoryULONG(pSrc);
  323. pSrc += sizeof(DWORD);
  324. /* pick out u,v components using lookup table.
  325. * u and v will be the bottom 10 bits of each pixel, so
  326. * convert to this layout
  327. */
  328. Chroma = ChromaBits65[(Luma01 >> 12) & 0xf] |
  329. ChromaBits43[ (Luma01 >> 28) & 0xf ];
  330. /* next two pixels + lower chroma bits */
  331. Luma23 = VC_ReadIOMemoryULONG(pSrc);
  332. pSrc += sizeof(DWORD);
  333. /* pickup u and v bits 2 - ignore bits 1, 0 since
  334. * we only use 5-bits per component for conversion
  335. */
  336. Chroma |= ChromaBits2[ ( Luma23 >> 12) & 0xf];
  337. /*
  338. * combine luma for pix 0 with common chroma bits to
  339. * get 15-bit yuv, then lookup to convert to
  340. * 15-bit rgb and store.
  341. */
  342. *(WORD *)pDst = pXlate[ ((Luma01 & 0xf8) << 7) | Chroma];
  343. pDst += sizeof(WORD);
  344. *(WORD *)pDst = pXlate[ ((Luma01 & 0xf80000) >> 9) | Chroma];
  345. pDst += sizeof(WORD);
  346. *(WORD *)pDst = pXlate[ ((Luma23 & 0xf8) << 7) | Chroma];
  347. pDst += sizeof(WORD);
  348. *(WORD *)pDst = pXlate[ ((Luma23 & 0xf80000) >> 9) | Chroma];
  349. pDst += sizeof(WORD);
  350. } // loop per 4 pixels
  351. /* move source pointer back to next line */
  352. pSrc -= RowInc;
  353. } // loop per row
  354. }
  355. /*
  356. * translate YUV from pSrc into 8-bit palettised data in pDst.
  357. *
  358. * pXlate is an array of bytes, one for each 15-bit YUV value, giving
  359. * the corresponding palette entry.
  360. *
  361. * dwWidth and dwHeight give the size of the copy rectangle in pixels.
  362. * WidthBytes is the width of one source line in bytes.
  363. *
  364. * Also flip the image vertically into a DIB format.
  365. */
  366. VOID
  367. CopyYUVToPal8(
  368. PUCHAR pDst, /* destination pixels */
  369. PUCHAR pSrc, /* source pixels */
  370. PUCHAR pXlate, /* translation table yuv-15 to palette entry */
  371. DWORD Width, /* width of copy rect in pixels */
  372. DWORD Height, /* height of copy rect in lines */
  373. DWORD WidthBytes /* width of one entire source line in bytes */
  374. )
  375. {
  376. int RowInc;
  377. int i, j;
  378. DWORD Luma01, Luma23;
  379. DWORD Chroma;
  380. DWORD destpix;
  381. /* force the copy width to 4-pixel alignment */
  382. if (Width & 3) {
  383. dprintf(("non-4 aligned copy "));
  384. Width &= ~3;
  385. }
  386. /*
  387. * adjust the source to point to the start of the last line,
  388. * and work upwards (to flip vertically into DIB format)
  389. */
  390. pSrc += (Height - 1) * WidthBytes;
  391. /*
  392. * calculate the amount to adjust pSrc by at the end of one line
  393. * of copying. At this point we are at the end of line N. We need
  394. * to move to the start of line N-1.
  395. */
  396. RowInc = WidthBytes + (Width * 2);
  397. /* loop copying each scanline */
  398. for (i = 0; i < (int) Height; i++) {
  399. START_PROFILING(&prf_line);
  400. /* loop copying four pixels at a time */
  401. for (j = 0; j < (int) Width; j += 4) {
  402. /*
  403. * get four pixels and convert to 15-bpp YUV
  404. */
  405. /* get luma for first 2 pixels + higher chroma bits */
  406. Luma01 = VC_ReadIOMemoryULONG(pSrc);
  407. pSrc += sizeof(DWORD);
  408. /* pick out u,v components using lookup table.
  409. * u and v will be the bottom 10 bits of each pixel, so
  410. * convert to this layout
  411. */
  412. Chroma = ChromaBits65[(Luma01 >> 12) & 0xf] |
  413. ChromaBits43[ (Luma01 >> 28) & 0xf ];
  414. /* next two pixels + lower chroma bits */
  415. Luma23 = VC_ReadIOMemoryULONG(pSrc);
  416. pSrc += sizeof(DWORD);
  417. /* pickup u and v bits 2 - ignore bits 1, 0 since
  418. * we only use 5-bits per component for conversion
  419. */
  420. Chroma |= ChromaBits2[ ( Luma23 >> 12) & 0xf];
  421. /*
  422. * combine luma for each pixel with common chroma bits to
  423. * get 15-bit yuv, then lookup to convert to
  424. * palette index and store in destination
  425. */
  426. destpix = (pXlate[ ((Luma23 & 0xf80000) >> 9) | Chroma] << 8) |
  427. pXlate[ ((Luma23 & 0xf8) << 7) | Chroma];
  428. destpix <<= 8;
  429. destpix |= pXlate[ ((Luma01 & 0xf80000) >> 9) | Chroma];
  430. destpix <<= 8;
  431. destpix |= pXlate[ ((Luma01 & 0xf8) << 7) | Chroma];
  432. * (DWORD *) pDst = destpix;
  433. pDst += sizeof(DWORD);
  434. } // loop per 4 pixels
  435. STOP_PROFILING(&prf_line);
  436. /* move source pointer back to next line */
  437. pSrc -= RowInc;
  438. } // loop per row
  439. }
  440. /*
  441. * translate YUV from pSrc into 24-bit RGB in pDst.
  442. *
  443. * dwWidth and dwHeight give the size of the copy rectangle in pixels.
  444. * WidthBytes is the width of one source line in bytes.
  445. *
  446. * Also flip the image vertically into a DIB format.
  447. */
  448. VOID
  449. CopyYUVToRGB24(
  450. PUCHAR pDst, /* destination pixels */
  451. PUCHAR pSrc, /* source pixels */
  452. DWORD Width, /* width of copy rect in pixels */
  453. DWORD Height, /* height of copy rect in lines */
  454. DWORD WidthBytes /* width of one entire source line in bytes */
  455. )
  456. {
  457. WORD pixel;
  458. int y[4];
  459. int u, v;
  460. int ScaledU, ScaledV;
  461. int ScaledUforG, ScaledVforG;
  462. int RowInc;
  463. int i, j, k;
  464. int red, green, blue;
  465. /* force the copy width to 4-pixel alignment */
  466. if (Width & 3) {
  467. dprintf(("non-4 aligned copy "));
  468. Width &= ~3;
  469. }
  470. /*
  471. * adjust the source to point to the start of the last line,
  472. * and work upwards (to flip vertically into DIB format)
  473. */
  474. pSrc += (Height - 1) * WidthBytes;
  475. /*
  476. * calculate the amount to adjust pSrc by at the end of one line
  477. * of copying. At this point we are at the end of line N. We need
  478. * to move to the start of line N-1.
  479. */
  480. RowInc = WidthBytes + (Width * 2);
  481. /* loop copying each scanline */
  482. for (i = 0; i < (int) Height; i++) {
  483. /* loop copying four pixels at a time */
  484. for (j = 0; j < (int) Width; j += 4) {
  485. /* grab four pixels and separate out the components.
  486. * we are only interested in 5-bits worth of each component.
  487. *
  488. * we scale the y value by 1024 to save time in the yuv-rgb555
  489. * conversions below. See YUVToRGB555 above for an explanation
  490. * of these calculations
  491. */
  492. pixel = VC_ReadIOMemoryUSHORT(pSrc);
  493. pSrc += sizeof(WORD);
  494. y[0] = (pixel & 0xfe) * 1024;
  495. u = (signed char) ((pixel & 0xc000) >> 8);
  496. v = (signed char) ((pixel & 0x3000) >> 6);
  497. pixel = VC_ReadIOMemoryUSHORT(pSrc);
  498. pSrc += sizeof(WORD);
  499. y[1] = (pixel & 0xfe) * 1024;
  500. u |= (pixel & 0xc000) >> 10;
  501. v |= (pixel & 0x3000) >> 8;
  502. pixel = VC_ReadIOMemoryUSHORT(pSrc);
  503. pSrc += sizeof(WORD);
  504. y[2] = (pixel & 0xfe) * 1024;
  505. /* discard chroma bit 1 */
  506. u |= (pixel & 0x8000) >> 12;
  507. v |= (pixel & 0x2000) >> 10;
  508. pixel = VC_ReadIOMemoryUSHORT(pSrc);
  509. pSrc += sizeof(WORD);
  510. y[3] = (pixel & 0xfe) * 1024;
  511. /* discard chroma bit 0 */
  512. /*
  513. * the u and v values we have are SIGNED 8-bit values.
  514. * we need to tell the compiler this so it will correctly
  515. * sign-extend them to ints
  516. */
  517. u = (signed char) u;
  518. v = (signed char) v;
  519. /*
  520. * The conversion code here is borrowed from YUVToRGB555 above.
  521. */
  522. ScaledU = u * 1774;
  523. ScaledV = v * 1404;
  524. ScaledUforG = u * 344;
  525. ScaledVforG = v * 715;
  526. /* now build all of the four pixels */
  527. for (k = 0; k < 4; k++) {
  528. red = RANGE( (ScaledV + y[k]) / 1024, 0, 255);
  529. blue = RANGE( (ScaledU + y[k]) / 1024, 0, 255);
  530. green = RANGE( (y[k] - ScaledVforG - ScaledUforG) / 1024, 0, 255);
  531. *pDst++ = blue;
  532. *pDst++ = green;
  533. *pDst++ = red;
  534. }
  535. } // loop per 4 pixels
  536. /* move source pointer back to next line */
  537. pSrc -= RowInc;
  538. } // loop per row
  539. }
  540. /*
  541. * copy a rectangle from pSrc to pDst without any conversion.
  542. *
  543. * pSrc is an IOMemory address and thus must be accessed using the
  544. * VC_ReadIOMemory* functions.
  545. *
  546. * Width x Height is the size of the copy rectangle in BYTES. SourceWidth
  547. * is the width of the entire source line.
  548. */
  549. VOID
  550. CopyRectFromIOMemory(
  551. PUCHAR pDst,
  552. PUCHAR pSrc,
  553. DWORD Width,
  554. DWORD Height,
  555. DWORD SourceWidth
  556. )
  557. {
  558. int i;
  559. for (i = 0; i < (int)Height; i++) {
  560. /* copy one line */
  561. VC_ReadIOMemoryBlock(pDst,
  562. pSrc,
  563. Width // width is in BYTES
  564. );
  565. /* skip to start of next line */
  566. pSrc += SourceWidth;
  567. pDst += Width; // width is already in BYTES
  568. }
  569. }
  570. /*
  571. * take the rectangle rcSource out of the source dib, and place
  572. * at (0,0) in the destination.
  573. *
  574. * The destination is assumed to be in IOMemory.
  575. */
  576. VOID
  577. CopyRectToIOMemory(
  578. PUCHAR pDst,
  579. PUCHAR pSrc,
  580. PRECT prcSource,
  581. DWORD SourceLineWidth, // in BYTES
  582. DWORD DestLineWidth, // in BYTES
  583. DWORD PixelSize // pixel size - for rcSource
  584. )
  585. {
  586. int i;
  587. int width = (prcSource->right - prcSource->left) * PixelSize;
  588. /*
  589. * move pSrc to start of copy rect
  590. */
  591. pSrc += (prcSource->top * SourceLineWidth) + (prcSource->left * PixelSize);
  592. for (i = prcSource->bottom - prcSource->top; i>0; i--) {
  593. VC_WriteIOMemoryBlock(pDst, pSrc, width);
  594. pSrc += SourceLineWidth;
  595. pDst += DestLineWidth;
  596. }
  597. }
  598. /*
  599. * draw a frame to the device
  600. *
  601. * This is called via VC_AccessData so that we can safely access
  602. * the user data without worrying about bad pointers.
  603. */
  604. BOOLEAN
  605. HW_DrawFrame_Safe(
  606. PDEVICE_INFO pDevInfo,
  607. PUCHAR pSource,
  608. ULONG SourceLength,
  609. PVOID pContext
  610. )
  611. {
  612. PDRAWBUFFER pDraw = (PDRAWBUFFER) pContext;
  613. PUCHAR pFrame;
  614. pFrame = VC_GetFrameBuffer(pDevInfo);
  615. CopyRectToIOMemory(
  616. pFrame, // destination
  617. pSource, // from here
  618. &pDraw->rcSource, // source rectangle within dib
  619. pDraw->ulWidth * 2, // size in BYTES of entire source line
  620. FRAMEBUFFERWIDTH, // size in bytes of one frame buffer line
  621. 2 // pixel size in bytes (source == dest)
  622. );
  623. return (TRUE);
  624. }
  625. /*
  626. * Write a frame's worth of data direct to the frame
  627. * buffer for overlay.
  628. */
  629. BOOLEAN
  630. HW_DrawFrame(PDEVICE_INFO pDevInfo, PDRAWBUFFER pDraw)
  631. {
  632. /*
  633. * first check that source rect is actually within the frame
  634. */
  635. if ((pDraw->rcSource.top >= pDraw->rcSource.bottom) ||
  636. (pDraw->rcSource.top < 0) ||
  637. (pDraw->rcSource.bottom > (int)pDraw->ulHeight) ||
  638. (pDraw->rcSource.left >= pDraw->rcSource.right) ||
  639. (pDraw->rcSource.left < 0) ||
  640. (pDraw->rcSource.right > (int)pDraw->ulWidth)) {
  641. return(FALSE);
  642. }
  643. /* check that no conversion is required */
  644. if (pDraw->Format != FOURCC_YUV411) {
  645. return(FALSE);
  646. }
  647. /* ensure we can access frame buffer */
  648. HW_Capture(pDevInfo, FALSE);
  649. /*
  650. * package this up in an exception handler so that bad user data
  651. * does not fault the driver
  652. */
  653. return VC_AccessData(
  654. pDevInfo,
  655. pDraw->lpData,
  656. pDraw->ulWidth * pDraw->ulHeight * 2, // size of frame data (2bytes/pixel)
  657. HW_DrawFrame_Safe,
  658. pDraw
  659. );
  660. }