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"
39 #include "pipe/p_winsys.h"
40 #include "pipe/p_format.h"
41 #include "pipe/p_context.h"
42 #include "pipe/p_util.h"
43 #include "pipe/p_inlines.h"
44 #include "pipe/softpipe/sp_winsys.h"
47 #include "pipe/cell/ppu/cell_context.h"
48 #include "pipe/cell/ppu/cell_winsys.h"
50 #define TILE_SIZE 32 /* avoid compilation errors */
53 #include "xm_winsys_aub.h"
57 * Low-level OS/window system memory buffer
61 struct pipe_buffer base
;
62 boolean userBuffer
; /** Is this a user-space buffer? */
70 struct pipe_surface surface
;
77 * Derived from softpipe_winsys.
78 * We just need one extra field which indicates the pixel format to use for
79 * drawing surfaces so that we're compatible with the XVisual/window format.
81 struct xmesa_softpipe_winsys
83 struct softpipe_winsys spws
;
84 enum pipe_format pixelformat
;
90 static INLINE
struct xmesa_surface
*
91 xmesa_surface(struct pipe_surface
*ps
)
94 return (struct xmesa_surface
*) ps
;
98 static INLINE
struct xmesa_softpipe_winsys
*
99 xmesa_softpipe_winsys(struct softpipe_winsys
*spws
)
101 return (struct xmesa_softpipe_winsys
*) spws
;
105 * Turn the softpipe opaque buffer pointer into a dri_bufmgr opaque
108 static INLINE
struct xm_buffer
*
109 xm_buffer( struct pipe_buffer
*buf
)
111 return (struct xm_buffer
*)buf
;
116 /* Most callbacks map direcly onto dri_bufmgr operations:
119 xm_buffer_map(struct pipe_winsys
*pws
, struct pipe_buffer
*buf
,
122 struct xm_buffer
*xm_buf
= xm_buffer(buf
);
123 xm_buf
->mapped
= xm_buf
->data
;
124 return xm_buf
->mapped
;
128 xm_buffer_unmap(struct pipe_winsys
*pws
, struct pipe_buffer
*buf
)
130 struct xm_buffer
*xm_buf
= xm_buffer(buf
);
131 xm_buf
->mapped
= NULL
;
135 xm_buffer_destroy(struct pipe_winsys
*pws
,
136 struct pipe_buffer
*buf
)
138 struct xm_buffer
*oldBuf
= xm_buffer(buf
);
141 if (!oldBuf
->userBuffer
)
142 align_free(oldBuf
->data
);
151 * Display a surface that's in a tiled configuration. That is, all the
152 * pixels for a TILE_SIZExTILE_SIZE block are contiguous in memory.
155 xmesa_display_surface_tiled(XMesaBuffer b
, const struct pipe_surface
*surf
)
157 XImage
*ximage
= b
->tempImage
;
158 struct xm_buffer
*xm_buf
= xm_buffer(surf
->buffer
);
159 const uint tilesPerRow
= (surf
->width
+ TILE_SIZE
- 1) / TILE_SIZE
;
162 /* check that the XImage has been previously initialized */
163 assert(ximage
->format
);
164 assert(ximage
->bitmap_unit
);
166 /* update XImage's fields */
167 ximage
->width
= TILE_SIZE
;
168 ximage
->height
= TILE_SIZE
;
169 ximage
->bytes_per_line
= TILE_SIZE
* 4;
171 for (y
= 0; y
< surf
->height
; y
+= TILE_SIZE
) {
172 for (x
= 0; x
< surf
->width
; x
+= TILE_SIZE
) {
175 int tx
= x
/ TILE_SIZE
;
176 int ty
= y
/ TILE_SIZE
;
177 int offset
= ty
* tilesPerRow
+ tx
;
179 offset
*= 4 * TILE_SIZE
* TILE_SIZE
;
181 ximage
->data
= (char *) xm_buf
->data
+ offset
;
183 XPutImage(b
->xm_visual
->display
, b
->drawable
, b
->gc
,
184 ximage
, 0, 0, dx
, dy
, TILE_SIZE
, TILE_SIZE
);
191 * Display/copy the image in the surface into the X window specified
192 * by the XMesaBuffer.
195 xmesa_display_surface(XMesaBuffer b
, const struct pipe_surface
*surf
)
197 XImage
*ximage
= b
->tempImage
;
198 struct xm_buffer
*xm_buf
= xm_buffer(surf
->buffer
);
199 const struct xmesa_surface
*xm_surf
200 = xmesa_surface((struct pipe_surface
*) surf
);
202 if (xm_surf
->tileSize
) {
203 xmesa_display_surface_tiled(b
, surf
);
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
;
234 xmesa_display_surface(xmctx
->xm_buffer
, surf
);
240 xm_printf(struct pipe_winsys
*pws
, const char *fmtString
, ...)
243 va_start( args
, fmtString
);
244 vfprintf(stderr
, fmtString
, args
);
250 xm_get_name(struct pipe_winsys
*pws
)
256 static struct pipe_buffer
*
257 xm_buffer_create(struct pipe_winsys
*pws
,
262 struct xm_buffer
*buffer
= CALLOC_STRUCT(xm_buffer
);
263 buffer
->base
.refcount
= 1;
264 buffer
->base
.alignment
= alignment
;
265 buffer
->base
.usage
= usage
;
266 buffer
->base
.size
= size
;
268 /* align to 16-byte multiple for Cell */
269 buffer
->data
= align_malloc(size
, max(alignment
, 16));
271 return &buffer
->base
;
276 * Create buffer which wraps user-space data.
278 static struct pipe_buffer
*
279 xm_user_buffer_create(struct pipe_winsys
*pws
, void *ptr
, unsigned bytes
)
281 struct xm_buffer
*buffer
= CALLOC_STRUCT(xm_buffer
);
282 buffer
->base
.refcount
= 1;
283 buffer
->base
.size
= bytes
;
284 buffer
->userBuffer
= TRUE
;
287 return &buffer
->base
;
293 * Round n up to next multiple.
295 static INLINE
unsigned
296 round_up(unsigned n
, unsigned multiple
)
298 return (n
+ multiple
- 1) & ~(multiple
- 1);
302 xm_surface_alloc_storage(struct pipe_winsys
*winsys
,
303 struct pipe_surface
*surf
,
304 unsigned width
, unsigned height
,
305 enum pipe_format format
,
308 const unsigned alignment
= 64;
311 surf
->height
= height
;
312 surf
->format
= format
;
313 surf
->cpp
= pf_get_size(format
);
314 surf
->pitch
= round_up(width
, alignment
/ surf
->cpp
);
316 #ifdef GALLIUM_CELL /* XXX a bit of a hack */
317 height
= round_up(height
, TILE_SIZE
);
320 assert(!surf
->buffer
);
321 surf
->buffer
= winsys
->buffer_create(winsys
, alignment
,
322 PIPE_BUFFER_USAGE_PIXEL
,
323 surf
->pitch
* surf
->cpp
* height
);
332 * Called via pipe->surface_alloc() to create new surfaces (textures,
333 * renderbuffers, etc.
335 static struct pipe_surface
*
336 xm_surface_alloc(struct pipe_winsys
*ws
)
338 struct xmesa_surface
*xms
= CALLOC_STRUCT(xmesa_surface
);
342 xms
->surface
.refcount
= 1;
343 xms
->surface
.winsys
= ws
;
346 if (!getenv("GALLIUM_NOCELL")) {
347 xms
->tileSize
= 32; /** probably temporary */
351 return &xms
->surface
;
357 xm_surface_release(struct pipe_winsys
*winsys
, struct pipe_surface
**s
)
359 struct pipe_surface
*surf
= *s
;
361 if (surf
->refcount
== 0) {
363 pipe_buffer_reference(winsys
, &surf
->buffer
, NULL
);
372 * Return pointer to a pipe_winsys object.
373 * For Xlib, this is a singleton object.
374 * Nothing special for the Xlib driver so no subclassing or anything.
377 xmesa_get_pipe_winsys_aub(void)
379 static struct pipe_winsys
*ws
= NULL
;
381 if (!ws
&& getenv("XM_AUB")) {
382 ws
= xmesa_create_pipe_winsys_aub();
385 ws
= CALLOC_STRUCT(pipe_winsys
);
387 /* Fill in this struct with callbacks that pipe will need to
388 * communicate with the window system, buffer manager, etc.
390 ws
->buffer_create
= xm_buffer_create
;
391 ws
->user_buffer_create
= xm_user_buffer_create
;
392 ws
->buffer_map
= xm_buffer_map
;
393 ws
->buffer_unmap
= xm_buffer_unmap
;
394 ws
->buffer_destroy
= xm_buffer_destroy
;
396 ws
->surface_alloc
= xm_surface_alloc
;
397 ws
->surface_alloc_storage
= xm_surface_alloc_storage
;
398 ws
->surface_release
= xm_surface_release
;
400 ws
->flush_frontbuffer
= xm_flush_frontbuffer
;
401 ws
->printf
= xm_printf
;
402 ws
->get_name
= xm_get_name
;
410 * Called via softpipe_winsys->is_format_supported().
411 * This function is only called to test formats for front/back color surfaces.
412 * The winsys being queried will have been created at glXCreateContext
413 * time, with a pixel format corresponding to the context's visual.
416 xmesa_is_format_supported(struct softpipe_winsys
*sws
,
417 enum pipe_format format
)
419 struct xmesa_softpipe_winsys
*xmws
= xmesa_softpipe_winsys(sws
);
420 return (format
== xmws
->pixelformat
);
425 * Return pointer to a softpipe_winsys object.
427 static struct softpipe_winsys
*
428 xmesa_get_softpipe_winsys(uint pixelformat
)
430 struct xmesa_softpipe_winsys
*xmws
431 = CALLOC_STRUCT(xmesa_softpipe_winsys
);
435 xmws
->spws
.is_format_supported
= xmesa_is_format_supported
;
436 xmws
->pixelformat
= pixelformat
;
442 struct pipe_context
*
443 xmesa_create_pipe_context(XMesaContext xmesa
, uint pixelformat
)
445 struct pipe_winsys
*pws
= xmesa_get_pipe_winsys_aub();
446 struct pipe_context
*pipe
;
449 if (!getenv("GALLIUM_NOCELL")) {
450 struct cell_winsys
*cws
= cell_get_winsys(pixelformat
);
451 pipe
= cell_create_context(pws
, cws
);
459 struct softpipe_winsys
*spws
= xmesa_get_softpipe_winsys(pixelformat
);
460 pipe
= softpipe_create( pws
, spws
);