mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-04-23 09:30:36 +02:00
egl_dri2: Use double buffering for window surfaces
This commit is contained in:
parent
71fa227029
commit
87dde5b1cd
5 changed files with 112 additions and 42 deletions
|
|
@ -98,13 +98,16 @@ EGLint dri2_to_egl_attribute_map[] = {
|
|||
|
||||
struct dri2_egl_config *
|
||||
dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id,
|
||||
int depth, EGLint surface_type)
|
||||
int depth, EGLint surface_type, const EGLint *attr_list)
|
||||
{
|
||||
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;
|
||||
_EGLConfig *matching_config;
|
||||
EGLint num_configs = 0;
|
||||
EGLint config_id;
|
||||
int i;
|
||||
|
||||
dri2_dpy = disp->DriverData;
|
||||
|
|
@ -157,15 +160,9 @@ dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id,
|
|||
}
|
||||
}
|
||||
|
||||
/* In EGL, double buffer or not isn't a config attribute. Pixmaps
|
||||
* surfaces are always single buffered, pbuffer surfaces are always
|
||||
* back buffers and windows can be either, selected by passing an
|
||||
* attribute at window surface construction time. To support this
|
||||
* we ignore all double buffer configs and manipulate the buffer we
|
||||
* return in the getBuffer callback to get the behaviour we want. */
|
||||
|
||||
if (double_buffer)
|
||||
return NULL;
|
||||
if (attr_list)
|
||||
for (i = 0; attr_list[i] != EGL_NONE; i += 2)
|
||||
_eglSetConfigKey(&base, attr_list[i], attr_list[i+1]);
|
||||
|
||||
if (depth > 0 && depth != base.BufferSize)
|
||||
return NULL;
|
||||
|
|
@ -188,13 +185,48 @@ dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
conf = malloc(sizeof *conf);
|
||||
if (conf != NULL) {
|
||||
config_id = base.ConfigID;
|
||||
base.ConfigID = EGL_DONT_CARE;
|
||||
base.SurfaceType = EGL_DONT_CARE;
|
||||
num_configs = _eglFilterArray(disp->Configs, (void **) &matching_config, 1,
|
||||
(_EGLArrayForEach) _eglMatchConfig, &base);
|
||||
|
||||
if (num_configs == 1) {
|
||||
conf = (struct dri2_egl_config *) matching_config;
|
||||
|
||||
if (double_buffer && !conf->dri_double_config)
|
||||
conf->dri_double_config = dri_config;
|
||||
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;
|
||||
}
|
||||
|
||||
if (num_configs == 0) {
|
||||
conf = malloc(sizeof *conf);
|
||||
if (conf == NULL)
|
||||
return NULL;
|
||||
|
||||
memcpy(&conf->base, &base, sizeof base);
|
||||
conf->dri_config = dri_config;
|
||||
if (double_buffer) {
|
||||
conf->dri_double_config = dri_config;
|
||||
conf->dri_single_config = NULL;
|
||||
} else {
|
||||
conf->dri_single_config = dri_config;
|
||||
conf->dri_double_config = NULL;
|
||||
}
|
||||
conf->base.SurfaceType = 0;
|
||||
conf->base.ConfigID = config_id;
|
||||
|
||||
_eglLinkConfig(&conf->base);
|
||||
}
|
||||
|
||||
conf->base.SurfaceType |= surface_type & (!double_buffer ? EGL_PIXMAP_BIT:
|
||||
(EGL_WINDOW_BIT | EGL_PBUFFER_BIT | EGL_SWAP_BEHAVIOR_PRESERVED_BIT));
|
||||
|
||||
return conf;
|
||||
}
|
||||
|
||||
|
|
@ -491,8 +523,19 @@ dri2_create_context(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if (conf != NULL)
|
||||
dri_config = dri2_config->dri_config;
|
||||
if (conf != NULL) {
|
||||
/* The config chosen here isn't necessarily
|
||||
* used for surfaces later.
|
||||
* A pixmap surface will use the single config.
|
||||
* This opportunity depends on disabling the
|
||||
* doubleBufferMode check in
|
||||
* src/mesa/main/context.c:check_compatible()
|
||||
*/
|
||||
if (dri2_config->dri_double_config)
|
||||
dri_config = dri2_config->dri_double_config;
|
||||
else
|
||||
dri_config = dri2_config->dri_single_config;
|
||||
}
|
||||
else
|
||||
dri_config = NULL;
|
||||
|
||||
|
|
@ -507,7 +550,7 @@ dri2_create_context(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf,
|
|||
} else if (api == __DRI_API_OPENGL) {
|
||||
dri2_ctx->dri_context =
|
||||
dri2_dpy->dri2->createNewContext(dri2_dpy->dri_screen,
|
||||
dri2_config->dri_config,
|
||||
dri_config,
|
||||
dri2_ctx_shared ?
|
||||
dri2_ctx_shared->dri_context : NULL,
|
||||
dri2_ctx);
|
||||
|
|
|
|||
|
|
@ -139,7 +139,8 @@ struct dri2_egl_buffer {
|
|||
struct dri2_egl_config
|
||||
{
|
||||
_EGLConfig base;
|
||||
const __DRIconfig *dri_config;
|
||||
const __DRIconfig *dri_single_config;
|
||||
const __DRIconfig *dri_double_config;
|
||||
};
|
||||
|
||||
struct dri2_egl_image
|
||||
|
|
@ -163,7 +164,7 @@ dri2_create_screen(_EGLDisplay *disp);
|
|||
|
||||
struct dri2_egl_config *
|
||||
dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id,
|
||||
int depth, EGLint surface_type);
|
||||
int depth, EGLint surface_type, const EGLint *attr_list);
|
||||
|
||||
_EGLImage *
|
||||
dri2_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
|
||||
|
|
|
|||
|
|
@ -649,7 +649,7 @@ dri2_initialize_drm(_EGLDriver *drv, _EGLDisplay *disp)
|
|||
goto cleanup_driver;
|
||||
|
||||
for (i = 0; dri2_dpy->driver_configs[i]; i++)
|
||||
dri2_add_config(disp, dri2_dpy->driver_configs[i], i + 1, 0, 0);
|
||||
dri2_add_config(disp, dri2_dpy->driver_configs[i], i + 1, 0, 0, NULL);
|
||||
|
||||
disp->Extensions.MESA_drm_image = EGL_TRUE;
|
||||
disp->Extensions.KHR_image_base = EGL_TRUE;
|
||||
|
|
|
|||
|
|
@ -94,7 +94,10 @@ dri2_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type,
|
|||
|
||||
dri2_surf->dri_drawable =
|
||||
(*dri2_dpy->dri2->createNewDrawable) (dri2_dpy->dri_screen,
|
||||
dri2_conf->dri_config, dri2_surf);
|
||||
type == EGL_WINDOW_BIT ?
|
||||
dri2_conf->dri_double_config :
|
||||
dri2_conf->dri_single_config,
|
||||
dri2_surf);
|
||||
if (dri2_surf->dri_drawable == NULL) {
|
||||
_eglError(EGL_BAD_ALLOC, "dri2->createNewDrawable");
|
||||
goto cleanup_dri_drawable;
|
||||
|
|
@ -180,6 +183,27 @@ dri2_wl_egl_pixmap_destroy(struct wl_egl_pixmap *egl_pixmap)
|
|||
egl_pixmap->name = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
dri2_process_back_buffer(struct dri2_egl_surface *dri2_surf, unsigned format)
|
||||
{
|
||||
struct dri2_egl_display *dri2_dpy =
|
||||
dri2_egl_display(dri2_surf->base.Resource.Display);
|
||||
|
||||
(void) format;
|
||||
|
||||
switch (dri2_surf->type) {
|
||||
case DRI2_WINDOW_SURFACE:
|
||||
/* allocate a front buffer for our double-buffered window*/
|
||||
dri2_surf->dri_buffers[__DRI_BUFFER_FRONT_LEFT] =
|
||||
dri2_dpy->dri2->allocateBuffer(dri2_dpy->dri_screen,
|
||||
__DRI_BUFFER_FRONT_LEFT, format,
|
||||
dri2_surf->base.Width, dri2_surf->base.Height);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
dri2_process_front_buffer(struct dri2_egl_surface *dri2_surf, unsigned format)
|
||||
{
|
||||
|
|
@ -187,14 +211,7 @@ dri2_process_front_buffer(struct dri2_egl_surface *dri2_surf, unsigned format)
|
|||
dri2_egl_display(dri2_surf->base.Resource.Display);
|
||||
struct dri2_egl_buffer *dri2_buf;
|
||||
|
||||
/* allocate a back buffer for our double-buffered window*/
|
||||
switch (dri2_surf->type) {
|
||||
case DRI2_WINDOW_SURFACE:
|
||||
dri2_surf->dri_buffers[__DRI_BUFFER_BACK_LEFT] =
|
||||
dri2_dpy->dri2->allocateBuffer(dri2_dpy->dri_screen,
|
||||
__DRI_BUFFER_BACK_LEFT, format,
|
||||
dri2_surf->base.Width, dri2_surf->base.Height);
|
||||
break;
|
||||
case DRI2_PIXMAP_SURFACE:
|
||||
dri2_buf = malloc(sizeof *dri2_buf);
|
||||
if (!dri2_buf)
|
||||
|
|
@ -264,6 +281,8 @@ dri2_get_buffers_with_format(__DRIdrawable * driDrawable,
|
|||
|
||||
if (attachments[i] == __DRI_BUFFER_FRONT_LEFT)
|
||||
dri2_process_front_buffer(dri2_surf, attachments[i+1]);
|
||||
else if (attachments[i] == __DRI_BUFFER_BACK_LEFT)
|
||||
dri2_process_back_buffer(dri2_surf, attachments[i+1]);
|
||||
}
|
||||
|
||||
memcpy(&dri2_surf->buffers[dri2_surf->buffer_count],
|
||||
|
|
@ -396,7 +415,7 @@ dri2_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
|
|||
if (!dri2_surf->wl_drm_buffer[WL_BUFFER_FRONT])
|
||||
dri2_surf->wl_drm_buffer[WL_BUFFER_FRONT] =
|
||||
wayland_create_buffer(dri2_surf,
|
||||
dri2_surf->dri_buffers[__DRI_BUFFER_BACK_LEFT]);
|
||||
dri2_surf->dri_buffers[__DRI_BUFFER_FRONT_LEFT]);
|
||||
|
||||
wl_surface_attach(dri2_surf->wl_win->surface,
|
||||
dri2_surf->wl_drm_buffer[WL_BUFFER_FRONT],
|
||||
|
|
@ -584,7 +603,7 @@ dri2_initialize_wayland(_EGLDriver *drv, _EGLDisplay *disp)
|
|||
|
||||
for (i = 0; dri2_dpy->driver_configs[i]; i++)
|
||||
dri2_add_config(disp, dri2_dpy->driver_configs[i], i + 1, 0,
|
||||
EGL_WINDOW_BIT | EGL_PIXMAP_BIT);
|
||||
EGL_WINDOW_BIT | EGL_PIXMAP_BIT, NULL);
|
||||
|
||||
|
||||
disp->Extensions.MESA_drm_image = EGL_TRUE;
|
||||
|
|
|
|||
|
|
@ -79,7 +79,10 @@ dri2_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type,
|
|||
|
||||
dri2_surf->dri_drawable =
|
||||
(*dri2_dpy->dri2->createNewDrawable) (dri2_dpy->dri_screen,
|
||||
dri2_conf->dri_config, dri2_surf);
|
||||
type == EGL_WINDOW_BIT ?
|
||||
dri2_conf->dri_double_config :
|
||||
dri2_conf->dri_single_config,
|
||||
dri2_surf);
|
||||
if (dri2_surf->dri_drawable == NULL) {
|
||||
_eglError(EGL_BAD_ALLOC, "dri2->createNewDrawable");
|
||||
goto cleanup_pixmap;
|
||||
|
|
@ -428,8 +431,12 @@ dri2_add_configs_for_visuals(struct dri2_egl_display *dri2_dpy,
|
|||
xcb_depth_iterator_t d;
|
||||
xcb_visualtype_t *visuals;
|
||||
int i, j, id;
|
||||
struct dri2_egl_config *conf;
|
||||
EGLint surface_type;
|
||||
EGLint config_attrs[] = {
|
||||
EGL_NATIVE_VISUAL_ID, 0,
|
||||
EGL_NATIVE_VISUAL_TYPE, 0,
|
||||
EGL_NONE
|
||||
};
|
||||
|
||||
s = xcb_setup_roots_iterator(xcb_get_setup(dri2_dpy->conn));
|
||||
d = xcb_screen_allowed_depths_iterator(s.data);
|
||||
|
|
@ -451,14 +458,11 @@ dri2_add_configs_for_visuals(struct dri2_egl_display *dri2_dpy,
|
|||
|
||||
class_added[visuals[i]._class] = EGL_TRUE;
|
||||
for (j = 0; dri2_dpy->driver_configs[j]; j++) {
|
||||
conf = dri2_add_config(disp, dri2_dpy->driver_configs[j],
|
||||
id++, d.data->depth, surface_type);
|
||||
if (conf == NULL)
|
||||
continue;
|
||||
_eglSetConfigKey(&conf->base,
|
||||
EGL_NATIVE_VISUAL_ID, visuals[i].visual_id);
|
||||
_eglSetConfigKey(&conf->base,
|
||||
EGL_NATIVE_VISUAL_TYPE, visuals[i]._class);
|
||||
config_attrs[1] = visuals[i].visual_id;
|
||||
config_attrs[3] = visuals[i]._class;
|
||||
|
||||
dri2_add_config(disp, dri2_dpy->driver_configs[j], id++,
|
||||
d.data->depth, surface_type, config_attrs);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -481,6 +485,7 @@ dri2_copy_region(_EGLDriver *drv, _EGLDisplay *disp,
|
|||
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) {
|
||||
|
|
@ -502,14 +507,16 @@ dri2_copy_region(_EGLDriver *drv, _EGLDisplay *disp,
|
|||
#endif
|
||||
#endif
|
||||
|
||||
if (!dri2_surf->have_fake_front)
|
||||
return EGL_TRUE;
|
||||
if (dri2_surf->have_fake_front)
|
||||
render_attachment = XCB_DRI2_ATTACHMENT_BUFFER_FAKE_FRONT_LEFT;
|
||||
else
|
||||
render_attachment = XCB_DRI2_ATTACHMENT_BUFFER_BACK_LEFT;
|
||||
|
||||
cookie = xcb_dri2_copy_region_unchecked(dri2_dpy->conn,
|
||||
dri2_surf->drawable,
|
||||
region,
|
||||
XCB_DRI2_ATTACHMENT_BUFFER_FRONT_LEFT,
|
||||
XCB_DRI2_ATTACHMENT_BUFFER_FAKE_FRONT_LEFT);
|
||||
render_attachment);
|
||||
free(xcb_dri2_copy_region_reply(dri2_dpy->conn, cookie, NULL));
|
||||
|
||||
return EGL_TRUE;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue