mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-01-26 10:00:22 +01:00
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.
This commit is contained in:
parent
4a15913208
commit
a73ae3d5eb
10 changed files with 111 additions and 53 deletions
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -284,6 +284,10 @@ struct pipe_surface
|
|||
};
|
||||
|
||||
|
||||
#define PIPE_TEXTURE_USAGE_RENDER_TARGET 0x1
|
||||
#define PIPE_TEXTURE_USAGE_DISPLAY_TARGET 0x2 /* ie a backbuffer */
|
||||
#define PIPE_TEXTURE_USAGE_SAMPLER 0x4
|
||||
|
||||
/**
|
||||
* Texture object.
|
||||
*/
|
||||
|
|
@ -300,7 +304,7 @@ struct pipe_texture
|
|||
unsigned last_level:8; /**< Index of last mipmap level present/defined */
|
||||
unsigned compressed:1;
|
||||
|
||||
unsigned usage;
|
||||
unsigned tex_usage; /* PIPE_TEXTURE_USAGE_* */
|
||||
|
||||
/* These are also refcounted:
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -126,7 +126,8 @@ create_color_map_texture(GLcontext *ctx)
|
|||
|
||||
/* create texture for color map/table */
|
||||
pt = st_texture_create(ctx->st, PIPE_TEXTURE_2D, format, 0,
|
||||
texSize, texSize, 1, 0);
|
||||
texSize, texSize, 1, 0,
|
||||
PIPE_TEXTURE_USAGE_SAMPLER);
|
||||
return pt;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -321,7 +321,8 @@ make_bitmap_texture(GLcontext *ctx, GLsizei width, GLsizei height,
|
|||
* Create texture to hold bitmap pattern.
|
||||
*/
|
||||
pt = st_texture_create(ctx->st, PIPE_TEXTURE_2D, ctx->st->bitmap.tex_format,
|
||||
0, width, height, 1, 0);
|
||||
0, width, height, 1, 0,
|
||||
PIPE_TEXTURE_USAGE_SAMPLER);
|
||||
if (!pt) {
|
||||
_mesa_unmap_bitmap_pbo(ctx, unpack);
|
||||
return NULL;
|
||||
|
|
@ -539,7 +540,8 @@ reset_cache(struct st_context *st)
|
|||
cache->texture = st_texture_create(st, PIPE_TEXTURE_2D,
|
||||
st->bitmap.tex_format, 0,
|
||||
BITMAP_CACHE_WIDTH, BITMAP_CACHE_HEIGHT,
|
||||
1, 0);
|
||||
1, 0,
|
||||
PIPE_TEXTURE_USAGE_SAMPLER);
|
||||
|
||||
/* Map the texture surface.
|
||||
* Subsequent glBitmap calls will write into the texture image.
|
||||
|
|
|
|||
|
|
@ -346,7 +346,8 @@ make_texture(struct st_context *st,
|
|||
return NULL;
|
||||
|
||||
pt = st_texture_create(st, PIPE_TEXTURE_2D, pipeFormat, 0, width, height,
|
||||
1, 0);
|
||||
1, 0,
|
||||
PIPE_TEXTURE_USAGE_SAMPLER);
|
||||
if (!pt) {
|
||||
_mesa_unmap_drawpix_pbo(ctx, unpack);
|
||||
return NULL;
|
||||
|
|
@ -994,7 +995,8 @@ st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy,
|
|||
}
|
||||
|
||||
pt = st_texture_create(ctx->st, PIPE_TEXTURE_2D, texFormat, 0,
|
||||
width, height, 1, 0);
|
||||
width, height, 1, 0,
|
||||
PIPE_TEXTURE_USAGE_SAMPLER);
|
||||
if (!pt)
|
||||
return;
|
||||
|
||||
|
|
|
|||
|
|
@ -90,8 +90,8 @@ st_renderbuffer_alloc_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
|
|||
{
|
||||
struct pipe_context *pipe = ctx->st->pipe;
|
||||
struct st_renderbuffer *strb = st_renderbuffer(rb);
|
||||
|
||||
struct pipe_texture template, *texture;
|
||||
unsigned surface_usage;
|
||||
|
||||
/* Free the old surface (and texture if we hold the last
|
||||
* reference):
|
||||
|
|
@ -117,10 +117,15 @@ st_renderbuffer_alloc_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
|
|||
template.height[0] = height;
|
||||
template.depth[0] = 1;
|
||||
template.last_level = 0;
|
||||
template.usage = (PIPE_BUFFER_USAGE_CPU_WRITE |
|
||||
PIPE_BUFFER_USAGE_CPU_READ |
|
||||
PIPE_BUFFER_USAGE_GPU_WRITE |
|
||||
PIPE_BUFFER_USAGE_GPU_READ);
|
||||
template.tex_usage = (PIPE_TEXTURE_USAGE_DISPLAY_TARGET |
|
||||
PIPE_TEXTURE_USAGE_RENDER_TARGET);
|
||||
|
||||
/* Probably need dedicated flags for surface usage too:
|
||||
*/
|
||||
surface_usage = (PIPE_BUFFER_USAGE_GPU_READ |
|
||||
PIPE_BUFFER_USAGE_GPU_WRITE |
|
||||
PIPE_BUFFER_USAGE_CPU_READ |
|
||||
PIPE_BUFFER_USAGE_CPU_WRITE);
|
||||
|
||||
texture = pipe->screen->texture_create( pipe->screen,
|
||||
&template );
|
||||
|
|
@ -137,11 +142,13 @@ st_renderbuffer_alloc_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
|
|||
* to tell the driver to go ahead and allocate the buffer, even
|
||||
* if HW doesn't support the format.
|
||||
*/
|
||||
template.usage = (PIPE_BUFFER_USAGE_CPU_READ |
|
||||
PIPE_BUFFER_USAGE_CPU_WRITE);
|
||||
template.tex_usage = 0;
|
||||
surface_usage = (PIPE_BUFFER_USAGE_CPU_READ |
|
||||
PIPE_BUFFER_USAGE_CPU_WRITE);
|
||||
|
||||
texture = pipe->screen->texture_create( pipe->screen,
|
||||
&template );
|
||||
|
||||
}
|
||||
|
||||
if (!texture)
|
||||
|
|
@ -150,7 +157,7 @@ st_renderbuffer_alloc_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
|
|||
strb->surface = pipe->screen->get_tex_surface( pipe->screen,
|
||||
texture,
|
||||
0, 0, 0,
|
||||
template.usage );
|
||||
surface_usage );
|
||||
|
||||
pipe_texture_reference( &texture, NULL );
|
||||
|
||||
|
|
|
|||
|
|
@ -333,7 +333,9 @@ guess_and_alloc_texture(struct st_context *st,
|
|||
width,
|
||||
height,
|
||||
depth,
|
||||
comp_byte);
|
||||
comp_byte,
|
||||
( PIPE_TEXTURE_USAGE_RENDER_TARGET |
|
||||
PIPE_TEXTURE_USAGE_SAMPLER ));
|
||||
|
||||
DBG("%s - success\n", __FUNCTION__);
|
||||
}
|
||||
|
|
@ -1501,7 +1503,11 @@ st_finalize_texture(GLcontext *ctx,
|
|||
firstImage->base.Width2,
|
||||
firstImage->base.Height2,
|
||||
firstImage->base.Depth2,
|
||||
comp_byte);
|
||||
comp_byte,
|
||||
|
||||
( PIPE_TEXTURE_USAGE_RENDER_TARGET |
|
||||
PIPE_TEXTURE_USAGE_SAMPLER ));
|
||||
|
||||
if (!stObj->pt) {
|
||||
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
|
||||
return GL_FALSE;
|
||||
|
|
|
|||
|
|
@ -75,7 +75,8 @@ st_texture_create(struct st_context *st,
|
|||
GLuint width0,
|
||||
GLuint height0,
|
||||
GLuint depth0,
|
||||
GLuint compress_byte)
|
||||
GLuint compress_byte,
|
||||
GLuint usage )
|
||||
{
|
||||
struct pipe_texture pt, *newtex;
|
||||
struct pipe_screen *screen = st->pipe->screen;
|
||||
|
|
@ -98,6 +99,7 @@ st_texture_create(struct st_context *st,
|
|||
pt.depth[0] = depth0;
|
||||
pt.compressed = compress_byte ? 1 : 0;
|
||||
pt.cpp = pt.compressed ? compress_byte : st_sizeof_format(format);
|
||||
pt.tex_usage = usage;
|
||||
|
||||
newtex = screen->texture_create(screen, &pt);
|
||||
|
||||
|
|
|
|||
|
|
@ -105,7 +105,8 @@ st_texture_create(struct st_context *st,
|
|||
GLuint width0,
|
||||
GLuint height0,
|
||||
GLuint depth0,
|
||||
GLuint compress_byte);
|
||||
GLuint compress_byte,
|
||||
GLuint tex_usage );
|
||||
|
||||
|
||||
/* Check if an image fits into an existing texture object.
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue