X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fegl%2Fdrivers%2Fdri2%2Fegl_dri2.c;h=ba728a1583ba8331ba9c028e66b8496a17ae9162;hb=58911b86a15676f116c693e84ea6b9ebabb906ed;hp=10309e6eeaf06e32c13555b7aa7aab1071da2588;hpb=93aea63a33c575bbce80acad391e810acc2f3e94;p=mesa.git diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c index 10309e6eeaf..ba728a1583b 100644 --- a/src/egl/drivers/dri2/egl_dri2.c +++ b/src/egl/drivers/dri2/egl_dri2.c @@ -97,15 +97,29 @@ EGLint dri2_to_egl_attribute_map[] = { 0, /* __DRI_ATTRIB_FRAMEBUFFER_SRGB_CAPABLE */ }; +static EGLBoolean +dri2_match_config(const _EGLConfig *conf, const _EGLConfig *criteria) +{ + if (_eglCompareConfigs(conf, criteria, NULL, EGL_FALSE) != 0) + return EGL_FALSE; + + if (!_eglMatchConfig(conf, criteria)) + return EGL_FALSE; + + return EGL_TRUE; +} + struct dri2_egl_config * dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id, - int depth, EGLint surface_type, const EGLint *attr_list) + int depth, EGLint surface_type, const EGLint *attr_list, + const unsigned int *rgba_masks) { struct dri2_egl_config *conf; struct dri2_egl_display *dri2_dpy; _EGLConfig base; unsigned int attrib, value, double_buffer; EGLint key, bind_to_texture_rgb, bind_to_texture_rgba; + unsigned int dri_masks[4] = { 0, 0, 0, 0 }; _EGLConfig *matching_config; EGLint num_configs = 0; EGLint config_id; @@ -153,6 +167,22 @@ dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id, double_buffer = value; break; + case __DRI_ATTRIB_RED_MASK: + dri_masks[0] = value; + break; + + case __DRI_ATTRIB_GREEN_MASK: + dri_masks[1] = value; + break; + + case __DRI_ATTRIB_BLUE_MASK: + dri_masks[2] = value; + break; + + case __DRI_ATTRIB_ALPHA_MASK: + dri_masks[3] = value; + break; + default: key = dri2_to_egl_attribute_map[attrib]; if (key != 0) @@ -168,6 +198,9 @@ dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id, if (depth > 0 && depth != base.BufferSize) return NULL; + if (rgba_masks && memcmp(rgba_masks, dri_masks, sizeof(dri_masks))) + return NULL; + base.NativeRenderable = EGL_TRUE; base.SurfaceType = surface_type; @@ -190,7 +223,7 @@ dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id, base.ConfigID = EGL_DONT_CARE; base.SurfaceType = EGL_DONT_CARE; num_configs = _eglFilterArray(disp->Configs, (void **) &matching_config, 1, - (_EGLArrayForEach) _eglMatchConfig, &base); + (_EGLArrayForEach) dri2_match_config, &base); if (num_configs == 1) { conf = (struct dri2_egl_config *) matching_config; @@ -200,10 +233,8 @@ dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id, else if (!double_buffer && !conf->dri_single_config) conf->dri_single_config = dri_config; else - /* a similar config type is already added - * => attach it as new config - */ - num_configs = 0; + /* a similar config type is already added (unlikely) => discard */ + return NULL; } else if (num_configs == 0) { conf = malloc(sizeof *conf); @@ -234,7 +265,7 @@ dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id, return conf; } -static __DRIimage * +__DRIimage * dri2_lookup_egl_image(__DRIscreen *screen, void *image, void *data) { _EGLDisplay *disp = data; @@ -324,8 +355,8 @@ dri2_bind_extensions(struct dri2_egl_display *dri2_dpy, return ret; } -EGLBoolean -dri2_load_driver(_EGLDisplay *disp) +static const __DRIextension ** +dri2_open_driver(_EGLDisplay *disp) { struct dri2_egl_display *dri2_dpy = disp->DriverData; const __DRIextension **extensions; @@ -364,9 +395,9 @@ dri2_load_driver(_EGLDisplay *disp) if (dri2_dpy->driver == NULL) { _eglLog(_EGL_WARNING, - "DRI2: failed to open any driver (search paths %s)", - search_paths); - return EGL_FALSE; + "DRI2: failed to open %s (search paths %s)", + dri2_dpy->driver_name, search_paths); + return NULL; } _eglLog(_EGL_DEBUG, "DRI2: dlopen(%s)", path); @@ -375,59 +406,54 @@ dri2_load_driver(_EGLDisplay *disp) _eglLog(_EGL_WARNING, "DRI2: driver exports no extensions (%s)", dlerror()); dlclose(dri2_dpy->driver); - return EGL_FALSE; } - if (strcmp(dri2_dpy->driver_name, "swrast") == 0) { - if (!dri2_bind_extensions(dri2_dpy, swrast_driver_extensions, extensions)) { - dlclose(dri2_dpy->driver); - return EGL_FALSE; - } - } else { - if (!dri2_bind_extensions(dri2_dpy, dri2_driver_extensions, extensions)) { - dlclose(dri2_dpy->driver); - return EGL_FALSE; - } - } + return extensions; +} + +EGLBoolean +dri2_load_driver(_EGLDisplay *disp) +{ + struct dri2_egl_display *dri2_dpy = disp->DriverData; + const __DRIextension **extensions; + + extensions = dri2_open_driver(disp); + if (!extensions) + return EGL_FALSE; + + if (!dri2_bind_extensions(dri2_dpy, dri2_driver_extensions, extensions)) { + dlclose(dri2_dpy->driver); + return EGL_FALSE; + } return EGL_TRUE; } EGLBoolean -dri2_create_screen(_EGLDisplay *disp) +dri2_load_driver_swrast(_EGLDisplay *disp) { + struct dri2_egl_display *dri2_dpy = disp->DriverData; const __DRIextension **extensions; - struct dri2_egl_display *dri2_dpy; - unsigned int api_mask; - dri2_dpy = disp->DriverData; + dri2_dpy->driver_name = "swrast"; + extensions = dri2_open_driver(disp); - if (dri2_dpy->dri2) { - dri2_dpy->dri_screen = - dri2_dpy->dri2->createNewScreen(0, dri2_dpy->fd, dri2_dpy->extensions, - &dri2_dpy->driver_configs, disp); - } else { - assert(dri2_dpy->swrast); - dri2_dpy->dri_screen = - dri2_dpy->swrast->createNewScreen(0, dri2_dpy->extensions, - &dri2_dpy->driver_configs, disp); - } + if (!extensions) + return EGL_FALSE; - if (dri2_dpy->dri_screen == NULL) { - _eglLog(_EGL_WARNING, "DRI2: failed to create dri screen"); + if (!dri2_bind_extensions(dri2_dpy, swrast_driver_extensions, extensions)) { + dlclose(dri2_dpy->driver); return EGL_FALSE; } - extensions = dri2_dpy->core->getExtensions(dri2_dpy->dri_screen); - - if (dri2_dpy->dri2) { - if (!dri2_bind_extensions(dri2_dpy, dri2_core_extensions, extensions)) - goto cleanup_dri_screen; - } else { - assert(dri2_dpy->swrast); - if (!dri2_bind_extensions(dri2_dpy, swrast_core_extensions, extensions)) - goto cleanup_dri_screen; - } + return EGL_TRUE; +} + +void +dri2_setup_screen(_EGLDisplay *disp) +{ + struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); + unsigned int api_mask; if (dri2_dpy->dri2) { if (dri2_dpy->dri2->base.version >= 2) @@ -470,6 +496,46 @@ dri2_create_screen(_EGLDisplay *disp) disp->Extensions.KHR_image_base = EGL_TRUE; disp->Extensions.KHR_gl_renderbuffer_image = EGL_TRUE; } +} + +EGLBoolean +dri2_create_screen(_EGLDisplay *disp) +{ + const __DRIextension **extensions; + struct dri2_egl_display *dri2_dpy; + + dri2_dpy = disp->DriverData; + + if (dri2_dpy->dri2) { + dri2_dpy->dri_screen = + dri2_dpy->dri2->createNewScreen(0, dri2_dpy->fd, dri2_dpy->extensions, + &dri2_dpy->driver_configs, disp); + } else { + assert(dri2_dpy->swrast); + dri2_dpy->dri_screen = + dri2_dpy->swrast->createNewScreen(0, dri2_dpy->extensions, + &dri2_dpy->driver_configs, disp); + } + + if (dri2_dpy->dri_screen == NULL) { + _eglLog(_EGL_WARNING, "DRI2: failed to create dri screen"); + return EGL_FALSE; + } + + dri2_dpy->own_dri_screen = 1; + + extensions = dri2_dpy->core->getExtensions(dri2_dpy->dri_screen); + + if (dri2_dpy->dri2) { + if (!dri2_bind_extensions(dri2_dpy, dri2_core_extensions, extensions)) + goto cleanup_dri_screen; + } else { + assert(dri2_dpy->swrast); + if (!dri2_bind_extensions(dri2_dpy, swrast_core_extensions, extensions)) + goto cleanup_dri_screen; + } + + dri2_setup_screen(disp); return EGL_TRUE; @@ -498,10 +564,12 @@ dri2_initialize(_EGLDriver *drv, _EGLDisplay *disp) #endif #ifdef HAVE_LIBUDEV +#ifdef HAVE_DRM_PLATFORM case _EGL_PLATFORM_DRM: if (disp->Options.TestOnly) return EGL_TRUE; return dri2_initialize_drm(drv, disp); +#endif #ifdef HAVE_WAYLAND_PLATFORM case _EGL_PLATFORM_WAYLAND: if (disp->Options.TestOnly) @@ -526,14 +594,37 @@ dri2_terminate(_EGLDriver *drv, _EGLDisplay *disp) _eglReleaseDisplayResources(drv, disp); _eglCleanupDisplay(disp); - dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen); + if (dri2_dpy->own_dri_screen) + dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen); if (dri2_dpy->fd) close(dri2_dpy->fd); - dlclose(dri2_dpy->driver); + if (dri2_dpy->driver) + dlclose(dri2_dpy->driver); + + if (disp->PlatformDisplay == NULL) { + switch (disp->Platform) { #ifdef HAVE_X11_PLATFORM - if (disp->PlatformDisplay == NULL) - xcb_disconnect(dri2_dpy->conn); + case _EGL_PLATFORM_X11: + xcb_disconnect(dri2_dpy->conn); + break; #endif +#ifdef HAVE_WAYLAND_PLATFORM + case _EGL_PLATFORM_WAYLAND: + wl_display_destroy(dri2_dpy->wl_dpy); + break; +#endif +#ifdef HAVE_DRM_PLATFORM + case _EGL_PLATFORM_DRM: + if (dri2_dpy->own_gbm_device) { + gbm_device_destroy(&dri2_dpy->gbm_dri->base.base); + } + break; +#endif + default: + break; + } + } + free(dri2_dpy); disp->DriverData = NULL; @@ -655,6 +746,23 @@ dri2_create_context(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf, return NULL; } +/** + * Called via eglDestroyContext(), drv->API.DestroyContext(). + */ +static EGLBoolean +dri2_destroy_context(_EGLDriver *drv, _EGLDisplay *disp, _EGLContext *ctx) +{ + struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx); + struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); + + if (_eglPutContext(ctx)) { + dri2_dpy->core->destroyContext(dri2_ctx->dri_context); + free(dri2_ctx); + } + + return EGL_TRUE; +} + /** * Called via eglMakeCurrent(), drv->API.MakeCurrent(). */ @@ -695,9 +803,8 @@ dri2_make_current(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *dsurf, drv->API.DestroySurface(drv, disp, old_dsurf); if (old_rsurf) drv->API.DestroySurface(drv, disp, old_rsurf); - /* no destroy? */ if (old_ctx) - _eglPutContext(old_ctx); + drv->API.DestroyContext(drv, disp, old_ctx); return EGL_TRUE; } else { @@ -855,8 +962,10 @@ dri2_create_image_khr_renderbuffer(_EGLDisplay *disp, _EGLContext *ctx, return EGL_NO_IMAGE_KHR; } - if (!_eglInitImage(&dri2_img->base, disp)) + if (!_eglInitImage(&dri2_img->base, disp)) { + free(dri2_img); return EGL_NO_IMAGE_KHR; + } dri2_img->dri_image = dri2_dpy->image->createImageFromRenderbuffer(dri2_ctx->dri_context, @@ -1267,13 +1376,16 @@ _EGL_MAIN(const char *args) memset(dri2_drv, 0, sizeof *dri2_drv); - if (!dri2_load(&dri2_drv->base)) + if (!dri2_load(&dri2_drv->base)) { + free(dri2_drv); return NULL; + } _eglInitDriverFallbacks(&dri2_drv->base); dri2_drv->base.API.Initialize = dri2_initialize; dri2_drv->base.API.Terminate = dri2_terminate; dri2_drv->base.API.CreateContext = dri2_create_context; + dri2_drv->base.API.DestroyContext = dri2_destroy_context; dri2_drv->base.API.MakeCurrent = dri2_make_current; dri2_drv->base.API.GetProcAddress = dri2_get_proc_address; dri2_drv->base.API.WaitClient = dri2_wait_client;