From: Jesse Barnes Date: Wed, 16 Sep 2009 06:23:09 +0000 (-0700) Subject: DRI2: add OML_sync_control support X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=daf7fe69f7bd0caa955d30b43fc35b7ce0069b6b;p=mesa.git DRI2: add OML_sync_control support Add OML_sync_control support, along with a simple program for testing it. This means adding support for the DRI2GetMSC, DRI2WaitMSC and DRI2WaitSBC requests. Signed-off-by: Jesse Barnes --- diff --git a/progs/xdemos/.gitignore b/progs/xdemos/.gitignore index 1b9b3a87c01..5ae0f5a0627 100644 --- a/progs/xdemos/.gitignore +++ b/progs/xdemos/.gitignore @@ -26,3 +26,4 @@ xdemo xfont xrotfontdemo yuvrect_client +msctest diff --git a/progs/xdemos/Makefile b/progs/xdemos/Makefile index 77f667978ce..f866a328656 100644 --- a/progs/xdemos/Makefile +++ b/progs/xdemos/Makefile @@ -29,6 +29,7 @@ PROGS = \ glxsnoop \ glxswapcontrol \ manywin \ + msctest \ multictx \ offset \ overlay \ diff --git a/progs/xdemos/msctest.c b/progs/xdemos/msctest.c new file mode 100644 index 00000000000..001ecf04d6c --- /dev/null +++ b/progs/xdemos/msctest.c @@ -0,0 +1,202 @@ +/* + * Copyright © 2009 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Jesse Barnes + * + */ + +/** @file msctest.c + * Simple test for MSC functionality. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void (*get_sync_values)(Display *dpy, Window winGL, int64_t *ust, int64_t *msc, int64_t *sbc); +void (*wait_sync)(Display *dpy, Window winGL, int64_t target_msc, int64_t divisor, int64_t remainder, int64_t *ust, int64_t *msc, int64_t *sbc); + +static int GLXExtensionSupported(Display *dpy, const char *extension) +{ + const char *extensionsString, *client_extensions, *pos; + + extensionsString = glXQueryExtensionsString(dpy, DefaultScreen(dpy)); + client_extensions = glXGetClientString(dpy, GLX_EXTENSIONS); + + pos = strstr(extensionsString, extension); + + if (pos != NULL && (pos == extensionsString || pos[-1] == ' ') && + (pos[strlen(extension)] == ' ' || pos[strlen(extension)] == '\0')) + return 1; + + pos = strstr(client_extensions, extension); + + if (pos != NULL && (pos == extensionsString || pos[-1] == ' ') && + (pos[strlen(extension)] == ' ' || pos[strlen(extension)] == '\0')) + return 1; + + return 0; +} + +extern char *optarg; +extern int optind, opterr, optopt; +static char optstr[] = "v"; + +static void usage(char *name) +{ + printf("usage: %s\n", name); + exit(-1); +} + +int main(int argc, char *argv[]) +{ + Display *disp; + XVisualInfo *pvi; + XSetWindowAttributes swa; + int attrib[14]; + Window winGL; + GLXContext context; + int dummy; + Atom wmDelete; + int verbose = 0, width = 200, height = 200; + int c, i = 1; + int64_t ust, msc, sbc; + + opterr = 0; + while ((c = getopt(argc, argv, optstr)) != -1) { + switch (c) { + case 'v': + verbose = 1; + break; + default: + usage(argv[0]); + break; + } + } + + disp = XOpenDisplay(NULL); + if (!disp) { + fprintf(stderr, "failed to open display\n"); + return -1; + } + + if (!glXQueryExtension(disp, &dummy, &dummy)) { + fprintf(stderr, "glXQueryExtension failed\n"); + return -1; + } + + if (!GLXExtensionSupported(disp, "GLX_OML_sync_control")) { + fprintf(stderr, "GLX_OML_sync_control not supported, exiting\n"); + return -1; + } + + attrib[0] = GLX_RGBA; + attrib[1] = 1; + attrib[2] = GLX_RED_SIZE; + attrib[3] = 1; + attrib[4] = GLX_GREEN_SIZE; + attrib[5] = 1; + attrib[6] = GLX_BLUE_SIZE; + attrib[7] = 1; + attrib[8] = GLX_DOUBLEBUFFER; + attrib[9] = 1; + attrib[10] = None; + + pvi = glXChooseVisual(disp, DefaultScreen(disp), attrib); + if (!pvi) { + fprintf(stderr, "failed to choose visual, exiting\n"); + return -1; + } + + context = glXCreateContext(disp, pvi, None, GL_TRUE); + if (!context) { + fprintf(stderr, "failed to create glx context\n"); + return -1; + } + + pvi->screen = DefaultScreen(disp); + + swa.colormap = XCreateColormap(disp, RootWindow(disp, pvi->screen), + pvi->visual, AllocNone); + swa.border_pixel = 0; + swa.event_mask = ExposureMask | KeyPressMask | ButtonPressMask | + StructureNotifyMask; + winGL = XCreateWindow(disp, RootWindow(disp, pvi->screen), + 0, 0, + width, height, + 0, pvi->depth, InputOutput, pvi->visual, + CWBorderPixel | CWColormap | CWEventMask, &swa); + if (!winGL) { + fprintf(stderr, "window creation failed\n"); + return -1; + } + wmDelete = XInternAtom(disp, "WM_DELETE_WINDOW", True); + XSetWMProtocols(disp, winGL, &wmDelete, 1); + + XSetStandardProperties(disp, winGL, "msc test", "msc text", + None, NULL, 0, NULL); + + XMapRaised(disp, winGL); + + glXMakeCurrent(disp, winGL, context); + + get_sync_values = glXGetProcAddress((unsigned char *)"glXGetSyncValuesOML"); + wait_sync = glXGetProcAddress((unsigned char *)"glXWaitForMscOML"); + + if (!get_sync_values || !wait_sync) { + fprintf(stderr, "failed to get sync values function\n"); + return -1; + } + + while (i++) { + get_sync_values(disp, winGL, &ust, &msc, &sbc); + fprintf(stderr, "ust: %llu, msc: %llu, sbc: %llu\n", ust, msc, + sbc); + + /* Alternate colors to make tearing obvious */ + if (i & 1) + glClearColor(1.0f, 1.0f, 1.0f, 1.0f); + else + glClearColor(1.0f, 0.0f, 0.0f, 0.0f); + glClear(GL_COLOR_BUFFER_BIT); + glXSwapBuffers(disp, winGL); + wait_sync(disp, winGL, 0, 60, 0, &ust, &msc, &sbc); + fprintf(stderr, + "wait returned ust: %llu, msc: %llu, sbc: %llu\n", + ust, msc, sbc); + sleep(1); + } + + XDestroyWindow(disp, winGL); + glXDestroyContext(disp, context); + XCloseDisplay(disp); + + return 0; +} diff --git a/src/glx/x11/dri2.c b/src/glx/x11/dri2.c index a0f8901d42d..922edbdcf52 100644 --- a/src/glx/x11/dri2.c +++ b/src/glx/x11/dri2.c @@ -34,6 +34,7 @@ #ifdef GLX_DIRECT_RENDERING #define NEED_REPLIES +#include #include #include #include @@ -380,10 +381,30 @@ DRI2CopyRegion(Display * dpy, XID drawable, XserverRegion region, SyncHandle(); } -void DRI2SwapBuffers(Display *dpy, XID drawable) +static void +load_swap_req(xDRI2SwapBuffersReq *req, CARD64 target, CARD64 divisor, + CARD64 remainder) +{ + req->target_msc_hi = target >> 32; + req->target_msc_lo = target & 0xffffffff; + req->divisor_hi = divisor >> 32; + req->divisor_lo = divisor & 0xffffffff; + req->remainder_hi = remainder >> 32; + req->remainder_lo = remainder & 0xffffffff; +} + +static CARD64 +vals_to_card64(CARD32 lo, CARD32 hi) +{ + return (CARD64)hi << 32 | lo; +} + +void DRI2SwapBuffers(Display *dpy, XID drawable, CARD64 target_msc, + CARD64 divisor, CARD64 remainder, CARD64 *count) { XExtDisplayInfo *info = DRI2FindDisplay(dpy); xDRI2SwapBuffersReq *req; + xDRI2SwapBuffersReply rep; XextSimpleCheckExtension (dpy, info, dri2ExtensionName); @@ -392,8 +413,128 @@ void DRI2SwapBuffers(Display *dpy, XID drawable) req->reqType = info->codes->major_opcode; req->dri2ReqType = X_DRI2SwapBuffers; req->drawable = drawable; + load_swap_req(req, target_msc, divisor, remainder); + + _XReply(dpy, (xReply *)&rep, 0, xFalse); + + *count = vals_to_card64(rep.swap_lo, rep.swap_hi); + + UnlockDisplay(dpy); + SyncHandle(); +} + +Bool DRI2GetMSC(Display *dpy, XID drawable, CARD64 *ust, CARD64 *msc, + CARD64 *sbc) +{ + XExtDisplayInfo *info = DRI2FindDisplay(dpy); + xDRI2GetMSCReq *req; + xDRI2MSCReply rep; + + XextCheckExtension (dpy, info, dri2ExtensionName, False); + + LockDisplay(dpy); + GetReq(DRI2GetMSC, req); + req->reqType = info->codes->major_opcode; + req->dri2ReqType = X_DRI2GetMSC; + req->drawable = drawable; + + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + + *ust = vals_to_card64(rep.ust_lo, rep.ust_hi); + *msc = vals_to_card64(rep.msc_lo, rep.msc_hi); + *sbc = vals_to_card64(rep.sbc_lo, rep.sbc_hi); + + UnlockDisplay(dpy); + SyncHandle(); + + return True; +} + +static void +load_msc_req(xDRI2WaitMSCReq *req, CARD64 target, CARD64 divisor, + CARD64 remainder) +{ + req->target_msc_hi = target >> 32; + req->target_msc_lo = target & 0xffffffff; + req->divisor_hi = divisor >> 32; + req->divisor_lo = divisor & 0xffffffff; + req->remainder_hi = remainder >> 32; + req->remainder_lo = remainder & 0xffffffff; +} + +Bool DRI2WaitMSC(Display *dpy, XID drawable, CARD64 target_msc, CARD64 divisor, + CARD64 remainder, CARD64 *ust, CARD64 *msc, CARD64 *sbc) +{ + XExtDisplayInfo *info = DRI2FindDisplay(dpy); + xDRI2WaitMSCReq *req; + xDRI2MSCReply rep; + + XextCheckExtension (dpy, info, dri2ExtensionName, False); + + LockDisplay(dpy); + GetReq(DRI2WaitMSC, req); + req->reqType = info->codes->major_opcode; + req->dri2ReqType = X_DRI2WaitMSC; + req->drawable = drawable; + load_msc_req(req, target_msc, divisor, remainder); + + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + + *ust = ((CARD64)rep.ust_hi << 32) | (CARD64)rep.ust_lo; + *msc = ((CARD64)rep.msc_hi << 32) | (CARD64)rep.msc_lo; + *sbc = ((CARD64)rep.sbc_hi << 32) | (CARD64)rep.sbc_lo; + + UnlockDisplay(dpy); + SyncHandle(); + + return True; +} + +static void +load_sbc_req(xDRI2WaitSBCReq *req, CARD64 target) +{ + req->target_sbc_hi = target >> 32; + req->target_sbc_lo = target & 0xffffffff; +} + +Bool DRI2WaitSBC(Display *dpy, XID drawable, CARD64 target_sbc, CARD64 *ust, + CARD64 *msc, CARD64 *sbc) +{ + XExtDisplayInfo *info = DRI2FindDisplay(dpy); + xDRI2WaitSBCReq *req; + xDRI2MSCReply rep; + + XextCheckExtension (dpy, info, dri2ExtensionName, False); + + LockDisplay(dpy); + GetReq(DRI2WaitSBC, req); + req->reqType = info->codes->major_opcode; + req->dri2ReqType = X_DRI2WaitSBC; + req->drawable = drawable; + load_sbc_req(req, target_sbc); + + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + + *ust = ((CARD64)rep.ust_hi << 32) | rep.ust_lo; + *msc = ((CARD64)rep.msc_hi << 32) | rep.msc_lo; + *sbc = ((CARD64)rep.sbc_hi << 32) | rep.sbc_lo; + UnlockDisplay(dpy); SyncHandle(); + + return True; } #endif /* GLX_DIRECT_RENDERING */ diff --git a/src/glx/x11/dri2.h b/src/glx/x11/dri2.h index ba6eff5e4f7..ae6030842cb 100644 --- a/src/glx/x11/dri2.h +++ b/src/glx/x11/dri2.h @@ -86,6 +86,18 @@ DRI2CopyRegion(Display * dpy, XID drawable, CARD32 dest, CARD32 src); extern void -DRI2SwapBuffers(Display *dpy, XID drawable); +DRI2SwapBuffers(Display *dpy, XID drawable, CARD64 target_msc, CARD64 divisor, + CARD64 remainder, CARD64 *count); + +extern Bool +DRI2GetMSC(Display *dpy, XID drawable, CARD64 *ust, CARD64 *msc, CARD64 *sbc); + +extern Bool +DRI2WaitMSC(Display *dpy, XID drawable, CARD64 target_msc, CARD64 divisor, + CARD64 remainder, CARD64 *ust, CARD64 *msc, CARD64 *sbc); + +extern Bool +DRI2WaitSBC(Display *dpy, XID drawable, CARD64 target_sbc, CARD64 *ust, + CARD64 *msc, CARD64 *sbc); #endif diff --git a/src/glx/x11/dri2_glx.c b/src/glx/x11/dri2_glx.c index 114cad2ae7d..86bfe46a855 100644 --- a/src/glx/x11/dri2_glx.c +++ b/src/glx/x11/dri2_glx.c @@ -199,9 +199,31 @@ dri2CreateDrawable(__GLXscreenConfigs * psc, return &pdraw->base; } +static int +dri2DrawableGetMSC(__GLXscreenConfigs *psc, __GLXDRIdrawable *pdraw, + int64_t *ust, int64_t *msc, int64_t *sbc) +{ + return DRI2GetMSC(psc->dpy, pdraw->drawable, ust, msc, sbc); +} + +static int +dri2WaitForMSC(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor, + int64_t remainder, int64_t *ust, int64_t *msc, int64_t *sbc) +{ + return DRI2WaitMSC(pdraw->psc->dpy, pdraw->drawable, target_msc, divisor, + remainder, ust, msc, sbc); +} + +static int +dri2WaitForSBC(__GLXDRIdrawable *pdraw, int64_t target_sbc, int64_t *ust, + int64_t *msc, int64_t *sbc) +{ + return DRI2WaitSBC(pdraw->psc->dpy, pdraw->drawable, target_sbc, ust, msc, + sbc); +} + static void -dri2CopySubBuffer(__GLXDRIdrawable * pdraw, - int x, int y, int width, int height) +dri2CopySubBuffer(__GLXDRIdrawable *pdraw, int x, int y, int width, int height) { __GLXDRIdrawablePrivate *priv = (__GLXDRIdrawablePrivate *) pdraw; XRectangle xrect; @@ -233,14 +255,6 @@ dri2CopySubBuffer(__GLXDRIdrawable * pdraw, dri2WaitX(pdraw); } -static void -dri2SwapBuffers(__GLXDRIdrawable * pdraw) -{ - __GLXDRIdrawablePrivate *priv = (__GLXDRIdrawablePrivate *) pdraw; - - dri2CopySubBuffer(pdraw, 0, 0, priv->width, priv->height); -} - static void dri2WaitX(__GLXDRIdrawable *pdraw) { @@ -344,13 +358,15 @@ process_buffers(__GLXDRIdrawablePrivate * pdraw, DRI2Buffer * buffers, } -static void dri2SwapBuffers(__GLXDRIdrawable *pdraw) +static int64_t +dri2SwapBuffers(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor, + int64_t remainder) { __GLXDRIdrawablePrivate *priv = (__GLXDRIdrawablePrivate *) pdraw; __GLXdisplayPrivate *dpyPriv = __glXInitialize(priv->base.psc->dpy); __GLXDRIdisplayPrivate *pdp = (__GLXDRIdisplayPrivate *)dpyPriv->dri2Display; - __GLXscreenConfigs *psc = pdraw->psc; + int64_t ret; #ifdef __DRI2_FLUSH if (pdraw->psc->f) @@ -358,15 +374,20 @@ static void dri2SwapBuffers(__GLXDRIdrawable *pdraw) #endif /* Old servers can't handle swapbuffers */ - if (!pdp->swapAvailable) - return dri2CopySubBuffer(pdraw, 0, 0, priv->width, priv->height); + if (!pdp->swapAvailable) { + dri2CopySubBuffer(pdraw, 0, 0, priv->width, priv->height); + return 0; + } - DRI2SwapBuffers(pdraw->psc->dpy, pdraw->drawable); + DRI2SwapBuffers(pdraw->psc->dpy, pdraw->drawable, target_msc, divisor, + remainder, &ret); #if __DRI2_FLUSH_VERSION >= 2 if (pdraw->psc->f) (*pdraw->psc->f->flushInvalidate)(pdraw->driDrawable); #endif + + return ret; } static __DRIbuffer * @@ -464,7 +485,7 @@ dri2CreateScreen(__GLXscreenConfigs * psc, int screen, psc->ext_list_first_time = GL_TRUE; if (!DRI2Connect(psc->dpy, RootWindow(psc->dpy, screen), - &driverName, &deviceName)) + &driverName, &deviceName)) return NULL; psc->driver = driOpenDriver(driverName); @@ -481,9 +502,9 @@ dri2CreateScreen(__GLXscreenConfigs * psc, int screen, for (i = 0; extensions[i]; i++) { if (strcmp(extensions[i]->name, __DRI_CORE) == 0) - psc->core = (__DRIcoreExtension *) extensions[i]; + psc->core = (__DRIcoreExtension *) extensions[i]; if (strcmp(extensions[i]->name, __DRI_DRI2) == 0) - psc->dri2 = (__DRIdri2Extension *) extensions[i]; + psc->dri2 = (__DRIdri2Extension *) extensions[i]; } if (psc->core == NULL || psc->dri2 == NULL) { @@ -512,16 +533,17 @@ dri2CreateScreen(__GLXscreenConfigs * psc, int screen, */ psc->__driScreen = psc->dri2->createNewScreen(screen, psc->fd, ((pdp->driMinor < 1) - ? loader_extensions_old - : loader_extensions), - &driver_configs, psc); + ? loader_extensions_old + : loader_extensions), + &driver_configs, psc); if (psc->__driScreen == NULL) { ErrorMessageF("failed to create dri screen\n"); return NULL; } - driBindExtensions(psc, 1); + driBindCommonExtensions(psc); + dri2BindExtensions(psc); psc->configs = driConvertConfigs(psc->core, psc->configs, driver_configs); psc->visuals = driConvertConfigs(psc->core, psc->visuals, driver_configs); @@ -534,6 +556,9 @@ dri2CreateScreen(__GLXscreenConfigs * psc, int screen, psp->swapBuffers = dri2SwapBuffers; psp->waitGL = dri2WaitGL; psp->waitX = dri2WaitX; + psp->getDrawableMSC = dri2DrawableGetMSC; + psp->waitForMSC = dri2WaitForMSC; + psp->waitForSBC = dri2WaitForSBC; /* DRI2 suports SubBuffer through DRI2CopyRegion, so it's always * available.*/ @@ -545,7 +570,7 @@ dri2CreateScreen(__GLXscreenConfigs * psc, int screen, return psp; - handle_error: +handle_error: Xfree(driverName); Xfree(deviceName); diff --git a/src/glx/x11/dri_common.c b/src/glx/x11/dri_common.c index 9c825ad74ab..a94c752194a 100644 --- a/src/glx/x11/dri_common.c +++ b/src/glx/x11/dri_common.c @@ -336,8 +336,9 @@ driConvertConfigs(const __DRIcoreExtension * core, return head.next; } +/* Bind DRI1 specific extensions */ _X_HIDDEN void -driBindExtensions(__GLXscreenConfigs * psc, int dri2) +driBindExtensions(__GLXscreenConfigs *psc) { const __DRIextension **extensions; int i; @@ -345,35 +346,13 @@ driBindExtensions(__GLXscreenConfigs * psc, int dri2) 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->driCopySubBuffer = - (__DRIcopySubBufferExtension *) extensions[i]; - __glXEnableDirectExtension(psc, "GLX_MESA_copy_sub_buffer"); - } -#endif - #ifdef __DRI_SWAP_CONTROL /* No DRI2 support for swap_control at the moment, since SwapBuffers * is done by the X server */ - if (strcmp(extensions[i]->name, __DRI_SWAP_CONTROL) == 0 && !dri2) { - 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"); + 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 @@ -390,23 +369,77 @@ driBindExtensions(__GLXscreenConfigs * psc, int dri2) * 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"); + /* Ignore unknown extensions */ + } +} + +/* Bind DRI2 specific extensions */ +_X_HIDDEN void +dri2BindExtensions(__GLXscreenConfigs *psc) +{ + const __DRIextension **extensions; + int i; + + extensions = psc->core->getExtensions(psc->__driScreen); + + for (i = 0; extensions[i]; i++) { +#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 -#ifdef __DRI_TEX_BUFFER - if ((strcmp(extensions[i]->name, __DRI_TEX_BUFFER) == 0) && dri2) { - psc->texBuffer = (__DRItexBufferExtension *) extensions[i]; - __glXEnableDirectExtension(psc, "GLX_EXT_texture_from_pixmap"); +#ifdef __DRI2_MEDIA_STREAM_COUNTER + if (strcmp(extensions[i]->name, __DRI2_MEDIA_STREAM_COUNTER) == 0) { + psc->msc = (__DRI2mediaStreamCounterExtension *) extensions[i]; + __glXEnableDirectExtension(psc, "GLX_SGI_video_sync"); } #endif #ifdef __DRI2_FLUSH - if ((strcmp(extensions[i]->name, __DRI2_FLUSH) == 0) && dri2) { - psc->f = (__DRI2flushExtension *) extensions[i]; - /* internal driver extension, no GL extension exposed */ + if ((strcmp(extensions[i]->name, __DRI2_FLUSH) == 0)) { + psc->f = (__DRI2flushExtension *) extensions[i]; + /* internal driver extension, no GL extension exposed */ + } +#endif + } +} + +/* Bind extensions common to DRI1 and DRI2 */ +_X_HIDDEN void +driBindCommonExtensions(__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->driCopySubBuffer = (__DRIcopySubBufferExtension *) extensions[i]; + __glXEnableDirectExtension(psc, "GLX_MESA_copy_sub_buffer"); + } +#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_READ_DRAWABLE + if (strcmp(extensions[i]->name, __DRI_READ_DRAWABLE) == 0) { + __glXEnableDirectExtension(psc, "GLX_SGI_make_current_read"); } #endif diff --git a/src/glx/x11/dri_common.h b/src/glx/x11/dri_common.h index 61ac9c64160..bb178db7875 100644 --- a/src/glx/x11/dri_common.h +++ b/src/glx/x11/dri_common.h @@ -56,6 +56,8 @@ extern void ErrorMessageF(const char *f, ...); extern void *driOpenDriver(const char *driverName); -extern void driBindExtensions(__GLXscreenConfigs * psc, int dri2); +extern void driBindExtensions(__GLXscreenConfigs * psc); +extern void dri2BindExtensions(__GLXscreenConfigs * psc); +extern void driBindCommonExtensions(__GLXscreenConfigs * psc); #endif /* _DRI_COMMON_H */ diff --git a/src/glx/x11/dri_glx.c b/src/glx/x11/dri_glx.c index 4f7acb6cc32..42cb25304e2 100644 --- a/src/glx/x11/dri_glx.c +++ b/src/glx/x11/dri_glx.c @@ -620,10 +620,12 @@ driCreateDrawable(__GLXscreenConfigs * psc, return pdraw; } -static void -driSwapBuffers(__GLXDRIdrawable * pdraw) +static int64_t +driSwapBuffers(__GLXDRIdrawable * pdraw, int64_t unused1, int64_t unused2, + int64_t unused3) { (*pdraw->psc->core->swapBuffers) (pdraw->driDrawable); + return 0; } static void @@ -683,9 +685,9 @@ driCreateScreen(__GLXscreenConfigs * psc, int screen, for (i = 0; extensions[i]; i++) { if (strcmp(extensions[i]->name, __DRI_CORE) == 0) - psc->core = (__DRIcoreExtension *) extensions[i]; + psc->core = (__DRIcoreExtension *) extensions[i]; if (strcmp(extensions[i]->name, __DRI_LEGACY) == 0) - psc->legacy = (__DRIlegacyExtension *) extensions[i]; + psc->legacy = (__DRIlegacyExtension *) extensions[i]; } if (psc->core == NULL || psc->legacy == NULL) { @@ -701,7 +703,9 @@ driCreateScreen(__GLXscreenConfigs * psc, int screen, return NULL; } - driBindExtensions(psc, 0); + driBindExtensions(psc); + driBindCommonExtensions(psc); + if (psc->driCopySubBuffer) psp->copySubBuffer = driCopySubBuffer; diff --git a/src/glx/x11/drisw_glx.c b/src/glx/x11/drisw_glx.c index 1866b2cc870..6a51d748afe 100644 --- a/src/glx/x11/drisw_glx.c +++ b/src/glx/x11/drisw_glx.c @@ -398,7 +398,8 @@ driCreateScreen(__GLXscreenConfigs * psc, int screen, goto handle_error; } - driBindExtensions(psc, 0); + driBindExtensions(psc); + driBindCommonExtensions(psc); psc->configs = driConvertConfigs(psc->core, psc->configs, driver_configs); psc->visuals = driConvertConfigs(psc->core, psc->visuals, driver_configs); diff --git a/src/glx/x11/glxclient.h b/src/glx/x11/glxclient.h index 00ee14fb05b..2b835a0a9ca 100644 --- a/src/glx/x11/glxclient.h +++ b/src/glx/x11/glxclient.h @@ -121,26 +121,33 @@ struct __GLXDRIdisplayRec __GLXdisplayPrivate * priv); }; -struct __GLXDRIscreenRec -{ - - void (*destroyScreen) (__GLXscreenConfigs * psc); - - __GLXDRIcontext *(*createContext) (__GLXscreenConfigs * psc, - const __GLcontextModes * mode, - GLXContext gc, - GLXContext shareList, int renderType); - - __GLXDRIdrawable *(*createDrawable) (__GLXscreenConfigs * psc, - XID drawable, - GLXDrawable glxDrawable, - const __GLcontextModes * modes); - - void (*swapBuffers) (__GLXDRIdrawable * pdraw); - void (*copySubBuffer) (__GLXDRIdrawable * pdraw, - int x, int y, int width, int height); - void (*waitX) (__GLXDRIdrawable * pdraw); - void (*waitGL) (__GLXDRIdrawable * pdraw); +struct __GLXDRIscreenRec { + + void (*destroyScreen)(__GLXscreenConfigs *psc); + + __GLXDRIcontext *(*createContext)(__GLXscreenConfigs *psc, + const __GLcontextModes *mode, + GLXContext gc, + GLXContext shareList, int renderType); + + __GLXDRIdrawable *(*createDrawable)(__GLXscreenConfigs *psc, + XID drawable, + GLXDrawable glxDrawable, + const __GLcontextModes *modes); + + int64_t (*swapBuffers)(__GLXDRIdrawable *pdraw, int64_t target_msc, + int64_t divisor, int64_t remainder); + void (*copySubBuffer)(__GLXDRIdrawable *pdraw, + int x, int y, int width, int height); + void (*waitX)(__GLXDRIdrawable *pdraw); + void (*waitGL)(__GLXDRIdrawable *pdraw); + int (*getDrawableMSC)(__GLXscreenConfigs *psc, __GLXDRIdrawable *pdraw, + int64_t *ust, int64_t *msc, int64_t *sbc); + int (*waitForMSC)(__GLXDRIdrawable *pdraw, int64_t target_msc, + int64_t divisor, int64_t remainder, int64_t *ust, + int64_t *msc, int64_t *sbc); + int (*waitForSBC)(__GLXDRIdrawable *pdraw, int64_t target_sbc, int64_t *ust, + int64_t *msc, int64_t *sbc); }; struct __GLXDRIcontextRec diff --git a/src/glx/x11/glxcmds.c b/src/glx/x11/glxcmds.c index daa9076471a..c7ccaaa0b5f 100644 --- a/src/glx/x11/glxcmds.c +++ b/src/glx/x11/glxcmds.c @@ -982,7 +982,7 @@ glXSwapBuffers(Display * dpy, GLXDrawable drawable) if (pdraw != NULL) { glFlush(); - (*pdraw->psc->driScreen->swapBuffers) (pdraw); + (*pdraw->psc->driScreen->swapBuffers)(pdraw, 0, 0, 0); return; } #endif @@ -1898,17 +1898,17 @@ __glXSwapIntervalSGI(int interval) #ifdef __DRI_SWAP_CONTROL if (gc->driContext) { - __GLXscreenConfigs *const psc = GetGLXScreenConfigs(gc->currentDpy, - gc->screen); + __GLXscreenConfigs * const psc = GetGLXScreenConfigs( gc->currentDpy, + gc->screen ); __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(gc->currentDpy, - gc->currentDrawable, - NULL); + gc->currentDrawable, + NULL); if (psc->swapControl != NULL && pdraw != NULL) { - psc->swapControl->setSwapInterval(pdraw->driDrawable, interval); - return 0; + psc->swapControl->setSwapInterval(pdraw->driDrawable, interval); + return 0; } - else { - return GLX_BAD_CONTEXT; + else if (pdraw == NULL) { + return GLX_BAD_CONTEXT; } } #endif @@ -2102,64 +2102,73 @@ __glXQueryFrameTrackingMESA(Display * dpy, GLXDrawable drawable, static int __glXGetVideoSyncSGI(unsigned int *count) { + int64_t ust, msc, sbc; + int ret; + GLXContext gc = __glXGetCurrentContext(); + __GLXscreenConfigs *psc; + __GLXDRIdrawable *pdraw; + + if (!gc || !gc->driContext) + return GLX_BAD_CONTEXT; + + psc = GetGLXScreenConfigs(gc->currentDpy, gc->screen); + pdraw = GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL); + /* FIXME: Looking at the GLX_SGI_video_sync spec in the extension registry, * FIXME: there should be a GLX encoding for this call. I can find no * FIXME: documentation for the GLX encoding. */ #ifdef __DRI_MEDIA_STREAM_COUNTER - GLXContext gc = __glXGetCurrentContext(); + if ( psc->msc && psc->driScreen ) { + ret = (*psc->msc->getDrawableMSC)(psc->__driScreen, + pdraw->driDrawable, &msc); + *count = (unsigned) msc; - - if (gc != NULL && gc->driContext) { - __GLXscreenConfigs *const psc = GetGLXScreenConfigs(gc->currentDpy, - gc->screen); - if (psc->msc && psc->driScreen) { - __GLXDRIdrawable *pdraw = - GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL); - int64_t temp; - int ret; - - ret = (*psc->msc->getDrawableMSC) (psc->__driScreen, - pdraw->driDrawable, &temp); - *count = (unsigned) temp; - - return (ret == 0) ? 0 : GLX_BAD_CONTEXT; - } + return (ret == 0) ? 0 : GLX_BAD_CONTEXT; } -#else - (void) count; #endif + if (psc->driScreen && psc->driScreen->getDrawableMSC) { + ret = psc->driScreen->getDrawableMSC(psc, pdraw, &ust, &msc, &sbc); + *count = (unsigned) msc; + return (ret == True) ? 0 : GLX_BAD_CONTEXT; + } + return GLX_BAD_CONTEXT; } static int __glXWaitVideoSyncSGI(int divisor, int remainder, unsigned int *count) { -#ifdef __DRI_MEDIA_STREAM_COUNTER GLXContext gc = __glXGetCurrentContext(); + __GLXscreenConfigs *psc; + __GLXDRIdrawable *pdraw; + int64_t ust, msc, sbc; + int ret; if (divisor <= 0 || remainder < 0) return GLX_BAD_VALUE; - if (gc != NULL && gc->driContext) { - __GLXscreenConfigs *const psc = GetGLXScreenConfigs(gc->currentDpy, - gc->screen); - if (psc->msc != NULL && psc->driScreen) { - __GLXDRIdrawable *pdraw = - GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL); - int ret; - int64_t msc; - int64_t sbc; - - ret = (*psc->msc->waitForMSC) (pdraw->driDrawable, 0, - divisor, remainder, &msc, &sbc); - *count = (unsigned) msc; - return (ret == 0) ? 0 : GLX_BAD_CONTEXT; - } + if (!gc || !gc->driContext) + return GLX_BAD_CONTEXT; + + psc = GetGLXScreenConfigs( gc->currentDpy, gc->screen); + pdraw = GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL); + +#ifdef __DRI_MEDIA_STREAM_COUNTER + if (psc->msc != NULL && psc->driScreen ) { + ret = (*psc->msc->waitForMSC)(pdraw->driDrawable, 0, + divisor, remainder, &msc, &sbc); + *count = (unsigned) msc; + return (ret == 0) ? 0 : GLX_BAD_CONTEXT; } -#else - (void) count; #endif + if (psc->driScreen && psc->driScreen->waitForMSC) { + ret = psc->driScreen->waitForMSC(pdraw, 0, divisor, remainder, &ust, &msc, + &sbc); + *count = (unsigned) msc; + return (ret == True) ? 0 : GLX_BAD_CONTEXT; + } + return GLX_BAD_CONTEXT; } @@ -2312,27 +2321,29 @@ static Bool __glXGetSyncValuesOML(Display * dpy, GLXDrawable drawable, int64_t * ust, int64_t * msc, int64_t * sbc) { -#if defined(__DRI_SWAP_BUFFER_COUNTER) && defined(__DRI_MEDIA_STREAM_COUNTER) - __GLXdisplayPrivate *const priv = __glXInitialize(dpy); + __GLXdisplayPrivate * const priv = __glXInitialize(dpy); + int i, ret; + __GLXDRIdrawable *pdraw; + __GLXscreenConfigs *psc; - if (priv != NULL) { - int i; - __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &i); - __GLXscreenConfigs *const psc = &priv->screenConfigs[i]; + if (!priv) + return False; - assert((pdraw == NULL) || (i != -1)); - return ((pdraw && psc->sbc && psc->msc) - && ((*psc->msc->getMSC) (psc->driScreen, msc) == 0) - && ((*psc->sbc->getSBC) (pdraw->driDrawable, sbc) == 0) - && (__glXGetUST(ust) == 0)); - } -#else - (void) dpy; - (void) drawable; - (void) ust; - (void) msc; - (void) sbc; + pdraw = GetGLXDRIDrawable(dpy, drawable, &i); + psc = &priv->screenConfigs[i]; + +#if defined(__DRI_SWAP_BUFFER_COUNTER) && defined(__DRI_MEDIA_STREAM_COUNTER) + if (pdraw && psc->sbc && psc->sbc) + return ( (pdraw && psc->sbc && psc->msc) + && ((*psc->msc->getMSC)(psc->driScreen, msc) == 0) + && ((*psc->sbc->getSBC)(pdraw->driDrawable, sbc) == 0) + && (__glXGetUST(ust) == 0) ); #endif + if (pdraw && psc && psc->driScreen && psc->driScreen->getDrawableMSC) { + ret = psc->driScreen->getDrawableMSC(psc, pdraw, ust, msc, sbc); + return ret; + } + return False; } @@ -2440,11 +2451,14 @@ static int64_t __glXSwapBuffersMscOML(Display * dpy, GLXDrawable drawable, int64_t target_msc, int64_t divisor, int64_t remainder) { -#ifdef __DRI_SWAP_BUFFER_COUNTER + GLXContext gc = __glXGetCurrentContext(); int screen; __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen); __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen); + if (!pdraw || !gc->driContext) /* no GLX for this */ + return -1; + /* The OML_sync_control spec says these should "generate a GLX_BAD_VALUE * error", but it also says "It [glXSwapBuffersMscOML] will return a value * of -1 if the function failed because of errors detected in the input @@ -2455,18 +2469,19 @@ __glXSwapBuffersMscOML(Display * dpy, GLXDrawable drawable, if (divisor > 0 && remainder >= divisor) return -1; - if (pdraw != NULL && psc->counters != NULL) - return (*psc->sbc->swapBuffersMSC) (pdraw->driDrawable, target_msc, - divisor, remainder); +#ifdef __DRI_SWAP_BUFFER_COUNTER + if (psc->counters != NULL) + return (*psc->sbc->swapBuffersMSC)(pdraw->driDrawable, target_msc, + divisor, remainder); +#endif -#else - (void) dpy; - (void) drawable; - (void) target_msc; - (void) divisor; - (void) remainder; +#ifdef GLX_DIRECT_RENDERING + if (psc->driScreen && psc->driScreen->swapBuffers) + return (*psc->driScreen->swapBuffers)(pdraw, target_msc, divisor, + remainder); #endif - return 0; + + return -1; } @@ -2476,12 +2491,14 @@ __glXWaitForMscOML(Display * dpy, GLXDrawable drawable, int64_t remainder, int64_t * ust, int64_t * msc, int64_t * sbc) { -#ifdef __DRI_MEDIA_STREAM_COUNTER - int screen = 0; + int screen; __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen); - __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen); + __GLXscreenConfigs * const psc = GetGLXScreenConfigs( dpy, screen ); int ret; + fprintf(stderr, "waitmsc: %lld, %lld, %lld\n", target_msc, divisor, + remainder); + /* The OML_sync_control spec says these should "generate a GLX_BAD_VALUE * error", but the return type in the spec is Bool. */ @@ -2490,7 +2507,9 @@ __glXWaitForMscOML(Display * dpy, GLXDrawable drawable, if (divisor > 0 && remainder >= divisor) return False; +#ifdef __DRI_MEDIA_STREAM_COUNTER if (pdraw != NULL && psc->msc != NULL) { + fprintf(stderr, "dri1 msc\n"); ret = (*psc->msc->waitForMSC) (pdraw->driDrawable, target_msc, divisor, remainder, msc, sbc); @@ -2499,16 +2518,14 @@ __glXWaitForMscOML(Display * dpy, GLXDrawable drawable, */ return ((ret == 0) && (__glXGetUST(ust) == 0)); } -#else - (void) dpy; - (void) drawable; - (void) target_msc; - (void) divisor; - (void) remainder; - (void) ust; - (void) msc; - (void) sbc; #endif + if (pdraw && psc->driScreen && psc->driScreen->waitForMSC) { + ret = psc->driScreen->waitForMSC(pdraw, target_msc, divisor, remainder, + ust, msc, sbc); + return ret; + } + + fprintf(stderr, "no drawable??\n"); return False; } @@ -2518,7 +2535,6 @@ __glXWaitForSbcOML(Display * dpy, GLXDrawable drawable, int64_t target_sbc, int64_t * ust, int64_t * msc, int64_t * sbc) { -#ifdef __DRI_SWAP_BUFFER_COUNTER int screen; __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen); __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen); @@ -2529,7 +2545,7 @@ __glXWaitForSbcOML(Display * dpy, GLXDrawable drawable, */ if (target_sbc < 0) return False; - +#ifdef __DRI_SWAP_BUFFER_COUNTER if (pdraw != NULL && psc->sbc != NULL) { ret = (*psc->sbc->waitForSBC) (pdraw->driDrawable, target_sbc, msc, sbc); @@ -2539,14 +2555,11 @@ __glXWaitForSbcOML(Display * dpy, GLXDrawable drawable, */ return ((ret == 0) && (__glXGetUST(ust) == 0)); } -#else - (void) dpy; - (void) drawable; - (void) target_sbc; - (void) ust; - (void) msc; - (void) sbc; #endif + if (pdraw && psc->driScreen && psc->driScreen->waitForMSC) { + ret = psc->driScreen->waitForSBC(pdraw, target_sbc, ust, msc, sbc); + return ret; + } return False; }