Leaked source code of windows server 2003
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.

1412 lines
53 KiB

  1. /******************************Module*Header**********************************\
  2. *
  3. * **************************
  4. * * DirectDraw SAMPLE CODE *
  5. * **************************
  6. *
  7. * Module Name: ddover.c
  8. *
  9. * Content: DirectDraw Overlays implementation
  10. *
  11. * Copyright (c) 1994-1999 3Dlabs Inc. Ltd. All rights reserved.
  12. * Copyright (c) 1995-2003 Microsoft Corporation. All rights reserved.
  13. \*****************************************************************************/
  14. #include "glint.h"
  15. #include "dma.h"
  16. #include "ddover.h"
  17. #define P3R3DX_VIDEO 1
  18. #include "ramdac.h"
  19. #if WNT_DDRAW
  20. #define ENABLE_OVERLAY(pThisDisplay, flag) \
  21. FORCED_IN_ORDER_WRITE ( pThisDisplay->bOverlayEnabled, flag )
  22. #define SET_OVERLAY_HEIGHT(pThisDisplay, height) \
  23. FORCED_IN_ORDER_WRITE ( pThisDisplay->VBLANKUpdateOverlayHeight, height )
  24. #define SET_OVERLAY_WIDTH(pThisDisplay, width) \
  25. FORCED_IN_ORDER_WRITE ( pThisDisplay->VBLANKUpdateOverlayWidth, width )
  26. #else
  27. #define ENABLE_OVERLAY(pThisDisplay, flag) \
  28. FORCED_IN_ORDER_WRITE ( pThisDisplay->pGLInfo->bOverlayEnabled, flag )
  29. #define SET_OVERLAY_HEIGHT(pThisDisplay, height) \
  30. FORCED_IN_ORDER_WRITE ( pThisDisplay->pGLInfo->VBLANKUpdateOverlayHeight, height )
  31. #define SET_OVERLAY_WIDTH(pThisDisplay, width) \
  32. FORCED_IN_ORDER_WRITE ( pThisDisplay->pGLInfo->VBLANKUpdateOverlayWidth, width )
  33. #endif // WNT_DDRAW
  34. // Flags used in the dwOverlayFiltering entry.
  35. #define OVERLAY_FILTERING_X 0x1
  36. #define OVERLAY_FILTERING_Y 0x2
  37. // The table that says whether the overlay will actually work at
  38. // This res, dot clock, etc.
  39. typedef struct OverlayWorksEntry_tag
  40. {
  41. int iMemBandwidth; // Actually just memory clock in kHz (well, 1024Hz units actually).
  42. int iDotBandwidth; // In kbytes/sec, i.e. dotclock * pixel depth / 2^10
  43. int iSourceWidth; // In bytes, i.e. pixels*depth.
  44. int iWidthCoverage; // Fraction of screen covered by overlay horizontally * 0x10000
  45. } OverlayWorksEntry;
  46. // This table lists areas that the overlay works in. If there is more memory
  47. // bandwidth, and less of the other factors than given on any single line,
  48. // then the overlay will work. If no single line covers the current mode,
  49. // then the overlay will fail.
  50. // Having more memory bandwidth is fine, and having less for all the others
  51. // is fine - the overlay will still work.
  52. #define SIZE_OF_OVERLAY_WORKS_TABLE 18
  53. // DVD size is 1440 wide (720 YUYV pixels).
  54. static OverlayWorksEntry OverlayWorksTable[SIZE_OF_OVERLAY_WORKS_TABLE] =
  55. {
  56. { 68359, 210937, 928, 0x10000 }, // Max source width at 70MHz, 1152x864x16,75Hz
  57. { 68359, 210937, 1024, 0x06000 }, // Max coverage of 1024 width at 70MHz, 1152x864x16,75Hz
  58. { 68359, 210937, 2048, 0x04000 }, // Max coverage of 2048 width at 70MHz, 1152x864x16,75Hz
  59. { 68359, 421875, 864, 0x10000 }, // Max source width at 70MHz, 1152x864x32,75Hz
  60. { 68359, 421875, 1024, 0x04400 }, // Max coverage of 1024 width at 70MHz, 1152x864x32,75Hz
  61. { 68359, 421875, 2048, 0x03800 }, // Max coverage of 2048 width at 70MHz, 1152x864x32,75Hz
  62. { 87890, 210937, 1440, 0x10000 }, // Max source width at 90MHz, 1152x864x16,75Hz
  63. { 87890, 210937, 2048, 0x07000 }, // Max coverage of 2048 width at 90MHz, 1152x864x16,75Hz
  64. { 87890, 421875, 1152, 0x10000 }, // Max source width at 90MHz, 1152x864x32,75Hz
  65. { 87890, 421875, 1440, 0x09000 }, // Max DVD size at 90MHz, 1152x864x32,75Hz
  66. { 87890, 421875, 2048, 0x05500 }, // Max coverage of 2048 width at 90MHz, 1152x864x32,75Hz
  67. { 87890, 685546, 834, 0x10000 }, // Max source width at 90MHz, 1600x1200x32,64Hz
  68. { 87890, 685546, 2048, 0x03000 }, // Max coverage of 2048 width at 90MHz, 1600x1200x32,64Hz
  69. // Shipping clock is 110, so measure at 105 just to be on the safe side.
  70. { 102559, 210937, 2048, 0x07155 }, // Max coverage of 2048 width at 105MHz, 1152x864x16,75Hz
  71. { 102559, 306640, 1440, 0x10000 }, // Max resoloution for fulscreen DVD at 105MHz: 1024x768x32,75Hz
  72. { 102559, 421875, 1440, 0x09e38 }, // Max DVD size at 105MHz, 1152x864x32,75Hz
  73. { 102559, 421875, 2048, 0x0551c }, // Max coverage of 2048 width at 105MHz, 1152x864x32,75Hz
  74. // ...and one that only just works at 109MHz!
  75. { 106445, 421875, 1440, 0x10000 } // Max DVD size at 109MHz, 1152x864x32,75Hz
  76. };
  77. //-----------------------------------------------------------------------------
  78. //
  79. // __OV_Compute_Best_Fit_Delta
  80. //
  81. // Function to calculate a 12.12 delta value to provide scaling from
  82. // a src_dimension to the target dest_dimension.
  83. // The dest_dimension is not adjustable, but the src_dimension may be adjusted
  84. // slightly, so that the delta yields a more accurate value for dest.
  85. // filter_adj should be set to 1 if linear filtering is going to be anabled
  86. // during scaling, and 0 otherwise.
  87. // int_bits indicates the number of bits in the scaled delta format
  88. //
  89. //-----------------------------------------------------------------------------
  90. int
  91. __OV_Compute_Best_Fit_Delta(
  92. unsigned long *src_dimension,
  93. unsigned long dest_dimension,
  94. unsigned long filter_adj,
  95. unsigned long int_bits,
  96. unsigned long *best_delta)
  97. {
  98. int result = 0;
  99. float fp_delta;
  100. float delta;
  101. unsigned long delta_mid;
  102. unsigned long delta_down;
  103. unsigned long delta_up;
  104. float mid_src_dim;
  105. float down_src_dim;
  106. float up_src_dim;
  107. float mid_err;
  108. float mid_frac;
  109. int mid_ok;
  110. float down_err;
  111. float down_frac;
  112. int down_ok;
  113. float up_err;
  114. float up_frac;
  115. int up_ok;
  116. int itemp;
  117. // The value at which a scaled delta value is deemed too large
  118. const unsigned int max_scaled_int = (1 << (12+int_bits));
  119. // Calculate an exact floating point delta
  120. fp_delta = (float)(*src_dimension - filter_adj) / dest_dimension;
  121. // Calculate the scaled representation of the delta
  122. delta = (fp_delta * (1<<12));
  123. // Truncate to max_int
  124. if (delta >= max_scaled_int)
  125. {
  126. delta = (float)(max_scaled_int - 1); // Just below the overflow value
  127. }
  128. // Calculate the scaled approximation to the delta
  129. myFtoi(&delta_mid, delta);
  130. // Calculate the scaled approximation to the delta, less a 'bit'
  131. // But don't let it go out of range
  132. myFtoi(&delta_down, delta);
  133. if (delta_down != 0)
  134. {
  135. delta_down --;
  136. }
  137. // Calculate the scaled approximation to the delta, plus a 'bit'
  138. // But don't let it go out of range
  139. myFtoi(&delta_up, delta);
  140. if ((delta_up + 1) < max_scaled_int)
  141. {
  142. delta_up ++;
  143. }
  144. // Recompute the source dimensions, based on the dest and deltas
  145. mid_src_dim =
  146. (((float)(dest_dimension - 1) * delta_mid) / (1<<12)) + filter_adj;
  147. down_src_dim =
  148. (((float)(dest_dimension - 1) * delta_down) / (1<<12)) + filter_adj;
  149. up_src_dim =
  150. (((float)(dest_dimension - 1) * delta_up) / (1<<12)) + filter_adj;
  151. // Choose the delta which gives final source coordinate closest the target,
  152. // while giving a fraction 'f' such that (1.0 - f) <= delta
  153. mid_err = (float)myFabs(mid_src_dim - *src_dimension);
  154. myFtoi(&itemp, mid_src_dim);
  155. mid_frac = mid_src_dim - itemp;
  156. mid_ok = ((1.0 - mid_frac) <= ((float)(delta_mid) / (1<<12)));
  157. down_err = (float)myFabs(down_src_dim - *src_dimension);
  158. myFtoi(&itemp, down_src_dim);
  159. down_frac = down_src_dim - itemp;
  160. down_ok = ((1.0 - down_frac) <= ((float)(delta_down) / (1<<12)));
  161. up_err = (float)myFabs(up_src_dim - *src_dimension);
  162. myFtoi(&itemp, up_src_dim);
  163. up_frac = (up_src_dim - itemp);
  164. up_ok = ((1.0 - up_frac) <= ((float)(delta_up) / (1<<12)));
  165. if (mid_ok && (!down_ok || (mid_err <= down_err)) &&
  166. (!up_ok || (mid_err <= up_err)))
  167. {
  168. *best_delta = delta_mid;
  169. myFtoi(&itemp, (mid_src_dim + ((float)(delta_mid) / (1<<12))));
  170. *src_dimension = (unsigned long)(itemp - filter_adj);
  171. result = 1;
  172. }
  173. else if (down_ok &&
  174. (!mid_ok || (down_err <= mid_err)) &&
  175. (!up_ok || (down_err <= up_err )) )
  176. {
  177. *best_delta = delta_down;
  178. myFtoi(&itemp, (down_src_dim + ((float)(delta_down) / (1<<12))));
  179. *src_dimension = (unsigned long)(itemp - filter_adj);
  180. result = 1;
  181. }
  182. else if (up_ok &&
  183. (!mid_ok || (up_err <= mid_err )) &&
  184. (!down_ok || (up_err <= down_err)) )
  185. {
  186. *best_delta = delta_up;
  187. myFtoi(&itemp, (up_src_dim + ((float)(delta_up) / (1<<12))));
  188. *src_dimension = (unsigned long)(itemp - filter_adj);
  189. result = 1;
  190. }
  191. else
  192. {
  193. result = 0;
  194. *best_delta = delta_mid;
  195. myFtoi(&itemp, (mid_src_dim + ((float)(delta_mid) / (1<<12))));
  196. myFtoi(&itemp, (itemp - filter_adj) + 0.9999f);
  197. *src_dimension = (unsigned long)itemp;
  198. }
  199. return result;
  200. } // __OV_Compute_Best_Fit_Delta
  201. //-----------------------------------------------------------------------------
  202. //
  203. // __OV_Find_Zoom
  204. //
  205. //-----------------------------------------------------------------------------
  206. #define VALID_WIDTH(w) ((w & 3) == 0)
  207. #define MAKE_VALID_WIDTH(w) ((w) & ~0x3)
  208. #define WIDTH_STEP 4
  209. int
  210. __OV_Find_Zoom(
  211. unsigned long src_width,
  212. unsigned long* shrink_width,
  213. unsigned long dest_width,
  214. unsigned long* zoom_delta,
  215. BOOL bFilter)
  216. {
  217. int zoom_ok;
  218. int zx_adj = 0;
  219. // Find a suitable zoom delta for the given source
  220. // the source image may be adjusted in width by as much as 8 pixels to
  221. // acheive a match
  222. // Find zoom for requested width
  223. unsigned long trunc_width = MAKE_VALID_WIDTH(*shrink_width);
  224. zoom_ok = __OV_Compute_Best_Fit_Delta(&trunc_width,
  225. dest_width,
  226. zx_adj,
  227. (bFilter ? 1 : 0),
  228. zoom_delta);
  229. // If no zoom was matched for the requested width, start searching up and down
  230. if (!zoom_ok || (!VALID_WIDTH(trunc_width)))
  231. {
  232. unsigned long up_width = MAKE_VALID_WIDTH(trunc_width) + WIDTH_STEP;
  233. unsigned long down_width = MAKE_VALID_WIDTH(trunc_width) - WIDTH_STEP;
  234. int done_up = 0;
  235. int done_down = 0;
  236. do
  237. {
  238. // Check upwards
  239. zoom_ok = 0;
  240. if (up_width < dest_width)
  241. {
  242. unsigned long new_width = up_width;
  243. zoom_ok = __OV_Compute_Best_Fit_Delta(&new_width,
  244. dest_width,
  245. zx_adj,
  246. (bFilter ? 1 : 0),
  247. zoom_delta);
  248. // If the above call somehow adjusts width to invalid,
  249. // mark the delta invalid
  250. if (!VALID_WIDTH(new_width))
  251. {
  252. zoom_ok = 0;
  253. }
  254. if (zoom_ok)
  255. {
  256. *shrink_width = new_width;
  257. }
  258. else
  259. {
  260. up_width += WIDTH_STEP;
  261. }
  262. }
  263. else
  264. done_up = 1;
  265. // Check downwards
  266. if (!zoom_ok && (down_width >= 4) && (down_width < src_width))
  267. {
  268. unsigned long new_width = down_width;
  269. zoom_ok =
  270. __OV_Compute_Best_Fit_Delta(&new_width, dest_width, zx_adj, (bFilter ? 1 : 0),
  271. zoom_delta);
  272. // If the above call somehow adjusts width to invalid,
  273. // mark the delta invalid
  274. if (!VALID_WIDTH(new_width))
  275. {
  276. zoom_ok = 0;
  277. }
  278. if (zoom_ok)
  279. {
  280. *shrink_width = new_width;
  281. }
  282. else
  283. {
  284. down_width -= WIDTH_STEP;
  285. }
  286. }
  287. else
  288. {
  289. done_down = 1;
  290. }
  291. } while (!zoom_ok && (!done_up || !done_down));
  292. }
  293. return zoom_ok;
  294. } // __OV_Find_Zoom
  295. //-----------------------------------------------------------------------------
  296. //
  297. // __OV_Compute_Params
  298. //
  299. //-----------------------------------------------------------------------------
  300. unsigned long
  301. __OV_Compute_Params(
  302. unsigned long src_width,
  303. unsigned long dest_width,
  304. unsigned long *ovr_shrinkxd,
  305. unsigned long *ovr_zoomxd,
  306. unsigned long *ovr_w,
  307. BOOL bFilter)
  308. {
  309. unsigned long iterations = 0;
  310. unsigned long sx_adj = 0;
  311. const unsigned long fixed_one = 0x00001000;
  312. //
  313. // Use the source and destination rectangle dimensions to compute
  314. // delta values
  315. //
  316. int zoom_ok;
  317. unsigned long adj_src_width = src_width + 1; // +1 to account for -- below
  318. unsigned long exact_shrink_xd;
  319. unsigned long exact_zoom_xd;
  320. do
  321. {
  322. unsigned long shrink_width;
  323. // Step to next source width
  324. adj_src_width--;
  325. // Make a stab at the deltas for the current source width
  326. // Initially, the deltas are assumed to be 1, and the width due to
  327. // shrinking is therefore equal to src width
  328. shrink_width = adj_src_width;
  329. exact_shrink_xd = fixed_one;
  330. exact_zoom_xd = fixed_one;
  331. // Compute the shrink width and delta required
  332. if (dest_width < adj_src_width)
  333. {
  334. // Shrink
  335. myFtoi(&exact_shrink_xd, (((float)(adj_src_width - sx_adj) /
  336. (float)(dest_width)) * (1<<12)) + 0.999f);
  337. myFtoi(&shrink_width,(adj_src_width - sx_adj) /
  338. ((float)(exact_shrink_xd) / (1<<12)));
  339. }
  340. // Truncate shrink to valid width
  341. if (!VALID_WIDTH(shrink_width) && (shrink_width > 4))
  342. {
  343. shrink_width = MAKE_VALID_WIDTH(shrink_width);
  344. myFtoi(&exact_shrink_xd,(((float)(adj_src_width - sx_adj) /
  345. (float)(shrink_width)) * (1<<12)) + 0.999f);
  346. }
  347. // Compute any zoom delta required
  348. zoom_ok = 1;
  349. if (shrink_width < dest_width)
  350. {
  351. // Make an attempt at a zoom delta, and shrink-width for this src width
  352. zoom_ok = __OV_Find_Zoom(adj_src_width, &shrink_width, dest_width,
  353. &exact_zoom_xd, bFilter);
  354. // Compute shrink delta
  355. myFtoi(&exact_shrink_xd,(((float)(adj_src_width - sx_adj) /
  356. (float)(shrink_width)) * (1<<12)) + 0.999f);
  357. }
  358. } while (0);
  359. *ovr_zoomxd = exact_zoom_xd;
  360. *ovr_shrinkxd = exact_shrink_xd;
  361. *ovr_w = adj_src_width;
  362. return iterations;
  363. } // __OV_Compute_Params
  364. //-----------------------------------------------------------------------------
  365. //
  366. // __OV_ClipRectangles
  367. //
  368. // Clip the dest rectangle against the screen and change the source
  369. // rect appropriately
  370. //
  371. //-----------------------------------------------------------------------------
  372. void
  373. __OV_ClipRectangles(
  374. P3_THUNKEDDATA* pThisDisplay,
  375. DRVRECT* rcNewSrc,
  376. DRVRECT* rcNewDest)
  377. {
  378. float ScaleX;
  379. float ScaleY;
  380. float OffsetX;
  381. float OffsetY;
  382. float fTemp;
  383. DRVRECT rcSrc;
  384. DRVRECT rcDest;
  385. // Find the scale and offset from screen rects to overlay rects.
  386. // This is like a transform to take the dest rect to the source.
  387. ScaleX = (float)( pThisDisplay->P3Overlay.rcSrc.right -
  388. pThisDisplay->P3Overlay.rcSrc.left ) /
  389. (float)( pThisDisplay->P3Overlay.rcDest.right -
  390. pThisDisplay->P3Overlay.rcDest.left );
  391. ScaleY = (float)(pThisDisplay->P3Overlay.rcSrc.bottom -
  392. pThisDisplay->P3Overlay.rcSrc.top ) /
  393. (float)( pThisDisplay->P3Overlay.rcDest.bottom -
  394. pThisDisplay->P3Overlay.rcDest.top );
  395. OffsetX = ((float)pThisDisplay->P3Overlay.rcSrc.left / ScaleX) -
  396. (float)pThisDisplay->P3Overlay.rcDest.left;
  397. OffsetY = ((float)pThisDisplay->P3Overlay.rcSrc.top / ScaleY) -
  398. (float)pThisDisplay->P3Overlay.rcDest.top;
  399. // Clip the dest against the screen
  400. if (pThisDisplay->P3Overlay.rcDest.right >
  401. (LONG)pThisDisplay->dwScreenWidth)
  402. {
  403. rcDest.right = (LONG)pThisDisplay->dwScreenWidth;
  404. }
  405. else
  406. {
  407. rcDest.right = pThisDisplay->P3Overlay.rcDest.right;
  408. }
  409. if (pThisDisplay->P3Overlay.rcDest.left < 0)
  410. {
  411. rcDest.left = 0;
  412. }
  413. else
  414. {
  415. rcDest.left = pThisDisplay->P3Overlay.rcDest.left;
  416. }
  417. if (pThisDisplay->P3Overlay.rcDest.top < 0)
  418. {
  419. rcDest.top = 0;
  420. }
  421. else
  422. {
  423. rcDest.top = pThisDisplay->P3Overlay.rcDest.top;
  424. }
  425. if (pThisDisplay->P3Overlay.rcDest.bottom >
  426. (LONG)pThisDisplay->dwScreenHeight)
  427. {
  428. rcDest.bottom = (LONG)pThisDisplay->dwScreenHeight;
  429. }
  430. else
  431. {
  432. rcDest.bottom = pThisDisplay->P3Overlay.rcDest.bottom;
  433. }
  434. // Transform the new dest rect to the new source rect
  435. fTemp = ( ( (float)rcDest.left + OffsetX ) * ScaleX + 0.499f);
  436. myFtoi ( (int*)&(rcSrc.left), fTemp );
  437. fTemp = ( ( (float)rcDest.right + OffsetX ) * ScaleX + 0.499f);
  438. myFtoi ( (int*)&(rcSrc.right), fTemp );
  439. fTemp = ( ( (float)rcDest.top + OffsetY ) * ScaleY + 0.499f);
  440. myFtoi ( (int*)&(rcSrc.top), fTemp );
  441. fTemp = ( ( (float)rcDest.bottom + OffsetY ) * ScaleY + 0.499f);
  442. myFtoi ( (int*)&(rcSrc.bottom), fTemp );
  443. *rcNewSrc = rcSrc;
  444. *rcNewDest = rcDest;
  445. DISPDBG((DBGLVL,"rcSrc.left: %d, rcSrc.right: %d",
  446. rcSrc.left, rcSrc.right));
  447. DISPDBG((DBGLVL,"rcDest.left: %d, rcDest.right: %d",
  448. rcDest.left, rcDest.right));
  449. return;
  450. } // __OV_ClipRectangles
  451. //-----------------------------------------------------------------------------
  452. //
  453. // _DD_OV_UpdateSource
  454. //
  455. // Update the source DDRAW surface that we are displaying from
  456. // This routine is also used when using the overlay to stretch up for a
  457. // DFP display, so the DDraw overlay mechnism may be disabled and inactive
  458. // when this is called. It must allow for this.
  459. //
  460. //-----------------------------------------------------------------------------
  461. void
  462. _DD_OV_UpdateSource(
  463. P3_THUNKEDDATA* pThisDisplay,
  464. LPDDRAWI_DDRAWSURFACE_LCL pSurf)
  465. {
  466. DWORD dwOverlaySourceOffset;
  467. DISPDBG ((DBGLVL,"** In _DD_OV_UpdateSource"));
  468. // Update current overlay surface
  469. pThisDisplay->P3Overlay.pCurrentOverlay = pSurf->lpGbl->fpVidMem;
  470. // Increase the buffer index
  471. pThisDisplay->P3Overlay.dwCurrentVideoBuffer++;
  472. if (pThisDisplay->P3Overlay.dwCurrentVideoBuffer > 2)
  473. {
  474. pThisDisplay->P3Overlay.dwCurrentVideoBuffer = 0;
  475. }
  476. dwOverlaySourceOffset = (DWORD)(pSurf->lpGbl->fpVidMem -
  477. pThisDisplay->dwScreenFlatAddr);
  478. switch (DDSurf_BitDepth(pSurf))
  479. {
  480. case 8:
  481. break;
  482. case 16:
  483. dwOverlaySourceOffset >>= 1;
  484. break;
  485. case 32:
  486. dwOverlaySourceOffset >>= 2;
  487. break;
  488. default:
  489. DISPDBG((ERRLVL,"Oops Overlay depth makes no sense"));
  490. break;
  491. }
  492. switch(pThisDisplay->P3Overlay.dwCurrentVideoBuffer)
  493. {
  494. case 0:
  495. LOAD_GLINT_CTRL_REG(VideoOverlayBase0, dwOverlaySourceOffset);
  496. LOAD_GLINT_CTRL_REG(VideoOverlayIndex, 0);
  497. break;
  498. case 1:
  499. LOAD_GLINT_CTRL_REG(VideoOverlayBase1, dwOverlaySourceOffset);
  500. LOAD_GLINT_CTRL_REG(VideoOverlayIndex, 1);
  501. break;
  502. case 2:
  503. LOAD_GLINT_CTRL_REG(VideoOverlayBase2, dwOverlaySourceOffset);
  504. LOAD_GLINT_CTRL_REG(VideoOverlayIndex, 2);
  505. break;
  506. }
  507. } // _DD_OV_UpdateSource
  508. //-----------------------------------------------------------------------------
  509. //
  510. // __OV_UpdatePosition
  511. //
  512. // Given the correct starting rectangle, this function clips it against the
  513. // screen and updates the overlay position registers.
  514. // If *pdwShrinkFactor is NULL, then the overlay is updated, otherwise the
  515. // desired shrink factor is put in *pdwShrinkFactor and the registers are
  516. // NOT updated. This is so the shrink factor can be checked to see if the
  517. // overlay would actually work in this case.
  518. //
  519. //-----------------------------------------------------------------------------
  520. void
  521. __OV_UpdatePosition(
  522. P3_THUNKEDDATA* pThisDisplay,
  523. DWORD *pdwShrinkFactor)
  524. {
  525. DWORD dwSrcWidth;
  526. DWORD dwSrcHeight;
  527. DWORD dwDestHeight;
  528. DWORD dwDestWidth;
  529. DWORD dwXDeltaZoom;
  530. DWORD dwXDeltaShrink;
  531. DWORD dwYDelta;
  532. DWORD dwSrcAdjust;
  533. DRVRECT rcNewSrc;
  534. DRVRECT rcNewDest;
  535. P3RDRAMDAC *pP3RDRegs;
  536. DWORD dwLastShrink;
  537. DWORD dwLastZoom;
  538. DISPDBG ((DBGLVL,"**In __OV_UpdatePosition"));
  539. // Get a pointer to the ramdac
  540. pP3RDRegs = (P3RDRAMDAC *)&(pThisDisplay->pGlint->ExtVCReg);
  541. // Get the clipped destination rectangles
  542. __OV_ClipRectangles(pThisDisplay, &rcNewSrc, &rcNewDest);
  543. // Get the widths
  544. dwDestWidth = (DWORD)(rcNewDest.right - rcNewDest.left);
  545. dwDestHeight = (DWORD)(rcNewDest.bottom - rcNewDest.top);
  546. dwSrcWidth = (DWORD)(rcNewSrc.right - rcNewSrc.left);
  547. dwSrcHeight = (DWORD)(rcNewSrc.bottom - rcNewSrc.top);
  548. if ( pThisDisplay->bOverlayPixelDouble )
  549. {
  550. // We need to double the destination width first.
  551. dwDestWidth <<= 1;
  552. }
  553. // Compute the overlay parameters
  554. __OV_Compute_Params(dwSrcWidth,
  555. dwDestWidth,
  556. &dwXDeltaShrink,
  557. &dwXDeltaZoom,
  558. &dwSrcAdjust,
  559. ( ( pThisDisplay->dwOverlayFiltering & OVERLAY_FILTERING_X ) != 0 ) );
  560. DISPDBG((DBGLVL,"OVERLAY: XShrink 0x%x", dwXDeltaShrink));
  561. DISPDBG((DBGLVL,"OVERLAY: XZoom 0x%x", dwXDeltaZoom));
  562. if ( pdwShrinkFactor != NULL )
  563. {
  564. // We just wanted to know the shrink factor.
  565. *pdwShrinkFactor = dwXDeltaShrink;
  566. return;
  567. }
  568. dwLastZoom = READ_GLINT_CTRL_REG(VideoOverlayZoomXDelta);
  569. dwLastShrink = READ_GLINT_CTRL_REG(VideoOverlayShrinkXDelta);
  570. if ( ((dwLastZoom >> 4) != dwXDeltaZoom) ||
  571. ((dwLastShrink >> 4) != dwXDeltaShrink) )
  572. {
  573. //dwCurrentMode = READ_GLINT_CTRL_REG(VideoOverlayMode);
  574. //LOAD_GLINT_CTRL_REG(VideoOverlayMode, 0);
  575. LOAD_GLINT_CTRL_REG(VideoOverlayZoomXDelta, (dwXDeltaZoom << 4));
  576. LOAD_GLINT_CTRL_REG(VideoOverlayShrinkXDelta, (dwXDeltaShrink << 4));
  577. DISPDBG((DBGLVL,"OVERLAY: VideoOverlayZoomXDelta 0x%x", dwXDeltaZoom << 4));
  578. DISPDBG((DBGLVL,"OVERLAY: VideoOverlayShrinkXDelta 0x%x", dwXDeltaShrink << 4));
  579. //LOAD_GLINT_CTRL_REG(VideoOverlayMode, dwCurrentMode);
  580. }
  581. // Load up the Y scaling
  582. if ( ( pThisDisplay->dwOverlayFiltering & OVERLAY_FILTERING_Y ) != 0 )
  583. {
  584. // Apply filtering.
  585. dwYDelta = ( ( ( dwSrcHeight - 1 ) << 12 ) + dwDestHeight - 1 ) / dwDestHeight;
  586. // Make sure this will cause proper termination
  587. ASSERTDD ( ( dwYDelta * dwDestHeight ) >= ( ( dwSrcHeight - 1 ) << 12 ), "** __OV_UpdatePosition: dwYDelta is not big enough" );
  588. ASSERTDD ( ( dwYDelta * ( dwDestHeight - 1 ) ) < ( ( dwSrcHeight - 1 ) << 12 ), "** __OV_UpdatePosition: dwYDelta is too big" );
  589. dwYDelta <<= 4;
  590. }
  591. else
  592. {
  593. dwYDelta = ( ( dwSrcHeight << 12 ) + dwDestHeight - 1 ) / dwDestHeight;
  594. // Make sure this will cause proper termination
  595. ASSERTDD ( ( dwYDelta * dwDestHeight ) >= ( dwSrcHeight << 12 ), "** __OV_UpdatePosition: dwYDelta is not big enough" );
  596. ASSERTDD ( ( dwYDelta * ( dwDestHeight - 1 ) ) < ( dwSrcHeight << 12 ), "** __OV_UpdatePosition: dwYDelta is too big" );
  597. dwYDelta <<= 4;
  598. }
  599. LOAD_GLINT_CTRL_REG(VideoOverlayYDelta, dwYDelta);
  600. // Width & Height
  601. if ( RENDERCHIP_PERMEDIAP3 )
  602. {
  603. // These registers are _not_ synched to VBLANK like all the others,
  604. // so we need to do it manually.
  605. if ( ( pThisDisplay->dwOverlayFiltering & OVERLAY_FILTERING_Y ) != 0 )
  606. {
  607. SET_OVERLAY_HEIGHT ( pThisDisplay, ( rcNewSrc.bottom - rcNewSrc.top - 1 ) );
  608. }
  609. else
  610. {
  611. SET_OVERLAY_HEIGHT ( pThisDisplay, rcNewSrc.bottom - rcNewSrc.top );
  612. }
  613. SET_OVERLAY_WIDTH ( pThisDisplay, rcNewSrc.right - rcNewSrc.left );
  614. }
  615. else
  616. {
  617. // These auto-sync on everything else.
  618. LOAD_GLINT_CTRL_REG(VideoOverlayWidth, rcNewSrc.right - rcNewSrc.left);
  619. LOAD_GLINT_CTRL_REG(VideoOverlayHeight, rcNewSrc.bottom - rcNewSrc.top);
  620. }
  621. // Origin of source
  622. LOAD_GLINT_CTRL_REG(VideoOverlayOrigin, (rcNewSrc.top << 16) | (rcNewSrc.left & 0xFFFF));
  623. DISPDBG((DBGLVL,"OVERLAY: VideoOverlayWidth 0x%x", rcNewSrc.right - rcNewSrc.left));
  624. DISPDBG((DBGLVL,"OVERLAY: VideoOverlayHeight 0x%x", rcNewSrc.bottom - rcNewSrc.top));
  625. DISPDBG((DBGLVL,"OVERLAY: VideoOverlayOrigin 0x%x", (rcNewSrc.top << 16) | (rcNewSrc.left & 0xFFFF) ));
  626. DISPDBG((DBGLVL,"OVERLAY: VideoOverlayYDelta 0x%x", dwYDelta ));
  627. // Setup Overlay Dest in RAMDAC Unit.
  628. // RAMDAC registers are only 8bits wide.
  629. if ( pThisDisplay->bOverlayPixelDouble )
  630. {
  631. // Need to double all these numbers.
  632. P3RD_LOAD_INDEX_REG(P3RD_VIDEO_OVERLAY_XSTARTLOW, ((rcNewDest.left << 1) & 0xFF));
  633. P3RD_LOAD_INDEX_REG(P3RD_VIDEO_OVERLAY_XSTARTHIGH, (rcNewDest.left >> 7));
  634. P3RD_LOAD_INDEX_REG(P3RD_VIDEO_OVERLAY_XENDLOW, ((rcNewDest.right << 1 ) & 0xFF));
  635. P3RD_LOAD_INDEX_REG(P3RD_VIDEO_OVERLAY_XENDHIGH, (rcNewDest.right >> 7));
  636. }
  637. else
  638. {
  639. P3RD_LOAD_INDEX_REG(P3RD_VIDEO_OVERLAY_XSTARTLOW, (rcNewDest.left & 0xFF));
  640. P3RD_LOAD_INDEX_REG(P3RD_VIDEO_OVERLAY_XSTARTHIGH, (rcNewDest.left >> 8));
  641. P3RD_LOAD_INDEX_REG(P3RD_VIDEO_OVERLAY_XENDLOW, (rcNewDest.right & 0xFF));
  642. P3RD_LOAD_INDEX_REG(P3RD_VIDEO_OVERLAY_XENDHIGH, (rcNewDest.right >> 8));
  643. }
  644. P3RD_LOAD_INDEX_REG(P3RD_VIDEO_OVERLAY_YSTARTLOW, (rcNewDest.top & 0xFF));
  645. P3RD_LOAD_INDEX_REG(P3RD_VIDEO_OVERLAY_YSTARTHIGH, (rcNewDest.top >> 8));
  646. P3RD_LOAD_INDEX_REG(P3RD_VIDEO_OVERLAY_YENDLOW, (rcNewDest.bottom & 0xFF));
  647. P3RD_LOAD_INDEX_REG(P3RD_VIDEO_OVERLAY_YENDHIGH, (rcNewDest.bottom >> 8));
  648. DISPDBG((DBGLVL,"OVERLAY: P3RD_VIDEO_OVERLAY_XSTARTLOW 0x%x", (rcNewDest.left & 0xFF) ));
  649. DISPDBG((DBGLVL,"OVERLAY: P3RD_VIDEO_OVERLAY_XSTARTHIGH 0x%x", (rcNewDest.left >> 8) ));
  650. DISPDBG((DBGLVL,"OVERLAY: P3RD_VIDEO_OVERLAY_YSTARTLOW 0x%x", (rcNewDest.top & 0xFF) ));
  651. DISPDBG((DBGLVL,"OVERLAY: P3RD_VIDEO_OVERLAY_YSTARTHIGH 0x%x", (rcNewDest.top >> 8) ));
  652. DISPDBG((DBGLVL,"OVERLAY: P3RD_VIDEO_OVERLAY_XENDLOW 0x%x", (rcNewDest.right & 0xFF) ));
  653. DISPDBG((DBGLVL,"OVERLAY: P3RD_VIDEO_OVERLAY_XENDHIGH 0x%x", (rcNewDest.right >> 8) ));
  654. DISPDBG((DBGLVL,"OVERLAY: P3RD_VIDEO_OVERLAY_YENDLOW 0x%x", (rcNewDest.bottom & 0xFF) ));
  655. DISPDBG((DBGLVL,"OVERLAY: P3RD_VIDEO_OVERLAY_YENDHIGH 0x%x", (rcNewDest.bottom >> 8) ));
  656. } // __OV_UpdatePosition
  657. //-----------------------------------------------------------------------------
  658. //
  659. // DdUpdateOverlay
  660. //
  661. // Repositions or modifies the visual attributes of an overlay surface.
  662. //
  663. // DdUpdateOverlay shows, hides, or repositions an overlay surface on the
  664. // screen. It also sets attributes of the overlay surface, such as the stretch
  665. // factor or type of color key to be used.
  666. //
  667. // The driver should determine whether it has the bandwidth to support the
  668. // overlay update request. The driver should use dwFlags to determine the type
  669. // of request and how to process it.
  670. //
  671. // The driver/hardware must stretch or shrink the overlay accordingly when the
  672. // rectangles specified by rDest and rSrc are different sizes.
  673. //
  674. // Note that DdFlip is used for flipping between overlay surfaces, so
  675. // performance for DdUpdateOverlay is not critical.
  676. //
  677. //
  678. // Parameters
  679. //
  680. // puod
  681. // Points to a DD_UPDATEOVERLAYDATA structure that contains the
  682. // information required to update the overlay.
  683. //
  684. // .lpDD
  685. // Points to a DD_DIRECTDRAW_GLOBAL structure that represents
  686. // the DirectDraw object.
  687. // .lpDDDestSurface
  688. // Points to a DD_SURFACE_LOCAL structure that represents the
  689. // DirectDraw surface to be overlaid. This value can be NULL
  690. // if DDOVER_HIDE is specified in dwFlags.
  691. // .rDest
  692. // Specifies a RECTL structure that contains the x, y, width,
  693. // and height of the region on the destination surface to be
  694. // overlaid.
  695. // .lpDDSrcSurface
  696. // Points to a DD_SURFACE_LOCAL structure that describes the
  697. // overlay surface.
  698. // .rSrc
  699. // Specifies a RECTL structure that contains the x, y, width,
  700. // and height of the region on the source surface to be used
  701. // for the overlay.
  702. // .dwFlags
  703. // Specifies how the driver should handle the overlay. This
  704. // member can be a combination of any of the following flags:
  705. //
  706. // DDOVER_HIDE
  707. // The driver should hide the overlay; that is, the driver
  708. // should turn this overlay off.
  709. // DDOVER_SHOW
  710. // The driver should show the overlay; that is, the driver
  711. // should turn this overlay on.
  712. // DDOVER_KEYDEST
  713. // The driver should use the color key associated with the
  714. // destination surface.
  715. // DDOVER_KEYDESTOVERRIDE
  716. // The driver should use the dckDestColorKey member of the
  717. // DDOVERLAYFX structure as the destination color key
  718. // instead of the color key associated with the destination
  719. // surface.
  720. // DDOVER_KEYSRC
  721. // The driver should use the color key associated with the
  722. // destination surface.
  723. // DDOVER_KEYSRCOVERRIDE
  724. // The driver should use the dckSrcColorKey member of the
  725. // DDOVERLAYFX structure as the source color key instead of
  726. // the color key associated with the destination surface.
  727. // DDOVER_DDFX
  728. // The driver should show the overlay surface using the
  729. // attributes specified by overlayFX.
  730. // DDOVER_ADDDIRTYRECT
  731. // Should be ignored by the driver.
  732. // DDOVER_REFRESHDIRTYRECTS
  733. // Should be ignored by the driver.
  734. // DDOVER_REFRESHALL
  735. // Should be ignored by the driver.
  736. // DDOVER_INTERLEAVED
  737. // The overlay surface is composed of interleaved fields.
  738. // Drivers that support VPE need only check this flag.
  739. // DDOVER_AUTOFLIP
  740. // The driver should autoflip the overlay whenever the
  741. // hardware video port autoflips. Drivers that support VPE
  742. // need only check this flag.
  743. // DDOVER_BOB
  744. // The driver should display each field of VPE object data
  745. // individually without causing any jittery artifacts. This
  746. // flag pertains to both VPE and decoders that want to do
  747. // their own flipping in kernel mode using the kernel-mode
  748. // video transport functionality.
  749. // DDOVER_OVERRIDEBOBWEAVE
  750. // Bob/weave decisions should not be overridden by other
  751. // interfaces. If the overlay mixer sets this flag, DirectDraw
  752. // will not allow a kernel-mode driver to use the kernel-mode
  753. // video transport functionality to switch the hardware
  754. // between bob and weave mode.
  755. // DDOVER_BOBHARDWARE
  756. // Indicates that bob will be performed by hardware rather
  757. // than by software or emulation. Drivers that support VPE
  758. // need only check this flag.
  759. //
  760. // .overlayFX
  761. // Specifies a DDOVERLAYFX structure describing additional effects
  762. // that the driver should use to update the overlay. The driver
  763. // should use this structure only if one of DDOVER_DDFX,
  764. // DDOVER_KEYDESTOVERRIDE, or DDOVER_KEYSRCOVERRIDE are set in
  765. // dwFlags.
  766. // .ddRVal
  767. // Specifies the location in which the driver writes the return
  768. // value of the DdUpdateOverlay callback. A return code of DD_OK
  769. // indicates success.
  770. // .UpdateOverlay
  771. // This is unused on Windows 2000.
  772. //
  773. //-----------------------------------------------------------------------------
  774. DWORD CALLBACK
  775. DdUpdateOverlay(
  776. LPDDHAL_UPDATEOVERLAYDATA puod)
  777. {
  778. P3_THUNKEDDATA* pThisDisplay;
  779. DWORD dwDestColourKey;
  780. DWORD dwSrcColourKey;
  781. BOOL bSrcColorKey = FALSE;
  782. BOOL bDestColorKey = FALSE;
  783. P3_SURF_FORMAT* pFormatOverlaySrc;
  784. P3_SURF_FORMAT* pFormatOverlayDest;
  785. DWORD dwOverlayControl = 0;
  786. P3RDRAMDAC *pP3RDRegs;
  787. VideoOverlayModeReg OverlayMode;
  788. RDVideoOverlayControlReg RDOverlayControl;
  789. DWORD dwVideoOverlayUpdate;
  790. int iCurEntry, iCurDotBandwidth, iCurMemBandwidth,
  791. iCurSourceWidth, iCurWidthCoverage;
  792. BOOL bNoFilterInY;
  793. GET_THUNKEDDATA(pThisDisplay, puod->lpDD);
  794. // Get a pointer to the ramdac
  795. pP3RDRegs = (P3RDRAMDAC *)&(pThisDisplay->pGlint->ExtVCReg);
  796. DISPDBG ((DBGLVL,"**In DdUpdateOverlay dwFlags = %x",puod->dwFlags));
  797. ZeroMemory(&OverlayMode, sizeof(VideoOverlayModeReg));
  798. ZeroMemory(&RDOverlayControl, sizeof(RDOverlayControl));
  799. do
  800. {
  801. dwVideoOverlayUpdate = READ_GLINT_CTRL_REG(VideoOverlayUpdate);
  802. } while ((dwVideoOverlayUpdate & 0x1) != 0);
  803. // Are we hiding the overlay?
  804. if (puod->dwFlags & DDOVER_HIDE)
  805. {
  806. DISPDBG((DBGLVL,"** DdUpdateOverlay - hiding."));
  807. // Hide the overlay.
  808. if (pThisDisplay->P3Overlay.dwVisibleOverlays == 0)
  809. {
  810. // No overlay being shown.
  811. DISPDBG((WRNLVL,"** DdUpdateOverlay - DDOVER_HIDE - already hidden."));
  812. puod->ddRVal = DDERR_OUTOFCAPS;
  813. return DDHAL_DRIVER_HANDLED;
  814. }
  815. // Hide an overlay which is not shown
  816. if (pThisDisplay->P3Overlay.pCurrentOverlay !=
  817. puod->lpDDSrcSurface->lpGbl->fpVidMem)
  818. {
  819. // No overlay being shown.
  820. DISPDBG((WRNLVL,"** DdUpdateOverlay - overlay not visible."));
  821. puod->ddRVal = DD_OK;
  822. return DDHAL_DRIVER_HANDLED;
  823. }
  824. OverlayMode.Enable = __PERMEDIA_DISABLE;
  825. RDOverlayControl.Enable = __PERMEDIA_DISABLE;
  826. ENABLE_OVERLAY(pThisDisplay, FALSE);
  827. pThisDisplay->P3Overlay.pCurrentOverlay = (FLATPTR)NULL;
  828. pThisDisplay->P3Overlay.dwVisibleOverlays = 0;
  829. }
  830. // Are we showing the overlay?
  831. else if ((puod->dwFlags & DDOVER_SHOW) ||
  832. (pThisDisplay->P3Overlay.dwVisibleOverlays != 0))
  833. {
  834. if (pThisDisplay->P3Overlay.dwVisibleOverlays > 0)
  835. {
  836. // Compare the video memory pointer to decide whether this is the
  837. // the current overlay surface
  838. if (pThisDisplay->P3Overlay.pCurrentOverlay !=
  839. puod->lpDDSrcSurface->lpGbl->fpVidMem)
  840. {
  841. // Overlay is already being displayed. Can't have a new one.
  842. DISPDBG((WRNLVL,"** DdUpdateOverlay - DDOVER_SHOW - already being shown, and it's a new surface."));
  843. puod->ddRVal = DDERR_OUTOFCAPS;
  844. return DDHAL_DRIVER_HANDLED;
  845. }
  846. }
  847. if (((pThisDisplay->pGLInfo->dwFlags & GMVF_DFP_DISPLAY) != 0) &&
  848. ((pThisDisplay->pGLInfo->dwScreenWidth != pThisDisplay->pGLInfo->dwVideoWidth) ||
  849. (pThisDisplay->pGLInfo->dwScreenHeight != pThisDisplay->pGLInfo->dwVideoHeight)))
  850. {
  851. // Display driver is using the overlay on a DFP, so we can't use it.
  852. DISPDBG((WRNLVL,"** DdUpdateOverlay - DDOVER_SHOW - overlay being used for desktop stretching on DFP."));
  853. puod->ddRVal = DDERR_OUTOFCAPS;
  854. return DDHAL_DRIVER_HANDLED;
  855. }
  856. // See if the screen is currently byte-doubled.
  857. if ( ( ( READ_GLINT_CTRL_REG(MiscControl) ) & 0x80 ) == 0 )
  858. {
  859. pThisDisplay->bOverlayPixelDouble = FALSE;
  860. }
  861. else
  862. {
  863. pThisDisplay->bOverlayPixelDouble = TRUE;
  864. }
  865. // Set up Video Overlay Color Format.
  866. pFormatOverlaySrc = _DD_SUR_GetSurfaceFormat( puod->lpDDSrcSurface);
  867. pFormatOverlayDest = _DD_SUR_GetSurfaceFormat( puod->lpDDDestSurface);
  868. pThisDisplay->P3Overlay.dwCurrentVideoBuffer = 0;
  869. OverlayMode.Enable = __PERMEDIA_ENABLE;
  870. RDOverlayControl.Enable = __PERMEDIA_ENABLE;
  871. ENABLE_OVERLAY(pThisDisplay, TRUE);
  872. pThisDisplay->P3Overlay.dwVisibleOverlays = 1;
  873. if (pFormatOverlaySrc->DeviceFormat == SURF_YUV422)
  874. {
  875. OverlayMode.YUV = VO_YUV_422;
  876. OverlayMode.ColorOrder = VO_COLOR_ORDER_BGR;
  877. }
  878. else if (pFormatOverlaySrc->DeviceFormat == SURF_YUV444)
  879. {
  880. OverlayMode.YUV = VO_YUV_444;
  881. OverlayMode.ColorOrder = VO_COLOR_ORDER_BGR;
  882. }
  883. else
  884. {
  885. OverlayMode.YUV = VO_YUV_RGB;
  886. OverlayMode.ColorOrder = VO_COLOR_ORDER_RGB;
  887. switch (pFormatOverlaySrc->DitherFormat)
  888. {
  889. case P3RX_DITHERMODE_COLORFORMAT_8888:
  890. OverlayMode.ColorFormat = VO_CF_RGB8888;
  891. break;
  892. case P3RX_DITHERMODE_COLORFORMAT_4444:
  893. OverlayMode.ColorFormat = VO_CF_RGB4444;
  894. break;
  895. case P3RX_DITHERMODE_COLORFORMAT_5551:
  896. OverlayMode.ColorFormat = VO_CF_RGB5551;
  897. break;
  898. case P3RX_DITHERMODE_COLORFORMAT_565:
  899. OverlayMode.ColorFormat = VO_CF_RGB565;
  900. break;
  901. case P3RX_DITHERMODE_COLORFORMAT_332:
  902. OverlayMode.ColorFormat = VO_CF_RGB332;
  903. break;
  904. case P3RX_DITHERMODE_COLORFORMAT_CI:
  905. OverlayMode.ColorFormat = VO_CF_RGBCI8;
  906. break;
  907. default:
  908. DISPDBG((ERRLVL,"** DdUpdateOverlay: Unknown overlay pixel type"));
  909. puod->ddRVal = DDERR_INVALIDSURFACETYPE;
  910. return DDHAL_DRIVER_HANDLED;
  911. break;
  912. }
  913. }
  914. // Set up Video Overlay Pixel Size
  915. switch (pFormatOverlaySrc->dwBitsPerPixel)
  916. {
  917. case 8:
  918. OverlayMode.PixelSize = VO_PIXEL_SIZE8;
  919. RDOverlayControl.DirectColor = __PERMEDIA_DISABLE;
  920. break;
  921. case 16:
  922. OverlayMode.PixelSize = VO_PIXEL_SIZE16;
  923. RDOverlayControl.DirectColor = __PERMEDIA_ENABLE;
  924. break;
  925. case 32:
  926. OverlayMode.PixelSize = VO_PIXEL_SIZE32;
  927. RDOverlayControl.DirectColor = __PERMEDIA_ENABLE;
  928. break;
  929. default:
  930. break;
  931. }
  932. // Keep the rectangles
  933. pThisDisplay->P3Overlay.rcDest = *(DRVRECT*)&puod->rDest;
  934. if ( pThisDisplay->P3Overlay.rcDest.left == 1 )
  935. {
  936. // Don't use 2 - it will "reveal" the (purple) colourkey colour.
  937. pThisDisplay->P3Overlay.rcDest.left = 0;
  938. }
  939. if ( pThisDisplay->P3Overlay.rcDest.right == 1 )
  940. {
  941. // Don't use 0 - it will "reveal" the (purple) colourkey colour.
  942. pThisDisplay->P3Overlay.rcDest.right = 2;
  943. }
  944. pThisDisplay->P3Overlay.rcSrc = *(DRVRECT*)&puod->rSrc;
  945. pThisDisplay->dwOverlayFiltering = OVERLAY_FILTERING_X |
  946. OVERLAY_FILTERING_Y;
  947. // See if this overlay size works by looking it up in the table.
  948. iCurDotBandwidth = ( pThisDisplay->pGLInfo->PixelClockFrequency << pThisDisplay->pGLInfo->bPixelToBytesShift ) >> 10;
  949. iCurMemBandwidth = pThisDisplay->pGLInfo->MClkFrequency >> 10;
  950. iCurSourceWidth = ( puod->rSrc.right - puod->rSrc.left ) * ( pFormatOverlaySrc->dwBitsPerPixel >> 3 );
  951. iCurWidthCoverage = ( ( puod->rDest.right - puod->rDest.left ) << 16 ) / ( pThisDisplay->pGLInfo->dwScreenWidth );
  952. DISPDBG (( DBGLVL, "DdUpdateOverlay: Looking up mem=%d, pixel=%d, width=%d, coverage=0x%x", iCurMemBandwidth, iCurDotBandwidth, iCurSourceWidth, iCurWidthCoverage ));
  953. iCurEntry = 0;
  954. // Search for a line with lower memory bandwidth and higher everything else.
  955. while ( iCurEntry < SIZE_OF_OVERLAY_WORKS_TABLE )
  956. {
  957. if (( OverlayWorksTable[iCurEntry].iMemBandwidth <= iCurMemBandwidth ) &&
  958. ( OverlayWorksTable[iCurEntry].iDotBandwidth >= iCurDotBandwidth ) &&
  959. ( OverlayWorksTable[iCurEntry].iSourceWidth >= iCurSourceWidth ) &&
  960. ( OverlayWorksTable[iCurEntry].iWidthCoverage >= iCurWidthCoverage ) )
  961. {
  962. // Yep - this should be alright then.
  963. break;
  964. }
  965. iCurEntry++;
  966. }
  967. if ( iCurEntry == SIZE_OF_OVERLAY_WORKS_TABLE )
  968. {
  969. // Oops - this will fall over when filtered.
  970. DISPDBG((DBGLVL,"** P3RXOU32: overlay wanted mem=%d, pixel=%d, width=%d, coverage=0x%x", iCurMemBandwidth, iCurDotBandwidth, iCurSourceWidth, iCurWidthCoverage ));
  971. // Normal behaviour.
  972. bNoFilterInY = TRUE;
  973. }
  974. else
  975. {
  976. DISPDBG((DBGLVL,"** P3RXOU32: found mem=%d, pixel=%d, width=%d, coverage=0x%x", OverlayWorksTable[iCurEntry].iMemBandwidth, OverlayWorksTable[iCurEntry].iDotBandwidth, OverlayWorksTable[iCurEntry].iSourceWidth, OverlayWorksTable[iCurEntry].iWidthCoverage ));
  977. bNoFilterInY = FALSE;
  978. }
  979. if ( bNoFilterInY )
  980. {
  981. // Turn off Y filtering.
  982. pThisDisplay->dwOverlayFiltering &= ~OVERLAY_FILTERING_Y;
  983. }
  984. // Overlay is fine to show.
  985. __OV_UpdatePosition(pThisDisplay, NULL);
  986. _DD_OV_UpdateSource(pThisDisplay, puod->lpDDSrcSurface);
  987. // Stride of source
  988. LOAD_GLINT_CTRL_REG(VideoOverlayStride, DDSurf_GetPixelPitch(puod->lpDDSrcSurface));
  989. LOAD_GLINT_CTRL_REG(VideoOverlayFieldOffset, 0x0);
  990. if ( puod->dwFlags & DDOVER_KEYDEST )
  991. {
  992. // Use destination surface's destination colourkey for dst key.
  993. dwDestColourKey = puod->lpDDDestSurface->ddckCKDestOverlay.dwColorSpaceLowValue;
  994. bDestColorKey = TRUE;
  995. }
  996. if ( puod->dwFlags & DDOVER_KEYDESTOVERRIDE )
  997. {
  998. // Use DDOVERLAYFX dest colour for dst key.
  999. dwDestColourKey = puod->overlayFX.dckDestColorkey.dwColorSpaceLowValue;
  1000. bDestColorKey = TRUE;
  1001. }
  1002. if ( puod->dwFlags & DDOVER_KEYSRC )
  1003. {
  1004. // Use source surface's source colourkey for src key.
  1005. dwSrcColourKey = puod->lpDDSrcSurface->ddckCKSrcOverlay.dwColorSpaceLowValue;
  1006. bSrcColorKey = TRUE;
  1007. }
  1008. if ( puod->dwFlags & DDOVER_KEYSRCOVERRIDE )
  1009. {
  1010. // Use DDOVERLAYFX src colour for src key.
  1011. dwSrcColourKey = puod->overlayFX.dckSrcColorkey.dwColorSpaceLowValue;
  1012. bSrcColorKey = TRUE;
  1013. }
  1014. if (bSrcColorKey && bDestColorKey)
  1015. {
  1016. // We can't do both - return an error.
  1017. puod->ddRVal = DDERR_OUTOFCAPS;
  1018. return DDHAL_DRIVER_HANDLED;
  1019. }
  1020. RDOverlayControl.Mode = VO_MODE_ALWAYS;
  1021. if (bSrcColorKey)
  1022. {
  1023. if (pFormatOverlaySrc->DeviceFormat == SURF_YUV422)
  1024. {
  1025. // Er... this is a very odd pixel format - how do I get a useful number out of it?
  1026. DISPDBG((ERRLVL,"** DdUpdateOverlay: no idea how to get a YUV422 source colour"));
  1027. }
  1028. else if (pFormatOverlaySrc->DeviceFormat == SURF_YUV444)
  1029. {
  1030. // No idea how to get a useful number out of this.
  1031. DISPDBG((ERRLVL,"** DdUpdateOverlay: no idea how to get a YUV444 source colour"));
  1032. }
  1033. else
  1034. {
  1035. switch (pFormatOverlaySrc->DitherFormat)
  1036. {
  1037. case P3RX_DITHERMODE_COLORFORMAT_CI:
  1038. // Formatting already done.
  1039. break;
  1040. case P3RX_DITHERMODE_COLORFORMAT_332:
  1041. dwSrcColourKey = FORMAT_332_32BIT_BGR(dwSrcColourKey);
  1042. break;
  1043. case P3RX_DITHERMODE_COLORFORMAT_5551:
  1044. dwSrcColourKey = FORMAT_5551_32BIT_BGR(dwSrcColourKey);
  1045. break;
  1046. case P3RX_DITHERMODE_COLORFORMAT_4444:
  1047. dwSrcColourKey = FORMAT_4444_32BIT_BGR(dwSrcColourKey);
  1048. break;
  1049. case P3RX_DITHERMODE_COLORFORMAT_565:
  1050. dwSrcColourKey = FORMAT_565_32BIT_BGR(dwSrcColourKey);
  1051. break;
  1052. case P3RX_DITHERMODE_COLORFORMAT_8888:
  1053. dwSrcColourKey = FORMAT_8888_32BIT_BGR(dwSrcColourKey);
  1054. break;
  1055. default:
  1056. DISPDBG((ERRLVL,"** DdUpdateOverlay: Unknown overlay pixel type"));
  1057. break;
  1058. }
  1059. }
  1060. P3RD_LOAD_INDEX_REG(P3RD_VIDEO_OVERLAY_KEYR, (dwSrcColourKey & 0xFF));
  1061. P3RD_LOAD_INDEX_REG(P3RD_VIDEO_OVERLAY_KEYG, ((dwSrcColourKey >> 8) & 0xFF));
  1062. P3RD_LOAD_INDEX_REG(P3RD_VIDEO_OVERLAY_KEYB, ((dwSrcColourKey >> 16) & 0xFF));
  1063. RDOverlayControl.Mode = VO_MODE_OVERLAYKEY;
  1064. }
  1065. if (bDestColorKey)
  1066. {
  1067. switch (pFormatOverlayDest->dwBitsPerPixel)
  1068. {
  1069. case 8:
  1070. P3RD_LOAD_INDEX_REG(P3RD_VIDEO_OVERLAY_KEYR, (dwDestColourKey & 0xFF));
  1071. P3RD_LOAD_INDEX_REG(P3RD_VIDEO_OVERLAY_KEYG, (dwDestColourKey & 0xFF));
  1072. P3RD_LOAD_INDEX_REG(P3RD_VIDEO_OVERLAY_KEYB, (dwDestColourKey & 0xFF));
  1073. break;
  1074. case 16:
  1075. if (pFormatOverlayDest->DitherFormat == P3RX_DITHERMODE_COLORFORMAT_5551)
  1076. {
  1077. dwDestColourKey = FORMAT_5551_32BIT_BGR(dwDestColourKey);
  1078. }
  1079. else
  1080. {
  1081. dwDestColourKey = FORMAT_565_32BIT_BGR(dwDestColourKey);
  1082. }
  1083. P3RD_LOAD_INDEX_REG(P3RD_VIDEO_OVERLAY_KEYR, (dwDestColourKey & 0xFF));
  1084. P3RD_LOAD_INDEX_REG(P3RD_VIDEO_OVERLAY_KEYG, ((dwDestColourKey >> 8) & 0xFF));
  1085. P3RD_LOAD_INDEX_REG(P3RD_VIDEO_OVERLAY_KEYB, ((dwDestColourKey >> 16) & 0xFF));
  1086. break;
  1087. case 32:
  1088. dwDestColourKey = FORMAT_8888_32BIT_BGR(dwDestColourKey);
  1089. P3RD_LOAD_INDEX_REG(P3RD_VIDEO_OVERLAY_KEYR, (dwDestColourKey & 0xFF));
  1090. P3RD_LOAD_INDEX_REG(P3RD_VIDEO_OVERLAY_KEYG, ((dwDestColourKey >> 8) & 0xFF));
  1091. P3RD_LOAD_INDEX_REG(P3RD_VIDEO_OVERLAY_KEYB, ((dwDestColourKey >> 16) & 0xFF));
  1092. break;
  1093. default:
  1094. break;
  1095. }
  1096. RDOverlayControl.Mode = VO_MODE_MAINKEY;
  1097. }
  1098. // Filtering
  1099. if ( ( pThisDisplay->dwOverlayFiltering & OVERLAY_FILTERING_X ) != 0 )
  1100. {
  1101. if ( ( pThisDisplay->dwOverlayFiltering & OVERLAY_FILTERING_Y ) != 0 )
  1102. {
  1103. // Full filtering.
  1104. OverlayMode.Filter = 1;
  1105. }
  1106. else
  1107. {
  1108. // In X only - no extra bandwidth problems.
  1109. // BUT THIS DOESN'T SEEM TO WORK IN SOME CASES - WE JUST GET NO FILTERING AT ALL!
  1110. OverlayMode.Filter = 2;
  1111. }
  1112. }
  1113. else
  1114. {
  1115. // No filtering at all.
  1116. // (can't do Y filtering with no X filtering, but it never happens anyway).
  1117. OverlayMode.Filter = 0;
  1118. }
  1119. if (puod->dwFlags & DDOVER_ALPHADESTCONSTOVERRIDE)
  1120. {
  1121. P3RD_LOAD_INDEX_REG(P3RD_VIDEO_OVERLAY_BLEND, puod->overlayFX.dwAlphaDestConst);
  1122. RDOverlayControl.Mode = VO_MODE_BLEND;
  1123. }
  1124. }
  1125. // Load up the overlay mode
  1126. LOAD_GLINT_CTRL_REG(VideoOverlayMode, *(DWORD*)&OverlayMode);
  1127. // Setup the overlay control bits in the RAMDAC
  1128. P3RD_LOAD_INDEX_REG(P3RD_VIDEO_OVERLAY_CONTROL, *(BYTE*)&RDOverlayControl);
  1129. // Update the settings
  1130. UPDATE_OVERLAY(pThisDisplay, TRUE, TRUE);
  1131. puod->ddRVal = DD_OK;
  1132. return DDHAL_DRIVER_HANDLED;
  1133. } // DdUpdateOverlay
  1134. //-----------------------------------------------------------------------------
  1135. //
  1136. // DdSetOverlayPosition
  1137. //
  1138. // Sets the position for an overlay
  1139. //
  1140. // When the overlay is visible, the driver should cause the overlay to be
  1141. // displayed on the primary surface. The upper left corner of the overlay
  1142. // should be anchored at (lXPos,lYPos). For example, values of (0,0) indicates
  1143. // that the upper left corner of the overlay should appear in the upper left
  1144. // corner of the surface identified by lpDDDestSurface.
  1145. //
  1146. // When the overlay is invisible, the driver should set DDHAL_DRIVER_HANDLED in
  1147. // ddRVal and return.
  1148. //
  1149. // Parameters
  1150. //
  1151. // psopd
  1152. // Points to a DD_SETOVERLAYPOSITIONDATA structure that contains the
  1153. // information required to set the overlay position.
  1154. //
  1155. // .lpDD
  1156. // Points to a DD_DIRECTDRAW_GLOBAL structure that describes the
  1157. // driver.
  1158. // .lpDDSrcSurface
  1159. // Points to a DD_SURFACE_LOCAL structure that represents the
  1160. // DirectDraw overlay surface.
  1161. // .lpDDDestSurface
  1162. // Points to a DD_SURFACE_LOCAL structure representing the surface
  1163. // that is being overlaid.
  1164. // .lXPos
  1165. // Specifies the x coordinate of the upper left corner of the
  1166. // overlay, in pixels.
  1167. // .lYPos
  1168. // Specifies the y coordinate of the upper left corner of the
  1169. // overlay, in pixels.
  1170. // .ddRVal
  1171. // Specifies the location in which the driver writes the return
  1172. // value of the DdSetOverlayPosition callback. A return code of
  1173. // DD_OK indicates success.
  1174. // .SetOverlayPosition
  1175. // This is unused on Windows 2000.
  1176. //
  1177. //-----------------------------------------------------------------------------
  1178. DWORD CALLBACK
  1179. DdSetOverlayPosition(
  1180. LPDDHAL_SETOVERLAYPOSITIONDATA psopd)
  1181. {
  1182. P3_THUNKEDDATA* pThisDisplay;
  1183. LONG lDestWidth;
  1184. LONG lDestHeight;
  1185. DWORD dwVideoOverlayUpdate;
  1186. GET_THUNKEDDATA(pThisDisplay, psopd->lpDD);
  1187. DISPDBG ((DBGLVL,"**In DdSetOverlayPosition"));
  1188. if (pThisDisplay->P3Overlay.dwVisibleOverlays == 0)
  1189. {
  1190. psopd->ddRVal = DDERR_OVERLAYNOTVISIBLE;
  1191. return DDHAL_DRIVER_HANDLED;
  1192. }
  1193. do
  1194. {
  1195. dwVideoOverlayUpdate = READ_GLINT_CTRL_REG(VideoOverlayUpdate);
  1196. } while ((dwVideoOverlayUpdate & 0x1) != 0);
  1197. lDestWidth = pThisDisplay->P3Overlay.rcDest.right - pThisDisplay->P3Overlay.rcDest.left;
  1198. lDestHeight = pThisDisplay->P3Overlay.rcDest.bottom - pThisDisplay->P3Overlay.rcDest.top;
  1199. // Keep the new position
  1200. pThisDisplay->P3Overlay.rcDest.left = psopd->lXPos;
  1201. pThisDisplay->P3Overlay.rcDest.right = psopd->lXPos + (LONG)lDestWidth;
  1202. pThisDisplay->P3Overlay.rcDest.top = psopd->lYPos;
  1203. pThisDisplay->P3Overlay.rcDest.bottom = psopd->lYPos + (LONG)lDestHeight;
  1204. // Update the overlay position
  1205. __OV_UpdatePosition(pThisDisplay, NULL);
  1206. // Update the settings
  1207. LOAD_GLINT_CTRL_REG(VideoOverlayUpdate, VO_ENABLE);
  1208. psopd->ddRVal = DD_OK;
  1209. return DDHAL_DRIVER_HANDLED;
  1210. } // DdSetOverlayPosition