X-Git-Url: https://git.libre-soc.org/?p=mesa.git;a=blobdiff_plain;f=src%2Fegl%2Fdrivers%2Fdri2%2Fegl_dri2.c;h=f42ba6687f59c24150326fd623d3f87793e6c47c;hp=9d8a4d9cf7178ce866a7b520a0d756497f40a986;hb=8b0b6f907d7ba304cea02bdb81fbb914d6077cb9;hpb=ef923088d2c72863eff8f184e1576e20e85b9d05 diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c index 9d8a4d9cf71..f42ba6687f5 100644 --- a/src/egl/drivers/dri2/egl_dri2.c +++ b/src/egl/drivers/dri2/egl_dri2.c @@ -62,9 +62,12 @@ #include "egl_dri2.h" #include "GL/mesa_glinterop.h" #include "loader/loader.h" +#include "util/os_file.h" #include "util/u_atomic.h" #include "util/u_vector.h" #include "mapi/glapi/glapi.h" +#include "util/bitscan.h" +#include "util/u_math.h" /* Additional definitions not yet in the drm_fourcc.h. */ @@ -82,6 +85,56 @@ #define NUM_ATTRIBS 12 +static const struct dri2_pbuffer_visual { + const char *format_name; + unsigned int dri_image_format; + int rgba_shifts[4]; + unsigned int rgba_sizes[4]; +} dri2_pbuffer_visuals[] = { + { + "ABGR16F", + __DRI_IMAGE_FORMAT_ABGR16161616F, + { 0, 16, 32, 48 }, + { 16, 16, 16, 16 } + }, + { + "XBGR16F", + __DRI_IMAGE_FORMAT_XBGR16161616F, + { 0, 16, 32, -1 }, + { 16, 16, 16, 0 } + }, + { + "A2RGB10", + __DRI_IMAGE_FORMAT_ARGB2101010, + { 20, 10, 0, 30 }, + { 10, 10, 10, 2 } + }, + { + "X2RGB10", + __DRI_IMAGE_FORMAT_XRGB2101010, + { 20, 10, 0, -1 }, + { 10, 10, 10, 0 } + }, + { + "ARGB8888", + __DRI_IMAGE_FORMAT_ARGB8888, + { 16, 8, 0, 24 }, + { 8, 8, 8, 8 } + }, + { + "RGB888", + __DRI_IMAGE_FORMAT_XRGB8888, + { 16, 8, 0, -1 }, + { 8, 8, 8, 0 } + }, + { + "RGB565", + __DRI_IMAGE_FORMAT_RGB565, + { 11, 5, 0, -1 }, + { 5, 6, 5, 0 } + }, +}; + static void dri_set_background_context(void *loaderPrivate) { @@ -115,7 +168,7 @@ static GLboolean dri_is_thread_safe(void *loaderPrivate) { struct dri2_egl_surface *dri2_surf = loaderPrivate; - _EGLDisplay *display = dri2_surf->base.Resource.Display; + UNUSED _EGLDisplay *display = dri2_surf->base.Resource.Display; #ifdef HAVE_X11_PLATFORM Display *xdpy = (Display*)display->PlatformDisplay; @@ -149,14 +202,114 @@ const __DRIuseInvalidateExtension use_invalidate = { .base = { __DRI_USE_INVALIDATE, 1 } }; +static void +dri2_get_pbuffer_drawable_info(__DRIdrawable * draw, + int *x, int *y, int *w, int *h, + void *loaderPrivate) +{ + struct dri2_egl_surface *dri2_surf = loaderPrivate; + + *x = *y = 0; + *w = dri2_surf->base.Width; + *h = dri2_surf->base.Height; +} + +static int +dri2_get_bytes_per_pixel(struct dri2_egl_surface *dri2_surf) +{ + const int depth = dri2_surf->base.Config->BufferSize; + return depth ? util_next_power_of_two(depth / 8) : 0; +} + +static void +dri2_put_image(__DRIdrawable * draw, int op, + int x, int y, int w, int h, + char *data, void *loaderPrivate) +{ + struct dri2_egl_surface *dri2_surf = loaderPrivate; + const int bpp = dri2_get_bytes_per_pixel(dri2_surf); + const int width = dri2_surf->base.Width; + const int height = dri2_surf->base.Height; + const int dst_stride = width*bpp; + const int src_stride = w*bpp; + const int x_offset = x*bpp; + int copy_width = src_stride; + + if (!dri2_surf->swrast_device_buffer) + dri2_surf->swrast_device_buffer = malloc(height*dst_stride); + + if (dri2_surf->swrast_device_buffer) { + const char *src = data; + char *dst = dri2_surf->swrast_device_buffer; + + dst += x_offset; + dst += y*dst_stride; + + /* Drivers are allowed to submit OOB PutImage requests, so clip here. */ + if (copy_width > dst_stride - x_offset) + copy_width = dst_stride - x_offset; + if (h > height - y) + h = height - y; + + for (; 0 < h; --h) { + memcpy(dst, src, copy_width); + dst += dst_stride; + src += src_stride; + } + } +} + +static void +dri2_get_image(__DRIdrawable * read, + int x, int y, int w, int h, + char *data, void *loaderPrivate) +{ + struct dri2_egl_surface *dri2_surf = loaderPrivate; + const int bpp = dri2_get_bytes_per_pixel(dri2_surf); + const int width = dri2_surf->base.Width; + const int height = dri2_surf->base.Height; + const int src_stride = width*bpp; + const int dst_stride = w*bpp; + const int x_offset = x*bpp; + int copy_width = dst_stride; + const char *src = dri2_surf->swrast_device_buffer; + char *dst = data; + + if (!src) { + memset(data, 0, copy_width * h); + return; + } + + src += x_offset; + src += y*src_stride; + + /* Drivers are allowed to submit OOB GetImage requests, so clip here. */ + if (copy_width > src_stride - x_offset) + copy_width = src_stride - x_offset; + if (h > height - y) + h = height - y; + + for (; 0 < h; --h) { + memcpy(dst, src, copy_width); + src += src_stride; + dst += dst_stride; + } + +} + +/* HACK: technically we should have swrast_null, instead of these. + */ +const __DRIswrastLoaderExtension swrast_pbuffer_loader_extension = { + .base = { __DRI_SWRAST_LOADER, 1 }, + .getDrawableInfo = dri2_get_pbuffer_drawable_info, + .putImage = dri2_put_image, + .getImage = dri2_get_image, +}; + static const EGLint dri2_to_egl_attribute_map[__DRI_ATTRIB_MAX] = { [__DRI_ATTRIB_BUFFER_SIZE ] = EGL_BUFFER_SIZE, [__DRI_ATTRIB_LEVEL] = EGL_LEVEL, - [__DRI_ATTRIB_RED_SIZE] = EGL_RED_SIZE, - [__DRI_ATTRIB_GREEN_SIZE] = EGL_GREEN_SIZE, - [__DRI_ATTRIB_BLUE_SIZE] = EGL_BLUE_SIZE, [__DRI_ATTRIB_LUMINANCE_SIZE] = EGL_LUMINANCE_SIZE, - [__DRI_ATTRIB_ALPHA_SIZE] = EGL_ALPHA_SIZE, [__DRI_ATTRIB_DEPTH_SIZE] = EGL_DEPTH_SIZE, [__DRI_ATTRIB_STENCIL_SIZE] = EGL_STENCIL_SIZE, [__DRI_ATTRIB_SAMPLE_BUFFERS] = EGL_SAMPLE_BUFFERS, @@ -191,10 +344,77 @@ dri2_match_config(const _EGLConfig *conf, const _EGLConfig *criteria) return EGL_TRUE; } +void +dri2_get_shifts_and_sizes(const __DRIcoreExtension *core, + const __DRIconfig *config, int *shifts, + unsigned int *sizes) +{ + unsigned int mask; + + if (core->getConfigAttrib(config, __DRI_ATTRIB_RED_SHIFT, (unsigned int *)&shifts[0])) { + core->getConfigAttrib(config, __DRI_ATTRIB_GREEN_SHIFT, (unsigned int *)&shifts[1]); + core->getConfigAttrib(config, __DRI_ATTRIB_BLUE_SHIFT, (unsigned int *)&shifts[2]); + core->getConfigAttrib(config, __DRI_ATTRIB_ALPHA_SHIFT, (unsigned int *)&shifts[3]); + } else { + /* Driver isn't exposing shifts, so convert masks to shifts */ + core->getConfigAttrib(config, __DRI_ATTRIB_RED_MASK, &mask); + shifts[0] = ffs(mask) - 1; + core->getConfigAttrib(config, __DRI_ATTRIB_GREEN_MASK, &mask); + shifts[1] = ffs(mask) - 1; + core->getConfigAttrib(config, __DRI_ATTRIB_BLUE_MASK, &mask); + shifts[2] = ffs(mask) - 1; + core->getConfigAttrib(config, __DRI_ATTRIB_ALPHA_MASK, &mask); + shifts[3] = ffs(mask) - 1; + } + + core->getConfigAttrib(config, __DRI_ATTRIB_RED_SIZE, &sizes[0]); + core->getConfigAttrib(config, __DRI_ATTRIB_GREEN_SIZE, &sizes[1]); + core->getConfigAttrib(config, __DRI_ATTRIB_BLUE_SIZE, &sizes[2]); + core->getConfigAttrib(config, __DRI_ATTRIB_ALPHA_SIZE, &sizes[3]); +} + +void +dri2_get_render_type_float(const __DRIcoreExtension *core, + const __DRIconfig *config, + bool *is_float) +{ + unsigned int render_type; + + core->getConfigAttrib(config, __DRI_ATTRIB_RENDER_TYPE, &render_type); + *is_float = (render_type & __DRI_ATTRIB_FLOAT_BIT) ? true : false; +} + +unsigned int +dri2_image_format_for_pbuffer_config(struct dri2_egl_display *dri2_dpy, + const __DRIconfig *config) +{ + int shifts[4]; + unsigned int sizes[4]; + + dri2_get_shifts_and_sizes(dri2_dpy->core, config, shifts, sizes); + + for (unsigned i = 0; i < ARRAY_SIZE(dri2_pbuffer_visuals); ++i) { + const struct dri2_pbuffer_visual *visual = &dri2_pbuffer_visuals[i]; + + if (shifts[0] == visual->rgba_shifts[0] && + shifts[1] == visual->rgba_shifts[1] && + shifts[2] == visual->rgba_shifts[2] && + shifts[3] == visual->rgba_shifts[3] && + sizes[0] == visual->rgba_sizes[0] && + sizes[1] == visual->rgba_sizes[1] && + sizes[2] == visual->rgba_sizes[2] && + sizes[3] == visual->rgba_sizes[3]) { + return visual->dri_image_format; + } + } + + return __DRI_IMAGE_FORMAT_NONE; +} + struct dri2_egl_config * dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id, EGLint surface_type, const EGLint *attr_list, - const unsigned int *rgba_masks) + const int *rgba_shifts, const unsigned int *rgba_sizes) { struct dri2_egl_config *conf; struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); @@ -202,7 +422,8 @@ dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id, unsigned int attrib, value, double_buffer; bool srgb = false; EGLint key, bind_to_texture_rgb, bind_to_texture_rgba; - unsigned int dri_masks[4] = { 0, 0, 0, 0 }; + int dri_shifts[4] = { -1, -1, -1, -1 }; + unsigned int dri_sizes[4] = { 0, 0, 0, 0 }; _EGLConfig *matching_config; EGLint num_configs = 0; EGLint config_id; @@ -219,13 +440,15 @@ dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id, switch (attrib) { case __DRI_ATTRIB_RENDER_TYPE: + if (value & __DRI_ATTRIB_FLOAT_BIT) + base.ComponentType = EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT; if (value & __DRI_ATTRIB_RGBA_BIT) value = EGL_RGB_BUFFER; else if (value & __DRI_ATTRIB_LUMINANCE_BIT) value = EGL_LUMINANCE_BUFFER; else return NULL; - _eglSetConfigKey(&base, EGL_COLOR_BUFFER_TYPE, value); + base.ColorBufferType = value; break; case __DRI_ATTRIB_CONFIG_CAVEAT: @@ -235,7 +458,7 @@ dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id, value = EGL_SLOW_CONFIG; else value = EGL_NONE; - _eglSetConfigKey(&base, EGL_CONFIG_CAVEAT, value); + base.ConfigCaveat = value; break; case __DRI_ATTRIB_BIND_TO_TEXTURE_RGB: @@ -250,20 +473,56 @@ dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id, double_buffer = value; break; + case __DRI_ATTRIB_RED_SIZE: + dri_sizes[0] = value; + base.RedSize = value; + break; + case __DRI_ATTRIB_RED_MASK: - dri_masks[0] = value; + dri_shifts[0] = ffs(value) - 1; + break; + + case __DRI_ATTRIB_RED_SHIFT: + dri_shifts[0] = value; + break; + + case __DRI_ATTRIB_GREEN_SIZE: + dri_sizes[1] = value; + base.GreenSize = value; break; case __DRI_ATTRIB_GREEN_MASK: - dri_masks[1] = value; + dri_shifts[1] = ffs(value) - 1; + break; + + case __DRI_ATTRIB_GREEN_SHIFT: + dri_shifts[1] = value; + break; + + case __DRI_ATTRIB_BLUE_SIZE: + dri_sizes[2] = value; + base.BlueSize = value; break; case __DRI_ATTRIB_BLUE_MASK: - dri_masks[2] = value; + dri_shifts[2] = ffs(value) - 1; + break; + + case __DRI_ATTRIB_BLUE_SHIFT: + dri_shifts[2] = value; + break; + + case __DRI_ATTRIB_ALPHA_SIZE: + dri_sizes[3] = value; + base.AlphaSize = value; break; case __DRI_ATTRIB_ALPHA_MASK: - dri_masks[3] = value; + dri_shifts[3] = ffs(value) - 1; + break; + + case __DRI_ATTRIB_ALPHA_SHIFT: + dri_shifts[3] = value; break; case __DRI_ATTRIB_ACCUM_RED_SIZE: @@ -282,12 +541,10 @@ dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id, break; case __DRI_ATTRIB_MAX_PBUFFER_WIDTH: - _eglSetConfigKey(&base, EGL_MAX_PBUFFER_WIDTH, - _EGL_MAX_PBUFFER_WIDTH); + base.MaxPbufferWidth = _EGL_MAX_PBUFFER_WIDTH; break; case __DRI_ATTRIB_MAX_PBUFFER_HEIGHT: - _eglSetConfigKey(&base, EGL_MAX_PBUFFER_HEIGHT, - _EGL_MAX_PBUFFER_HEIGHT); + base.MaxPbufferHeight = _EGL_MAX_PBUFFER_HEIGHT; break; case __DRI_ATTRIB_MUTABLE_RENDER_BUFFER: if (disp->Extensions.KHR_mutable_render_buffer) @@ -305,7 +562,10 @@ dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id, for (int i = 0; attr_list[i] != EGL_NONE; i += 2) _eglSetConfigKey(&base, attr_list[i], attr_list[i+1]); - if (rgba_masks && memcmp(rgba_masks, dri_masks, sizeof(dri_masks))) + if (rgba_shifts && memcmp(rgba_shifts, dri_shifts, sizeof(dri_shifts))) + return NULL; + + if (rgba_sizes && memcmp(rgba_sizes, dri_sizes, sizeof(dri_sizes))) return NULL; base.NativeRenderable = EGL_TRUE; @@ -318,6 +578,22 @@ dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id, base.BindToTextureRGBA = bind_to_texture_rgba; } + if (double_buffer) { + surface_type &= ~EGL_PIXMAP_BIT; + } + + /* No support for pbuffer + MSAA for now. + * + * XXX TODO: pbuffer + MSAA does not work and causes crashes. + * See QT bugreport: https://bugreports.qt.io/browse/QTBUG-47509 + */ + if (base.Samples) { + surface_type &= ~EGL_PBUFFER_BIT; + } + + if (!surface_type) + return NULL; + base.RenderableType = disp->ClientAPIs; base.Conformant = disp->ClientAPIs; @@ -362,22 +638,42 @@ dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id, return NULL; } - if (double_buffer) { - surface_type &= ~EGL_PIXMAP_BIT; - } + conf->base.SurfaceType |= surface_type; - /* No support for pbuffer + MSAA for now. - * - * XXX TODO: pbuffer + MSAA does not work and causes crashes. - * See QT bugreport: https://bugreports.qt.io/browse/QTBUG-47509 - */ - if (base.Samples) { - surface_type &= ~EGL_PBUFFER_BIT; + return conf; +} + +EGLBoolean +dri2_add_pbuffer_configs_for_visuals(_EGLDriver *drv, _EGLDisplay *disp) +{ + struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); + unsigned int format_count[ARRAY_SIZE(dri2_pbuffer_visuals)] = { 0 }; + unsigned int config_count = 0; + + for (unsigned i = 0; dri2_dpy->driver_configs[i] != NULL; i++) { + for (unsigned j = 0; j < ARRAY_SIZE(dri2_pbuffer_visuals); j++) { + struct dri2_egl_config *dri2_conf; + + dri2_conf = dri2_add_config(disp, dri2_dpy->driver_configs[i], + config_count + 1, EGL_PBUFFER_BIT, NULL, + dri2_pbuffer_visuals[j].rgba_shifts, dri2_pbuffer_visuals[j].rgba_sizes); + + if (dri2_conf) { + if (dri2_conf->base.ConfigID == config_count + 1) + config_count++; + format_count[j]++; + } + } } - conf->base.SurfaceType |= surface_type; + for (unsigned i = 0; i < ARRAY_SIZE(format_count); i++) { + if (!format_count[i]) { + _eglLog(_EGL_DEBUG, "No DRI config supports native format %s", + dri2_pbuffer_visuals[i].format_name); + } + } - return conf; + return (config_count != 0); } __DRIimage * @@ -452,6 +748,7 @@ static const struct dri2_extension_match optional_core_extensions[] = { { __DRI2_NO_ERROR, 1, offsetof(struct dri2_egl_display, no_error) }, { __DRI2_CONFIG_QUERY, 1, offsetof(struct dri2_egl_display, config) }, { __DRI2_FENCE, 1, offsetof(struct dri2_egl_display, fence) }, + { __DRI2_BUFFER_DAMAGE, 1, offsetof(struct dri2_egl_display, buffer_damage) }, { __DRI2_RENDERER_QUERY, 1, offsetof(struct dri2_egl_display, rendererQuery) }, { __DRI2_INTEROP, 1, offsetof(struct dri2_egl_display, interop) }, { __DRI_IMAGE, 1, offsetof(struct dri2_egl_display, image) }, @@ -528,6 +825,7 @@ dri2_load_driver_common(_EGLDisplay *disp, if (!dri2_bind_extensions(dri2_dpy, driver_extensions, extensions, false)) { dlclose(dri2_dpy->driver); + dri2_dpy->driver = NULL; return EGL_FALSE; } dri2_dpy->driver_extensions = extensions; @@ -709,11 +1007,6 @@ dri2_setup_screen(_EGLDisplay *disp) if (dri2_dpy->image->base.version >= 8 && dri2_dpy->image->createImageFromDmaBufs) { disp->Extensions.EXT_image_dma_buf_import = EGL_TRUE; - } - if (dri2_dpy->image->base.version >= 15 && - dri2_dpy->image->createImageFromDmaBufs2 && - dri2_dpy->image->queryDmaBufFormats && - dri2_dpy->image->queryDmaBufModifiers) { disp->Extensions.EXT_image_dma_buf_import_modifiers = EGL_TRUE; } #endif @@ -721,6 +1014,9 @@ dri2_setup_screen(_EGLDisplay *disp) if (dri2_dpy->flush_control) disp->Extensions.KHR_context_flush_control = EGL_TRUE; + + if (dri2_dpy->buffer_damage && dri2_dpy->buffer_damage->set_damage_region) + disp->Extensions.KHR_partial_update = EGL_TRUE; } void @@ -840,7 +1136,7 @@ dri2_setup_extensions(_EGLDisplay *disp) } /** - * Called via eglInitialize(), GLX_drv->API.Initialize(). + * Called via eglInitialize(), drv->Initialize(). * * This must be guaranteed to be called exactly once, even if eglInitialize is * called many times (without a eglTerminate in between). @@ -874,6 +1170,9 @@ dri2_initialize(_EGLDriver *drv, _EGLDisplay *disp) case _EGL_PLATFORM_SURFACELESS: ret = dri2_initialize_surfaceless(drv, disp); break; + case _EGL_PLATFORM_DEVICE: + ret = dri2_initialize_device(drv, disp); + break; case _EGL_PLATFORM_X11: ret = dri2_initialize_x11(drv, disp); break; @@ -1006,7 +1305,7 @@ dri2_egl_surface_free_local_buffers(struct dri2_egl_surface *dri2_surf) } /** - * Called via eglTerminate(), drv->API.Terminate(). + * Called via eglTerminate(), drv->Terminate(). * * This must be guaranteed to be called exactly once, even if eglTerminate is * called many times (without a eglInitialize in between). @@ -1164,7 +1463,7 @@ dri2_fill_context_attribs(struct dri2_egl_context *dri2_ctx, } /** - * Called via eglCreateContext(), drv->API.CreateContext(). + * Called via eglCreateContext(), drv->CreateContext(). */ static _EGLContext * dri2_create_context(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf, @@ -1242,6 +1541,9 @@ dri2_create_context(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf, && dri2_ctx->base.ClientMinorVersion >= 2)) && dri2_ctx->base.Profile == EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR) api = __DRI_API_OPENGL_CORE; + else if (dri2_ctx->base.ClientMajorVersion == 3 && + dri2_ctx->base.ClientMinorVersion == 1) + api = __DRI_API_OPENGL_CORE; else api = __DRI_API_OPENGL; break; @@ -1336,7 +1638,7 @@ dri2_create_context(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf, } /** - * Called via eglDestroyContext(), drv->API.DestroyContext(). + * Called via eglDestroyContext(), drv->DestroyContext(). */ static EGLBoolean dri2_destroy_context(_EGLDriver *drv, _EGLDisplay *disp, _EGLContext *ctx) @@ -1354,7 +1656,8 @@ dri2_destroy_context(_EGLDriver *drv, _EGLDisplay *disp, _EGLContext *ctx) EGLBoolean dri2_init_surface(_EGLSurface *surf, _EGLDisplay *disp, EGLint type, - _EGLConfig *conf, const EGLint *attrib_list, EGLBoolean enable_out_fence) + _EGLConfig *conf, const EGLint *attrib_list, + EGLBoolean enable_out_fence, void *native_surface) { struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf); struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); @@ -1368,7 +1671,7 @@ dri2_init_surface(_EGLSurface *surf, _EGLDisplay *disp, EGLint type, dri2_surf->enable_out_fence = enable_out_fence; } - return _eglInitSurface(surf, disp, type, conf, attrib_list); + return _eglInitSurface(surf, disp, type, conf, attrib_list, native_surface); } static void @@ -1424,8 +1727,33 @@ dri2_surf_update_fence_fd(_EGLContext *ctx, dri2_surface_set_out_fence_fd(surf, fence_fd); } +EGLBoolean +dri2_create_drawable(struct dri2_egl_display *dri2_dpy, + const __DRIconfig *config, + struct dri2_egl_surface *dri2_surf, + void *loaderPrivate) +{ + __DRIcreateNewDrawableFunc createNewDrawable; + + if (dri2_dpy->image_driver) + createNewDrawable = dri2_dpy->image_driver->createNewDrawable; + else if (dri2_dpy->dri2) + createNewDrawable = dri2_dpy->dri2->createNewDrawable; + else if (dri2_dpy->swrast) + createNewDrawable = dri2_dpy->swrast->createNewDrawable; + else + return _eglError(EGL_BAD_ALLOC, "no createNewDrawable"); + + dri2_surf->dri_drawable = createNewDrawable(dri2_dpy->dri_screen, + config, loaderPrivate); + if (dri2_surf->dri_drawable == NULL) + return _eglError(EGL_BAD_ALLOC, "createNewDrawable"); + + return EGL_TRUE; +} + /** - * Called via eglMakeCurrent(), drv->API.MakeCurrent(). + * Called via eglMakeCurrent(), drv->MakeCurrent(). */ static EGLBoolean dri2_make_current(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *dsurf, @@ -1440,33 +1768,22 @@ dri2_make_current(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *dsurf, _EGLSurface *tmp_dsurf, *tmp_rsurf; __DRIdrawable *ddraw, *rdraw; __DRIcontext *cctx; - EGLBoolean unbind; if (!dri2_dpy) return _eglError(EGL_NOT_INITIALIZED, "eglMakeCurrent"); - /* make new bindings */ - if (!_eglBindContext(ctx, dsurf, rsurf, &old_ctx, &old_dsurf, &old_rsurf)) { - /* _eglBindContext already sets the EGL error (in _eglCheckMakeCurrent) */ + /* make new bindings, set the EGL error otherwise */ + if (!_eglBindContext(ctx, dsurf, rsurf, &old_ctx, &old_dsurf, &old_rsurf)) return EGL_FALSE; - } if (old_ctx) { + __DRIcontext *old_cctx = dri2_egl_context(old_ctx)->dri_context; old_disp = old_ctx->Resource.Display; old_dri2_dpy = dri2_egl_display(old_disp); - } - /* flush before context switch */ - if (old_ctx) + /* flush before context switch */ dri2_gl_flush(); - ddraw = (dsurf) ? dri2_dpy->vtbl->get_dri_drawable(dsurf) : NULL; - rdraw = (rsurf) ? dri2_dpy->vtbl->get_dri_drawable(rsurf) : NULL; - cctx = (dri2_ctx) ? dri2_ctx->dri_context : NULL; - - if (old_ctx) { - __DRIcontext *old_cctx = dri2_egl_context(old_ctx)->dri_context; - if (old_dsurf) dri2_surf_update_fence_fd(old_ctx, disp, old_dsurf); @@ -1479,41 +1796,44 @@ dri2_make_current(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *dsurf, dri2_dpy->core->unbindContext(old_cctx); } - unbind = (cctx == NULL && ddraw == NULL && rdraw == NULL); + ddraw = (dsurf) ? dri2_dpy->vtbl->get_dri_drawable(dsurf) : NULL; + rdraw = (rsurf) ? dri2_dpy->vtbl->get_dri_drawable(rsurf) : NULL; + cctx = (dri2_ctx) ? dri2_ctx->dri_context : NULL; - if (!unbind && !dri2_dpy->core->bindContext(cctx, ddraw, rdraw)) { - /* undo the previous _eglBindContext */ - _eglBindContext(old_ctx, old_dsurf, old_rsurf, &ctx, &tmp_dsurf, &tmp_rsurf); - assert(&dri2_ctx->base == ctx && - tmp_dsurf == dsurf && - tmp_rsurf == rsurf); + if (cctx || ddraw || rdraw) { + if (!dri2_dpy->core->bindContext(cctx, ddraw, rdraw)) { + /* undo the previous _eglBindContext */ + _eglBindContext(old_ctx, old_dsurf, old_rsurf, &ctx, &tmp_dsurf, &tmp_rsurf); + assert(&dri2_ctx->base == ctx && + tmp_dsurf == dsurf && + tmp_rsurf == rsurf); + + if (old_dsurf && _eglSurfaceInSharedBufferMode(old_dsurf) && + old_dri2_dpy->vtbl->set_shared_buffer_mode) { + old_dri2_dpy->vtbl->set_shared_buffer_mode(old_disp, old_dsurf, true); + } - if (old_dsurf && _eglSurfaceInSharedBufferMode(old_dsurf) && - old_dri2_dpy->vtbl->set_shared_buffer_mode) { - old_dri2_dpy->vtbl->set_shared_buffer_mode(old_disp, old_dsurf, true); - } + _eglPutSurface(dsurf); + _eglPutSurface(rsurf); + _eglPutContext(ctx); - _eglPutSurface(dsurf); - _eglPutSurface(rsurf); - _eglPutContext(ctx); + _eglPutSurface(old_dsurf); + _eglPutSurface(old_rsurf); + _eglPutContext(old_ctx); - _eglPutSurface(old_dsurf); - _eglPutSurface(old_rsurf); - _eglPutContext(old_ctx); + /* dri2_dpy->core->bindContext failed. We cannot tell for sure why, but + * setting the error to EGL_BAD_MATCH is surely better than leaving it + * as EGL_SUCCESS. + */ + return _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); + } - /* dri2_dpy->core->bindContext failed. We cannot tell for sure why, but - * setting the error to EGL_BAD_MATCH is surely better than leaving it - * as EGL_SUCCESS. - */ - return _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); + dri2_dpy->ref_count++; } dri2_destroy_surface(drv, disp, old_dsurf); dri2_destroy_surface(drv, disp, old_rsurf); - if (!unbind) - dri2_dpy->ref_count++; - if (old_ctx) { dri2_destroy_context(drv, disp, old_ctx); dri2_display_release(old_disp); @@ -1543,7 +1863,7 @@ dri2_surface_get_dri_drawable(_EGLSurface *surf) } /* - * Called from eglGetProcAddress() via drv->API.GetProcAddress(). + * Called from eglGetProcAddress() via drv->GetProcAddress(). */ static _EGLProc dri2_get_proc_address(_EGLDriver *drv, const char *procname) @@ -1567,6 +1887,8 @@ dri2_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *disp, const EGLint *attrib_list) { struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); + if (!dri2_dpy->vtbl->create_pixmap_surface) + return NULL; return dri2_dpy->vtbl->create_pixmap_surface(drv, disp, conf, native_pixmap, attrib_list); } @@ -1576,6 +1898,8 @@ dri2_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf, const EGLint *attrib_list) { struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); + if (!dri2_dpy->vtbl->create_pbuffer_surface) + return NULL; return dri2_dpy->vtbl->create_pbuffer_surface(drv, disp, conf, attrib_list); } @@ -1629,11 +1953,22 @@ static EGLBoolean dri2_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf) { struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); + __DRIdrawable *dri_drawable = dri2_dpy->vtbl->get_dri_drawable(surf); _EGLContext *ctx = _eglGetCurrentContext(); + EGLBoolean ret; if (ctx && surf) dri2_surf_update_fence_fd(ctx, disp, surf); - return dri2_dpy->vtbl->swap_buffers(drv, disp, surf); + ret = dri2_dpy->vtbl->swap_buffers(drv, disp, surf); + + /* SwapBuffers marks the end of the frame; reset the damage region for + * use again next time. + */ + if (ret && dri2_dpy->buffer_damage && + dri2_dpy->buffer_damage->set_damage_region) + dri2_dpy->buffer_damage->set_damage_region(dri_drawable, 0, NULL); + + return ret; } static EGLBoolean @@ -1642,12 +1977,26 @@ dri2_swap_buffers_with_damage(_EGLDriver *drv, _EGLDisplay *disp, const EGLint *rects, EGLint n_rects) { struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); + __DRIdrawable *dri_drawable = dri2_dpy->vtbl->get_dri_drawable(surf); _EGLContext *ctx = _eglGetCurrentContext(); + EGLBoolean ret; if (ctx && surf) dri2_surf_update_fence_fd(ctx, disp, surf); - return dri2_dpy->vtbl->swap_buffers_with_damage(drv, disp, surf, - rects, n_rects); + if (dri2_dpy->vtbl->swap_buffers_with_damage) + ret = dri2_dpy->vtbl->swap_buffers_with_damage(drv, disp, surf, + rects, n_rects); + else + ret = dri2_dpy->vtbl->swap_buffers(drv, disp, surf); + + /* SwapBuffers marks the end of the frame; reset the damage region for + * use again next time. + */ + if (ret && dri2_dpy->buffer_damage && + dri2_dpy->buffer_damage->set_damage_region) + dri2_dpy->buffer_damage->set_damage_region(dri_drawable, 0, NULL); + + return ret; } static EGLBoolean @@ -1655,7 +2004,21 @@ dri2_swap_buffers_region(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf, EGLint numRects, const EGLint *rects) { struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); - return dri2_dpy->vtbl->swap_buffers_region(drv, disp, surf, numRects, rects); + __DRIdrawable *dri_drawable = dri2_dpy->vtbl->get_dri_drawable(surf); + EGLBoolean ret; + + if (!dri2_dpy->vtbl->swap_buffers_region) + return EGL_FALSE; + ret = dri2_dpy->vtbl->swap_buffers_region(drv, disp, surf, numRects, rects); + + /* SwapBuffers marks the end of the frame; reset the damage region for + * use again next time. + */ + if (ret && dri2_dpy->buffer_damage && + dri2_dpy->buffer_damage->set_damage_region) + dri2_dpy->buffer_damage->set_damage_region(dri_drawable, 0, NULL); + + return ret; } static EGLBoolean @@ -1663,7 +2026,13 @@ dri2_set_damage_region(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf, EGLint *rects, EGLint n_rects) { struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); - return dri2_dpy->vtbl->set_damage_region(drv, disp, surf, rects, n_rects); + __DRIdrawable *drawable = dri2_dpy->vtbl->get_dri_drawable(surf); + + if (!dri2_dpy->buffer_damage || !dri2_dpy->buffer_damage->set_damage_region) + return EGL_FALSE; + + dri2_dpy->buffer_damage->set_damage_region(drawable, n_rects, rects); + return EGL_TRUE; } static EGLBoolean @@ -1671,6 +2040,8 @@ dri2_post_sub_buffer(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf, EGLint x, EGLint y, EGLint width, EGLint height) { struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); + if (!dri2_dpy->vtbl->post_sub_buffer) + return EGL_FALSE; return dri2_dpy->vtbl->post_sub_buffer(drv, disp, surf, x, y, width, height); } @@ -1679,6 +2050,8 @@ dri2_copy_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf, void *native_pixmap_target) { struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); + if (!dri2_dpy->vtbl->copy_buffers) + return _eglError(EGL_BAD_NATIVE_PIXMAP, "no support for native pixmaps"); return dri2_dpy->vtbl->copy_buffers(drv, disp, surf, native_pixmap_target); } @@ -1686,6 +2059,8 @@ static EGLint dri2_query_buffer_age(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf) { struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); + if (!dri2_dpy->vtbl->query_buffer_age) + return 0; return dri2_dpy->vtbl->query_buffer_age(drv, disp, surf); } @@ -1964,6 +2339,8 @@ dri2_get_sync_values_chromium(_EGLDisplay *disp, _EGLSurface *surf, EGLuint64KHR *sbc) { struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); + if (!dri2_dpy->vtbl->get_sync_values) + return EGL_FALSE; return dri2_dpy->vtbl->get_sync_values(disp, surf, ust, msc, sbc); } @@ -2080,6 +2457,8 @@ dri2_create_wayland_buffer_from_image(_EGLDriver *drv, _EGLDisplay *disp, _EGLImage *img) { struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); + if (!dri2_dpy->vtbl->create_wayland_buffer_from_image) + return NULL; return dri2_dpy->vtbl->create_wayland_buffer_from_image(drv, disp, img); } @@ -2244,6 +2623,8 @@ dri2_num_fourcc_format_planes(EGLint format) case DRM_FORMAT_ABGR2101010: case DRM_FORMAT_RGBA1010102: case DRM_FORMAT_BGRA1010102: + case DRM_FORMAT_XBGR16161616F: + case DRM_FORMAT_ABGR16161616F: case DRM_FORMAT_YUYV: case DRM_FORMAT_YVYU: case DRM_FORMAT_UYVY: @@ -2627,21 +3008,39 @@ dri2_export_dma_buf_image_query_mesa(_EGLDriver *drv, _EGLDisplay *disp, { struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); struct dri2_egl_image *dri2_img = dri2_egl_image(img); + int num_planes; (void) drv; if (!dri2_can_export_dma_buf_image(disp, img)) return EGL_FALSE; + dri2_dpy->image->queryImage(dri2_img->dri_image, + __DRI_IMAGE_ATTRIB_NUM_PLANES, &num_planes); if (nplanes) - dri2_dpy->image->queryImage(dri2_img->dri_image, - __DRI_IMAGE_ATTRIB_NUM_PLANES, nplanes); + *nplanes = num_planes; + if (fourcc) dri2_dpy->image->queryImage(dri2_img->dri_image, __DRI_IMAGE_ATTRIB_FOURCC, fourcc); - if (modifiers) - *modifiers = 0; + if (modifiers) { + int mod_hi, mod_lo; + uint64_t modifier = DRM_FORMAT_MOD_INVALID; + bool query; + + query = dri2_dpy->image->queryImage(dri2_img->dri_image, + __DRI_IMAGE_ATTRIB_MODIFIER_UPPER, + &mod_hi); + query &= dri2_dpy->image->queryImage(dri2_img->dri_image, + __DRI_IMAGE_ATTRIB_MODIFIER_LOWER, + &mod_lo); + if (query) + modifier = combine_u32_into_u64 (mod_hi, mod_lo); + + for (int i = 0; i < num_planes; i++) + modifiers[i] = modifier; + } return EGL_TRUE; } @@ -3069,7 +3468,7 @@ dri2_dup_native_fence_fd(_EGLDriver *drv, _EGLDisplay *disp, _EGLSync *sync) return EGL_NO_NATIVE_FENCE_FD_ANDROID; } - return dup(sync->SyncFd); + return os_dupfd_cloexec(sync->SyncFd); } static void @@ -3248,55 +3647,55 @@ dri2_interop_export_object(_EGLDisplay *disp, _EGLContext *ctx, void _eglInitDriver(_EGLDriver *dri2_drv) { - dri2_drv->API.Initialize = dri2_initialize; - dri2_drv->API.Terminate = dri2_terminate; - dri2_drv->API.CreateContext = dri2_create_context; - dri2_drv->API.DestroyContext = dri2_destroy_context; - dri2_drv->API.MakeCurrent = dri2_make_current; - dri2_drv->API.CreateWindowSurface = dri2_create_window_surface; - dri2_drv->API.CreatePixmapSurface = dri2_create_pixmap_surface; - dri2_drv->API.CreatePbufferSurface = dri2_create_pbuffer_surface; - dri2_drv->API.DestroySurface = dri2_destroy_surface; - dri2_drv->API.GetProcAddress = dri2_get_proc_address; - dri2_drv->API.WaitClient = dri2_wait_client; - dri2_drv->API.WaitNative = dri2_wait_native; - dri2_drv->API.BindTexImage = dri2_bind_tex_image; - dri2_drv->API.ReleaseTexImage = dri2_release_tex_image; - dri2_drv->API.SwapInterval = dri2_swap_interval; - dri2_drv->API.SwapBuffers = dri2_swap_buffers; - dri2_drv->API.SwapBuffersWithDamageEXT = dri2_swap_buffers_with_damage; - dri2_drv->API.SwapBuffersRegionNOK = dri2_swap_buffers_region; - dri2_drv->API.SetDamageRegion = dri2_set_damage_region; - dri2_drv->API.PostSubBufferNV = dri2_post_sub_buffer; - dri2_drv->API.CopyBuffers = dri2_copy_buffers, - dri2_drv->API.QueryBufferAge = dri2_query_buffer_age; - dri2_drv->API.CreateImageKHR = dri2_create_image; - dri2_drv->API.DestroyImageKHR = dri2_destroy_image_khr; - dri2_drv->API.CreateWaylandBufferFromImageWL = dri2_create_wayland_buffer_from_image; - dri2_drv->API.QuerySurface = dri2_query_surface; - dri2_drv->API.QueryDriverName = dri2_query_driver_name; - dri2_drv->API.QueryDriverConfig = dri2_query_driver_config; + dri2_drv->Initialize = dri2_initialize; + dri2_drv->Terminate = dri2_terminate; + dri2_drv->CreateContext = dri2_create_context; + dri2_drv->DestroyContext = dri2_destroy_context; + dri2_drv->MakeCurrent = dri2_make_current; + dri2_drv->CreateWindowSurface = dri2_create_window_surface; + dri2_drv->CreatePixmapSurface = dri2_create_pixmap_surface; + dri2_drv->CreatePbufferSurface = dri2_create_pbuffer_surface; + dri2_drv->DestroySurface = dri2_destroy_surface; + dri2_drv->GetProcAddress = dri2_get_proc_address; + dri2_drv->WaitClient = dri2_wait_client; + dri2_drv->WaitNative = dri2_wait_native; + dri2_drv->BindTexImage = dri2_bind_tex_image; + dri2_drv->ReleaseTexImage = dri2_release_tex_image; + dri2_drv->SwapInterval = dri2_swap_interval; + dri2_drv->SwapBuffers = dri2_swap_buffers; + dri2_drv->SwapBuffersWithDamageEXT = dri2_swap_buffers_with_damage; + dri2_drv->SwapBuffersRegionNOK = dri2_swap_buffers_region; + dri2_drv->SetDamageRegion = dri2_set_damage_region; + dri2_drv->PostSubBufferNV = dri2_post_sub_buffer; + dri2_drv->CopyBuffers = dri2_copy_buffers, + dri2_drv->QueryBufferAge = dri2_query_buffer_age; + dri2_drv->CreateImageKHR = dri2_create_image; + dri2_drv->DestroyImageKHR = dri2_destroy_image_khr; + dri2_drv->CreateWaylandBufferFromImageWL = dri2_create_wayland_buffer_from_image; + dri2_drv->QuerySurface = dri2_query_surface; + dri2_drv->QueryDriverName = dri2_query_driver_name; + dri2_drv->QueryDriverConfig = dri2_query_driver_config; #ifdef HAVE_LIBDRM - dri2_drv->API.CreateDRMImageMESA = dri2_create_drm_image_mesa; - dri2_drv->API.ExportDRMImageMESA = dri2_export_drm_image_mesa; - dri2_drv->API.ExportDMABUFImageQueryMESA = dri2_export_dma_buf_image_query_mesa; - dri2_drv->API.ExportDMABUFImageMESA = dri2_export_dma_buf_image_mesa; - dri2_drv->API.QueryDmaBufFormatsEXT = dri2_query_dma_buf_formats; - dri2_drv->API.QueryDmaBufModifiersEXT = dri2_query_dma_buf_modifiers; + dri2_drv->CreateDRMImageMESA = dri2_create_drm_image_mesa; + dri2_drv->ExportDRMImageMESA = dri2_export_drm_image_mesa; + dri2_drv->ExportDMABUFImageQueryMESA = dri2_export_dma_buf_image_query_mesa; + dri2_drv->ExportDMABUFImageMESA = dri2_export_dma_buf_image_mesa; + dri2_drv->QueryDmaBufFormatsEXT = dri2_query_dma_buf_formats; + dri2_drv->QueryDmaBufModifiersEXT = dri2_query_dma_buf_modifiers; #endif #ifdef HAVE_WAYLAND_PLATFORM - dri2_drv->API.BindWaylandDisplayWL = dri2_bind_wayland_display_wl; - dri2_drv->API.UnbindWaylandDisplayWL = dri2_unbind_wayland_display_wl; - dri2_drv->API.QueryWaylandBufferWL = dri2_query_wayland_buffer_wl; + dri2_drv->BindWaylandDisplayWL = dri2_bind_wayland_display_wl; + dri2_drv->UnbindWaylandDisplayWL = dri2_unbind_wayland_display_wl; + dri2_drv->QueryWaylandBufferWL = dri2_query_wayland_buffer_wl; #endif - dri2_drv->API.GetSyncValuesCHROMIUM = dri2_get_sync_values_chromium; - dri2_drv->API.CreateSyncKHR = dri2_create_sync; - dri2_drv->API.ClientWaitSyncKHR = dri2_client_wait_sync; - dri2_drv->API.SignalSyncKHR = dri2_signal_sync; - dri2_drv->API.WaitSyncKHR = dri2_server_wait_sync; - dri2_drv->API.DestroySyncKHR = dri2_destroy_sync; - dri2_drv->API.GLInteropQueryDeviceInfo = dri2_interop_query_device_info; - dri2_drv->API.GLInteropExportObject = dri2_interop_export_object; - dri2_drv->API.DupNativeFenceFDANDROID = dri2_dup_native_fence_fd; - dri2_drv->API.SetBlobCacheFuncsANDROID = dri2_set_blob_cache_funcs; + dri2_drv->GetSyncValuesCHROMIUM = dri2_get_sync_values_chromium; + dri2_drv->CreateSyncKHR = dri2_create_sync; + dri2_drv->ClientWaitSyncKHR = dri2_client_wait_sync; + dri2_drv->SignalSyncKHR = dri2_signal_sync; + dri2_drv->WaitSyncKHR = dri2_server_wait_sync; + dri2_drv->DestroySyncKHR = dri2_destroy_sync; + dri2_drv->GLInteropQueryDeviceInfo = dri2_interop_query_device_info; + dri2_drv->GLInteropExportObject = dri2_interop_export_object; + dri2_drv->DupNativeFenceFDANDROID = dri2_dup_native_fence_fd; + dri2_drv->SetBlobCacheFuncsANDROID = dri2_set_blob_cache_funcs; }