#include "dri_common.h"
#include "dri3_priv.h"
#include "loader.h"
+#include "dri2.h"
static const struct glx_context_vtable dri3_context_vtable;
.flushFrontBuffer = dri3_flush_front_buffer,
};
+const __DRIuseInvalidateExtension dri3UseInvalidate = {
+ .base = { __DRI_USE_INVALIDATE, 1 }
+};
+
+static const __DRIextension *loader_extensions[] = {
+ &imageLoaderExtension.base,
+ &systemTimeExtension.base,
+ &dri3UseInvalidate.base,
+ NULL
+};
+
/** dri3_swap_buffers
*
* Make the current back buffer visible using the present extension
struct dri3_screen *psc = (struct dri3_screen *) priv->base.psc;
Display *dpy = priv->base.psc->dpy;
xcb_connection_t *c = XGetXCBConnection(dpy);
- int buf_id = DRI3_BACK_ID(priv->cur_back);
+ struct dri3_buffer *back;
int64_t ret = 0;
unsigned flags = __DRI2_FLUSH_DRAWABLE;
flags |= __DRI2_FLUSH_CONTEXT;
dri3_flush(psc, priv, flags, __DRI2_THROTTLE_SWAPBUFFER);
+ back = priv->buffers[DRI3_BACK_ID(priv->cur_back)];
dri3_flush_present_events(priv);
- if (priv->buffers[buf_id] && !priv->is_pixmap) {
- dri3_fence_reset(c, priv->buffers[buf_id]);
+ if (back && !priv->is_pixmap) {
+ dri3_fence_reset(c, back);
/* Compute when we want the frame shown by taking the last known successful
* MSC and adding in a swap interval for each outstanding swap request
if (target_msc == 0)
target_msc = priv->msc + priv->swap_interval * (priv->send_sbc - priv->recv_sbc);
- priv->buffers[buf_id]->busy = 1;
+ back->busy = 1;
+ back->last_swap = priv->send_sbc;
xcb_present_pixmap(c,
priv->base.xDrawable,
- priv->buffers[buf_id]->pixmap,
+ back->pixmap,
(uint32_t) priv->send_sbc,
0, /* valid */
0, /* update */
0, /* y_off */
None, /* target_crtc */
None,
- priv->buffers[buf_id]->sync_fence,
+ back->sync_fence,
XCB_PRESENT_OPTION_NONE,
target_msc,
divisor,
if (priv->have_fake_front) {
dri3_fence_reset(c, priv->buffers[DRI3_FRONT_ID]);
dri3_copy_area(c,
- priv->buffers[buf_id]->pixmap,
+ back->pixmap,
priv->buffers[DRI3_FRONT_ID]->pixmap,
dri3_drawable_gc(priv),
0, 0, 0, 0, priv->width, priv->height);
++(*priv->stamp);
}
+ (*psc->f->invalidate)(priv->driDrawable);
+
return ret;
}
+static int
+dri3_get_buffer_age(__GLXDRIdrawable *pdraw)
+{
+ xcb_connection_t *c = XGetXCBConnection(pdraw->psc->dpy);
+ struct dri3_drawable *priv = (struct dri3_drawable *) pdraw;
+ int back_id = DRI3_BACK_ID(dri3_find_back(c, priv));
+
+ if (back_id < 0 || !priv->buffers[back_id])
+ return 0;
+
+ if (priv->buffers[back_id]->last_swap != 0)
+ return priv->send_sbc - priv->buffers[back_id]->last_swap + 1;
+ else
+ return 0;
+}
+
/** dri3_open
*
* Wrapper around xcb_dri3_open
if (pdraw != NULL) {
psc = (struct dri3_screen *) base->psc;
- if (psc->texBuffer->releaseTexBuffer)
+ if (psc->texBuffer->base.version >= 3 &&
+ psc->texBuffer->releaseTexBuffer != NULL)
(*psc->texBuffer->releaseTexBuffer) (pcp->driContext,
pdraw->base.textureTarget,
pdraw->driDrawable);
}
static const struct glx_context_vtable dri3_context_vtable = {
- dri3_destroy_context,
- dri3_bind_context,
- dri3_unbind_context,
- dri3_wait_gl,
- dri3_wait_x,
- DRI_glXUseXFont,
- dri3_bind_tex_image,
- dri3_release_tex_image,
- NULL, /* get_proc_address */
+ .destroy = dri3_destroy_context,
+ .bind = dri3_bind_context,
+ .unbind = dri3_unbind_context,
+ .wait_gl = dri3_wait_gl,
+ .wait_x = dri3_wait_x,
+ .use_x_font = DRI_glXUseXFont,
+ .bind_tex_image = dri3_bind_tex_image,
+ .release_tex_image = dri3_release_tex_image,
+ .get_proc_address = NULL,
};
/** dri3_bind_extensions
/* internal driver extension, no GL extension exposed */
}
+ if (strcmp(extensions[i]->name, __DRI_IMAGE) == 0)
+ psc->image = (__DRIimageExtension *) extensions[i];
+
if ((strcmp(extensions[i]->name, __DRI2_CONFIG_QUERY) == 0))
psc->config = (__DRI2configQueryExtension *) extensions[i];
if (strcmp(extensions[i]->name, __DRI2_ROBUSTNESS) == 0)
__glXEnableDirectExtension(&psc->base,
"GLX_ARB_create_context_robustness");
+
+ if (strcmp(extensions[i]->name, __DRI2_RENDERER_QUERY) == 0) {
+ psc->rendererQuery = (__DRI2rendererQueryExtension *) extensions[i];
+ __glXEnableDirectExtension(&psc->base, "GLX_MESA_query_renderer");
+ }
}
}
static const struct glx_screen_vtable dri3_screen_vtable = {
- dri3_create_context,
- dri3_create_context_attribs
+ .create_context = dri3_create_context,
+ .create_context_attribs = dri3_create_context_attribs,
+ .query_renderer_integer = dri3_query_renderer_integer,
+ .query_renderer_string = dri3_query_renderer_string,
};
/** dri3_create_screen
psc->driScreen =
psc->image_driver->createNewScreen2(screen, psc->fd,
- (const __DRIextension **)
- &pdp->loader_extensions[0],
+ pdp->loader_extensions,
extensions,
&driver_configs, psc);
goto handle_error;
}
- extensions = (*psc->core->getExtensions)(psc->driScreen);
-
- for (i = 0; extensions[i]; i++) {
- if (strcmp(extensions[i]->name, __DRI_IMAGE) == 0)
- psc->image = (__DRIimageExtension *) extensions[i];
- }
+ dri3_bind_extensions(psc, priv, driverName);
- if (psc->image == NULL) {
- ErrorMessageF("image extension not found\n");
+ if (!psc->image || psc->image->base.version < 7 || !psc->image->createImageFromFds) {
+ ErrorMessageF("Version 7 or imageFromFds image extension not found\n");
goto handle_error;
}
- dri3_bind_extensions(psc, priv, driverName);
-
if (!psc->f || psc->f->base.version < 4) {
ErrorMessageF("Version 4 or later of flush extension not found\n");
goto handle_error;
configs = driConvertConfigs(psc->core, psc->base.configs, driver_configs);
visuals = driConvertConfigs(psc->core, psc->base.visuals, driver_configs);
- if (!configs || !visuals)
+ if (!configs || !visuals) {
+ ErrorMessageF("No matching fbConfigs or visuals found\n");
goto handle_error;
+ }
glx_config_destroy_list(psc->base.configs);
psc->base.configs = configs;
psp->copySubBuffer = dri3_copy_sub_buffer;
__glXEnableDirectExtension(&psc->base, "GLX_MESA_copy_sub_buffer");
+ psp->getBufferAge = dri3_get_buffer_age;
+ __glXEnableDirectExtension(&psc->base, "GLX_EXT_buffer_age");
+
free(driverName);
free(deviceName);
dri3_create_display(Display * dpy)
{
struct dri3_display *pdp;
- int i;
xcb_connection_t *c = XGetXCBConnection(dpy);
xcb_dri3_query_version_cookie_t dri3_cookie;
xcb_dri3_query_version_reply_t *dri3_reply;
pdp->base.createScreen = dri3_create_screen;
loader_set_logger(dri_message);
- i = 0;
-
- pdp->loader_extensions[i++] = &imageLoaderExtension.base;
-
- pdp->loader_extensions[i++] = &systemTimeExtension.base;
- pdp->loader_extensions[i++] = NULL;
+ pdp->loader_extensions = loader_extensions;
return &pdp->base;
no_extension: