00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #include "glxheader.h"
00037 #include "xmesaP.h"
00038
00039 #undef ASSERT
00040 #undef Elements
00041
00042 #include "pipe/p_winsys.h"
00043 #include "pipe/p_format.h"
00044 #include "pipe/p_context.h"
00045 #include "pipe/p_inlines.h"
00046 #include "util/u_math.h"
00047 #include "util/u_memory.h"
00048 #include "softpipe/sp_winsys.h"
00049
00050 #ifdef GALLIUM_CELL
00051 #include "cell/ppu/cell_context.h"
00052 #include "cell/ppu/cell_screen.h"
00053 #include "cell/ppu/cell_winsys.h"
00054 #else
00055 #define TILE_SIZE 32
00056 #endif
00057
00058 #ifdef GALLIUM_TRACE
00059 #include "trace/tr_screen.h"
00060 #include "trace/tr_context.h"
00061 #endif
00062
00063 #include "xm_winsys_aub.h"
00064
00065
00070 struct xm_buffer
00071 {
00072 struct pipe_buffer base;
00073 boolean userBuffer;
00074 void *data;
00075 void *mapped;
00076
00077 XImage *tempImage;
00078 int shm;
00079 #if defined(USE_XSHM) && !defined(XFree86Server)
00080 XShmSegmentInfo shminfo;
00081 #endif
00082 };
00083
00084
00088 struct xmesa_pipe_winsys
00089 {
00090 struct pipe_winsys base;
00091 struct xmesa_visual *xm_visual;
00092 int shm;
00093 };
00094
00095
00096
00098 static INLINE struct xm_buffer *
00099 xm_buffer( struct pipe_buffer *buf )
00100 {
00101 return (struct xm_buffer *)buf;
00102 }
00103
00104
00108 #if defined(USE_XSHM) && !defined(XFree86Server)
00109
00110 #define XSHM_ENABLED(b) ((b)->shm)
00111
00112 static volatile int mesaXErrorFlag = 0;
00113
00117 static int
00118 mesaHandleXError(XMesaDisplay *dpy, XErrorEvent *event)
00119 {
00120 (void) dpy;
00121 (void) event;
00122 mesaXErrorFlag = 1;
00123 return 0;
00124 }
00125
00126
00127 static GLboolean alloc_shm(struct xm_buffer *buf, unsigned size)
00128 {
00129 XShmSegmentInfo *const shminfo = & buf->shminfo;
00130
00131 shminfo->shmid = shmget(IPC_PRIVATE, size, IPC_CREAT|0777);
00132 if (shminfo->shmid < 0) {
00133 return GL_FALSE;
00134 }
00135
00136 shminfo->shmaddr = (char *) shmat(shminfo->shmid, 0, 0);
00137 if (shminfo->shmaddr == (char *) -1) {
00138 shmctl(shminfo->shmid, IPC_RMID, 0);
00139 return GL_FALSE;
00140 }
00141
00142 shminfo->readOnly = False;
00143 return GL_TRUE;
00144 }
00145
00146
00150 static void
00151 alloc_shm_ximage(struct xm_buffer *b, struct xmesa_buffer *xmb,
00152 unsigned width, unsigned height)
00153 {
00154
00155
00156
00157
00158
00159
00160 #if 0
00161 GC gc;
00162 #endif
00163 int (*old_handler)(XMesaDisplay *, XErrorEvent *);
00164
00165 b->tempImage = XShmCreateImage(xmb->xm_visual->display,
00166 xmb->xm_visual->visinfo->visual,
00167 xmb->xm_visual->visinfo->depth,
00168 ZPixmap,
00169 NULL,
00170 &b->shminfo,
00171 width, height);
00172 if (b->tempImage == NULL) {
00173 b->shm = 0;
00174 return;
00175 }
00176
00177
00178 mesaXErrorFlag = 0;
00179 old_handler = XSetErrorHandler(mesaHandleXError);
00180
00181 XShmAttach(xmb->xm_visual->display, &b->shminfo);
00182 XSync(xmb->xm_visual->display, False);
00183
00184 if (mesaXErrorFlag) {
00185
00186 XFlush(xmb->xm_visual->display);
00187 mesaXErrorFlag = 0;
00188 XDestroyImage(b->tempImage);
00189 b->tempImage = NULL;
00190 b->shm = 0;
00191 (void) XSetErrorHandler(old_handler);
00192 return;
00193 }
00194
00195
00196
00197 #if 0
00198 gc = XCreateGC(xmb->xm_visual->display, xmb->drawable, 0, NULL);
00199 XShmPutImage(xmb->xm_visual->display, xmb->drawable, gc,
00200 b->tempImage, 0, 0, 0, 0, 1, 1 , False);
00201 XSync(xmb->xm_visual->display, False);
00202 XFreeGC(xmb->xm_visual->display, gc);
00203 (void) XSetErrorHandler(old_handler);
00204 if (mesaXErrorFlag) {
00205 XFlush(xmb->xm_visual->display);
00206 mesaXErrorFlag = 0;
00207 XDestroyImage(b->tempImage);
00208 b->tempImage = NULL;
00209 b->shm = 0;
00210 return;
00211 }
00212 #endif
00213 }
00214
00215 #else
00216
00217 #define XSHM_ENABLED(b) 0
00218
00219 static void
00220 alloc_shm_ximage(struct xm_buffer *b, struct xmesa_buffer *xmb,
00221 unsigned width, unsigned height)
00222 {
00223 b->shm = 0;
00224 }
00225 #endif
00226
00227
00228
00229
00230
00231
00232 static void *
00233 xm_buffer_map(struct pipe_winsys *pws, struct pipe_buffer *buf,
00234 unsigned flags)
00235 {
00236 struct xm_buffer *xm_buf = xm_buffer(buf);
00237 xm_buf->mapped = xm_buf->data;
00238 return xm_buf->mapped;
00239 }
00240
00241 static void
00242 xm_buffer_unmap(struct pipe_winsys *pws, struct pipe_buffer *buf)
00243 {
00244 struct xm_buffer *xm_buf = xm_buffer(buf);
00245 xm_buf->mapped = NULL;
00246 }
00247
00248 static void
00249 xm_buffer_destroy(struct pipe_winsys *pws,
00250 struct pipe_buffer *buf)
00251 {
00252 struct xm_buffer *oldBuf = xm_buffer(buf);
00253
00254 if (oldBuf->data) {
00255 #if defined(USE_XSHM) && !defined(XFree86Server)
00256 if (oldBuf->shminfo.shmid >= 0) {
00257 shmdt(oldBuf->shminfo.shmaddr);
00258 shmctl(oldBuf->shminfo.shmid, IPC_RMID, 0);
00259
00260 oldBuf->shminfo.shmid = -1;
00261 oldBuf->shminfo.shmaddr = (char *) -1;
00262 }
00263 else
00264 #endif
00265 {
00266 if (!oldBuf->userBuffer) {
00267 align_free(oldBuf->data);
00268 }
00269 }
00270
00271 oldBuf->data = NULL;
00272 }
00273
00274 free(oldBuf);
00275 }
00276
00277
00291 static void
00292 twiddle_tile(const uint *tileIn, uint *tileOut)
00293 {
00294 int y, x;
00295
00296 for (y = 0; y < TILE_SIZE; y+=2) {
00297 for (x = 0; x < TILE_SIZE; x+=2) {
00298 int k = 4 * (y/2 * TILE_SIZE/2 + x/2);
00299 tileOut[y * TILE_SIZE + (x + 0)] = tileIn[k];
00300 tileOut[y * TILE_SIZE + (x + 1)] = tileIn[k+1];
00301 tileOut[(y + 1) * TILE_SIZE + (x + 0)] = tileIn[k+2];
00302 tileOut[(y + 1) * TILE_SIZE + (x + 1)] = tileIn[k+3];
00303 }
00304 }
00305 }
00306
00307
00308
00313 static void
00314 xmesa_display_surface_tiled(XMesaBuffer b, const struct pipe_surface *surf)
00315 {
00316 XImage *ximage;
00317 struct xm_buffer *xm_buf = xm_buffer(surf->buffer);
00318 const uint tilesPerRow = (surf->width + TILE_SIZE - 1) / TILE_SIZE;
00319 uint x, y;
00320
00321 if (XSHM_ENABLED(xm_buf) && (xm_buf->tempImage == NULL)) {
00322 alloc_shm_ximage(xm_buf, b, TILE_SIZE, TILE_SIZE);
00323 }
00324
00325 ximage = (XSHM_ENABLED(xm_buf)) ? xm_buf->tempImage : b->tempImage;
00326
00327
00328 assert(ximage->format);
00329 assert(ximage->bitmap_unit);
00330
00331 if (!XSHM_ENABLED(xm_buf)) {
00332
00333 ximage->width = TILE_SIZE;
00334 ximage->height = TILE_SIZE;
00335 ximage->bytes_per_line = TILE_SIZE * 4;
00336 }
00337
00338 for (y = 0; y < surf->height; y += TILE_SIZE) {
00339 for (x = 0; x < surf->width; x += TILE_SIZE) {
00340 uint tmpTile[TILE_SIZE * TILE_SIZE];
00341 int tx = x / TILE_SIZE;
00342 int ty = y / TILE_SIZE;
00343 int offset = ty * tilesPerRow + tx;
00344 int w = TILE_SIZE;
00345 int h = TILE_SIZE;
00346
00347 if (y + h > surf->height)
00348 h = surf->height - y;
00349 if (x + w > surf->width)
00350 w = surf->width - x;
00351
00352
00353 offset *= TILE_SIZE * TILE_SIZE;
00354
00355 if (XSHM_ENABLED(xm_buf)) {
00356 ximage->data = (char *) xm_buf->data + 4 * offset;
00357
00358 memcpy(tmpTile, (uint *) ximage->data, sizeof(tmpTile));
00359
00360 twiddle_tile(tmpTile, (uint *) ximage->data);
00361
00362 #if defined(USE_XSHM) && !defined(XFree86Server)
00363 XShmPutImage(b->xm_visual->display, b->drawable, b->gc,
00364 ximage, 0, 0, x, y, w, h, False);
00365 #endif
00366 }
00367 else {
00368
00369 twiddle_tile((uint *) xm_buf->data + offset, tmpTile);
00370
00371 ximage->data = (char *) tmpTile;
00372 XPutImage(b->xm_visual->display, b->drawable, b->gc,
00373 ximage, 0, 0, x, y, w, h);
00374 }
00375 }
00376 }
00377 }
00378
00379
00384 void
00385 xmesa_display_surface(XMesaBuffer b, const struct pipe_surface *surf)
00386 {
00387 XImage *ximage;
00388 struct xm_buffer *xm_buf = xm_buffer(surf->buffer);
00389 static boolean no_swap = 0;
00390 static boolean firsttime = 1;
00391 static int tileSize = 0;
00392
00393 if (firsttime) {
00394 no_swap = getenv("SP_NO_RAST") != NULL;
00395 #ifdef GALLIUM_CELL
00396 if (!getenv("GALLIUM_NOCELL")) {
00397 tileSize = 32;
00398 }
00399 #endif
00400 firsttime = 0;
00401 }
00402
00403 if (no_swap)
00404 return;
00405
00406 if (tileSize) {
00407 xmesa_display_surface_tiled(b, surf);
00408 return;
00409 }
00410
00411 if (XSHM_ENABLED(xm_buf) && (xm_buf->tempImage == NULL)) {
00412 assert(surf->block.width == 1);
00413 assert(surf->block.height == 1);
00414 alloc_shm_ximage(xm_buf, b, surf->stride/surf->block.size, surf->height);
00415 }
00416
00417 ximage = (XSHM_ENABLED(xm_buf)) ? xm_buf->tempImage : b->tempImage;
00418 ximage->data = xm_buf->data;
00419
00420
00421 if (XSHM_ENABLED(xm_buf)) {
00422 #if defined(USE_XSHM) && !defined(XFree86Server)
00423 XShmPutImage(b->xm_visual->display, b->drawable, b->gc,
00424 ximage, 0, 0, 0, 0, surf->width, surf->height, False);
00425 #endif
00426 } else {
00427
00428 assert(ximage->format);
00429 assert(ximage->bitmap_unit);
00430
00431
00432 ximage->width = surf->width;
00433 ximage->height = surf->height;
00434 ximage->bytes_per_line = surf->stride;
00435
00436 XPutImage(b->xm_visual->display, b->drawable, b->gc,
00437 ximage, 0, 0, 0, 0, surf->width, surf->height);
00438 }
00439 }
00440
00441
00442 static void
00443 xm_flush_frontbuffer(struct pipe_winsys *pws,
00444 struct pipe_surface *surf,
00445 void *context_private)
00446 {
00447
00448
00449
00450
00451 XMesaContext xmctx = (XMesaContext) context_private;
00452 xmesa_display_surface(xmctx->xm_buffer, surf);
00453 }
00454
00455
00456
00457 static const char *
00458 xm_get_name(struct pipe_winsys *pws)
00459 {
00460 return "Xlib";
00461 }
00462
00463
00464 static struct pipe_buffer *
00465 xm_buffer_create(struct pipe_winsys *pws,
00466 unsigned alignment,
00467 unsigned usage,
00468 unsigned size)
00469 {
00470 struct xm_buffer *buffer = CALLOC_STRUCT(xm_buffer);
00471 #if defined(USE_XSHM) && !defined(XFree86Server)
00472 struct xmesa_pipe_winsys *xpws = (struct xmesa_pipe_winsys *) pws;
00473 #endif
00474
00475 buffer->base.refcount = 1;
00476 buffer->base.alignment = alignment;
00477 buffer->base.usage = usage;
00478 buffer->base.size = size;
00479
00480
00481 #if defined(USE_XSHM) && !defined(XFree86Server)
00482 buffer->shminfo.shmid = -1;
00483 buffer->shminfo.shmaddr = (char *) -1;
00484
00485 if (xpws->shm && (usage & PIPE_BUFFER_USAGE_PIXEL) != 0) {
00486 buffer->shm = xpws->shm;
00487
00488 if (alloc_shm(buffer, size)) {
00489 buffer->data = buffer->shminfo.shmaddr;
00490 }
00491 }
00492 #endif
00493
00494 if (buffer->data == NULL) {
00495 buffer->shm = 0;
00496
00497
00498 buffer->data = align_malloc(size, max(alignment, 16));
00499 }
00500
00501 return &buffer->base;
00502 }
00503
00504
00508 static struct pipe_buffer *
00509 xm_user_buffer_create(struct pipe_winsys *pws, void *ptr, unsigned bytes)
00510 {
00511 struct xm_buffer *buffer = CALLOC_STRUCT(xm_buffer);
00512 buffer->base.refcount = 1;
00513 buffer->base.size = bytes;
00514 buffer->userBuffer = TRUE;
00515 buffer->data = ptr;
00516 buffer->shm = 0;
00517
00518 return &buffer->base;
00519 }
00520
00521
00522
00526 static INLINE unsigned
00527 round_up(unsigned n, unsigned multiple)
00528 {
00529 return (n + multiple - 1) & ~(multiple - 1);
00530 }
00531
00532 static int
00533 xm_surface_alloc_storage(struct pipe_winsys *winsys,
00534 struct pipe_surface *surf,
00535 unsigned width, unsigned height,
00536 enum pipe_format format,
00537 unsigned flags,
00538 unsigned tex_usage)
00539 {
00540 const unsigned alignment = 64;
00541
00542 surf->width = width;
00543 surf->height = height;
00544 surf->format = format;
00545 pf_get_block(format, &surf->block);
00546 surf->nblocksx = pf_get_nblocksx(&surf->block, width);
00547 surf->nblocksy = pf_get_nblocksy(&surf->block, height);
00548 surf->stride = round_up(surf->nblocksx * surf->block.size, alignment);
00549 surf->usage = flags;
00550
00551 assert(!surf->buffer);
00552 surf->buffer = winsys->buffer_create(winsys, alignment,
00553 PIPE_BUFFER_USAGE_PIXEL,
00554 #ifdef GALLIUM_CELL
00555 surf->stride * round_up(surf->nblocksy, TILE_SIZE));
00556 #else
00557 surf->stride * surf->nblocksy);
00558 #endif
00559
00560 if(!surf->buffer)
00561 return -1;
00562
00563 return 0;
00564 }
00565
00566
00570 static struct pipe_surface *
00571 xm_surface_alloc(struct pipe_winsys *ws)
00572 {
00573 struct pipe_surface *surface = CALLOC_STRUCT(pipe_surface);
00574
00575 assert(ws);
00576
00577 surface->refcount = 1;
00578 surface->winsys = ws;
00579
00580 return surface;
00581 }
00582
00583
00584
00585 static void
00586 xm_surface_release(struct pipe_winsys *winsys, struct pipe_surface **s)
00587 {
00588 struct pipe_surface *surf = *s;
00589 assert(!surf->texture);
00590 surf->refcount--;
00591 if (surf->refcount == 0) {
00592 if (surf->buffer)
00593 winsys_buffer_reference(winsys, &surf->buffer, NULL);
00594 free(surf);
00595 }
00596 *s = NULL;
00597 }
00598
00599
00600
00601
00602
00603
00604
00605 static void
00606 xm_fence_reference(struct pipe_winsys *sws, struct pipe_fence_handle **ptr,
00607 struct pipe_fence_handle *fence)
00608 {
00609 }
00610
00611
00612 static int
00613 xm_fence_signalled(struct pipe_winsys *sws, struct pipe_fence_handle *fence,
00614 unsigned flag)
00615 {
00616 return 0;
00617 }
00618
00619
00620 static int
00621 xm_fence_finish(struct pipe_winsys *sws, struct pipe_fence_handle *fence,
00622 unsigned flag)
00623 {
00624 return 0;
00625 }
00626
00627
00633 struct pipe_winsys *
00634 xmesa_get_pipe_winsys_aub(struct xmesa_visual *xm_vis)
00635 {
00636 static struct xmesa_pipe_winsys *ws = NULL;
00637
00638 if (!ws) {
00639 ws = (struct xmesa_pipe_winsys *) xmesa_create_pipe_winsys_aub();
00640 }
00641 return &ws->base;
00642 }
00643
00644
00645 static struct pipe_winsys *
00646 xmesa_get_pipe_winsys(struct xmesa_visual *xm_vis)
00647 {
00648 static struct xmesa_pipe_winsys *ws = NULL;
00649
00650 if (!ws) {
00651 ws = CALLOC_STRUCT(xmesa_pipe_winsys);
00652
00653 ws->xm_visual = xm_vis;
00654 ws->shm = xmesa_check_for_xshm(xm_vis->display);
00655
00656
00657
00658
00659 ws->base.buffer_create = xm_buffer_create;
00660 ws->base.user_buffer_create = xm_user_buffer_create;
00661 ws->base.buffer_map = xm_buffer_map;
00662 ws->base.buffer_unmap = xm_buffer_unmap;
00663 ws->base.buffer_destroy = xm_buffer_destroy;
00664
00665 ws->base.surface_alloc = xm_surface_alloc;
00666 ws->base.surface_alloc_storage = xm_surface_alloc_storage;
00667 ws->base.surface_release = xm_surface_release;
00668
00669 ws->base.fence_reference = xm_fence_reference;
00670 ws->base.fence_signalled = xm_fence_signalled;
00671 ws->base.fence_finish = xm_fence_finish;
00672
00673 ws->base.flush_frontbuffer = xm_flush_frontbuffer;
00674 ws->base.get_name = xm_get_name;
00675 }
00676
00677 return &ws->base;
00678 }
00679
00680
00681 struct pipe_context *
00682 xmesa_create_pipe_context(XMesaContext xmesa, uint pixelformat)
00683 {
00684 struct pipe_winsys *pws;
00685 struct pipe_context *pipe;
00686
00687 if (getenv("XM_AUB")) {
00688 pws = xmesa_get_pipe_winsys_aub(xmesa->xm_visual);
00689 }
00690 else {
00691 pws = xmesa_get_pipe_winsys(xmesa->xm_visual);
00692 }
00693
00694 #ifdef GALLIUM_CELL
00695 if (!getenv("GALLIUM_NOCELL")) {
00696 struct cell_winsys *cws = cell_get_winsys(pixelformat);
00697 struct pipe_screen *screen = cell_create_screen(pws);
00698
00699 pipe = cell_create_context(screen, cws);
00700 }
00701 else
00702 #endif
00703 {
00704 struct pipe_screen *screen = softpipe_create_screen(pws);
00705
00706 pipe = softpipe_create(screen, pws, NULL);
00707
00708 #ifdef GALLIUM_TRACE
00709 screen = trace_screen_create(screen);
00710
00711 pipe = trace_context_create(screen, pipe);
00712 #endif
00713 }
00714
00715 if (pipe)
00716 pipe->priv = xmesa;
00717
00718 return pipe;
00719 }