gallium: No longer allow CPU mapping surfaces directly.

Instead, a new pipe_transfer object has to be created and mapped for
transferring data between the CPU and a texture. This gives the driver more
flexibility for textures in address spaces that aren't CPU accessible.

This is a first pass; softpipe/xlib builds and runs glxgears, but it only shows
a black window. Looks like something's off related to the Z buffer, so the
depth test always fails.
This commit is contained in:
Michel Dänzer
2009-02-05 19:41:18 +01:00
parent e0c3b4970d
commit 4617981ec7
31 changed files with 793 additions and 678 deletions

View File

@@ -26,7 +26,7 @@
**************************************************************************/
/**
* Framebuffer/surface tile caching.
* Texture tile caching.
*
* Author:
* Brian Paul
@@ -52,7 +52,8 @@ struct softpipe_tile_cache
{
struct pipe_screen *screen;
struct pipe_surface *surface; /**< the surface we're caching */
void *surface_map;
struct pipe_transfer *transfer;
void *transfer_map;
struct pipe_texture *texture; /**< if caching a texture */
struct softpipe_cached_tile entries[NUM_ENTRIES];
uint clear_flags[(MAX_WIDTH / TILE_SIZE) * (MAX_HEIGHT / TILE_SIZE) / 32];
@@ -60,8 +61,8 @@ struct softpipe_tile_cache
uint clear_val;
boolean depth_stencil; /** Is the surface a depth/stencil format? */
struct pipe_surface *tex_surf;
void *tex_surf_map;
struct pipe_transfer *tex_trans;
void *tex_trans_map;
int tex_face, tex_level, tex_z;
struct softpipe_cached_tile tile; /**< scratch tile for clears */
@@ -131,16 +132,19 @@ sp_create_tile_cache( struct pipe_screen *screen )
void
sp_destroy_tile_cache(struct softpipe_tile_cache *tc)
{
struct pipe_screen *screen;
uint pos;
for (pos = 0; pos < NUM_ENTRIES; pos++) {
/*assert(tc->entries[pos].x < 0);*/
}
if (tc->surface) {
pipe_surface_reference(&tc->surface, NULL);
if (tc->transfer) {
screen = tc->transfer->texture->screen;
screen->tex_transfer_release(screen, &tc->transfer);
}
if (tc->tex_surf) {
pipe_surface_reference(&tc->tex_surf, NULL);
if (tc->tex_trans) {
screen = tc->tex_trans->texture->screen;
screen->tex_transfer_release(screen, &tc->tex_trans);
}
FREE( tc );
@@ -154,34 +158,42 @@ void
sp_tile_cache_set_surface(struct softpipe_tile_cache *tc,
struct pipe_surface *ps)
{
struct pipe_screen *screen = ps->texture->screen;
assert(!tc->texture);
if (tc->surface_map) {
tc->screen->surface_unmap(tc->screen, tc->surface);
tc->surface_map = NULL;
if (tc->transfer) {
if (ps->texture == tc->transfer->texture &&
ps->face == tc->transfer->face &&
ps->level == tc->transfer->level &&
ps->zslice == tc->transfer->zslice)
return;
if (tc->transfer_map) {
tc->screen->transfer_unmap(tc->screen, tc->transfer);
tc->transfer_map = NULL;
}
screen->tex_transfer_release(screen, &tc->transfer);
}
pipe_surface_reference(&tc->surface, ps);
tc->transfer = screen->get_tex_transfer(screen, ps->texture, ps->face,
ps->level, ps->zslice,
PIPE_TRANSFER_READ_WRITE,
0, 0, ps->width, ps->height);
if (tc->surface) {
if (tc->surface_map) /* XXX: this is always NULL!? */
tc->surface_map = tc->screen->surface_map(tc->screen, tc->surface,
PIPE_BUFFER_USAGE_CPU_READ |
PIPE_BUFFER_USAGE_CPU_WRITE);
tc->depth_stencil = (ps->format == PIPE_FORMAT_S8Z24_UNORM ||
ps->format == PIPE_FORMAT_X8Z24_UNORM ||
ps->format == PIPE_FORMAT_Z24S8_UNORM ||
ps->format == PIPE_FORMAT_Z24X8_UNORM ||
ps->format == PIPE_FORMAT_Z16_UNORM ||
ps->format == PIPE_FORMAT_Z32_UNORM ||
ps->format == PIPE_FORMAT_S8_UNORM);
}
tc->depth_stencil = (ps->format == PIPE_FORMAT_S8Z24_UNORM ||
ps->format == PIPE_FORMAT_X8Z24_UNORM ||
ps->format == PIPE_FORMAT_Z24S8_UNORM ||
ps->format == PIPE_FORMAT_Z24X8_UNORM ||
ps->format == PIPE_FORMAT_Z16_UNORM ||
ps->format == PIPE_FORMAT_Z32_UNORM ||
ps->format == PIPE_FORMAT_S8_UNORM);
}
/**
* Return the surface being cached.
* Return the transfer being cached.
*/
struct pipe_surface *
sp_tile_cache_get_surface(struct softpipe_tile_cache *tc)
@@ -191,30 +203,27 @@ sp_tile_cache_get_surface(struct softpipe_tile_cache *tc)
void
sp_tile_cache_map_surfaces(struct softpipe_tile_cache *tc)
sp_tile_cache_map_transfers(struct softpipe_tile_cache *tc)
{
if (tc->surface && !tc->surface_map)
tc->surface_map = tc->screen->surface_map(tc->screen, tc->surface,
PIPE_BUFFER_USAGE_CPU_WRITE |
PIPE_BUFFER_USAGE_CPU_READ);
if (tc->transfer && !tc->transfer_map)
tc->transfer_map = tc->screen->transfer_map(tc->screen, tc->transfer);
if (tc->tex_surf && !tc->tex_surf_map)
tc->tex_surf_map = tc->screen->surface_map(tc->screen, tc->tex_surf,
PIPE_BUFFER_USAGE_CPU_READ);
if (tc->tex_trans && !tc->tex_trans_map)
tc->tex_trans_map = tc->screen->transfer_map(tc->screen, tc->tex_trans);
}
void
sp_tile_cache_unmap_surfaces(struct softpipe_tile_cache *tc)
sp_tile_cache_unmap_transfers(struct softpipe_tile_cache *tc)
{
if (tc->surface_map) {
tc->screen->surface_unmap(tc->screen, tc->surface);
tc->surface_map = NULL;
if (tc->transfer_map) {
tc->screen->transfer_unmap(tc->screen, tc->transfer);
tc->transfer_map = NULL;
}
if (tc->tex_surf_map) {
tc->screen->surface_unmap(tc->screen, tc->tex_surf);
tc->tex_surf_map = NULL;
if (tc->tex_trans_map) {
tc->screen->transfer_unmap(tc->screen, tc->tex_trans);
tc->tex_trans_map = NULL;
}
}
@@ -227,17 +236,18 @@ sp_tile_cache_set_texture(struct pipe_context *pipe,
struct softpipe_tile_cache *tc,
struct pipe_texture *texture)
{
struct pipe_screen *screen = texture->screen;
uint i;
assert(!tc->surface);
assert(!tc->transfer);
pipe_texture_reference(&tc->texture, texture);
if (tc->tex_surf_map) {
tc->screen->surface_unmap(tc->screen, tc->tex_surf);
tc->tex_surf_map = NULL;
if (tc->tex_trans_map) {
tc->screen->transfer_unmap(tc->screen, tc->tex_trans);
tc->tex_trans_map = NULL;
}
pipe_surface_reference(&tc->tex_surf, NULL);
screen->tex_transfer_release(screen, &tc->tex_trans);
/* mark as entries as invalid/empty */
/* XXX we should try to avoid this when the teximage hasn't changed */
@@ -328,9 +338,9 @@ static void
sp_tile_cache_flush_clear(struct pipe_context *pipe,
struct softpipe_tile_cache *tc)
{
struct pipe_surface *ps = tc->surface;
const uint w = tc->surface->width;
const uint h = tc->surface->height;
struct pipe_transfer *ps = tc->transfer;
const uint w = tc->transfer->width;
const uint h = tc->transfer->height;
uint x, y;
uint numCleared = 0;
@@ -359,18 +369,18 @@ sp_tile_cache_flush_clear(struct pipe_context *pipe,
/**
* Flush the tile cache: write all dirty tiles back to the surface.
* Flush the tile cache: write all dirty tiles back to the transfer.
* any tiles "flagged" as cleared will be "really" cleared.
*/
void
sp_flush_tile_cache(struct softpipe_context *softpipe,
struct softpipe_tile_cache *tc)
{
struct pipe_surface *ps = tc->surface;
struct pipe_transfer *ps = tc->transfer;
int inuse = 0, pos;
if (ps) {
/* caching a drawing surface */
/* caching a drawing transfer */
for (pos = 0; pos < NUM_ENTRIES; pos++) {
struct softpipe_cached_tile *tile = tc->entries + pos;
if (tile->x >= 0) {
@@ -415,7 +425,7 @@ struct softpipe_cached_tile *
sp_get_cached_tile(struct softpipe_context *softpipe,
struct softpipe_tile_cache *tc, int x, int y)
{
struct pipe_surface *ps = tc->surface;
struct pipe_transfer *ps = tc->transfer;
/* tile pos in framebuffer: */
const int tile_x = x & ~(TILE_SIZE - 1);
@@ -456,7 +466,7 @@ sp_get_cached_tile(struct softpipe_context *softpipe,
clear_clear_flag(tc->clear_flags, x, y);
}
else {
/* get new tile data from surface */
/* get new tile data from transfer */
if (tc->depth_stencil) {
pipe_get_tile_raw(ps,
tile->x, tile->y, TILE_SIZE, TILE_SIZE,
@@ -523,28 +533,30 @@ sp_get_cached_tile_tex(struct softpipe_context *sp,
level != tile->level) {
/* cache miss */
/* check if we need to get a new surface */
if (!tc->tex_surf ||
/* check if we need to get a new transfer */
if (!tc->tex_trans ||
tc->tex_face != face ||
tc->tex_level != level ||
tc->tex_z != z) {
/* get new surface (view into texture) */
/* get new transfer (view into texture) */
if (tc->tex_surf_map)
tc->screen->surface_unmap(tc->screen, tc->tex_surf);
if (tc->tex_trans_map)
tc->screen->transfer_unmap(tc->screen, tc->tex_trans);
screen->tex_transfer_release(screen, &tc->tex_trans);
tc->tex_surf = screen->get_tex_surface(screen, tc->texture, face, level, z,
PIPE_BUFFER_USAGE_CPU_READ);
tc->tex_surf_map = screen->surface_map(screen, tc->tex_surf,
PIPE_BUFFER_USAGE_CPU_READ);
tc->tex_trans = screen->get_tex_transfer(screen, tc->texture, face, level, z,
PIPE_TRANSFER_READ, 0, 0,
tc->texture->width[level],
tc->texture->height[level]);
tc->tex_trans_map = screen->transfer_map(screen, tc->tex_trans);
tc->tex_face = face;
tc->tex_level = level;
tc->tex_z = z;
}
/* get tile from the surface (view into texture) */
pipe_get_tile_rgba(tc->tex_surf,
/* get tile from the transfer (view into texture) */
pipe_get_tile_rgba(tc->tex_trans,
tile_x, tile_y, TILE_SIZE, TILE_SIZE,
(float *) tile->data.color);
tile->x = tile_x;
@@ -571,7 +583,7 @@ sp_tile_cache_clear(struct softpipe_tile_cache *tc, uint clearValue)
tc->clear_val = clearValue;
switch (tc->surface->format) {
switch (tc->transfer->format) {
case PIPE_FORMAT_R8G8B8A8_UNORM:
r = (clearValue >> 24) & 0xff;
g = (clearValue >> 16) & 0xff;