doublebuffer.pas 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. {
  2. This file is part of the Free Pascal run time library.
  3. A file in Amiga system run time library.
  4. Copyright (c) 1998-2002 by Nils Sjoholm
  5. member of the Amiga RTL development team.
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. unit doublebuffer;
  13. {
  14. DoubleBuffer.p
  15. These routines provide a very simple double buffer
  16. mechanism, mainly by being a bit inflexible with the
  17. choice of screens and windows.
  18. The first thing to do is to set up a NewScreen structure,
  19. just like you would do for OpenScreen. This can be any
  20. sort of screen. Then call OpenDoubleBuffer, which will
  21. return a pointer to a full-screen, borderless backdrop
  22. window, or Nil if something went wrong.
  23. If you write into the window's RastPort, it won't be
  24. visible until you call SwapBuffers. By the way, you
  25. can always write into the same RastPort - you don't
  26. need to reinitialize after SwapBuffers. All the
  27. buffer swapping takes place at the level of BitMaps,
  28. so it's transparent to RastPorts.
  29. When you have finished, call CloseDoubleBuffer. If you
  30. close the window and screen seperately it might crash
  31. (I'm not sure), but you'll definitely lose memory.
  32. One last point: GfxBase must be open before you call
  33. OpenDoubleBuffer
  34. }
  35. {
  36. History:
  37. This is just an translation of DoubleBuffer.p from PCQ pascal
  38. to FPC Pascal.
  39. 28 Aug 2000.
  40. [email protected]
  41. }
  42. interface
  43. uses exec, intuition, graphics;
  44. {
  45. OpenDoubleBuffer opens the Screen described in "ns" without
  46. modification, then opens a full screen, borderless backdrop
  47. window on it. That way the window and screen normally share
  48. the same BitMap.
  49. Assuming all that went OK, it allocates an extra BitMap record
  50. and the Rasters to go along with it. Then it points the
  51. Window's BitMap, in its RastPort, at the extra bitmap.
  52. }
  53. Function OpenDoubleBuffer(ns : pNewScreen) : pWindow;
  54. {
  55. SwapBuffers swaps the PlanePtrs in the Window's and Screen's
  56. BitMap structure's, then calls ScrollVPort on the Screen's
  57. ViewPort to get everything going.
  58. }
  59. Procedure SwapBuffers(w : pWindow);
  60. {
  61. CloseDoubleBuffer resets the Window's BitMap to the Screen's
  62. BitMap (just in case), closes the Window and Screen, then
  63. deallocates the extra BitMap structure and Rasters.
  64. }
  65. Procedure CloseDoubleBuffer(w : pWindow);
  66. implementation
  67. Function OpenDoubleBuffer(ns : pNewScreen) : pWindow;
  68. var
  69. s : pScreen;
  70. w : pWindow;
  71. bm : pBitMap;
  72. i,j : Integer;
  73. nw : tNewWindow;
  74. rp : pRastPort;
  75. begin
  76. s := OpenScreen(ns);
  77. if s = Nil then
  78. OpenDoubleBuffer := Nil;
  79. ShowTitle(s, 0);
  80. with s^ do begin
  81. nw.LeftEdge := LeftEdge;
  82. nw.TopEdge := TopEdge;
  83. nw.Width := Width;
  84. nw.Height := Height;
  85. end;
  86. with nw do begin
  87. DetailPen := 0;
  88. BlockPen := 0;
  89. IDCMPFlags := 0;
  90. Flags := WFLG_BACKDROP + WFLG_BORDERLESS + WFLG_ACTIVATE;
  91. FirstGadget := Nil;
  92. CheckMark := Nil;
  93. Title := nil;
  94. Screen := s;
  95. BitMap := Nil;
  96. WType := CUSTOMSCREEN_f;
  97. end;
  98. w := OpenWindow(Addr(nw));
  99. if w = Nil then begin
  100. CloseScreen(s);
  101. OpenDoubleBuffer := Nil;
  102. end;
  103. bm := AllocMem(SizeOf(tBitMap), MEMF_PUBLIC);
  104. if bm = Nil then begin
  105. CloseWindow(w);
  106. CloseScreen(s);
  107. OpenDoubleBuffer := Nil;
  108. end;
  109. bm^ := s^.BitMap;
  110. with bm^ do
  111. for i := 0 to Pred(Depth) do begin
  112. Planes[i] := AllocRaster(s^.Width, s^.Height);
  113. if Planes[i] = Nil then begin
  114. if i > 0 then
  115. for j := 0 to Pred(i) do
  116. FreeRaster(Planes[j], s^.Width, s^.Height);
  117. CloseWindow(w);
  118. CloseScreen(s);
  119. OpenDoubleBuffer := Nil;
  120. end;
  121. end;
  122. rp := w^.RPort;
  123. rp^.bitMap := bm;
  124. OpenDoubleBuffer := w;
  125. end;
  126. {
  127. SwapBuffers swaps the PlanePtrs in the Window's and Screen's
  128. BitMap structure's, then calls ScrollVPort on the Screen's
  129. ViewPort to get everything going.
  130. }
  131. Procedure SwapBuffers(w : pWindow);
  132. var
  133. s : pScreen;
  134. bm1,
  135. bm2 : pBitMap;
  136. rp : pRastPort;
  137. Temp : Array [0..7] of PLANEPTR;
  138. begin
  139. s := w^.WScreen;
  140. rp := w^.RPort;
  141. bm1 := rp^.bitMap;
  142. bm2 := addr(s^.BitMap);
  143. {Temp := bm2^.Planes;
  144. This is really stupid I can't assign
  145. bm2^.Planes to Temp, Sigh
  146. }
  147. Temp[0] := bm2^.Planes[0];
  148. Temp[1] := bm2^.Planes[1];
  149. Temp[2] := bm2^.Planes[2];
  150. Temp[3] := bm2^.Planes[3];
  151. Temp[4] := bm2^.Planes[4];
  152. Temp[5] := bm2^.Planes[5];
  153. Temp[6] := bm2^.Planes[6];
  154. Temp[7] := bm2^.Planes[7];
  155. bm2^.Planes := bm1^.Planes;
  156. { bm1^.Planes := Temp;
  157. And this one to, stupid
  158. }
  159. bm1^.Planes[0] := Temp[0];
  160. bm1^.Planes[1] := Temp[1];
  161. bm1^.Planes[2] := Temp[2];
  162. bm1^.Planes[3] := Temp[3];
  163. bm1^.Planes[4] := Temp[4];
  164. bm1^.Planes[5] := Temp[5];
  165. bm1^.Planes[6] := Temp[6];
  166. bm1^.Planes[7] := Temp[7];
  167. ScrollVPort(addr(s^.ViewPort));
  168. end;
  169. {
  170. CloseDoubleBuffer resets the Window's BitMap to the Screen's
  171. BitMap (just in case), closes the Window and Screen, then
  172. deallocates the extra BitMap structure and Rasters.
  173. }
  174. Procedure CloseDoubleBuffer(w : pWindow);
  175. var
  176. s : pScreen;
  177. bm : pBitMap;
  178. i : longint;
  179. rp : pRastPort;
  180. begin
  181. s := w^.WScreen;
  182. rp := w^.RPort;
  183. bm := rp^.bitMap;
  184. rp^.bitMap := addr(s^.BitMap);
  185. with bm^ do
  186. for i := 0 to Pred(Depth) do
  187. FreeRaster(Planes[i], s^.Width, s^.Height);
  188. FreeMem(bm, SizeOf(tBitMap));
  189. CloseWindow(w);
  190. CloseScreen(s);
  191. end;
  192. end.
  193. {
  194. $Log$
  195. Revision 1.1 2002-11-22 21:34:59 nils
  196. * initial release
  197. }