From a73ae3d5eb8419feab5aea26573aa41b72f941eb Mon Sep 17 00:00:00 2001 From: Keith Whitwell Date: Fri, 2 May 2008 16:46:31 +0100 Subject: gallium: Add texture usage flags, special-case allocation of display targets For many envirionments it's necessary to allocate display targets in a window-system friendly manner. Add facilities so that a driver can tell if a texture is likely to be used to generate a display surface and if use special allocation paths if necessary. Hook up softpipe to call into the winsys->surface_alloc_storage() routine in this case, though we probably want to change that interface slightly also. --- src/gallium/drivers/softpipe/sp_texture.c | 101 ++++++++++++++++++++---------- src/gallium/drivers/softpipe/sp_texture.h | 2 +- 2 files changed, 68 insertions(+), 35 deletions(-) (limited to 'src/gallium/drivers') diff --git a/src/gallium/drivers/softpipe/sp_texture.c b/src/gallium/drivers/softpipe/sp_texture.c index 2b31cd4f25..599ff2ac45 100644 --- a/src/gallium/drivers/softpipe/sp_texture.c +++ b/src/gallium/drivers/softpipe/sp_texture.c @@ -52,40 +52,87 @@ static unsigned minify( unsigned d ) } -static void -softpipe_texture_layout(struct softpipe_texture * spt) +/* Conventional allocation path for non-display textures: + */ +static boolean +softpipe_texture_layout(struct pipe_screen *screen, + struct softpipe_texture * spt) { + struct pipe_winsys *ws = screen->winsys; struct pipe_texture *pt = &spt->base; unsigned level; unsigned width = pt->width[0]; unsigned height = pt->height[0]; unsigned depth = pt->depth[0]; - spt->buffer_size = 0; + unsigned buffer_size = 0; for (level = 0; level <= pt->last_level; level++) { pt->width[level] = width; pt->height[level] = height; pt->depth[level] = depth; + spt->pitch[level] = width; - spt->level_offset[level] = spt->buffer_size; + spt->level_offset[level] = buffer_size; - spt->buffer_size += ((pt->compressed) ? MAX2(1, height/4) : height) * - ((pt->target == PIPE_TEXTURE_CUBE) ? 6 : depth) * - width * pt->cpp; + buffer_size += (((pt->compressed) ? MAX2(1, height/4) : height) * + ((pt->target == PIPE_TEXTURE_CUBE) ? 6 : depth) * + width * pt->cpp); width = minify(width); height = minify(height); depth = minify(depth); } + + spt->buffer = ws->buffer_create(ws, 32, + PIPE_BUFFER_USAGE_PIXEL, + buffer_size); + + return spt->buffer != NULL; } + +/* Hack it up to use the old winsys->surface_alloc_storage() + * method for now: + */ +static boolean +softpipe_displaytarget_layout(struct pipe_screen *screen, + struct softpipe_texture * spt) +{ + struct pipe_winsys *ws = screen->winsys; + struct pipe_surface surf; + unsigned flags = (PIPE_BUFFER_USAGE_CPU_READ | + PIPE_BUFFER_USAGE_CPU_WRITE | + PIPE_BUFFER_USAGE_GPU_READ | + PIPE_BUFFER_USAGE_GPU_WRITE); + + + memset(&surf, 0, sizeof(surf)); + + ws->surface_alloc_storage( ws, + &surf, + spt->base.width[0], + spt->base.height[0], + spt->base.format, + flags); + + /* Now extract the goodies: + */ + spt->buffer = surf.buffer; + spt->pitch[0] = surf.pitch; + + return spt->buffer != NULL; +} + + + + + static struct pipe_texture * softpipe_texture_create(struct pipe_screen *screen, const struct pipe_texture *templat) { - struct pipe_winsys *ws = screen->winsys; struct softpipe_texture *spt = CALLOC_STRUCT(softpipe_texture); if (!spt) return NULL; @@ -94,19 +141,21 @@ softpipe_texture_create(struct pipe_screen *screen, spt->base.refcount = 1; spt->base.screen = screen; - softpipe_texture_layout(spt); - - spt->buffer = ws->buffer_create(ws, 32, - PIPE_BUFFER_USAGE_PIXEL, - spt->buffer_size); - if (!spt->buffer) { - FREE(spt); - return NULL; + if (spt->base.tex_usage & PIPE_TEXTURE_USAGE_DISPLAY_TARGET) { + if (!softpipe_displaytarget_layout(screen, spt)) + goto fail; } - + else { + if (!softpipe_texture_layout(screen, spt)) + goto fail; + } + assert(spt->base.refcount == 1); - return &spt->base; + + fail: + FREE(spt); + return NULL; } @@ -178,22 +227,6 @@ softpipe_get_tex_surface(struct pipe_screen *screen, assert(face == 0); assert(zslice == 0); } - - if (usage & (PIPE_BUFFER_USAGE_CPU_WRITE | - PIPE_BUFFER_USAGE_GPU_WRITE)) { - /* XXX if writing to the texture, invalidate the texcache entries!!! - * - * Actually, no. Flushing dependent contexts is still done - * explicitly and separately. Hardware drivers won't insert - * FLUSH commands into a command stream at this point, - * neither should softpipe try to flush caches. - * - * Those contexts could be living in separate threads & doing - * all sorts of unrelated stuff... Context<->texture - * dependency tracking needs to happen elsewhere. - */ - /* assert(0); */ - } } return ps; } diff --git a/src/gallium/drivers/softpipe/sp_texture.h b/src/gallium/drivers/softpipe/sp_texture.h index 2ba093320d..779a9d8fc9 100644 --- a/src/gallium/drivers/softpipe/sp_texture.h +++ b/src/gallium/drivers/softpipe/sp_texture.h @@ -42,11 +42,11 @@ struct softpipe_texture struct pipe_texture base; unsigned long level_offset[PIPE_MAX_TEXTURE_LEVELS]; + unsigned long pitch[PIPE_MAX_TEXTURE_LEVELS]; /* The data is held here: */ struct pipe_buffer *buffer; - unsigned long buffer_size; }; -- cgit v1.2.3