2007-10-19 10:08:24 -06:00
|
|
|
/**************************************************************************
|
|
|
|
*
|
|
|
|
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
|
|
|
|
* All Rights Reserved.
|
|
|
|
*
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
|
|
* copy of this software and associated documentation files (the
|
|
|
|
* "Software"), to deal in the Software without restriction, including
|
|
|
|
* without limitation the rights to use, copy, modify, merge, publish,
|
|
|
|
* distribute, sub license, and/or sell copies of the Software, and to
|
|
|
|
* permit persons to whom the Software is furnished to do so, subject to
|
|
|
|
* the following conditions:
|
|
|
|
*
|
|
|
|
* The above copyright notice and this permission notice (including the
|
|
|
|
* next paragraph) shall be included in all copies or substantial portions
|
|
|
|
* of the Software.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
|
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
|
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
|
|
|
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
|
|
|
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
|
|
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
|
|
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
*
|
|
|
|
**************************************************************************/
|
|
|
|
|
|
|
|
/**
|
2009-02-05 19:41:18 +01:00
|
|
|
* Texture tile caching.
|
2007-10-19 10:08:24 -06:00
|
|
|
*
|
|
|
|
* Author:
|
|
|
|
* Brian Paul
|
|
|
|
*/
|
|
|
|
|
2007-10-29 16:59:57 +00:00
|
|
|
#include "pipe/p_inlines.h"
|
2008-08-24 17:48:55 -06:00
|
|
|
#include "util/u_memory.h"
|
|
|
|
#include "util/u_tile.h"
|
2007-10-19 10:08:24 -06:00
|
|
|
#include "sp_context.h"
|
|
|
|
#include "sp_surface.h"
|
2008-06-20 15:58:19 -06:00
|
|
|
#include "sp_texture.h"
|
2007-10-19 10:08:24 -06:00
|
|
|
#include "sp_tile_cache.h"
|
|
|
|
|
2009-02-16 18:45:58 -07:00
|
|
|
#define NUM_ENTRIES 50
|
2007-10-19 10:08:24 -06:00
|
|
|
|
|
|
|
|
|
|
|
/** XXX move these */
|
2009-09-22 15:35:05 -06:00
|
|
|
#define MAX_WIDTH 4096
|
|
|
|
#define MAX_HEIGHT 4096
|
2007-10-19 10:08:24 -06:00
|
|
|
|
|
|
|
|
|
|
|
struct softpipe_tile_cache
|
|
|
|
{
|
2008-05-01 11:07:21 +01:00
|
|
|
struct pipe_screen *screen;
|
2007-10-27 09:26:59 -06:00
|
|
|
struct pipe_surface *surface; /**< the surface we're caching */
|
2009-02-05 19:41:18 +01:00
|
|
|
struct pipe_transfer *transfer;
|
|
|
|
void *transfer_map;
|
2007-11-30 20:48:03 +01:00
|
|
|
struct pipe_texture *texture; /**< if caching a texture */
|
2007-10-19 10:08:24 -06:00
|
|
|
struct softpipe_cached_tile entries[NUM_ENTRIES];
|
|
|
|
uint clear_flags[(MAX_WIDTH / TILE_SIZE) * (MAX_HEIGHT / TILE_SIZE) / 32];
|
2009-04-06 15:31:58 -06:00
|
|
|
float clear_color[4]; /**< for color bufs */
|
|
|
|
uint clear_val; /**< for z+stencil, or packed color clear value */
|
|
|
|
boolean depth_stencil; /**< Is the surface a depth/stencil format? */
|
2007-12-07 21:21:58 -07:00
|
|
|
|
2009-02-05 19:41:18 +01:00
|
|
|
struct pipe_transfer *tex_trans;
|
|
|
|
void *tex_trans_map;
|
2007-12-07 21:21:58 -07:00
|
|
|
int tex_face, tex_level, tex_z;
|
2007-12-15 09:49:20 -07:00
|
|
|
|
|
|
|
struct softpipe_cached_tile tile; /**< scratch tile for clears */
|
2007-10-19 10:08:24 -06:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Return the position in the cache for the tile that contains win pos (x,y).
|
|
|
|
* We currently use a direct mapped cache so this is like a hack key.
|
|
|
|
* At some point we should investige something more sophisticated, like
|
|
|
|
* a LRU replacement policy.
|
|
|
|
*/
|
|
|
|
#define CACHE_POS(x, y) \
|
|
|
|
(((x) / TILE_SIZE + ((y) / TILE_SIZE) * 5) % NUM_ENTRIES)
|
|
|
|
|
|
|
|
|
|
|
|
|
2007-12-07 20:13:10 -07:00
|
|
|
/**
|
|
|
|
* Is the tile at (x,y) in cleared state?
|
|
|
|
*/
|
2007-12-07 15:32:13 -07:00
|
|
|
static INLINE uint
|
2007-10-19 10:08:24 -06:00
|
|
|
is_clear_flag_set(const uint *bitvec, int x, int y)
|
|
|
|
{
|
|
|
|
int pos, bit;
|
|
|
|
x /= TILE_SIZE;
|
|
|
|
y /= TILE_SIZE;
|
|
|
|
pos = y * (MAX_WIDTH / TILE_SIZE) + x;
|
2007-10-23 18:49:19 -06:00
|
|
|
assert(pos / 32 < (MAX_WIDTH / TILE_SIZE) * (MAX_HEIGHT / TILE_SIZE) / 32);
|
2007-10-19 10:08:24 -06:00
|
|
|
bit = bitvec[pos / 32] & (1 << (pos & 31));
|
|
|
|
return bit;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-12-07 20:13:10 -07:00
|
|
|
/**
|
|
|
|
* Mark the tile at (x,y) as not cleared.
|
|
|
|
*/
|
2007-12-07 15:32:13 -07:00
|
|
|
static INLINE void
|
2007-10-19 10:08:24 -06:00
|
|
|
clear_clear_flag(uint *bitvec, int x, int y)
|
|
|
|
{
|
|
|
|
int pos;
|
|
|
|
x /= TILE_SIZE;
|
|
|
|
y /= TILE_SIZE;
|
|
|
|
pos = y * (MAX_WIDTH / TILE_SIZE) + x;
|
2007-10-23 18:49:19 -06:00
|
|
|
assert(pos / 32 < (MAX_WIDTH / TILE_SIZE) * (MAX_HEIGHT / TILE_SIZE) / 32);
|
2007-10-19 10:08:24 -06:00
|
|
|
bitvec[pos / 32] &= ~(1 << (pos & 31));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
struct softpipe_tile_cache *
|
2008-05-01 11:07:21 +01:00
|
|
|
sp_create_tile_cache( struct pipe_screen *screen )
|
2007-10-19 10:08:24 -06:00
|
|
|
{
|
|
|
|
struct softpipe_tile_cache *tc;
|
|
|
|
uint pos;
|
2009-09-23 10:50:38 -06:00
|
|
|
int maxLevels, maxTexSize;
|
|
|
|
|
|
|
|
/* sanity checking: max sure MAX_WIDTH/HEIGHT >= largest texture image */
|
|
|
|
maxLevels = screen->get_param(screen, PIPE_CAP_MAX_TEXTURE_2D_LEVELS);
|
|
|
|
maxTexSize = 1 << (maxLevels - 1);
|
|
|
|
assert(MAX_WIDTH >= maxTexSize);
|
2007-10-19 10:08:24 -06:00
|
|
|
|
2007-10-29 16:20:45 +00:00
|
|
|
tc = CALLOC_STRUCT( softpipe_tile_cache );
|
2007-10-19 10:08:24 -06:00
|
|
|
if (tc) {
|
2008-05-01 11:07:21 +01:00
|
|
|
tc->screen = screen;
|
2007-10-19 10:08:24 -06:00
|
|
|
for (pos = 0; pos < NUM_ENTRIES; pos++) {
|
|
|
|
tc->entries[pos].x =
|
|
|
|
tc->entries[pos].y = -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return tc;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
sp_destroy_tile_cache(struct softpipe_tile_cache *tc)
|
|
|
|
{
|
2009-02-05 19:41:18 +01:00
|
|
|
struct pipe_screen *screen;
|
2007-10-19 10:08:24 -06:00
|
|
|
uint pos;
|
2007-12-27 19:18:12 -07:00
|
|
|
|
2007-10-19 10:08:24 -06:00
|
|
|
for (pos = 0; pos < NUM_ENTRIES; pos++) {
|
2008-05-02 09:26:17 -06:00
|
|
|
/*assert(tc->entries[pos].x < 0);*/
|
2007-12-27 19:18:12 -07:00
|
|
|
}
|
2009-02-05 19:41:18 +01:00
|
|
|
if (tc->transfer) {
|
|
|
|
screen = tc->transfer->texture->screen;
|
2009-03-04 11:58:48 +01:00
|
|
|
screen->tex_transfer_destroy(tc->transfer);
|
2007-12-27 19:18:12 -07:00
|
|
|
}
|
2009-02-05 19:41:18 +01:00
|
|
|
if (tc->tex_trans) {
|
|
|
|
screen = tc->tex_trans->texture->screen;
|
2009-03-04 11:58:48 +01:00
|
|
|
screen->tex_transfer_destroy(tc->tex_trans);
|
2007-10-19 10:08:24 -06:00
|
|
|
}
|
2007-12-27 19:18:12 -07:00
|
|
|
|
2007-10-29 16:20:45 +00:00
|
|
|
FREE( tc );
|
2007-10-19 10:08:24 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-12-07 20:13:10 -07:00
|
|
|
/**
|
|
|
|
* Specify the surface to cache.
|
|
|
|
*/
|
2007-10-20 15:18:02 -06:00
|
|
|
void
|
2007-12-07 15:32:13 -07:00
|
|
|
sp_tile_cache_set_surface(struct softpipe_tile_cache *tc,
|
2007-10-27 09:26:59 -06:00
|
|
|
struct pipe_surface *ps)
|
2007-10-20 15:18:02 -06:00
|
|
|
{
|
2007-12-07 20:13:10 -07:00
|
|
|
assert(!tc->texture);
|
|
|
|
|
2009-02-05 19:41:18 +01:00
|
|
|
if (tc->transfer) {
|
2009-02-12 20:13:09 +01:00
|
|
|
struct pipe_screen *screen = tc->transfer->texture->screen;
|
|
|
|
|
2009-02-12 19:43:43 +01:00
|
|
|
if (ps == tc->surface)
|
2009-02-05 19:41:18 +01:00
|
|
|
return;
|
2007-12-07 12:30:35 +01:00
|
|
|
|
2009-02-05 19:41:18 +01:00
|
|
|
if (tc->transfer_map) {
|
2009-03-04 11:58:48 +01:00
|
|
|
screen->transfer_unmap(screen, tc->transfer);
|
2009-02-05 19:41:18 +01:00
|
|
|
tc->transfer_map = NULL;
|
|
|
|
}
|
|
|
|
|
2009-03-04 11:58:48 +01:00
|
|
|
screen->tex_transfer_destroy(tc->transfer);
|
2009-03-18 09:55:00 -06:00
|
|
|
tc->transfer = NULL;
|
2007-12-07 15:46:10 -07:00
|
|
|
}
|
2007-12-07 12:30:35 +01:00
|
|
|
|
2009-02-12 19:43:43 +01:00
|
|
|
tc->surface = ps;
|
|
|
|
|
2009-02-12 20:13:09 +01:00
|
|
|
if (ps) {
|
|
|
|
struct pipe_screen *screen = ps->texture->screen;
|
2007-12-07 15:32:13 -07:00
|
|
|
|
2009-02-12 20:13:09 +01:00
|
|
|
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);
|
2007-12-12 14:45:22 -07:00
|
|
|
|
2007-12-07 20:13:10 -07:00
|
|
|
tc->depth_stencil = (ps->format == PIPE_FORMAT_S8Z24_UNORM ||
|
2008-08-07 15:05:13 -06:00
|
|
|
ps->format == PIPE_FORMAT_X8Z24_UNORM ||
|
2008-05-30 15:07:58 -06:00
|
|
|
ps->format == PIPE_FORMAT_Z24S8_UNORM ||
|
2008-08-07 15:05:13 -06:00
|
|
|
ps->format == PIPE_FORMAT_Z24X8_UNORM ||
|
2007-12-07 20:13:10 -07:00
|
|
|
ps->format == PIPE_FORMAT_Z16_UNORM ||
|
|
|
|
ps->format == PIPE_FORMAT_Z32_UNORM ||
|
2008-04-30 16:41:53 -06:00
|
|
|
ps->format == PIPE_FORMAT_S8_UNORM);
|
2007-12-07 20:13:10 -07:00
|
|
|
}
|
2007-10-20 15:18:02 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-12-07 20:13:10 -07:00
|
|
|
/**
|
2009-02-05 19:41:18 +01:00
|
|
|
* Return the transfer being cached.
|
2007-12-07 20:13:10 -07:00
|
|
|
*/
|
2007-10-27 09:26:59 -06:00
|
|
|
struct pipe_surface *
|
2007-12-07 15:32:13 -07:00
|
|
|
sp_tile_cache_get_surface(struct softpipe_tile_cache *tc)
|
2007-10-23 18:49:19 -06:00
|
|
|
{
|
|
|
|
return tc->surface;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-01-10 17:44:04 +01:00
|
|
|
void
|
2009-02-05 19:41:18 +01:00
|
|
|
sp_tile_cache_map_transfers(struct softpipe_tile_cache *tc)
|
2008-01-10 17:44:04 +01:00
|
|
|
{
|
2009-02-05 19:41:18 +01:00
|
|
|
if (tc->transfer && !tc->transfer_map)
|
|
|
|
tc->transfer_map = tc->screen->transfer_map(tc->screen, tc->transfer);
|
|
|
|
|
|
|
|
if (tc->tex_trans && !tc->tex_trans_map)
|
|
|
|
tc->tex_trans_map = tc->screen->transfer_map(tc->screen, tc->tex_trans);
|
2008-01-10 17:44:04 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2009-02-05 19:41:18 +01:00
|
|
|
sp_tile_cache_unmap_transfers(struct softpipe_tile_cache *tc)
|
2008-01-10 17:44:04 +01:00
|
|
|
{
|
2009-02-05 19:41:18 +01:00
|
|
|
if (tc->transfer_map) {
|
|
|
|
tc->screen->transfer_unmap(tc->screen, tc->transfer);
|
|
|
|
tc->transfer_map = NULL;
|
2008-01-10 17:44:04 +01:00
|
|
|
}
|
|
|
|
|
2009-02-05 19:41:18 +01:00
|
|
|
if (tc->tex_trans_map) {
|
|
|
|
tc->screen->transfer_unmap(tc->screen, tc->tex_trans);
|
|
|
|
tc->tex_trans_map = NULL;
|
2008-01-10 17:44:04 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-12-07 20:13:10 -07:00
|
|
|
/**
|
|
|
|
* Specify the texture to cache.
|
|
|
|
*/
|
2007-10-21 18:06:35 -06:00
|
|
|
void
|
2008-02-20 11:15:59 -07:00
|
|
|
sp_tile_cache_set_texture(struct pipe_context *pipe,
|
|
|
|
struct softpipe_tile_cache *tc,
|
2007-11-30 20:48:03 +01:00
|
|
|
struct pipe_texture *texture)
|
2007-10-21 18:06:35 -06:00
|
|
|
{
|
2007-10-22 09:37:26 -06:00
|
|
|
uint i;
|
|
|
|
|
2009-02-05 19:41:18 +01:00
|
|
|
assert(!tc->transfer);
|
2007-12-07 20:13:10 -07:00
|
|
|
|
2008-02-26 19:31:22 -07:00
|
|
|
pipe_texture_reference(&tc->texture, texture);
|
2007-10-22 09:37:26 -06:00
|
|
|
|
2009-03-18 10:17:48 -06:00
|
|
|
if (tc->tex_trans) {
|
|
|
|
struct pipe_screen *screen = tc->tex_trans->texture->screen;
|
2009-02-12 20:13:09 +01:00
|
|
|
|
|
|
|
if (tc->tex_trans_map) {
|
2009-03-04 11:58:48 +01:00
|
|
|
screen->transfer_unmap(screen, tc->tex_trans);
|
2009-02-12 20:13:09 +01:00
|
|
|
tc->tex_trans_map = NULL;
|
|
|
|
}
|
|
|
|
|
2009-03-04 11:58:48 +01:00
|
|
|
screen->tex_transfer_destroy(tc->tex_trans);
|
2009-03-18 10:17:48 -06:00
|
|
|
tc->tex_trans = NULL;
|
2008-01-10 17:44:04 +01:00
|
|
|
}
|
2007-12-07 21:21:58 -07:00
|
|
|
|
2007-10-22 09:37:26 -06:00
|
|
|
/* mark as entries as invalid/empty */
|
|
|
|
/* XXX we should try to avoid this when the teximage hasn't changed */
|
|
|
|
for (i = 0; i < NUM_ENTRIES; i++) {
|
|
|
|
tc->entries[i].x = -1;
|
|
|
|
}
|
2007-12-07 21:21:58 -07:00
|
|
|
|
|
|
|
tc->tex_face = -1; /* any invalid value here */
|
2007-10-21 18:06:35 -06:00
|
|
|
}
|
2007-10-20 15:18:02 -06:00
|
|
|
|
2007-10-19 10:08:24 -06:00
|
|
|
|
2007-12-07 20:13:10 -07:00
|
|
|
/**
|
|
|
|
* Set pixels in a tile to the given clear color/value, float.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
clear_tile_rgba(struct softpipe_cached_tile *tile,
|
|
|
|
enum pipe_format format,
|
|
|
|
const float clear_value[4])
|
2007-12-07 15:32:13 -07:00
|
|
|
{
|
2007-12-07 20:13:10 -07:00
|
|
|
if (clear_value[0] == 0.0 &&
|
|
|
|
clear_value[1] == 0.0 &&
|
|
|
|
clear_value[2] == 0.0 &&
|
|
|
|
clear_value[3] == 0.0) {
|
|
|
|
memset(tile->data.color, 0, sizeof(tile->data.color));
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
uint i, j;
|
|
|
|
for (i = 0; i < TILE_SIZE; i++) {
|
|
|
|
for (j = 0; j < TILE_SIZE; j++) {
|
|
|
|
tile->data.color[i][j][0] = clear_value[0];
|
|
|
|
tile->data.color[i][j][1] = clear_value[1];
|
|
|
|
tile->data.color[i][j][2] = clear_value[2];
|
|
|
|
tile->data.color[i][j][3] = clear_value[3];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2007-12-07 15:32:13 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2007-12-07 20:13:10 -07:00
|
|
|
* Set a tile to a solid value/color.
|
2007-12-07 15:32:13 -07:00
|
|
|
*/
|
|
|
|
static void
|
2007-12-07 16:46:30 -07:00
|
|
|
clear_tile(struct softpipe_cached_tile *tile,
|
|
|
|
enum pipe_format format,
|
2007-12-07 20:13:10 -07:00
|
|
|
uint clear_value)
|
2007-12-07 15:32:13 -07:00
|
|
|
{
|
|
|
|
uint i, j;
|
|
|
|
|
2007-12-16 10:00:51 -07:00
|
|
|
switch (pf_get_size(format)) {
|
|
|
|
case 1:
|
2007-12-07 20:13:10 -07:00
|
|
|
memset(tile->data.any, 0, TILE_SIZE * TILE_SIZE);
|
2007-12-07 15:32:13 -07:00
|
|
|
break;
|
2007-12-16 10:00:51 -07:00
|
|
|
case 2:
|
2007-12-07 20:13:10 -07:00
|
|
|
if (clear_value == 0) {
|
|
|
|
memset(tile->data.any, 0, 2 * TILE_SIZE * TILE_SIZE);
|
2007-12-07 15:32:13 -07:00
|
|
|
}
|
2007-12-07 20:13:10 -07:00
|
|
|
else {
|
2007-12-07 15:32:13 -07:00
|
|
|
for (i = 0; i < TILE_SIZE; i++) {
|
|
|
|
for (j = 0; j < TILE_SIZE; j++) {
|
2008-01-17 13:39:14 +09:00
|
|
|
tile->data.depth16[i][j] = (ushort) clear_value;
|
2007-12-07 15:32:13 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2007-12-16 10:00:51 -07:00
|
|
|
case 4:
|
2007-12-07 20:13:10 -07:00
|
|
|
if (clear_value == 0) {
|
|
|
|
memset(tile->data.any, 0, 4 * TILE_SIZE * TILE_SIZE);
|
2007-12-07 15:32:13 -07:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
for (i = 0; i < TILE_SIZE; i++) {
|
|
|
|
for (j = 0; j < TILE_SIZE; j++) {
|
2007-12-07 20:13:10 -07:00
|
|
|
tile->data.color32[i][j] = clear_value;
|
2007-12-07 15:32:13 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2007-12-16 10:00:51 -07:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
assert(0);
|
2007-12-07 15:32:13 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2007-12-07 15:46:10 -07:00
|
|
|
* Actually clear the tiles which were flagged as being in a clear state.
|
2007-12-07 15:32:13 -07:00
|
|
|
*/
|
2007-12-07 15:46:10 -07:00
|
|
|
static void
|
2007-12-07 15:32:13 -07:00
|
|
|
sp_tile_cache_flush_clear(struct pipe_context *pipe,
|
|
|
|
struct softpipe_tile_cache *tc)
|
|
|
|
{
|
2009-02-12 19:38:35 +01:00
|
|
|
struct pipe_transfer *pt = tc->transfer;
|
2009-02-05 19:41:18 +01:00
|
|
|
const uint w = tc->transfer->width;
|
|
|
|
const uint h = tc->transfer->height;
|
2007-12-07 15:32:13 -07:00
|
|
|
uint x, y;
|
|
|
|
uint numCleared = 0;
|
|
|
|
|
2007-12-15 09:49:20 -07:00
|
|
|
/* clear the scratch tile to the clear value */
|
2009-02-12 19:38:35 +01:00
|
|
|
clear_tile(&tc->tile, pt->format, tc->clear_val);
|
2007-12-07 15:32:13 -07:00
|
|
|
|
|
|
|
/* push the tile to all positions marked as clear */
|
|
|
|
for (y = 0; y < h; y += TILE_SIZE) {
|
|
|
|
for (x = 0; x < w; x += TILE_SIZE) {
|
|
|
|
if (is_clear_flag_set(tc->clear_flags, x, y)) {
|
2009-02-12 19:38:35 +01:00
|
|
|
pipe_put_tile_raw(pt,
|
2008-05-02 09:26:17 -06:00
|
|
|
x, y, TILE_SIZE, TILE_SIZE,
|
|
|
|
tc->tile.data.color32, 0/*STRIDE*/);
|
2007-12-07 15:32:13 -07:00
|
|
|
|
|
|
|
/* do this? */
|
|
|
|
clear_clear_flag(tc->clear_flags, x, y);
|
|
|
|
|
|
|
|
numCleared++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#if 0
|
2008-02-06 14:37:49 +09:00
|
|
|
debug_printf("num cleared: %u\n", numCleared);
|
2007-12-07 15:32:13 -07:00
|
|
|
#endif
|
2007-10-19 10:08:24 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-12-07 15:46:10 -07:00
|
|
|
/**
|
2009-02-05 19:41:18 +01:00
|
|
|
* Flush the tile cache: write all dirty tiles back to the transfer.
|
2007-12-07 15:46:10 -07:00
|
|
|
* any tiles "flagged" as cleared will be "really" cleared.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
sp_flush_tile_cache(struct softpipe_context *softpipe,
|
|
|
|
struct softpipe_tile_cache *tc)
|
|
|
|
{
|
2009-02-12 19:38:35 +01:00
|
|
|
struct pipe_transfer *pt = tc->transfer;
|
2007-12-07 15:46:10 -07:00
|
|
|
int inuse = 0, pos;
|
|
|
|
|
2009-02-12 19:38:35 +01:00
|
|
|
if (pt) {
|
2009-02-05 19:41:18 +01:00
|
|
|
/* caching a drawing transfer */
|
2008-02-20 13:24:52 -07:00
|
|
|
for (pos = 0; pos < NUM_ENTRIES; pos++) {
|
|
|
|
struct softpipe_cached_tile *tile = tc->entries + pos;
|
|
|
|
if (tile->x >= 0) {
|
|
|
|
if (tc->depth_stencil) {
|
2009-02-12 19:38:35 +01:00
|
|
|
pipe_put_tile_raw(pt,
|
2008-05-02 09:26:17 -06:00
|
|
|
tile->x, tile->y, TILE_SIZE, TILE_SIZE,
|
|
|
|
tile->data.depth32, 0/*STRIDE*/);
|
2008-02-20 13:24:52 -07:00
|
|
|
}
|
|
|
|
else {
|
2009-02-12 19:38:35 +01:00
|
|
|
pipe_put_tile_rgba(pt,
|
2008-02-20 13:24:52 -07:00
|
|
|
tile->x, tile->y, TILE_SIZE, TILE_SIZE,
|
|
|
|
(float *) tile->data.color);
|
|
|
|
}
|
|
|
|
tile->x = tile->y = -1; /* mark as empty */
|
|
|
|
inuse++;
|
2007-12-07 20:13:10 -07:00
|
|
|
}
|
2007-12-07 15:46:10 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
#if TILE_CLEAR_OPTIMIZATION
|
2008-02-20 13:24:52 -07:00
|
|
|
sp_tile_cache_flush_clear(&softpipe->pipe, tc);
|
2007-12-07 15:46:10 -07:00
|
|
|
#endif
|
2008-02-20 13:24:52 -07:00
|
|
|
}
|
|
|
|
else if (tc->texture) {
|
2008-05-02 09:26:17 -06:00
|
|
|
/* caching a texture, mark all entries as empty */
|
2008-02-20 13:24:52 -07:00
|
|
|
for (pos = 0; pos < NUM_ENTRIES; pos++) {
|
|
|
|
tc->entries[pos].x = -1;
|
|
|
|
}
|
|
|
|
tc->tex_face = -1;
|
|
|
|
}
|
2007-12-07 15:46:10 -07:00
|
|
|
|
|
|
|
#if 0
|
2008-02-06 14:37:49 +09:00
|
|
|
debug_printf("flushed tiles in use: %d\n", inuse);
|
2007-12-07 15:46:10 -07:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get a tile from the cache.
|
|
|
|
* \param x, y position of tile, in pixels
|
|
|
|
*/
|
2007-10-19 10:08:24 -06:00
|
|
|
struct softpipe_cached_tile *
|
2007-10-25 18:50:15 -06:00
|
|
|
sp_get_cached_tile(struct softpipe_context *softpipe,
|
|
|
|
struct softpipe_tile_cache *tc, int x, int y)
|
2007-10-19 10:08:24 -06:00
|
|
|
{
|
2009-02-12 19:38:35 +01:00
|
|
|
struct pipe_transfer *pt = tc->transfer;
|
2007-10-19 10:08:24 -06:00
|
|
|
|
|
|
|
/* tile pos in framebuffer: */
|
|
|
|
const int tile_x = x & ~(TILE_SIZE - 1);
|
|
|
|
const int tile_y = y & ~(TILE_SIZE - 1);
|
|
|
|
|
|
|
|
/* cache pos/entry: */
|
|
|
|
const int pos = CACHE_POS(x, y);
|
|
|
|
struct softpipe_cached_tile *tile = tc->entries + pos;
|
|
|
|
|
|
|
|
if (tile_x != tile->x ||
|
|
|
|
tile_y != tile->y) {
|
|
|
|
|
|
|
|
if (tile->x != -1) {
|
|
|
|
/* put dirty tile back in framebuffer */
|
2007-12-07 20:13:10 -07:00
|
|
|
if (tc->depth_stencil) {
|
2009-02-12 19:38:35 +01:00
|
|
|
pipe_put_tile_raw(pt,
|
2008-01-31 13:32:29 -07:00
|
|
|
tile->x, tile->y, TILE_SIZE, TILE_SIZE,
|
|
|
|
tile->data.depth32, 0/*STRIDE*/);
|
2007-12-07 20:13:10 -07:00
|
|
|
}
|
|
|
|
else {
|
2009-02-12 19:38:35 +01:00
|
|
|
pipe_put_tile_rgba(pt,
|
2008-01-14 16:17:01 +01:00
|
|
|
tile->x, tile->y, TILE_SIZE, TILE_SIZE,
|
|
|
|
(float *) tile->data.color);
|
2007-12-07 20:13:10 -07:00
|
|
|
}
|
2007-10-19 10:08:24 -06:00
|
|
|
}
|
|
|
|
|
2007-12-07 15:32:13 -07:00
|
|
|
tile->x = tile_x;
|
|
|
|
tile->y = tile_y;
|
|
|
|
|
2007-10-23 18:49:19 -06:00
|
|
|
if (is_clear_flag_set(tc->clear_flags, x, y)) {
|
2007-10-20 15:18:02 -06:00
|
|
|
/* don't get tile from framebuffer, just clear it */
|
2007-12-07 20:13:10 -07:00
|
|
|
if (tc->depth_stencil) {
|
2009-02-12 19:38:35 +01:00
|
|
|
clear_tile(tile, pt->format, tc->clear_val);
|
2007-12-07 20:13:10 -07:00
|
|
|
}
|
|
|
|
else {
|
2009-02-12 19:38:35 +01:00
|
|
|
clear_tile_rgba(tile, pt->format, tc->clear_color);
|
2007-12-07 20:13:10 -07:00
|
|
|
}
|
2007-10-19 10:08:24 -06:00
|
|
|
clear_clear_flag(tc->clear_flags, x, y);
|
|
|
|
}
|
|
|
|
else {
|
2009-02-05 19:41:18 +01:00
|
|
|
/* get new tile data from transfer */
|
2007-12-07 20:13:10 -07:00
|
|
|
if (tc->depth_stencil) {
|
2009-02-12 19:38:35 +01:00
|
|
|
pipe_get_tile_raw(pt,
|
2008-01-31 13:32:29 -07:00
|
|
|
tile->x, tile->y, TILE_SIZE, TILE_SIZE,
|
|
|
|
tile->data.depth32, 0/*STRIDE*/);
|
2007-12-07 20:13:10 -07:00
|
|
|
}
|
|
|
|
else {
|
2009-02-12 19:38:35 +01:00
|
|
|
pipe_get_tile_rgba(pt,
|
2008-01-14 16:17:01 +01:00
|
|
|
tile->x, tile->y, TILE_SIZE, TILE_SIZE,
|
|
|
|
(float *) tile->data.color);
|
2007-12-07 20:13:10 -07:00
|
|
|
}
|
2007-10-19 10:08:24 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return tile;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-10-21 18:06:35 -06:00
|
|
|
/**
|
|
|
|
* Given the texture face, level, zslice, x and y values, compute
|
|
|
|
* the cache entry position/index where we'd hope to find the
|
|
|
|
* cached texture tile.
|
|
|
|
* This is basically a direct-map cache.
|
|
|
|
* XXX There's probably lots of ways in which we can improve this.
|
|
|
|
*/
|
2007-10-22 09:37:26 -06:00
|
|
|
static INLINE uint
|
2007-10-21 18:06:35 -06:00
|
|
|
tex_cache_pos(int x, int y, int z, int face, int level)
|
|
|
|
{
|
2009-02-16 18:45:58 -07:00
|
|
|
uint entry = x + y * 9 + z * 3 + face + level * 7;
|
2007-10-21 18:06:35 -06:00
|
|
|
return entry % NUM_ENTRIES;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Similar to sp_get_cached_tile() but for textures.
|
|
|
|
* Tiles are read-only and indexed with more params.
|
|
|
|
*/
|
2007-10-22 09:37:26 -06:00
|
|
|
const struct softpipe_cached_tile *
|
2008-11-23 19:15:15 -07:00
|
|
|
sp_get_cached_tile_tex(struct softpipe_context *sp,
|
2007-10-22 09:37:26 -06:00
|
|
|
struct softpipe_tile_cache *tc, int x, int y, int z,
|
2007-10-21 18:06:35 -06:00
|
|
|
int face, int level)
|
|
|
|
{
|
2008-11-23 19:15:15 -07:00
|
|
|
struct pipe_screen *screen = sp->pipe.screen;
|
2007-10-21 18:06:35 -06:00
|
|
|
/* tile pos in framebuffer: */
|
|
|
|
const int tile_x = x & ~(TILE_SIZE - 1);
|
|
|
|
const int tile_y = y & ~(TILE_SIZE - 1);
|
|
|
|
/* cache pos/entry: */
|
2007-10-22 09:37:26 -06:00
|
|
|
const uint pos = tex_cache_pos(x / TILE_SIZE, y / TILE_SIZE, z,
|
|
|
|
face, level);
|
2007-10-21 18:06:35 -06:00
|
|
|
struct softpipe_cached_tile *tile = tc->entries + pos;
|
|
|
|
|
2008-06-20 15:58:19 -06:00
|
|
|
if (tc->texture) {
|
|
|
|
struct softpipe_texture *spt = softpipe_texture(tc->texture);
|
|
|
|
if (spt->modified) {
|
2009-02-16 18:45:58 -07:00
|
|
|
/* texture was modified, invalidate all cached tiles */
|
|
|
|
uint p;
|
|
|
|
for (p = 0; p < NUM_ENTRIES; p++) {
|
|
|
|
tile = tc->entries + p;
|
|
|
|
tile->x = -1;
|
|
|
|
}
|
2008-06-20 15:58:19 -06:00
|
|
|
spt->modified = FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-10-21 18:06:35 -06:00
|
|
|
if (tile_x != tile->x ||
|
|
|
|
tile_y != tile->y ||
|
|
|
|
z != tile->z ||
|
|
|
|
face != tile->face ||
|
|
|
|
level != tile->level) {
|
2007-12-07 21:21:58 -07:00
|
|
|
/* cache miss */
|
2007-10-21 18:06:35 -06:00
|
|
|
|
2009-02-16 18:45:58 -07:00
|
|
|
#if 0
|
|
|
|
printf("miss at %u x=%d y=%d z=%d face=%d level=%d\n", pos,
|
|
|
|
x/TILE_SIZE, y/TILE_SIZE, z, face, level);
|
|
|
|
#endif
|
2009-02-05 19:41:18 +01:00
|
|
|
/* check if we need to get a new transfer */
|
|
|
|
if (!tc->tex_trans ||
|
2007-12-07 21:21:58 -07:00
|
|
|
tc->tex_face != face ||
|
|
|
|
tc->tex_level != level ||
|
|
|
|
tc->tex_z != z) {
|
2009-02-05 19:41:18 +01:00
|
|
|
/* get new transfer (view into texture) */
|
2007-12-07 12:30:35 +01:00
|
|
|
|
2009-03-18 10:17:48 -06:00
|
|
|
if (tc->tex_trans) {
|
|
|
|
if (tc->tex_trans_map) {
|
2009-02-12 20:13:09 +01:00
|
|
|
tc->screen->transfer_unmap(tc->screen, tc->tex_trans);
|
2009-03-18 10:17:48 -06:00
|
|
|
tc->tex_trans_map = NULL;
|
|
|
|
}
|
2007-12-07 12:30:35 +01:00
|
|
|
|
2009-03-04 11:58:48 +01:00
|
|
|
screen->tex_transfer_destroy(tc->tex_trans);
|
2009-03-18 10:17:48 -06:00
|
|
|
tc->tex_trans = NULL;
|
2009-02-12 20:13:09 +01:00
|
|
|
}
|
2007-10-21 18:06:35 -06:00
|
|
|
|
2009-02-05 19:41:18 +01:00
|
|
|
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);
|
2007-12-07 21:21:58 -07:00
|
|
|
|
|
|
|
tc->tex_face = face;
|
|
|
|
tc->tex_level = level;
|
|
|
|
tc->tex_z = z;
|
|
|
|
}
|
|
|
|
|
2009-02-05 19:41:18 +01:00
|
|
|
/* get tile from the transfer (view into texture) */
|
|
|
|
pipe_get_tile_rgba(tc->tex_trans,
|
2008-01-14 16:17:01 +01:00
|
|
|
tile_x, tile_y, TILE_SIZE, TILE_SIZE,
|
|
|
|
(float *) tile->data.color);
|
2007-10-22 09:37:26 -06:00
|
|
|
tile->x = tile_x;
|
|
|
|
tile->y = tile_y;
|
|
|
|
tile->z = z;
|
|
|
|
tile->face = face;
|
|
|
|
tile->level = level;
|
2007-10-21 18:06:35 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
return tile;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-10-23 18:49:19 -06:00
|
|
|
/**
|
|
|
|
* When a whole surface is being cleared to a value we can avoid
|
|
|
|
* fetching tiles above.
|
|
|
|
* Save the color and set a 'clearflag' for each tile of the screen.
|
|
|
|
*/
|
2007-10-19 10:08:24 -06:00
|
|
|
void
|
2009-04-06 15:31:58 -06:00
|
|
|
sp_tile_cache_clear(struct softpipe_tile_cache *tc, const float *rgba,
|
|
|
|
uint clearValue)
|
2007-10-19 10:08:24 -06:00
|
|
|
{
|
2008-01-23 15:39:34 -07:00
|
|
|
uint pos;
|
2007-12-07 20:13:10 -07:00
|
|
|
|
2009-04-06 15:31:58 -06:00
|
|
|
tc->clear_color[0] = rgba[0];
|
|
|
|
tc->clear_color[1] = rgba[1];
|
|
|
|
tc->clear_color[2] = rgba[2];
|
|
|
|
tc->clear_color[3] = rgba[3];
|
2007-12-07 20:13:10 -07:00
|
|
|
|
2009-04-06 15:31:58 -06:00
|
|
|
tc->clear_val = clearValue;
|
2007-10-23 18:49:19 -06:00
|
|
|
|
2007-12-07 15:32:13 -07:00
|
|
|
#if TILE_CLEAR_OPTIMIZATION
|
2007-12-07 15:46:10 -07:00
|
|
|
/* set flags to indicate all the tiles are cleared */
|
2007-10-20 15:18:02 -06:00
|
|
|
memset(tc->clear_flags, 255, sizeof(tc->clear_flags));
|
2007-10-23 18:49:19 -06:00
|
|
|
#else
|
2007-12-07 15:46:10 -07:00
|
|
|
/* disable the optimization */
|
2007-10-23 18:49:19 -06:00
|
|
|
memset(tc->clear_flags, 0, sizeof(tc->clear_flags));
|
|
|
|
#endif
|
2008-01-23 15:39:34 -07:00
|
|
|
|
|
|
|
for (pos = 0; pos < NUM_ENTRIES; pos++) {
|
|
|
|
struct softpipe_cached_tile *tile = tc->entries + pos;
|
|
|
|
tile->x = tile->y = -1;
|
|
|
|
}
|
2007-10-19 10:08:24 -06:00
|
|
|
}
|