image.inc 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. {$WARNING this should be in the IPC unit!!!}
  2. Const
  3. { IPC_CREAT = $200;
  4. IPC_EXCL = $400;
  5. IPC_NOWAIT = $800;}
  6. IPC_PRIVATE = 0;
  7. Constructor TX11Image.Create(display : PDisplay; screen, width, height : Integer; format : TPTCFormat);
  8. Begin
  9. m_width := width;
  10. m_height := height;
  11. m_disp := display;
  12. m_image := Nil;
  13. End;
  14. Destructor TX11Image.Destroy;
  15. Begin
  16. Inherited Destroy;
  17. End;
  18. Constructor TX11NormalImage.Create(display : PDisplay; screen, width, height : Integer; format : TPTCFormat);
  19. Var
  20. xpad, xpitch : Integer;
  21. tmp_m_pixels : PChar;
  22. Begin
  23. { cerr << "Creating normal image" << endl << flush; }
  24. m_image := Nil;
  25. m_pixels := Nil;
  26. Inherited Create(display, screen, width, height, format);
  27. xpad := format.bits;
  28. If format.bits = 24 Then
  29. xpad := 32;
  30. xpitch := width * format.bits Div 8;
  31. Inc(xpitch, 3);
  32. xpitch := xpitch And (Not 3);
  33. m_pixels := GetMem(xpitch * height);
  34. Pointer(tmp_m_pixels) := Pointer(m_pixels);
  35. m_image := XCreateImage(display, DefaultVisual(display, screen),
  36. DefaultDepth(display, screen),
  37. ZPixmap, 0, tmp_m_pixels,
  38. width, height, xpad, 0);
  39. If m_image = Nil Then
  40. Raise TPTCError.Create('cannot create XImage');
  41. End;
  42. Destructor TX11NormalImage.Destroy;
  43. Begin
  44. If m_image <> Nil Then
  45. Begin
  46. { Restore XImage's buffer pointer }
  47. m_image^.data := Nil;
  48. XDestroyImage(m_image);
  49. End;
  50. If m_pixels <> Nil Then
  51. FreeMem(m_pixels);
  52. Inherited Destroy;
  53. End;
  54. Procedure TX11NormalImage.put(w : TWindow; gc : TGC; x, y : Integer);
  55. Begin
  56. XPutImage(m_disp, w, gc, m_image, 0, 0, x, y, m_width, m_height);
  57. XSync(m_disp, False);
  58. End;
  59. Procedure TX11NormalImage.put(w : TWindow; gc : TGC; sx, sy, dx, dy,
  60. width, height : Integer);
  61. Begin
  62. XPutImage(m_disp, w, gc, m_image, sx, sy, dx, dy, width, height);
  63. XSync(m_disp, False);
  64. End;
  65. Function TX11NormalImage.lock : Pointer;
  66. Begin
  67. lock := m_pixels;
  68. End;
  69. Function TX11NormalImage.pitch : Integer;
  70. Begin
  71. pitch := m_image^.bytes_per_line;
  72. End;
  73. {$IFDEF HAVE_X11_EXTENSIONS_XSHM}
  74. Var
  75. Fshm_error : Boolean;
  76. Fshm_oldhandler : Function(disp : PDisplay; xev : PXErrorEvent) : Integer; CDecl;
  77. Function Fshm_errorhandler(disp : PDisplay; xev : PXErrorEvent) : Integer; CDecl;
  78. Begin
  79. If xev^.error_code=BadAccess Then
  80. Begin
  81. Fshm_error := True;
  82. Result := 0;
  83. End
  84. Else
  85. Result := Fshm_oldhandler(disp, xev);
  86. End;
  87. Constructor TX11SHMImage.Create(display : PDisplay; screen, width, height : Integer; format : TPTCFormat);
  88. Begin
  89. { cerr << "Creating SHM image" << endl << flush; }
  90. shminfo.shmid := -1;
  91. shminfo.shmaddr := Pointer(-1);
  92. FShmAttached := False;
  93. m_image := Nil;
  94. Inherited Create(display, screen, width, height, format);
  95. m_image := XShmCreateImage(display, DefaultVisual(display, screen),
  96. DefaultDepth(display, screen),
  97. ZPixmap, Nil, @shminfo, width, height);
  98. If m_image = Nil Then
  99. Raise TPTCError.Create('cannot create SHM image');
  100. shminfo.shmid := shmget(IPC_PRIVATE, m_image^.bytes_per_line * m_image^.height,
  101. IPC_CREAT Or &777);
  102. If shminfo.shmid = -1 Then
  103. Raise TPTCError.Create('cannot get shared memory segment');
  104. shminfo.shmaddr := shmat(shminfo.shmid, Nil, 0);
  105. shminfo.readOnly := False;
  106. m_image^.data := shminfo.shmaddr;
  107. If Pointer(shminfo.shmaddr) = Pointer(-1) Then
  108. Raise TPTCError.Create('cannot allocate shared memory');
  109. // Try and attach the segment to the server. Bugfix: Have to catch
  110. // bad access errors in case it runs over the net.
  111. Fshm_error := False;
  112. Fshm_oldhandler := XSetErrorHandler(@Fshm_errorhandler);
  113. Try
  114. If XShmAttach(display, @shminfo) = 0 Then
  115. Raise TPTCError.Create('cannot attach shared memory segment to display');
  116. XSync(display, False);
  117. If Fshm_error Then
  118. Raise TPTCError.Create('cannot attach shared memory segment to display');
  119. FShmAttached := True;
  120. Finally
  121. XSetErrorHandler(Fshm_oldhandler);
  122. End;
  123. End;
  124. Destructor TX11SHMImage.Destroy;
  125. Begin
  126. If FShmAttached Then
  127. Begin
  128. XShmDetach(m_disp, @shminfo);
  129. XSync(m_disp, False);
  130. End;
  131. If m_image <> Nil Then
  132. XDestroyImage(m_image);
  133. If Pointer(shminfo.shmaddr) <> Pointer(-1) Then
  134. shmdt(shminfo.shmaddr);
  135. If shminfo.shmid <> -1 Then
  136. shmctl(shminfo.shmid, IPC_RMID, Nil);
  137. Inherited Destroy;
  138. End;
  139. Procedure TX11SHMImage.put(w : TWindow; gc : TGC; x, y : Integer);
  140. Begin
  141. XShmPutImage(m_disp, w, gc, m_image, 0, 0, x, y, m_width, m_height, False);
  142. XSync(m_disp, False);
  143. End;
  144. Procedure TX11SHMImage.put(w : TWindow; gc : TGC; sx, sy, dx, dy,
  145. width, height : Integer);
  146. Begin
  147. XShmPutImage(m_disp, w, gc, m_image, sx, sy, dx, dy, width, height, False);
  148. XSync(m_disp, False);
  149. End;
  150. Function TX11SHMImage.lock : Pointer;
  151. Begin
  152. lock := Pointer(shminfo.shmaddr);
  153. End;
  154. Function TX11SHMImage.pitch : Integer;
  155. Begin
  156. pitch := m_image^.bytes_per_line;
  157. End;
  158. {$ENDIF}