static struct dri3_drawable *
loader_drawable_to_dri3_drawable(struct loader_dri3_drawable *draw) {
size_t offset = offsetof(struct dri3_drawable, loader_drawable);
+ if (!draw)
+ return NULL;
return (struct dri3_drawable *)(((void*) draw) - offset);
}
-static int
-glx_dri3_get_swap_interval(struct loader_dri3_drawable *draw)
-{
- struct dri3_drawable *priv = loader_drawable_to_dri3_drawable(draw);
-
- return priv->swap_interval;
-}
-
-static int
-glx_dri3_clamp_swap_interval(struct loader_dri3_drawable *draw, int interval)
-{
- return interval;
-}
-
-static void
-glx_dri3_set_swap_interval(struct loader_dri3_drawable *draw, int interval)
-{
- struct dri3_drawable *priv = loader_drawable_to_dri3_drawable(draw);
-
- priv->swap_interval = interval;
-}
-
static void
glx_dri3_set_drawable_size(struct loader_dri3_drawable *draw,
int width, int height)
glx_dri3_in_current_context(struct loader_dri3_drawable *draw)
{
struct dri3_drawable *priv = loader_drawable_to_dri3_drawable(draw);
+
+ if (!priv)
+ return false;
+
struct dri3_context *pcp = (struct dri3_context *) __glXGetCurrentContext();
struct dri3_screen *psc = (struct dri3_screen *) priv->base.psc;
glx_dri3_get_dri_context(struct loader_dri3_drawable *draw)
{
struct glx_context *gc = __glXGetCurrentContext();
+ struct dri3_context *dri3Ctx = (struct dri3_context *) gc;
- if (gc) {
- struct dri3_context *dri3Ctx = (struct dri3_context *) gc;
- return dri3Ctx->driContext;
- }
+ return (gc != &dummyContext) ? dri3Ctx->driContext : NULL;
+}
- return NULL;
+static __DRIscreen *
+glx_dri3_get_dri_screen(void)
+{
+ struct glx_context *gc = __glXGetCurrentContext();
+ struct dri3_context *pcp = (struct dri3_context *) gc;
+ struct dri3_screen *psc = (struct dri3_screen *) pcp->base.psc;
+
+ return (gc != &dummyContext && psc) ? psc->driScreen : NULL;
}
static void
/* DRI3+Present together uses microseconds for UST. */
if (priv->previous_ust + interval * 1000000 <= current_ust) {
if (priv->previous_ust) {
- fprintf(stderr, "libGL: FPS = %.1f\n",
+ fprintf(stderr, "libGL: FPS = %.2f\n",
((uint64_t) priv->frames * 1000000) /
(double)(current_ust - priv->previous_ust));
}
}
}
-static struct loader_dri3_vtable glx_dri3_vtable = {
- .get_swap_interval = glx_dri3_get_swap_interval,
- .clamp_swap_interval = glx_dri3_clamp_swap_interval,
- .set_swap_interval = glx_dri3_set_swap_interval,
+static const struct loader_dri3_vtable glx_dri3_vtable = {
.set_drawable_size = glx_dri3_set_drawable_size,
.in_current_context = glx_dri3_in_current_context,
.get_dri_context = glx_dri3_get_dri_context,
+ .get_dri_screen = glx_dri3_get_dri_screen,
.flush_drawable = glx_dri3_flush_drawable,
.show_fps = glx_dri3_show_fps,
};
struct dri3_context *pcp = (struct dri3_context *) context;
struct dri3_screen *psc = (struct dri3_screen *) pcp->base.psc;
struct dri3_drawable *pdraw, *pread;
+ __DRIdrawable *dri_draw = NULL, *dri_read = NULL;
pdraw = (struct dri3_drawable *) driFetchDrawable(context, draw);
pread = (struct dri3_drawable *) driFetchDrawable(context, read);
driReleaseDrawables(&pcp->base);
- if (pdraw == NULL || pread == NULL)
+ if (pdraw)
+ dri_draw = pdraw->loader_drawable.dri_drawable;
+ else if (draw != None)
return GLXBadDrawable;
- if (!(*psc->core->bindContext) (pcp->driContext,
- pdraw->loader_drawable.dri_drawable,
- pread->loader_drawable.dri_drawable))
+ if (pread)
+ dri_read = pread->loader_drawable.dri_drawable;
+ else if (read != None)
+ return GLXBadDrawable;
+
+ if (!(*psc->core->bindContext) (pcp->driContext, dri_draw, dri_read))
return GLXBadContext;
+ if (dri_draw)
+ psc->f->invalidate(dri_draw);
+ if (dri_read && dri_read != dri_draw)
+ psc->f->invalidate(dri_read);
+
return Success;
}
uint32_t flags = 0;
unsigned api;
int reset = __DRI_CTX_RESET_NO_NOTIFICATION;
- uint32_t ctx_attribs[2 * 5];
+ int release = __DRI_CTX_RELEASE_BEHAVIOR_FLUSH;
+ uint32_t ctx_attribs[2 * 6];
unsigned num_ctx_attribs = 0;
uint32_t render_type;
if (!dri2_convert_glx_attribs(num_attribs, attribs,
&major_ver, &minor_ver,
&render_type, &flags, &api,
- &reset, error))
+ &reset, &release, error))
goto error_exit;
+ if (!dri2_check_no_error(flags, shareList, major_ver, error)) {
+ goto error_exit;
+ }
+
/* Check the renderType value */
if (!validate_renderType_against_config(config_base, render_type))
goto error_exit;
goto error_exit;
}
- if (!glx_context_init(&pcp->base, &psc->base, &config->base))
+ if (!glx_context_init(&pcp->base, &psc->base, config_base))
goto error_exit;
ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_MAJOR_VERSION;
ctx_attribs[num_ctx_attribs++] = reset;
}
+ if (release != __DRI_CTX_RELEASE_BEHAVIOR_FLUSH) {
+ ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_RELEASE_BEHAVIOR;
+ ctx_attribs[num_ctx_attribs++] = release;
+ }
+
if (flags != 0) {
ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_FLAGS;
* GLX_CONTEXT_*_BIT values.
*/
ctx_attribs[num_ctx_attribs++] = flags;
+
+ if (flags & __DRI_CTX_FLAG_NO_ERROR)
+ pcp->base.noError = GL_TRUE;
}
pcp->driContext =
(*psc->image_driver->createContextAttribs) (psc->driScreen,
api,
- config->driConfig,
+ config ? config->driConfig
+ : NULL,
shared,
num_ctx_attribs / 2,
ctx_attribs,
struct glx_context *shareList, int renderType)
{
unsigned int error;
+ uint32_t attribs[2] = { GLX_RENDER_TYPE, renderType };
return dri3_create_context_attribs(base, config_base, shareList,
- 0, NULL, &error);
+ 1, attribs, &error);
}
static void
struct dri3_drawable *pdraw;
struct dri3_screen *psc = (struct dri3_screen *) base;
__GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) config_base;
+ bool has_multibuffer = false;
+#ifdef HAVE_DRI3_MODIFIERS
+ const struct dri3_display *const pdp = (struct dri3_display *)
+ base->display->dri3Display;
+#endif
pdraw = calloc(1, sizeof(*pdraw));
if (!pdraw)
pdraw->base.drawable = drawable;
pdraw->base.psc = &psc->base;
+#ifdef HAVE_DRI3_MODIFIERS
+ if ((psc->image && psc->image->base.version >= 15) &&
+ (pdp->dri3Major > 1 || (pdp->dri3Major == 1 && pdp->dri3Minor >= 2)) &&
+ (pdp->presentMajor > 1 ||
+ (pdp->presentMajor == 1 && pdp->presentMinor >= 2)))
+ has_multibuffer = true;
+#endif
+
(void) __glXInitialize(psc->base.dpy);
if (loader_dri3_drawable_init(XGetXCBConnection(base->dpy),
xDrawable, psc->driScreen,
- psc->is_different_gpu, config->driConfig,
+ psc->is_different_gpu, has_multibuffer,
+ config->driConfig,
&psc->loader_dri3_ext, &glx_dri3_vtable,
&pdraw->loader_drawable)) {
free(pdraw);
loader_dri3_flush(draw, __DRI2_FLUSH_DRAWABLE, __DRI2_THROTTLE_FLUSHFRONT);
+ psc->f->invalidate(driDrawable);
loader_dri3_wait_gl(draw);
}
+/**
+ * Make sure all pending swapbuffers have been submitted to hardware
+ *
+ * \param driDrawable[in] Pointer to the dri drawable whose swaps we are
+ * flushing.
+ * \param loaderPrivate[in] Pointer to the corresponding struct
+ * loader_dri_drawable.
+ */
+static void
+dri3_flush_swap_buffers(__DRIdrawable *driDrawable, void *loaderPrivate)
+{
+ struct loader_dri3_drawable *draw = loaderPrivate;
+ struct dri3_drawable *pdraw = loader_drawable_to_dri3_drawable(draw);
+ struct dri3_screen *psc;
+
+ if (!pdraw)
+ return;
+
+ if (!pdraw->base.psc)
+ return;
+
+ psc = (struct dri3_screen *) pdraw->base.psc;
+
+ (void) __glXInitialize(psc->base.dpy);
+ loader_dri3_swapbuffer_barrier(draw);
+}
+
+static void
+dri_set_background_context(void *loaderPrivate)
+{
+ struct dri3_context *pcp = (struct dri3_context *)loaderPrivate;
+ __glXSetCurrentContext(&pcp->base);
+}
+
+static GLboolean
+dri_is_thread_safe(void *loaderPrivate)
+{
+ /* Unlike DRI2, DRI3 doesn't call GetBuffers/GetBuffersWithFormat
+ * during draw so we're safe here.
+ */
+ return true;
+}
+
/* The image loader extension record for DRI3
*/
static const __DRIimageLoaderExtension imageLoaderExtension = {
- .base = { __DRI_IMAGE_LOADER, 1 },
+ .base = { __DRI_IMAGE_LOADER, 3 },
.getBuffers = loader_dri3_get_buffers,
.flushFrontBuffer = dri3_flush_front_buffer,
+ .flushSwapBuffers = dri3_flush_swap_buffers,
};
const __DRIuseInvalidateExtension dri3UseInvalidate = {
.base = { __DRI_USE_INVALIDATE, 1 }
};
+static const __DRIbackgroundCallableExtension driBackgroundCallable = {
+ .base = { __DRI_BACKGROUND_CALLABLE, 2 },
+
+ .setBackgroundContext = dri_set_background_context,
+ .isThreadSafe = dri_is_thread_safe,
+};
+
static const __DRIextension *loader_extensions[] = {
&imageLoaderExtension.base,
- &systemTimeExtension.base,
&dri3UseInvalidate.base,
+ &driBackgroundCallable.base,
NULL
};
return loader_dri3_swap_buffers_msc(&priv->loader_drawable,
target_msc, divisor, remainder,
- flags, false);
+ flags, NULL, 0, false);
}
static int
struct dri3_screen *psc = (struct dri3_screen *) base;
/* Free the direct rendering per screen data */
+ loader_dri3_close_screen(psc->driScreen);
(*psc->core->destroyScreen) (psc->driScreen);
driDestroyConfigs(psc->driver_configs);
close(psc->fd);
static int
dri3_set_swap_interval(__GLXDRIdrawable *pdraw, int interval)
{
+ assert(pdraw != NULL);
+
struct dri3_drawable *priv = (struct dri3_drawable *) pdraw;
GLint vblank_mode = DRI_CONF_VBLANK_DEF_INTERVAL_1;
struct dri3_screen *psc = (struct dri3_screen *) priv->base.psc;
static int
dri3_get_swap_interval(__GLXDRIdrawable *pdraw)
{
+ assert(pdraw != NULL);
+
struct dri3_drawable *priv = (struct dri3_drawable *) pdraw;
- return priv->swap_interval;
+ return priv->loader_drawable.swap_interval;
}
static void
if (pdraw != NULL) {
psc = (struct dri3_screen *) base->psc;
- (*psc->f->invalidate)(pdraw->loader_drawable.dri_drawable);
+ psc->f->invalidate(pdraw->loader_drawable.dri_drawable);
XSync(dpy, false);
.bind_tex_image = dri3_bind_tex_image,
.release_tex_image = dri3_release_tex_image,
.get_proc_address = NULL,
+ .interop_query_device_info = dri3_interop_query_device_info,
+ .interop_export_object = dri3_interop_export_object
};
/** dri3_bind_extensions
extensions = psc->core->getExtensions(psc->driScreen);
- __glXEnableDirectExtension(&psc->base, "GLX_SGI_video_sync");
__glXEnableDirectExtension(&psc->base, "GLX_SGI_swap_control");
__glXEnableDirectExtension(&psc->base, "GLX_MESA_swap_control");
__glXEnableDirectExtension(&psc->base, "GLX_SGI_make_current_read");
__glXEnableDirectExtension(&psc->base, "GLX_ARB_create_context");
__glXEnableDirectExtension(&psc->base, "GLX_ARB_create_context_profile");
- if ((mask & (1 << __DRI_API_GLES2)) != 0)
+ if ((mask & ((1 << __DRI_API_GLES) |
+ (1 << __DRI_API_GLES2) |
+ (1 << __DRI_API_GLES3))) != 0) {
+ __glXEnableDirectExtension(&psc->base,
+ "GLX_EXT_create_context_es_profile");
__glXEnableDirectExtension(&psc->base,
"GLX_EXT_create_context_es2_profile");
+ }
for (i = 0; extensions[i]; i++) {
/* when on a different gpu than the server, the server pixmaps
__glXEnableDirectExtension(&psc->base,
"GLX_ARB_create_context_robustness");
+ if (strcmp(extensions[i]->name, __DRI2_NO_ERROR) == 0)
+ __glXEnableDirectExtension(&psc->base,
+ "GLX_ARB_create_context_no_error");
+
if (strcmp(extensions[i]->name, __DRI2_RENDERER_QUERY) == 0) {
psc->rendererQuery = (__DRI2rendererQueryExtension *) extensions[i];
__glXEnableDirectExtension(&psc->base, "GLX_MESA_query_renderer");
}
+
+ if (strcmp(extensions[i]->name, __DRI2_INTEROP) == 0)
+ psc->interop = (__DRI2interopExtension*)extensions[i];
+
+ if (strcmp(extensions[i]->name, __DRI2_FLUSH_CONTROL) == 0)
+ __glXEnableDirectExtension(&psc->base,
+ "GLX_ARB_context_flush_control");
}
}
struct dri3_screen *psc;
__GLXDRIscreen *psp;
struct glx_config *configs = NULL, *visuals = NULL;
- char *driverName, *deviceName, *tmp;
+ char *driverName, *tmp;
int i;
+ unsigned char disable;
psc = calloc(1, sizeof *psc);
if (psc == NULL)
}
psc->fd = loader_get_user_preferred_fd(psc->fd, &psc->is_different_gpu);
- deviceName = NULL;
- driverName = loader_get_driver_for_fd(psc->fd, 0);
+ driverName = loader_get_driver_for_fd(psc->fd);
if (!driverName) {
ErrorMessageF("No driver found\n");
goto handle_error;
}
- psc->driver = driOpenDriver(driverName);
- if (psc->driver == NULL) {
- ErrorMessageF("driver pointer missing\n");
- goto handle_error;
- }
-
- extensions = driGetDriverExtensions(psc->driver, driverName);
+ extensions = driOpenDriver(driverName, &psc->driver);
if (extensions == NULL)
goto handle_error;
psp->waitForSBC = dri3_wait_for_sbc;
psp->setSwapInterval = dri3_set_swap_interval;
psp->getSwapInterval = dri3_get_swap_interval;
- __glXEnableDirectExtension(&psc->base, "GLX_OML_sync_control");
+ if (psc->config->configQueryb(psc->driScreen,
+ "glx_disable_oml_sync_control",
+ &disable) || !disable)
+ __glXEnableDirectExtension(&psc->base, "GLX_OML_sync_control");
+
+ if (psc->config->configQueryb(psc->driScreen,
+ "glx_disable_sgi_video_sync",
+ &disable) || !disable)
+ __glXEnableDirectExtension(&psc->base, "GLX_SGI_video_sync");
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");
+ if (psc->config->configQueryb(psc->driScreen,
+ "glx_disable_ext_buffer_age",
+ &disable) || !disable)
+ __glXEnableDirectExtension(&psc->base, "GLX_EXT_buffer_age");
free(driverName);
- free(deviceName);
tmp = getenv("LIBGL_SHOW_FPS");
psc->show_fps_interval = tmp ? atoi(tmp) : 0;
return &psc->base;
handle_error:
- CriticalErrorMessageF("failed to load driver: %s\n", driverName);
+ CriticalErrorMessageF("failed to load driver: %s\n", driverName ? driverName : "(null)");
if (configs)
glx_config_destroy_list(configs);
dlclose(psc->driver);
free(driverName);
- free(deviceName);
glx_screen_cleanup(&psc->base);
free(psc);
free(dpy);
}
+/* Only request versions of these protocols which we actually support. */
+#define DRI3_SUPPORTED_MAJOR 1
+#define PRESENT_SUPPORTED_MAJOR 1
+
+#ifdef HAVE_DRI3_MODIFIERS
+#define DRI3_SUPPORTED_MINOR 2
+#define PRESENT_SUPPORTED_MINOR 2
+#else
+#define PRESENT_SUPPORTED_MINOR 0
+#define DRI3_SUPPORTED_MINOR 0
+#endif
+
/** dri3_create_display
*
* Allocate, initialize and return a __DRIdisplayPrivate object.
return NULL;
dri3_cookie = xcb_dri3_query_version(c,
- XCB_DRI3_MAJOR_VERSION,
- XCB_DRI3_MINOR_VERSION);
-
-
+ DRI3_SUPPORTED_MAJOR,
+ DRI3_SUPPORTED_MINOR);
present_cookie = xcb_present_query_version(c,
- XCB_PRESENT_MAJOR_VERSION,
- XCB_PRESENT_MINOR_VERSION);
+ PRESENT_SUPPORTED_MAJOR,
+ PRESENT_SUPPORTED_MINOR);
pdp = malloc(sizeof *pdp);
if (pdp == NULL)
pdp->base.destroyDisplay = dri3_destroy_display;
pdp->base.createScreen = dri3_create_screen;
- loader_set_logger(dri_message);
-
pdp->loader_extensions = loader_extensions;
return &pdp->base;