summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith Whitwell <keith@tungstengraphics.com>2008-05-02 16:46:31 +0100
committerKeith Whitwell <keith@tungstengraphics.com>2008-05-02 16:46:31 +0100
commita73ae3d5eb8419feab5aea26573aa41b72f941eb (patch)
tree74fa3e6004be0ef5d266680bd57c2fccec521a4e
parent4a159132082429d5492f5298c2ccb0df551c9f65 (diff)
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.
-rw-r--r--src/gallium/drivers/softpipe/sp_texture.c101
-rw-r--r--src/gallium/drivers/softpipe/sp_texture.h2
-rw-r--r--src/gallium/include/pipe/p_state.h6
-rw-r--r--src/mesa/state_tracker/st_atom_pixeltransfer.c3
-rw-r--r--src/mesa/state_tracker/st_cb_bitmap.c6
-rw-r--r--src/mesa/state_tracker/st_cb_drawpixels.c6
-rw-r--r--src/mesa/state_tracker/st_cb_fbo.c23
-rw-r--r--src/mesa/state_tracker/st_cb_texture.c10
-rw-r--r--src/mesa/state_tracker/st_texture.c4
-rw-r--r--src/mesa/state_tracker/st_texture.h3
10 files changed, 111 insertions, 53 deletions
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;
};
diff --git a/src/gallium/include/pipe/p_state.h b/src/gallium/include/pipe/p_state.h
index 277ee4b319..d7565dff96 100644
--- a/src/gallium/include/pipe/p_state.h
+++ b/src/gallium/include/pipe/p_state.h
@@ -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:
*/
diff --git a/src/mesa/state_tracker/st_atom_pixeltransfer.c b/src/mesa/state_tracker/st_atom_pixeltransfer.c
index 0c32d53c4a..e500ac8684 100644
--- a/src/mesa/state_tracker/st_atom_pixeltransfer.c
+++ b/src/mesa/state_tracker/st_atom_pixeltransfer.c
@@ -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;
}
diff --git a/src/mesa/state_tracker/st_cb_bitmap.c b/src/mesa/state_tracker/st_cb_bitmap.c
index 873b765c2c..f816e59104 100644
--- a/src/mesa/state_tracker/st_cb_bitmap.c
+++ b/src/mesa/state_tracker/st_cb_bitmap.c
@@ -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.
diff --git a/src/mesa/state_tracker/st_cb_drawpixels.c b/src/mesa/state_tracker/st_cb_drawpixels.c
index 9ae53c95f8..8c775ad886 100644
--- a/src/mesa/state_tracker/st_cb_drawpixels.c
+++ b/src/mesa/state_tracker/st_cb_drawpixels.c
@@ -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;
diff --git a/src/mesa/state_tracker/st_cb_fbo.c b/src/mesa/state_tracker/st_cb_fbo.c
index b174714171..21d61e2163 100644
--- a/src/mesa/state_tracker/st_cb_fbo.c
+++ b/src/mesa/state_tracker/st_cb_fbo.c
@@ -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 );
diff --git a/src/mesa/state_tracker/st_cb_texture.c b/src/mesa/state_tracker/st_cb_texture.c
index 4cca3364c1..06caa06e77 100644
--- a/src/mesa/state_tracker/st_cb_texture.c
+++ b/src/mesa/state_tracker/st_cb_texture.c
@@ -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;
diff --git a/src/mesa/state_tracker/st_texture.c b/src/mesa/state_tracker/st_texture.c
index d6268fc80c..2b3742d4e5 100644
--- a/src/mesa/state_tracker/st_texture.c
+++ b/src/mesa/state_tracker/st_texture.c
@@ -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);
diff --git a/src/mesa/state_tracker/st_texture.h b/src/mesa/state_tracker/st_texture.h
index f6d5733e21..6a9f08ec6b 100644
--- a/src/mesa/state_tracker/st_texture.h
+++ b/src/mesa/state_tracker/st_texture.h
@@ -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.