mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-04-17 10:30:38 +02:00
st/egl_g3d: Update validate to use an attachment mask.
A validate call asks for the buffers of a native surface. Using a mask to represent the interested buffers is more intuitive. It also rules out corner cases such as a single attachment being listed multiple times.
This commit is contained in:
parent
1ed6311945
commit
fda897ad71
6 changed files with 116 additions and 129 deletions
|
|
@ -44,8 +44,13 @@ egl_g3d_validate_context(_EGLDisplay *dpy, _EGLContext *ctx)
|
|||
struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
|
||||
struct pipe_screen *screen = gdpy->native->screen;
|
||||
struct egl_g3d_context *gctx = egl_g3d_context(ctx);
|
||||
EGLint num_surfaces;
|
||||
EGLint s, i;
|
||||
const uint st_att_map[NUM_NATIVE_ATTACHMENTS] = {
|
||||
ST_SURFACE_FRONT_LEFT,
|
||||
ST_SURFACE_BACK_LEFT,
|
||||
ST_SURFACE_FRONT_RIGHT,
|
||||
ST_SURFACE_BACK_RIGHT,
|
||||
};
|
||||
EGLint num_surfaces, s;
|
||||
|
||||
/* validate draw and/or read buffers */
|
||||
num_surfaces = (gctx->base.ReadSurface == gctx->base.DrawSurface) ? 1 : 2;
|
||||
|
|
@ -53,6 +58,7 @@ egl_g3d_validate_context(_EGLDisplay *dpy, _EGLContext *ctx)
|
|||
struct pipe_texture *textures[NUM_NATIVE_ATTACHMENTS];
|
||||
struct egl_g3d_surface *gsurf;
|
||||
struct egl_g3d_buffer *gbuf;
|
||||
EGLint att;
|
||||
|
||||
if (s == 0) {
|
||||
gsurf = egl_g3d_surface(gctx->base.DrawSurface);
|
||||
|
|
@ -66,30 +72,31 @@ egl_g3d_validate_context(_EGLDisplay *dpy, _EGLContext *ctx)
|
|||
if (!gctx->force_validate) {
|
||||
unsigned int seq_num;
|
||||
|
||||
gsurf->native->validate(gsurf->native,
|
||||
gbuf->native_atts, gbuf->num_atts,
|
||||
gsurf->native->validate(gsurf->native, gbuf->attachment_mask,
|
||||
&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,
|
||||
pipe_surface_reference(&gsurf->render_surface, NULL);
|
||||
memset(textures, 0, sizeof(textures));
|
||||
|
||||
gsurf->native->validate(gsurf->native, gbuf->attachment_mask,
|
||||
&gsurf->sequence_number, textures,
|
||||
&gsurf->base.Width, &gsurf->base.Height);
|
||||
for (i = 0; i < gbuf->num_atts; i++) {
|
||||
struct pipe_texture *pt = textures[i];
|
||||
for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) {
|
||||
struct pipe_texture *pt = textures[att];
|
||||
struct pipe_surface *ps;
|
||||
|
||||
if (pt) {
|
||||
if (native_attachment_mask_test(gbuf->attachment_mask, att) && pt) {
|
||||
ps = screen->get_tex_surface(screen, pt, 0, 0, 0,
|
||||
PIPE_BUFFER_USAGE_GPU_READ |
|
||||
PIPE_BUFFER_USAGE_GPU_WRITE);
|
||||
gctx->stapi->st_set_framebuffer_surface(gbuf->st_fb,
|
||||
gbuf->st_atts[i], ps);
|
||||
st_att_map[att], ps);
|
||||
|
||||
if (gbuf->native_atts[i] == gsurf->render_att)
|
||||
if (gsurf->render_att == att)
|
||||
pipe_surface_reference(&gsurf->render_surface, ps);
|
||||
|
||||
pipe_surface_reference(&ps, NULL);
|
||||
|
|
@ -128,13 +135,7 @@ static void
|
|||
egl_g3d_route_context(_EGLDisplay *dpy, _EGLContext *ctx)
|
||||
{
|
||||
struct egl_g3d_context *gctx = egl_g3d_context(ctx);
|
||||
const uint st_att_map[NUM_NATIVE_ATTACHMENTS] = {
|
||||
ST_SURFACE_FRONT_LEFT,
|
||||
ST_SURFACE_BACK_LEFT,
|
||||
ST_SURFACE_FRONT_RIGHT,
|
||||
ST_SURFACE_BACK_RIGHT,
|
||||
};
|
||||
EGLint s, i;
|
||||
EGLint s;
|
||||
|
||||
/* route draw and read buffers' attachments */
|
||||
for (s = 0; s < 2; s++) {
|
||||
|
|
@ -150,11 +151,7 @@ egl_g3d_route_context(_EGLDisplay *dpy, _EGLContext *ctx)
|
|||
gbuf = &gctx->read;
|
||||
}
|
||||
|
||||
gbuf->native_atts[0] = gsurf->render_att;
|
||||
gbuf->num_atts = 1;
|
||||
|
||||
for (i = 0; i < gbuf->num_atts; i++)
|
||||
gbuf->st_atts[i] = st_att_map[gbuf->native_atts[i]];
|
||||
gbuf->attachment_mask = (1 << gsurf->render_att);
|
||||
|
||||
/* FIXME OpenGL defaults to draw the front or back buffer when the
|
||||
* context is single-buffered or double-buffered respectively. In EGL,
|
||||
|
|
@ -196,19 +193,19 @@ egl_g3d_realloc_context(_EGLDisplay *dpy, _EGLContext *ctx)
|
|||
if (!gdraw || priv != (void *) &gdraw->base) {
|
||||
gctx->stapi->st_unreference_framebuffer(gctx->draw.st_fb);
|
||||
gctx->draw.st_fb = NULL;
|
||||
gctx->draw.num_atts = 0;
|
||||
gctx->draw.attachment_mask = 0x0;
|
||||
}
|
||||
|
||||
if (is_equal) {
|
||||
gctx->read.st_fb = NULL;
|
||||
gctx->draw.num_atts = 0;
|
||||
gctx->draw.attachment_mask = 0x0;
|
||||
}
|
||||
else {
|
||||
priv = gctx->stapi->st_framebuffer_private(gctx->read.st_fb);
|
||||
if (!gread || priv != (void *) &gread->base) {
|
||||
gctx->stapi->st_unreference_framebuffer(gctx->read.st_fb);
|
||||
gctx->read.st_fb = NULL;
|
||||
gctx->draw.num_atts = 0;
|
||||
gctx->draw.attachment_mask = 0x0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -628,7 +625,7 @@ init_surface_geometry(_EGLSurface *surf)
|
|||
{
|
||||
struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
|
||||
|
||||
return gsurf->native->validate(gsurf->native, NULL, 0,
|
||||
return gsurf->native->validate(gsurf->native, 0x0,
|
||||
&gsurf->sequence_number, NULL,
|
||||
&gsurf->base.Width, &gsurf->base.Height);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,9 +52,7 @@ struct egl_g3d_display {
|
|||
|
||||
struct egl_g3d_buffer {
|
||||
struct st_framebuffer *st_fb;
|
||||
EGLint num_atts;
|
||||
enum native_attachment native_atts[NUM_NATIVE_ATTACHMENTS];
|
||||
uint st_atts[NUM_NATIVE_ATTACHMENTS];
|
||||
uint attachment_mask;
|
||||
};
|
||||
|
||||
struct egl_g3d_context {
|
||||
|
|
|
|||
|
|
@ -64,18 +64,18 @@ struct native_surface {
|
|||
boolean (*flush_frontbuffer)(struct native_surface *nsurf);
|
||||
|
||||
/**
|
||||
* 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 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.
|
||||
* Validate the buffers of the surface. textures, if not NULL, points to an
|
||||
* array of size NUM_NATIVE_ATTACHMENTS and the returned textures are owned
|
||||
* by 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
|
||||
* might change in the future.
|
||||
* If this function is called multiple times with different attachment
|
||||
* masks, those not listed in the latest call might be destroyed. This
|
||||
* behavior might change in the future.
|
||||
*/
|
||||
boolean (*validate)(struct native_surface *nsurf,
|
||||
const enum native_attachment *natts,
|
||||
unsigned num_natts,
|
||||
boolean (*validate)(struct native_surface *nsurf, uint attachment_mask,
|
||||
unsigned int *seq_num, struct pipe_texture **textures,
|
||||
int *width, int *height);
|
||||
|
||||
|
|
@ -211,6 +211,15 @@ struct native_display_modeset {
|
|||
const struct native_mode *nmode);
|
||||
};
|
||||
|
||||
/**
|
||||
* Test whether an attachment is set in the mask.
|
||||
*/
|
||||
static INLINE boolean
|
||||
native_attachment_mask_test(uint mask, enum native_attachment att)
|
||||
{
|
||||
return !!(mask & (1 << att));
|
||||
}
|
||||
|
||||
const char *
|
||||
native_get_name(void);
|
||||
|
||||
|
|
|
|||
|
|
@ -33,9 +33,7 @@
|
|||
#include "native_kms.h"
|
||||
|
||||
static boolean
|
||||
kms_surface_validate(struct native_surface *nsurf,
|
||||
const enum native_attachment *natts,
|
||||
unsigned num_natts,
|
||||
kms_surface_validate(struct native_surface *nsurf, uint attachment_mask,
|
||||
unsigned int *seq_num, struct pipe_texture **textures,
|
||||
int *width, int *height)
|
||||
{
|
||||
|
|
@ -43,12 +41,9 @@ kms_surface_validate(struct native_surface *nsurf,
|
|||
struct kms_display *kdpy = ksurf->kdpy;
|
||||
struct pipe_screen *screen = kdpy->base.screen;
|
||||
struct pipe_texture templ, *ptex;
|
||||
int i;
|
||||
|
||||
if (num_natts) {
|
||||
if (textures)
|
||||
memset(textures, 0, sizeof(*textures) * num_natts);
|
||||
int att;
|
||||
|
||||
if (attachment_mask) {
|
||||
memset(&templ, 0, sizeof(templ));
|
||||
templ.target = PIPE_TEXTURE_2D;
|
||||
templ.last_level = 0;
|
||||
|
|
@ -62,17 +57,21 @@ kms_surface_validate(struct native_surface *nsurf,
|
|||
}
|
||||
|
||||
/* create textures */
|
||||
for (i = 0; i < num_natts; i++) {
|
||||
enum native_attachment natt = natts[i];
|
||||
for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) {
|
||||
/* delay the allocation */
|
||||
if (!native_attachment_mask_test(attachment_mask, att))
|
||||
continue;
|
||||
|
||||
ptex = ksurf->textures[natt];
|
||||
ptex = ksurf->textures[att];
|
||||
if (!ptex) {
|
||||
ptex = screen->texture_create(screen, &templ);
|
||||
ksurf->textures[natt] = ptex;
|
||||
ksurf->textures[att] = ptex;
|
||||
}
|
||||
|
||||
if (textures)
|
||||
pipe_texture_reference(&textures[i], ptex);
|
||||
if (textures) {
|
||||
textures[att] = NULL;
|
||||
pipe_texture_reference(&textures[att], ptex);
|
||||
}
|
||||
}
|
||||
|
||||
if (seq_num)
|
||||
|
|
@ -113,7 +112,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, NULL);
|
||||
kms_surface_validate(&ksurf->base, 1 << natt, NULL, NULL, NULL, NULL);
|
||||
if (!ksurf->textures[natt])
|
||||
return FALSE;
|
||||
|
||||
|
|
|
|||
|
|
@ -134,22 +134,18 @@ dri2_surface_swap_buffers(struct native_surface *nsurf)
|
|||
}
|
||||
|
||||
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)
|
||||
dri2_surface_validate(struct native_surface *nsurf, uint attachment_mask,
|
||||
unsigned int *seq_num, struct pipe_texture **textures,
|
||||
int *width, int *height)
|
||||
{
|
||||
struct dri2_surface *dri2surf = dri2_surface(nsurf);
|
||||
struct dri2_display *dri2dpy = dri2surf->dri2dpy;
|
||||
unsigned int dri2atts[NUM_NATIVE_ATTACHMENTS];
|
||||
EGLint texture_indices[NUM_NATIVE_ATTACHMENTS];
|
||||
struct pipe_texture templ;
|
||||
struct x11_drawable_buffer *xbufs;
|
||||
int num_ins, num_outs, i;
|
||||
int num_ins, num_outs, att, i;
|
||||
|
||||
if (num_natts) {
|
||||
if (attachment_mask) {
|
||||
memset(&templ, 0, sizeof(templ));
|
||||
templ.target = PIPE_TEXTURE_2D;
|
||||
templ.last_level = 0;
|
||||
|
|
@ -160,24 +156,27 @@ dri2_surface_validate(struct native_surface *nsurf,
|
|||
templ.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET;
|
||||
|
||||
if (textures)
|
||||
memset(textures, 0, sizeof(*textures) * num_natts);
|
||||
memset(textures, 0, sizeof(*textures) * NUM_NATIVE_ATTACHMENTS);
|
||||
}
|
||||
|
||||
/* create textures for pbuffer */
|
||||
if (dri2surf->type == DRI2_SURFACE_TYPE_PBUFFER) {
|
||||
struct pipe_screen *screen = dri2dpy->base.screen;
|
||||
|
||||
for (i = 0; i < num_natts; i++) {
|
||||
enum native_attachment natt = natts[i];
|
||||
struct pipe_texture *ptex = dri2surf->pbuffer_textures[natt];
|
||||
for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) {
|
||||
struct pipe_texture *ptex = dri2surf->pbuffer_textures[att];
|
||||
|
||||
/* delay the allocation */
|
||||
if (!native_attachment_mask_test(attachment_mask, att))
|
||||
continue;
|
||||
|
||||
if (!ptex) {
|
||||
ptex = screen->texture_create(screen, &templ);
|
||||
dri2surf->pbuffer_textures[natt] = ptex;
|
||||
dri2surf->pbuffer_textures[att] = ptex;
|
||||
}
|
||||
|
||||
if (textures)
|
||||
pipe_texture_reference(&textures[i], ptex);
|
||||
pipe_texture_reference(&textures[att], ptex);
|
||||
}
|
||||
|
||||
if (seq_num)
|
||||
|
|
@ -190,34 +189,34 @@ dri2_surface_validate(struct native_surface *nsurf,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++)
|
||||
texture_indices[i] = -1;
|
||||
|
||||
/* prepare the attachments */
|
||||
num_ins = num_natts;
|
||||
for (i = 0; i < num_natts; i++) {
|
||||
unsigned int dri2att;
|
||||
num_ins = 0;
|
||||
for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) {
|
||||
if (native_attachment_mask_test(attachment_mask, att)) {
|
||||
unsigned int dri2att;
|
||||
|
||||
switch (natts[i]) {
|
||||
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;
|
||||
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++;
|
||||
}
|
||||
dri2atts[i] = dri2att;
|
||||
texture_indices[natts[i]] = i;
|
||||
}
|
||||
|
||||
dri2surf->have_back = FALSE;
|
||||
|
|
@ -266,13 +265,13 @@ dri2_surface_validate(struct native_surface *nsurf,
|
|||
break;
|
||||
}
|
||||
|
||||
if (!desc || texture_indices[natt] < 0 ||
|
||||
(textures && textures[texture_indices[natt]])) {
|
||||
if (!desc || !native_attachment_mask_test(attachment_mask, natt) ||
|
||||
(textures && textures[natt])) {
|
||||
if (!desc)
|
||||
_eglLog(_EGL_WARNING, "unknown buffer %d", xbuf->attachment);
|
||||
else if (texture_indices[natt] < 0)
|
||||
else if (!native_attachment_mask_test(attachment_mask, natt))
|
||||
_eglLog(_EGL_WARNING, "unexpected buffer %d", xbuf->attachment);
|
||||
else if (textures && textures[texture_indices[natt]])
|
||||
else
|
||||
_eglLog(_EGL_WARNING, "both real and fake front buffers are listed");
|
||||
continue;
|
||||
}
|
||||
|
|
@ -284,7 +283,7 @@ dri2_surface_validate(struct native_surface *nsurf,
|
|||
desc, xbuf->pitch, xbuf->name);
|
||||
if (ptex) {
|
||||
/* the caller owns the textures */
|
||||
textures[texture_indices[natt]] = ptex;
|
||||
textures[natt] = ptex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -289,27 +289,21 @@ ximage_surface_update_geometry(struct native_surface *nsurf)
|
|||
}
|
||||
|
||||
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)
|
||||
ximage_surface_validate(struct native_surface *nsurf, uint attachment_mask,
|
||||
unsigned int *seq_num, struct pipe_texture **textures,
|
||||
int *width, int *height)
|
||||
{
|
||||
struct ximage_surface *xsurf = ximage_surface(nsurf);
|
||||
boolean new_buffers = FALSE, error = FALSE;
|
||||
unsigned i;
|
||||
boolean new_buffers = FALSE;
|
||||
int att;
|
||||
|
||||
ximage_surface_update_geometry(&xsurf->base);
|
||||
|
||||
if (textures)
|
||||
memset(textures, 0, sizeof(*textures) * num_natts);
|
||||
for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) {
|
||||
struct ximage_buffer *xbuf = &xsurf->buffers[att];
|
||||
|
||||
for (i = 0; i < num_natts; i++) {
|
||||
enum native_attachment natt = natts[i];
|
||||
struct ximage_buffer *xbuf = &xsurf->buffers[natt];
|
||||
|
||||
if (!xbuf)
|
||||
/* delay the allocation */
|
||||
if (!native_attachment_mask_test(attachment_mask, att))
|
||||
continue;
|
||||
|
||||
/* reallocate the texture */
|
||||
|
|
@ -317,7 +311,7 @@ ximage_surface_validate(struct native_surface *nsurf,
|
|||
xsurf->width != xbuf->texture->width0 ||
|
||||
xsurf->height != xbuf->texture->height0) {
|
||||
new_buffers = TRUE;
|
||||
if (ximage_surface_alloc_buffer(&xsurf->base, natt)) {
|
||||
if (ximage_surface_alloc_buffer(&xsurf->base, att)) {
|
||||
/* update ximage */
|
||||
if (xbuf->ximage) {
|
||||
xbuf->ximage->width = xbuf->transfer->width;
|
||||
|
|
@ -327,19 +321,10 @@ ximage_surface_validate(struct native_surface *nsurf,
|
|||
}
|
||||
}
|
||||
|
||||
/* 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;
|
||||
if (textures) {
|
||||
textures[att] = NULL;
|
||||
pipe_texture_reference(&textures[att], xbuf->texture);
|
||||
}
|
||||
|
||||
if (textures)
|
||||
pipe_texture_reference(&textures[i], xbuf->texture);
|
||||
}
|
||||
|
||||
/* increase the sequence number so that caller knows */
|
||||
|
|
@ -353,7 +338,7 @@ ximage_surface_validate(struct native_surface *nsurf,
|
|||
if (height)
|
||||
*height = xsurf->height;
|
||||
|
||||
return !error;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue