drisw: use shared memory when possible

If drisw_loader_funcs implements put_image_shm, allocates display
target data with shared memory and display with put_image_shm().

Reviewed-by: Dave Airlie <airlied@redhat.com>
Reviewed-by: Adam Jackson <ajax@redhat.com>
This commit is contained in:
Marc-André Lureau 2015-06-10 17:45:11 +02:00 committed by Dave Airlie
parent 63c427fa71
commit cf54bd5e83

View file

@ -26,6 +26,9 @@
* *
**************************************************************************/ **************************************************************************/
#include <sys/ipc.h>
#include <sys/shm.h>
#include "pipe/p_compiler.h" #include "pipe/p_compiler.h"
#include "pipe/p_format.h" #include "pipe/p_format.h"
#include "util/u_inlines.h" #include "util/u_inlines.h"
@ -45,6 +48,7 @@ struct dri_sw_displaytarget
unsigned stride; unsigned stride;
unsigned map_flags; unsigned map_flags;
int shmid;
void *data; void *data;
void *mapped; void *mapped;
const void *front_private; const void *front_private;
@ -79,6 +83,25 @@ dri_sw_is_displaytarget_format_supported( struct sw_winsys *ws,
return TRUE; return TRUE;
} }
static char *
alloc_shm(struct dri_sw_displaytarget *dri_sw_dt, unsigned size)
{
char *addr;
dri_sw_dt->shmid = shmget(IPC_PRIVATE, size, IPC_CREAT|0777);
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;
}
static struct sw_displaytarget * static struct sw_displaytarget *
dri_sw_displaytarget_create(struct sw_winsys *winsys, dri_sw_displaytarget_create(struct sw_winsys *winsys,
unsigned tex_usage, unsigned tex_usage,
@ -88,6 +111,7 @@ dri_sw_displaytarget_create(struct sw_winsys *winsys,
const void *front_private, const void *front_private,
unsigned *stride) unsigned *stride)
{ {
struct dri_sw_winsys *ws = dri_sw_winsys(winsys);
struct dri_sw_displaytarget *dri_sw_dt; struct dri_sw_displaytarget *dri_sw_dt;
unsigned nblocksy, size, format_stride; unsigned nblocksy, size, format_stride;
@ -106,7 +130,13 @@ dri_sw_displaytarget_create(struct sw_winsys *winsys,
nblocksy = util_format_get_nblocksy(format, height); nblocksy = util_format_get_nblocksy(format, height);
size = dri_sw_dt->stride * nblocksy; size = dri_sw_dt->stride * nblocksy;
dri_sw_dt->data = align_malloc(size, alignment); dri_sw_dt->shmid = -1;
if (ws->lf->put_image_shm)
dri_sw_dt->data = alloc_shm(dri_sw_dt, size);
if(!dri_sw_dt->data)
dri_sw_dt->data = align_malloc(size, alignment);
if(!dri_sw_dt->data) if(!dri_sw_dt->data)
goto no_data; goto no_data;
@ -125,7 +155,12 @@ dri_sw_displaytarget_destroy(struct sw_winsys *ws,
{ {
struct dri_sw_displaytarget *dri_sw_dt = dri_sw_displaytarget(dt); struct dri_sw_displaytarget *dri_sw_dt = dri_sw_displaytarget(dt);
align_free(dri_sw_dt->data); if (dri_sw_dt->shmid >= 0) {
shmdt(dri_sw_dt->data);
shmctl(dri_sw_dt->shmid, IPC_RMID, 0);
} else {
align_free(dri_sw_dt->data);
}
FREE(dri_sw_dt); FREE(dri_sw_dt);
} }
@ -187,25 +222,38 @@ dri_sw_displaytarget_display(struct sw_winsys *ws,
struct dri_sw_winsys *dri_sw_ws = dri_sw_winsys(ws); struct dri_sw_winsys *dri_sw_ws = dri_sw_winsys(ws);
struct dri_sw_displaytarget *dri_sw_dt = dri_sw_displaytarget(dt); struct dri_sw_displaytarget *dri_sw_dt = dri_sw_displaytarget(dt);
struct dri_drawable *dri_drawable = (struct dri_drawable *)context_private; 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 blsize = util_format_get_blocksize(dri_sw_dt->format);
unsigned offset = 0;
void *data = dri_sw_dt->data;
/* Set the width to 'stride / cpp'. /* Set the width to 'stride / cpp'.
* *
* PutImage correctly clips to the width of the dst drawable. * PutImage correctly clips to the width of the dst drawable.
*/ */
width = dri_sw_dt->stride / blsize;
height = dri_sw_dt->height;
if (box) { if (box) {
void *data; offset = (dri_sw_dt->stride * box->y) + box->x * blsize;
data = (char *)dri_sw_dt->data + (dri_sw_dt->stride * box->y) + box->x * blsize; data += offset;
dri_sw_ws->lf->put_image2(dri_drawable, data, x = box->x;
box->x, box->y, box->width, box->height, dri_sw_dt->stride); y = box->y;
width = box->width;
height = box->height;
} else { } else {
dri_sw_ws->lf->put_image(dri_drawable, dri_sw_dt->data, width, height); width = dri_sw_dt->stride / blsize;
height = dri_sw_dt->height;
} }
if (dri_sw_dt->shmid != -1) {
dri_sw_ws->lf->put_image_shm(dri_drawable, dri_sw_dt->shmid, dri_sw_dt->data, offset,
x, y, width, height, dri_sw_dt->stride);
return;
}
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 static void