mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-05 05:18:08 +02:00
drisw/glx: use XShm if possible
Implements putImageShm from DRIswrastLoaderExtension. If XShm extension is not available, or fails, it will fallback on regular XPutImage(). Tested on Linux only with 16bpp and 32bpp visual. (airlied: tested on 24bpp as well) Reviewed-by: Dave Airlie <airlied@redhat.com> Reviewed-by: Adam Jackson <ajax@redhat.com>
This commit is contained in:
parent
cf54bd5e83
commit
bcd80be49a
2 changed files with 144 additions and 24 deletions
|
|
@ -28,10 +28,12 @@
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
#include "dri_common.h"
|
#include "dri_common.h"
|
||||||
#include "drisw_priv.h"
|
#include "drisw_priv.h"
|
||||||
|
#include <X11/extensions/shmproto.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
static Bool
|
static Bool
|
||||||
XCreateDrawable(struct drisw_drawable * pdp,
|
XCreateGCs(struct drisw_drawable * pdp,
|
||||||
Display * dpy, XID drawable, int visualid)
|
Display * dpy, XID drawable, int visualid)
|
||||||
{
|
{
|
||||||
XGCValues gcvalues;
|
XGCValues gcvalues;
|
||||||
long visMask;
|
long visMask;
|
||||||
|
|
@ -56,15 +58,78 @@ XCreateDrawable(struct drisw_drawable * pdp,
|
||||||
if (!pdp->visinfo || num_visuals == 0)
|
if (!pdp->visinfo || num_visuals == 0)
|
||||||
return False;
|
return False;
|
||||||
|
|
||||||
/* create XImage */
|
return True;
|
||||||
pdp->ximage = XCreateImage(dpy,
|
}
|
||||||
pdp->visinfo->visual,
|
|
||||||
pdp->visinfo->depth,
|
static int xshm_error = 0;
|
||||||
ZPixmap, 0, /* format, offset */
|
static int xshm_opcode = -1;
|
||||||
NULL, /* data */
|
|
||||||
0, 0, /* width, height */
|
/**
|
||||||
32, /* bitmap_pad */
|
* Catches potential Xlib errors.
|
||||||
0); /* bytes_per_line */
|
*/
|
||||||
|
static int
|
||||||
|
handle_xerror(Display *dpy, XErrorEvent *event)
|
||||||
|
{
|
||||||
|
(void) dpy;
|
||||||
|
|
||||||
|
assert(xshm_opcode != -1);
|
||||||
|
if (event->request_code != xshm_opcode ||
|
||||||
|
event->minor_code != X_ShmAttach)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
xshm_error = 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Bool
|
||||||
|
XCreateDrawable(struct drisw_drawable * pdp, int shmid, Display * dpy)
|
||||||
|
{
|
||||||
|
if (pdp->ximage) {
|
||||||
|
XDestroyImage(pdp->ximage);
|
||||||
|
pdp->ximage = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!xshm_error && shmid >= 0) {
|
||||||
|
pdp->shminfo.shmid = shmid;
|
||||||
|
pdp->ximage = XShmCreateImage(dpy,
|
||||||
|
pdp->visinfo->visual,
|
||||||
|
pdp->visinfo->depth,
|
||||||
|
ZPixmap, /* format */
|
||||||
|
NULL, /* data */
|
||||||
|
&pdp->shminfo, /* shminfo */
|
||||||
|
0, 0); /* width, height */
|
||||||
|
if (pdp->ximage != NULL) {
|
||||||
|
int (*old_handler)(Display *, XErrorEvent *);
|
||||||
|
|
||||||
|
/* dispatch pending errors */
|
||||||
|
XSync(dpy, False);
|
||||||
|
|
||||||
|
old_handler = XSetErrorHandler(handle_xerror);
|
||||||
|
/* This may trigger the X protocol error we're ready to catch: */
|
||||||
|
XShmAttach(dpy, &pdp->shminfo);
|
||||||
|
XSync(dpy, False);
|
||||||
|
|
||||||
|
if (xshm_error) {
|
||||||
|
/* we are on a remote display, this error is normal, don't print it */
|
||||||
|
XDestroyImage(pdp->ximage);
|
||||||
|
pdp->ximage = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
(void) XSetErrorHandler(old_handler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pdp->ximage == NULL) {
|
||||||
|
pdp->shminfo.shmid = -1;
|
||||||
|
pdp->ximage = XCreateImage(dpy,
|
||||||
|
pdp->visinfo->visual,
|
||||||
|
pdp->visinfo->depth,
|
||||||
|
ZPixmap, 0, /* format, offset */
|
||||||
|
NULL, /* data */
|
||||||
|
0, 0, /* width, height */
|
||||||
|
32, /* bitmap_pad */
|
||||||
|
0); /* bytes_per_line */
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* swrast does not handle 24-bit depth with 24 bpp, so let X do the
|
* swrast does not handle 24-bit depth with 24 bpp, so let X do the
|
||||||
|
|
@ -79,7 +144,9 @@ XCreateDrawable(struct drisw_drawable * pdp,
|
||||||
static void
|
static void
|
||||||
XDestroyDrawable(struct drisw_drawable * pdp, Display * dpy, XID drawable)
|
XDestroyDrawable(struct drisw_drawable * pdp, Display * dpy, XID drawable)
|
||||||
{
|
{
|
||||||
XDestroyImage(pdp->ximage);
|
if (pdp->ximage)
|
||||||
|
XDestroyImage(pdp->ximage);
|
||||||
|
|
||||||
free(pdp->visinfo);
|
free(pdp->visinfo);
|
||||||
|
|
||||||
XFreeGC(dpy, pdp->gc);
|
XFreeGC(dpy, pdp->gc);
|
||||||
|
|
@ -133,9 +200,9 @@ bytes_per_line(unsigned pitch_bits, unsigned mul)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
swrastPutImage2(__DRIdrawable * draw, int op,
|
swrastXPutImage(__DRIdrawable * draw, int op,
|
||||||
int x, int y, int w, int h, int stride,
|
int x, int y, int w, int h, int stride,
|
||||||
char *data, void *loaderPrivate)
|
int shmid, char *data, void *loaderPrivate)
|
||||||
{
|
{
|
||||||
struct drisw_drawable *pdp = loaderPrivate;
|
struct drisw_drawable *pdp = loaderPrivate;
|
||||||
__GLXDRIdrawable *pdraw = &(pdp->base);
|
__GLXDRIdrawable *pdraw = &(pdp->base);
|
||||||
|
|
@ -144,6 +211,11 @@ swrastPutImage2(__DRIdrawable * draw, int op,
|
||||||
XImage *ximage;
|
XImage *ximage;
|
||||||
GC gc;
|
GC gc;
|
||||||
|
|
||||||
|
if (!pdp->ximage || shmid != pdp->shminfo.shmid) {
|
||||||
|
if (!XCreateDrawable(pdp, shmid, dpy))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case __DRI_SWRAST_IMAGE_OP_DRAW:
|
case __DRI_SWRAST_IMAGE_OP_DRAW:
|
||||||
gc = pdp->gc;
|
gc = pdp->gc;
|
||||||
|
|
@ -156,24 +228,52 @@ swrastPutImage2(__DRIdrawable * draw, int op,
|
||||||
}
|
}
|
||||||
|
|
||||||
drawable = pdraw->xDrawable;
|
drawable = pdraw->xDrawable;
|
||||||
|
|
||||||
ximage = pdp->ximage;
|
ximage = pdp->ximage;
|
||||||
ximage->data = data;
|
|
||||||
ximage->width = w;
|
|
||||||
ximage->height = h;
|
|
||||||
ximage->bytes_per_line = stride ? stride : bytes_per_line(w * ximage->bits_per_pixel, 32);
|
ximage->bytes_per_line = stride ? stride : bytes_per_line(w * ximage->bits_per_pixel, 32);
|
||||||
|
ximage->data = data;
|
||||||
|
|
||||||
XPutImage(dpy, drawable, gc, ximage, 0, 0, x, y, w, h);
|
if (pdp->shminfo.shmid >= 0) {
|
||||||
|
ximage->width = ximage->bytes_per_line / ((ximage->bits_per_pixel + 7)/ 8);
|
||||||
|
ximage->height = h;
|
||||||
|
XShmPutImage(dpy, drawable, gc, ximage, 0, 0, x, y, w, h, False);
|
||||||
|
XSync(dpy, False);
|
||||||
|
} else {
|
||||||
|
ximage->width = w;
|
||||||
|
ximage->height = h;
|
||||||
|
XPutImage(dpy, drawable, gc, ximage, 0, 0, x, y, w, h);
|
||||||
|
}
|
||||||
ximage->data = NULL;
|
ximage->data = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
swrastPutImageShm(__DRIdrawable * draw, int op,
|
||||||
|
int x, int y, int w, int h, int stride,
|
||||||
|
int shmid, char *shmaddr, unsigned offset,
|
||||||
|
void *loaderPrivate)
|
||||||
|
{
|
||||||
|
struct drisw_drawable *pdp = loaderPrivate;
|
||||||
|
|
||||||
|
pdp->shminfo.shmaddr = shmaddr;
|
||||||
|
swrastXPutImage(draw, op, x, y, w, h, stride, shmid,
|
||||||
|
shmaddr + offset, loaderPrivate);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
swrastPutImage2(__DRIdrawable * draw, int op,
|
||||||
|
int x, int y, int w, int h, int stride,
|
||||||
|
char *data, void *loaderPrivate)
|
||||||
|
{
|
||||||
|
swrastXPutImage(draw, op, x, y, w, h, stride, -1,
|
||||||
|
data, loaderPrivate);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
swrastPutImage(__DRIdrawable * draw, int op,
|
swrastPutImage(__DRIdrawable * draw, int op,
|
||||||
int x, int y, int w, int h,
|
int x, int y, int w, int h,
|
||||||
char *data, void *loaderPrivate)
|
char *data, void *loaderPrivate)
|
||||||
{
|
{
|
||||||
swrastPutImage2(draw, op, x, y, w, h, 0, data, loaderPrivate);
|
swrastXPutImage(draw, op, x, y, w, h, 0, -1,
|
||||||
|
data, loaderPrivate);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -187,6 +287,11 @@ swrastGetImage2(__DRIdrawable * read,
|
||||||
Drawable readable;
|
Drawable readable;
|
||||||
XImage *ximage;
|
XImage *ximage;
|
||||||
|
|
||||||
|
if (!prp->ximage || prp->shminfo.shmid >= 0) {
|
||||||
|
if (!XCreateDrawable(prp, -1, dpy))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
readable = pread->xDrawable;
|
readable = pread->xDrawable;
|
||||||
|
|
||||||
ximage = prp->ximage;
|
ximage = prp->ximage;
|
||||||
|
|
@ -208,14 +313,15 @@ swrastGetImage(__DRIdrawable * read,
|
||||||
swrastGetImage2(read, x, y, w, h, 0, data, loaderPrivate);
|
swrastGetImage2(read, x, y, w, h, 0, data, loaderPrivate);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const __DRIswrastLoaderExtension swrastLoaderExtension = {
|
static __DRIswrastLoaderExtension swrastLoaderExtension = {
|
||||||
.base = {__DRI_SWRAST_LOADER, 3 },
|
.base = {__DRI_SWRAST_LOADER, 4 },
|
||||||
|
|
||||||
.getDrawableInfo = swrastGetDrawableInfo,
|
.getDrawableInfo = swrastGetDrawableInfo,
|
||||||
.putImage = swrastPutImage,
|
.putImage = swrastPutImage,
|
||||||
.getImage = swrastGetImage,
|
.getImage = swrastGetImage,
|
||||||
.putImage2 = swrastPutImage2,
|
.putImage2 = swrastPutImage2,
|
||||||
.getImage2 = swrastGetImage2,
|
.getImage2 = swrastGetImage2,
|
||||||
|
.putImageShm = swrastPutImageShm,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const __DRIextension *loader_extensions[] = {
|
static const __DRIextension *loader_extensions[] = {
|
||||||
|
|
@ -527,7 +633,7 @@ driswCreateDrawable(struct glx_screen *base, XID xDrawable,
|
||||||
pdp->base.drawable = drawable;
|
pdp->base.drawable = drawable;
|
||||||
pdp->base.psc = &psc->base;
|
pdp->base.psc = &psc->base;
|
||||||
|
|
||||||
ret = XCreateDrawable(pdp, psc->base.dpy, xDrawable, modes->visualID);
|
ret = XCreateGCs(pdp, psc->base.dpy, xDrawable, modes->visualID);
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
free(pdp);
|
free(pdp);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
@ -661,6 +767,14 @@ driswBindExtensions(struct drisw_screen *psc, const __DRIextension **extensions)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
check_xshm(Display *dpy)
|
||||||
|
{
|
||||||
|
int ignore;
|
||||||
|
|
||||||
|
return XQueryExtension(dpy, "MIT-SHM", &xshm_opcode, &ignore, &ignore);
|
||||||
|
}
|
||||||
|
|
||||||
static struct glx_screen *
|
static struct glx_screen *
|
||||||
driswCreateScreen(int screen, struct glx_display *priv)
|
driswCreateScreen(int screen, struct glx_display *priv)
|
||||||
{
|
{
|
||||||
|
|
@ -688,6 +802,9 @@ driswCreateScreen(int screen, struct glx_display *priv)
|
||||||
if (extensions == NULL)
|
if (extensions == NULL)
|
||||||
goto handle_error;
|
goto handle_error;
|
||||||
|
|
||||||
|
if (!check_xshm(psc->base.dpy))
|
||||||
|
swrastLoaderExtension.putImageShm = NULL;
|
||||||
|
|
||||||
for (i = 0; extensions[i]; i++) {
|
for (i = 0; extensions[i]; i++) {
|
||||||
if (strcmp(extensions[i]->name, __DRI_CORE) == 0)
|
if (strcmp(extensions[i]->name, __DRI_CORE) == 0)
|
||||||
psc->core = (__DRIcoreExtension *) extensions[i];
|
psc->core = (__DRIcoreExtension *) extensions[i];
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,8 @@
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <X11/extensions/XShm.h>
|
||||||
|
|
||||||
struct drisw_display
|
struct drisw_display
|
||||||
{
|
{
|
||||||
__GLXDRIdisplay base;
|
__GLXDRIdisplay base;
|
||||||
|
|
@ -62,6 +64,7 @@ struct drisw_drawable
|
||||||
__DRIdrawable *driDrawable;
|
__DRIdrawable *driDrawable;
|
||||||
XVisualInfo *visinfo;
|
XVisualInfo *visinfo;
|
||||||
XImage *ximage;
|
XImage *ximage;
|
||||||
|
XShmSegmentInfo shminfo;
|
||||||
};
|
};
|
||||||
|
|
||||||
_X_HIDDEN int
|
_X_HIDDEN int
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue