mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-06 09:28:07 +02:00
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.
This commit is contained in:
parent
6a2936b876
commit
6cb89b23ee
7 changed files with 66 additions and 21 deletions
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue