X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fegl%2Fdrivers%2Fdri2%2Fplatform_x11.c;h=7486a91ec0c8887d653d740aacb0878c511e997b;hb=0695cf68f5afb903f93cc3779444d095b218271d;hp=4d72335552b3c996733dea65d4f8f52710dc1571;hpb=3104e5cb4f8524e9852300aa1e112d7fe31545ca;p=mesa.git diff --git a/src/egl/drivers/dri2/platform_x11.c b/src/egl/drivers/dri2/platform_x11.c index 4d72335552b..7486a91ec0c 100644 --- a/src/egl/drivers/dri2/platform_x11.c +++ b/src/egl/drivers/dri2/platform_x11.c @@ -39,6 +39,137 @@ #include "egl_dri2.h" +static void +swrastCreateDrawable(struct dri2_egl_display * dri2_dpy, + struct dri2_egl_surface * dri2_surf, + int depth) +{ + uint32_t mask; + const uint32_t function = GXcopy; + uint32_t valgc[2]; + + /* create GC's */ + dri2_surf->gc = xcb_generate_id(dri2_dpy->conn); + mask = XCB_GC_FUNCTION; + xcb_create_gc(dri2_dpy->conn, dri2_surf->gc, dri2_surf->drawable, mask, &function); + + dri2_surf->swapgc = xcb_generate_id(dri2_dpy->conn); + mask = XCB_GC_FUNCTION | XCB_GC_GRAPHICS_EXPOSURES; + valgc[0] = function; + valgc[1] = False; + xcb_create_gc(dri2_dpy->conn, dri2_surf->swapgc, dri2_surf->drawable, mask, valgc); + dri2_surf->depth = depth; + switch (depth) { + case 32: + case 24: + dri2_surf->bytes_per_pixel = 4; + break; + case 16: + dri2_surf->bytes_per_pixel = 2; + break; + case 8: + dri2_surf->bytes_per_pixel = 1; + break; + case 0: + dri2_surf->bytes_per_pixel = 0; + break; + default: + _eglLog(_EGL_WARNING, "unsupported depth %d", depth); + } +} + +static void +swrastDestroyDrawable(struct dri2_egl_display * dri2_dpy, + struct dri2_egl_surface * dri2_surf) +{ + xcb_free_gc(dri2_dpy->conn, dri2_surf->gc); + xcb_free_gc(dri2_dpy->conn, dri2_surf->swapgc); +} + +static void +swrastGetDrawableInfo(__DRIdrawable * draw, + int *x, int *y, int *w, int *h, + void *loaderPrivate) +{ + struct dri2_egl_surface *dri2_surf = loaderPrivate; + struct dri2_egl_display *dri2_dpy = dri2_egl_display(dri2_surf->base.Resource.Display); + + xcb_get_geometry_cookie_t cookie; + xcb_get_geometry_reply_t *reply; + xcb_generic_error_t *error; + + *w = *h = 0; + cookie = xcb_get_geometry (dri2_dpy->conn, dri2_surf->drawable); + reply = xcb_get_geometry_reply (dri2_dpy->conn, cookie, &error); + if (reply == NULL) + return; + + if (error != NULL) { + _eglLog(_EGL_WARNING, "error in xcb_get_geometry"); + free(error); + } else { + *w = reply->width; + *h = reply->height; + } + free(reply); +} + +static void +swrastPutImage(__DRIdrawable * draw, int op, + int x, int y, int w, int h, + char *data, void *loaderPrivate) +{ + struct dri2_egl_surface *dri2_surf = loaderPrivate; + struct dri2_egl_display *dri2_dpy = dri2_egl_display(dri2_surf->base.Resource.Display); + + xcb_gcontext_t gc; + + switch (op) { + case __DRI_SWRAST_IMAGE_OP_DRAW: + gc = dri2_surf->gc; + break; + case __DRI_SWRAST_IMAGE_OP_SWAP: + gc = dri2_surf->swapgc; + break; + default: + return; + } + + xcb_put_image(dri2_dpy->conn, XCB_IMAGE_FORMAT_Z_PIXMAP, dri2_surf->drawable, + gc, w, h, x, y, 0, dri2_surf->depth, + w*h*dri2_surf->bytes_per_pixel, (const uint8_t *)data); +} + +static void +swrastGetImage(__DRIdrawable * read, + int x, int y, int w, int h, + char *data, void *loaderPrivate) +{ + struct dri2_egl_surface *dri2_surf = loaderPrivate; + struct dri2_egl_display *dri2_dpy = dri2_egl_display(dri2_surf->base.Resource.Display); + + xcb_get_image_cookie_t cookie; + xcb_get_image_reply_t *reply; + xcb_generic_error_t *error; + + cookie = xcb_get_image (dri2_dpy->conn, XCB_IMAGE_FORMAT_Z_PIXMAP, + dri2_surf->drawable, x, y, w, h, ~0); + reply = xcb_get_image_reply (dri2_dpy->conn, cookie, &error); + if (reply == NULL) + return; + + if (error != NULL) { + _eglLog(_EGL_WARNING, "error in xcb_get_image"); + free(error); + } else { + uint32_t bytes = xcb_get_image_data_length(reply); + uint8_t *idata = xcb_get_image_data(reply); + memcpy(data, idata, bytes); + } + free(reply); +} + + /** * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface(). */ @@ -77,18 +208,31 @@ dri2_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type, dri2_surf->drawable = window; } - dri2_surf->dri_drawable = - (*dri2_dpy->dri2->createNewDrawable) (dri2_dpy->dri_screen, - type == EGL_WINDOW_BIT ? - dri2_conf->dri_double_config : - dri2_conf->dri_single_config, - dri2_surf); + if (dri2_dpy->dri2) { + dri2_surf->dri_drawable = + (*dri2_dpy->dri2->createNewDrawable) (dri2_dpy->dri_screen, + type == EGL_WINDOW_BIT ? + dri2_conf->dri_double_config : + dri2_conf->dri_single_config, + dri2_surf); + } else { + assert(dri2_dpy->swrast); + dri2_surf->dri_drawable = + (*dri2_dpy->swrast->createNewDrawable) (dri2_dpy->dri_screen, + dri2_conf->dri_double_config, + dri2_surf); + } + if (dri2_surf->dri_drawable == NULL) { _eglError(EGL_BAD_ALLOC, "dri2->createNewDrawable"); goto cleanup_pixmap; } - - xcb_dri2_create_drawable (dri2_dpy->conn, dri2_surf->drawable); + + if (dri2_dpy->dri2) { + xcb_dri2_create_drawable (dri2_dpy->conn, dri2_surf->drawable); + } else { + swrastCreateDrawable(dri2_dpy, dri2_surf, _eglGetConfigKey(conf, EGL_BUFFER_SIZE)); + } if (type != EGL_PBUFFER_BIT) { cookie = xcb_get_geometry (dri2_dpy->conn, dri2_surf->drawable); @@ -104,6 +248,9 @@ dri2_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type, free(reply); } + /* we always copy the back buffer to front */ + dri2_surf->base.PostSubBufferSupportedNV = EGL_TRUE; + return &dri2_surf->base; cleanup_dri_drawable: @@ -159,7 +306,12 @@ dri2_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf) (*dri2_dpy->core->destroyDrawable)(dri2_surf->dri_drawable); - xcb_dri2_destroy_drawable (dri2_dpy->conn, dri2_surf->drawable); + if (dri2_dpy->dri2) { + xcb_dri2_destroy_drawable (dri2_dpy->conn, dri2_surf->drawable); + } else { + assert(dri2_dpy->swrast); + swrastDestroyDrawable(dri2_dpy, dri2_surf); + } if (surf->Type == EGL_PBUFFER_BIT) xcb_free_pixmap (dri2_dpy->conn, dri2_surf->drawable); @@ -329,10 +481,20 @@ dri2_connect(struct dri2_egl_display *dri2_dpy) xcb_dri2_connect_cookie_t connect_cookie; xcb_generic_error_t *error; xcb_screen_iterator_t s; + char *driver_name, *device_name; + const xcb_query_extension_reply_t *extension; xcb_prefetch_extension_data (dri2_dpy->conn, &xcb_xfixes_id); xcb_prefetch_extension_data (dri2_dpy->conn, &xcb_dri2_id); + extension = xcb_get_extension_data(dri2_dpy->conn, &xcb_xfixes_id); + if (!(extension && extension->present)) + return EGL_FALSE; + + extension = xcb_get_extension_data(dri2_dpy->conn, &xcb_dri2_id); + if (!(extension && extension->present)) + return EGL_FALSE; + xfixes_query_cookie = xcb_xfixes_query_version(dri2_dpy->conn, XCB_XFIXES_MAJOR_VERSION, XCB_XFIXES_MINOR_VERSION); @@ -351,7 +513,7 @@ dri2_connect(struct dri2_egl_display *dri2_dpy) xfixes_query_cookie, &error); if (xfixes_query == NULL || error != NULL || xfixes_query->major_version < 2) { - _eglLog(_EGL_FATAL, "DRI2: failed to query xfixes version"); + _eglLog(_EGL_WARNING, "DRI2: failed to query xfixes version"); free(error); return EGL_FALSE; } @@ -360,7 +522,7 @@ dri2_connect(struct dri2_egl_display *dri2_dpy) dri2_query = xcb_dri2_query_version_reply (dri2_dpy->conn, dri2_query_cookie, &error); if (dri2_query == NULL || error != NULL) { - _eglLog(_EGL_FATAL, "DRI2: failed to query version"); + _eglLog(_EGL_WARNING, "DRI2: failed to query version"); free(error); return EGL_FALSE; } @@ -371,18 +533,25 @@ dri2_connect(struct dri2_egl_display *dri2_dpy) connect = xcb_dri2_connect_reply (dri2_dpy->conn, connect_cookie, NULL); if (connect == NULL || connect->driver_name_length + connect->device_name_length == 0) { - _eglLog(_EGL_FATAL, "DRI2: failed to authenticate"); + _eglLog(_EGL_WARNING, "DRI2: failed to authenticate"); return EGL_FALSE; } - dri2_dpy->device_name = - dri2_strndup(xcb_dri2_connect_device_name (connect), - xcb_dri2_connect_device_name_length (connect)); - + driver_name = xcb_dri2_connect_driver_name (connect); dri2_dpy->driver_name = - dri2_strndup(xcb_dri2_connect_driver_name (connect), + dri2_strndup(driver_name, xcb_dri2_connect_driver_name_length (connect)); +#if XCB_DRI2_CONNECT_DEVICE_NAME_BROKEN + device_name = driver_name + ((connect->driver_name_length + 3) & ~3); +#else + device_name = xcb_dri2_connect_device_name (connect); +#endif + + dri2_dpy->device_name = + dri2_strndup(device_name, + xcb_dri2_connect_device_name_length (connect)); + if (dri2_dpy->device_name == NULL || dri2_dpy->driver_name == NULL) { free(dri2_dpy->device_name); free(dri2_dpy->driver_name); @@ -394,31 +563,45 @@ dri2_connect(struct dri2_egl_display *dri2_dpy) return EGL_TRUE; } -static EGLBoolean -dri2_authenticate(struct dri2_egl_display *dri2_dpy) +static int +dri2_x11_authenticate(_EGLDisplay *disp, uint32_t id) { + struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); xcb_dri2_authenticate_reply_t *authenticate; xcb_dri2_authenticate_cookie_t authenticate_cookie; xcb_screen_iterator_t s; - drm_magic_t magic; - - if (drmGetMagic(dri2_dpy->fd, &magic)) { - _eglLog(_EGL_FATAL, "DRI2: failed to get drm magic"); - return EGL_FALSE; - } + int ret = 0; s = xcb_setup_roots_iterator(xcb_get_setup(dri2_dpy->conn)); authenticate_cookie = - xcb_dri2_authenticate_unchecked(dri2_dpy->conn, s.data->root, magic); + xcb_dri2_authenticate_unchecked(dri2_dpy->conn, s.data->root, id); authenticate = xcb_dri2_authenticate_reply(dri2_dpy->conn, authenticate_cookie, NULL); - if (authenticate == NULL || !authenticate->authenticated) { - _eglLog(_EGL_FATAL, "DRI2: failed to authenticate"); + + if (authenticate == NULL || !authenticate->authenticated) + ret = -1; + + if (authenticate) free(authenticate); + + return ret; +} + +static EGLBoolean +dri2_authenticate(_EGLDisplay *disp) +{ + struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); + drm_magic_t magic; + + if (drmGetMagic(dri2_dpy->fd, &magic)) { + _eglLog(_EGL_WARNING, "DRI2: failed to get drm magic"); + return EGL_FALSE; + } + + if (dri2_x11_authenticate(disp, magic) < 0) { + _eglLog(_EGL_WARNING, "DRI2: failed to authenticate"); return EGL_FALSE; } - - free(authenticate); return EGL_TRUE; } @@ -462,7 +645,7 @@ dri2_add_configs_for_visuals(struct dri2_egl_display *dri2_dpy, config_attrs[3] = visuals[i]._class; dri2_add_config(disp, dri2_dpy->driver_configs[j], id++, - d.data->depth, surface_type, config_attrs); + d.data->depth, surface_type, config_attrs, NULL); } } @@ -481,30 +664,18 @@ static EGLBoolean dri2_copy_region(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw, xcb_xfixes_region_t region) { - struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv); struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw); - _EGLContext *ctx; enum xcb_dri2_attachment_t render_attachment; xcb_dri2_copy_region_cookie_t cookie; - if (dri2_drv->glFlush) { - ctx = _eglGetCurrentContext(); - if (ctx && ctx->DrawSurface == &dri2_surf->base) - dri2_drv->glFlush(); - } - - (*dri2_dpy->flush->flush)(dri2_surf->dri_drawable); + /* No-op for a pixmap or pbuffer surface */ + if (draw->Type == EGL_PIXMAP_BIT || draw->Type == EGL_PBUFFER_BIT) + return EGL_TRUE; -#if 0 - /* FIXME: Add support for dri swapbuffers, that'll give us swap - * interval and page flipping (at least for fullscreen windows) as - * well as the page flip event. Unless surface->SwapBehavior is - * EGL_BUFFER_PRESERVED. */ -#if __DRI2_FLUSH_VERSION >= 2 - if (pdraw->psc->f) - (*pdraw->psc->f->flushInvalidate)(pdraw->driDrawable); -#endif +#ifdef __DRI2_FLUSH + if (dri2_dpy->flush) + (*dri2_dpy->flush->flush)(dri2_surf->dri_drawable); #endif if (dri2_surf->have_fake_front) @@ -522,12 +693,75 @@ dri2_copy_region(_EGLDriver *drv, _EGLDisplay *disp, return EGL_TRUE; } +static int64_t +dri2_swap_buffers_msc(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw, + int64_t msc, int64_t divisor, int64_t remainder) +{ +#if XCB_DRI2_MINOR_VERSION >= 3 + struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); + struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw); + uint32_t msc_hi = msc >> 32; + uint32_t msc_lo = msc & 0xffffffff; + uint32_t divisor_hi = divisor >> 32; + uint32_t divisor_lo = divisor & 0xffffffff; + uint32_t remainder_hi = remainder >> 32; + uint32_t remainder_lo = remainder & 0xffffffff; + xcb_dri2_swap_buffers_cookie_t cookie; + xcb_dri2_swap_buffers_reply_t *reply; + int64_t swap_count = -1; + + /* No-op for a pixmap or pbuffer surface */ + if (draw->Type == EGL_PIXMAP_BIT || draw->Type == EGL_PBUFFER_BIT) + return 0; + + if (draw->SwapBehavior == EGL_BUFFER_PRESERVED || !dri2_dpy->swap_available) + return dri2_copy_region(drv, disp, draw, dri2_surf->region) ? 0 : -1; + +#ifdef __DRI2_FLUSH + if (dri2_dpy->flush) + (*dri2_dpy->flush->flush)(dri2_surf->dri_drawable); +#endif + + cookie = xcb_dri2_swap_buffers_unchecked(dri2_dpy->conn, dri2_surf->drawable, + msc_hi, msc_lo, divisor_hi, divisor_lo, remainder_hi, remainder_lo); + + reply = xcb_dri2_swap_buffers_reply(dri2_dpy->conn, cookie, NULL); + + if (reply) { + swap_count = (((int64_t)reply->swap_hi) << 32) | reply->swap_lo; + free(reply); + } + +#if __DRI2_FLUSH_VERSION >= 3 + /* If the server doesn't send invalidate events */ + if (dri2_dpy->invalidate_available && dri2_dpy->flush && + dri2_dpy->flush->base.version >= 3 && dri2_dpy->flush->invalidate) + (*dri2_dpy->flush->invalidate)(dri2_surf->dri_drawable); +#endif + + return swap_count; +#else + struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw); + + return dri2_copy_region(drv, disp, draw, dri2_surf->region) ? 0 : -1; +#endif /* XCB_DRI2_MINOR_VERSION >= 3 */ + +} + static EGLBoolean dri2_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw) { + struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw); - return dri2_copy_region(drv, disp, draw, dri2_surf->region); + if (dri2_dpy->dri2) { + return dri2_swap_buffers_msc(drv, disp, draw, 0, 0, 0) != -1; + } else { + assert(dri2_dpy->swrast); + + dri2_dpy->core->swapBuffers(dri2_surf->dri_drawable); + return EGL_TRUE; + } } static EGLBoolean @@ -560,6 +794,43 @@ dri2_swap_buffers_region(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw, return ret; } +static EGLBoolean +dri2_post_sub_buffer(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw, + EGLint x, EGLint y, EGLint width, EGLint height) +{ + const EGLint rect[4] = { x, draw->Height - y - height, width, height }; + + if (x < 0 || y < 0 || width < 0 || height < 0) + _eglError(EGL_BAD_PARAMETER, "eglPostSubBufferNV"); + + return dri2_swap_buffers_region(drv, disp, draw, 1, rect); +} + +static EGLBoolean +dri2_swap_interval(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf, EGLint interval) +{ +#if XCB_DRI2_MINOR_VERSION >= 3 + struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); + struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf); +#endif + + /* XXX Check vblank_mode here? */ + + if (interval > surf->Config->MaxSwapInterval) + interval = surf->Config->MaxSwapInterval; + else if (interval < surf->Config->MinSwapInterval) + interval = surf->Config->MinSwapInterval; + +#if XCB_DRI2_MINOR_VERSION >= 3 + if (interval != surf->SwapInterval && dri2_dpy->swap_available) + xcb_dri2_swap_interval(dri2_dpy->conn, dri2_surf->drawable, interval); +#endif + + surf->SwapInterval = interval; + + return EGL_TRUE; +} + static EGLBoolean dri2_copy_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf, EGLNativePixmapType target) @@ -605,7 +876,7 @@ dri2_create_image_khr_pixmap(_EGLDisplay *disp, _EGLContext *ctx, (void) ctx; - drawable = (xcb_drawable_t) buffer; + drawable = (xcb_drawable_t) (uintptr_t) buffer; xcb_dri2_create_drawable (dri2_dpy->conn, drawable); attachments[0] = XCB_DRI2_ATTACHMENT_BUFFER_FRONT_LEFT; buffers_cookie = @@ -625,6 +896,7 @@ dri2_create_image_khr_pixmap(_EGLDisplay *disp, _EGLContext *ctx, _eglError(EGL_BAD_ALLOC, "xcb_get_geometry"); free(error); free(buffers_reply); + return NULL; } switch (geometry_reply->depth) { @@ -656,6 +928,7 @@ dri2_create_image_khr_pixmap(_EGLDisplay *disp, _EGLContext *ctx, if (!_eglInitImage(&dri2_img->base, disp)) { free(buffers_reply); free(geometry_reply); + free(dri2_img); return EGL_NO_IMAGE_KHR; } @@ -690,8 +963,86 @@ dri2_x11_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp, } } -EGLBoolean -dri2_initialize_x11(_EGLDriver *drv, _EGLDisplay *disp) +static EGLBoolean +dri2_initialize_x11_swrast(_EGLDriver *drv, _EGLDisplay *disp) +{ + struct dri2_egl_display *dri2_dpy; + + drv->API.CreateWindowSurface = dri2_create_window_surface; + drv->API.CreatePixmapSurface = dri2_create_pixmap_surface; + drv->API.CreatePbufferSurface = dri2_create_pbuffer_surface; + drv->API.DestroySurface = dri2_destroy_surface; + drv->API.SwapBuffers = dri2_swap_buffers; + drv->API.CopyBuffers = dri2_copy_buffers; + + drv->API.SwapBuffersRegionNOK = NULL; + drv->API.CreateImageKHR = NULL; + drv->API.DestroyImageKHR = NULL; + drv->API.CreateDRMImageMESA = NULL; + drv->API.ExportDRMImageMESA = NULL; + + dri2_dpy = malloc(sizeof *dri2_dpy); + if (!dri2_dpy) + return _eglError(EGL_BAD_ALLOC, "eglInitialize"); + + memset(dri2_dpy, 0, sizeof *dri2_dpy); + + disp->DriverData = (void *) dri2_dpy; + if (disp->PlatformDisplay == NULL) { + dri2_dpy->conn = xcb_connect(0, 0); + } else { + dri2_dpy->conn = XGetXCBConnection((Display *) disp->PlatformDisplay); + } + + if (xcb_connection_has_error(dri2_dpy->conn)) { + _eglLog(_EGL_WARNING, "DRI2: xcb_connect failed"); + goto cleanup_dpy; + } + + if (!dri2_load_driver_swrast(disp)) + goto cleanup_conn; + + dri2_dpy->swrast_loader_extension.base.name = __DRI_SWRAST_LOADER; + dri2_dpy->swrast_loader_extension.base.version = __DRI_SWRAST_LOADER_VERSION; + dri2_dpy->swrast_loader_extension.getDrawableInfo = swrastGetDrawableInfo; + dri2_dpy->swrast_loader_extension.putImage = swrastPutImage; + dri2_dpy->swrast_loader_extension.getImage = swrastGetImage; + + dri2_dpy->extensions[0] = &dri2_dpy->swrast_loader_extension.base; + dri2_dpy->extensions[1] = NULL; + dri2_dpy->extensions[2] = NULL; + + if (!dri2_create_screen(disp)) + goto cleanup_driver; + + if (dri2_dpy->conn) { + if (!dri2_add_configs_for_visuals(dri2_dpy, disp)) + goto cleanup_configs; + } + + /* we're supporting EGL 1.4 */ + disp->VersionMajor = 1; + disp->VersionMinor = 4; + + return EGL_TRUE; + + cleanup_configs: + _eglCleanupDisplay(disp); + dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen); + cleanup_driver: + dlclose(dri2_dpy->driver); + cleanup_conn: + if (disp->PlatformDisplay == NULL) + xcb_disconnect(dri2_dpy->conn); + cleanup_dpy: + free(dri2_dpy); + + return EGL_FALSE; +} + + +static EGLBoolean +dri2_initialize_x11_dri2(_EGLDriver *drv, _EGLDisplay *disp) { struct dri2_egl_display *dri2_dpy; @@ -703,11 +1054,15 @@ dri2_initialize_x11(_EGLDriver *drv, _EGLDisplay *disp) drv->API.CopyBuffers = dri2_copy_buffers; drv->API.CreateImageKHR = dri2_x11_create_image_khr; drv->API.SwapBuffersRegionNOK = dri2_swap_buffers_region; + drv->API.PostSubBufferNV = dri2_post_sub_buffer; + drv->API.SwapInterval = dri2_swap_interval; dri2_dpy = malloc(sizeof *dri2_dpy); if (!dri2_dpy) return _eglError(EGL_BAD_ALLOC, "eglInitialize"); + memset(dri2_dpy, 0, sizeof *dri2_dpy); + disp->DriverData = (void *) dri2_dpy; if (disp->PlatformDisplay == NULL) { dri2_dpy->conn = xcb_connect(0, 0); @@ -728,7 +1083,16 @@ dri2_initialize_x11(_EGLDriver *drv, _EGLDisplay *disp) if (!dri2_load_driver(disp)) goto cleanup_conn; - dri2_dpy->fd = open(dri2_dpy->device_name, O_RDWR); +#ifdef O_CLOEXEC + dri2_dpy->fd = open(dri2_dpy->device_name, O_RDWR | O_CLOEXEC); + if (dri2_dpy->fd == -1 && errno == EINVAL) +#endif + { + dri2_dpy->fd = open(dri2_dpy->device_name, O_RDWR); + if (dri2_dpy->fd != -1) + fcntl(dri2_dpy->fd, F_SETFD, fcntl(dri2_dpy->fd, F_GETFD) | + FD_CLOEXEC); + } if (dri2_dpy->fd == -1) { _eglLog(_EGL_WARNING, "DRI2: could not open %s (%s)", dri2_dpy->device_name, @@ -737,7 +1101,7 @@ dri2_initialize_x11(_EGLDriver *drv, _EGLDisplay *disp) } if (dri2_dpy->conn) { - if (!dri2_authenticate(dri2_dpy)) + if (!dri2_authenticate(disp)) goto cleanup_fd; } @@ -760,6 +1124,11 @@ dri2_initialize_x11(_EGLDriver *drv, _EGLDisplay *disp) dri2_dpy->extensions[1] = &image_lookup_extension.base; dri2_dpy->extensions[2] = NULL; +#if XCB_DRI2_MINOR_VERSION >= 3 + dri2_dpy->swap_available = (dri2_dpy->dri2_minor >= 2); + dri2_dpy->invalidate_available = (dri2_dpy->dri2_minor >= 3); +#endif + if (!dri2_create_screen(disp)) goto cleanup_fd; @@ -768,13 +1137,15 @@ dri2_initialize_x11(_EGLDriver *drv, _EGLDisplay *disp) goto cleanup_configs; } - disp->Extensions.MESA_drm_image = EGL_TRUE; - disp->Extensions.KHR_image_base = EGL_TRUE; disp->Extensions.KHR_image_pixmap = EGL_TRUE; - disp->Extensions.KHR_gl_renderbuffer_image = EGL_TRUE; - disp->Extensions.KHR_gl_texture_2D_image = EGL_TRUE; disp->Extensions.NOK_swap_region = EGL_TRUE; disp->Extensions.NOK_texture_from_pixmap = EGL_TRUE; + disp->Extensions.NV_post_sub_buffer = EGL_TRUE; + +#ifdef HAVE_WAYLAND_PLATFORM + disp->Extensions.WL_bind_wayland_display = EGL_TRUE; +#endif + dri2_dpy->authenticate = dri2_x11_authenticate; /* we're supporting EGL 1.4 */ disp->VersionMajor = 1; @@ -797,3 +1168,22 @@ dri2_initialize_x11(_EGLDriver *drv, _EGLDisplay *disp) return EGL_FALSE; } + +EGLBoolean +dri2_initialize_x11(_EGLDriver *drv, _EGLDisplay *disp) +{ + EGLBoolean initialized = EGL_TRUE; + + int x11_dri2_accel = (getenv("LIBGL_ALWAYS_SOFTWARE") == NULL); + + if (x11_dri2_accel) { + if (!dri2_initialize_x11_dri2(drv, disp)) { + initialized = dri2_initialize_x11_swrast(drv, disp); + } + } else { + initialized = dri2_initialize_x11_swrast(drv, disp); + } + + return initialized; +} +