From 6cb89b23eeac50cfb0c5fb8d77e19f869b524eac Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Tue, 12 Jan 2010 18:08:02 +0800 Subject: st/egl_g3d: Use a sequence number to decide if validation is required. It is not safe to assume that the native surface has not changed since the last validation by checking the geometry alone. Add a sequence number to "validate" callback for that purpose. This is inspired by Luca Barbieri's work. --- .../state_trackers/egl_g3d/common/egl_g3d.c | 35 ++++++++++++++-------- .../state_trackers/egl_g3d/common/egl_g3d.h | 1 + src/gallium/state_trackers/egl_g3d/common/native.h | 7 +++-- .../state_trackers/egl_g3d/kms/native_kms.c | 9 ++++-- .../state_trackers/egl_g3d/kms/native_kms.h | 1 + .../state_trackers/egl_g3d/x11/native_dri2.c | 20 +++++++++++-- .../state_trackers/egl_g3d/x11/native_ximage.c | 14 ++++++++- 7 files changed, 66 insertions(+), 21 deletions(-) diff --git a/src/gallium/state_trackers/egl_g3d/common/egl_g3d.c b/src/gallium/state_trackers/egl_g3d/common/egl_g3d.c index 741e5b4659..9d5734d46f 100644 --- a/src/gallium/state_trackers/egl_g3d/common/egl_g3d.c +++ b/src/gallium/state_trackers/egl_g3d/common/egl_g3d.c @@ -63,22 +63,19 @@ egl_g3d_validate_context(_EGLDisplay *dpy, _EGLContext *ctx) } if (!gctx->force_validate) { - EGLint cur_w, cur_h; + unsigned int seq_num; - cur_w = gsurf->base.Width; - cur_h = gsurf->base.Height; gsurf->native->validate(gsurf->native, gbuf->native_atts, gbuf->num_atts, - NULL, - &gsurf->base.Width, &gsurf->base.Height); - /* validate only when the geometry changed */ - if (gsurf->base.Width == cur_w && gsurf->base.Height == cur_h) + &seq_num, NULL, NULL, NULL); + /* skip validation */ + if (gsurf->sequence_number == seq_num) continue; } gsurf->native->validate(gsurf->native, gbuf->native_atts, gbuf->num_atts, - (struct pipe_texture **) textures, + &gsurf->sequence_number, textures, &gsurf->base.Width, &gsurf->base.Height); for (i = 0; i < gbuf->num_atts; i++) { struct pipe_texture *pt = textures[i]; @@ -599,6 +596,16 @@ 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, NULL, 0, + &gsurf->sequence_number, NULL, + &gsurf->base.Width, &gsurf->base.Height); +} + static _EGLSurface * egl_g3d_create_window_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, EGLNativeWindowType win, @@ -626,8 +633,7 @@ egl_g3d_create_window_surface(_EGLDriver *drv, _EGLDisplay *dpy, return NULL; } - if (!gsurf->native->validate(gsurf->native, NULL, 0, NULL, - &gsurf->base.Width, &gsurf->base.Height)) { + if (!init_surface_geometry(&gsurf->base)) { gsurf->native->destroy(gsurf->native); free(gsurf); return NULL; @@ -667,8 +673,7 @@ egl_g3d_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *dpy, return NULL; } - if (!gsurf->native->validate(gsurf->native, NULL, 0, NULL, - &gsurf->base.Width, &gsurf->base.Height)) { + if (!init_surface_geometry(&gsurf->base)) { gsurf->native->destroy(gsurf->native); free(gsurf); return NULL; @@ -706,6 +711,12 @@ egl_g3d_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *dpy, 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; diff --git a/src/gallium/state_trackers/egl_g3d/common/egl_g3d.h b/src/gallium/state_trackers/egl_g3d/common/egl_g3d.h index 33894b614f..4c8b8dfe9e 100644 --- a/src/gallium/state_trackers/egl_g3d/common/egl_g3d.h +++ b/src/gallium/state_trackers/egl_g3d/common/egl_g3d.h @@ -73,6 +73,7 @@ struct egl_g3d_surface { struct native_surface *native; enum native_attachment render_att; struct pipe_surface *render_surface; + unsigned int sequence_number; }; struct egl_g3d_config { diff --git a/src/gallium/state_trackers/egl_g3d/common/native.h b/src/gallium/state_trackers/egl_g3d/common/native.h index 5ddcf67360..4714e24b5c 100644 --- a/src/gallium/state_trackers/egl_g3d/common/native.h +++ b/src/gallium/state_trackers/egl_g3d/common/native.h @@ -65,8 +65,9 @@ struct native_surface { /** * Validate the buffers of the surface. The returned textures are owned by - * the caller. It is possible that this function is called with textures, - * width, or height being NULL. + * the caller. A sequence number is also returned. The caller can use it + * to check if anything has changed since the last call. Any of the pointers + * may be NULL and it indicates the caller has no interest in those values. * * If this function is called multiple times with different attachments, * those not listed in the latest call might be destroyed. This behavior @@ -75,7 +76,7 @@ struct native_surface { boolean (*validate)(struct native_surface *nsurf, const enum native_attachment *natts, unsigned num_natts, - struct pipe_texture **textures, + unsigned int *seq_num, struct pipe_texture **textures, int *width, int *height); /** diff --git a/src/gallium/state_trackers/egl_g3d/kms/native_kms.c b/src/gallium/state_trackers/egl_g3d/kms/native_kms.c index 0e0babdb14..a44b9b9ae5 100644 --- a/src/gallium/state_trackers/egl_g3d/kms/native_kms.c +++ b/src/gallium/state_trackers/egl_g3d/kms/native_kms.c @@ -36,7 +36,7 @@ static boolean kms_surface_validate(struct native_surface *nsurf, const enum native_attachment *natts, unsigned num_natts, - struct pipe_texture **textures, + unsigned int *seq_num, struct pipe_texture **textures, int *width, int *height) { struct kms_surface *ksurf = kms_surface(nsurf); @@ -75,6 +75,8 @@ kms_surface_validate(struct native_surface *nsurf, pipe_texture_reference(&textures[i], ptex); } + if (seq_num) + *seq_num = ksurf->sequence_number; if (width) *width = ksurf->width; if (height) @@ -111,7 +113,7 @@ kms_surface_init_framebuffers(struct native_surface *nsurf, boolean need_back) if (!fb->texture) { /* make sure the texture has been allocated */ - kms_surface_validate(&ksurf->base, &natt, 1, NULL, NULL, NULL); + kms_surface_validate(&ksurf->base, &natt, 1, NULL, NULL, NULL, NULL); if (!ksurf->textures[natt]) return FALSE; @@ -196,6 +198,9 @@ kms_surface_swap_buffers(struct native_surface *nsurf) ksurf->textures[NATIVE_ATTACHMENT_BACK_LEFT]; ksurf->textures[NATIVE_ATTACHMENT_BACK_LEFT] = tmp_texture; + /* the front/back textures are swapped */ + ksurf->sequence_number++; + return TRUE; } diff --git a/src/gallium/state_trackers/egl_g3d/kms/native_kms.h b/src/gallium/state_trackers/egl_g3d/kms/native_kms.h index 3f869b25ac..095186e3cf 100644 --- a/src/gallium/state_trackers/egl_g3d/kms/native_kms.h +++ b/src/gallium/state_trackers/egl_g3d/kms/native_kms.h @@ -81,6 +81,7 @@ struct kms_surface { int width, height; struct pipe_texture *textures[NUM_NATIVE_ATTACHMENTS]; + unsigned int sequence_number; struct kms_framebuffer front_fb, back_fb; boolean is_shown; diff --git a/src/gallium/state_trackers/egl_g3d/x11/native_dri2.c b/src/gallium/state_trackers/egl_g3d/x11/native_dri2.c index 0dda786bbd..2192a1366d 100644 --- a/src/gallium/state_trackers/egl_g3d/x11/native_dri2.c +++ b/src/gallium/state_trackers/egl_g3d/x11/native_dri2.c @@ -64,6 +64,7 @@ struct dri2_surface { struct pipe_texture *pbuffer_textures[NUM_NATIVE_ATTACHMENTS]; boolean have_back, have_fake; int width, height; + unsigned int sequence_number; }; struct dri2_config { @@ -136,6 +137,7 @@ static boolean dri2_surface_validate(struct native_surface *nsurf, const enum native_attachment *natts, unsigned num_natts, + unsigned int *seq_num, struct pipe_texture **textures, int *width, int *height) { @@ -178,6 +180,8 @@ dri2_surface_validate(struct native_surface *nsurf, pipe_texture_reference(&textures[i], ptex); } + if (seq_num) + *seq_num = dri2surf->sequence_number; if (width) *width = dri2surf->width; if (height) @@ -219,15 +223,23 @@ dri2_surface_validate(struct native_surface *nsurf, dri2surf->have_back = FALSE; dri2surf->have_fake = FALSE; + /* remember old geometry */ + templ.width0 = dri2surf->width; + templ.height0 = dri2surf->height; + xbufs = x11_drawable_get_buffers(dri2dpy->xscr, dri2surf->drawable, &dri2surf->width, &dri2surf->height, dri2atts, FALSE, num_ins, &num_outs); if (!xbufs) return FALSE; - /* update width and height */ - templ.width0 = dri2surf->width; - templ.height0 = dri2surf->height; + if (templ.width0 != dri2surf->width || templ.height0 != dri2surf->height) { + /* are there cases where the buffers change and the geometry doesn't? */ + dri2surf->sequence_number++; + + templ.width0 = dri2surf->width; + templ.height0 = dri2surf->height; + } for (i = 0; i < num_outs; i++) { struct x11_drawable_buffer *xbuf = &xbufs[i]; @@ -279,6 +291,8 @@ dri2_surface_validate(struct native_surface *nsurf, free(xbufs); + if (seq_num) + *seq_num = dri2surf->sequence_number; if (width) *width = dri2surf->width; if (height) diff --git a/src/gallium/state_trackers/egl_g3d/x11/native_ximage.c b/src/gallium/state_trackers/egl_g3d/x11/native_ximage.c index e02faa9b7b..1a1844ec49 100644 --- a/src/gallium/state_trackers/egl_g3d/x11/native_ximage.c +++ b/src/gallium/state_trackers/egl_g3d/x11/native_ximage.c @@ -83,6 +83,7 @@ struct ximage_surface { GC gc; struct ximage_buffer buffers[NUM_NATIVE_ATTACHMENTS]; + unsigned int sequence_number; }; struct ximage_config { @@ -260,6 +261,9 @@ ximage_surface_swap_buffers(struct native_surface *nsurf) *xfront = *xback; *xback = xtmp; + /* the front/back textures are swapped */ + xsurf->sequence_number++; + return ximage_surface_draw_buffer(nsurf, NATIVE_ATTACHMENT_FRONT_LEFT); } @@ -288,11 +292,12 @@ static boolean ximage_surface_validate(struct native_surface *nsurf, const enum native_attachment *natts, unsigned num_natts, + unsigned int *seq_num, struct pipe_texture **textures, int *width, int *height) { struct ximage_surface *xsurf = ximage_surface(nsurf); - boolean error = FALSE; + boolean new_buffers = FALSE, error = FALSE; unsigned i; ximage_surface_update_geometry(&xsurf->base); @@ -311,6 +316,7 @@ ximage_surface_validate(struct native_surface *nsurf, if (!xbuf->texture || xsurf->width != xbuf->texture->width0 || xsurf->height != xbuf->texture->height0) { + new_buffers = TRUE; if (ximage_surface_alloc_buffer(&xsurf->base, natt)) { /* update ximage */ if (xbuf->ximage) { @@ -336,6 +342,12 @@ ximage_surface_validate(struct native_surface *nsurf, pipe_texture_reference(&textures[i], xbuf->texture); } + /* increase the sequence number so that caller knows */ + if (new_buffers) + xsurf->sequence_number++; + + if (seq_num) + *seq_num = xsurf->sequence_number; if (width) *width = xsurf->width; if (height) -- cgit v1.2.3