Search
lxdream.org :: lxdream/src/pvr2/tacore.c :: diff
lxdream 0.9.1
released Jun 29
Download Now
filename src/pvr2/tacore.c
changeset 193:31151fcc3cb7
prev189:615b70cfd729
next194:7fcecbcd5f01
author nkeynes
date Fri Aug 04 01:38:30 2006 +0000 (13 years ago)
permissions -rw-r--r--
last change Add more tile list limit tests
Implement tile list limits in the ta core.
Rename TA_TILEEND to TA_LISTEND
file annotate diff log raw
1.1 --- a/src/pvr2/tacore.c Wed Aug 02 04:06:45 2006 +0000
1.2 +++ b/src/pvr2/tacore.c Fri Aug 04 01:38:30 2006 +0000
1.3 @@ -1,5 +1,5 @@
1.4 /**
1.5 - * $Id: tacore.c,v 1.1 2006-08-02 04:06:45 nkeynes Exp $
1.6 + * $Id: tacore.c,v 1.2 2006-08-04 01:38:27 nkeynes Exp $
1.7 *
1.8 * PVR2 Tile Accelerator implementation
1.9 *
1.10 @@ -120,7 +120,9 @@
1.11 int width, height; /* Tile resolution, ie 20x15 */
1.12 int tilelist_dir; /* Growth direction of the tilelist, 0 = up, 1 = down */
1.13 uint32_t tilelist_size; /* Size of the tilelist segments */
1.14 + uint32_t tilelist_start; /* Initial address of the tilelist */
1.15 int current_vertex_type;
1.16 + gboolean accept_vertexes;
1.17 int vertex_count; /* index of last start-vertex seen, or -1 if no vertexes
1.18 * are present
1.19 */
1.20 @@ -160,6 +162,18 @@
1.21 ta_status.debug_output = 0;
1.22 }
1.23
1.24 +void pvr2_ta_save_state( FILE *f )
1.25 +{
1.26 + fwrite( &ta_status, sizeof(ta_status), 1, f );
1.27 +}
1.28 +
1.29 +int pvr2_ta_load_state( FILE *f )
1.30 +{
1.31 + if( fread( &ta_status, sizeof(ta_status), 1, f ) != 1 )
1.32 + return 1;
1.33 + return 0;
1.34 +}
1.35 +
1.36 void pvr2_ta_init() {
1.37 ta_status.state = STATE_IDLE;
1.38 ta_status.current_list_type = -1;
1.39 @@ -168,6 +182,7 @@
1.40 ta_status.vertex_count = 0;
1.41 ta_status.max_vertex = 3;
1.42 ta_status.last_triangle_bounds.x1 = -1;
1.43 + ta_status.accept_vertexes = TRUE;
1.44
1.45 uint32_t size = MMIO_READ( PVR2, TA_TILESIZE );
1.46 ta_status.width = (size & 0xFFFF) + 1;
1.47 @@ -181,6 +196,7 @@
1.48 plistpos -= ta_status.tilelist_size;
1.49 }
1.50 MMIO_WRITE( PVR2, TA_LISTPOS, plistpos );
1.51 + ta_status.tilelist_start = plistpos;
1.52 }
1.53
1.54 static uint32_t parse_float_colour( float a, float r, float g, float b ) {
1.55 @@ -208,26 +224,42 @@
1.56 static void ta_init_list( unsigned int listtype ) {
1.57 int config = MMIO_READ( PVR2, TA_TILECFG );
1.58 int tile_matrix = MMIO_READ( PVR2, TA_TILEBASE );
1.59 - if( listtype <= TA_LIST_PUNCH_OUT ) {
1.60 + int list_end = MMIO_READ( PVR2, TA_LISTEND );
1.61 +
1.62 + ta_status.current_tile_matrix = tile_matrix;
1.63 +
1.64 + /* If the list grows down, the end must be < tile matrix start.
1.65 + * If it grows up, the end must be > tile matrix start.
1.66 + * Don't ask me why, it just does...
1.67 + */
1.68 + if( ((ta_status.tilelist_dir == TA_GROW_DOWN && list_end <= tile_matrix) ||
1.69 + (ta_status.tilelist_dir == TA_GROW_UP && list_end >= tile_matrix )) &&
1.70 + listtype <= TA_LIST_PUNCH_OUT ) {
1.71 int i;
1.72 uint32_t *p;
1.73 for( i=0; i < listtype; i++ ) {
1.74 int size = tilematrix_sizes[(config & 0x03)] << 2;
1.75 - tile_matrix += ta_status.width * ta_status.height * size;
1.76 + ta_status.current_tile_matrix += ta_status.width * ta_status.height * size;
1.77 config >>= 4;
1.78 }
1.79 - ta_status.current_tile_matrix = tile_matrix;
1.80 ta_status.current_tile_size = tilematrix_sizes[(config & 0x03)];
1.81
1.82 /* Initialize each tile to 0xF0000000 */
1.83 if( ta_status.current_tile_size != 0 ) {
1.84 - p = (uint32_t *)(video_base + tile_matrix);
1.85 + p = (uint32_t *)(video_base + ta_status.current_tile_matrix);
1.86 for( i=0; i< ta_status.width * ta_status.height; i++ ) {
1.87 *p = 0xF0000000;
1.88 p += ta_status.current_tile_size;
1.89 }
1.90 }
1.91 + } else {
1.92 + ta_status.current_tile_size = 0;
1.93 }
1.94 +
1.95 + if( tile_matrix == list_end ) {
1.96 + ta_status.current_tile_size = 0;
1.97 + }
1.98 +
1.99 ta_status.state = STATE_IN_LIST;
1.100 ta_status.current_list_type = listtype;
1.101 ta_status.last_triangle_bounds.x1 = -1;
1.102 @@ -274,19 +306,56 @@
1.103 return rv;
1.104 }
1.105
1.106 +#define TA_NO_ALLOC 0xFFFFFFFF
1.107 +
1.108 /**
1.109 - * Allocate a new tile list from the grow space
1.110 + * Allocate a new tile list block from the grow space and update the
1.111 + * word at reference to be a link to the new block.
1.112 */
1.113 -static uint32_t ta_alloc_tilelist() {
1.114 +static uint32_t ta_alloc_tilelist( uint32_t reference ) {
1.115 uint32_t posn = MMIO_READ( PVR2, TA_LISTPOS );
1.116 + uint32_t limit = MMIO_READ( PVR2, TA_LISTEND ) >> 2;
1.117 uint32_t newposn;
1.118 + uint32_t result;
1.119 if( ta_status.tilelist_dir == TA_GROW_DOWN ) {
1.120 newposn = posn - ta_status.tilelist_size;
1.121 + if( posn == limit ) {
1.122 + PVRRAM(posn<<2) = 0xF0000000;
1.123 + PVRRAM(reference) = 0xE0000000 | (posn<<2);
1.124 + return TA_NO_ALLOC;
1.125 + } else if( posn < limit ) {
1.126 + PVRRAM(reference) = 0xE0000000 | (posn<<2);
1.127 + return TA_NO_ALLOC;
1.128 + } else if( newposn <= limit ) {
1.129 + } else if( newposn <= (limit + ta_status.tilelist_size) ) {
1.130 + asic_event( EVENT_TA_ERROR );
1.131 + asic_event( EVENT_PVR_MATRIX_ALLOC_FAIL );
1.132 + MMIO_WRITE( PVR2, TA_LISTPOS, newposn );
1.133 + } else {
1.134 + MMIO_WRITE( PVR2, TA_LISTPOS, newposn );
1.135 + }
1.136 + PVRRAM(reference) = 0xE0000000 | (posn<<2);
1.137 + return posn << 2;
1.138 } else {
1.139 newposn = posn + ta_status.tilelist_size;
1.140 + if( posn == limit ) {
1.141 + PVRRAM(posn<<2) = 0xF0000000;
1.142 + PVRRAM(reference) = 0xE0000000 | (posn<<2);
1.143 + return TA_NO_ALLOC;
1.144 + } else if ( posn > limit ) {
1.145 + PVRRAM(reference) = 0xE0000000 | (posn<<2);
1.146 + return TA_NO_ALLOC;
1.147 + } else if( newposn >= limit ) {
1.148 + } else if( newposn >= (limit - ta_status.tilelist_size) ) {
1.149 + asic_event( EVENT_TA_ERROR );
1.150 + asic_event( EVENT_PVR_MATRIX_ALLOC_FAIL );
1.151 + MMIO_WRITE( PVR2, TA_LISTPOS, newposn );
1.152 + } else {
1.153 + MMIO_WRITE( PVR2, TA_LISTPOS, newposn );
1.154 + }
1.155 + PVRRAM(reference) = 0xE0000000 | (posn<<2);
1.156 + return posn << 2;
1.157 }
1.158 - MMIO_WRITE( PVR2, TA_LISTPOS, newposn );
1.159 - return posn << 2;
1.160 }
1.161
1.162 /**
1.163 @@ -294,6 +363,7 @@
1.164 */
1.165 static int ta_write_tile_entry( int x, int y, uint32_t tile_entry ) {
1.166 uint32_t tile = TILESLOT(x,y);
1.167 + uint32_t tilestart = tile;
1.168 uint32_t value;
1.169 uint32_t lasttri = 0;
1.170 int i,l;
1.171 @@ -338,14 +408,17 @@
1.172 }
1.173
1.174 if( value == 0xF0000000 ) {
1.175 - value = ta_alloc_tilelist();
1.176 - PVRRAM(tile) = value | 0xE0000000;
1.177 - tile = value;
1.178 - PVRRAM(tile) = tile_entry;
1.179 - PVRRAM(tile+4) = 0xF0000000;
1.180 + tile = ta_alloc_tilelist(tile);
1.181 + if( tile != TA_NO_ALLOC ) {
1.182 + PVRRAM(tile) = tile_entry;
1.183 + PVRRAM(tile+4) = 0xF0000000;
1.184 + }
1.185 return;
1.186 } else if( (value & 0xFF000000) == 0xE0000000 ) {
1.187 - tile = (value & 0x00FFFFFF);
1.188 + value &= 0x00FFFFFF;
1.189 + if( value == tilestart )
1.190 + return 0; /* Loop */
1.191 + tilestart = tile = value;
1.192 } else {
1.193 /* This should never happen */
1.194 return 0;
1.195 @@ -443,6 +516,11 @@
1.196 }
1.197 }
1.198
1.199 + if( ta_status.current_tile_size == 0 ) {
1.200 + /* No memory for tile entry, so don't write anything */
1.201 + return;
1.202 + }
1.203 +
1.204 /* And now the tile entries. Triangles are different from everything else */
1.205 if( ta_status.vertex_count == 3 ) {
1.206 tile_entry |= 0x80000000;
1.207 @@ -642,7 +720,6 @@
1.208 memcpy( &ta_status.poly_vertex[i], &ta_status.poly_vertex[ta_status.vertex_count-1],
1.209 sizeof( struct pvr2_ta_vertex ) );
1.210 }
1.211 - ta_status.vertex_count = ta_status.max_vertex;
1.212 }
1.213
1.214 static void ta_parse_vertex( union ta_data *data ) {
1.215 @@ -908,14 +985,17 @@
1.216 }
1.217
1.218 if( ta_status.vertex_count != 0 ) {
1.219 + /* Error, and not a very well handled one either */
1.220 + asic_event( EVENT_PVR_BAD_INPUT );
1.221 + asic_event( EVENT_TA_ERROR );
1.222 + ta_status.accept_vertexes = FALSE;
1.223 ta_fill_vertexes();
1.224 - ta_commit_polygon();
1.225 - }
1.226 -
1.227 - if( TA_IS_MODIFIER_LIST( ta_status.current_list_type ) ) {
1.228 - ta_parse_modifier_context(data);
1.229 } else {
1.230 - ta_parse_polygon_context(data);
1.231 + if( TA_IS_MODIFIER_LIST( ta_status.current_list_type ) ) {
1.232 + ta_parse_modifier_context(data);
1.233 + } else {
1.234 + ta_parse_polygon_context(data);
1.235 + }
1.236 }
1.237 break;
1.238 case TA_CMD_SPRITE_CONTEXT:
.