diff options
| -rw-r--r-- | src/egl/drivers/dri2/egl_dri2.c | 75 | ||||
| -rw-r--r-- | src/egl/drivers/dri2/egl_dri2.h | 5 | ||||
| -rw-r--r-- | src/egl/drivers/dri2/platform_drm.c | 2 | ||||
| -rw-r--r-- | src/egl/drivers/dri2/platform_wayland.c | 35 | ||||
| -rw-r--r-- | src/egl/drivers/dri2/platform_x11.c | 33 | 
5 files changed, 110 insertions, 40 deletions
| diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c index 3e5107756a..2c4deaf7c0 100644 --- a/src/egl/drivers/dri2/egl_dri2.c +++ b/src/egl/drivers/dri2/egl_dri2.c @@ -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); diff --git a/src/egl/drivers/dri2/egl_dri2.h b/src/egl/drivers/dri2/egl_dri2.h index 72e887c95b..1656a50c01 100644 --- a/src/egl/drivers/dri2/egl_dri2.h +++ b/src/egl/drivers/dri2/egl_dri2.h @@ -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, diff --git a/src/egl/drivers/dri2/platform_drm.c b/src/egl/drivers/dri2/platform_drm.c index 431bfa0fcc..42939a57a2 100644 --- a/src/egl/drivers/dri2/platform_drm.c +++ b/src/egl/drivers/dri2/platform_drm.c @@ -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; diff --git a/src/egl/drivers/dri2/platform_wayland.c b/src/egl/drivers/dri2/platform_wayland.c index 16e088827e..9be9a81903 100644 --- a/src/egl/drivers/dri2/platform_wayland.c +++ b/src/egl/drivers/dri2/platform_wayland.c @@ -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; @@ -181,20 +184,34 @@ dri2_wl_egl_pixmap_destroy(struct wl_egl_pixmap *egl_pixmap)  }  static void -dri2_process_front_buffer(struct dri2_egl_surface *dri2_surf, unsigned format) +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); -   struct dri2_egl_buffer *dri2_buf; -   /* allocate a back buffer for our double-buffered window*/ +   (void) format; +     switch (dri2_surf->type) {     case DRI2_WINDOW_SURFACE: -      dri2_surf->dri_buffers[__DRI_BUFFER_BACK_LEFT] =  +      /* 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_BACK_LEFT, format, +               __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) +{ +   struct dri2_egl_display *dri2_dpy = +      dri2_egl_display(dri2_surf->base.Resource.Display); +   struct dri2_egl_buffer *dri2_buf; + +   switch (dri2_surf->type) {     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; diff --git a/src/egl/drivers/dri2/platform_x11.c b/src/egl/drivers/dri2/platform_x11.c index 3b2f06e748..e360266d80 100644 --- a/src/egl/drivers/dri2/platform_x11.c +++ b/src/egl/drivers/dri2/platform_x11.c @@ -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; | 
