dgadisp.inc 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426
  1. Constructor TX11DGADisplay.Create;
  2. Begin
  3. m_indirect := False;
  4. m_inmode := False;
  5. modeinfo := Nil;
  6. Inherited Create;
  7. // dga_LoadLibrary;
  8. { If (XF86DGAQueryExtension = Nil) Or (XF86DGAGetVideo = Nil) Or
  9. (XF86DGAGetViewPortSize = Nil) Or (XF86DGAForkApp = Nil) Or
  10. (XF86DGADirectVideo = Nil) Or (XF86DGASetViewPort = Nil) Or
  11. (XF86DGAInstallColormap = Nil) Then
  12. Raise TPTCError.Create('DGA extension not available');}
  13. End;
  14. Destructor TX11DGADisplay.Destroy;
  15. Begin
  16. close; {fix close!}
  17. // dga_UnloadLibrary;
  18. Inherited Destroy;
  19. End;
  20. Procedure TX11DGADisplay.open(title : String; _width, _height : Integer; Const _format : TPTCFormat; disp : PDisplay; screen : Integer);
  21. Var
  22. dummy1, dummy2 : Integer;
  23. vml : PXF86VidModeModeLine;
  24. dotclock : Integer;
  25. i : Integer;
  26. found : Boolean;
  27. root : TWindow;
  28. e : TXEvent;
  29. tmpArea : TPTCArea;
  30. r, g, b : Single;
  31. found_mode : Integer;
  32. min_diff : Integer;
  33. d_x, d_y : Integer;
  34. Begin
  35. m_disp := disp;
  36. m_screen := screen;
  37. m_width := _width;
  38. m_height := _height;
  39. { Check if we are root }
  40. If fpgeteuid <> 0 Then
  41. Raise TPTCError.Create('Have to be root to switch to DGA mode');
  42. { Check if the DGA extension and VidMode extension can be used }
  43. If Not XF86DGAQueryExtension(disp, @dummy1, @dummy2) Then
  44. Raise TPTCError.Create('DGA extension not available');
  45. If Not XF86VidModeQueryExtension(disp, @dummy1, @dummy2) Then
  46. Raise TPTCError.Create('VidMode extension not available');
  47. { Get all availabe video modes }
  48. XF86VidModeGetAllModeLines(m_disp, m_screen, @num_modeinfo, @modeinfo);
  49. previousmode := -1;
  50. { Save previous mode }
  51. New(vml);
  52. Try
  53. XF86VidModeGetModeLine(m_disp, m_screen, @dotclock, vml);
  54. Try
  55. For i := 0 To num_modeinfo - 1 Do
  56. Begin
  57. If (vml^.hdisplay = modeinfo[i]^.hdisplay) And
  58. (vml^.vdisplay = modeinfo[i]^.vdisplay) Then
  59. Begin
  60. previousmode := i;
  61. Break;
  62. End;
  63. End;
  64. Finally
  65. If vml^.privsize <> 0 Then
  66. XFree(vml^.c_private);
  67. End;
  68. Finally
  69. Dispose(vml);
  70. End;
  71. If previousmode = -1 Then
  72. Raise TPTCError.Create('Current mode not found in modelist?! Err, this shouldn''t happen :)');
  73. { Find a video mode to set }
  74. { Normal modesetting first, find exactly matching mode }
  75. If (m_flags And PTC_X11_PEDANTIC_DGA) = 0 Then
  76. Begin
  77. found := False;
  78. For i := 0 To num_modeinfo - 1 Do
  79. Begin
  80. If (modeinfo[i]^.hdisplay = _width) And (modeinfo[i]^.vdisplay = _height) Then
  81. Begin
  82. If Not XF86VidModeSwitchToMode(m_disp, m_screen, modeinfo[i]) Then
  83. Raise TPTCError.Create('Error switching to requested video mode');
  84. m_destx := 0;
  85. m_desty := 0;
  86. found := True;
  87. Break;
  88. End;
  89. End;
  90. If Not found Then
  91. Raise TPTCError.Create('Cannot find matching DGA video mode');
  92. End
  93. Else
  94. Begin
  95. found_mode := $FFFF;
  96. { Try to find a mode that matches the width first }
  97. For i := 0 To num_modeinfo - 1 Do
  98. Begin
  99. If (modeinfo[i]^.hdisplay = _width) And
  100. (modeinfo[i]^.vdisplay >= _height) Then
  101. Begin
  102. found_mode := i;
  103. Break;
  104. End;
  105. End;
  106. { Next try to match the height }
  107. If found_mode = $FFFF Then
  108. For i := 0 To num_modeinfo - 1 Do
  109. Begin
  110. If (modeinfo[i]^.hdisplay >= _width) And
  111. (modeinfo[i]^.vdisplay = _height) Then
  112. Begin
  113. found_mode := i;
  114. Break;
  115. End;
  116. End;
  117. { Finally, find the mode that is bigger than the requested one and makes }
  118. { the least difference }
  119. min_diff := 987654321;
  120. For i := 0 To num_modeinfo - 1 Do
  121. Begin
  122. If (modeinfo[i]^.hdisplay >= _width) And (modeinfo[i]^.vdisplay >= _height) Then
  123. Begin
  124. d_x := sqr(modeinfo[i]^.hdisplay - _width);
  125. d_y := sqr(modeinfo[i]^.vdisplay - _height);
  126. If (d_x + d_y) < min_diff Then
  127. Begin
  128. min_diff := d_x + d_y;
  129. found_mode := i;
  130. End;
  131. End;
  132. End;
  133. If found_mode <> $FFFF Then
  134. Begin
  135. If Not XF86VidModeSwitchToMode(m_disp, m_screen, modeinfo[found_mode]) Then
  136. Raise TPTCError.Create('Error switching to requested video mode');
  137. m_destx := (modeinfo[found_mode]^.hdisplay Div 2) - (_width Div 2);
  138. m_desty := (modeinfo[found_mode]^.vdisplay Div 2) - (_height Div 2);
  139. End
  140. Else
  141. Raise TPTCError.Create('Cannot find a video mode to use');
  142. End;
  143. XFlush(m_disp);
  144. m_inmode := True;
  145. { Check if the requested colour mode is available }
  146. m_format := getFormat(_format);
  147. { Grab exclusive control over the keyboard and mouse }
  148. root := XRootWindow(m_disp, m_screen);
  149. XGrabKeyboard(m_disp, root, True, GrabModeAsync, GrabModeAsync, CurrentTime);
  150. XGrabPointer(m_disp, root, True, PointerMotionMask Or ButtonPressMask Or
  151. ButtonReleaseMask, GrabModeAsync, GrabModeAsync, None, None,
  152. CurrentTime);
  153. XFlush(m_disp);
  154. { Get Display information }
  155. XF86DGAGetVideo(m_disp, m_screen, @dga_addr, @dga_linewidth,
  156. @dga_banksize, @dga_memsize);
  157. { Don't have to be root anymore }
  158. { setuid(getuid);...}
  159. XF86DGAGetViewPortSize(m_disp, m_screen, @dga_width, @dga_height);
  160. If XF86DGAForkApp(m_screen) <> 0 Then
  161. Raise TPTCError.Create('cannot do safety fork')
  162. Else
  163. Begin
  164. If XF86DGADirectVideo(m_disp, m_screen, XF86DGADirectGraphics Or
  165. XF86DGADirectKeyb Or XF86DGADirectMouse) = 0 Then
  166. Raise TPTCError.Create('cannot switch to DGA mode');
  167. End;
  168. m_indirect := True;
  169. FillChar(dga_addr^, dga_linewidth * dga_height * (m_format.bits Div 8), 0);
  170. XSelectInput(m_disp, DefaultRootWindow(m_disp),
  171. KeyPressMask Or KeyReleaseMask);
  172. XF86DGASetViewPort(m_disp, m_screen, 0, 0); { Important.. sort of =) }
  173. found := False;
  174. Repeat
  175. { Stupid loop. The key }
  176. { events were causing }
  177. { problems.. }
  178. found := XCheckMaskEvent(m_disp, KeyPressMask Or KeyReleaseMask, @e);
  179. Until Not found;
  180. { Create colour map in 8 bit mode }
  181. If m_format.bits = 8 Then
  182. Begin
  183. m_colours := GetMem(256 * SizeOf(TXColor));
  184. If m_colours = Nil Then
  185. Raise TPTCError.Create('Cannot allocate colour map cells');
  186. m_cmap := XCreateColormap(m_disp, RootWindow(m_disp, m_screen),
  187. DefaultVisual(m_disp, m_screen), AllocAll);
  188. If m_cmap = 0 Then
  189. Raise TPTCError.Create('Cannot create colour map');
  190. End
  191. Else
  192. m_cmap := 0;
  193. { Set 332 palette, for now }
  194. If (m_format.bits = 8) And m_format.direct Then
  195. Begin
  196. {Taken from PTC 0.72, i hope it's fine}
  197. For i := 0 To 255 Do
  198. Begin
  199. r := ((i And $E0) Shr 5) * 255 / 7;
  200. g := ((i And $1C) Shr 2) * 255 / 7;
  201. b := (i And $03) * 255 / 3;
  202. m_colours[i].pixel := i;
  203. m_colours[i].red := Round(r) Shl 8;
  204. m_colours[i].green := Round(g) Shl 8;
  205. m_colours[i].blue := Round(b) Shl 8;
  206. Byte(m_colours[i].flags) := DoRed Or DoGreen Or DoBlue;
  207. End;
  208. XStoreColors(m_disp, m_cmap, m_colours, 256);
  209. XF86DGAInstallColormap(m_disp, m_screen, m_cmap);
  210. End;
  211. { Set clipping area }
  212. tmpArea := TPTCArea.Create(0, 0, m_width, m_height);
  213. Try
  214. m_clip.ASSign(tmpArea);
  215. Finally
  216. tmpArea.Free;
  217. End;
  218. End;
  219. { Not in DGA mode }
  220. Procedure TX11DGADisplay.open(disp : PDisplay; screen : Integer; w : TWindow; Const _format : TPTCFormat);
  221. Begin
  222. If disp = Nil Then; { Prevent warnings }
  223. If screen = 0 Then;
  224. If w = 0 Then;
  225. If _format = Nil Then;
  226. End;
  227. Procedure TX11DGADisplay.open(disp : PDisplay; screen : Integer; _window : TWindow; Const _format : TPTCFormat; x, y, w, h : Integer);
  228. Begin
  229. If (disp = Nil) Or (screen = 0) Or (_window = 0) Or (_format = Nil) Or (x = 0) Or
  230. (y = 0) Or (w = 0) Or (h = 0) Then;
  231. End;
  232. Procedure TX11DGADisplay.close;
  233. Begin
  234. If m_indirect Then
  235. Begin
  236. m_indirect := False;
  237. XF86DGADirectVideo(m_disp, m_screen, 0);
  238. End;
  239. // Writeln('lala1');
  240. If m_inmode Then
  241. Begin
  242. m_inmode := False;
  243. XF86VidModeSwitchToMode(m_disp, m_screen, modeinfo[previousmode]);
  244. XUngrabKeyboard(m_disp, CurrentTime);
  245. XUngrabPointer(m_disp, CurrentTime);
  246. End;
  247. // Writeln('lala2');
  248. If m_disp <> Nil Then
  249. XFlush(m_disp);
  250. // Writeln('lala3');
  251. If m_cmap <> 0 Then
  252. Begin
  253. XFreeColormap(m_disp, m_cmap);
  254. m_cmap := 0;
  255. End;
  256. // Writeln('lala4');
  257. FreeMemAndNil(m_colours);
  258. // Writeln('lala5');
  259. If modeinfo <> Nil Then
  260. Begin
  261. XFree(modeinfo);
  262. modeinfo := Nil;
  263. End;
  264. // Writeln('lala6');
  265. End;
  266. Procedure TX11DGADisplay.update;
  267. Begin
  268. End;
  269. Procedure TX11DGADisplay.update(Const _area : TPTCArea);
  270. Begin
  271. End;
  272. Procedure TX11DGADisplay.internal_ReadKey(k : TPTCKey);
  273. Var
  274. e : TXEvent;
  275. sym : TKeySym;
  276. press : Boolean;
  277. alt, shift, ctrl : Boolean;
  278. uni : Integer;
  279. tmpkey : TPTCKey;
  280. Begin
  281. XMaskEvent(m_disp, KeyPressMask Or KeyReleaseMask, @e); { Blocks and waits }
  282. If (e._type <> KeyPress) And (e._type <> KeyRelease) Then
  283. Raise TPTCError.Create('XMaskEvent returned event <> KeyPress/KeyRelease');
  284. { XLookupString(@e.xkey, Nil, 0, @sym, Nil);}
  285. sym := XLookupKeySym(@e.xkey, 0);
  286. uni := X11ConvertKeySymToUnicode(sym);
  287. alt := (e.xkey.state And Mod1Mask) <> 0;
  288. shift := (e.xkey.state And ShiftMask) <> 0;
  289. ctrl := (e.xkey.state And ControlMask) <> 0;
  290. If e._type = KeyPress Then
  291. press := True
  292. Else
  293. press := False;
  294. tmpkey := Nil;
  295. Try
  296. Case sym Shr 8 Of
  297. 0 : tmpkey := TPTCKey.Create(m_normalkeys[sym And $FF], uni, alt, shift, ctrl, press);
  298. $FF : tmpkey := TPTCKey.Create(m_functionkeys[sym And $FF], uni, alt, shift, ctrl, press);
  299. Else
  300. tmpkey := TPTCKey.Create;
  301. End;
  302. k.ASSign(tmpkey);
  303. Finally
  304. tmpkey.Free;
  305. End;
  306. End;
  307. Function TX11DGADisplay.internal_PeekKey(k : TPTCKey) : Boolean;
  308. Var
  309. e : TXEvent;
  310. Begin
  311. If XCheckMaskEvent(m_disp, KeyPressMask Or KeyReleaseMask, @e) Then
  312. Begin
  313. XPutBackEvent(m_disp, @e); { Simulate "normal" kbhit behaviour }
  314. XPutBackEvent(m_disp, @e); { i.e. leave the buffer intact }
  315. internal_ReadKey(k);
  316. Result := True;
  317. End
  318. Else
  319. Result := False;
  320. End;
  321. Function TX11DGADisplay.lock : Pointer;
  322. Begin
  323. lock := dga_addr + dga_linewidth * m_desty * (m_format.bits Div 8) +
  324. m_destx * (m_format.bits Div 8);
  325. End;
  326. Procedure TX11DGADisplay.unlock;
  327. Begin
  328. End;
  329. Procedure TX11DGADisplay.palette(Const _palette : TPTCPalette);
  330. Var
  331. pal : Pint32;
  332. i : Integer;
  333. Begin
  334. pal := _palette.data;
  335. If Not m_format.indexed Then
  336. Exit;
  337. For i := 0 To 255 Do
  338. Begin
  339. m_colours[i].pixel := i;
  340. m_colours[i].red := ((pal[i] Shr 16) And $FF) Shl 8;
  341. m_colours[i].green := ((pal[i] Shr 8) And $FF) Shl 8;
  342. m_colours[i].blue := (pal[i] And $FF) Shl 8;
  343. Byte(m_colours[i].flags) := DoRed Or DoGreen Or DoBlue;
  344. End;
  345. XStoreColors(m_disp, m_cmap, m_colours, 256);
  346. XF86DGAInstallColormap(m_disp, m_screen, m_cmap);
  347. End;
  348. Function TX11DGADisplay.pitch : Integer;
  349. Begin
  350. pitch := dga_linewidth * (m_format.bits Div 8);
  351. End;
  352. Function TX11DGADisplay.getX11Window : TWindow;
  353. Begin
  354. getX11Window := DefaultRootWindow(m_disp);
  355. End;