diff options
Diffstat (limited to 'src/gallium/state_trackers/egl/x11/native_ximage.c')
-rw-r--r-- | src/gallium/state_trackers/egl/x11/native_ximage.c | 278 |
1 files changed, 109 insertions, 169 deletions
diff --git a/src/gallium/state_trackers/egl/x11/native_ximage.c b/src/gallium/state_trackers/egl/x11/native_ximage.c index 3421c1951a..c6b16354f9 100644 --- a/src/gallium/state_trackers/egl/x11/native_ximage.c +++ b/src/gallium/state_trackers/egl/x11/native_ximage.c @@ -28,17 +28,19 @@ #include <sys/shm.h> #include <X11/Xlib.h> #include <X11/Xutil.h> -#include <X11/extensions/XShm.h> #include "util/u_memory.h" #include "util/u_math.h" #include "util/u_format.h" #include "pipe/p_compiler.h" -#include "util/u_simple_screen.h" #include "util/u_inlines.h" -#include "softpipe/sp_winsys.h" +#include "state_tracker/xlib_sw_winsys.h" +#include "target-helpers/wrap_screen.h" +#include "util/u_debug.h" +#include "softpipe/sp_public.h" +#include "llvmpipe/lp_public.h" +#include "cell/ppu/cell_public.h" #include "egllog.h" -#include "sw_winsys.h" #include "native_x11.h" #include "x11_screen.h" @@ -53,24 +55,18 @@ struct ximage_display { Display *dpy; boolean own_dpy; - struct x11_screen *xscr; - int xscr_number; - struct native_event_handler *event_handler; - boolean use_xshm; + struct x11_screen *xscr; + int xscr_number; - struct pipe_winsys *winsys; struct ximage_config *configs; int num_configs; }; struct ximage_buffer { - XImage *ximage; - struct pipe_texture *texture; - XShmSegmentInfo *shm_info; - boolean xshm_attached; + struct xlib_drawable xdraw; }; struct ximage_surface { @@ -81,13 +77,13 @@ struct ximage_surface { XVisualInfo visual; struct ximage_display *xdpy; - GC gc; - unsigned int server_stamp; unsigned int client_stamp; int width, height; struct ximage_buffer buffers[NUM_NATIVE_ATTACHMENTS]; uint valid_mask; + + struct pipe_surface *draw_surface; }; struct ximage_config { @@ -121,18 +117,6 @@ ximage_surface_free_buffer(struct native_surface *nsurf, struct ximage_buffer *xbuf = &xsurf->buffers[which]; pipe_texture_reference(&xbuf->texture, NULL); - - if (xbuf->shm_info) { - if (xbuf->xshm_attached) - XShmDetach(xsurf->xdpy->dpy, xbuf->shm_info); - if (xbuf->shm_info->shmaddr != (void *) -1) - shmdt(xbuf->shm_info->shmaddr); - if (xbuf->shm_info->shmid != -1) - shmctl(xbuf->shm_info->shmid, IPC_RMID, 0); - - xbuf->shm_info->shmaddr = (void *) -1; - xbuf->shm_info->shmid = -1; - } } static boolean @@ -156,40 +140,25 @@ ximage_surface_alloc_buffer(struct native_surface *nsurf, templ.depth0 = 1; templ.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET; - if (xbuf->shm_info) { - struct pipe_buffer *pbuf; - unsigned stride, size; - void *addr = NULL; - - stride = util_format_get_stride(xsurf->color_format, xsurf->width); - /* alignment should depend on visual? */ - stride = align(stride, 4); - size = stride * xsurf->height; - - /* create and attach shm object */ - xbuf->shm_info->shmid = shmget(IPC_PRIVATE, size, 0755); - if (xbuf->shm_info->shmid != -1) { - xbuf->shm_info->shmaddr = - shmat(xbuf->shm_info->shmid, NULL, 0); - if (xbuf->shm_info->shmaddr != (void *) -1) { - if (XShmAttach(xsurf->xdpy->dpy, xbuf->shm_info)) { - addr = xbuf->shm_info->shmaddr; - xbuf->xshm_attached = TRUE; - } - } - } - - if (addr) { - pbuf = screen->user_buffer_create(screen, addr, size); - if (pbuf) { - xbuf->texture = - screen->texture_blanket(screen, &templ, &stride, pbuf); - pipe_buffer_reference(&pbuf, NULL); - } + if (xsurf->type != XIMAGE_SURFACE_TYPE_PBUFFER) { + switch (which) { + case NATIVE_ATTACHMENT_FRONT_LEFT: + case NATIVE_ATTACHMENT_FRONT_RIGHT: + templ.tex_usage |= PIPE_TEXTURE_USAGE_SCANOUT; + break; + case NATIVE_ATTACHMENT_BACK_LEFT: + case NATIVE_ATTACHMENT_BACK_RIGHT: + templ.tex_usage |= PIPE_TEXTURE_USAGE_DISPLAY_TARGET; + break; + default: + break; } } - else { - xbuf->texture = screen->texture_create(screen, &templ); + xbuf->texture = screen->texture_create(screen, &templ); + if (xbuf->texture) { + xbuf->xdraw.visual = xsurf->visual.visual; + xbuf->xdraw.depth = xsurf->visual.depth; + xbuf->xdraw.drawable = xsurf->drawable; } /* clean up the buffer if allocation failed */ @@ -269,18 +238,10 @@ ximage_surface_update_buffers(struct native_surface *nsurf, uint buffer_mask) new_valid = 0x0; for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) { if (native_attachment_mask_test(buffer_mask, att)) { - struct ximage_buffer *xbuf = &xsurf->buffers[att]; - /* reallocate the texture */ if (!ximage_surface_alloc_buffer(&xsurf->base, att)) break; - /* update ximage */ - if (xbuf->ximage) { - xbuf->ximage->width = xsurf->width; - xbuf->ximage->height = xsurf->height; - } - new_valid |= (1 << att); if (buffer_mask == new_valid) break; @@ -300,43 +261,26 @@ ximage_surface_draw_buffer(struct native_surface *nsurf, struct ximage_surface *xsurf = ximage_surface(nsurf); struct ximage_buffer *xbuf = &xsurf->buffers[which]; struct pipe_screen *screen = xsurf->xdpy->base.screen; - struct pipe_transfer *transfer; + struct pipe_surface *psurf; if (xsurf->type == XIMAGE_SURFACE_TYPE_PBUFFER) return TRUE; - assert(xsurf->drawable && xbuf->ximage && xbuf->texture); + assert(xsurf->drawable && xbuf->texture); - transfer = screen->get_tex_transfer(screen, xbuf->texture, - 0, 0, 0, PIPE_TRANSFER_READ, 0, 0, xsurf->width, xsurf->height); - if (!transfer) - return FALSE; + psurf = xsurf->draw_surface; + if (!psurf || psurf->texture != xbuf->texture) { + pipe_surface_reference(&xsurf->draw_surface, NULL); - xbuf->ximage->bytes_per_line = transfer->stride; - xbuf->ximage->data = screen->transfer_map(screen, transfer); - if (!xbuf->ximage->data) { - screen->tex_transfer_destroy(transfer); - return FALSE; - } - - - if (xbuf->shm_info) - XShmPutImage(xsurf->xdpy->dpy, xsurf->drawable, xsurf->gc, - xbuf->ximage, 0, 0, 0, 0, xsurf->width, xsurf->height, False); - else - XPutImage(xsurf->xdpy->dpy, xsurf->drawable, xsurf->gc, - xbuf->ximage, 0, 0, 0, 0, xsurf->width, xsurf->height); - - xbuf->ximage->data = NULL; - screen->transfer_unmap(screen, transfer); + psurf = screen->get_tex_surface(screen, + xbuf->texture, 0, 0, 0, PIPE_BUFFER_USAGE_CPU_READ); + if (!psurf) + return FALSE; - /* - * softpipe allows the pipe transfer to be re-used, but we don't want to - * rely on that behavior. - */ - screen->tex_transfer_destroy(transfer); + xsurf->draw_surface = psurf; + } - XSync(xsurf->xdpy->dpy, FALSE); + screen->flush_frontbuffer(screen, psurf, &xbuf->xdraw); return TRUE; } @@ -364,7 +308,8 @@ ximage_surface_swap_buffers(struct native_surface *nsurf) boolean ret; /* display the back buffer first */ - ret = ximage_surface_draw_buffer(nsurf, NATIVE_ATTACHMENT_BACK_LEFT); + ret = ximage_surface_draw_buffer(&xsurf->base, + NATIVE_ATTACHMENT_BACK_LEFT); /* force buffers to be updated in next validation call */ xsurf->server_stamp++; ximage_surface_notify_invalid(&xsurf->base); @@ -372,13 +317,12 @@ ximage_surface_swap_buffers(struct native_surface *nsurf) xfront = &xsurf->buffers[NATIVE_ATTACHMENT_FRONT_LEFT]; xback = &xsurf->buffers[NATIVE_ATTACHMENT_BACK_LEFT]; - /* skip swapping so that the front buffer is allocated only when needed */ - if (!xfront->texture) - return ret; - - xtmp = *xfront; - *xfront = *xback; - *xback = xtmp; + /* skip swapping unless there is a front buffer */ + if (xfront->texture) { + xtmp = *xfront; + *xfront = *xback; + *xback = xtmp; + } return ret; } @@ -433,18 +377,11 @@ ximage_surface_destroy(struct native_surface *nsurf) struct ximage_surface *xsurf = ximage_surface(nsurf); int i; - for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) { - struct ximage_buffer *xbuf = &xsurf->buffers[i]; + pipe_surface_reference(&xsurf->draw_surface, NULL); + + for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) ximage_surface_free_buffer(&xsurf->base, i); - /* xbuf->shm_info is owned by xbuf->ximage? */ - if (xbuf->ximage) { - XDestroyImage(xbuf->ximage); - xbuf->ximage = NULL; - } - } - if (xsurf->type != XIMAGE_SURFACE_TYPE_PBUFFER) - XFreeGC(xsurf->xdpy->dpy, xsurf->gc); free(xsurf); } @@ -457,7 +394,6 @@ ximage_display_create_surface(struct native_display *ndpy, struct ximage_display *xdpy = ximage_display(ndpy); struct ximage_config *xconf = ximage_config(nconf); struct ximage_surface *xsurf; - int i; xsurf = CALLOC_STRUCT(ximage_surface); if (!xsurf) @@ -471,52 +407,8 @@ ximage_display_create_surface(struct native_display *ndpy, if (xsurf->type != XIMAGE_SURFACE_TYPE_PBUFFER) { xsurf->drawable = drawable; xsurf->visual = *xconf->visual; - - xsurf->gc = XCreateGC(xdpy->dpy, xsurf->drawable, 0, NULL); - if (!xsurf->gc) { - free(xsurf); - return NULL; - } - /* initialize the geometry */ ximage_surface_update_buffers(&xsurf->base, 0x0); - - for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) { - struct ximage_buffer *xbuf = &xsurf->buffers[i]; - - if (xdpy->use_xshm) { - xbuf->shm_info = calloc(1, sizeof(*xbuf->shm_info)); - if (xbuf->shm_info) { - /* initialize shm info */ - xbuf->shm_info->shmid = -1; - xbuf->shm_info->shmaddr = (void *) -1; - xbuf->shm_info->readOnly = TRUE; - - xbuf->ximage = XShmCreateImage(xsurf->xdpy->dpy, - xsurf->visual.visual, - xsurf->visual.depth, - ZPixmap, NULL, - xbuf->shm_info, - 0, 0); - } - } - else { - xbuf->ximage = XCreateImage(xsurf->xdpy->dpy, - xsurf->visual.visual, - xsurf->visual.depth, - ZPixmap, 0, /* format, offset */ - NULL, /* data */ - 0, 0, /* size */ - 8, /* bitmap_pad */ - 0); /* bytes_per_line */ - } - - if (!xbuf->ximage) { - XFreeGC(xdpy->dpy, xsurf->gc); - free(xsurf); - return NULL; - } - } } xsurf->base.destroy = ximage_surface_destroy; @@ -727,7 +619,6 @@ ximage_display_destroy(struct native_display *ndpy) free(xdpy->configs); xdpy->base.screen->destroy(xdpy->base.screen); - free(xdpy->winsys); x11_screen_destroy(xdpy->xscr); if (xdpy->own_dpy) @@ -735,10 +626,63 @@ ximage_display_destroy(struct native_display *ndpy) free(xdpy); } + +/* Helper function to build a subset of a driver stack consisting of + * one of the software rasterizers (cell, llvmpipe, softpipe) and the + * xlib winsys. + * + * This function could be shared, but currently causes headaches for + * the build systems, particularly scons if we try. + * + * Long term, want to avoid having global #defines for things like + * GALLIUM_LLVMPIPE, GALLIUM_CELL, etc. Scons already eliminates + * those #defines, so things that are painful for it now are likely to + * be painful for other build systems in the future. + */ +static struct pipe_screen * +swrast_xlib_create_screen( Display *display ) +{ + struct sw_winsys *winsys; + struct pipe_screen *screen = NULL; + + /* Create the underlying winsys, which performs presents to Xlib + * drawables: + */ + winsys = xlib_create_sw_winsys( display ); + if (winsys == NULL) + return NULL; + + /* Create a software rasterizer on top of that winsys. Use + * llvmpipe if it is available. + */ +#if defined(GALLIUM_LLVMPIPE) + if (screen == NULL && + !debug_get_bool_option("GALLIUM_NO_LLVM", FALSE)) + screen = llvmpipe_create_screen( winsys ); +#endif + + if (screen == NULL) + screen = softpipe_create_screen( winsys ); + + if (screen == NULL) + goto fail; + + /* Inject any wrapping layers we want to here: + */ + return gallium_wrap_screen( screen ); + +fail: + if (winsys) + winsys->destroy( winsys ); + + return NULL; +} + + + struct native_display * x11_create_ximage_display(EGLNativeDisplayType dpy, - struct native_event_handler *event_handler, - boolean use_xshm) + struct native_event_handler *event_handler) { struct ximage_display *xdpy; @@ -756,6 +700,8 @@ x11_create_ximage_display(EGLNativeDisplayType dpy, xdpy->own_dpy = TRUE; } + xdpy->event_handler = event_handler; + xdpy->xscr_number = DefaultScreen(xdpy->dpy); xdpy->xscr = x11_screen_create(xdpy->dpy, xdpy->xscr_number); if (!xdpy->xscr) { @@ -763,13 +709,7 @@ x11_create_ximage_display(EGLNativeDisplayType dpy, return NULL; } - xdpy->event_handler = event_handler; - - xdpy->use_xshm = - (use_xshm && x11_screen_support(xdpy->xscr, X11_SCREEN_EXTENSION_XSHM)); - - xdpy->winsys = create_sw_winsys(); - xdpy->base.screen = softpipe_create_screen(xdpy->winsys); + xdpy->base.screen = swrast_xlib_create_screen(xdpy->dpy); xdpy->base.destroy = ximage_display_destroy; xdpy->base.get_param = ximage_display_get_param; |