diff options
Diffstat (limited to 'src/gallium/state_trackers/egl')
-rw-r--r-- | src/gallium/state_trackers/egl/common/egl_g3d.c | 224 | ||||
-rw-r--r-- | src/gallium/state_trackers/egl/x11/native_dri2.c | 229 | ||||
-rw-r--r-- | src/gallium/state_trackers/egl/x11/native_x11.c | 2 | ||||
-rw-r--r-- | src/gallium/state_trackers/egl/x11/native_ximage.c | 62 | ||||
-rw-r--r-- | src/gallium/state_trackers/egl/x11/x11_screen.c | 68 | ||||
-rw-r--r-- | src/gallium/state_trackers/egl/x11/x11_screen.h | 10 |
6 files changed, 363 insertions, 232 deletions
diff --git a/src/gallium/state_trackers/egl/common/egl_g3d.c b/src/gallium/state_trackers/egl/common/egl_g3d.c index d769d253ac..086e644e21 100644 --- a/src/gallium/state_trackers/egl/common/egl_g3d.c +++ b/src/gallium/state_trackers/egl/common/egl_g3d.c @@ -687,131 +687,143 @@ egl_g3d_destroy_context(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx) return EGL_TRUE; } -static EGLBoolean -init_surface_geometry(_EGLSurface *surf) -{ - struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); - - return gsurf->native->validate(gsurf->native, 0x0, - &gsurf->sequence_number, NULL, - &gsurf->base.Width, &gsurf->base.Height); -} +struct egl_g3d_create_surface_arg { + EGLint type; + union { + EGLNativeWindowType win; + EGLNativePixmapType pix; + } u; +}; static _EGLSurface * -egl_g3d_create_window_surface(_EGLDriver *drv, _EGLDisplay *dpy, - _EGLConfig *conf, EGLNativeWindowType win, - const EGLint *attribs) +egl_g3d_create_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, + struct egl_g3d_create_surface_arg *arg, + const EGLint *attribs) { struct egl_g3d_display *gdpy = egl_g3d_display(dpy); struct egl_g3d_config *gconf = egl_g3d_config(conf); struct egl_g3d_surface *gsurf; + struct native_surface *nsurf; + const char *err; + + switch (arg->type) { + case EGL_WINDOW_BIT: + err = "eglCreateWindowSurface"; + break; + case EGL_PIXMAP_BIT: + err = "eglCreatePixmapSurface"; + break; + case EGL_PBUFFER_BIT: + err = "eglCreatePBufferSurface"; + break; +#ifdef EGL_MESA_screen_surface + case EGL_SCREEN_BIT_MESA: + err = "eglCreateScreenSurface"; + break; +#endif + default: + err = "eglCreateUnknownSurface"; + break; + } gsurf = CALLOC_STRUCT(egl_g3d_surface); if (!gsurf) { - _eglError(EGL_BAD_ALLOC, "eglCreateWindowSurface"); + _eglError(EGL_BAD_ALLOC, err); return NULL; } - if (!_eglInitSurface(&gsurf->base, dpy, EGL_WINDOW_BIT, conf, attribs)) { + if (!_eglInitSurface(&gsurf->base, dpy, arg->type, conf, attribs)) { free(gsurf); return NULL; } - gsurf->native = - gdpy->native->create_window_surface(gdpy->native, win, gconf->native); - if (!gsurf->native) { + /* create the native surface */ + switch (arg->type) { + case EGL_WINDOW_BIT: + nsurf = gdpy->native->create_window_surface(gdpy->native, + arg->u.win, gconf->native); + break; + case EGL_PIXMAP_BIT: + nsurf = gdpy->native->create_pixmap_surface(gdpy->native, + arg->u.pix, gconf->native); + break; + case EGL_PBUFFER_BIT: + nsurf = gdpy->native->create_pbuffer_surface(gdpy->native, + gconf->native, gsurf->base.Width, gsurf->base.Height); + break; +#ifdef EGL_MESA_screen_surface + case EGL_SCREEN_BIT_MESA: + /* prefer back buffer (move to _eglInitSurface?) */ + gsurf->base.RenderBuffer = EGL_BACK_BUFFER; + nsurf = gdpy->native->modeset->create_scanout_surface(gdpy->native, + gconf->native, gsurf->base.Width, gsurf->base.Height); + break; +#endif + default: + nsurf = NULL; + break; + } + + if (!nsurf) { free(gsurf); return NULL; } - - if (!init_surface_geometry(&gsurf->base)) { - gsurf->native->destroy(gsurf->native); + /* initialize the geometry */ + if (!nsurf->validate(nsurf, 0x0, &gsurf->sequence_number, NULL, + &gsurf->base.Width, &gsurf->base.Height)) { + nsurf->destroy(nsurf); free(gsurf); return NULL; } - gsurf->render_att = (gsurf->base.RenderBuffer == EGL_SINGLE_BUFFER || - !gconf->native->mode.doubleBufferMode) ? + gsurf->native = nsurf; + + gsurf->render_att = (gsurf->base.RenderBuffer == EGL_SINGLE_BUFFER) ? NATIVE_ATTACHMENT_FRONT_LEFT : NATIVE_ATTACHMENT_BACK_LEFT; + if (!gconf->native->mode.doubleBufferMode) + gsurf->render_att = NATIVE_ATTACHMENT_FRONT_LEFT; return &gsurf->base; } static _EGLSurface * -egl_g3d_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *dpy, - _EGLConfig *conf, EGLNativePixmapType pix, +egl_g3d_create_window_surface(_EGLDriver *drv, _EGLDisplay *dpy, + _EGLConfig *conf, EGLNativeWindowType win, const EGLint *attribs) { - struct egl_g3d_display *gdpy = egl_g3d_display(dpy); - struct egl_g3d_config *gconf = egl_g3d_config(conf); - struct egl_g3d_surface *gsurf; - - gsurf = CALLOC_STRUCT(egl_g3d_surface); - if (!gsurf) { - _eglError(EGL_BAD_ALLOC, "eglCreatePixmapSurface"); - return NULL; - } + struct egl_g3d_create_surface_arg arg; - if (!_eglInitSurface(&gsurf->base, dpy, EGL_PIXMAP_BIT, conf, attribs)) { - free(gsurf); - return NULL; - } + memset(&arg, 0, sizeof(arg)); + arg.type = EGL_WINDOW_BIT; + arg.u.win = win; - gsurf->native = - gdpy->native->create_pixmap_surface(gdpy->native, pix, gconf->native); - if (!gsurf->native) { - free(gsurf); - return NULL; - } + return egl_g3d_create_surface(drv, dpy, conf, &arg, attribs); +} - if (!init_surface_geometry(&gsurf->base)) { - gsurf->native->destroy(gsurf->native); - free(gsurf); - return NULL; - } +static _EGLSurface * +egl_g3d_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *dpy, + _EGLConfig *conf, EGLNativePixmapType pix, + const EGLint *attribs) +{ + struct egl_g3d_create_surface_arg arg; - gsurf->render_att = NATIVE_ATTACHMENT_FRONT_LEFT; + memset(&arg, 0, sizeof(arg)); + arg.type = EGL_PIXMAP_BIT; + arg.u.pix = pix; - return &gsurf->base; + return egl_g3d_create_surface(drv, dpy, conf, &arg, attribs); } static _EGLSurface * egl_g3d_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, const EGLint *attribs) { - struct egl_g3d_display *gdpy = egl_g3d_display(dpy); - struct egl_g3d_config *gconf = egl_g3d_config(conf); - struct egl_g3d_surface *gsurf; - - gsurf = CALLOC_STRUCT(egl_g3d_surface); - if (!gsurf) { - _eglError(EGL_BAD_ALLOC, "eglCreatePbufferSurface"); - return NULL; - } + struct egl_g3d_create_surface_arg arg; - if (!_eglInitSurface(&gsurf->base, dpy, EGL_PBUFFER_BIT, conf, attribs)) { - free(gsurf); - return NULL; - } - - gsurf->native = - gdpy->native->create_pbuffer_surface(gdpy->native, gconf->native, - gsurf->base.Width, gsurf->base.Height); - if (!gsurf->native) { - free(gsurf); - return NULL; - } - - if (!init_surface_geometry(&gsurf->base)) { - gsurf->native->destroy(gsurf->native); - free(gsurf); - return NULL; - } - - gsurf->render_att = (!gconf->native->mode.doubleBufferMode) ? - NATIVE_ATTACHMENT_FRONT_LEFT : NATIVE_ATTACHMENT_BACK_LEFT; + memset(&arg, 0, sizeof(arg)); + arg.type = EGL_PBUFFER_BIT; - return &gsurf->base; + return egl_g3d_create_surface(drv, dpy, conf, &arg, attribs); } /** @@ -919,25 +931,7 @@ egl_g3d_swap_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf) if (gctx) gctx->stapi->st_notify_swapbuffers(gctx->draw.st_fb); - /* - * We drew on the back buffer, unless there was no back buffer. - * In that case, we drew on the front buffer. Either case, we call - * swap_buffers. - */ - if (!gsurf->native->swap_buffers(gsurf->native)) - return EGL_FALSE; - - if (gctx) { - struct egl_g3d_config *gconf = egl_g3d_config(gsurf->base.Config); - - /* force validation if the swap method is not copy */ - if (gconf->native->mode.swapMethod != GLX_SWAP_COPY_OML) { - gctx->force_validate = EGL_TRUE; - egl_g3d_validate_context(dpy, &gctx->base); - } - } - - return EGL_TRUE; + return gsurf->native->swap_buffers(gsurf->native); } /** @@ -1171,34 +1165,12 @@ static _EGLSurface * egl_g3d_create_screen_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, const EGLint *attribs) { - struct egl_g3d_display *gdpy = egl_g3d_display(dpy); - struct egl_g3d_config *gconf = egl_g3d_config(conf); - struct egl_g3d_surface *gsurf; - - gsurf = CALLOC_STRUCT(egl_g3d_surface); - if (!gsurf) { - _eglError(EGL_BAD_ALLOC, "eglCreatePbufferSurface"); - return NULL; - } - - if (!_eglInitSurface(&gsurf->base, dpy, - EGL_SCREEN_BIT_MESA, conf, attribs)) { - free(gsurf); - return NULL; - } + struct egl_g3d_create_surface_arg arg; - gsurf->native = - gdpy->native->modeset->create_scanout_surface(gdpy->native, - gconf->native, gsurf->base.Width, gsurf->base.Height); - if (!gsurf->native) { - free(gsurf); - return NULL; - } + memset(&arg, 0, sizeof(arg)); + arg.type = EGL_SCREEN_BIT_MESA; - gsurf->render_att = (!gconf->native->mode.doubleBufferMode) ? - NATIVE_ATTACHMENT_FRONT_LEFT : NATIVE_ATTACHMENT_BACK_LEFT; - - return &gsurf->base; + return egl_g3d_create_surface(drv, dpy, conf, &arg, attribs); } static EGLBoolean diff --git a/src/gallium/state_trackers/egl/x11/native_dri2.c b/src/gallium/state_trackers/egl/x11/native_dri2.c index dbd1a64992..8df58891a0 100644 --- a/src/gallium/state_trackers/egl/x11/native_dri2.c +++ b/src/gallium/state_trackers/egl/x11/native_dri2.c @@ -26,6 +26,7 @@ #include "util/u_math.h" #include "util/u_format.h" #include "util/u_inlines.h" +#include "util/u_hash_table.h" #include "pipe/p_compiler.h" #include "pipe/p_screen.h" #include "pipe/p_context.h" @@ -50,9 +51,13 @@ struct dri2_display { struct drm_api *api; struct x11_screen *xscr; int xscr_number; + const char *dri_driver; + int dri_major, dri_minor; struct dri2_config *configs; int num_configs; + + struct util_hash_table *surfaces; }; struct dri2_surface { @@ -62,7 +67,8 @@ struct dri2_surface { enum pipe_format color_format; struct dri2_display *dri2dpy; - unsigned int sequence_number; + unsigned int server_stamp; + unsigned int client_stamp; int width, height; struct pipe_texture *textures[NUM_NATIVE_ATTACHMENTS]; uint valid_mask; @@ -96,65 +102,23 @@ dri2_config(const struct native_config *nconf) } /** - * Get the buffers from the server. + * Process the buffers returned by the server. */ static void -dri2_surface_get_buffers(struct native_surface *nsurf, uint buffer_mask) +dri2_surface_process_drawable_buffers(struct native_surface *nsurf, + struct x11_drawable_buffer *xbufs, + int num_xbufs) { struct dri2_surface *dri2surf = dri2_surface(nsurf); struct dri2_display *dri2dpy = dri2surf->dri2dpy; - unsigned int dri2atts[NUM_NATIVE_ATTACHMENTS]; - int num_ins, num_outs, att, i; - struct x11_drawable_buffer *xbufs; struct pipe_texture templ; uint valid_mask; + int i; - /* prepare the attachments */ - num_ins = 0; - for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) { - if (native_attachment_mask_test(buffer_mask, att)) { - unsigned int dri2att; - - switch (att) { - case NATIVE_ATTACHMENT_FRONT_LEFT: - dri2att = DRI2BufferFrontLeft; - break; - case NATIVE_ATTACHMENT_BACK_LEFT: - dri2att = DRI2BufferBackLeft; - break; - case NATIVE_ATTACHMENT_FRONT_RIGHT: - dri2att = DRI2BufferFrontRight; - break; - case NATIVE_ATTACHMENT_BACK_RIGHT: - dri2att = DRI2BufferBackRight; - break; - default: - assert(0); - dri2att = 0; - break; - } - - dri2atts[num_ins] = dri2att; - num_ins++; - } - } - - xbufs = x11_drawable_get_buffers(dri2dpy->xscr, dri2surf->drawable, - &dri2surf->width, &dri2surf->height, - dri2atts, FALSE, num_ins, &num_outs); - - /* we should be able to do better... */ - if (xbufs && dri2surf->last_num_xbufs == num_outs && - memcmp(dri2surf->last_xbufs, xbufs, sizeof(*xbufs) * num_outs) == 0) { - free(xbufs); - return; - } - - /* free the old buffers */ + /* free the old textures */ for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) pipe_texture_reference(&dri2surf->textures[i], NULL); dri2surf->valid_mask = 0x0; - dri2surf->sequence_number++; dri2surf->have_back = FALSE; dri2surf->have_fake = FALSE; @@ -172,7 +136,7 @@ dri2_surface_get_buffers(struct native_surface *nsurf, uint buffer_mask) templ.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET; valid_mask = 0x0; - for (i = 0; i < num_outs; i++) { + for (i = 0; i < num_xbufs; i++) { struct x11_drawable_buffer *xbuf = &xbufs[i]; const char *desc; enum native_attachment natt; @@ -212,12 +176,72 @@ dri2_surface_get_buffers(struct native_surface *nsurf, uint buffer_mask) valid_mask |= 1 << natt; } + dri2surf->valid_mask = valid_mask; +} + +/** + * Get the buffers from the server. + */ +static void +dri2_surface_get_buffers(struct native_surface *nsurf, uint buffer_mask) +{ + struct dri2_surface *dri2surf = dri2_surface(nsurf); + struct dri2_display *dri2dpy = dri2surf->dri2dpy; + unsigned int dri2atts[NUM_NATIVE_ATTACHMENTS]; + int num_ins, num_outs, att; + struct x11_drawable_buffer *xbufs; + + /* prepare the attachments */ + num_ins = 0; + for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) { + if (native_attachment_mask_test(buffer_mask, att)) { + unsigned int dri2att; + + switch (att) { + case NATIVE_ATTACHMENT_FRONT_LEFT: + dri2att = DRI2BufferFrontLeft; + break; + case NATIVE_ATTACHMENT_BACK_LEFT: + dri2att = DRI2BufferBackLeft; + break; + case NATIVE_ATTACHMENT_FRONT_RIGHT: + dri2att = DRI2BufferFrontRight; + break; + case NATIVE_ATTACHMENT_BACK_RIGHT: + dri2att = DRI2BufferBackRight; + break; + default: + assert(0); + dri2att = 0; + break; + } + + dri2atts[num_ins] = dri2att; + num_ins++; + } + } + + xbufs = x11_drawable_get_buffers(dri2dpy->xscr, dri2surf->drawable, + &dri2surf->width, &dri2surf->height, + dri2atts, FALSE, num_ins, &num_outs); + + /* we should be able to do better... */ + if (xbufs && dri2surf->last_num_xbufs == num_outs && + memcmp(dri2surf->last_xbufs, xbufs, sizeof(*xbufs) * num_outs) == 0) { + free(xbufs); + dri2surf->client_stamp = dri2surf->server_stamp; + return; + } + + dri2_surface_process_drawable_buffers(&dri2surf->base, xbufs, num_outs); + + dri2surf->server_stamp++; + dri2surf->client_stamp = dri2surf->server_stamp; + if (dri2surf->last_xbufs) free(dri2surf->last_xbufs); dri2surf->last_xbufs = xbufs; dri2surf->last_num_xbufs = num_outs; - - dri2surf->valid_mask = valid_mask; } /** @@ -264,7 +288,7 @@ dri2_surface_update_buffers(struct native_surface *nsurf, uint buffer_mask) } } dri2surf->valid_mask |= new_valid; - /* no need to update sequence number */ + /* no need to update the stamps */ } else { dri2_surface_get_buffers(&dri2surf->base, buffer_mask); @@ -273,6 +297,16 @@ dri2_surface_update_buffers(struct native_surface *nsurf, uint buffer_mask) return ((dri2surf->valid_mask & buffer_mask) == buffer_mask); } +/** + * Return TRUE if the surface receives DRI2_InvalidateBuffers events. + */ +static INLINE boolean +dri2_surface_receive_events(struct native_surface *nsurf) +{ + struct dri2_surface *dri2surf = dri2_surface(nsurf); + return (dri2surf->dri2dpy->dri_minor >= 3); +} + static boolean dri2_surface_flush_frontbuffer(struct native_surface *nsurf) { @@ -289,6 +323,10 @@ dri2_surface_flush_frontbuffer(struct native_surface *nsurf) 0, 0, dri2surf->width, dri2surf->height, DRI2BufferFakeFrontLeft, DRI2BufferFrontLeft); + /* force buffers to be updated in next validation call */ + if (!dri2_surface_receive_events(&dri2surf->base)) + dri2surf->server_stamp++; + return TRUE; } @@ -314,6 +352,10 @@ dri2_surface_swap_buffers(struct native_surface *nsurf) 0, 0, dri2surf->width, dri2surf->height, DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft); + /* force buffers to be updated in next validation call */ + if (!dri2_surface_receive_events(&dri2surf->base)) + dri2surf->server_stamp++; + return TRUE; } @@ -324,11 +366,14 @@ dri2_surface_validate(struct native_surface *nsurf, uint attachment_mask, { struct dri2_surface *dri2surf = dri2_surface(nsurf); - if (!dri2_surface_update_buffers(&dri2surf->base, attachment_mask)) - return FALSE; + if (dri2surf->server_stamp != dri2surf->client_stamp || + (dri2surf->valid_mask & attachment_mask) != attachment_mask) { + if (!dri2_surface_update_buffers(&dri2surf->base, attachment_mask)) + return FALSE; + } if (seq_num) - *seq_num = dri2surf->sequence_number; + *seq_num = dri2surf->client_stamp; if (textures) { int att; @@ -377,9 +422,13 @@ dri2_surface_destroy(struct native_surface *nsurf) pipe_texture_reference(&ptex, NULL); } - if (dri2surf->drawable) + if (dri2surf->drawable) { x11_drawable_enable_dri2(dri2surf->dri2dpy->xscr, dri2surf->drawable, FALSE); + + util_hash_table_remove(dri2surf->dri2dpy->surfaces, + (void *) dri2surf->drawable); + } free(dri2surf); } @@ -408,8 +457,14 @@ dri2_display_create_surface(struct native_display *ndpy, dri2surf->base.validate = dri2_surface_validate; dri2surf->base.wait = dri2_surface_wait; - if (drawable) + if (drawable) { x11_drawable_enable_dri2(dri2dpy->xscr, drawable, TRUE); + /* initialize the geometry */ + dri2_surface_update_buffers(&dri2surf->base, 0x0); + + util_hash_table_set(dri2surf->dri2dpy->surfaces, + (void *) dri2surf->drawable, (void *) &dri2surf->base); + } return dri2surf; } @@ -655,6 +710,9 @@ dri2_display_destroy(struct native_display *ndpy) if (dri2dpy->base.screen) dri2dpy->base.screen->destroy(dri2dpy->base.screen); + if (dri2dpy->surfaces) + util_hash_table_destroy(dri2dpy->surfaces); + if (dri2dpy->xscr) x11_screen_destroy(dri2dpy->xscr); if (dri2dpy->own_dpy) @@ -664,6 +722,24 @@ dri2_display_destroy(struct native_display *ndpy) free(dri2dpy); } +static void +dri2_display_invalidate_buffers(struct x11_screen *xscr, Drawable drawable, + void *user_data) +{ + struct native_display *ndpy = (struct native_display* ) user_data; + struct dri2_display *dri2dpy = dri2_display(ndpy); + struct native_surface *nsurf; + struct dri2_surface *dri2surf; + + nsurf = (struct native_surface *) + util_hash_table_get(dri2dpy->surfaces, (void *) drawable); + if (!nsurf) + return; + + dri2surf = dri2_surface(nsurf); + dri2surf->server_stamp++; +} + /** * Initialize DRI2 and pipe screen. */ @@ -681,7 +757,17 @@ dri2_display_init_screen(struct native_display *ndpy) return FALSE; } - fd = x11_screen_enable_dri2(dri2dpy->xscr, driver); + dri2dpy->dri_driver = x11_screen_probe_dri2(dri2dpy->xscr, + &dri2dpy->dri_major, &dri2dpy->dri_minor); + if (!dri2dpy->dri_driver || !driver || + strcmp(dri2dpy->dri_driver, driver) != 0) { + _eglLog(_EGL_WARNING, "Driver mismatch: %s != %s", + dri2dpy->dri_driver, dri2dpy->api->name); + return FALSE; + } + + fd = x11_screen_enable_dri2(dri2dpy->xscr, + dri2_display_invalidate_buffers, &dri2dpy->base); if (fd < 0) return FALSE; @@ -696,6 +782,19 @@ dri2_display_init_screen(struct native_display *ndpy) return TRUE; } +static unsigned +dri2_display_hash_table_hash(void *key) +{ + XID drawable = pointer_to_uintptr(key); + return (unsigned) drawable; +} + +static int +dri2_display_hash_table_compare(void *key1, void *key2) +{ + return (key1 - key2); +} + struct native_display * x11_create_dri2_display(EGLNativeDisplayType dpy, struct drm_api *api) { @@ -706,11 +805,6 @@ x11_create_dri2_display(EGLNativeDisplayType dpy, struct drm_api *api) return NULL; dri2dpy->api = api; - if (!dri2dpy->api) { - _eglLog(_EGL_WARNING, "failed to create DRM API"); - free(dri2dpy); - return NULL; - } dri2dpy->dpy = dpy; if (!dri2dpy->dpy) { @@ -734,6 +828,13 @@ x11_create_dri2_display(EGLNativeDisplayType dpy, struct drm_api *api) return NULL; } + dri2dpy->surfaces = util_hash_table_create(dri2_display_hash_table_hash, + dri2_display_hash_table_compare); + if (!dri2dpy->surfaces) { + dri2_display_destroy(&dri2dpy->base); + return NULL; + } + dri2dpy->base.destroy = dri2_display_destroy; dri2dpy->base.get_configs = dri2_display_get_configs; dri2dpy->base.is_pixmap_supported = dri2_display_is_pixmap_supported; diff --git a/src/gallium/state_trackers/egl/x11/native_x11.c b/src/gallium/state_trackers/egl/x11/native_x11.c index 55f0d4d308..3add95d0ac 100644 --- a/src/gallium/state_trackers/egl/x11/native_x11.c +++ b/src/gallium/state_trackers/egl/x11/native_x11.c @@ -70,7 +70,7 @@ native_create_probe(EGLNativeDisplayType dpy) xscr = x11_screen_create(xdpy, scr); if (xscr) { if (x11_screen_support(xscr, X11_SCREEN_EXTENSION_DRI2)) { - driver_name = x11_screen_probe_dri2(xscr); + driver_name = x11_screen_probe_dri2(xscr, NULL, NULL); if (driver_name) nprobe->data = strdup(driver_name); } diff --git a/src/gallium/state_trackers/egl/x11/native_ximage.c b/src/gallium/state_trackers/egl/x11/native_ximage.c index 78675a1998..8ba73f289d 100644 --- a/src/gallium/state_trackers/egl/x11/native_ximage.c +++ b/src/gallium/state_trackers/egl/x11/native_ximage.c @@ -81,7 +81,8 @@ struct ximage_surface { GC gc; - unsigned int sequence_number; + unsigned int server_stamp; + unsigned int client_stamp; int width, height; struct ximage_buffer buffers[NUM_NATIVE_ATTACHMENTS]; uint valid_mask; @@ -216,18 +217,11 @@ ximage_surface_update_geometry(struct native_surface *nsurf) ok = XGetGeometry(xsurf->xdpy->dpy, xsurf->drawable, &root, &x, &y, &w, &h, &border, &depth); - if (!ok) { - w = xsurf->width; - h = xsurf->height; - } - - /* all buffers become invalid */ - if (xsurf->width != w || xsurf->height != h) { + if (ok && (xsurf->width != w || xsurf->height != h)) { xsurf->width = w; xsurf->height = h; - xsurf->valid_mask = 0x0; - xsurf->sequence_number++; + xsurf->server_stamp++; updated = TRUE; } @@ -247,10 +241,18 @@ ximage_surface_update_buffers(struct native_surface *nsurf, uint buffer_mask) int att; updated = ximage_surface_update_geometry(&xsurf->base); - buffer_mask &= ~xsurf->valid_mask; - /* all requested buffers are valid */ - if (!buffer_mask) - return TRUE; + if (updated) { + /* all buffers become invalid */ + xsurf->valid_mask = 0x0; + } + else { + buffer_mask &= ~xsurf->valid_mask; + /* all requested buffers are valid */ + if (!buffer_mask) { + xsurf->client_stamp = xsurf->server_stamp; + return TRUE; + } + } new_valid = 0x0; for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) { @@ -273,11 +275,8 @@ ximage_surface_update_buffers(struct native_surface *nsurf, uint buffer_mask) } } - if (new_valid) { - xsurf->valid_mask |= new_valid; - if (updated) - xsurf->sequence_number++; - } + xsurf->valid_mask |= new_valid; + xsurf->client_stamp = xsurf->server_stamp; return (new_valid == buffer_mask); } @@ -333,7 +332,15 @@ ximage_surface_draw_buffer(struct native_surface *nsurf, static boolean ximage_surface_flush_frontbuffer(struct native_surface *nsurf) { - return ximage_surface_draw_buffer(nsurf, NATIVE_ATTACHMENT_FRONT_LEFT); + struct ximage_surface *xsurf = ximage_surface(nsurf); + boolean ret; + + ret = ximage_surface_draw_buffer(&xsurf->base, + NATIVE_ATTACHMENT_FRONT_LEFT); + /* force buffers to be updated in next validation call */ + xsurf->server_stamp++; + + return ret; } static boolean @@ -345,6 +352,8 @@ ximage_surface_swap_buffers(struct native_surface *nsurf) /* display the back buffer first */ ret = ximage_surface_draw_buffer(nsurf, NATIVE_ATTACHMENT_BACK_LEFT); + /* force buffers to be updated in next validation call */ + xsurf->server_stamp++; xfront = &xsurf->buffers[NATIVE_ATTACHMENT_FRONT_LEFT]; xback = &xsurf->buffers[NATIVE_ATTACHMENT_BACK_LEFT]; @@ -356,7 +365,6 @@ ximage_surface_swap_buffers(struct native_surface *nsurf) xtmp = *xfront; *xfront = *xback; *xback = xtmp; - xsurf->sequence_number++; return ret; } @@ -368,11 +376,14 @@ ximage_surface_validate(struct native_surface *nsurf, uint attachment_mask, { struct ximage_surface *xsurf = ximage_surface(nsurf); - if (!ximage_surface_update_buffers(&xsurf->base, attachment_mask)) - return FALSE; + if (xsurf->client_stamp != xsurf->server_stamp || + (xsurf->valid_mask & attachment_mask) != attachment_mask) { + if (!ximage_surface_update_buffers(&xsurf->base, attachment_mask)) + return FALSE; + } if (seq_num) - *seq_num = xsurf->sequence_number; + *seq_num = xsurf->client_stamp; if (textures) { int att; @@ -453,6 +464,9 @@ ximage_display_create_surface(struct native_display *ndpy, return NULL; } + /* initialize the geometry */ + ximage_surface_update_buffers(&xsurf->base, 0x0); + for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) { struct ximage_buffer *xbuf = &xsurf->buffers[i]; diff --git a/src/gallium/state_trackers/egl/x11/x11_screen.c b/src/gallium/state_trackers/egl/x11/x11_screen.c index d72bfc99d3..f409611484 100644 --- a/src/gallium/state_trackers/egl/x11/x11_screen.c +++ b/src/gallium/state_trackers/egl/x11/x11_screen.c @@ -39,6 +39,9 @@ #include "glxinit.h" struct x11_screen { + /* dummy base class */ + struct __GLXDRIdisplayRec base; + Display *dpy; int number; @@ -53,6 +56,9 @@ struct x11_screen { char *dri_device; int dri_fd; + x11_drawable_invalidate_buffers dri_invalidate_buffers; + void *dri_user_data; + XVisualInfo *visuals; int num_visuals; @@ -98,6 +104,8 @@ x11_screen_destroy(struct x11_screen *xscr) Xfree(xscr->dri_device); /* xscr->glx_dpy will be destroyed with the X display */ + if (xscr->glx_dpy) + xscr->glx_dpy->dri2Display = NULL; if (xscr->visuals) XFree(xscr->visuals); @@ -247,24 +255,25 @@ x11_screen_get_glx_visuals(struct x11_screen *xscr) : NULL; } -static boolean -x11_screen_is_driver_equal(struct x11_screen *xscr, const char *driver) -{ - return (strcmp(xscr->dri_driver, driver) == 0); -} - /** * Probe the screen for the DRI2 driver name. */ const char * -x11_screen_probe_dri2(struct x11_screen *xscr) +x11_screen_probe_dri2(struct x11_screen *xscr, int *major, int *minor) { + if (!x11_screen_init_dri2(xscr)) + return NULL; + /* get the driver name and the device name */ if (!xscr->dri_driver) { if (!DRI2Connect(xscr->dpy, RootWindow(xscr->dpy, xscr->number), &xscr->dri_driver, &xscr->dri_device)) xscr->dri_driver = xscr->dri_device = NULL; } + if (major) + *major = xscr->dri_major; + if (minor) + *minor = xscr->dri_minor; return xscr->dri_driver; } @@ -274,21 +283,17 @@ x11_screen_probe_dri2(struct x11_screen *xscr) * descriptor will be closed automatically when the screen is destoryed. */ int -x11_screen_enable_dri2(struct x11_screen *xscr, const char *driver) +x11_screen_enable_dri2(struct x11_screen *xscr, + x11_drawable_invalidate_buffers invalidate_buffers, + void *user_data) { if (xscr->dri_fd < 0) { int fd; drm_magic_t magic; /* get the driver name and the device name first */ - if (!x11_screen_probe_dri2(xscr)) - return -1; - - if (!x11_screen_is_driver_equal(xscr, driver)) { - _eglLog(_EGL_WARNING, "Driver mismatch: %s != %s", - xscr->dri_driver, driver); + if (!x11_screen_probe_dri2(xscr, NULL, NULL)) return -1; - } fd = open(xscr->dri_device, O_RDWR); if (fd < 0) { @@ -310,6 +315,22 @@ x11_screen_enable_dri2(struct x11_screen *xscr, const char *driver) return -1; } + if (!x11_screen_init_glx(xscr)) { + _eglLog(_EGL_WARNING, "failed to initialize GLX"); + close(fd); + return -1; + } + if (xscr->glx_dpy->dri2Display) { + _eglLog(_EGL_WARNING, + "display is already managed by another x11 screen"); + close(fd); + return -1; + } + + xscr->glx_dpy->dri2Display = (__GLXDRIdisplay *) xscr; + xscr->dri_invalidate_buffers = invalidate_buffers; + xscr->dri_user_data = user_data; + xscr->dri_fd = fd; } @@ -451,3 +472,20 @@ x11_context_modes_count(const __GLcontextModes *modes) count++; return count; } + +/** + * This is called from src/glx/dri2.c. + */ +void +dri2InvalidateBuffers(Display *dpy, XID drawable) +{ + __GLXdisplayPrivate *priv = __glXInitialize(dpy); + struct x11_screen *xscr = NULL; + + if (priv && priv->dri2Display) + xscr = (struct x11_screen *) priv->dri2Display; + if (!xscr || !xscr->dri_invalidate_buffers) + return; + + xscr->dri_invalidate_buffers(xscr, drawable, xscr->dri_user_data); +} diff --git a/src/gallium/state_trackers/egl/x11/x11_screen.h b/src/gallium/state_trackers/egl/x11/x11_screen.h index 5432858ac3..37e8d5a40e 100644 --- a/src/gallium/state_trackers/egl/x11/x11_screen.h +++ b/src/gallium/state_trackers/egl/x11/x11_screen.h @@ -48,6 +48,10 @@ struct x11_drawable_buffer { struct x11_screen; +typedef void (*x11_drawable_invalidate_buffers)(struct x11_screen *xscr, + Drawable drawable, + void *user_data); + struct x11_screen * x11_screen_create(Display *dpy, int screen); @@ -71,10 +75,12 @@ const __GLcontextModes * x11_screen_get_glx_visuals(struct x11_screen *xscr); const char * -x11_screen_probe_dri2(struct x11_screen *xscr); +x11_screen_probe_dri2(struct x11_screen *xscr, int *major, int *minor); int -x11_screen_enable_dri2(struct x11_screen *xscr, const char *driver); +x11_screen_enable_dri2(struct x11_screen *xscr, + x11_drawable_invalidate_buffers invalidate_buffers, + void *user_data); __GLcontextModes * x11_context_modes_create(unsigned count); |