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 **************************************************************************/
36 #include "glxheader.h"
38 #include "main/macros.h"
40 #include "pipe/p_winsys.h"
41 #include "pipe/p_format.h"
42 #include "pipe/p_context.h"
43 #include "pipe/softpipe/sp_winsys.h"
47 * Low-level OS/window system memory buffer
51 boolean userBuffer
; /** Is this a user-space buffer? */
61 struct pipe_surface surface
;
62 /* no extra fields for now */
67 * Derived from softpipe_winsys.
68 * We just need one extra field which indicates the pixel format to use for
69 * drawing surfaces so that we're compatible with the XVisual/window format.
71 struct xmesa_softpipe_winsys
73 struct softpipe_winsys spws
;
80 static INLINE
struct xmesa_surface
*
81 xmesa_surface(struct pipe_surface
*ps
)
84 return (struct xmesa_surface
*) ps
;
88 static INLINE
struct xmesa_softpipe_winsys
*
89 xmesa_softpipe_winsys(struct softpipe_winsys
*spws
)
91 return (struct xmesa_softpipe_winsys
*) spws
;
95 * Turn the softpipe opaque buffer pointer into a dri_bufmgr opaque
98 static INLINE
struct xm_buffer
*
99 xm_bo( struct pipe_buffer_handle
*bo
)
101 return (struct xm_buffer
*) bo
;
104 static INLINE
struct pipe_buffer_handle
*
105 pipe_bo( struct xm_buffer
*bo
)
107 return (struct pipe_buffer_handle
*) bo
;
111 /* Most callbacks map direcly onto dri_bufmgr operations:
114 xm_buffer_map(struct pipe_winsys
*pws
, struct pipe_buffer_handle
*buf
,
117 struct xm_buffer
*xm_buf
= xm_bo(buf
);
118 xm_buf
->mapped
= xm_buf
->data
;
119 return xm_buf
->mapped
;
123 xm_buffer_unmap(struct pipe_winsys
*pws
, struct pipe_buffer_handle
*buf
)
125 struct xm_buffer
*xm_buf
= xm_bo(buf
);
126 xm_buf
->mapped
= NULL
;
130 xm_buffer_reference(struct pipe_winsys
*pws
,
131 struct pipe_buffer_handle
**ptr
,
132 struct pipe_buffer_handle
*buf
)
135 struct xm_buffer
*oldBuf
= xm_bo(*ptr
);
137 assert(oldBuf
->refcount
>= 0);
138 if (oldBuf
->refcount
== 0) {
140 if (!oldBuf
->userBuffer
)
152 struct xm_buffer
*newBuf
= xm_bo(buf
);
159 xm_buffer_data(struct pipe_winsys
*pws
, struct pipe_buffer_handle
*buf
,
160 unsigned size
, const void *data
, unsigned usage
)
162 struct xm_buffer
*xm_buf
= xm_bo(buf
);
163 assert(!xm_buf
->userBuffer
);
164 if (xm_buf
->size
!= size
) {
167 xm_buf
->data
= malloc(size
);
171 memcpy(xm_buf
->data
, data
, size
);
175 xm_buffer_subdata(struct pipe_winsys
*pws
, struct pipe_buffer_handle
*buf
,
176 unsigned long offset
, unsigned long size
, const void *data
)
178 struct xm_buffer
*xm_buf
= xm_bo(buf
);
179 GLubyte
*b
= (GLubyte
*) xm_buf
->data
;
180 assert(!xm_buf
->userBuffer
);
182 memcpy(b
+ offset
, data
, size
);
186 xm_buffer_get_subdata(struct pipe_winsys
*pws
, struct pipe_buffer_handle
*buf
,
187 unsigned long offset
, unsigned long size
, void *data
)
189 const struct xm_buffer
*xm_buf
= xm_bo(buf
);
190 const GLubyte
*b
= (GLubyte
*) xm_buf
->data
;
191 assert(!xm_buf
->userBuffer
);
193 memcpy(data
, b
+ offset
, size
);
198 * Display/copy the image in the surface into the X window specified
199 * by the XMesaBuffer.
202 xmesa_display_surface(XMesaBuffer b
, const struct pipe_surface
*surf
)
204 XImage
*ximage
= b
->tempImage
;
205 struct xm_buffer
*xm_buf
= xm_bo(surf
->buffer
);
207 /* check that the XImage has been previously initialized */
208 assert(ximage
->format
);
209 assert(ximage
->bitmap_unit
);
211 /* update XImage's fields */
212 ximage
->width
= surf
->width
;
213 ximage
->height
= surf
->height
;
214 ximage
->bytes_per_line
= surf
->pitch
* (ximage
->bits_per_pixel
/ 8);
215 ximage
->data
= xm_buf
->data
;
217 /* display image in Window */
218 XPutImage(b
->xm_visual
->display
, b
->drawable
, b
->gc
,
219 ximage
, 0, 0, 0, 0, surf
->width
, surf
->height
);
224 xm_flush_frontbuffer(struct pipe_winsys
*pws
,
225 struct pipe_surface
*surf
,
226 void *context_private
)
228 /* The Xlib driver's front color surfaces are actually X Windows so
229 * this flush is a no-op.
230 * If we instead did front buffer rendering to a temporary XImage,
231 * this would be the place to copy the Ximage to the on-screen Window.
233 XMesaContext xmctx
= (XMesaContext
) context_private
;
235 xmesa_display_surface(xmctx
->xm_buffer
, surf
);
241 xm_printf(struct pipe_winsys
*pws
, const char *fmtString
, ...)
244 va_start( args
, fmtString
);
245 vfprintf(stderr
, fmtString
, args
);
251 xm_get_name(struct pipe_winsys
*pws
)
257 static struct pipe_buffer_handle
*
258 xm_buffer_create(struct pipe_winsys
*pws
, unsigned flags
)
260 struct xm_buffer
*buffer
= CALLOC_STRUCT(xm_buffer
);
261 buffer
->refcount
= 1;
262 return pipe_bo(buffer
);
267 * Create buffer which wraps user-space data.
269 static struct pipe_buffer_handle
*
270 xm_user_buffer_create(struct pipe_winsys
*pws
, void *ptr
, unsigned bytes
)
272 struct xm_buffer
*buffer
= CALLOC_STRUCT(xm_buffer
);
273 buffer
->userBuffer
= TRUE
;
274 buffer
->refcount
= 1;
276 buffer
->size
= bytes
;
277 return pipe_bo(buffer
);
283 * Round n up to next multiple.
285 static INLINE
unsigned
286 round_up(unsigned n
, unsigned multiple
)
288 return (n
+ multiple
- 1) & ~(multiple
- 1);
292 xm_surface_pitch(struct pipe_winsys
*winsys
, unsigned cpp
, unsigned width
,
295 return round_up(width
, 64 / cpp
);
300 * Called via pipe->surface_alloc() to create new surfaces (textures,
301 * renderbuffers, etc.
303 static struct pipe_surface
*
304 xm_surface_alloc(struct pipe_winsys
*ws
, enum pipe_format pipeFormat
)
306 struct xmesa_surface
*xms
= CALLOC_STRUCT(xmesa_surface
);
311 xms
->surface
.format
= pipeFormat
;
312 xms
->surface
.refcount
= 1;
313 xms
->surface
.winsys
= ws
;
315 return &xms
->surface
;
321 xm_surface_release(struct pipe_winsys
*winsys
, struct pipe_surface
**s
)
323 struct pipe_surface
*surf
= *s
;
325 if (surf
->refcount
== 0) {
327 winsys
->buffer_reference(winsys
, &surf
->buffer
, NULL
);
336 * Return pointer to a pipe_winsys object.
337 * For Xlib, this is a singleton object.
338 * Nothing special for the Xlib driver so no subclassing or anything.
340 static struct pipe_winsys
*
341 xmesa_get_pipe_winsys(void)
343 static struct pipe_winsys
*ws
= NULL
;
346 ws
= CALLOC_STRUCT(pipe_winsys
);
348 /* Fill in this struct with callbacks that pipe will need to
349 * communicate with the window system, buffer manager, etc.
351 ws
->buffer_create
= xm_buffer_create
;
352 ws
->user_buffer_create
= xm_user_buffer_create
;
353 ws
->buffer_map
= xm_buffer_map
;
354 ws
->buffer_unmap
= xm_buffer_unmap
;
355 ws
->buffer_reference
= xm_buffer_reference
;
356 ws
->buffer_data
= xm_buffer_data
;
357 ws
->buffer_subdata
= xm_buffer_subdata
;
358 ws
->buffer_get_subdata
= xm_buffer_get_subdata
;
360 ws
->surface_pitch
= xm_surface_pitch
;
361 ws
->surface_alloc
= xm_surface_alloc
;
362 ws
->surface_release
= xm_surface_release
;
364 ws
->flush_frontbuffer
= xm_flush_frontbuffer
;
365 ws
->printf
= xm_printf
;
366 ws
->get_name
= xm_get_name
;
374 * The winsys being queried will have been created at glXCreateContext
375 * time, with a pixel format corresponding to the context's visual.
377 * XXX we should pass a flag indicating if the format is going to be
378 * use for a drawing surface vs. a texture. In the later case, we
379 * can support any format.
382 xmesa_is_format_supported(struct softpipe_winsys
*sws
,
383 enum pipe_format format
)
385 struct xmesa_softpipe_winsys
*xmws
= xmesa_softpipe_winsys(sws
);
387 if (format
== xmws
->pixelformat
) {
391 /* non-color / window surface format */
393 case PIPE_FORMAT_R16G16B16A16_SNORM
:
394 case PIPE_FORMAT_S8Z24_UNORM
:
395 case PIPE_FORMAT_U_S8
:
396 case PIPE_FORMAT_Z16_UNORM
:
397 case PIPE_FORMAT_Z32_UNORM
:
407 * Return pointer to a softpipe_winsys object.
409 static struct softpipe_winsys
*
410 xmesa_get_softpipe_winsys(uint pixelformat
)
412 struct xmesa_softpipe_winsys
*xmws
413 = CALLOC_STRUCT(xmesa_softpipe_winsys
);
417 xmws
->spws
.is_format_supported
= xmesa_is_format_supported
;
418 xmws
->pixelformat
= pixelformat
;
424 struct pipe_context
*
425 xmesa_create_pipe_context(XMesaContext xmesa
, uint pixelformat
)
427 struct pipe_winsys
*pws
= xmesa_get_pipe_winsys();
428 struct softpipe_winsys
*spws
= xmesa_get_softpipe_winsys(pixelformat
);
429 struct pipe_context
*pipe
;
431 pipe
= softpipe_create( pws
, spws
);