#include <X11/Xlib.h>
#include <X11/extensions/Xfixes.h>
-#include <X11/extensions/Xdamage.h>
#include "glapi.h"
#include "glxclient.h"
#include <X11/extensions/dri2proto.h>
const __DRI2flushExtension *f;
const __DRI2configQueryExtension *config;
const __DRItexBufferExtension *texBuffer;
+ const __DRI2throttleExtension *throttle;
const __DRIconfig **driver_configs;
void *driver;
pdraw = (struct dri2_drawable *) driFetchDrawable(context, draw);
pread = (struct dri2_drawable *) driFetchDrawable(context, read);
+ driReleaseDrawables(&pcp->base);
+
if (pdraw == NULL || pread == NULL)
return GLXBadDrawable;
struct dri2_screen *psc = (struct dri2_screen *) pcp->base.psc;
(*psc->core->unbindContext) (pcp->driContext);
-
- if (context == new)
- driReleaseDrawables(&pcp->base);
}
static struct glx_context *
__DRIcontext *shared = NULL;
if (shareList) {
+ /* If the shareList context is not a DRI2 context, we cannot possibly
+ * create a DRI2 context that shares it.
+ */
+ if (shareList->vtable->destroy != dri2_destroy_context) {
+ return NULL;
+ }
+
pcp_shared = (struct dri2_context *) shareList;
shared = pcp_shared->driContext;
}
#endif /* X_DRI2WaitMSC */
+/**
+ * dri2Throttle - Request driver throttling
+ *
+ * This function uses the DRI2 throttle extension to give the
+ * driver the opportunity to throttle on flush front, copysubbuffer
+ * and swapbuffers.
+ */
static void
-dri2CopySubBuffer(__GLXDRIdrawable *pdraw, int x, int y, int width, int height)
+dri2Throttle(struct dri2_screen *psc,
+ struct dri2_drawable *draw,
+ enum __DRI2throttleReason reason)
+{
+ if (psc->throttle) {
+ struct glx_context *gc = __glXGetCurrentContext();
+ struct dri2_context *dri2Ctx = (struct dri2_context *)gc;
+ __DRIcontext *ctx =
+ (dri2Ctx) ? dri2Ctx->driContext : NULL;
+
+ psc->throttle->throttle(ctx, draw->driDrawable, reason);
+ }
+}
+
+static void
+__dri2CopySubBuffer(__GLXDRIdrawable *pdraw, int x, int y,
+ int width, int height,
+ enum __DRI2throttleReason reason)
{
struct dri2_drawable *priv = (struct dri2_drawable *) pdraw;
struct dri2_screen *psc = (struct dri2_screen *) pdraw->psc;
(*psc->f->flush) (priv->driDrawable);
#endif
+ dri2Throttle(psc, priv, reason);
+
region = XFixesCreateRegion(psc->base.dpy, &xrect, 1);
DRI2CopyRegion(psc->base.dpy, pdraw->xDrawable, region,
DRI2BufferFrontLeft, DRI2BufferBackLeft);
XFixesDestroyRegion(psc->base.dpy, region);
}
+static void
+dri2CopySubBuffer(__GLXDRIdrawable *pdraw, int x, int y,
+ int width, int height)
+{
+ __dri2CopySubBuffer(pdraw, x, y, width, height,
+ __DRI2_THROTTLE_COPYSUBBUFFER);
+}
+
+
static void
dri2_copy_drawable(struct dri2_drawable *priv, int dest, int src)
{
static void
dri2FlushFrontBuffer(__DRIdrawable *driDrawable, void *loaderPrivate)
{
+ struct glx_display *priv;
+ struct dri2_display *pdp;
+ struct glx_context *gc;
struct dri2_drawable *pdraw = loaderPrivate;
- struct glx_display *priv = __glXInitialize(pdraw->base.psc->dpy);
- struct dri2_display *pdp = (struct dri2_display *)priv->dri2Display;
- struct glx_context *gc = __glXGetCurrentContext();
+ struct dri2_screen *psc;
+
+ if (!pdraw)
+ return;
+
+ if (!pdraw->base.psc)
+ return;
+
+ psc = (struct dri2_screen *) pdraw->base.psc;
+
+ priv = __glXInitialize(psc->base.dpy);
+ pdp = (struct dri2_display *) priv->dri2Display;
+ gc = __glXGetCurrentContext();
+
+ dri2Throttle(psc, pdraw, __DRI2_THROTTLE_FLUSHFRONT);
/* Old servers don't send invalidate events */
if (!pdp->invalidateAvailable)
(struct dri2_display *)dpyPriv->dri2Display;
CARD64 ret = 0;
+ /* Check we have the right attachments */
+ if (!priv->have_back)
+ return ret;
+
+ /* Old servers can't handle swapbuffers */
+ if (!pdp->swapAvailable) {
+ __dri2CopySubBuffer(pdraw, 0, 0, priv->width, priv->height,
+ __DRI2_THROTTLE_SWAPBUFFER);
+ } else {
+#ifdef X_DRI2SwapBuffers
#ifdef __DRI2_FLUSH
if (psc->f) {
struct glx_context *gc = __glXGetCurrentContext();
}
#endif
- /* Old servers don't send invalidate events */
- if (!pdp->invalidateAvailable)
- dri2InvalidateBuffers(dpyPriv->dpy, pdraw->xDrawable);
+ dri2Throttle(psc, priv, __DRI2_THROTTLE_SWAPBUFFER);
- /* Old servers can't handle swapbuffers */
- if (!pdp->swapAvailable) {
- dri2CopySubBuffer(pdraw, 0, 0, priv->width, priv->height);
- return 0;
+ DRI2SwapBuffers(psc->base.dpy, pdraw->xDrawable,
+ target_msc, divisor, remainder, &ret);
+#endif
}
-#ifdef X_DRI2SwapBuffers
- DRI2SwapBuffers(psc->base.dpy, pdraw->xDrawable, target_msc, divisor,
- remainder, &ret);
-#endif
+ /* Old servers don't send invalidate events */
+ if (!pdp->invalidateAvailable)
+ dri2InvalidateBuffers(dpyPriv->dpy, pdraw->xDrawable);
return ret;
}
{
__GLXDRIdrawable *pdraw =
dri2GetGlxDrawableFromXDrawableId(dpy, drawable);
- struct dri2_screen *psc = (struct dri2_screen *) pdraw->psc;
+ struct dri2_screen *psc;
struct dri2_drawable *pdp = (struct dri2_drawable *) pdraw;
+ if (!pdraw)
+ return;
+
+ psc = (struct dri2_screen *) pdraw->psc;
+
#if __DRI2_FLUSH_VERSION >= 3
- if (pdraw && psc->f)
+ if (pdraw && psc->f && psc->f->base.version >= 3 && psc->f->invalidate)
psc->f->invalidate(pdp->driDrawable);
#endif
}
psc = (struct dri2_screen *) base->psc;
#if __DRI2_FLUSH_VERSION >= 3
- if (!pdp->invalidateAvailable && psc->f)
+ if (!pdp->invalidateAvailable && psc->f &&
+ psc->f->base.version >= 3 && psc->f->invalidate)
psc->f->invalidate(pdraw->driDrawable);
#endif
DRI_glXUseXFont,
dri2_bind_tex_image,
dri2_release_tex_image,
+ NULL, /* get_proc_address */
};
static void
if ((strcmp(extensions[i]->name, __DRI2_CONFIG_QUERY) == 0))
psc->config = (__DRI2configQueryExtension *) extensions[i];
+
+ if (((strcmp(extensions[i]->name, __DRI2_THROTTLE) == 0)))
+ psc->throttle = (__DRI2throttleExtension *) extensions[i];
}
}
priv->dri2Display;
struct dri2_screen *psc;
__GLXDRIscreen *psp;
+ struct glx_config *configs = NULL, *visuals = NULL;
char *driverName, *deviceName;
drm_magic_t magic;
int i;
&driverName, &deviceName)) {
glx_screen_cleanup(&psc->base);
XFree(psc);
+ InfoMessageF("screen %d does not appear to be DRI2 capable\n", screen);
return NULL;
}
extensions = psc->core->getExtensions(psc->driScreen);
dri2BindExtensions(psc, extensions);
- psc->base.configs =
- driConvertConfigs(psc->core, psc->base.configs, driver_configs);
- psc->base.visuals =
- driConvertConfigs(psc->core, psc->base.visuals, driver_configs);
+ configs = driConvertConfigs(psc->core, psc->base.configs, driver_configs);
+ visuals = driConvertConfigs(psc->core, psc->base.visuals, driver_configs);
+
+ if (!configs || !visuals)
+ goto handle_error;
+
+ glx_config_destroy_list(psc->base.configs);
+ psc->base.configs = configs;
+ glx_config_destroy_list(psc->base.visuals);
+ psc->base.visuals = visuals;
psc->driver_configs = driver_configs;
return &psc->base;
handle_error:
+ if (configs)
+ glx_config_destroy_list(configs);
+ if (visuals)
+ glx_config_destroy_list(visuals);
+ if (psc->driScreen)
+ psc->core->destroyScreen(psc->driScreen);
+ psc->driScreen = NULL;
if (psc->fd >= 0)
close(psc->fd);
if (psc->driver)
dlclose(psc->driver);
+
Xfree(driverName);
Xfree(deviceName);
glx_screen_cleanup(&psc->base);
static void
dri2DestroyDisplay(__GLXDRIdisplay * dpy)
{
+ struct dri2_display *pdp = (struct dri2_display *) dpy;
+
+ __glxHashDestroy(pdp->dri2Hash);
Xfree(dpy);
}