/** * Get a tile from the cache. * \param x, y position of tile, in pixels */ struct softpipe_cached_tile * sp_find_cached_tile(struct softpipe_tile_cache *tc, union tile_address addr ) { struct pipe_transfer *pt = tc->transfer; /* cache pos/entry: */ const int pos = CACHE_POS(addr.bits.x, addr.bits.y); struct softpipe_cached_tile *tile = tc->entries[pos]; if (!tile) { tile = sp_alloc_tile(tc); tc->entries[pos] = tile; } if (addr.value != tc->tile_addrs[pos].value) { assert(pt->resource); if (tc->tile_addrs[pos].bits.invalid == 0) { /* put dirty tile back in framebuffer */ if (tc->depth_stencil) { pipe_put_tile_raw(tc->pipe, pt, tc->tile_addrs[pos].bits.x * TILE_SIZE, tc->tile_addrs[pos].bits.y * TILE_SIZE, TILE_SIZE, TILE_SIZE, tile->data.depth32, 0/*STRIDE*/); } else { if (util_format_is_pure_uint(tc->surface->format)) { pipe_put_tile_ui_format(tc->pipe, pt, tc->tile_addrs[pos].bits.x * TILE_SIZE, tc->tile_addrs[pos].bits.y * TILE_SIZE, TILE_SIZE, TILE_SIZE, tc->surface->format, (unsigned *) tile->data.colorui128); } else if (util_format_is_pure_sint(tc->surface->format)) { pipe_put_tile_i_format(tc->pipe, pt, tc->tile_addrs[pos].bits.x * TILE_SIZE, tc->tile_addrs[pos].bits.y * TILE_SIZE, TILE_SIZE, TILE_SIZE, tc->surface->format, (int *) tile->data.colori128); } else { pipe_put_tile_rgba_format(tc->pipe, pt, tc->tile_addrs[pos].bits.x * TILE_SIZE, tc->tile_addrs[pos].bits.y * TILE_SIZE, TILE_SIZE, TILE_SIZE, tc->surface->format, (float *) tile->data.color); } } } tc->tile_addrs[pos] = addr; if (is_clear_flag_set(tc->clear_flags, addr)) { /* don't get tile from framebuffer, just clear it */ if (tc->depth_stencil) { clear_tile(tile, pt->resource->format, tc->clear_val); } else { clear_tile_rgba(tile, pt->resource->format, &tc->clear_color); } clear_clear_flag(tc->clear_flags, addr); } else { /* get new tile data from transfer */ if (tc->depth_stencil) { pipe_get_tile_raw(tc->pipe, pt, tc->tile_addrs[pos].bits.x * TILE_SIZE, tc->tile_addrs[pos].bits.y * TILE_SIZE, TILE_SIZE, TILE_SIZE, tile->data.depth32, 0/*STRIDE*/); } else { if (util_format_is_pure_uint(tc->surface->format)) { pipe_get_tile_ui_format(tc->pipe, pt, tc->tile_addrs[pos].bits.x * TILE_SIZE, tc->tile_addrs[pos].bits.y * TILE_SIZE, TILE_SIZE, TILE_SIZE, tc->surface->format, (unsigned *) tile->data.colorui128); } else if (util_format_is_pure_sint(tc->surface->format)) { pipe_get_tile_i_format(tc->pipe, pt, tc->tile_addrs[pos].bits.x * TILE_SIZE, tc->tile_addrs[pos].bits.y * TILE_SIZE, TILE_SIZE, TILE_SIZE, tc->surface->format, (int *) tile->data.colori128); } else { pipe_get_tile_rgba_format(tc->pipe, pt, tc->tile_addrs[pos].bits.x * TILE_SIZE, tc->tile_addrs[pos].bits.y * TILE_SIZE, TILE_SIZE, TILE_SIZE, tc->surface->format, (float *) tile->data.color); } } } } tc->last_tile = tile; tc->last_tile_addr = addr; return tile; }
/** * Similar to sp_get_cached_tile() but for textures. * Tiles are read-only and indexed with more params. */ const struct softpipe_tex_cached_tile * sp_find_cached_tile_tex(struct softpipe_tex_tile_cache *tc, union tex_tile_address addr ) { struct softpipe_tex_cached_tile *tile; boolean zs = util_format_is_depth_or_stencil(tc->format); tile = tc->entries + tex_cache_pos( addr ); if (addr.value != tile->addr.value) { /* cache miss. Most misses are because we've invaldiated the * texture cache previously -- most commonly on binding a new * texture. Currently we effectively flush the cache on texture * bind. */ #if 0 _debug_printf("miss at %u: x=%d y=%d z=%d face=%d level=%d\n" " tile %u: x=%d y=%d z=%d face=%d level=%d\n", pos, x/TILE_SIZE, y/TILE_SIZE, z, face, level, pos, tile->addr.bits.x, tile->addr.bits.y, tile->z, tile->face, tile->level); #endif /* check if we need to get a new transfer */ if (!tc->tex_trans || tc->tex_face != addr.bits.face || tc->tex_level != addr.bits.level || tc->tex_z != addr.bits.z) { /* get new transfer (view into texture) */ unsigned width, height, layer; if (tc->tex_trans) { if (tc->tex_trans_map) { tc->pipe->transfer_unmap(tc->pipe, tc->tex_trans); tc->tex_trans_map = NULL; } tc->pipe->transfer_destroy(tc->pipe, tc->tex_trans); tc->tex_trans = NULL; } width = u_minify(tc->texture->width0, addr.bits.level); if (tc->texture->target == PIPE_TEXTURE_1D_ARRAY) { height = tc->texture->array_size; layer = 0; } else { height = u_minify(tc->texture->height0, addr.bits.level); layer = addr.bits.face + addr.bits.z; } tc->tex_trans = pipe_get_transfer(tc->pipe, tc->texture, addr.bits.level, layer, PIPE_TRANSFER_READ | PIPE_TRANSFER_UNSYNCHRONIZED, 0, 0, width, height); tc->tex_trans_map = tc->pipe->transfer_map(tc->pipe, tc->tex_trans); tc->tex_face = addr.bits.face; tc->tex_level = addr.bits.level; tc->tex_z = addr.bits.z; } /* Get tile from the transfer (view into texture), explicitly passing * the image format. */ if (!zs && util_format_is_pure_uint(tc->format)) { pipe_get_tile_ui_format(tc->pipe, tc->tex_trans, addr.bits.x * TILE_SIZE, addr.bits.y * TILE_SIZE, TILE_SIZE, TILE_SIZE, tc->format, (unsigned *) tile->data.colorui); } else if (!zs && util_format_is_pure_sint(tc->format)) { pipe_get_tile_i_format(tc->pipe, tc->tex_trans, addr.bits.x * TILE_SIZE, addr.bits.y * TILE_SIZE, TILE_SIZE, TILE_SIZE, tc->format, (int *) tile->data.colori); } else { pipe_get_tile_rgba_format(tc->pipe, tc->tex_trans, addr.bits.x * TILE_SIZE, addr.bits.y * TILE_SIZE, TILE_SIZE, TILE_SIZE, tc->format, (float *) tile->data.color); } tile->addr = addr; } tc->last_tile = tile; return tile; }