On Mon, Jan 4, 2010 at 11:12 PM, Luca Barbieri <l...@luca-barbieri.com> wrote: > The current code revalidates based on whether width or height have changed. > This is unreliable (it may change two times, with another context having got > the buffers for the intermediate size in the meantime) and causes two DRI2 > calls. > Instead, we add the notion of a drawable sequence number, which tracks the > number of times the surface textures have changed. > This sequence number, along with a pointer to the surface, is stored in > egl_g3d_buffer and is passed to ->validate. > ->validate for DRI2 updates an internal sequence number if the width or > height changed. > If it did not change, it checks whether it matches the one provided by the > client and, if so, does not return any texture. > Otherwise, it proceeds as normal. > If context validation is being forced, the sequence numbers are reset to 0 to > force it. I like the idea of sequence number. More comments inline. > --- > .../state_trackers/egl_g3d/common/egl_g3d.c | 32 +++++++--------- > .../state_trackers/egl_g3d/common/egl_g3d.h | 2 + > src/gallium/state_trackers/egl_g3d/common/native.h | 4 ++- > .../state_trackers/egl_g3d/x11/native_dri2.c | 28 ++++++++++---- > .../state_trackers/egl_g3d/x11/native_ximage.c | 39 > +++++++++++++------- > 5 files changed, 65 insertions(+), 40 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 d68f49e..480f5a7 100644 > --- a/src/gallium/state_trackers/egl_g3d/common/egl_g3d.c > +++ b/src/gallium/state_trackers/egl_g3d/common/egl_g3d.c > @@ -47,11 +47,11 @@ egl_g3d_validate_context(_EGLDisplay *dpy, _EGLContext > *ctx) > EGLint s, i; > > /* validate draw and/or read buffers */ > - num_surfaces = (gctx->base.ReadSurface == gctx->base.DrawSurface) ? 1 : 2; > - for (s = 0; s < num_surfaces; s++) { > + for (s = 0; s < 2; s++) { Why this change? > struct pipe_texture *textures[NUM_NATIVE_ATTACHMENTS]; > struct egl_g3d_surface *gsurf; > struct egl_g3d_buffer *gbuf; > + int cur_seq_num; > > if (s == 0) { > gsurf = egl_g3d_surface(gctx->base.DrawSurface); > @@ -62,24 +62,20 @@ egl_g3d_validate_context(_EGLDisplay *dpy, _EGLContext > *ctx) > gbuf = &gctx->read; > } > > - if (!gctx->force_validate) { > - EGLint cur_w, cur_h; > - > - 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) > - continue; > - } > + if (gctx->force_validate || gsurf != gbuf->surface) > + gbuf->seq_num = 0; > + cur_seq_num = gbuf->seq_num; > > gsurf->native->validate(gsurf->native, > gbuf->native_atts, gbuf->num_atts, > (struct pipe_texture **) textures, > - &gsurf->base.Width, &gsurf->base.Height); > + &gsurf->base.Width, &gsurf->base.Height, &gbuf->seq_num); > + > + if(gbuf->seq_num == cur_seq_num) > + continue; > + > + gbuf->surface = gsurf; > + Can we keep the logic as simple as:
if (not forced) { get_current_sequence_number(); if (seq_num has not changed) continue; } validate_and_update_buffers(); There should be no need to reset the sequence number or comparing the surface. > for (i = 0; i < gbuf->num_atts; i++) { > struct pipe_texture *pt = textures[i]; > struct pipe_surface *ps; > @@ -538,7 +534,7 @@ egl_g3d_create_window_surface(_EGLDriver *drv, > _EGLDisplay *dpy, > } > > if (!gsurf->native->validate(gsurf->native, NULL, 0, NULL, > - &gsurf->base.Width, &gsurf->base.Height)) { > + &gsurf->base.Width, &gsurf->base.Height, 0)) { > gsurf->native->destroy(gsurf->native); > free(gsurf); > return NULL; > @@ -579,7 +575,7 @@ egl_g3d_create_pixmap_surface(_EGLDriver *drv, > _EGLDisplay *dpy, > } > > if (!gsurf->native->validate(gsurf->native, NULL, 0, NULL, > - &gsurf->base.Width, &gsurf->base.Height)) { > + &gsurf->base.Width, &gsurf->base.Height, 0)) { > gsurf->native->destroy(gsurf->native); > free(gsurf); > return NULL; > 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 7f6823f..223b881 100644 > --- a/src/gallium/state_trackers/egl_g3d/common/egl_g3d.h > +++ b/src/gallium/state_trackers/egl_g3d/common/egl_g3d.h > @@ -51,6 +51,8 @@ struct egl_g3d_display { > > struct egl_g3d_buffer { > struct st_framebuffer *st_fb; > + struct egl_g3d_surface* surface; This might not be needed. > + int seq_num; > EGLint num_atts; > enum native_attachment native_atts[NUM_NATIVE_ATTACHMENTS]; > uint st_atts[NUM_NATIVE_ATTACHMENTS]; > diff --git a/src/gallium/state_trackers/egl_g3d/common/native.h > b/src/gallium/state_trackers/egl_g3d/common/native.h > index a59ceac..24cc506 100644 > --- a/src/gallium/state_trackers/egl_g3d/common/native.h > +++ b/src/gallium/state_trackers/egl_g3d/common/native.h > @@ -67,12 +67,14 @@ struct native_surface { > /** > * Validate the buffers of the surface. Those not listed in the > attachments > * will be destroyed. The returned textures are owned by the caller. > + * If *seq_num is not 0, it will do nothing if the surface sequence number > + * did not change. The current sequence number will be returned. Could we make it: /** * Validate the buffers of the surface. The returned textures are owned by * the caller. A sequence number is also returned. The caller can use it * to see 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 * might change in the future. */ That is, seq_num is no longer an input. > */ > boolean (*validate)(struct native_surface *nsurf, > const enum native_attachment *natts, > unsigned num_natts, > struct pipe_texture **textures, > - int *width, int *height); > + int *width, int *height, int* seq_num); > > /** > * Wait until all native commands affecting the surface has been executed. > 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 890e11d..e38695b 100644 > --- a/src/gallium/state_trackers/egl_g3d/x11/native_dri2.c > +++ b/src/gallium/state_trackers/egl_g3d/x11/native_dri2.c > @@ -67,6 +67,7 @@ struct dri2_surface { > unsigned names[NUM_NATIVE_ATTACHMENTS]; > boolean have_back, have_fake; > int width, height; > + int seq_num; > }; > > struct dri2_config { > @@ -140,7 +141,7 @@ dri2_surface_validate(struct native_surface *nsurf, > const enum native_attachment *natts, > unsigned num_natts, > struct pipe_texture **textures, > - int *width, int *height) > + int *width, int *height, int* seq_num) > { > struct dri2_surface *dri2surf = dri2_surface(nsurf); > struct dri2_display *dri2dpy = dri2surf->dri2dpy; > @@ -211,18 +212,26 @@ dri2_surface_validate(struct native_surface *nsurf, > texture_indices[natts[i]] = i; > } > > - dri2surf->have_back = FALSE; > - dri2surf->have_fake = FALSE; > - > xbufs = x11_drawable_get_buffers(dri2dpy->xscr, dri2surf->drawable, > - &dri2surf->width, &dri2surf->height, > + &templ.width0, &templ.height0, > dri2atts, FALSE, num_ins, &num_outs); > if (!xbufs) > return FALSE; > > - /* update width and height */ > - templ.width0 = dri2surf->width; > - templ.height0 = dri2surf->height; > + if(!dri2surf->seq_num || dri2surf->width != templ.width0 || > dri2surf->height != templ.height0) > + { > + /* update width and height */ > + dri2surf->width = templ.width0; > + dri2surf->height = templ.height0; > + > + if(!++dri2surf->seq_num) > + ++dri2surf->seq_num; /* wrap to 1, not 0 */ > + } > + else if(seq_num && *seq_num == dri2surf->seq_num) > + goto out; If this function is called twice, one with a back attachement followed by one without a back attachment, x11_drawable_get_buffers above will destroy the back buffer in the second call. We need to update dri2surf->have_back before bailing out. > + > + dri2surf->have_back = FALSE; > + dri2surf->have_fake = FALSE; > > for (i = 0; i < num_outs; i++) { > struct x11_drawable_buffer *xbuf = &xbufs[i]; > @@ -309,12 +318,15 @@ dri2_surface_validate(struct native_surface *nsurf, > } > } > > +out: > free(xbufs); > > if (width) > *width = dri2surf->width; > if (height) > *height = dri2surf->height; > + if(seq_num) > + *seq_num = dri2surf->seq_num; > > return TRUE; > } > 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 e02faa9..70e2ffb 100644 > --- a/src/gallium/state_trackers/egl_g3d/x11/native_ximage.c > +++ b/src/gallium/state_trackers/egl_g3d/x11/native_ximage.c > @@ -80,6 +80,7 @@ struct ximage_surface { > struct ximage_display *xdpy; > > int width, height; > + int seq_num; > GC gc; > > struct ximage_buffer buffers[NUM_NATIVE_ATTACHMENTS]; > @@ -289,10 +290,11 @@ ximage_surface_validate(struct native_surface *nsurf, > const enum native_attachment *natts, > unsigned num_natts, > struct pipe_texture **textures, > - int *width, int *height) > + int *width, int *height, int* seq_num) > { > struct ximage_surface *xsurf = ximage_surface(nsurf); > boolean error = FALSE; > + boolean changed = FALSE; > unsigned i; > > ximage_surface_update_geometry(&xsurf->base); > @@ -318,28 +320,39 @@ ximage_surface_validate(struct native_surface *nsurf, > xbuf->ximage->height = xbuf->transfer->height; > xbuf->ximage->bytes_per_line = xbuf->transfer->stride; > } > + > + changed = TRUE; > } > - } > > - /* allocation failed */ > - if (!xbuf->texture) { > - unsigned j; > - for (j = 0; j < i; j++) > - pipe_texture_reference(&textures[j], NULL); > - for (j = i; j < num_natts; j++) > - textures[j] = NULL; > - error = TRUE; > - break; > + /* allocation failed */ > + if (!xbuf->texture) > + return FALSE; > } > + } > + > + if(changed) > + { > + if(!++xsurf->seq_num) > + ++xsurf->seq_num; /* wrap to 1 */ > + } > + else if(seq_num && *seq_num == xsurf->seq_num) > + return TRUE; > > - if (textures) > - pipe_texture_reference(&textures[i], xbuf->texture); > + if(textures) { > + for (i = 0; i < num_natts; i++) { > + struct ximage_buffer *xbuf = &xsurf->buffers[natts[i]]; > + > + if (xbuf) > + pipe_texture_reference(&textures[i], xbuf->texture); > + } > } > > if (width) > *width = xsurf->width; > if (height) > *height = xsurf->height; > + if(seq_num) > + *seq_num = xsurf->seq_num; > > return !error; > } > -- > 1.6.3.3 > > ------------------------------------------------------------------------------ This SF.Net email is sponsored by the Verizon Developer Community Take advantage of Verizon's best-in-class app development support A streamlined, 14 day to market process makes app distribution fast and easy Join now and get one step closer to millions of Verizon customers http://p.sf.net/sfu/verizon-dev2dev _______________________________________________ Mesa3d-dev mailing list Mesa3d-dev@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/mesa3d-dev