1 /**************************************************************************
3 * Copyright 2007 Tungsten Graphics, Inc., Bismarck, ND., USA
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
18 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20 * USE OR OTHER DEALINGS IN THE SOFTWARE.
22 * The above copyright notice and this permission notice (including the
23 * next paragraph) shall be included in all copies or substantial portions
27 **************************************************************************/
42 #include "pipe/p_format.h"
43 #include "pipe/p_context.h"
44 #include "util/u_inlines.h"
45 #include "util/u_format.h"
46 #include "util/u_math.h"
47 #include "util/u_memory.h"
49 #include "state_tracker/sw_winsys.h"
54 * Subclass of pipe_buffer for Xlib winsys.
55 * Low-level OS/window system memory buffer
57 struct xm_displaytarget
59 enum pipe_format format
;
70 XShmSegmentInfo shminfo
;
76 * Subclass of sw_winsys for Xlib winsys
78 struct xmesa_sw_winsys
80 struct sw_winsys base
;
81 /* struct xmesa_visual *xm_visual; */
87 static INLINE
struct xm_displaytarget
*
88 xm_displaytarget( struct sw_displaytarget
*dt
)
90 return (struct xm_displaytarget
*)dt
;
95 * X Shared Memory Image extension code
100 static volatile int mesaXErrorFlag
= 0;
103 * Catches potential Xlib errors.
106 mesaHandleXError(Display
*dpy
, XErrorEvent
*event
)
115 static char *alloc_shm(struct xm_displaytarget
*buf
, unsigned size
)
117 XShmSegmentInfo
*const shminfo
= & buf
->shminfo
;
119 shminfo
->shmid
= shmget(IPC_PRIVATE
, size
, IPC_CREAT
|0777);
120 if (shminfo
->shmid
< 0) {
124 shminfo
->shmaddr
= (char *) shmat(shminfo
->shmid
, 0, 0);
125 if (shminfo
->shmaddr
== (char *) -1) {
126 shmctl(shminfo
->shmid
, IPC_RMID
, 0);
130 shminfo
->readOnly
= False
;
131 return shminfo
->shmaddr
;
136 * Allocate a shared memory XImage back buffer for the given XMesaBuffer.
139 alloc_shm_ximage(struct xm_displaytarget
*xm_buffer
,
140 struct xmesa_buffer
*xmb
,
141 unsigned width
, unsigned height
)
144 * We have to do a _lot_ of error checking here to be sure we can
145 * really use the XSHM extension. It seems different servers trigger
146 * errors at different points if the extension won't work. Therefore
147 * we have to be very careful...
149 int (*old_handler
)(Display
*, XErrorEvent
*);
151 xm_buffer
->tempImage
= XShmCreateImage(xmb
->xm_visual
->display
,
152 xmb
->xm_visual
->visinfo
->visual
,
153 xmb
->xm_visual
->visinfo
->depth
,
158 if (xm_buffer
->tempImage
== NULL
) {
165 old_handler
= XSetErrorHandler(mesaHandleXError
);
166 /* This may trigger the X protocol error we're ready to catch: */
167 XShmAttach(xmb
->xm_visual
->display
, &xm_buffer
->shminfo
);
168 XSync(xmb
->xm_visual
->display
, False
);
170 if (mesaXErrorFlag
) {
171 /* we are on a remote display, this error is normal, don't print it */
172 XFlush(xmb
->xm_visual
->display
);
174 XDestroyImage(xm_buffer
->tempImage
);
175 xm_buffer
->tempImage
= NULL
;
177 (void) XSetErrorHandler(old_handler
);
184 #endif /* USE_XSHM */
187 xm_is_displaytarget_format_supported( struct sw_winsys
*ws
,
188 enum pipe_format format
)
190 /* TODO: check visuals or other sensible thing here */
196 xm_displaytarget_map(struct sw_winsys
*ws
,
197 struct sw_displaytarget
*dt
,
200 struct xm_displaytarget
*xm_dt
= xm_displaytarget(dt
);
201 xm_dt
->mapped
= xm_dt
->data
;
202 return xm_dt
->mapped
;
206 xm_displaytarget_unmap(struct sw_winsys
*ws
,
207 struct sw_displaytarget
*dt
)
209 struct xm_displaytarget
*xm_dt
= xm_displaytarget(dt
);
210 xm_dt
->mapped
= NULL
;
214 xm_displaytarget_destroy(struct sw_winsys
*ws
,
215 struct sw_displaytarget
*dt
)
217 struct xm_displaytarget
*xm_dt
= xm_displaytarget(dt
);
221 if (xm_dt
->shminfo
.shmid
>= 0) {
222 shmdt(xm_dt
->shminfo
.shmaddr
);
223 shmctl(xm_dt
->shminfo
.shmid
, IPC_RMID
, 0);
225 xm_dt
->shminfo
.shmid
= -1;
226 xm_dt
->shminfo
.shmaddr
= (char *) -1;
238 * Display/copy the image in the surface into the X window specified
239 * by the XMesaBuffer.
242 xlib_sw_display(struct xmesa_buffer
*xm_buffer
,
243 struct sw_displaytarget
*dt
)
246 struct xm_displaytarget
*xm_dt
= xm_displaytarget(dt
);
247 static boolean no_swap
= 0;
248 static boolean firsttime
= 1;
251 no_swap
= getenv("SP_NO_RAST") != NULL
;
261 if (xm_dt
->tempImage
== NULL
)
263 assert(util_format_get_blockwidth(xm_dt
->format
) == 1);
264 assert(util_format_get_blockheight(xm_dt
->format
) == 1);
265 alloc_shm_ximage(xm_dt
, xm_buffer
,
266 xm_dt
->stride
/ util_format_get_blocksize(xm_dt
->format
),
270 ximage
= xm_dt
->tempImage
;
271 ximage
->data
= xm_dt
->data
;
273 /* _debug_printf("XSHM\n"); */
274 XShmPutImage(xm_buffer
->xm_visual
->display
, xm_buffer
->drawable
, xm_buffer
->gc
,
275 ximage
, 0, 0, 0, 0, xm_dt
->width
, xm_dt
->height
, False
);
280 /* display image in Window */
281 ximage
= xm_dt
->tempImage
;
282 ximage
->data
= xm_dt
->data
;
284 /* check that the XImage has been previously initialized */
285 assert(ximage
->format
);
286 assert(ximage
->bitmap_unit
);
288 /* update XImage's fields */
289 ximage
->width
= xm_dt
->width
;
290 ximage
->height
= xm_dt
->height
;
291 ximage
->bytes_per_line
= xm_dt
->stride
;
293 /* _debug_printf("XPUT\n"); */
294 XPutImage(xm_buffer
->xm_visual
->display
, xm_buffer
->drawable
, xm_buffer
->gc
,
295 ximage
, 0, 0, 0, 0, xm_dt
->width
, xm_dt
->height
);
300 * Display/copy the image in the surface into the X window specified
301 * by the XMesaBuffer.
304 xm_displaytarget_display(struct sw_winsys
*ws
,
305 struct sw_displaytarget
*dt
,
306 void *context_private
)
308 XMesaContext xmctx
= (XMesaContext
) context_private
;
309 struct xmesa_buffer
*xm_buffer
= xmctx
->xm_buffer
;
310 xm_sw_display(xm_buffer
, dt
);
314 static struct sw_displaytarget
*
315 xm_displaytarget_create(struct sw_winsys
*winsys
,
316 enum pipe_format format
,
317 unsigned width
, unsigned height
,
321 struct xm_displaytarget
*xm_dt
= CALLOC_STRUCT(xm_displaytarget
);
322 unsigned nblocksy
, size
;
324 xm_dt
= CALLOC_STRUCT(xm_displaytarget
);
328 xm_dt
->format
= format
;
329 xm_dt
->width
= width
;
330 xm_dt
->height
= height
;
332 nblocksy
= util_format_get_nblocksy(format
, height
);
333 xm_dt
->stride
= align(util_format_get_stride(format
, width
), alignment
);
334 size
= xm_dt
->stride
* nblocksy
;
337 if (!debug_get_bool_option("XLIB_NO_SHM", FALSE
))
339 xm_dt
->shminfo
.shmid
= -1;
340 xm_dt
->shminfo
.shmaddr
= (char *) -1;
343 xm_dt
->data
= alloc_shm(xm_dt
, size
);
350 xm_dt
->data
= align_malloc(size
, alignment
);
355 *stride
= xm_dt
->stride
;
356 return (struct sw_displaytarget
*)xm_dt
;
366 xm_destroy( struct sw_winsys
*ws
)
373 xlib_create_sw_winsys( void )
375 struct xmesa_sw_winsys
*ws
;
377 ws
= CALLOC_STRUCT(xmesa_sw_winsys
);
381 ws
->base
.destroy
= xm_destroy
;
383 ws
->base
.is_displaytarget_format_supported
= xm_is_displaytarget_format_supported
;
385 ws
->base
.displaytarget_create
= xm_displaytarget_create
;
386 ws
->base
.displaytarget_map
= xm_displaytarget_map
;
387 ws
->base
.displaytarget_unmap
= xm_displaytarget_unmap
;
388 ws
->base
.displaytarget_destroy
= xm_displaytarget_destroy
;
390 ws
->base
.displaytarget_display
= xm_displaytarget_display
;