X-Git-Url: https://git.libre-soc.org/?p=mesa.git;a=blobdiff_plain;f=src%2Fegl%2Fdrivers%2Fdri2%2Fegl_dri2.c;h=4be39627302566baca9ecd0eb1c3d6ff34fa7fb2;hp=5d36c49b2c9ff2c910716f42e3aa79890d3624a9;hb=6fc532ae05352a5540c658580cde08b1e0e9f84c;hpb=c19dab7c5929bc70633002111bbb2b496a90899e diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c index 5d36c49b2c9..4be39627302 100644 --- a/src/egl/drivers/dri2/egl_dri2.c +++ b/src/egl/drivers/dri2/egl_dri2.c @@ -42,7 +42,6 @@ #include #include -#include "eglconfigutil.h" #include "eglconfig.h" #include "eglcontext.h" #include "egldisplay.h" @@ -50,10 +49,13 @@ #include "eglcurrent.h" #include "egllog.h" #include "eglsurface.h" +#include "eglimage.h" struct dri2_egl_driver { _EGLDriver base; + + void (*glFlush)(void); }; struct dri2_egl_display @@ -62,15 +64,21 @@ struct dri2_egl_display int dri2_major; int dri2_minor; __DRIscreen *dri_screen; + const __DRIconfig **driver_configs; void *driver; __DRIcoreExtension *core; __DRIdri2Extension *dri2; __DRI2flushExtension *flush; __DRItexBufferExtension *tex_buffer; + __DRIimageExtension *image; int fd; + char *device_name; + char *driver_name; + __DRIdri2LoaderExtension loader_extension; - const __DRIextension *extensions[2]; + __DRIimageLookupExtension image_lookup_extension; + const __DRIextension *extensions[3]; }; struct dri2_egl_context @@ -93,12 +101,19 @@ struct dri2_egl_surface struct dri2_egl_config { - _EGLConfig base; + _EGLConfig base; const __DRIconfig *dri_config; }; +struct dri2_egl_image +{ + _EGLImage base; + __DRIimage *dri_image; +}; + /* standard typecasts */ _EGL_DRIVER_STANDARD_TYPECASTS(dri2_egl) +_EGL_DRIVER_TYPECAST(dri2_egl_image, _EGLImage, obj) EGLint dri2_to_egl_attribute_map[] = { 0, @@ -346,6 +361,25 @@ dri2_flush_front_buffer(__DRIdrawable * driDrawable, void *loaderPrivate) #endif } +static __DRIimage * +dri2_lookup_egl_image(__DRIcontext *context, void *image, void *data) +{ + struct dri2_egl_context *dri2_ctx = data; + _EGLDisplay *disp = dri2_ctx->base.Resource.Display; + struct dri2_egl_image *dri2_img; + _EGLImage *img; + + img = _eglLookupImage(image, disp); + if (img == NULL) { + _eglError(EGL_BAD_PARAMETER, "dri2_lookup_egl_image"); + return NULL; + } + + dri2_img = dri2_egl_image(image); + + return dri2_img->dri_image; +} + static __DRIbuffer * dri2_get_buffers_with_format(__DRIdrawable * driDrawable, int *width, int *height, @@ -383,9 +417,9 @@ dri2_get_buffers_with_format(__DRIdrawable * driDrawable, } #ifdef GLX_USE_TLS -static const char dri_driver_format[] = "%.*s/tls/%.*s_dri.so"; +static const char dri_driver_format[] = "%.*s/tls/%s_dri.so"; #else -static const char dri_driver_format[] = "%.*s/%.*s_dri.so"; +static const char dri_driver_format[] = "%.*s/%s_dri.so"; #endif static const char dri_driver_path[] = DEFAULT_DRIVER_DIR; @@ -405,6 +439,7 @@ static struct dri2_extension_match dri2_driver_extensions[] = { static struct dri2_extension_match dri2_core_extensions[] = { { __DRI2_FLUSH, 1, offsetof(struct dri2_egl_display, flush) }, { __DRI_TEX_BUFFER, 2, offsetof(struct dri2_egl_display, tex_buffer) }, + { __DRI_IMAGE, 1, offsetof(struct dri2_egl_display, image) }, { NULL } }; @@ -441,45 +476,32 @@ dri2_bind_extensions(struct dri2_egl_display *dri2_dpy, return ret; } -/** - * Called via eglInitialize(), GLX_drv->API.Initialize(). - */ +static char * +dri2_strndup(const char *s, int length) +{ + char *d; + + d = malloc(length + 1); + if (d == NULL) + return NULL; + + memcpy(d, s, length); + d[length] = '\0'; + + return d; +} + static EGLBoolean -dri2_initialize(_EGLDriver *drv, _EGLDisplay *disp, - EGLint *major, EGLint *minor) +dri2_connect(struct dri2_egl_display *dri2_dpy) { - const __DRIextension **extensions; - const __DRIconfig **driver_configs; - struct dri2_egl_display *dri2_dpy; - char path[PATH_MAX], *search_paths, *p, *next, *end; xcb_xfixes_query_version_reply_t *xfixes_query; xcb_xfixes_query_version_cookie_t xfixes_query_cookie; xcb_dri2_query_version_reply_t *dri2_query; xcb_dri2_query_version_cookie_t dri2_query_cookie; xcb_dri2_connect_reply_t *connect; xcb_dri2_connect_cookie_t connect_cookie; - xcb_dri2_authenticate_reply_t *authenticate; - xcb_dri2_authenticate_cookie_t authenticate_cookie; xcb_generic_error_t *error; - drm_magic_t magic; xcb_screen_iterator_t s; - xcb_depth_iterator_t d; - xcb_visualtype_t *visuals; - int i, j, id; - - dri2_dpy = malloc(sizeof *dri2_dpy); - if (!dri2_dpy) - return _eglError(EGL_BAD_ALLOC, "eglInitialize"); - - disp->DriverData = (void *) dri2_dpy; - if (disp->NativeDisplay != NULL) - dri2_dpy->conn = XGetXCBConnection(disp->NativeDisplay); - else - dri2_dpy->conn = xcb_connect(0, 0); - if (!dri2_dpy->conn) { - _eglLog(_EGL_WARNING, "DRI2: xcb_connect failed"); - goto cleanup_dpy; - } xcb_prefetch_extension_data (dri2_dpy->conn, &xcb_xfixes_id); xcb_prefetch_extension_data (dri2_dpy->conn, &xcb_dri2_id); @@ -504,7 +526,7 @@ dri2_initialize(_EGLDriver *drv, _EGLDisplay *disp, error != NULL || xfixes_query->major_version < 2) { _eglLog(_EGL_FATAL, "DRI2: failed to query xfixes version"); free(error); - goto cleanup_conn; + return EGL_FALSE; } free(xfixes_query); @@ -513,7 +535,7 @@ dri2_initialize(_EGLDriver *drv, _EGLDisplay *disp, if (dri2_query == NULL || error != NULL) { _eglLog(_EGL_FATAL, "DRI2: failed to query version"); free(error); - goto cleanup_conn; + return EGL_FALSE; } dri2_dpy->dri2_major = dri2_query->major_version; dri2_dpy->dri2_minor = dri2_query->minor_version; @@ -523,7 +545,126 @@ dri2_initialize(_EGLDriver *drv, _EGLDisplay *disp, if (connect == NULL || connect->driver_name_length + connect->device_name_length == 0) { _eglLog(_EGL_FATAL, "DRI2: failed to authenticate"); - goto cleanup_connect; + return EGL_FALSE; + } + + dri2_dpy->device_name = + dri2_strndup(xcb_dri2_connect_device_name (connect), + xcb_dri2_connect_device_name_length (connect)); + + dri2_dpy->driver_name = + dri2_strndup(xcb_dri2_connect_driver_name (connect), + xcb_dri2_connect_driver_name_length (connect)); + + if (dri2_dpy->device_name == NULL || dri2_dpy->driver_name == NULL) { + free(dri2_dpy->device_name); + free(dri2_dpy->driver_name); + free(connect); + return EGL_FALSE; + } + free(connect); + + return EGL_TRUE; +} + +static EGLBoolean +dri2_authenticate(struct dri2_egl_display *dri2_dpy) +{ + 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; + } + + s = xcb_setup_roots_iterator(xcb_get_setup(dri2_dpy->conn)); + authenticate_cookie = + xcb_dri2_authenticate_unchecked(dri2_dpy->conn, s.data->root, magic); + authenticate = + xcb_dri2_authenticate_reply(dri2_dpy->conn, authenticate_cookie, NULL); + if (authenticate == NULL || !authenticate->authenticated) { + _eglLog(_EGL_FATAL, "DRI2: failed to authenticate"); + free(authenticate); + return EGL_FALSE; + } + + free(authenticate); + + return EGL_TRUE; +} + +static EGLBoolean +dri2_add_configs_for_visuals(struct dri2_egl_display *dri2_dpy, + _EGLDisplay *disp) +{ + xcb_screen_iterator_t s; + xcb_depth_iterator_t d; + xcb_visualtype_t *visuals; + int i, j, id; + + s = xcb_setup_roots_iterator(xcb_get_setup(dri2_dpy->conn)); + d = xcb_screen_allowed_depths_iterator(s.data); + id = 1; + while (d.rem > 0) { + EGLBoolean class_added[6] = { 0, }; + + visuals = xcb_depth_visuals(d.data); + for (i = 0; i < xcb_depth_visuals_length(d.data); i++) { + if (class_added[visuals[i]._class]) + continue; + + class_added[visuals[i]._class] = EGL_TRUE; + for (j = 0; dri2_dpy->driver_configs[j]; j++) + dri2_add_config(disp, dri2_dpy->driver_configs[j], + id++, d.data->depth, &visuals[i]); + } + + xcb_depth_next(&d); + } + + if (!disp->NumConfigs) { + _eglLog(_EGL_WARNING, "DRI2: failed to create any config"); + return EGL_FALSE; + } + + return EGL_TRUE; +} + +/** + * Called via eglInitialize(), GLX_drv->API.Initialize(). + */ +static EGLBoolean +dri2_initialize(_EGLDriver *drv, _EGLDisplay *disp, + EGLint *major, EGLint *minor) +{ + const __DRIextension **extensions; + struct dri2_egl_display *dri2_dpy; + char path[PATH_MAX], *search_paths, *p, *next, *end; + + dri2_dpy = malloc(sizeof *dri2_dpy); + if (!dri2_dpy) + return _eglError(EGL_BAD_ALLOC, "eglInitialize"); + + disp->DriverData = (void *) dri2_dpy; + if (disp->NativeDisplay == NULL) { + dri2_dpy->conn = xcb_connect(0, 0); + if (!dri2_dpy->conn) { + _eglLog(_EGL_WARNING, "DRI2: xcb_connect failed"); + goto cleanup_dpy; + } + } else { + dri2_dpy->conn = XGetXCBConnection(disp->NativeDisplay); + } + + if (dri2_dpy->conn == NULL) + goto cleanup_conn; + + if (dri2_dpy->conn) { + if (!dri2_connect(dri2_dpy)) + goto cleanup_conn; } search_paths = NULL; @@ -542,11 +683,7 @@ dri2_initialize(_EGLDriver *drv, _EGLDisplay *disp, next = end; snprintf(path, sizeof path, - dri_driver_format, - (int) (next - p), p, - xcb_dri2_connect_driver_name_length (connect), - xcb_dri2_connect_driver_name (connect)); - + dri_driver_format, (int) (next - p), p, dri2_dpy->driver_name); dri2_dpy->driver = dlopen(path, RTLD_NOW | RTLD_GLOBAL); } @@ -554,7 +691,7 @@ dri2_initialize(_EGLDriver *drv, _EGLDisplay *disp, _eglLog(_EGL_FATAL, "DRI2: failed to open any driver (search paths %s)", search_paths); - goto cleanup_connect; + goto cleanup_conn; } _eglLog(_EGL_DEBUG, "DRI2: dlopen(%s)", path); @@ -568,32 +705,19 @@ dri2_initialize(_EGLDriver *drv, _EGLDisplay *disp, if (!dri2_bind_extensions(dri2_dpy, dri2_driver_extensions, extensions)) goto cleanup_driver; - snprintf(path, sizeof path, "%.*s", - xcb_dri2_connect_device_name_length (connect), - xcb_dri2_connect_device_name (connect)); - dri2_dpy->fd = open (path, O_RDWR); + dri2_dpy->fd = open(dri2_dpy->device_name, O_RDWR); if (dri2_dpy->fd == -1) { _eglLog(_EGL_FATAL, - "DRI2: could not open %s (%s)", path, strerror(errno)); + "DRI2: could not open %s (%s)", dri2_dpy->device_name, + strerror(errno)); goto cleanup_driver; } - if (drmGetMagic(dri2_dpy->fd, &magic)) { - _eglLog(_EGL_FATAL, "DRI2: failed to get drm magic"); - goto cleanup_fd; - } - - authenticate_cookie = xcb_dri2_authenticate_unchecked (dri2_dpy->conn, - s.data->root, magic); - authenticate = xcb_dri2_authenticate_reply (dri2_dpy->conn, - authenticate_cookie, NULL); - if (authenticate == NULL || !authenticate->authenticated) { - _eglLog(_EGL_FATAL, "DRI2: failed to authenticate"); - free(authenticate); - goto cleanup_fd; + if (dri2_dpy->conn) { + if (!dri2_authenticate(dri2_dpy)) + goto cleanup_fd; } - free(authenticate); if (dri2_dpy->dri2_minor >= 1) { dri2_dpy->loader_extension.base.name = __DRI_DRI2_LOADER; dri2_dpy->loader_extension.base.version = 3; @@ -609,12 +733,17 @@ dri2_initialize(_EGLDriver *drv, _EGLDisplay *disp, dri2_dpy->loader_extension.getBuffersWithFormat = NULL; } + dri2_dpy->image_lookup_extension.base.name = __DRI_IMAGE_LOOKUP; + dri2_dpy->image_lookup_extension.base.version = 1; + dri2_dpy->image_lookup_extension.lookupEGLImage = dri2_lookup_egl_image; + dri2_dpy->extensions[0] = &dri2_dpy->loader_extension.base; - dri2_dpy->extensions[1] = NULL; + dri2_dpy->extensions[1] = &dri2_dpy->image_lookup_extension.base; + dri2_dpy->extensions[2] = NULL; dri2_dpy->dri_screen = dri2_dpy->dri2->createNewScreen(0, dri2_dpy->fd, dri2_dpy->extensions, - &driver_configs, dri2_dpy); + &dri2_dpy->driver_configs, dri2_dpy); if (dri2_dpy->dri_screen == NULL) { _eglLog(_EGL_FATAL, "DRI2: failed to create dri screen"); @@ -625,38 +754,21 @@ dri2_initialize(_EGLDriver *drv, _EGLDisplay *disp, if (!dri2_bind_extensions(dri2_dpy, dri2_core_extensions, extensions)) goto cleanup_dri_screen; - s = xcb_setup_roots_iterator(xcb_get_setup(dri2_dpy->conn)); - d = xcb_screen_allowed_depths_iterator(s.data); - id = 1; - while (d.rem > 0) { - EGLBoolean class_added[6] = { 0, }; - - visuals = xcb_depth_visuals(d.data); - for (i = 0; i < xcb_depth_visuals_length(d.data); i++) { - if (class_added[visuals[i]._class]) - continue; - - class_added[visuals[i]._class] = EGL_TRUE; - for (j = 0; driver_configs[j]; j++) - dri2_add_config(disp, driver_configs[j], - id++, d.data->depth, &visuals[i]); - - } - - xcb_depth_next(&d); - } - - if (!disp->NumConfigs) { - _eglLog(_EGL_WARNING, "DRI2: failed to create any config"); - goto cleanup_configs; + if (dri2_dpy->conn) { + if (!dri2_add_configs_for_visuals(dri2_dpy, disp)) + goto cleanup_configs; } disp->ClientAPIsMask = EGL_OPENGL_BIT; + 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; /* we're supporting EGL 1.4 */ *major = 1; *minor = 4; - free (connect); + return EGL_TRUE; cleanup_configs: @@ -667,8 +779,6 @@ dri2_initialize(_EGLDriver *drv, _EGLDisplay *disp, close(dri2_dpy->fd); cleanup_driver: dlclose(dri2_dpy->driver); - cleanup_connect: - free(connect); cleanup_conn: if (disp->NativeDisplay == NULL) xcb_disconnect(dri2_dpy->conn); @@ -767,6 +877,7 @@ static EGLBoolean dri2_make_current(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *dsurf, _EGLSurface *rsurf, _EGLContext *ctx) { + 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_dsurf = dri2_egl_surface(dsurf); struct dri2_egl_surface *dri2_rsurf = dri2_egl_surface(rsurf); @@ -778,6 +889,10 @@ dri2_make_current(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *dsurf, if (!_eglBindContext(&ctx, &dsurf, &rsurf)) return EGL_FALSE; + /* flush before context switch */ + if (ctx && dri2_drv->glFlush) + dri2_drv->glFlush(); + ddraw = (dri2_dsurf) ? dri2_dsurf->dri_drawable : NULL; rdraw = (dri2_rsurf) ? dri2_rsurf->dri_drawable : NULL; cctx = (dri2_ctx) ? dri2_ctx->dri_context : NULL; @@ -905,10 +1020,18 @@ dri2_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *disp, static EGLBoolean dri2_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw) { + 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; 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); #if 0 @@ -1064,6 +1187,152 @@ dri2_release_tex_image(_EGLDriver *drv, return EGL_TRUE; } +static _EGLImage * +dri2_create_image_khr_pixmap(_EGLDisplay *disp, _EGLContext *ctx, + EGLClientBuffer buffer, const EGLint *attr_list) +{ + struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); + struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx); + struct dri2_egl_image *dri2_img; + unsigned int attachments[1]; + xcb_drawable_t drawable; + xcb_dri2_get_buffers_cookie_t buffers_cookie; + xcb_dri2_get_buffers_reply_t *buffers_reply; + xcb_dri2_dri2_buffer_t *buffers; + xcb_get_geometry_cookie_t geometry_cookie; + xcb_get_geometry_reply_t *geometry_reply; + xcb_generic_error_t *error; + int stride, format; + + drawable = (xcb_drawable_t) buffer; + xcb_dri2_create_drawable (dri2_dpy->conn, drawable); + attachments[0] = XCB_DRI2_ATTACHMENT_BUFFER_FRONT_LEFT; + buffers_cookie = + xcb_dri2_get_buffers_unchecked (dri2_dpy->conn, + drawable, 1, 1, attachments); + geometry_cookie = xcb_get_geometry (dri2_dpy->conn, drawable); + buffers_reply = xcb_dri2_get_buffers_reply (dri2_dpy->conn, + buffers_cookie, NULL); + buffers = xcb_dri2_get_buffers_buffers (buffers_reply); + if (buffers == NULL) { + return NULL; + } + + geometry_reply = xcb_get_geometry_reply (dri2_dpy->conn, + geometry_cookie, &error); + if (geometry_reply == NULL || error != NULL) { + _eglError(EGL_BAD_ALLOC, "xcb_get_geometry"); + free(error); + free(buffers_reply); + } + + switch (geometry_reply->depth) { + case 16: + format = __DRI_IMAGE_FORMAT_RGB565; + break; + case 24: + format = __DRI_IMAGE_FORMAT_XRGB8888; + break; + case 32: + format = __DRI_IMAGE_FORMAT_ARGB8888; + break; + default: + _eglError(EGL_BAD_PARAMETER, + "dri2_create_image_khr: unsupported pixmap depth"); + free(buffers_reply); + free(geometry_reply); + return NULL; + } + + dri2_img = malloc(sizeof *dri2_img); + if (!dri2_img) { + free(buffers_reply); + free(geometry_reply); + _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr"); + return EGL_NO_IMAGE_KHR; + } + + if (!_eglInitImage(&dri2_img->base, disp, attr_list)) { + free(buffers_reply); + free(geometry_reply); + return EGL_NO_IMAGE_KHR; + } + + stride = buffers[0].pitch / buffers[0].cpp; + dri2_img->dri_image = + dri2_dpy->image->createImageFromName(dri2_ctx->dri_context, + buffers_reply->width, + buffers_reply->height, + format, + buffers[0].name, + stride, + dri2_img); + + free(buffers_reply); + free(geometry_reply); + + return &dri2_img->base; +} + +static _EGLImage * +dri2_create_image_khr_renderbuffer(_EGLDisplay *disp, _EGLContext *ctx, + EGLClientBuffer buffer, + const EGLint *attr_list) +{ + struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); + struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx); + struct dri2_egl_image *dri2_img; + GLuint renderbuffer = (GLuint) buffer; + + if (renderbuffer == 0) { + _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr"); + return EGL_NO_IMAGE_KHR; + } + + dri2_img = malloc(sizeof *dri2_img); + if (!dri2_img) { + _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr"); + return EGL_NO_IMAGE_KHR; + } + + if (!_eglInitImage(&dri2_img->base, disp, attr_list)) + return EGL_NO_IMAGE_KHR; + + dri2_img->dri_image = + dri2_dpy->image->createImageFromRenderbuffer(dri2_ctx->dri_context, + renderbuffer, + dri2_img); + + return &dri2_img->base; +} + +static _EGLImage * +dri2_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp, + _EGLContext *ctx, EGLenum target, + EGLClientBuffer buffer, const EGLint *attr_list) +{ + switch (target) { + case EGL_NATIVE_PIXMAP_KHR: + return dri2_create_image_khr_pixmap(disp, ctx, buffer, attr_list); + case EGL_GL_RENDERBUFFER_KHR: + return dri2_create_image_khr_renderbuffer(disp, ctx, buffer, attr_list); + default: + _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr"); + return EGL_NO_IMAGE_KHR; + } +} + +static EGLBoolean +dri2_destroy_image_khr(_EGLDriver *drv, _EGLDisplay *disp, _EGLImage *image) +{ + struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); + struct dri2_egl_image *dri2_img = dri2_egl_image(image); + + dri2_dpy->image->destroyImage(dri2_img->dri_image); + free(dri2_img); + + return EGL_TRUE; +} /** * This is the main entrypoint into the driver, called by libEGL. @@ -1094,9 +1363,14 @@ _eglMain(const char *args) dri2_drv->base.API.CopyBuffers = dri2_copy_buffers; dri2_drv->base.API.BindTexImage = dri2_bind_tex_image; dri2_drv->base.API.ReleaseTexImage = dri2_release_tex_image; + dri2_drv->base.API.CreateImageKHR = dri2_create_image_khr; + dri2_drv->base.API.DestroyImageKHR = dri2_destroy_image_khr; dri2_drv->base.Name = "DRI2"; dri2_drv->base.Unload = dri2_unload; + dri2_drv->glFlush = + (void (*)(void)) dri2_get_proc_address(&dri2_drv->base, "glFlush"); + return &dri2_drv->base; }