X-Git-Url: https://git.libre-soc.org/?p=mesa.git;a=blobdiff_plain;f=src%2Fgallium%2Fwinsys%2Fsw%2Fdri%2Fdri_sw_winsys.c;h=f9ff6d25d730138c2dfc19d9354461d1607c6664;hp=1bca827bd65f7d6bc80a4f114074336ade2ec411;hb=4e465c91b8e5a0017216c8d8db0f6b08cb1ad465;hpb=e4c54d404959aa1bce26caa313c0a47e65ff211a diff --git a/src/gallium/winsys/sw/dri/dri_sw_winsys.c b/src/gallium/winsys/sw/dri/dri_sw_winsys.c index 1bca827bd65..f9ff6d25d73 100644 --- a/src/gallium/winsys/sw/dri/dri_sw_winsys.c +++ b/src/gallium/winsys/sw/dri/dri_sw_winsys.c @@ -26,14 +26,26 @@ * **************************************************************************/ +#ifdef HAVE_SYS_SHM_H +#include +#include +#ifdef __FreeBSD__ +/* sys/ipc.h -> sys/_types.h -> machine/param.h + * - defines ALIGN which clashes with our ALIGN + */ +#undef ALIGN +#endif +#endif + #include "pipe/p_compiler.h" #include "pipe/p_format.h" +#include "pipe/p_state.h" #include "util/u_inlines.h" -#include "util/u_format.h" +#include "util/format/u_format.h" #include "util/u_math.h" #include "util/u_memory.h" -#include "state_tracker/sw_winsys.h" +#include "frontend/sw_winsys.h" #include "dri_sw_winsys.h" @@ -44,47 +56,74 @@ struct dri_sw_displaytarget unsigned height; unsigned stride; + unsigned map_flags; + int shmid; void *data; void *mapped; + const void *front_private; }; struct dri_sw_winsys { struct sw_winsys base; - struct drisw_loader_funcs *lf; + const struct drisw_loader_funcs *lf; }; -static INLINE struct dri_sw_displaytarget * +static inline struct dri_sw_displaytarget * dri_sw_displaytarget( struct sw_displaytarget *dt ) { return (struct dri_sw_displaytarget *)dt; } -static INLINE struct dri_sw_winsys * +static inline struct dri_sw_winsys * dri_sw_winsys( struct sw_winsys *ws ) { return (struct dri_sw_winsys *)ws; } -static boolean +static bool dri_sw_is_displaytarget_format_supported( struct sw_winsys *ws, unsigned tex_usage, enum pipe_format format ) { /* TODO: check visuals or other sensible thing here */ - return TRUE; + return true; } +#ifdef HAVE_SYS_SHM_H +static char * +alloc_shm(struct dri_sw_displaytarget *dri_sw_dt, unsigned size) +{ + char *addr; + + /* 0600 = user read+write */ + dri_sw_dt->shmid = shmget(IPC_PRIVATE, size, IPC_CREAT | 0600); + if (dri_sw_dt->shmid < 0) + return NULL; + + addr = (char *) shmat(dri_sw_dt->shmid, 0, 0); + /* mark the segment immediately for deletion to avoid leaks */ + shmctl(dri_sw_dt->shmid, IPC_RMID, 0); + + if (addr == (char *) -1) + return NULL; + + return addr; +} +#endif + static struct sw_displaytarget * dri_sw_displaytarget_create(struct sw_winsys *winsys, unsigned tex_usage, enum pipe_format format, unsigned width, unsigned height, unsigned alignment, + const void *front_private, unsigned *stride) { + struct dri_sw_winsys *ws = dri_sw_winsys(winsys); struct dri_sw_displaytarget *dri_sw_dt; unsigned nblocksy, size, format_stride; @@ -95,6 +134,7 @@ dri_sw_displaytarget_create(struct sw_winsys *winsys, dri_sw_dt->format = format; dri_sw_dt->width = width; dri_sw_dt->height = height; + dri_sw_dt->front_private = front_private; format_stride = util_format_get_stride(format, width); dri_sw_dt->stride = align(format_stride, alignment); @@ -102,7 +142,16 @@ dri_sw_displaytarget_create(struct sw_winsys *winsys, nblocksy = util_format_get_nblocksy(format, height); size = dri_sw_dt->stride * nblocksy; - dri_sw_dt->data = align_malloc(size, alignment); + dri_sw_dt->shmid = -1; + +#ifdef HAVE_SYS_SHM_H + if (ws->lf->put_image_shm) + dri_sw_dt->data = alloc_shm(dri_sw_dt, size); +#endif + + if(!dri_sw_dt->data) + dri_sw_dt->data = align_malloc(size, alignment); + if(!dri_sw_dt->data) goto no_data; @@ -121,8 +170,13 @@ dri_sw_displaytarget_destroy(struct sw_winsys *ws, { struct dri_sw_displaytarget *dri_sw_dt = dri_sw_displaytarget(dt); - if (dri_sw_dt->data) { - FREE(dri_sw_dt->data); + if (dri_sw_dt->shmid >= 0) { +#ifdef HAVE_SYS_SHM_H + shmdt(dri_sw_dt->data); + shmctl(dri_sw_dt->shmid, IPC_RMID, 0); +#endif + } else { + align_free(dri_sw_dt->data); } FREE(dri_sw_dt); @@ -135,6 +189,12 @@ dri_sw_displaytarget_map(struct sw_winsys *ws, { struct dri_sw_displaytarget *dri_sw_dt = dri_sw_displaytarget(dt); dri_sw_dt->mapped = dri_sw_dt->data; + + if (dri_sw_dt->front_private && (flags & PIPE_TRANSFER_READ)) { + struct dri_sw_winsys *dri_sw_ws = dri_sw_winsys(ws); + dri_sw_ws->lf->get_image((void *)dri_sw_dt->front_private, 0, 0, dri_sw_dt->width, dri_sw_dt->height, dri_sw_dt->stride, dri_sw_dt->data); + } + dri_sw_dt->map_flags = flags; return dri_sw_dt->mapped; } @@ -143,6 +203,11 @@ dri_sw_displaytarget_unmap(struct sw_winsys *ws, struct sw_displaytarget *dt) { struct dri_sw_displaytarget *dri_sw_dt = dri_sw_displaytarget(dt); + if (dri_sw_dt->front_private && (dri_sw_dt->map_flags & PIPE_TRANSFER_WRITE)) { + struct dri_sw_winsys *dri_sw_ws = dri_sw_winsys(ws); + dri_sw_ws->lf->put_image2((void *)dri_sw_dt->front_private, dri_sw_dt->data, 0, 0, dri_sw_dt->width, dri_sw_dt->height, dri_sw_dt->stride); + } + dri_sw_dt->map_flags = 0; dri_sw_dt->mapped = NULL; } @@ -156,37 +221,71 @@ dri_sw_displaytarget_from_handle(struct sw_winsys *winsys, return NULL; } -static boolean +static bool dri_sw_displaytarget_get_handle(struct sw_winsys *winsys, struct sw_displaytarget *dt, struct winsys_handle *whandle) { - assert(0); - return FALSE; + struct dri_sw_displaytarget *dri_sw_dt = dri_sw_displaytarget(dt); + + if (whandle->type == WINSYS_HANDLE_TYPE_SHMID) { + if (dri_sw_dt->shmid < 0) + return false; + whandle->handle = dri_sw_dt->shmid; + return true; + } + + return false; } static void dri_sw_displaytarget_display(struct sw_winsys *ws, struct sw_displaytarget *dt, - void *context_private) + void *context_private, + struct pipe_box *box) { struct dri_sw_winsys *dri_sw_ws = dri_sw_winsys(ws); struct dri_sw_displaytarget *dri_sw_dt = dri_sw_displaytarget(dt); struct dri_drawable *dri_drawable = (struct dri_drawable *)context_private; - unsigned width, height; - + unsigned width, height, x = 0, y = 0; + unsigned blsize = util_format_get_blocksize(dri_sw_dt->format); + unsigned offset = 0; + unsigned offset_x = 0; + char *data = dri_sw_dt->data; + bool is_shm = dri_sw_dt->shmid != -1; /* Set the width to 'stride / cpp'. * * PutImage correctly clips to the width of the dst drawable. */ - width = dri_sw_dt->stride / util_format_get_blocksize(dri_sw_dt->format); + if (box) { + offset = dri_sw_dt->stride * box->y; + offset_x = box->x * blsize; + data += offset; + /* don't add x offset for shm, the put_image_shm will deal with it */ + if (!is_shm) + data += offset_x; + x = box->x; + y = box->y; + width = box->width; + height = box->height; + } else { + width = dri_sw_dt->stride / blsize; + height = dri_sw_dt->height; + } - height = dri_sw_dt->height; + if (is_shm) { + dri_sw_ws->lf->put_image_shm(dri_drawable, dri_sw_dt->shmid, dri_sw_dt->data, offset, offset_x, + x, y, width, height, dri_sw_dt->stride); + return; + } - dri_sw_ws->lf->put_image(dri_drawable, dri_sw_dt->data, width, height); + if (box) + dri_sw_ws->lf->put_image2(dri_drawable, data, + x, y, width, height, dri_sw_dt->stride); + else + dri_sw_ws->lf->put_image(dri_drawable, data, width, height); } - static void dri_destroy_sw_winsys(struct sw_winsys *winsys) { @@ -194,7 +293,7 @@ dri_destroy_sw_winsys(struct sw_winsys *winsys) } struct sw_winsys * -dri_create_sw_winsys(struct drisw_loader_funcs *lf) +dri_create_sw_winsys(const struct drisw_loader_funcs *lf) { struct dri_sw_winsys *ws;