diff options
author | Kristian Høgsberg <[email protected]> | 2008-03-26 19:26:59 -0400 |
---|---|---|
committer | Kristian Høgsberg <[email protected]> | 2008-03-31 16:51:26 -0400 |
commit | e82dd8c6e1fa2fff5b960de26961080ba5e9651d (patch) | |
tree | 1bd230661a032b1ab539998f947573de1acaf80d /src/glx | |
parent | 63d8a8417d68365cd10c11178516378411c09f87 (diff) |
DRI interface changes and DRI2 direct rendering support.
Add DRI2 direct rendering support to libGL and add DRI2 client side
protocol code. Extend the GLX 1.3 create drawable functions in
glx_pbuffer.c to call into the DRI driver when possible.
Introduce __DRIconfig, opaque struct that represents a DRI driver
configuration. Get's rid of the open coded __GLcontextModes in the
DRI driver interface and the context modes create and destroy
functions that the loader was requires to provide. glcore.h is no
longer part of the DRI driver interface. The DRI config is GL binding
agnostic, that is, not specific to GLX, EGL or other bindings.
The core API is now also an extension, and the driver exports a list
of extensions as the symbol __driDriverExtensions, which the loader
must dlsym() for. The list of extension will always include the DRI
core extension, which allows creating and manipulating DRI screens,
drawables and contexts. The DRI legacy extension, when available,
provides alternative entry points for creating the DRI objects that
work with the XF86DRI infrastructure.
Change DRI2 client code to not use drm drawables or contexts. We
never used drm_drawable_t's and the only use for drm_context_t was as
a unique identifier when taking the lock. We now just allocate a
unique lock ID out of the DRILock sarea block. Once we get rid of the
lock entirely, we can drop this hack.
Change the interface between dri_util.c and the drivers, so that the
drivers now export the DriverAPI struct as driDriverAPI instead of the
InitScreen entry point. This lets us avoid dlsym()'ing for the DRI2
init screen function to see if DRI2 is supported by the driver.
Diffstat (limited to 'src/glx')
-rw-r--r-- | src/glx/x11/Makefile | 5 | ||||
-rw-r--r-- | src/glx/x11/dri2.c | 252 | ||||
-rw-r--r-- | src/glx/x11/dri2.h | 53 | ||||
-rw-r--r-- | src/glx/x11/dri2_glx.c | 471 | ||||
-rw-r--r-- | src/glx/x11/dri_glx.c | 398 | ||||
-rw-r--r-- | src/glx/x11/glx_pbuffer.c | 70 | ||||
-rw-r--r-- | src/glx/x11/glxclient.h | 38 | ||||
-rw-r--r-- | src/glx/x11/glxcmds.c | 140 | ||||
-rw-r--r-- | src/glx/x11/glxext.c | 66 | ||||
-rw-r--r-- | src/glx/x11/glxextensions.c | 62 | ||||
-rw-r--r-- | src/glx/x11/glxextensions.h | 6 |
11 files changed, 1305 insertions, 256 deletions
diff --git a/src/glx/x11/Makefile b/src/glx/x11/Makefile index 8fa3700a04c..2d44e8df7a1 100644 --- a/src/glx/x11/Makefile +++ b/src/glx/x11/Makefile @@ -32,7 +32,9 @@ SOURCES = \ glx_texture_compression.c \ dri_glx.c \ XF86dri.c \ - glxhash.c + glxhash.c \ + dri2_glx.c \ + dri2.c include $(TOP)/src/mesa/sources @@ -48,6 +50,7 @@ INCLUDES = -I. \ -I$(TOP)/src/mesa/main \ -I$(TOP)/src/mesa/glapi \ $(LIBDRM_CFLAGS) \ + $(DRI2PROTO_CFLAGS) \ $(X11_INCLUDES) diff --git a/src/glx/x11/dri2.c b/src/glx/x11/dri2.c new file mode 100644 index 00000000000..c3012c4e5fb --- /dev/null +++ b/src/glx/x11/dri2.c @@ -0,0 +1,252 @@ +/* + * Copyright © 2008 Red Hat, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Soft- + * ware"), to deal in the Software without restriction, including without + * limitation the rights to use, copy, modify, merge, publish, distribute, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, provided that the above copyright + * notice(s) and this permission notice appear in all copies of the Soft- + * ware and that both the above copyright notice(s) and this permission + * notice appear in supporting documentation. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- + * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY + * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN + * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE- + * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR- + * MANCE OF THIS SOFTWARE. + * + * Except as contained in this notice, the name of a copyright holder shall + * not be used in advertising or otherwise to promote the sale, use or + * other dealings in this Software without prior written authorization of + * the copyright holder. + * + * Authors: + * Kristian Høgsberg ([email protected]) + */ + + +#define NEED_REPLIES +#include <X11/Xlibint.h> +#include <X11/extensions/Xext.h> +#include <X11/extensions/extutil.h> +#include "glheader.h" +#include "xf86drm.h" +#include "dri2proto.h" +#include "dri2.h" + +static char dri2ExtensionName[] = DRI2_NAME; +static XExtensionInfo *dri2Info; +static XEXT_GENERATE_CLOSE_DISPLAY (DRI2CloseDisplay, dri2Info) +static /* const */ XExtensionHooks dri2ExtensionHooks = { + NULL, /* create_gc */ + NULL, /* copy_gc */ + NULL, /* flush_gc */ + NULL, /* free_gc */ + NULL, /* create_font */ + NULL, /* free_font */ + DRI2CloseDisplay, /* close_display */ + NULL, /* wire_to_event */ + NULL, /* event_to_wire */ + NULL, /* error */ + NULL, /* error_string */ +}; + +static XEXT_GENERATE_FIND_DISPLAY (DRI2FindDisplay, dri2Info, + dri2ExtensionName, + &dri2ExtensionHooks, + 0, NULL) + +Bool DRI2QueryExtension(Display *dpy, int *eventBase, int *errorBase) +{ + XExtDisplayInfo *info = DRI2FindDisplay(dpy); + + if (XextHasExtension(info)) { + *eventBase = info->codes->first_event; + *errorBase = info->codes->first_error; + return True; + } + + return False; +} + +Bool DRI2QueryVersion(Display *dpy, int *major, int *minor) +{ + XExtDisplayInfo *info = DRI2FindDisplay (dpy); + xDRI2QueryVersionReply rep; + xDRI2QueryVersionReq *req; + + XextCheckExtension (dpy, info, dri2ExtensionName, False); + + LockDisplay(dpy); + GetReq(DRI2QueryVersion, req); + req->reqType = info->codes->major_opcode; + req->dri2ReqType = X_DRI2QueryVersion; + req->majorVersion = DRI2_MAJOR; + req->minorVersion = DRI2_MINOR; + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + *major = rep.majorVersion; + *minor = rep.minorVersion; + UnlockDisplay(dpy); + SyncHandle(); + + return True; +} + +Bool DRI2Connect(Display *dpy, int screen, + char **driverName, char **busId, unsigned int *sareaHandle) +{ + XExtDisplayInfo *info = DRI2FindDisplay(dpy); + xDRI2ConnectReply rep; + xDRI2ConnectReq *req; + + XextCheckExtension (dpy, info, dri2ExtensionName, False); + + LockDisplay(dpy); + GetReq(DRI2Connect, req); + req->reqType = info->codes->major_opcode; + req->dri2ReqType = X_DRI2Connect; + req->screen = screen; + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + + *sareaHandle = rep.sareaHandle; + + *driverName = Xmalloc(rep.driverNameLength + 1); + if (*driverName == NULL) { + _XEatData(dpy, + ((rep.driverNameLength + 3) & ~3) + + ((rep.busIdLength + 3) & ~3)); + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + _XReadPad(dpy, *driverName, rep.driverNameLength); + (*driverName)[rep.driverNameLength] = '\0'; + + *busId = Xmalloc(rep.busIdLength + 1); + if (*busId == NULL) { + Xfree(*driverName); + _XEatData(dpy, ((rep.busIdLength + 3) & ~3)); + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + _XReadPad(dpy, *busId, rep.busIdLength); + (*busId)[rep.busIdLength] = '\0'; + + UnlockDisplay(dpy); + SyncHandle(); + + return rep.sareaHandle != 0; +} + +Bool DRI2AuthConnection(Display *dpy, int screen, drm_magic_t magic) +{ + XExtDisplayInfo *info = DRI2FindDisplay(dpy); + xDRI2AuthConnectionReq *req; + xDRI2AuthConnectionReply rep; + + XextCheckExtension (dpy, info, dri2ExtensionName, False); + + LockDisplay(dpy); + GetReq(DRI2AuthConnection, req); + req->reqType = info->codes->major_opcode; + req->dri2ReqType = X_DRI2AuthConnection; + req->screen = screen; + req->magic = magic; + rep.authenticated = 0; + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + UnlockDisplay(dpy); + SyncHandle(); + + return rep.authenticated; +} + +Bool DRI2CreateDrawable(Display *dpy, XID drawable, + unsigned int *handle, unsigned int *head) +{ + XExtDisplayInfo *info = DRI2FindDisplay(dpy); + xDRI2CreateDrawableReply rep; + xDRI2CreateDrawableReq *req; + + XextCheckExtension (dpy, info, dri2ExtensionName, False); + + LockDisplay(dpy); + GetReq(DRI2CreateDrawable, req); + req->reqType = info->codes->major_opcode; + req->dri2ReqType = X_DRI2CreateDrawable; + req->drawable = drawable; + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + UnlockDisplay(dpy); + SyncHandle(); + + *handle = rep.handle; + *head = rep.head; + + return True; +} + +void DRI2DestroyDrawable(Display *dpy, XID drawable) +{ + XExtDisplayInfo *info = DRI2FindDisplay(dpy); + xDRI2DestroyDrawableReq *req; + + XextSimpleCheckExtension (dpy, info, dri2ExtensionName); + + XSync(dpy, GL_FALSE); + + LockDisplay(dpy); + GetReq(DRI2DestroyDrawable, req); + req->reqType = info->codes->major_opcode; + req->dri2ReqType = X_DRI2DestroyDrawable; + req->drawable = drawable; + UnlockDisplay(dpy); + SyncHandle(); +} + +Bool DRI2ReemitDrawableInfo(Display *dpy, XID drawable, unsigned int *head) +{ + XExtDisplayInfo *info = DRI2FindDisplay(dpy); + xDRI2ReemitDrawableInfoReply rep; + xDRI2ReemitDrawableInfoReq *req; + + XextCheckExtension (dpy, info, dri2ExtensionName, False); + + LockDisplay(dpy); + GetReq(DRI2ReemitDrawableInfo, req); + req->reqType = info->codes->major_opcode; + req->dri2ReqType = X_DRI2ReemitDrawableInfo; + req->drawable = drawable; + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + UnlockDisplay(dpy); + SyncHandle(); + + *head = rep.head; + + return True; +} diff --git a/src/glx/x11/dri2.h b/src/glx/x11/dri2.h new file mode 100644 index 00000000000..1dfd0448b2f --- /dev/null +++ b/src/glx/x11/dri2.h @@ -0,0 +1,53 @@ +/* + * Copyright © 2007,2008 Red Hat, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Soft- + * ware"), to deal in the Software without restriction, including without + * limitation the rights to use, copy, modify, merge, publish, distribute, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, provided that the above copyright + * notice(s) and this permission notice appear in all copies of the Soft- + * ware and that both the above copyright notice(s) and this permission + * notice appear in supporting documentation. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- + * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY + * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN + * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE- + * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR- + * MANCE OF THIS SOFTWARE. + * + * Except as contained in this notice, the name of a copyright holder shall + * not be used in advertising or otherwise to promote the sale, use or + * other dealings in this Software without prior written authorization of + * the copyright holder. + * + * Authors: + * Kristian Høgsberg ([email protected]) + */ + +#ifndef _DRI2_H_ +#define _DRI2_H_ + +extern Bool +DRI2QueryExtension(Display *display, int *eventBase, int *errorBase); +extern Bool +DRI2QueryVersion(Display *display, int *major, int *minor); +extern Bool +DRI2Connect(Display *display, int screen, + char **driverName, char **busId, unsigned int *sareaHandle); +extern Bool +DRI2AuthConnection(Display *display, int screen, drm_magic_t magic); +extern Bool +DRI2CreateDrawable(Display *display, XID drawable, + unsigned int *handle, unsigned int *head); +extern void +DRI2DestroyDrawable(Display *display, XID handle); +extern Bool +DRI2ReemitDrawableInfo(Display *dpy, XID handle, unsigned int *head); + +#endif diff --git a/src/glx/x11/dri2_glx.c b/src/glx/x11/dri2_glx.c new file mode 100644 index 00000000000..1a6abaedab8 --- /dev/null +++ b/src/glx/x11/dri2_glx.c @@ -0,0 +1,471 @@ +/* + * Copyright © 2008 Red Hat, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Soft- + * ware"), to deal in the Software without restriction, including without + * limitation the rights to use, copy, modify, merge, publish, distribute, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, provided that the above copyright + * notice(s) and this permission notice appear in all copies of the Soft- + * ware and that both the above copyright notice(s) and this permission + * notice appear in supporting documentation. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- + * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY + * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN + * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE- + * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR- + * MANCE OF THIS SOFTWARE. + * + * Except as contained in this notice, the name of a copyright holder shall + * not be used in advertising or otherwise to promote the sale, use or + * other dealings in this Software without prior written authorization of + * the copyright holder. + * + * Authors: + * Kristian Høgsberg ([email protected]) + */ + +#ifdef GLX_DIRECT_RENDERING + +#include <unistd.h> +#include <X11/Xlibint.h> +#include <X11/extensions/Xext.h> +#include <X11/extensions/extutil.h> +#include <X11/extensions/Xfixes.h> +#include <X11/extensions/Xdamage.h> +#include "glheader.h" +#include "glxclient.h" +#include "xf86dri.h" +#include "sarea.h" +#include <stdio.h> +#include <dlfcn.h> +#include <sys/types.h> +#include <stdarg.h> +#include "glcontextmodes.h" +#include <sys/mman.h> +#include "xf86drm.h" +#include "dri2.h" + + +#ifndef RTLD_NOW +#define RTLD_NOW 0 +#endif +#ifndef RTLD_GLOBAL +#define RTLD_GLOBAL 0 +#endif + +typedef struct __GLXDRIdisplayPrivateRec __GLXDRIdisplayPrivate; +typedef struct __GLXDRIcontextPrivateRec __GLXDRIcontextPrivate; +typedef struct __GLXDRIconfigPrivateRec __GLXDRIconfigPrivate; + +struct __GLXDRIdisplayPrivateRec { + __GLXDRIdisplay base; + + /* + ** XFree86-DRI version information + */ + int driMajor; + int driMinor; + int driPatch; +}; + +struct __GLXDRIcontextPrivateRec { + __GLXDRIcontext base; + __DRIcontext *driContext; + __GLXscreenConfigs *psc; +}; + +struct __GLXDRIconfigPrivateRec { + __GLcontextModes modes; + const __DRIconfig *driConfig; +}; + +static void dri2DestroyContext(__GLXDRIcontext *context, + __GLXscreenConfigs *psc, Display *dpy) +{ + __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context; + const __DRIcoreExtension *core = pcp->psc->core; + + (*core->destroyContext)(pcp->driContext); + + Xfree(pcp); +} + +static Bool dri2BindContext(__GLXDRIcontext *context, + __GLXDRIdrawable *draw, __GLXDRIdrawable *read) +{ + __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context; + const __DRIcoreExtension *core = pcp->psc->core; + + return (*core->bindContext)(pcp->driContext, + draw->driDrawable, + read->driDrawable); +} + +static void dri2UnbindContext(__GLXDRIcontext *context) +{ + __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context; + const __DRIcoreExtension *core = pcp->psc->core; + + (*core->unbindContext)(pcp->driContext); +} + +static __GLXDRIcontext *dri2CreateContext(__GLXscreenConfigs *psc, + const __GLcontextModes *mode, + GLXContext gc, + GLXContext shareList, int renderType) +{ + __GLXDRIcontextPrivate *pcp, *pcp_shared; + __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) mode; + const __DRIcoreExtension *core = psc->core; + __DRIcontext *shared = NULL; + + if (shareList) { + pcp_shared = (__GLXDRIcontextPrivate *) shareList->driContext; + shared = pcp_shared->driContext; + } + + pcp = Xmalloc(sizeof *pcp); + if (pcp == NULL) + return NULL; + + pcp->psc = psc; + pcp->driContext = + (*core->createNewContext)(psc->__driScreen, + config->driConfig, shared, pcp); + gc->__driContext = pcp->driContext; + + if (pcp->driContext == NULL) { + Xfree(pcp); + return NULL; + } + + pcp->base.destroyContext = dri2DestroyContext; + pcp->base.bindContext = dri2BindContext; + pcp->base.unbindContext = dri2UnbindContext; + + return &pcp->base; +} + +static void dri2DestroyDrawable(__GLXDRIdrawable *pdraw) +{ + const __DRIcoreExtension *core = pdraw->psc->core; + + (*core->destroyDrawable)(pdraw->driDrawable); + DRI2DestroyDrawable(pdraw->psc->dpy, pdraw->drawable); + Xfree(pdraw); +} + +static __GLXDRIdrawable *dri2CreateDrawable(__GLXscreenConfigs *psc, + XID xDrawable, + GLXDrawable drawable, + const __GLcontextModes *modes) +{ + __GLXDRIdrawable *pdraw; + __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) modes; + unsigned int handle, head; + const __DRIcoreExtension *core = psc->core; + + pdraw = Xmalloc(sizeof(*pdraw)); + if (!pdraw) + return NULL; + + pdraw->destroyDrawable = dri2DestroyDrawable; + pdraw->xDrawable = xDrawable; + pdraw->drawable = drawable; + pdraw->psc = psc; + + fprintf(stderr, "calling DRI2CreateDrawable, XID 0x%lx, GLX ID 0x%lx\n", + xDrawable, drawable); + + if (!DRI2CreateDrawable(psc->dpy, xDrawable, &handle, &head)) { + Xfree(pdraw); + return NULL; + } + + fprintf(stderr, "success, head 0x%x, handle 0x%x\n", head, handle); + + /* Create a new drawable */ + pdraw->driDrawable = + (*core->createNewDrawable)(psc->__driScreen, + config->driConfig, + handle, + head, + pdraw); + + if (!pdraw->driDrawable) { + DRI2DestroyDrawable(psc->dpy, drawable); + Xfree(pdraw); + return NULL; + } + + return pdraw; +} + +static void dri2DestroyScreen(__GLXscreenConfigs *psc) +{ + /* Free the direct rendering per screen data */ + (*psc->core->destroyScreen)(psc->__driScreen); + drmClose(psc->fd); + psc->__driScreen = NULL; +} + + +static void dri2ReemitDrawableInfo(__DRIdrawable *draw, unsigned int *tail, + void *loaderPrivate) +{ + __GLXDRIdrawable *pdraw = loaderPrivate; + + DRI2ReemitDrawableInfo(pdraw->psc->dpy, pdraw->drawable, tail); +} + +static void dri2PostDamage(__DRIdrawable *draw, + struct drm_clip_rect *rects, + int numRects, void *loaderPrivate) +{ + XRectangle *xrects; + XserverRegion region; + __GLXDRIdrawable *glxDraw = loaderPrivate; + __GLXscreenConfigs *psc = glxDraw->psc; + Display *dpy = psc->dpy; + int i; + + xrects = malloc(sizeof(XRectangle) * numRects); + if (xrects == NULL) + return; + + for (i = 0; i < numRects; i++) { + xrects[i].x = rects[i].x1; + xrects[i].y = rects[i].y1; + xrects[i].width = rects[i].x2 - rects[i].x1; + xrects[i].height = rects[i].y2 - rects[i].y1; + } + region = XFixesCreateRegion(dpy, xrects, numRects); + free(xrects); + XDamageAdd(dpy, glxDraw->xDrawable, region); + XFixesDestroyRegion(dpy, region); +} + +static const __DRIloaderExtension dri2LoaderExtension = { + { __DRI_LOADER, __DRI_LOADER_VERSION }, + dri2ReemitDrawableInfo, + dri2PostDamage +}; + +_X_HIDDEN const __DRIsystemTimeExtension systemTimeExtension; + +static const __DRIextension *loader_extensions[] = { + &dri2LoaderExtension.base, + &systemTimeExtension.base, + NULL +}; + +/* We need a dri_common.h type-of-thing. */ + +extern void ErrorMessageF(const char *f, ...); + +extern void *driOpenDriver(const char *driverName); + +extern __GLcontextModes * +driConvertConfigs(const __DRIcoreExtension *core, + __GLcontextModes *modes, const __DRIconfig **configs); + +extern void driBindExtensions(__GLXscreenConfigs *psc); + +void +driBindExtensions(__GLXscreenConfigs *psc) +{ + const __DRIextension **extensions; + int i; + + extensions = psc->core->getExtensions(psc->__driScreen); + + for (i = 0; extensions[i]; i++) { +#ifdef __DRI_COPY_SUB_BUFFER + if (strcmp(extensions[i]->name, __DRI_COPY_SUB_BUFFER) == 0) { + psc->copySubBuffer = (__DRIcopySubBufferExtension *) extensions[i]; + __glXEnableDirectExtension(psc, "GLX_MESA_copy_sub_buffer_bit"); + } +#endif + +#ifdef __DRI_SWAP_CONTROL + if (strcmp(extensions[i]->name, __DRI_SWAP_CONTROL) == 0) { + psc->swapControl = (__DRIswapControlExtension *) extensions[i]; + __glXEnableDirectExtension(psc, "GLX_SGI_swap_control"); + __glXEnableDirectExtension(psc, "GLX_MESA_swap_control"); + } +#endif + +#ifdef __DRI_ALLOCATE + if (strcmp(extensions[i]->name, __DRI_ALLOCATE) == 0) { + psc->allocate = (__DRIallocateExtension *) extensions[i]; + __glXEnableDirectExtension(psc, "GLX_MESA_allocate_memory"); + } +#endif + +#ifdef __DRI_FRAME_TRACKING + if (strcmp(extensions[i]->name, __DRI_FRAME_TRACKING) == 0) { + psc->frameTracking = (__DRIframeTrackingExtension *) extensions[i]; + __glXEnableDirectExtension(psc, "GLX_MESA_swap_frame_usage"); + } +#endif + +#ifdef __DRI_MEDIA_STREAM_COUNTER + if (strcmp(extensions[i]->name, __DRI_MEDIA_STREAM_COUNTER) == 0) { + psc->msc = (__DRImediaStreamCounterExtension *) extensions[i]; + __glXEnableDirectExtension(psc, "GLX_SGI_video_sync"); + } +#endif + +#ifdef __DRI_SWAP_BUFFER_COUNTER + /* No driver supports this at this time and the extension is + * not defined in dri_interface.h. Will enable + * GLX_OML_sync_control if implemented. */ +#endif + +#ifdef __DRI_READ_DRAWABLE + if (strcmp(extensions[i]->name, __DRI_READ_DRAWABLE) == 0) { + __glXEnableDirectExtension(psc, "GLX_SGI_make_current_read"); + } +#endif + +#ifdef __DRI_TEX_BUFFER + if (strcmp(extensions[i]->name, __DRI_TEX_BUFFER) == 0) { + psc->texBuffer = (__DRItexBufferExtension *) extensions[i]; + __glXEnableDirectExtension(psc, "GLX_EXT_texture_from_pixmap"); + } +#endif + + /* Ignore unknown extensions */ + } +} + +static __GLXDRIscreen *dri2CreateScreen(__GLXscreenConfigs *psc, int screen, + __GLXdisplayPrivate *priv) +{ + const __DRIconfig **driver_configs; + const __DRIextension **extensions; + __GLXDRIscreen *psp; + unsigned int sareaHandle; + char *driverName, *busID; + drm_magic_t magic; + int i; + + psp = Xmalloc(sizeof *psp); + if (psp == NULL) + return NULL; + + /* Initialize per screen dynamic client GLX extensions */ + psc->ext_list_first_time = GL_TRUE; + + if (!DRI2Connect(psc->dpy, screen, &driverName, &busID, &sareaHandle)) + return NULL; + + psc->driver = driOpenDriver(driverName); + if (psc->driver == NULL) + goto handle_error; + + extensions = dlsym(psc->driver, __DRI_DRIVER_EXTENSIONS); + if (extensions == NULL) { + ErrorMessageF("driver exports no extensions (%s)\n", dlerror()); + goto handle_error; + } + + for (i = 0; extensions[i]; i++) { + if (strcmp(extensions[i]->name, __DRI_CORE) == 0) + psc->core = (__DRIcoreExtension *) extensions[i]; + } + + if (psc->core == NULL) { + ErrorMessageF("core dri extension not found\n"); + goto handle_error; + } + + psc->fd = drmOpen(NULL, busID); + if (psc->fd < 0) { + ErrorMessageF("failed to open drm device: %s\n", strerror(errno)); + return NULL; + } + + if (drmGetMagic(psc->fd, &magic)) + return NULL; + + if (!DRI2AuthConnection(psc->dpy, screen, magic)) { + ErrorMessageF("failed to authenticate drm access\n"); + return NULL; + } + + psc->__driScreen = + psc->core->createNewScreen(screen, psc->fd, sareaHandle, + loader_extensions, &driver_configs, psc); + if (psc->__driScreen == NULL) { + ErrorMessageF("failed to create dri screen\n"); + return NULL; + } + + driBindExtensions(psc); + + psc->configs = driConvertConfigs(psc->core, psc->configs, driver_configs); + psc->visuals = driConvertConfigs(psc->core, psc->visuals, driver_configs); + + psp->destroyScreen = dri2DestroyScreen; + psp->createContext = dri2CreateContext; + psp->createDrawable = dri2CreateDrawable; + + Xfree(driverName); + Xfree(busID); + + return psp; + + handle_error: + Xfree(driverName); + Xfree(busID); + + /* FIXME: clean up here */ + + return NULL; +} + +/* Called from __glXFreeDisplayPrivate. + */ +static void dri2DestroyDisplay(__GLXDRIdisplay *dpy) +{ + Xfree(dpy); +} + +/* + * Allocate, initialize and return a __DRIdisplayPrivate object. + * This is called from __glXInitialize() when we are given a new + * display pointer. + */ +_X_HIDDEN __GLXDRIdisplay *dri2CreateDisplay(Display *dpy) +{ + __GLXDRIdisplayPrivate *pdp; + int eventBase, errorBase; + + if (!DRI2QueryExtension(dpy, &eventBase, &errorBase)) + return NULL; + + pdp = Xmalloc(sizeof *pdp); + if (pdp == NULL) + return NULL; + + if (!DRI2QueryVersion(dpy, &pdp->driMajor, &pdp->driMinor)) { + Xfree(pdp); + return NULL; + } + + pdp->driPatch = 0; + + pdp->base.destroyDisplay = dri2DestroyDisplay; + pdp->base.createScreen = dri2CreateScreen; + + return &pdp->base; +} + +#endif /* GLX_DIRECT_RENDERING */ diff --git a/src/glx/x11/dri_glx.c b/src/glx/x11/dri_glx.c index 514c082f6cd..31ade0da2a3 100644 --- a/src/glx/x11/dri_glx.c +++ b/src/glx/x11/dri_glx.c @@ -52,7 +52,6 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include <sys/mman.h> #include "xf86drm.h" - #ifndef RTLD_NOW #define RTLD_NOW 0 #endif @@ -62,6 +61,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. typedef struct __GLXDRIdisplayPrivateRec __GLXDRIdisplayPrivate; typedef struct __GLXDRIcontextPrivateRec __GLXDRIcontextPrivate; +typedef struct __GLXDRIconfigPrivateRec __GLXDRIconfigPrivate; struct __GLXDRIdisplayPrivateRec { __GLXDRIdisplay base; @@ -76,8 +76,14 @@ struct __GLXDRIdisplayPrivateRec { struct __GLXDRIcontextPrivateRec { __GLXDRIcontext base; - __DRIcontext driContext; + __DRIcontext *driContext; XID hwContextID; + __GLXscreenConfigs *psc; +}; + +struct __GLXDRIconfigPrivateRec { + __GLcontextModes modes; + const __DRIconfig *driConfig; }; #ifndef DEFAULT_DRIVER_DIR @@ -98,10 +104,12 @@ static void InfoMessageF(const char *f, ...) } } +extern void ErrorMessageF(const char *f, ...); + /** * Print error to stderr, unless LIBGL_DEBUG=="quiet". */ -static void ErrorMessageF(const char *f, ...) +_X_HIDDEN void ErrorMessageF(const char *f, ...) { va_list args; const char *env; @@ -114,16 +122,7 @@ static void ErrorMessageF(const char *f, ...) } } - -/** - * Versioned name of the expected \c __driCreateNewScreen function. - * - * The version of the last incompatible loader/driver inteface change is - * appended to the name of the \c __driCreateNewScreen function. This - * prevents loaders from trying to load drivers that are too old. - */ -static const char createNewScreenName[] = __DRI_CREATE_NEW_SCREEN_STRING; - +extern void *driOpenDriver(const char *driverName); /** * Try to \c dlopen the named driver. @@ -137,7 +136,7 @@ static const char createNewScreenName[] = __DRI_CREATE_NEW_SCREEN_STRING; * \returns * A handle from \c dlopen, or \c NULL if driver file not found. */ -static void *OpenDriver(const char *driverName) +_X_HIDDEN void *driOpenDriver(const char *driverName) { void *glhandle, *handle; const char *libPaths, *p, *next; @@ -244,7 +243,7 @@ static void *driGetDriver(Display *dpy, int scrNum) void *ret; if (GetDriverName(dpy, scrNum, &driverName)) { - ret = OpenDriver(driverName); + ret = driOpenDriver(driverName); if (driverName) Xfree(driverName); return ret; @@ -287,17 +286,22 @@ PUBLIC const char *glXGetScreenDriver (Display *dpy, int scrNum) { * * Note: The driver remains opened after this function returns. */ -PUBLIC const char *glXGetDriverConfig (const char *driverName) { - void *handle = OpenDriver (driverName); +PUBLIC const char *glXGetDriverConfig (const char *driverName) +{ + void *handle = driOpenDriver (driverName); if (handle) return dlsym (handle, "__driConfigOptions"); else return NULL; } -static void -filter_modes( __GLcontextModes ** server_modes, - const __GLcontextModes * driver_modes ) +extern void +driFilterModes(__GLcontextModes ** server_modes, + const __GLcontextModes * driver_modes); + +_X_HIDDEN void +driFilterModes(__GLcontextModes ** server_modes, + const __GLcontextModes * driver_modes) { __GLcontextModes * m; __GLcontextModes ** prev_next; @@ -349,6 +353,7 @@ filter_modes( __GLcontextModes ** server_modes, } #ifdef XDAMAGE_1_1_INTERFACE + static GLboolean has_damage_post(Display *dpy) { static GLboolean inited = GL_FALSE; @@ -369,20 +374,18 @@ static GLboolean has_damage_post(Display *dpy) return has_damage; } -#endif /* XDAMAGE_1_1_INTERFACE */ static void __glXReportDamage(__DRIdrawable *driDraw, int x, int y, drm_clip_rect_t *rects, int num_rects, - GLboolean front_buffer) + GLboolean front_buffer, + void *loaderPrivate) { -#ifdef XDAMAGE_1_1_INTERFACE XRectangle *xrects; XserverRegion region; int i; int x_off, y_off; - __GLXDRIdrawable *glxDraw = - containerOf(driDraw, __GLXDRIdrawable, driDrawable); + __GLXDRIdrawable *glxDraw = loaderPrivate; __GLXscreenConfigs *psc = glxDraw->psc; Display *dpy = psc->dpy; Drawable drawable; @@ -397,7 +400,7 @@ static void __glXReportDamage(__DRIdrawable *driDraw, } else{ x_off = 0; y_off = 0; - drawable = glxDraw->drawable; + drawable = glxDraw->xDrawable; } xrects = malloc(sizeof(XRectangle) * num_rects); @@ -414,19 +417,25 @@ static void __glXReportDamage(__DRIdrawable *driDraw, free(xrects); XDamageAdd(dpy, drawable, region); XFixesDestroyRegion(dpy, region); -#endif } +static const __DRIdamageExtension damageExtension = { + { __DRI_DAMAGE, __DRI_DAMAGE_VERSION }, + __glXReportDamage, +}; + +#endif + static GLboolean __glXDRIGetDrawableInfo(__DRIdrawable *drawable, unsigned int *index, unsigned int *stamp, int *X, int *Y, int *W, int *H, int *numClipRects, drm_clip_rect_t ** pClipRects, int *backX, int *backY, - int *numBackClipRects, drm_clip_rect_t **pBackClipRects) + int *numBackClipRects, drm_clip_rect_t **pBackClipRects, + void *loaderPrivate) { - __GLXDRIdrawable *glxDraw = - containerOf(drawable, __GLXDRIdrawable, driDrawable); + __GLXDRIdrawable *glxDraw = loaderPrivate; __GLXscreenConfigs *psc = glxDraw->psc; Display *dpy = psc->dpy; @@ -437,17 +446,7 @@ __glXDRIGetDrawableInfo(__DRIdrawable *drawable, numBackClipRects, pBackClipRects); } - -/** - * Table of functions exported by the loader to the driver. - */ -static const __DRIcontextModesExtension contextModesExtension = { - { __DRI_CONTEXT_MODES, __DRI_CONTEXT_MODES_VERSION }, - _gl_context_modes_create, - _gl_context_modes_destroy, -}; - -static const __DRIsystemTimeExtension systemTimeExtension = { +_X_HIDDEN const __DRIsystemTimeExtension systemTimeExtension = { { __DRI_SYSTEM_TIME, __DRI_SYSTEM_TIME_VERSION }, __glXGetUST, __driGetMscRateOML, @@ -458,19 +457,189 @@ static const __DRIgetDrawableInfoExtension getDrawableInfoExtension = { __glXDRIGetDrawableInfo }; -static const __DRIdamageExtension damageExtension = { - { __DRI_DAMAGE, __DRI_DAMAGE_VERSION }, - __glXReportDamage, -}; - static const __DRIextension *loader_extensions[] = { - &contextModesExtension.base, &systemTimeExtension.base, &getDrawableInfoExtension.base, + +#ifdef XDAMAGE_1_1_INTERFACE &damageExtension.base, +#endif + NULL }; +#define __ATTRIB(attrib, field) \ + { attrib, offsetof(__GLcontextModes, field) } + +static const struct { unsigned int attrib, offset; } attribMap[] = { + __ATTRIB(__DRI_ATTRIB_BUFFER_SIZE, rgbBits), + __ATTRIB(__DRI_ATTRIB_LEVEL, level), + __ATTRIB(__DRI_ATTRIB_RED_SIZE, redBits), + __ATTRIB(__DRI_ATTRIB_GREEN_SIZE, greenBits), + __ATTRIB(__DRI_ATTRIB_BLUE_SIZE, blueBits), + __ATTRIB(__DRI_ATTRIB_ALPHA_SIZE, alphaBits), + __ATTRIB(__DRI_ATTRIB_DEPTH_SIZE, depthBits), + __ATTRIB(__DRI_ATTRIB_STENCIL_SIZE, stencilBits), + __ATTRIB(__DRI_ATTRIB_ACCUM_RED_SIZE, accumRedBits), + __ATTRIB(__DRI_ATTRIB_ACCUM_GREEN_SIZE, accumGreenBits), + __ATTRIB(__DRI_ATTRIB_ACCUM_BLUE_SIZE, accumBlueBits), + __ATTRIB(__DRI_ATTRIB_ACCUM_ALPHA_SIZE, accumAlphaBits), + __ATTRIB(__DRI_ATTRIB_SAMPLE_BUFFERS, sampleBuffers), + __ATTRIB(__DRI_ATTRIB_SAMPLES, samples), + __ATTRIB(__DRI_ATTRIB_DOUBLE_BUFFER, doubleBufferMode), + __ATTRIB(__DRI_ATTRIB_STEREO, stereoMode), + __ATTRIB(__DRI_ATTRIB_AUX_BUFFERS, numAuxBuffers), +#if 0 + __ATTRIB(__DRI_ATTRIB_TRANSPARENT_TYPE, transparentPixel), + __ATTRIB(__DRI_ATTRIB_TRANSPARENT_INDEX_VALUE, transparentIndex), + __ATTRIB(__DRI_ATTRIB_TRANSPARENT_RED_VALUE, transparentRed), + __ATTRIB(__DRI_ATTRIB_TRANSPARENT_GREEN_VALUE, transparentGreen), + __ATTRIB(__DRI_ATTRIB_TRANSPARENT_BLUE_VALUE, transparentBlue), + __ATTRIB(__DRI_ATTRIB_TRANSPARENT_ALPHA_VALUE, transparentAlpha), + __ATTRIB(__DRI_ATTRIB_RED_MASK, redMask), + __ATTRIB(__DRI_ATTRIB_GREEN_MASK, greenMask), + __ATTRIB(__DRI_ATTRIB_BLUE_MASK, blueMask), + __ATTRIB(__DRI_ATTRIB_ALPHA_MASK, alphaMask), +#endif + __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_WIDTH, maxPbufferWidth), + __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_HEIGHT, maxPbufferHeight), + __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_PIXELS, maxPbufferPixels), + __ATTRIB(__DRI_ATTRIB_OPTIMAL_PBUFFER_WIDTH, optimalPbufferWidth), + __ATTRIB(__DRI_ATTRIB_OPTIMAL_PBUFFER_HEIGHT, optimalPbufferHeight), +#if 0 + __ATTRIB(__DRI_ATTRIB_SWAP_METHOD, swapMethod), + __ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_RGB, bindToTextureRgb), + __ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_RGBA, bindToTextureRgba), + __ATTRIB(__DRI_ATTRIB_BIND_TO_MIPMAP_TEXTURE, bindToMipmapTexture), + __ATTRIB(__DRI_ATTRIB_YINVERTED, yInverted), +#endif +}; + +#define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0])) + +static int +scalarEqual(__GLcontextModes *mode, unsigned int attrib, unsigned int value) +{ + unsigned int driValue; + int i; + + for (i = 0; i < ARRAY_SIZE(attribMap); i++) + if (attribMap[i].attrib == attrib) { + driValue = *(unsigned int *) ((char *) mode + attribMap[i].offset); + return driValue == value; + } + + return GL_TRUE; /* Is a non-existing attribute equal to value? */ +} + +static int +driConfigEqual(const __DRIcoreExtension *core, + __GLcontextModes *modes, const __DRIconfig *driConfig) +{ + unsigned int attrib, value, glxValue; + int i; + + i = 0; + while (core->indexConfigAttrib(driConfig, i++, &attrib, &value)) { + switch (attrib) { + case __DRI_ATTRIB_RENDER_TYPE: + glxValue = 0; + if (value & __DRI_ATTRIB_RGBA_BIT) { + glxValue |= GLX_RGBA_BIT; + } else if (value & __DRI_ATTRIB_COLOR_INDEX_BIT) { + glxValue |= GLX_COLOR_INDEX_BIT; + } + if (glxValue != modes->renderType) + return GL_FALSE; + break; + + case __DRI_ATTRIB_CONFIG_CAVEAT: + if (value & __DRI_ATTRIB_NON_CONFORMANT_CONFIG) + glxValue = GLX_NON_CONFORMANT_CONFIG; + else if (value & __DRI_ATTRIB_SLOW_BIT) + glxValue = GLX_SLOW_CONFIG; + else + glxValue = GLX_NONE; + if (glxValue != modes->visualRating) + return GL_FALSE; + break; + +#if 0 + /* The X server doesn't send these, so ignore them for now. */ + case __DRI_ATTRIB_BIND_TO_TEXTURE_TARGETS: + glxValue = 0; + if (value & __DRI_ATTRIB_TEXTURE_1D_BIT) + glxValue |= GLX_TEXTURE_1D_BIT_EXT; + if (value & __DRI_ATTRIB_TEXTURE_2D_BIT) + glxValue |= GLX_TEXTURE_2D_BIT_EXT; + if (value & __DRI_ATTRIB_TEXTURE_RECTANGLE_BIT) + glxValue |= GLX_TEXTURE_RECTANGLE_BIT_EXT; + if (glxValue != modes->bindToTextureTargets) + return GL_FALSE; + break; +#endif + + default: + if (!scalarEqual(modes, attrib, value)) + return GL_FALSE; + } + } + + return GL_TRUE; +} + +static __GLcontextModes * +createDriMode(const __DRIcoreExtension *core, + __GLcontextModes *modes, const __DRIconfig **driConfigs) +{ + __GLXDRIconfigPrivate *config; + int i; + + for (i = 0; driConfigs[i]; i++) { + if (driConfigEqual(core, modes, driConfigs[i])) + break; + } + + if (driConfigs[i] == NULL) + return NULL; + + config = Xmalloc(sizeof *config); + if (config == NULL) + return NULL; + + config->modes = *modes; + config->driConfig = driConfigs[i]; + + return &config->modes; +} + +extern __GLcontextModes * +driConvertConfigs(const __DRIcoreExtension *core, + __GLcontextModes *modes, const __DRIconfig **configs); + +_X_HIDDEN __GLcontextModes * +driConvertConfigs(const __DRIcoreExtension *core, + __GLcontextModes *modes, const __DRIconfig **configs) +{ + __GLcontextModes head, *tail, *m; + + tail = &head; + head.next = NULL; + for (m = modes; m; m = m->next) { + tail->next = createDriMode(core, m, configs); + if (tail->next == NULL) { + /* no matching dri config for m */ + continue; + } + + + tail = tail->next; + } + + _gl_context_modes_destroy(modes); + + return head.next; +} /** * Perform the required libGL-side initialization and call the client-side @@ -491,8 +660,7 @@ static const __DRIextension *loader_extensions[] = { */ static void * CallCreateNewScreen(Display *dpy, int scrn, __GLXscreenConfigs *psc, - __GLXDRIdisplayPrivate * driDpy, - PFNCREATENEWSCREENFUNC createNewScreen) + __GLXDRIdisplayPrivate * driDpy) { void *psp = NULL; #ifndef GLX_USE_APPLEGL @@ -507,12 +675,12 @@ CallCreateNewScreen(Display *dpy, int scrn, __GLXscreenConfigs *psc, int status; const char * err_msg; const char * err_extra; + const __DRIconfig **driver_configs; dri_version.major = driDpy->driMajor; dri_version.minor = driDpy->driMinor; dri_version.patch = driDpy->driPatch; - err_msg = "XF86DRIOpenConnection"; err_extra = NULL; @@ -608,12 +776,9 @@ CallCreateNewScreen(Display *dpy, int scrn, __GLXscreenConfigs *psc, err_extra = strerror( -status ); if ( status == 0 ) { - __GLcontextModes * driver_modes = NULL; - err_msg = "InitDriver"; err_extra = NULL; - psp = (*createNewScreen)(scrn, - &psc->__driScreen, + psp = (*psc->legacy->createNewScreen)(scrn, & ddx_version, & dri_version, & drm_version, @@ -621,11 +786,17 @@ CallCreateNewScreen(Display *dpy, int scrn, __GLXscreenConfigs *psc, pSAREA, fd, loader_extensions, - & driver_modes ); - - filter_modes(&psc->configs, driver_modes); - filter_modes(&psc->visuals, driver_modes); - _gl_context_modes_destroy(driver_modes); + & driver_configs, + psc); + + psc->configs = + driConvertConfigs(psc->core, + psc->configs, + driver_configs); + psc->visuals = + driConvertConfigs(psc->core, + psc->visuals, + driver_configs); } } } @@ -674,7 +845,7 @@ static void driDestroyContext(__GLXDRIcontext *context, { __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context; - (*pcp->driContext.destroyContext)(&pcp->driContext); + (*psc->core->destroyContext)(pcp->driContext); XF86DRIDestroyContext(psc->dpy, psc->scr, pcp->hwContextID); } @@ -683,17 +854,19 @@ static Bool driBindContext(__GLXDRIcontext *context, __GLXDRIdrawable *draw, __GLXDRIdrawable *read) { __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context; + const __DRIcoreExtension *core = pcp->psc->core; - return (*pcp->driContext.bindContext)(&pcp->driContext, - &draw->driDrawable, - &read->driDrawable); + return (*core->bindContext)(pcp->driContext, + draw->driDrawable, + read->driDrawable); } static void driUnbindContext(__GLXDRIcontext *context) { __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context; + const __DRIcoreExtension *core = pcp->psc->core; - (*pcp->driContext.unbindContext)(&pcp->driContext); + (*core->unbindContext)(pcp->driContext); } static __GLXDRIcontext *driCreateContext(__GLXscreenConfigs *psc, @@ -704,17 +877,19 @@ static __GLXDRIcontext *driCreateContext(__GLXscreenConfigs *psc, __GLXDRIcontextPrivate *pcp, *pcp_shared; drm_context_t hwContext; __DRIcontext *shared = NULL; + __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) mode; if (psc && psc->driScreen) { if (shareList) { pcp_shared = (__GLXDRIcontextPrivate *) shareList->driContext; - shared = &pcp_shared->driContext; + shared = pcp_shared->driContext; } pcp = Xmalloc(sizeof *pcp); if (pcp == NULL) return NULL; + pcp->psc = psc; if (!XF86DRICreateContextWithConfig(psc->dpy, psc->scr, mode->visualID, &pcp->hwContextID, &hwContext)) { @@ -722,13 +897,14 @@ static __GLXDRIcontext *driCreateContext(__GLXscreenConfigs *psc, return NULL; } - pcp->driContext.private = - (*psc->__driScreen.createNewContext)(&psc->__driScreen, - mode, renderType, - shared, - hwContext, - &pcp->driContext); - if (pcp->driContext.private == NULL) { + pcp->driContext = + (*psc->legacy->createNewContext)(psc->__driScreen, + config->driConfig, + renderType, + shared, + hwContext, + pcp); + if (pcp->driContext == NULL) { XF86DRIDestroyContext(psc->dpy, psc->scr, pcp->hwContextID); Xfree(pcp); return NULL; @@ -748,18 +924,24 @@ static void driDestroyDrawable(__GLXDRIdrawable *pdraw) { __GLXscreenConfigs *psc = pdraw->psc; - (*pdraw->driDrawable.destroyDrawable)(&pdraw->driDrawable); + (*psc->core->destroyDrawable)(pdraw->driDrawable); XF86DRIDestroyDrawable(psc->dpy, psc->scr, pdraw->drawable); Xfree(pdraw); } static __GLXDRIdrawable *driCreateDrawable(__GLXscreenConfigs *psc, + XID xDrawable, GLXDrawable drawable, - GLXContext gc) + const __GLcontextModes *modes) { __GLXDRIdrawable *pdraw; drm_drawable_t hwDrawable; void *empty_attribute_list = NULL; + __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) modes; + + /* Old dri can't handle GLX 1.3+ drawable constructors. */ + if (xDrawable != drawable) + return NULL; pdraw = Xmalloc(sizeof(*pdraw)); if (!pdraw) @@ -772,16 +954,15 @@ static __GLXDRIdrawable *driCreateDrawable(__GLXscreenConfigs *psc, return NULL; /* Create a new drawable */ - pdraw->driDrawable.private = - (*psc->__driScreen.createNewDrawable)(&psc->__driScreen, - gc->mode, - &pdraw->driDrawable, - hwDrawable, - GLX_WINDOW_BIT, - 0, - empty_attribute_list); - - if (!pdraw->driDrawable.private) { + pdraw->driDrawable = + (*psc->legacy->createNewDrawable)(psc->__driScreen, + config->driConfig, + hwDrawable, + GLX_WINDOW_BIT, + empty_attribute_list, + pdraw); + + if (!pdraw->driDrawable) { XF86DRIDestroyDrawable(psc->dpy, psc->scr, drawable); Xfree(pdraw); return NULL; @@ -795,19 +976,23 @@ static __GLXDRIdrawable *driCreateDrawable(__GLXscreenConfigs *psc, static void driDestroyScreen(__GLXscreenConfigs *psc) { /* Free the direct rendering per screen data */ - if (psc->__driScreen.private) - (*psc->__driScreen.destroyScreen)(&psc->__driScreen); - psc->__driScreen.private = NULL; + if (psc->__driScreen) + (*psc->core->destroyScreen)(psc->__driScreen); + psc->__driScreen = NULL; if (psc->driver) dlclose(psc->driver); } +void +driBindExtensions(__GLXscreenConfigs *psc); + static __GLXDRIscreen *driCreateScreen(__GLXscreenConfigs *psc, int screen, __GLXdisplayPrivate *priv) { - PFNCREATENEWSCREENFUNC createNewScreen; __GLXDRIdisplayPrivate *pdp; __GLXDRIscreen *psp; + const __DRIextension **extensions; + int i; psp = Xmalloc(sizeof *psp); if (psp == NULL) @@ -817,15 +1002,40 @@ static __GLXDRIscreen *driCreateScreen(__GLXscreenConfigs *psc, int screen, psc->ext_list_first_time = GL_TRUE; psc->driver = driGetDriver(priv->dpy, screen); - createNewScreen = dlsym(psc->driver, createNewScreenName); - if (createNewScreen == NULL) + if (psc->driver == NULL) { + Xfree(psp); + return NULL; + } + + extensions = dlsym(psc->driver, __DRI_DRIVER_EXTENSIONS); + if (extensions == NULL) { + ErrorMessageF("driver exports no extensions (%s)\n", dlerror()); + Xfree(psp); return NULL; + } + for (i = 0; extensions[i]; i++) { + if (strcmp(extensions[i]->name, __DRI_CORE) == 0) + psc->core = (__DRIcoreExtension *) extensions[i]; + if (strcmp(extensions[i]->name, __DRI_LEGACY) == 0) + psc->legacy = (__DRIlegacyExtension *) extensions[i]; + } + + if (psc->core == NULL || psc->legacy == NULL) { + Xfree(psp); + return NULL; + } + pdp = (__GLXDRIdisplayPrivate *) priv->driDisplay; - psc->__driScreen.private = - CallCreateNewScreen(psc->dpy, screen, psc, pdp, createNewScreen); - if (psc->__driScreen.private != NULL) - __glXScrEnableDRIExtension(psc); + psc->__driScreen = + CallCreateNewScreen(psc->dpy, screen, psc, pdp); + if (psc->__driScreen == NULL) { + dlclose(psc->driver); + Xfree(psp); + return NULL; + } + + driBindExtensions(psc); psp->destroyScreen = driDestroyScreen; psp->createContext = driCreateContext; diff --git a/src/glx/x11/glx_pbuffer.c b/src/glx/x11/glx_pbuffer.c index 52dad65170f..b0a8f71fd4a 100644 --- a/src/glx/x11/glx_pbuffer.c +++ b/src/glx/x11/glx_pbuffer.c @@ -271,6 +271,32 @@ GetDrawableAttribute( Display *dpy, GLXDrawable drawable, return 0; } +#ifdef GLX_DIRECT_RENDERING +extern __GLXDRIdrawable * +GetGLXDRIDrawable(Display *dpy, GLXDrawable drawable, int * const scrn_num); + +static GLenum +determineTextureTarget(const int *attribs, int numAttribs) +{ + GLenum target = 0; + int i; + + for (i = 0; i < numAttribs; i++) { + if (attribs[2 * i] == GLX_TEXTURE_TARGET_EXT) { + switch (attribs[2 * i + 1]) { + case GLX_TEXTURE_2D_EXT: + target = GL_TEXTURE_2D; + break; + case GLX_TEXTURE_RECTANGLE_EXT: + target = GL_TEXTURE_RECTANGLE_ARB; + break; + } + } + } + + return target; +} +#endif /** * Create a non-pbuffer GLX drawable. @@ -306,7 +332,7 @@ CreateDrawable( Display *dpy, const __GLcontextModes * fbconfig, req->glxCode = glxCode; req->screen = (CARD32) fbconfig->screen; req->fbconfig = fbconfig->fbconfigID; - req->window = (GLXPbuffer) drawable; + req->window = (CARD32) drawable; req->glxwindow = (GLXWindow) XAllocID(dpy); req->numAttribs = (CARD32) i; @@ -315,6 +341,34 @@ CreateDrawable( Display *dpy, const __GLcontextModes * fbconfig, UnlockDisplay(dpy); SyncHandle(); +#ifdef GLX_DIRECT_RENDERING + do { + /* FIXME: Maybe delay __DRIdrawable creation until the drawable + * is actually bound to a context... */ + + __GLXdisplayPrivate * const priv = __glXInitialize(dpy); + __GLXDRIdrawable *pdraw; + __GLXscreenConfigs *psc; + + psc = &priv->screenConfigs[fbconfig->screen]; + if (psc->driScreen == NULL) + break; + pdraw = psc->driScreen->createDrawable(psc, drawable, + req->glxwindow, fbconfig); + if (pdraw == NULL) { + fprintf(stderr, "failed to create drawable\n"); + break; + } + + if (__glxHashInsert(psc->drawHash, req->glxwindow, pdraw)) { + (*pdraw->destroyDrawable)(pdraw); + return None; /* FIXME: Check what we're supposed to do here... */ + } + + pdraw->textureTarget = determineTextureTarget(attrib_list, i); + } while (0); +#endif + return (GLXDrawable)req->glxwindow; } @@ -350,6 +404,20 @@ DestroyDrawable( Display * dpy, GLXDrawable drawable, CARD32 glxCode ) UnlockDisplay(dpy); SyncHandle(); +#ifdef GLX_DIRECT_RENDERING + { + int screen; + __GLXdisplayPrivate * const priv = __glXInitialize(dpy); + __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen); + __GLXscreenConfigs *psc = &priv->screenConfigs[screen]; + + if (pdraw != NULL) { + (*pdraw->destroyDrawable)(pdraw); + __glxHashDelete(psc->drawHash, drawable); + } + } +#endif + return; } diff --git a/src/glx/x11/glxclient.h b/src/glx/x11/glxclient.h index ea90282b08f..5fd64209df5 100644 --- a/src/glx/x11/glxclient.h +++ b/src/glx/x11/glxclient.h @@ -59,7 +59,6 @@ #include "GL/glxproto.h" #include "GL/internal/glcore.h" #include "glapitable.h" -#include "glxextensions.h" #include "glxhash.h" #if defined( USE_XTHREADS ) # include <X11/Xthreads.h> @@ -97,6 +96,8 @@ typedef struct __GLXDRIscreenRec __GLXDRIscreen; typedef struct __GLXDRIdrawableRec __GLXDRIdrawable; typedef struct __GLXDRIcontextRec __GLXDRIcontext; +#include "glxextensions.h" + struct __GLXDRIdisplayRec { /** * Method to destroy the private DRI display data. @@ -117,8 +118,9 @@ struct __GLXDRIscreenRec { GLXContext shareList, int renderType); __GLXDRIdrawable *(*createDrawable)(__GLXscreenConfigs *psc, - GLXDrawable drawable, - GLXContext gc); + XID drawable, + GLXDrawable glxDrawable, + const __GLcontextModes *modes); }; struct __GLXDRIcontextRec { @@ -134,9 +136,11 @@ struct __GLXDRIcontextRec { struct __GLXDRIdrawableRec { void (*destroyDrawable)(__GLXDRIdrawable *drawable); + XID xDrawable; XID drawable; __GLXscreenConfigs *psc; - __DRIdrawable driDrawable; + __DRIdrawable *driDrawable; + GLenum textureTarget; }; /* @@ -144,6 +148,7 @@ struct __GLXDRIdrawableRec { ** dependent methods. */ extern __GLXDRIdisplay *driCreateDisplay(Display *dpy); +extern __GLXDRIdisplay *dri2CreateDisplay(Display *dpy); extern void DRI_glXUseXFont( Font font, int first, int count, int listbase ); @@ -364,6 +369,7 @@ struct __GLXcontextRec { #ifdef GLX_DIRECT_RENDERING __GLXDRIcontext *driContext; + __DRIcontext *__driContext; #endif /** @@ -458,32 +464,38 @@ struct __GLXscreenConfigsRec { /** * Per screen direct rendering interface functions and data. */ - __DRIscreen __driScreen; + __DRIscreen *__driScreen; + const __DRIcoreExtension *core; + const __DRIlegacyExtension *legacy; __glxHashTable *drawHash; Display *dpy; - int scr; + int scr, fd; void *driver; __GLXDRIscreen *driScreen; #ifdef __DRI_COPY_SUB_BUFFER - __DRIcopySubBufferExtension *copySubBuffer; + const __DRIcopySubBufferExtension *copySubBuffer; #endif #ifdef __DRI_SWAP_CONTROL - __DRIswapControlExtension *swapControl; + const __DRIswapControlExtension *swapControl; #endif #ifdef __DRI_ALLOCATE - __DRIallocateExtension *allocate; + const __DRIallocateExtension *allocate; #endif #ifdef __DRI_FRAME_TRACKING - __DRIframeTrackingExtension *frameTracking; + const __DRIframeTrackingExtension *frameTracking; #endif #ifdef __DRI_MEDIA_STREAM_COUNTER - __DRImediaStreamCounterExtension *msc; + const __DRImediaStreamCounterExtension *msc; +#endif + +#ifdef __DRI_TEX_BUFFER + const __DRItexBufferExtension *texBuffer; #endif #endif @@ -555,6 +567,7 @@ struct __GLXdisplayPrivateRec { * Per display direct rendering interface functions and data. */ __GLXDRIdisplay *driDisplay; + __GLXDRIdisplay *dri2Display; #endif }; @@ -720,7 +733,8 @@ extern GLboolean __glXGetMscRateOML(Display * dpy, GLXDrawable drawable, #ifdef GLX_DIRECT_RENDERING GLboolean -__driGetMscRateOML(__DRIdrawable *draw, int32_t *numerator, int32_t *denominator); +__driGetMscRateOML(__DRIdrawable *draw, + int32_t *numerator, int32_t *denominator, void *private); #endif #endif /* !__GLX_client_h__ */ diff --git a/src/glx/x11/glxcmds.c b/src/glx/x11/glxcmds.c index 8d0f07fd0a1..ddb006193c2 100644 --- a/src/glx/x11/glxcmds.c +++ b/src/glx/x11/glxcmds.c @@ -109,6 +109,9 @@ static void GarbageCollectDRIDrawables(Display *dpy, __GLXscreenConfigs *sc) XSetErrorHandler(oldXErrorHandler); } +extern __GLXDRIdrawable * +GetGLXDRIDrawable(Display *dpy, GLXDrawable drawable, int * const scrn_num); + /** * Get the __DRIdrawable for the drawable associated with a GLXContext * @@ -118,24 +121,27 @@ static void GarbageCollectDRIDrawables(Display *dpy, __GLXscreenConfigs *sc) * \returns A pointer to the context's __DRIdrawable on success, or NULL if * the drawable is not associated with a direct-rendering context. */ -static __DRIdrawable * -GetDRIDrawable( Display *dpy, GLXDrawable drawable, int * const scrn_num ) +_X_HIDDEN __GLXDRIdrawable * +GetGLXDRIDrawable(Display *dpy, GLXDrawable drawable, int * const scrn_num) { - __GLXdisplayPrivate * const priv = __glXInitialize(dpy); - __GLXDRIdrawable * const pdraw; + __GLXdisplayPrivate *priv = __glXInitialize(dpy); + __GLXDRIdrawable *pdraw; const unsigned screen_count = ScreenCount(dpy); unsigned i; - __GLXscreenConfigs *sc; + __GLXscreenConfigs *psc; - if (priv == NULL || priv->driDisplay == NULL) + if (priv == NULL) return NULL; for (i = 0; i < screen_count; i++) { - sc = &priv->screenConfigs[i]; - if (__glxHashLookup(sc->drawHash, drawable, (void *) &pdraw) == 0) { + psc = &priv->screenConfigs[i]; + if (psc->drawHash == NULL) + continue; + + if (__glxHashLookup(psc->drawHash, drawable, (void *) &pdraw) == 0) { if (scrn_num != NULL) *scrn_num = i; - return &pdraw->driDrawable; + return pdraw; } } @@ -837,10 +843,10 @@ PUBLIC void glXSwapBuffers(Display *dpy, GLXDrawable drawable) GLXContextTag tag; CARD8 opcode; #ifdef GLX_DIRECT_RENDERING - __DRIdrawable *pdraw = GetDRIDrawable( dpy, drawable, NULL ); + __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, NULL); - if ( pdraw != NULL ) { - (*pdraw->swapBuffers)(pdraw); + if (pdraw != NULL) { + (*pdraw->psc->core->swapBuffers)(pdraw->driDrawable); return; } #endif @@ -1721,11 +1727,11 @@ static int __glXSwapIntervalSGI(int interval) if (gc->driContext) { __GLXscreenConfigs * const psc = GetGLXScreenConfigs( gc->currentDpy, gc->screen ); - __DRIdrawable * const pdraw = GetDRIDrawable( gc->currentDpy, - gc->currentDrawable, - NULL ); + __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(gc->currentDpy, + gc->currentDrawable, + NULL); if (psc->swapControl != NULL && pdraw != NULL) { - psc->swapControl->setSwapInterval(pdraw, interval); + psc->swapControl->setSwapInterval(pdraw->driDrawable, interval); return 0; } else { @@ -1775,10 +1781,10 @@ static int __glXSwapIntervalMESA(unsigned int interval) gc->screen ); if ( (psc != NULL) && (psc->driScreen != NULL) ) { - __DRIdrawable * const pdraw = - GetDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL); + __GLXDRIdrawable *pdraw = + GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL); if (psc->swapControl != NULL && pdraw != NULL) { - psc->swapControl->setSwapInterval(pdraw, interval); + psc->swapControl->setSwapInterval(pdraw->driDrawable, interval); return 0; } } @@ -1801,10 +1807,10 @@ static int __glXGetSwapIntervalMESA(void) gc->screen ); if ( (psc != NULL) && (psc->driScreen != NULL) ) { - __DRIdrawable * const pdraw = - GetDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL); + __GLXDRIdrawable *pdraw = + GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL); if (psc->swapControl != NULL && pdraw != NULL) { - return psc->swapControl->getSwapInterval(pdraw); + return psc->swapControl->getSwapInterval(pdraw->driDrawable); } } } @@ -1823,11 +1829,11 @@ static GLint __glXBeginFrameTrackingMESA(Display *dpy, GLXDrawable drawable) int status = GLX_BAD_CONTEXT; #ifdef __DRI_FRAME_TRACKING int screen; - __DRIdrawable * const pdraw = GetDRIDrawable(dpy, drawable, & screen); + __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen); __GLXscreenConfigs * const psc = GetGLXScreenConfigs(dpy, screen); if (pdraw != NULL && psc->frameTracking != NULL) - status = psc->frameTracking->frameTracking(pdraw, GL_TRUE); + status = psc->frameTracking->frameTracking(pdraw->driDrawable, GL_TRUE); #else (void) dpy; (void) drawable; @@ -1841,11 +1847,12 @@ static GLint __glXEndFrameTrackingMESA(Display *dpy, GLXDrawable drawable) int status = GLX_BAD_CONTEXT; #ifdef __DRI_FRAME_TRACKING int screen; - __DRIdrawable * const pdraw = GetDRIDrawable(dpy, drawable, & screen); - __GLXscreenConfigs * const psc = GetGLXScreenConfigs(dpy, screen); + __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, & screen); + __GLXscreenConfigs *psc = GetGLXScreenConfigs(dpy, screen); if (pdraw != NULL && psc->frameTracking != NULL) - status = psc->frameTracking->frameTracking(pdraw, GL_FALSE); + status = psc->frameTracking->frameTracking(pdraw->driDrawable, + GL_FALSE); #else (void) dpy; (void) drawable; @@ -1860,14 +1867,15 @@ static GLint __glXGetFrameUsageMESA(Display *dpy, GLXDrawable drawable, int status = GLX_BAD_CONTEXT; #ifdef __DRI_FRAME_TRACKING int screen; - __DRIdrawable * const pdraw = GetDRIDrawable(dpy, drawable, & screen); + __GLXDRIdrawable * const pdraw = GetGLXDRIDrawable(dpy, drawable, & screen); __GLXscreenConfigs * const psc = GetGLXScreenConfigs(dpy, screen); if (pdraw != NULL && psc->frameTracking != NULL) { int64_t sbc, missedFrames; float lastMissedUsage; - status = psc->frameTracking->queryFrameTracking(pdraw, &sbc, + status = psc->frameTracking->queryFrameTracking(pdraw->driDrawable, + &sbc, &missedFrames, &lastMissedUsage, usage); @@ -1888,13 +1896,14 @@ static GLint __glXQueryFrameTrackingMESA(Display *dpy, GLXDrawable drawable, int status = GLX_BAD_CONTEXT; #ifdef __DRI_FRAME_TRACKING int screen; - __DRIdrawable * const pdraw = GetDRIDrawable(dpy, drawable, & screen); + __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, & screen); __GLXscreenConfigs * const psc = GetGLXScreenConfigs(dpy, screen); if (pdraw != NULL && psc->frameTracking != NULL) { float usage; - status = psc->frameTracking->queryFrameTracking(pdraw, sbc, missedFrames, + status = psc->frameTracking->queryFrameTracking(pdraw->driDrawable, + sbc, missedFrames, lastMissedUsage, &usage); } #else @@ -1925,12 +1934,13 @@ static int __glXGetVideoSyncSGI(unsigned int *count) __GLXscreenConfigs * const psc = GetGLXScreenConfigs( gc->currentDpy, gc->screen ); if ( psc->msc && psc->driScreen ) { - __DRIdrawable * const pdraw = - GetDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL); + __GLXDRIdrawable *pdraw = + GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL); int64_t temp; int ret; - ret = (*psc->msc->getDrawableMSC)(&psc->__driScreen, pdraw, &temp); + ret = (*psc->msc->getDrawableMSC)(psc->__driScreen, + pdraw->driDrawable, &temp); *count = (unsigned) temp; return (ret == 0) ? 0 : GLX_BAD_CONTEXT; @@ -1954,14 +1964,14 @@ static int __glXWaitVideoSyncSGI(int divisor, int remainder, unsigned int *count __GLXscreenConfigs * const psc = GetGLXScreenConfigs( gc->currentDpy, gc->screen ); if (psc->msc != NULL && psc->driScreen ) { - __DRIdrawable * const pdraw = - GetDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL); + __GLXDRIdrawable *pdraw = + GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL); int ret; int64_t msc; int64_t sbc; - ret = (*psc->msc->waitForMSC)(pdraw, 0, divisor, remainder, &msc, - &sbc); + ret = (*psc->msc->waitForMSC)(pdraw->driDrawable, 0, + divisor, remainder, &msc, &sbc); *count = (unsigned) msc; return (ret == 0) ? 0 : GLX_BAD_CONTEXT; } @@ -2120,13 +2130,13 @@ static Bool __glXGetSyncValuesOML(Display *dpy, GLXDrawable drawable, if ( priv != NULL ) { int i; - __DRIdrawable * const pdraw = GetDRIDrawable( dpy, drawable, & i ); + __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &i); __GLXscreenConfigs * const psc = &priv->screenConfigs[i]; assert( (pdraw == NULL) || (i != -1) ); return ( (pdraw && psc->sbc && psc->msc) - && ((*psc->msc->getMSC)(&psc->driScreen, msc) == 0) - && ((*psc->sbc->getSBC)(pdraw, sbc) == 0) + && ((*psc->msc->getMSC)(psc->driScreen, msc) == 0) + && ((*psc->sbc->getSBC)(pdraw->driDrawable, sbc) == 0) && (__glXGetUST(ust) == 0) ); } #else @@ -2141,16 +2151,16 @@ static Bool __glXGetSyncValuesOML(Display *dpy, GLXDrawable drawable, #ifdef GLX_DIRECT_RENDERING _X_HIDDEN GLboolean -__driGetMscRateOML(__DRIdrawable *draw, int32_t *numerator, int32_t *denominator) +__driGetMscRateOML(__DRIdrawable *draw, + int32_t *numerator, int32_t *denominator, void *private) { #ifdef XF86VIDMODE __GLXscreenConfigs *psc; XF86VidModeModeLine mode_line; int dot_clock; int i; - __GLXDRIdrawable *glxDraw; + __GLXDRIdrawable *glxDraw = private; - glxDraw = containerOf(draw, __GLXDRIdrawable, driDrawable); psc = glxDraw->psc; if (XF86VidModeQueryVersion(psc->dpy, &i, &i) && XF86VidModeGetModeLine(psc->dpy, psc->scr, &dot_clock, &mode_line) ) { @@ -2223,12 +2233,12 @@ _X_HIDDEN GLboolean __glXGetMscRateOML(Display * dpy, GLXDrawable drawable, int32_t * denominator) { #if defined( GLX_DIRECT_RENDERING ) && defined( XF86VIDMODE ) - __DRIdrawable *driDraw = GetDRIDrawable(dpy, drawable, NULL); + __GLXDRIdrawable *draw = GetGLXDRIDrawable(dpy, drawable, NULL); - if (driDraw == NULL) + if (draw == NULL) return False; - return __driGetMscRateOML(driDraw, numerator, denominator); + return __driGetMscRateOML(draw->driDrawable, numerator, denominator, draw); #else (void) dpy; (void) drawable; @@ -2245,7 +2255,7 @@ static int64_t __glXSwapBuffersMscOML(Display *dpy, GLXDrawable drawable, { #ifdef __DRI_SWAP_BUFFER_COUNTER int screen; - __DRIdrawable *pdraw = GetDRIDrawable( dpy, drawable, & screen ); + __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen); __GLXscreenConfigs * const psc = GetGLXScreenConfigs( dpy, screen ); /* The OML_sync_control spec says these should "generate a GLX_BAD_VALUE @@ -2259,7 +2269,7 @@ static int64_t __glXSwapBuffersMscOML(Display *dpy, GLXDrawable drawable, return -1; if (pdraw != NULL && psc->counters != NULL) - return (*psc->sbc->swapBuffersMSC)(pdraw, target_msc, + return (*psc->sbc->swapBuffersMSC)(pdraw->driDrawable, target_msc, divisor, remainder); #else @@ -2280,7 +2290,7 @@ static Bool __glXWaitForMscOML(Display * dpy, GLXDrawable drawable, { #ifdef __DRI_MEDIA_STREAM_COUNTER int screen; - __DRIdrawable *pdraw = GetDRIDrawable( dpy, drawable, & screen ); + __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen); __GLXscreenConfigs * const psc = GetGLXScreenConfigs( dpy, screen ); int ret; @@ -2293,7 +2303,7 @@ static Bool __glXWaitForMscOML(Display * dpy, GLXDrawable drawable, return False; if (pdraw != NULL && psc->msc != NULL) { - ret = (*psc->msc->waitForMSC)(pdraw, target_msc, + ret = (*psc->msc->waitForMSC)(pdraw->driDrawable, target_msc, divisor, remainder, msc, sbc); /* __glXGetUST returns zero on success and non-zero on failure. @@ -2321,7 +2331,7 @@ static Bool __glXWaitForSbcOML(Display * dpy, GLXDrawable drawable, { #ifdef __DRI_SWAP_BUFFER_COUNTER int screen; - __DRIdrawable *pdraw = GetDRIDrawable( dpy, drawable, & screen ); + __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen); __GLXscreenConfigs * const psc = GetGLXScreenConfigs( dpy, screen ); int ret; @@ -2332,7 +2342,7 @@ static Bool __glXWaitForSbcOML(Display * dpy, GLXDrawable drawable, return False; if (pdraw != NULL && psc->sbc != NULL) { - ret = (*psc->sbc->waitForSBC)(pdraw, target_sbc, msc, sbc); + ret = (*psc->sbc->waitForSBC)(pdraw->driDrawable, target_sbc, msc, sbc); /* __glXGetUST returns zero on success and non-zero on failure. * This function returns True on success and False on failure. @@ -2364,9 +2374,8 @@ PUBLIC void *glXAllocateMemoryMESA(Display *dpy, int scrn, __GLXscreenConfigs * const psc = GetGLXScreenConfigs( dpy, scrn ); if (psc && psc->allocate) - return (*psc->allocate->allocateMemory)( &psc->__driScreen, size, - readFreq, writeFreq, - priority ); + return (*psc->allocate->allocateMemory)(psc->__driScreen, size, + readFreq, writeFreq, priority); #else (void) dpy; @@ -2387,7 +2396,7 @@ PUBLIC void glXFreeMemoryMESA(Display *dpy, int scrn, void *pointer) __GLXscreenConfigs * const psc = GetGLXScreenConfigs( dpy, scrn ); if (psc && psc->allocate) - (*psc->allocate->freeMemory)( &psc->__driScreen, pointer ); + (*psc->allocate->freeMemory)(psc->__driScreen, pointer); #else (void) dpy; @@ -2404,7 +2413,7 @@ PUBLIC GLuint glXGetMemoryOffsetMESA( Display *dpy, int scrn, __GLXscreenConfigs * const psc = GetGLXScreenConfigs( dpy, scrn ); if (psc && psc->allocate) - return (*psc->allocate->memoryOffset)( &psc->__driScreen, pointer ); + return (*psc->allocate->memoryOffset)(psc->__driScreen, pointer); #else (void) dpy; @@ -2480,11 +2489,12 @@ static void __glXCopySubBufferMESA(Display *dpy, GLXDrawable drawable, #ifdef __DRI_COPY_SUB_BUFFER int screen; - __DRIdrawable *pdraw = GetDRIDrawable( dpy, drawable, & screen ); + __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen); if ( pdraw != NULL ) { __GLXscreenConfigs * const psc = GetGLXScreenConfigs( dpy, screen ); if (psc->copySubBuffer != NULL) { - (*psc->copySubBuffer->copySubBuffer)(pdraw, x, y, width, height); + (*psc->copySubBuffer->copySubBuffer)(pdraw->driDrawable, + x, y, width, height); } return; @@ -2560,8 +2570,16 @@ static void __glXBindTexImageEXT(Display *dpy, } #ifdef GLX_DIRECT_RENDERING - if (gc->driContext) + if (gc->driContext) { + __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, NULL); + + if (pdraw != NULL) + (*pdraw->psc->texBuffer->setTexBuffer)(gc->__driContext, + pdraw->textureTarget, + pdraw->driDrawable); + return; + } #endif opcode = __glXSetupForCommand(dpy); diff --git a/src/glx/x11/glxext.c b/src/glx/x11/glxext.c index 525faab10e9..cd5c3196e36 100644 --- a/src/glx/x11/glxext.c +++ b/src/glx/x11/glxext.c @@ -107,9 +107,6 @@ static int _mesa_sparc_needs_init = 1; #define INIT_MESA_SPARC #endif -static Bool MakeContextCurrent(Display *dpy, GLXDrawable draw, - GLXDrawable read, GLXContext gc); - /* ** We setup some dummy structures here so that the API can be used ** even if no context is current. @@ -348,10 +345,10 @@ static void FreeScreenConfigs(__GLXdisplayPrivate *priv) Xfree((char*) psc->serverGLXexts); #ifdef GLX_DIRECT_RENDERING - if (psc->driScreen) + if (psc->driScreen) { psc->driScreen->destroyScreen(psc); - if (psc->drawHash) __glxHashDestroy(psc->drawHash); + } #endif } XFree((char*) priv->screenConfigs); @@ -381,6 +378,9 @@ static int __glXFreeDisplayPrivate(XExtData *extension) if (priv->driDisplay) (*priv->driDisplay->destroyDisplay)(priv->driDisplay); priv->driDisplay = NULL; + if (priv->dri2Display) + (*priv->dri2Display->destroyDisplay)(priv->dri2Display); + priv->dri2Display = NULL; #endif Xfree((char*) priv); @@ -774,14 +774,16 @@ static Bool AllocAndFetchScreenConfigs(Display *dpy, __GLXdisplayPrivate *priv) psc->scr = i; psc->dpy = dpy; #ifdef GLX_DIRECT_RENDERING - if (priv->driDisplay) { - /* Create drawable hash */ - psc->drawHash = __glxHashCreate(); - if (psc->drawHash == NULL) - continue; + psc->drawHash = __glxHashCreate(); + if (psc->drawHash == NULL) + continue; + if (priv->dri2Display) + psc->driScreen = (*priv->dri2Display->createScreen)(psc, i, priv); + if (psc->driScreen == NULL && priv->driDisplay) psc->driScreen = (*priv->driDisplay->createScreen)(psc, i, priv); - if (psc->driScreen == NULL) - __glxHashDestroy(psc->drawHash); + if (psc->driScreen == NULL) { + __glxHashDestroy(psc->drawHash); + psc->drawHash = NULL; } #endif } @@ -872,7 +874,8 @@ _X_HIDDEN __GLXdisplayPrivate *__glXInitialize(Display* dpy) ** (e.g., those called in AllocAndFetchScreenConfigs). */ if (getenv("LIBGL_ALWAYS_INDIRECT") == NULL) { - dpyPriv->driDisplay = driCreateDisplay(dpy); + dpyPriv->dri2Display = dri2CreateDisplay(dpy); + dpyPriv->driDisplay = driCreateDisplay(dpy); } #endif @@ -1188,21 +1191,35 @@ static Bool SendMakeCurrentRequest(Display *dpy, CARD8 opcode, #ifdef GLX_DIRECT_RENDERING static __GLXDRIdrawable * -FetchDRIDrawable(Display *dpy, GLXDrawable drawable, GLXContext gc) +FetchDRIDrawable(Display *dpy, + GLXDrawable glxDrawable, GLXContext gc, Bool pre13) { __GLXdisplayPrivate * const priv = __glXInitialize(dpy); __GLXDRIdrawable *pdraw; __GLXscreenConfigs *psc; + XID drawable; - if (priv == NULL || priv->driDisplay == NULL) + if (priv == NULL) return NULL; psc = &priv->screenConfigs[gc->screen]; - if (__glxHashLookup(psc->drawHash, drawable, (void *) &pdraw) == 0) + if (psc->drawHash == NULL) + return NULL; + + if (__glxHashLookup(psc->drawHash, glxDrawable, (void *) &pdraw) == 0) return pdraw; - pdraw = psc->driScreen->createDrawable(psc, drawable, gc); - if (__glxHashInsert(psc->drawHash, drawable, pdraw)) { + /* If this is glXMakeCurrent (pre GLX 1.3) we allow creating the + * GLX drawable on the fly. Otherwise we pass None as the X + * drawable */ + if (pre13) + drawable = glxDrawable; + else + drawable = None; + + pdraw = psc->driScreen->createDrawable(psc, drawable, + glxDrawable, gc->mode); + if (__glxHashInsert(psc->drawHash, glxDrawable, pdraw)) { (*pdraw->destroyDrawable)(pdraw); return NULL; } @@ -1218,7 +1235,8 @@ FetchDRIDrawable(Display *dpy, GLXDrawable drawable, GLXContext gc) * \note This is in this file so that it can access dummyContext. */ static Bool MakeContextCurrent(Display *dpy, GLXDrawable draw, - GLXDrawable read, GLXContext gc) + GLXDrawable read, GLXContext gc, + Bool pre13) { xGLXMakeCurrentReply reply; const GLXContext oldGC = __glXGetCurrentContext(); @@ -1245,8 +1263,8 @@ static Bool MakeContextCurrent(Display *dpy, GLXDrawable draw, #ifdef GLX_DIRECT_RENDERING /* Bind the direct rendering context to the drawable */ if (gc && gc->driContext) { - __GLXDRIdrawable *pdraw = FetchDRIDrawable(dpy, draw, gc); - __GLXDRIdrawable *pread = FetchDRIDrawable(dpy, read, gc); + __GLXDRIdrawable *pdraw = FetchDRIDrawable(dpy, draw, gc, pre13); + __GLXDRIdrawable *pread = FetchDRIDrawable(dpy, read, gc, pre13); bindReturnValue = (gc->driContext->bindContext) (gc->driContext, pdraw, pread); @@ -1368,16 +1386,16 @@ static Bool MakeContextCurrent(Display *dpy, GLXDrawable draw, PUBLIC Bool glXMakeCurrent(Display *dpy, GLXDrawable draw, GLXContext gc) { - return MakeContextCurrent( dpy, draw, draw, gc ); + return MakeContextCurrent(dpy, draw, draw, gc, True); } PUBLIC GLX_ALIAS(Bool, glXMakeCurrentReadSGI, (Display *dpy, GLXDrawable d, GLXDrawable r, GLXContext ctx), - (dpy, d, r, ctx), MakeContextCurrent) + (dpy, d, r, ctx, False), MakeContextCurrent) PUBLIC GLX_ALIAS(Bool, glXMakeContextCurrent, (Display *dpy, GLXDrawable d, GLXDrawable r, GLXContext ctx), - (dpy, d, r, ctx), MakeContextCurrent) + (dpy, d, r, ctx, False), MakeContextCurrent) #ifdef DEBUG diff --git a/src/glx/x11/glxextensions.c b/src/glx/x11/glxextensions.c index 6d78c7067d1..e8437184722 100644 --- a/src/glx/x11/glxextensions.c +++ b/src/glx/x11/glxextensions.c @@ -356,72 +356,16 @@ __glXProcessServerString( const struct extension_info * ext, } } -#ifdef GLX_DIRECT_RENDERING - void -__glXScrEnableDRIExtension(__GLXscreenConfigs *psc) +__glXEnableDirectExtension(__GLXscreenConfigs *psc, const char *name) { - const __DRIextension **extensions; - int i; - __glXExtensionsCtr(); __glXExtensionsCtrScreen(psc); - extensions = psc->__driScreen.getExtensions(&psc->__driScreen); - for (i = 0; extensions[i]; i++) { -#ifdef __DRI_COPY_SUB_BUFFER - if (strcmp(extensions[i]->name, __DRI_COPY_SUB_BUFFER) == 0) { - psc->copySubBuffer = (__DRIcopySubBufferExtension *) extensions[i]; - SET_BIT(psc->direct_support, MESA_copy_sub_buffer_bit); - } -#endif - -#ifdef __DRI_SWAP_CONTROL - if (strcmp(extensions[i]->name, __DRI_SWAP_CONTROL) == 0) { - psc->swapControl = (__DRIswapControlExtension *) extensions[i]; - SET_BIT(psc->direct_support, SGI_swap_control_bit); - SET_BIT(psc->direct_support, MESA_swap_control_bit); - } -#endif - -#ifdef __DRI_ALLOCATE - if (strcmp(extensions[i]->name, __DRI_ALLOCATE) == 0) { - psc->allocate = (__DRIallocateExtension *) extensions[i]; - SET_BIT(psc->direct_support, MESA_allocate_memory_bit); - } -#endif - -#ifdef __DRI_FRAME_TRACKING - if (strcmp(extensions[i]->name, __DRI_FRAME_TRACKING) == 0) { - psc->frameTracking = (__DRIframeTrackingExtension *) extensions[i]; - SET_BIT(psc->direct_support, MESA_swap_frame_usage_bit); - } -#endif - -#ifdef __DRI_MEDIA_STREAM_COUNTER - if (strcmp(extensions[i]->name, __DRI_MEDIA_STREAM_COUNTER) == 0) { - psc->msc = (__DRImediaStreamCounterExtension *) extensions[i]; - SET_BIT(psc->direct_support, SGI_video_sync_bit); - } -#endif - -#ifdef __DRI_SWAP_BUFFER_COUNTER - /* No driver supports this at this time and the extension is - * not defined in dri_interface.h. Will enable - * GLX_OML_sync_control if implemented. */ -#endif - -#ifdef __DRI_READ_DRAWABLE - if (strcmp(extensions[i]->name, __DRI_READ_DRAWABLE) == 0) { - SET_BIT(psc->direct_support, SGI_make_current_read_bit); - } -#endif - /* Ignore unknown extensions */ - } + set_glx_extension(known_glx_extensions, + name, strlen(name), GL_TRUE, psc->direct_support); } -#endif - /** * Initialize global extension support tables. */ diff --git a/src/glx/x11/glxextensions.h b/src/glx/x11/glxextensions.h index 144b02ad033..9cdd05ed761 100644 --- a/src/glx/x11/glxextensions.h +++ b/src/glx/x11/glxextensions.h @@ -235,10 +235,6 @@ extern const char * __glXGetClientExtensions( void ); extern void __glXCalculateUsableExtensions( struct __GLXscreenConfigsRec *psc, GLboolean display_is_direct_capable, int server_minor_version ); -#ifdef GLX_DIRECT_RENDERING -extern void __glXScrEnableDRIExtension( struct __GLXscreenConfigsRec *psc ); -#endif - extern void __glXCalculateUsableGLExtensions( struct __GLXcontextRec * gc, const char * server_string, int major_version, int minor_version ); extern void __glXGetGLVersion( int * major_version, int * minor_version ); @@ -247,6 +243,8 @@ extern char * __glXGetClientGLExtensionString( void ); extern GLboolean __glExtensionBitIsEnabled( const struct __GLXcontextRec * gc, unsigned bit ); +extern void +__glXEnableDirectExtension(__GLXscreenConfigs *psc, const char *name); /* Source-level backwards compatibility with old drivers. They won't * find the respective functions, though. |