X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fglx%2Fdri3_glx.c;h=ce60b95c71e34c4ba69fd95f140371290eea819b;hb=6b8f3724c83959e62b1be0330d6d14e58f91dc5b;hp=ee2431267319ed05a38febc4b62a4b73dfe3e977;hpb=179fc4aae8f782453f0488e8dd508f9a01117376;p=mesa.git diff --git a/src/glx/dri3_glx.c b/src/glx/dri3_glx.c index ee243126731..ce60b95c71e 100644 --- a/src/glx/dri3_glx.c +++ b/src/glx/dri3_glx.c @@ -81,31 +81,11 @@ 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) @@ -117,6 +97,10 @@ static bool 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; @@ -127,13 +111,19 @@ static __DRIcontext * 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 @@ -166,13 +156,11 @@ glx_dri3_show_fps(struct loader_dri3_drawable *draw, uint64_t current_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, }; @@ -202,20 +190,31 @@ dri3_bind_context(struct glx_context *context, struct glx_context *old, 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 (pread) + dri_read = pread->loader_drawable.dri_drawable; + else if (read != None) return GLXBadDrawable; - if (!(*psc->core->bindContext) (pcp->driContext, - pdraw->loader_drawable.dri_drawable, - pread->loader_drawable.dri_drawable)) + 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; } @@ -247,7 +246,8 @@ dri3_create_context_attribs(struct glx_screen *base, 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; @@ -256,7 +256,7 @@ dri3_create_context_attribs(struct glx_screen *base, if (!dri2_convert_glx_attribs(num_attribs, attribs, &major_ver, &minor_ver, &render_type, &flags, &api, - &reset, error)) + &reset, &release, error)) goto error_exit; /* Check the renderType value */ @@ -274,7 +274,7 @@ dri3_create_context_attribs(struct glx_screen *base, 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; @@ -291,6 +291,11 @@ dri3_create_context_attribs(struct glx_screen *base, 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; @@ -303,7 +308,8 @@ dri3_create_context_attribs(struct glx_screen *base, pcp->driContext = (*psc->image_driver->createContextAttribs) (psc->driScreen, api, - config->driConfig, + config ? config->driConfig + : NULL, shared, num_ctx_attribs / 2, ctx_attribs, @@ -329,9 +335,10 @@ dri3_create_context(struct glx_screen *base, 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 @@ -351,6 +358,11 @@ dri3_create_drawable(struct glx_screen *base, XID xDrawable, 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) @@ -361,11 +373,20 @@ dri3_create_drawable(struct glx_screen *base, XID xDrawable, 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); @@ -437,7 +458,8 @@ dri3_wait_x(struct glx_context *gc) struct dri3_drawable *priv = (struct dri3_drawable *) GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable); - loader_dri3_wait_x(&priv->loader_drawable); + if (priv) + loader_dri3_wait_x(&priv->loader_drawable); } static void @@ -446,7 +468,8 @@ dri3_wait_gl(struct glx_context *gc) struct dri3_drawable *priv = (struct dri3_drawable *) GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable); - loader_dri3_wait_gl(&priv->loader_drawable); + if (priv) + loader_dri3_wait_gl(&priv->loader_drawable); } /** @@ -472,26 +495,78 @@ dri3_flush_front_buffer(__DRIdrawable *driDrawable, void *loaderPrivate) 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 }; @@ -530,6 +605,7 @@ dri3_destroy_screen(struct glx_screen *base) 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); @@ -543,6 +619,8 @@ dri3_destroy_screen(struct glx_screen *base) 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; @@ -564,6 +642,7 @@ dri3_set_swap_interval(__GLXDRIdrawable *pdraw, int interval) break; } + priv->swap_interval = interval; loader_dri3_set_swap_interval(&priv->loader_drawable, interval); return 0; @@ -576,6 +655,8 @@ dri3_set_swap_interval(__GLXDRIdrawable *pdraw, int interval) static int dri3_get_swap_interval(__GLXDRIdrawable *pdraw) { + assert(pdraw != NULL); + struct dri3_drawable *priv = (struct dri3_drawable *) pdraw; return priv->swap_interval; @@ -636,6 +717,8 @@ static const struct glx_context_vtable dri3_context_vtable = { .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 @@ -652,7 +735,6 @@ dri3_bind_extensions(struct dri3_screen *psc, struct glx_display * priv, 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"); @@ -663,9 +745,14 @@ dri3_bind_extensions(struct dri3_screen *psc, struct glx_display * priv, __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 @@ -697,6 +784,13 @@ dri3_bind_extensions(struct dri3_screen *psc, struct glx_display * priv, 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"); } } @@ -730,8 +824,9 @@ dri3_create_screen(int screen, struct glx_display * priv) 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) @@ -759,9 +854,8 @@ dri3_create_screen(int screen, struct glx_display * priv) } 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; @@ -870,16 +964,26 @@ dri3_create_screen(int screen, struct glx_display * priv) 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; @@ -906,7 +1010,6 @@ handle_error: dlclose(psc->driver); free(driverName); - free(deviceName); glx_screen_cleanup(&psc->base); free(psc); @@ -923,6 +1026,18 @@ dri3_destroy_display(__GLXDRIdisplay * dpy) 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. @@ -954,13 +1069,11 @@ dri3_create_display(Display * dpy) 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)