diff options
28 files changed, 1062 insertions, 239 deletions
diff --git a/configure.ac b/configure.ac index 43069de1ea..33437f54f8 100644 --- a/configure.ac +++ b/configure.ac @@ -20,7 +20,7 @@ AC_CANONICAL_HOST dnl Versions for external dependencies LIBDRM_REQUIRED=2.4.15 LIBDRM_RADEON_REQUIRED=2.4.17 -DRI2PROTO_REQUIRED=1.99.3 +DRI2PROTO_REQUIRED=2.2 dnl Check for progs AC_PROG_CPP diff --git a/include/GL/glx.h b/include/GL/glx.h index 2884401406..82b0f22114 100644 --- a/include/GL/glx.h +++ b/include/GL/glx.h @@ -186,6 +186,16 @@ typedef XID GLXWindow; typedef XID GLXPbuffer; +/* +** Events. +** __GLX_NUMBER_EVENTS is set to 17 to account for the BufferClobberSGIX +** event - this helps initialization if the server supports the pbuffer +** extension and the client doesn't. +*/ +#define GLX_PbufferClobber 0 +#define GLX_BufferSwapComplete 1 + +#define __GLX_NUMBER_EVENTS 17 extern XVisualInfo* glXChooseVisual( Display *dpy, int screen, int *attribList ); @@ -507,8 +517,17 @@ typedef struct { int count; /* if nonzero, at least this many more */ } GLXPbufferClobberEvent; +typedef struct { + int event_type; + GLXDrawable drawable; + int64_t ust; + int64_t msc; + int64_t sbc; +} GLXBufferSwapComplete; + typedef union __GLXEvent { GLXPbufferClobberEvent glxpbufferclobber; + GLXBufferSwapComplete glxbufferswapcomplete; long pad[24]; } GLXEvent; diff --git a/include/GL/glxext.h b/include/GL/glxext.h index 9ac0592e05..36ee3665df 100644 --- a/include/GL/glxext.h +++ b/include/GL/glxext.h @@ -696,6 +696,14 @@ extern void glXJoinSwapGroupSGIX (Display *, GLXDrawable, GLXDrawable); typedef void ( * PFNGLXJOINSWAPGROUPSGIXPROC) (Display *dpy, GLXDrawable drawable, GLXDrawable member); #endif +#ifndef GLX_INTEL_swap_event +#define GLX_INTEL_swap_event +#define GLX_BUFFER_SWAP_COMPLETE_MASK 0x10000000 +#define GLX_EXCHANGE_COMPLETE 0x8024 +#define GLX_BLIT_COMPLETE 0x8025 +#define GLX_FLIP_COMPLETE 0x8026 +#endif + #ifndef GLX_SGIX_swap_barrier #define GLX_SGIX_swap_barrier 1 #ifdef GLX_GLXEXT_PROTOTYPES diff --git a/include/GL/internal/dri_interface.h b/include/GL/internal/dri_interface.h index 910c9166b5..ec6238f873 100644 --- a/include/GL/internal/dri_interface.h +++ b/include/GL/internal/dri_interface.h @@ -262,10 +262,22 @@ struct __DRItexBufferExtensionRec { * Used by drivers that implement DRI2 */ #define __DRI2_FLUSH "DRI2_Flush" -#define __DRI2_FLUSH_VERSION 1 +#define __DRI2_FLUSH_VERSION 2 struct __DRI2flushExtensionRec { __DRIextension base; void (*flush)(__DRIdrawable *drawable); + + /** + * Flush all rendering queue in the driver to the drm and + * invalidate all buffers. The driver will call out to + * getBuffers/getBuffersWithFormat before it starts rendering + * again. + * + * \param drawable the drawable to flush and invalidate + * + * \since 2 + */ + void (*flushInvalidate)(__DRIdrawable *drawable); }; diff --git a/progs/xdemos/.gitignore b/progs/xdemos/.gitignore index 1b9b3a87c0..5ae0f5a062 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 77f667978c..f866a32865 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/glsync.c b/progs/xdemos/glsync.c index 9d4b0f1ce2..c00ba9e468 100644 --- a/progs/xdemos/glsync.c +++ b/progs/xdemos/glsync.c @@ -59,6 +59,7 @@ void (*video_sync_get)(); void (*video_sync)(); +void (*swap_interval)(); static int GLXExtensionSupported(Display *dpy, const char *extension) { @@ -84,7 +85,7 @@ static int GLXExtensionSupported(Display *dpy, const char *extension) extern char *optarg; extern int optind, opterr, optopt; -static char optstr[] = "w:h:s:v"; +static char optstr[] = "w:h:s:vi:"; enum sync_type { none = 0, @@ -100,6 +101,7 @@ static void usage(char *name) printf("\t\tn: none\n"); printf("\t\ts: SGI video sync extension\n"); printf("\t\tb: buffer swap\n"); + printf("\t-i<swap interval>\n"); printf("\t-v: verbose (print count)\n"); exit(-1); } @@ -109,16 +111,28 @@ int main(int argc, char *argv[]) Display *disp; XVisualInfo *pvi; XSetWindowAttributes swa; - int attrib[14]; GLint last_val = -1, count = 0; Window winGL; GLXContext context; int dummy; Atom wmDelete; enum sync_type waitforsync = none; - int width = 500, height = 500, verbose = 0, - countonly = 0; + int width = 500, height = 500, verbose = 0, interval = 1; int c, i = 1; + int ret; + int attribs[] = { GLX_RGBA, + GLX_RED_SIZE, 1, + GLX_GREEN_SIZE, 1, + GLX_BLUE_SIZE, 1, + None }; + int db_attribs[] = { GLX_RGBA, + GLX_RED_SIZE, 1, + GLX_GREEN_SIZE, 1, + GLX_BLUE_SIZE, 1, + GLX_DOUBLEBUFFER, + GLX_DEPTH_SIZE, 1, + None }; + XSizeHints sizehints; opterr = 0; while ((c = getopt(argc, argv, optstr)) != -1) { @@ -148,6 +162,9 @@ int main(int argc, char *argv[]) case 'v': verbose = 1; break; + case 'i': + interval = atoi(optarg); + break; default: usage(argv[0]); break; @@ -170,34 +187,17 @@ int main(int argc, char *argv[]) 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; - if (waitforsync != buffer_swap) - attrib[8] = None; - else { - attrib[8] = GLX_DOUBLEBUFFER; - attrib[9] = 1; - attrib[10] = None; + if (waitforsync != buffer_swap) { + pvi = glXChooseVisual(disp, DefaultScreen(disp), attribs); + } else { + pvi = glXChooseVisual(disp, DefaultScreen(disp), db_attribs); } - 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), @@ -217,24 +217,58 @@ int main(int argc, char *argv[]) wmDelete = XInternAtom(disp, "WM_DELETE_WINDOW", True); XSetWMProtocols(disp, winGL, &wmDelete, 1); + sizehints.x = 0; + sizehints.y = 0; + sizehints.width = width; + sizehints.height = height; + sizehints.flags = USSize | USPosition; + + XSetNormalHints(disp, winGL, &sizehints); XSetStandardProperties(disp, winGL, "glsync test", "glsync text", - None, NULL, 0, NULL); + None, NULL, 0, &sizehints); - XMapRaised(disp, winGL); + context = glXCreateContext(disp, pvi, NULL, GL_TRUE); + if (!context) { + fprintf(stderr, "failed to create glx context\n"); + return -1; + } - glXMakeCurrent(disp, winGL, context); + XMapWindow(disp, winGL); + ret = glXMakeCurrent(disp, winGL, context); + if (ret) { + fprintf(stderr, "failed to make context current: %d\n", ret); + } video_sync_get = glXGetProcAddress((unsigned char *)"glXGetVideoSyncSGI"); video_sync = glXGetProcAddress((unsigned char *)"glXWaitVideoSyncSGI"); - if (!video_sync_get || !video_sync) { + swap_interval = glXGetProcAddress((unsigned char *)"glXSwapIntervalSGI"); + + if (!video_sync_get || !video_sync || !swap_interval) { fprintf(stderr, "failed to get sync functions\n"); return -1; } + if (waitforsync == buffer_swap) { + swap_interval(interval); + fprintf(stderr, "set swap interval to %d\n", interval); + } video_sync_get(&count); count++; + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); while (i++) { + /* Alternate colors to make tearing obvious */ + if (i & 1) { + glClearColor(1.0f, 1.0f, 1.0f, 1.0f); + glColor3f(1.0f, 1.0f, 1.0f); + } else { + glClearColor(1.0f, 0.0f, 0.0f, 0.0f); + glColor3f(1.0f, 0.0f, 0.0f); + } + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glRectf(0, 0, width, height); + /* Wait for vsync */ if (waitforsync == sgi_video_sync) { if (verbose) @@ -245,24 +279,19 @@ int main(int argc, char *argv[]) if (count == last_val) fprintf(stderr, "error: count didn't change: %d\n", count); last_val = count; + glFlush(); } else if (waitforsync == buffer_swap) { glXSwapBuffers(disp, winGL); + } else { + video_sync_get(&count); + sleep(1); + glFinish(); } - if (countonly) { - video_sync(2, 1, &count); + if (verbose) { + video_sync_get(&count); fprintf(stderr, "current count: %d\n", count); - sleep(1); - continue; } - - /* 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); - glFlush(); } XDestroyWindow(disp, winGL); diff --git a/progs/xdemos/msctest.c b/progs/xdemos/msctest.c new file mode 100644 index 0000000000..001ecf04d6 --- /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 <jesse.barnes@intel.com> + * + */ + +/** @file msctest.c + * Simple test for MSC functionality. + */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <GL/gl.h> +#include <GL/glu.h> +#include <GL/glx.h> +#include <GL/glxext.h> +#include <X11/X.h> +#include <X11/Xlib.h> +#include <X11/Xutil.h> + +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 dad04470a0..2cb5d3463a 100644 --- a/src/glx/x11/dri2.c +++ b/src/glx/x11/dri2.c @@ -34,12 +34,15 @@ #ifdef GLX_DIRECT_RENDERING #define NEED_REPLIES +#include <stdio.h> #include <X11/Xlibint.h> #include <X11/extensions/Xext.h> #include <X11/extensions/extutil.h> #include <X11/extensions/dri2proto.h> #include "xf86drm.h" #include "dri2.h" +#include "glxclient.h" +#include "GL/glxext.h" /* Allow the build to work with an older versions of dri2proto.h and * dri2tokens.h. @@ -55,6 +58,11 @@ static char dri2ExtensionName[] = DRI2_NAME; static XExtensionInfo *dri2Info; static XEXT_GENERATE_CLOSE_DISPLAY (DRI2CloseDisplay, dri2Info) +static Bool +DRI2WireToEvent(Display *dpy, XEvent *event, xEvent *wire); +static Status +DRI2EventToWire(Display *dpy, XEvent *event, xEvent *wire); + static /* const */ XExtensionHooks dri2ExtensionHooks = { NULL, /* create_gc */ NULL, /* copy_gc */ @@ -63,8 +71,8 @@ static /* const */ XExtensionHooks dri2ExtensionHooks = { NULL, /* create_font */ NULL, /* free_font */ DRI2CloseDisplay, /* close_display */ - NULL, /* wire_to_event */ - NULL, /* event_to_wire */ + DRI2WireToEvent, /* wire_to_event */ + DRI2EventToWire, /* event_to_wire */ NULL, /* error */ NULL, /* error_string */ }; @@ -75,6 +83,65 @@ static XEXT_GENERATE_FIND_DISPLAY (DRI2FindDisplay, &dri2ExtensionHooks, 0, NULL) +static Bool +DRI2WireToEvent(Display *dpy, XEvent *event, xEvent *wire) +{ + XExtDisplayInfo *info = DRI2FindDisplay(dpy); + + XextCheckExtension(dpy, info, dri2ExtensionName, False); + + switch ((wire->u.u.type & 0x7f) - info->codes->first_event) { + case DRI2_BufferSwapComplete: + { + GLXBufferSwapComplete *aevent = (GLXBufferSwapComplete *)event; + xDRI2BufferSwapComplete *awire = (xDRI2BufferSwapComplete *)wire; + switch (awire->type) { + case DRI2_EXCHANGE_COMPLETE: + aevent->event_type = GLX_EXCHANGE_COMPLETE; + break; + case DRI2_BLIT_COMPLETE: + aevent->event_type = GLX_BLIT_COMPLETE; + break; + case DRI2_FLIP_COMPLETE: + aevent->event_type = GLX_FLIP_COMPLETE; + break; + default: + /* unknown swap completion type */ + return False; + } + aevent->drawable = awire->drawable; + aevent->ust = ((CARD64)awire->ust_hi << 32) | awire->ust_lo; + aevent->msc = ((CARD64)awire->msc_hi << 32) | awire->msc_lo; + aevent->sbc = ((CARD64)awire->sbc_hi << 32) | awire->sbc_lo; + return True; + } + default: + /* client doesn't support server event */ + break; + } + + return False; +} + +/* We don't actually support this. It doesn't make sense for clients to + * send each other DRI2 events. + */ +static Status +DRI2EventToWire(Display *dpy, XEvent *event, xEvent *wire) +{ + XExtDisplayInfo *info = DRI2FindDisplay(dpy); + + XextCheckExtension(dpy, info, dri2ExtensionName, False); + + switch (event->type) { + default: + /* client doesn't support server event */ + break; + } + + return Success; +} + Bool DRI2QueryExtension(Display * dpy, int *eventBase, int *errorBase) { @@ -380,4 +447,177 @@ DRI2CopyRegion(Display * dpy, XID drawable, XserverRegion region, SyncHandle(); } +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); + + LockDisplay(dpy); + GetReq(DRI2SwapBuffers, req); + 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; +} + +void DRI2SwapInterval(Display *dpy, XID drawable, int interval) +{ + XExtDisplayInfo *info = DRI2FindDisplay(dpy); + xDRI2SwapIntervalReq *req; + + XextSimpleCheckExtension (dpy, info, dri2ExtensionName); + + LockDisplay(dpy); + GetReq(DRI2SwapInterval, req); + req->reqType = info->codes->major_opcode; + req->dri2ReqType = X_DRI2SwapInterval; + req->drawable = drawable; + req->interval = interval; + UnlockDisplay(dpy); + SyncHandle(); +} + #endif /* GLX_DIRECT_RENDERING */ diff --git a/src/glx/x11/dri2.h b/src/glx/x11/dri2.h index a6fe66e136..114e9f8f96 100644 --- a/src/glx/x11/dri2.h +++ b/src/glx/x11/dri2.h @@ -85,4 +85,22 @@ DRI2CopyRegion(Display * dpy, XID drawable, XserverRegion region, CARD32 dest, CARD32 src); +extern void +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); + +extern void +DRI2SwapInterval(Display *dpy, XID drawable, int interval); + #endif diff --git a/src/glx/x11/dri2_glx.c b/src/glx/x11/dri2_glx.c index 89efe3ab29..83149062f3 100644 --- a/src/glx/x11/dri2_glx.c +++ b/src/glx/x11/dri2_glx.c @@ -35,6 +35,7 @@ #include <X11/Xlib.h> #include <X11/extensions/Xfixes.h> #include <X11/extensions/Xdamage.h> +#include "glapi.h" #include "glxclient.h" #include "glcontextmodes.h" #include "xf86dri.h" @@ -46,6 +47,7 @@ #include "xf86drm.h" #include "dri2.h" #include "dri_common.h" +#include "../../mesa/drivers/dri/common/dri_util.h" #undef DRI2_MINOR #define DRI2_MINOR 1 @@ -64,6 +66,7 @@ struct __GLXDRIdisplayPrivateRec int driMajor; int driMinor; int driPatch; + int swapAvailable; }; struct __GLXDRIcontextPrivateRec @@ -81,6 +84,7 @@ struct __GLXDRIdrawablePrivateRec int width, height; int have_back; int have_fake_front; + int swap_interval; }; static void dri2WaitX(__GLXDRIdrawable * pdraw); @@ -197,9 +201,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; @@ -232,15 +258,7 @@ dri2CopySubBuffer(__GLXDRIdrawable * pdraw, } static void -dri2SwapBuffers(__GLXDRIdrawable * pdraw) -{ - __GLXDRIdrawablePrivate *priv = (__GLXDRIdrawablePrivate *) pdraw; - - dri2CopySubBuffer(pdraw, 0, 0, priv->width, priv->height); -} - -static void -dri2WaitX(__GLXDRIdrawable * pdraw) +dri2WaitX(__GLXDRIdrawable *pdraw) { __GLXDRIdrawablePrivate *priv = (__GLXDRIdrawablePrivate *) pdraw; XRectangle xrect; @@ -342,6 +360,38 @@ process_buffers(__GLXDRIdrawablePrivate * pdraw, DRI2Buffer * buffers, } +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; + int64_t ret; + +#ifdef __DRI2_FLUSH + if (pdraw->psc->f) + (*pdraw->psc->f->flush)(pdraw->driDrawable); +#endif + + /* Old servers can't handle swapbuffers */ + if (!pdp->swapAvailable) { + dri2CopySubBuffer(pdraw, 0, 0, priv->width, priv->height); + return 0; + } + + 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 * dri2GetBuffers(__DRIdrawable * driDrawable, int *width, int *height, @@ -390,6 +440,23 @@ dri2GetBuffersWithFormat(__DRIdrawable * driDrawable, return pdraw->buffers; } +static void +dri2SetSwapInterval(__GLXDRIdrawable *pdraw, int interval) +{ + __GLXDRIdrawablePrivate *priv = (__GLXDRIdrawablePrivate *) pdraw; + + DRI2SwapInterval(priv->base.psc->dpy, pdraw->xDrawable, interval); + priv->swap_interval = interval; +} + +static unsigned int +dri2GetSwapInterval(__GLXDRIdrawable *pdraw) +{ + __GLXDRIdrawablePrivate *priv = (__GLXDRIdrawablePrivate *) pdraw; + + return priv->swap_interval; +} + static const __DRIdri2LoaderExtension dri2LoaderExtension = { {__DRI_DRI2_LOADER, __DRI_DRI2_LOADER_VERSION}, dri2GetBuffers, @@ -437,7 +504,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); @@ -454,9 +521,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) { @@ -485,16 +552,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); @@ -507,6 +575,11 @@ dri2CreateScreen(__GLXscreenConfigs * psc, int screen, psp->swapBuffers = dri2SwapBuffers; psp->waitGL = dri2WaitGL; psp->waitX = dri2WaitX; + psp->getDrawableMSC = dri2DrawableGetMSC; + psp->waitForMSC = dri2WaitForMSC; + psp->waitForSBC = dri2WaitForSBC; + psp->setSwapInterval = dri2SetSwapInterval; + psp->getSwapInterval = dri2GetSwapInterval; /* DRI2 suports SubBuffer through DRI2CopyRegion, so it's always * available.*/ @@ -518,7 +591,7 @@ dri2CreateScreen(__GLXscreenConfigs * psc, int screen, return psp; - handle_error: +handle_error: Xfree(driverName); Xfree(deviceName); @@ -559,6 +632,9 @@ dri2CreateDisplay(Display * dpy) } pdp->driPatch = 0; + pdp->swapAvailable = 0; + if (pdp->driMinor >= 2) + pdp->swapAvailable = 1; pdp->base.destroyDisplay = dri2DestroyDisplay; pdp->base.createScreen = dri2CreateScreen; diff --git a/src/glx/x11/dri_common.c b/src/glx/x11/dri_common.c index 9c825ad74a..e4034161bb 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"); - } -#endif + /* 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) && dri2) { - psc->texBuffer = (__DRItexBufferExtension *) extensions[i]; - __glXEnableDirectExtension(psc, "GLX_EXT_texture_from_pixmap"); + if ((strcmp(extensions[i]->name, __DRI_TEX_BUFFER) == 0)) { + psc->texBuffer = (__DRItexBufferExtension *) extensions[i]; + __glXEnableDirectExtension(psc, "GLX_EXT_texture_from_pixmap"); } #endif + __glXEnableDirectExtension(psc, "GLX_SGI_video_sync"); + __glXEnableDirectExtension(psc, "GLX_SGI_swap_control"); + __glXEnableDirectExtension(psc, "GLX_MESA_swap_control"); + + /* FIXME: if DRI2 version supports it... */ + __glXEnableDirectExtension(psc, "INTEL_swap_event"); + #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 61ac9c6416..bb178db787 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 a890feeab2..e658644eca 100644 --- a/src/glx/x11/dri_glx.c +++ b/src/glx/x11/dri_glx.c @@ -607,10 +607,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 @@ -670,9 +672,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) { @@ -688,7 +690,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 1866b2cc87..6a51d748af 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 00ee14fb05..ded4f5a434 100644 --- a/src/glx/x11/glxclient.h +++ b/src/glx/x11/glxclient.h @@ -121,26 +121,35 @@ 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); + void (*setSwapInterval)(__GLXDRIdrawable *pdraw, int interval); + int (*getSwapInterval)(__GLXDRIdrawable *pdraw); }; struct __GLXDRIcontextRec diff --git a/src/glx/x11/glxcmds.c b/src/glx/x11/glxcmds.c index d1c68dd02e..c3be974ea9 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 @@ -1884,6 +1884,7 @@ __glXSwapIntervalSGI(int interval) { xGLXVendorPrivateReq *req; GLXContext gc = __glXGetCurrentContext(); + __GLXscreenConfigs *psc; Display *dpy; CARD32 *interval_ptr; CARD8 opcode; @@ -1898,20 +1899,30 @@ __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 + psc = GetGLXScreenConfigs( gc->currentDpy, gc->screen); + + if (gc->driContext && psc->driScreen && psc->driScreen->setSwapInterval) { + __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(gc->currentDpy, + gc->currentDrawable, + NULL); + psc->driScreen->setSwapInterval(pdraw, interval); + return 0; + } + dpy = gc->currentDpy; opcode = __glXSetupForCommand(dpy); if (!opcode) { @@ -1943,13 +1954,13 @@ __glXSwapIntervalSGI(int interval) static int __glXSwapIntervalMESA(unsigned int interval) { -#ifdef __DRI_SWAP_CONTROL GLXContext gc = __glXGetCurrentContext(); if (interval < 0) { return GLX_BAD_VALUE; } +#ifdef __DRI_SWAP_CONTROL if (gc != NULL && gc->driContext) { __GLXscreenConfigs *const psc = GetGLXScreenConfigs(gc->currentDpy, gc->screen); @@ -1963,10 +1974,20 @@ __glXSwapIntervalMESA(unsigned int interval) } } } -#else - (void) interval; #endif + if (gc != NULL && gc->driContext) { + __GLXscreenConfigs *psc; + + psc = GetGLXScreenConfigs( gc->currentDpy, gc->screen); + if (psc->driScreen && psc->driScreen->setSwapInterval) { + __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(gc->currentDpy, + gc->currentDrawable, NULL); + psc->driScreen->setSwapInterval(pdraw, interval); + return 0; + } + } + return GLX_BAD_CONTEXT; } @@ -1990,6 +2011,16 @@ __glXGetSwapIntervalMESA(void) } } #endif + if (gc != NULL && gc->driContext) { + __GLXscreenConfigs *psc; + + psc = GetGLXScreenConfigs( gc->currentDpy, gc->screen); + if (psc->driScreen && psc->driScreen->getSwapInterval) { + __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(gc->currentDpy, + gc->currentDrawable, NULL); + return psc->driScreen->getSwapInterval(pdraw); + } + } return 0; } @@ -2102,64 +2133,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 (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; + if ( psc->msc && psc->driScreen ) { + ret = (*psc->msc->getDrawableMSC)(psc->__driScreen, + pdraw->driDrawable, &msc); + *count = (unsigned) msc; - 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 +2352,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 +2482,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 +2500,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 +2522,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 +2538,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 +2549,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 +2566,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 +2576,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 +2586,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; } diff --git a/src/glx/x11/glxext.c b/src/glx/x11/glxext.c index 5633a3e4a2..fe65216c41 100644 --- a/src/glx/x11/glxext.c +++ b/src/glx/x11/glxext.c @@ -101,6 +101,10 @@ __glXCloseDisplay(Display * dpy, XExtCodes * codes) static XEXT_GENERATE_ERROR_STRING(__glXErrorString, __glXExtensionName, __GLX_NUMBER_ERRORS, error_list) +static Bool +__glXWireToEvent(Display *dpy, XEvent *event, xEvent *wire); +static Status +__glXEventToWire(Display *dpy, XEvent *event, xEvent *wire); static /* const */ XExtensionHooks __glXExtensionHooks = { NULL, /* create_gc */ @@ -110,8 +114,8 @@ static /* const */ XExtensionHooks __glXExtensionHooks = { NULL, /* create_font */ NULL, /* free_font */ __glXCloseDisplay, /* close_display */ - NULL, /* wire_to_event */ - NULL, /* event_to_wire */ + __glXWireToEvent, /* wire_to_event */ + __glXEventToWire, /* event_to_wire */ NULL, /* error */ __glXErrorString, /* error_string */ }; @@ -121,6 +125,89 @@ XEXT_GENERATE_FIND_DISPLAY(__glXFindDisplay, __glXExtensionInfo, __glXExtensionName, &__glXExtensionHooks, __GLX_NUMBER_EVENTS, NULL) +/* + * GLX events are a bit funky. We don't stuff the X event code into + * our user exposed (via XNextEvent) structure. Instead we use the GLX + * private event code namespace (and hope it doesn't conflict). Clients + * have to know that bit 15 in the event type field means they're getting + * a GLX event, and then handle the various sub-event types there, rather + * than simply checking the event code and handling it directly. + */ + +static Bool +__glXWireToEvent(Display *dpy, XEvent *event, xEvent *wire) +{ + XExtDisplayInfo *info = __glXFindDisplay(dpy); + + XextCheckExtension(dpy, info, __glXExtensionName, False); + + switch ((wire->u.u.type & 0x7f) - info->codes->first_event) { + case GLX_PbufferClobber: + { + GLXPbufferClobberEvent *aevent = (GLXPbufferClobberEvent *)event; + xGLXPbufferClobberEvent *awire = (xGLXPbufferClobberEvent *)wire; + aevent->event_type = awire->type; + aevent->serial = awire->sequenceNumber; + aevent->event_type = awire->event_type; + aevent->draw_type = awire->draw_type; + aevent->drawable = awire->drawable; + aevent->buffer_mask = awire->buffer_mask; + aevent->aux_buffer = awire->aux_buffer; + aevent->x = awire->x; + aevent->y = awire->y; + aevent->width = awire->width; + aevent->height = awire->height; + aevent->count = awire->count; + return True; + } + case GLX_BufferSwapComplete: + { + GLXBufferSwapComplete *aevent = (GLXBufferSwapComplete *)event; + xGLXBufferSwapComplete *awire = (xGLXBufferSwapComplete *)wire; + aevent->event_type = awire->event_type; + aevent->drawable = awire->drawable; + aevent->ust = ((CARD64)awire->ust_hi << 32) | awire->ust_lo; + aevent->msc = ((CARD64)awire->msc_hi << 32) | awire->msc_lo; + aevent->sbc = ((CARD64)awire->sbc_hi << 32) | awire->sbc_lo; + return True; + } + default: + /* client doesn't support server event */ + break; + } + + return False; +} + +/* We don't actually support this. It doesn't make sense for clients to + * send each other GLX events. + */ +static Status +__glXEventToWire(Display *dpy, XEvent *event, xEvent *wire) +{ + XExtDisplayInfo *info = __glXFindDisplay(dpy); + + XextCheckExtension(dpy, info, __glXExtensionName, False); + + switch (event->type) { + case GLX_DAMAGED: + break; + case GLX_SAVED: + break; + case GLX_EXCHANGE_COMPLETE: + break; + case GLX_BLIT_COMPLETE: + break; + case GLX_FLIP_COMPLETE: + break; + default: + /* client doesn't support server event */ + break; + } + + return Success; +} + /************************************************************************/ /* ** Free the per screen configs data as well as the array of diff --git a/src/glx/x11/glxextensions.c b/src/glx/x11/glxextensions.c index 6852128e2a..25a5c49293 100644 --- a/src/glx/x11/glxextensions.c +++ b/src/glx/x11/glxextensions.c @@ -104,6 +104,7 @@ static const struct extension_info known_glx_extensions[] = { { GLX(SGIX_swap_group), VER(0,0), N, N, N, N }, { GLX(SGIX_visual_select_group), VER(0,0), Y, Y, N, N }, { GLX(EXT_texture_from_pixmap), VER(0,0), Y, N, N, N }, + { GLX(INTEL_swap_event), VER(1,4), Y, Y, N, N }, { NULL } }; diff --git a/src/glx/x11/glxextensions.h b/src/glx/x11/glxextensions.h index 652c5db1c8..f556b1239c 100644 --- a/src/glx/x11/glxextensions.h +++ b/src/glx/x11/glxextensions.h @@ -65,7 +65,8 @@ enum SGIX_swap_barrier_bit, SGIX_swap_group_bit, SGIX_visual_select_group_bit, - EXT_texture_from_pixmap_bit + EXT_texture_from_pixmap_bit, + INTEL_swap_event_bit, }; enum diff --git a/src/mesa/drivers/dri/common/dri_util.c b/src/mesa/drivers/dri/common/dri_util.c index 0e01d74265..3649c29666 100644 --- a/src/mesa/drivers/dri/common/dri_util.c +++ b/src/mesa/drivers/dri/common/dri_util.c @@ -454,6 +454,7 @@ driCreateNewDrawable(__DRIscreen *psp, const __DRIconfig *config, pdp->driScreenPriv = psp; pdp->driContextPriv = &psp->dummyContextPriv; + pdp->validBuffers = GL_FALSE; if (!(*psp->DriverAPI.CreateBuffer)(psp, pdp, &config->modes, renderType == GLX_PIXMAP_BIT)) { diff --git a/src/mesa/drivers/dri/common/dri_util.h b/src/mesa/drivers/dri/common/dri_util.h index 35d8b8ff93..95df702f1a 100644 --- a/src/mesa/drivers/dri/common/dri_util.h +++ b/src/mesa/drivers/dri/common/dri_util.h @@ -376,6 +376,8 @@ struct __DRIdrawableRec { * GLX_MESA_swap_control. */ unsigned int swap_interval; + + GLboolean validBuffers; }; /** diff --git a/src/mesa/drivers/dri/intel/intel_context.c b/src/mesa/drivers/dri/intel/intel_context.c index 13a28f0419..3f6634c65a 100644 --- a/src/mesa/drivers/dri/intel/intel_context.c +++ b/src/mesa/drivers/dri/intel/intel_context.c @@ -70,8 +70,6 @@ int INTEL_DEBUG = (0); #define DRIVER_DATE_GEM "GEM " DRIVER_DATE -static void intel_flush(GLcontext *ctx, GLboolean needs_mi_flush); - static const GLubyte * intelGetString(GLcontext * ctx, GLenum name) { @@ -378,6 +376,7 @@ intel_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable) } } + drawable->validBuffers = GL_TRUE; driUpdateFramebufferSize(&intel->ctx, drawable); } @@ -461,7 +460,7 @@ intelInvalidateState(GLcontext * ctx, GLuint new_state) intel->vtbl.invalidate_state( intel, new_state ); } -static void +void intel_flush(GLcontext *ctx, GLboolean needs_mi_flush) { struct intel_context *intel = intel_context(ctx); diff --git a/src/mesa/drivers/dri/intel/intel_context.h b/src/mesa/drivers/dri/intel/intel_context.h index c7b7235836..07207bfbec 100644 --- a/src/mesa/drivers/dri/intel/intel_context.h +++ b/src/mesa/drivers/dri/intel/intel_context.h @@ -412,6 +412,7 @@ extern GLboolean intelInitContext(struct intel_context *intel, extern void intelFinish(GLcontext * ctx); extern void intelFlush(GLcontext * ctx); +extern void intel_flush(GLcontext * ctx, GLboolean needs_mi_flush); extern void intelInitDriverFunctions(struct dd_function_table *functions); diff --git a/src/mesa/drivers/dri/intel/intel_extensions.h b/src/mesa/drivers/dri/intel/intel_extensions.h index 1d1c97a4a9..e78e07356e 100644 --- a/src/mesa/drivers/dri/intel/intel_extensions.h +++ b/src/mesa/drivers/dri/intel/intel_extensions.h @@ -32,5 +32,8 @@ extern void intelInitExtensions(GLcontext *ctx); +extern void +intelFlushDrawable(__DRIdrawable *drawable); + #endif diff --git a/src/mesa/drivers/dri/intel/intel_screen.c b/src/mesa/drivers/dri/intel/intel_screen.c index 5165716e09..e240957197 100644 --- a/src/mesa/drivers/dri/intel/intel_screen.c +++ b/src/mesa/drivers/dri/intel/intel_screen.c @@ -113,10 +113,36 @@ static const __DRItexBufferExtension intelTexBufferExtension = { intelSetTexBuffer2, }; +static void +intelDRI2Flush(__DRIdrawable *drawable) +{ + struct intel_context *intel = drawable->driContextPriv->driverPrivate; + + if (intel->gen < 4) + INTEL_FIREVERTICES(intel); + + if (intel->batch->map != intel->batch->ptr) + intel_batchbuffer_flush(intel->batch); +} + +static void +intelDRI2FlushInvalidate(__DRIdrawable *drawable) +{ + intelDRI2Flush(drawable); + drawable->validBuffers = GL_FALSE; +} + +static const struct __DRI2flushExtensionRec intelFlushExtension = { + { __DRI2_FLUSH, __DRI2_FLUSH_VERSION }, + intelDRI2Flush, + intelDRI2FlushInvalidate, +}; + static const __DRIextension *intelScreenExtensions[] = { &driReadDrawableExtension, &intelTexOffsetExtension.base, &intelTexBufferExtension.base, + &intelFlushExtension.base, NULL }; @@ -311,11 +337,10 @@ __DRIconfig **intelInitScreen2(__DRIscreen *psp) intelScreenPrivate *intelScreen; GLenum fb_format[3]; GLenum fb_type[3]; - /* GLX_SWAP_COPY_OML is only supported because the Intel driver doesn't - * support pageflipping at all. - */ + static const GLenum back_buffer_modes[] = { - GLX_NONE, GLX_SWAP_UNDEFINED_OML, GLX_SWAP_COPY_OML + GLX_NONE, GLX_SWAP_UNDEFINED_OML, + GLX_SWAP_EXCHANGE_OML, GLX_SWAP_COPY_OML }; uint8_t depth_bits[4], stencil_bits[4], msaa_samples_array[1]; int color; diff --git a/src/mesa/drivers/dri/intel/intel_tex_image.c b/src/mesa/drivers/dri/intel/intel_tex_image.c index 307669f87e..6f41eafd0e 100644 --- a/src/mesa/drivers/dri/intel/intel_tex_image.c +++ b/src/mesa/drivers/dri/intel/intel_tex_image.c @@ -742,7 +742,8 @@ intelSetTexBuffer2(__DRIcontext *pDRICtx, GLint target, if (!intelObj) return; - intel_update_renderbuffers(pDRICtx, dPriv); + if (!dPriv->validBuffers) + intel_update_renderbuffers(pDRICtx, dPriv); rb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT); /* If the region isn't set, then intel_update_renderbuffers was unable diff --git a/src/mesa/drivers/x11/glxapi.c b/src/mesa/drivers/x11/glxapi.c index 02eea25a71..a17c2c3ffc 100644 --- a/src/mesa/drivers/x11/glxapi.c +++ b/src/mesa/drivers/x11/glxapi.c @@ -1173,6 +1173,9 @@ _glxapi_get_extensions(void) #ifdef GLX_EXT_texture_from_pixmap "GLX_EXT_texture_from_pixmap", #endif +#ifdef GLX_INTEL_swap_event + "GLX_INTEL_swap_event", +#endif NULL }; return extensions; |