Search
lxdream.org :: lxdream/src/pvr2/tacore.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/pvr2/tacore.c
changeset 198:627220aa0e3b
prev194:7fcecbcd5f01
next199:4433d9c1638c
author nkeynes
date Sun Aug 06 03:36:51 2006 +0000 (15 years ago)
permissions -rw-r--r--
last change Add tile clip parsing
view annotate diff log raw
     1 /**
     2  * $Id: tacore.c,v 1.4 2006-08-06 03:36:51 nkeynes Exp $
     3  *
     4  * PVR2 Tile Accelerator implementation
     5  *
     6  * Copyright (c) 2005 Nathan Keynes.
     7  *
     8  * This program is free software; you can redistribute it and/or modify
     9  * it under the terms of the GNU General Public License as published by
    10  * the Free Software Foundation; either version 2 of the License, or
    11  * (at your option) any later version.
    12  *
    13  * This program is distributed in the hope that it will be useful,
    14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    16  * GNU General Public License for more details.
    17  */
    18 #include "pvr2.h"
    19 #include "asic.h"
    21 #define STATE_IDLE                 0
    22 #define STATE_IN_LIST              1
    23 #define STATE_IN_POLYGON           2
    24 #define STATE_EXPECT_POLY_BLOCK2   3
    25 #define STATE_EXPECT_VERTEX_BLOCK2 4
    26 #define STATE_ERROR                5
    27 #define STATE_EXPECT_END_VERTEX_BLOCK2 7
    29 #define TA_CMD(i) ( (i) >> 29 )
    30 #define TA_CMD_END_LIST 0
    31 #define TA_CMD_CLIP 1
    32 #define TA_CMD_POLYGON_CONTEXT 4
    33 #define TA_CMD_SPRITE_CONTEXT 5
    34 #define TA_CMD_VERTEX 7
    36 #define TA_LIST_NONE -1
    37 #define TA_LIST_OPAQUE 0
    38 #define TA_LIST_OPAQUE_MOD 1
    39 #define TA_LIST_TRANS 2
    40 #define TA_LIST_TRANS_MOD 3
    41 #define TA_LIST_PUNCH_OUT 4
    42 #define TA_IS_MODIFIER_LIST(list) (list == TA_LIST_OPAQUE_MOD || list == TA_LIST_TRANS_MOD)
    44 #define TA_GROW_UP 0
    45 #define TA_GROW_DOWN 1
    47 #define TA_VERTEX_NONE                        -1
    48 #define TA_VERTEX_PACKED                      0x00
    49 #define TA_VERTEX_TEX_PACKED                  0x08
    50 #define TA_VERTEX_TEX_SPEC_PACKED             0x0C
    51 #define TA_VERTEX_TEX_UV16_PACKED             0x09
    52 #define TA_VERTEX_TEX_UV16_SPEC_PACKED        0x0D
    53 #define TA_VERTEX_FLOAT                       0x10
    54 #define TA_VERTEX_TEX_FLOAT                   0x18
    55 #define TA_VERTEX_TEX_SPEC_FLOAT              0x1C
    56 #define TA_VERTEX_TEX_UV16_FLOAT              0x19
    57 #define TA_VERTEX_TEX_UV16_SPEC_FLOAT         0x1D
    58 #define TA_VERTEX_INTENSITY                   0x20
    59 #define TA_VERTEX_TEX_INTENSITY               0x28
    60 #define TA_VERTEX_TEX_SPEC_INTENSITY          0x2C
    61 #define TA_VERTEX_TEX_UV16_INTENSITY          0x29
    62 #define TA_VERTEX_TEX_UV16_SPEC_INTENSITY     0x2D
    63 #define TA_VERTEX_PACKED_MOD                  0x40
    64 #define TA_VERTEX_TEX_PACKED_MOD              0x48
    65 #define TA_VERTEX_TEX_SPEC_PACKED_MOD         0x4C
    66 #define TA_VERTEX_TEX_UV16_PACKED_MOD         0x49
    67 #define TA_VERTEX_TEX_UV16_SPEC_PACKED_MOD    0x4D
    68 #define TA_VERTEX_INTENSITY_MOD               0x60
    69 #define TA_VERTEX_TEX_INTENSITY_MOD           0x68
    70 #define TA_VERTEX_TEX_SPEC_INTENSITY_MOD      0x6C
    71 #define TA_VERTEX_TEX_UV16_INTENSITY_MOD      0x69
    72 #define TA_VERTEX_TEX_UV16_SPEC_INTENSITY_MOD 0x6D
    73 #define TA_VERTEX_SPRITE                      0x80
    74 #define TA_VERTEX_TEX_SPRITE                  0x88
    75 #define TA_VERTEX_MOD_VOLUME                  0x81
    77 #define TA_IS_NORMAL_POLY() (ta_status.current_vertex_type < TA_VERTEX_SPRITE)
    79 static int strip_lengths[4] = {3,4,6,8}; /* in vertexes */
    80 #define TA_POLYCMD_LISTTYPE(i) ( ((i) >> 24) & 0x0F )
    81 #define TA_POLYCMD_USELENGTH(i) ( i & 0x00800000 )
    82 #define TA_POLYCMD_LENGTH(i)  strip_lengths[((i >> 18) & 0x03)]
    83 #define TA_POLYCMD_CLIP(i)  ((i>>16)&0x03)
    84 #define TA_POLYCMD_COLOURFMT(i)  (i & 0x00000030)
    85 #define TA_POLYCMD_COLOURFMT_ARGB32 0x00000000
    86 #define TA_POLYCMD_COLOURFMT_FLOAT 0x00000010
    87 #define TA_POLYCMD_COLOURFMT_INTENSITY 0x00000020
    88 #define TA_POLYCMD_COLOURFMT_LASTINT 0x00000030
    90 #define TA_POLYCMD_MODIFIED 0x00000080
    91 #define TA_POLYCMD_FULLMOD  0x00000040
    92 #define TA_POLYCMD_TEXTURED 0x00000008
    93 #define TA_POLYCMD_SPECULAR 0x00000004
    94 #define TA_POLYCMD_SHADED 0x00000002
    95 #define TA_POLYCMD_UV16 0x00000001
    97 #define TA_POLYCMD_IS_SPECULAR(i) ((i & 0x0000000C)==0x0000000C) /* Only applies to textured polys */
    98 #define TA_POLYCMD_IS_FULLMOD(i) ((i & 0x000000C0)==0x000000C0)
   101 #define TA_IS_END_VERTEX(i) (i & 0x10000000)
   103 #define MIN3( x1, x2, x3 ) ( (x1)<(x2)? ((x1)<(x3)?(x1):(x3)) : ((x2)<(x3)?(x2):(x3)) )
   104 #define MAX3( x1, x2, x3 ) ( (x1)>(x2)? ((x1)>(x3)?(x1):(x3)) : ((x2)>(x3)?(x2):(x3)) )
   106 #define TILESLOT( x, y ) (ta_status.current_tile_matrix + (ta_status.current_tile_size * (y * ta_status.width+ x) << 2))
   108 extern char *video_base;
   109 #define PVRRAM(addr) (*(uint32_t *)(video_base + ((addr)&PVR2_RAM_MASK)))
   111 struct pvr2_ta_vertex {
   112     float x,y,z;
   113     uint32_t detail[8]; /* 0-8 detail words */
   114 };
   116 struct tile_bounds {
   117     int x1, y1, x2, y2;
   118 };
   120 struct pvr2_ta_status {
   121     int state;
   122     int width, height; /* Tile resolution, ie 20x15 */
   123     int tilelist_dir; /* Growth direction of the tilelist, 0 = up, 1 = down */
   124     uint32_t tilelist_size; /* Size of the tilelist segments */
   125     uint32_t tilelist_start; /* Initial address of the tilelist */
   126     int current_vertex_type;
   127     gboolean accept_vertexes;
   128     int vertex_count; /* index of last start-vertex seen, or -1 if no vertexes 
   129 			 * are present
   130 			 */
   131     int max_vertex;     /* Maximum number of vertexes in the current polygon (3/4/6/8) */
   132     int current_list_type;
   133     uint32_t current_tile_matrix; /* Memory location of the first tile for the current list. */
   134     uint32_t current_tile_size; /* Size of the tile matrix space  in 32-bit words (0/8/16/32)*/
   135     uint32_t intensity1, intensity2;
   136     struct tile_bounds clip; 
   137     /**
   138      * Current working object
   139      */
   140     int poly_context_size;
   141     int poly_vertex_size;
   142     int poly_parity;
   143     uint32_t poly_context[5];
   144     uint32_t poly_pointer;
   145     struct tile_bounds last_triangle_bounds;
   146     struct pvr2_ta_vertex poly_vertex[8];
   147     int debug_output;
   148 };
   150 static struct pvr2_ta_status ta_status;
   152 static int tilematrix_sizes[4] = {0,8,16,32};
   154 /**
   155  * Convenience union - ta data is either 32-bit integer or 32-bit float.
   156  */
   157 union ta_data {
   158     unsigned int i;
   159     float f;
   160 };
   163 void pvr2_ta_reset() {
   164     ta_status.state = STATE_ERROR; /* State not valid until initialized */
   165     ta_status.debug_output = 0;
   166 }
   168 void pvr2_ta_save_state( FILE *f )
   169 {
   170     fwrite( &ta_status, sizeof(ta_status), 1, f );
   171 }
   173 int pvr2_ta_load_state( FILE *f )
   174 {
   175     if( fread( &ta_status, sizeof(ta_status), 1, f ) != 1 )
   176 	return 1;
   177     return 0;
   178 }
   180 void pvr2_ta_init() {
   181     ta_status.state = STATE_IDLE;
   182     ta_status.current_list_type = -1;
   183     ta_status.current_vertex_type = -1;
   184     ta_status.poly_parity = 0;
   185     ta_status.vertex_count = 0;
   186     ta_status.max_vertex = 3;
   187     ta_status.last_triangle_bounds.x1 = -1;
   188     ta_status.accept_vertexes = TRUE;
   189     ta_status.clip.x1 = 0;
   190     ta_status.clip.y1 = 0;
   192     uint32_t size = MMIO_READ( PVR2, TA_TILESIZE );
   193     ta_status.width = (size & 0xFFFF) + 1;
   194     ta_status.height = (size >> 16) + 1;
   195     ta_status.clip.x2 = ta_status.width-1;
   196     ta_status.clip.y2 = ta_status.height-1;
   197     uint32_t control = MMIO_READ( PVR2, TA_TILECFG );
   198     ta_status.tilelist_dir = (control >> 20) & 0x01;
   199     ta_status.tilelist_size = tilematrix_sizes[ (control & 0x03) ];
   200     MMIO_WRITE( PVR2, TA_POLYPOS, MMIO_READ( PVR2, TA_POLYBASE ) );
   201     uint32_t plistpos = MMIO_READ( PVR2, TA_LISTBASE ) >> 2;
   202     if( ta_status.tilelist_dir == TA_GROW_DOWN ) {
   203 	plistpos -= ta_status.tilelist_size;
   204     }
   205     MMIO_WRITE( PVR2, TA_LISTPOS, plistpos );
   206     ta_status.tilelist_start = plistpos;
   207 }
   209 static uint32_t parse_float_colour( float a, float r, float g, float b ) {
   210     return
   211     	(((unsigned int)((256 * CLAMP(a,0.0,1.0))-1))<<24) |
   212     	(((unsigned int)((256 * CLAMP(r,0.0,1.0))-1))<<16) |
   213     	(((unsigned int)((256 * CLAMP(g,0.0,1.0))-1))<<8) |
   214     	(((unsigned int)((256 * CLAMP(b,0.0,1.0))-1)));
   215 }
   217 static uint32_t parse_intensity_colour( uint32_t base, float intensity )
   218 {
   219     unsigned int i = (unsigned int)(256 * CLAMP(intensity, 0.0,1.0));
   221     return
   222 	(((((base & 0xFF) * i) & 0xFF00) |
   223 	  (((base & 0xFF00) * i) & 0xFF0000) |
   224 	  (((base & 0xFF0000) * i) & 0xFF000000)) >> 8) |
   225 	base & 0xFF000000;
   226 }
   228 /**
   229  * Initialize the specified TA list.
   230  */
   231 static void ta_init_list( unsigned int listtype ) {
   232     int config = MMIO_READ( PVR2, TA_TILECFG );
   233     int tile_matrix = MMIO_READ( PVR2, TA_TILEBASE );
   234     int list_end = MMIO_READ( PVR2, TA_LISTEND );
   236     ta_status.current_tile_matrix = tile_matrix;
   238     /* If the list grows down, the end must be < tile matrix start. 
   239      * If it grows up, the end must be > tile matrix start.
   240      * Don't ask me why, it just does...
   241      */
   242     if( ((ta_status.tilelist_dir == TA_GROW_DOWN && list_end <= tile_matrix) ||
   243 	 (ta_status.tilelist_dir == TA_GROW_UP && list_end >= tile_matrix )) &&
   244 	listtype <= TA_LIST_PUNCH_OUT ) {
   245 	int i;
   246 	uint32_t *p;
   247 	for( i=0; i < listtype; i++ ) {
   248 	    int size = tilematrix_sizes[(config & 0x03)] << 2;
   249 	    ta_status.current_tile_matrix += ta_status.width * ta_status.height * size;
   250 	    config >>= 4;
   251 	}
   252 	ta_status.current_tile_size = tilematrix_sizes[(config & 0x03)];
   254 	/* Initialize each tile to 0xF0000000 */
   255 	if( ta_status.current_tile_size != 0 ) {
   256 	    p = (uint32_t *)(video_base + ta_status.current_tile_matrix);
   257 	    for( i=0; i< ta_status.width * ta_status.height; i++ ) {
   258 		*p = 0xF0000000;
   259 		p += ta_status.current_tile_size;
   260 	    }
   261 	}
   262     } else {
   263 	ta_status.current_tile_size = 0;
   264     }
   266     if( tile_matrix == list_end ) {
   267 	ta_status.current_tile_size = 0;
   268     }
   270     ta_status.state = STATE_IN_LIST;
   271     ta_status.current_list_type = listtype;
   272     ta_status.last_triangle_bounds.x1 = -1;
   273 }
   275 static int list_events[5] = {EVENT_PVR_OPAQUE_DONE, EVENT_PVR_OPAQUEMOD_DONE, 
   276 			     EVENT_PVR_TRANS_DONE, EVENT_PVR_TRANSMOD_DONE,
   277 			     EVENT_PVR_PUNCHOUT_DONE };
   279 static void ta_end_list() {
   280     if( ta_status.current_list_type != TA_LIST_NONE ) {
   281 	asic_event( list_events[ta_status.current_list_type] );
   282 	if( ta_status.state == STATE_IN_POLYGON ) {
   283 	    asic_event( EVENT_TA_ERROR );
   284 	    asic_event( EVENT_PVR_BAD_INPUT );
   285 	}
   286 	ta_status.current_list_type = TA_LIST_NONE;
   287 	ta_status.current_vertex_type = -1;
   288 	ta_status.state = STATE_IDLE;
   289     }
   290 }
   292 /**
   293  * Write data out to the polygon buffer.
   294  * If the end-of-buffer is reached, asserts EVENT_PVR_PRIM_ALLOC_FAIL
   295  * @param data to be written
   296  * @param length Number of 32-bit words to write.
   297  * @return number of words actually written
   298  */
   299 static int ta_write_polygon_buffer( uint32_t *data, int length )
   300 {
   301     int rv;
   302     int posn = MMIO_READ( PVR2, TA_POLYPOS );
   303     int end = MMIO_READ( PVR2, TA_POLYEND );
   304     uint32_t *target = (uint32_t *)(video_base + posn);
   305     for( rv=0; rv < length; rv++ ) {
   306 	if( posn == end ) {
   307 	    asic_event( EVENT_PVR_PRIM_ALLOC_FAIL );
   308 	    asic_event( EVENT_TA_ERROR );
   309 	    //	    ta_status.state = STATE_ERROR;
   310 	    break;
   311 	}
   312 	*target++ = *data++;
   313 	posn += 4;
   314     }
   316     MMIO_WRITE( PVR2, TA_POLYPOS, posn );
   317     return rv;
   318 }
   320 #define TA_NO_ALLOC 0xFFFFFFFF
   322 /**
   323  * Allocate a new tile list block from the grow space and update the
   324  * word at reference to be a link to the new block.
   325  */
   326 static uint32_t ta_alloc_tilelist( uint32_t reference ) {
   327     uint32_t posn = MMIO_READ( PVR2, TA_LISTPOS );
   328     uint32_t limit = MMIO_READ( PVR2, TA_LISTEND ) >> 2;
   329     uint32_t newposn;
   330     uint32_t result;
   331     if( ta_status.tilelist_dir == TA_GROW_DOWN ) {
   332 	newposn = posn - ta_status.tilelist_size;
   333 	if( posn == limit ) {
   334 	    PVRRAM(posn<<2) = 0xF0000000;
   335 	    PVRRAM(reference) = 0xE0000000 | (posn<<2);
   336 	    return TA_NO_ALLOC;
   337 	} else if( posn < limit ) {
   338 	    PVRRAM(reference) = 0xE0000000 | (posn<<2);
   339 	    return TA_NO_ALLOC;
   340 	} else if( newposn <= limit ) {
   341 	} else if( newposn <= (limit + ta_status.tilelist_size) ) {
   342 	    asic_event( EVENT_TA_ERROR );
   343 	    asic_event( EVENT_PVR_MATRIX_ALLOC_FAIL );
   344 	    MMIO_WRITE( PVR2, TA_LISTPOS, newposn );
   345 	} else {
   346 	    MMIO_WRITE( PVR2, TA_LISTPOS, newposn );
   347 	}
   348 	PVRRAM(reference) = 0xE0000000 | (posn<<2);
   349 	return posn << 2;
   350     } else {
   351 	newposn = posn + ta_status.tilelist_size;
   352 	if( posn == limit ) {
   353 	    PVRRAM(posn<<2) = 0xF0000000;
   354 	    PVRRAM(reference) = 0xE0000000 | (posn<<2);
   355 	    return TA_NO_ALLOC;
   356 	} else if ( posn > limit ) {
   357 	    PVRRAM(reference) = 0xE0000000 | (posn<<2);
   358 	    return TA_NO_ALLOC;
   359 	} else if( newposn >= limit ) {
   360 	} else if( newposn >= (limit - ta_status.tilelist_size) ) {
   361 	    asic_event( EVENT_TA_ERROR );
   362 	    asic_event( EVENT_PVR_MATRIX_ALLOC_FAIL );
   363 	    MMIO_WRITE( PVR2, TA_LISTPOS, newposn );
   364 	} else {
   365 	    MMIO_WRITE( PVR2, TA_LISTPOS, newposn );
   366 	}	    
   367 	PVRRAM(reference) = 0xE0000000 | (posn<<2);
   368 	return posn << 2;
   369     }
   370 }
   372 /**
   373  * Write a tile entry out to the matrix.
   374  */
   375 static int ta_write_tile_entry( int x, int y, uint32_t tile_entry ) {
   376     uint32_t tile = TILESLOT(x,y);
   377     uint32_t tilestart = tile;
   378     uint32_t value;
   379     uint32_t lasttri = 0;
   380     int i,l;
   382     if( (tile_entry & 0x80000000) && 
   383 	ta_status.last_triangle_bounds.x1 != -1 &&
   384 	ta_status.last_triangle_bounds.x1 <= x &&
   385 	ta_status.last_triangle_bounds.x2 >= x &&
   386 	ta_status.last_triangle_bounds.y1 <= y &&
   387 	ta_status.last_triangle_bounds.y2 >= y ) {
   388 	/* potential for triangle stacking */
   389 	lasttri = tile_entry & 0xE1E00000;
   390     }
   393     if( PVRRAM(tile) == 0xF0000000 ) {
   394 	PVRRAM(tile) = tile_entry;
   395 	PVRRAM(tile+4) = 0xF0000000;
   396 	return;
   397     }
   399     while(1) {
   400 	value = PVRRAM(tile);
   401 	for( i=1; i<ta_status.current_tile_size; i++ ) {
   402 	    tile += 4;
   403 	    uint32_t nextval = PVRRAM(tile);
   404 	    if( nextval == 0xF0000000 ) {
   405 		if( lasttri != 0 && lasttri == (value&0xE1E00000) ) {
   406 		    int count = (value & 0x1E000000) + 0x02000000;
   407 		    if( count < 0x20000000 ) {
   408 			PVRRAM(tile-4) = (value & 0xE1FFFFFF) | count;
   409 			return;
   410 		    }
   411 		}
   412 		if( i < ta_status.current_tile_size-1 ) {
   413 		    PVRRAM(tile) = tile_entry;
   414 		    PVRRAM(tile+4) = 0xF0000000;
   415 		    return;
   416 		}
   417 	    }
   418 	    value = nextval;
   419 	}
   421 	if( value == 0xF0000000 ) {
   422 	    tile = ta_alloc_tilelist(tile);
   423 	    if( tile != TA_NO_ALLOC ) {
   424 		PVRRAM(tile) = tile_entry;
   425 		PVRRAM(tile+4) = 0xF0000000;
   426 	    }
   427 	    return;
   428 	} else if( (value & 0xFF000000) == 0xE0000000 ) {
   429 	    value &= 0x00FFFFFF;
   430 	    if( value == tilestart )
   431 		return 0; /* Loop */
   432 	    tilestart = tile = value;
   433 	} else {
   434 	    /* This should never happen */
   435 	    return 0;
   436 	}
   437     }
   438 }
   440 /**
   441  * Write a completed polygon out to the memory buffers 
   442  * OPTIMIZEME: This is not terribly efficient at the moment.
   443  */
   444 static void ta_commit_polygon( ) {
   445     int i, x, y;
   446     int tx[ta_status.vertex_count], ty[ta_status.vertex_count];
   447     struct tile_bounds triangle_bound[ta_status.vertex_count - 2];
   448     struct tile_bounds polygon_bound;
   449     uint32_t poly_context[5];
   451     if( ta_status.vertex_count < 2 ) {
   452 	return; /* No polygons - ignore */
   453     }
   454     memcpy( poly_context, ta_status.poly_context, ta_status.poly_context_size * 4 );
   456     /* Compute the tile coordinates for each vertex (need to be careful with
   457      * clamping here)
   458      */
   459     for( i=0; i<ta_status.vertex_count; i++ ) {
   460 	if( ta_status.poly_vertex[i].x < 0.0 ) {
   461 	    tx[i] = -1;
   462 	} else if( ta_status.poly_vertex[i].x > (float)INT_MAX ) {
   463 	    tx[i] = INT_MAX/32;
   464 	} else {
   465 	    tx[i] = (int)(ta_status.poly_vertex[i].x / 32.0);
   466 	}
   467 	if( ta_status.poly_vertex[i].y < 0.0 ) {
   468 	    ty[i] = -1;
   469 	} else if( ta_status.poly_vertex[i].y > (float)INT_MAX ) {
   470 	    ty[i] = INT_MAX/32;
   471 	} else {
   472 	    ty[i] = (int)(ta_status.poly_vertex[i].y / 32.0);
   473 	}
   475     }
   477     /* Compute bounding box for each triangle individually, as well
   478      * as the overall polygon.
   479      */
   481     for( i=0; i<ta_status.vertex_count-2; i++ ) {
   482 	triangle_bound[i].x1 = MIN3(tx[i],tx[i+1],tx[i+2]);
   483 	triangle_bound[i].x2 = MAX3(tx[i],tx[i+1],tx[i+2]);
   484 	triangle_bound[i].y1 = MIN3(ty[i],ty[i+1],ty[i+2]);
   485 	triangle_bound[i].y2 = MAX3(ty[i],ty[i+1],ty[i+2]);
   486 	if( i == 0 ) {
   487 	    polygon_bound.x1 = triangle_bound[0].x1;
   488 	    polygon_bound.y1 = triangle_bound[0].y1;
   489 	    polygon_bound.x2 = triangle_bound[0].x2;
   490 	    polygon_bound.y2 = triangle_bound[0].y2;
   491 	} else {
   492 	    polygon_bound.x1 = MIN(polygon_bound.x1, triangle_bound[i].x1);
   493 	    polygon_bound.x2 = MAX(polygon_bound.x2, triangle_bound[i].x2);
   494 	    polygon_bound.y1 = MIN(polygon_bound.y1, triangle_bound[i].y1);
   495 	    polygon_bound.y2 = MAX(polygon_bound.y2, triangle_bound[i].y2);
   496 	}
   497     }
   499     /* If the polygon is actually entirely out of the frustum, clip it entirely */
   500     if( polygon_bound.x2 < 0 || polygon_bound.x1 > ta_status.width ||
   501 	polygon_bound.y2 < 0 || polygon_bound.y1 > ta_status.height ) {
   502 	return;
   503     }
   505     /* Clamp the polygon bounds to the frustum */
   506     if( polygon_bound.x1 < 0 ) polygon_bound.x1 = 0;
   507     if( polygon_bound.x2 >= ta_status.width ) polygon_bound.x2 = ta_status.width-1;
   508     if( polygon_bound.y1 < 0 ) polygon_bound.y1 = 0;
   509     if( polygon_bound.y2 >= ta_status.width ) polygon_bound.y2 = ta_status.height-1;
   511     /* Set the "single tile" flag if it's entirely contained in 1 tile */
   512     if( polygon_bound.x1 == polygon_bound.x2 &&
   513 	polygon_bound.y1 == polygon_bound.y2 ) {
   514 	poly_context[0] |= 0x00200000;
   515     }
   517     /* Ok, we're good to go - write out the polygon first */
   518     uint32_t tile_entry = MMIO_READ( PVR2, TA_POLYPOS ) >> 2 | ta_status.poly_pointer;
   520     int status = ta_write_polygon_buffer( poly_context, ta_status.poly_context_size );
   521     if( status == 0 ) {
   522 	/* No memory available - abort */
   523 	return;
   524     } else {
   525 	for( i=0; i<ta_status.vertex_count && status != 0; i++ ) {
   526 	    status = ta_write_polygon_buffer( (uint32_t *)(&ta_status.poly_vertex[i]), 3 + ta_status.poly_vertex_size );
   527 	}
   528     }
   530     if( ta_status.current_tile_size == 0 ) {
   531 	/* No memory for tile entry, so don't write anything */
   532 	return;
   533     }
   535     /* And now the tile entries. Triangles are different from everything else */
   536     if( ta_status.vertex_count == 3 ) {
   537 	tile_entry |= 0x80000000;
   538 	for( y=polygon_bound.y1; y<=polygon_bound.y2; y++ ) {
   539 	    for( x=polygon_bound.x1; x<=polygon_bound.x2; x++ ) {
   540 		ta_write_tile_entry( x,y,tile_entry );
   541 	    }
   542 	}
   543 	ta_status.last_triangle_bounds.x1 = polygon_bound.x1;
   544 	ta_status.last_triangle_bounds.y1 = polygon_bound.y1;
   545 	ta_status.last_triangle_bounds.x2 = polygon_bound.x2;
   546 	ta_status.last_triangle_bounds.y2 = polygon_bound.y2;
   547     } else if( ta_status.current_vertex_type == TA_VERTEX_SPRITE ||
   548 	       ta_status.current_vertex_type == TA_VERTEX_TEX_SPRITE ) {
   549 	tile_entry |= 0xA0000000;
   550 	for( y=polygon_bound.y1; y<=polygon_bound.y2; y++ ) {
   551 	    for( x=polygon_bound.x1; x<=polygon_bound.x2; x++ ) {
   552 		ta_write_tile_entry( x,y,tile_entry );
   553 	    }
   554 	}
   555 	ta_status.last_triangle_bounds.x1 = polygon_bound.x1;
   556 	ta_status.last_triangle_bounds.y1 = polygon_bound.y1;
   557 	ta_status.last_triangle_bounds.x2 = polygon_bound.x2;
   558 	ta_status.last_triangle_bounds.y2 = polygon_bound.y2;
   559     } else {
   560 	for( y=polygon_bound.y1; y<=polygon_bound.y2; y++ ) {
   561 	    for( x=polygon_bound.x1; x<=polygon_bound.x2; x++ ) {
   562 		uint32_t entry = tile_entry;
   563 		for( i=0; i<ta_status.vertex_count-2; i++ ) {
   564 		    if( triangle_bound[i].x1 <= x && triangle_bound[i].x2 >= x &&
   565 			triangle_bound[i].y1 <= y && triangle_bound[i].y2 >= y ) {
   566 			entry |= (0x40000000>>i);
   567 		    }
   568 		}
   569 		ta_write_tile_entry( x, y, entry );
   570 	    }
   571 	}
   572 	ta_status.last_triangle_bounds.x1 = -1;
   573     }
   574 }
   576 /**
   577  * Variant of ta_split_polygon called when vertex_count == max_vertex, but 
   578  * the client hasn't sent the LAST VERTEX flag. Commit the poly as normal
   579  * first, then start a new poly with the first 2 vertexes taken from the 
   580  * current one.
   581  */
   582 static void ta_split_polygon() {
   583     ta_commit_polygon();
   584     if( TA_IS_NORMAL_POLY() ) { 
   585 	/* This only applies to ordinary polys - Sprites + modifier lists are
   586 	 * handled differently
   587 	 */
   588 	if( ta_status.vertex_count == 3 ) {
   589 	    /* Triangles use an odd/even scheme */
   590 	    if( ta_status.poly_parity == 0 ) {
   591 		memcpy( &ta_status.poly_vertex[0], &ta_status.poly_vertex[2], 
   592 			sizeof(struct pvr2_ta_vertex) );
   593 		ta_status.poly_parity = 1;
   594 	    } else {
   595 		memcpy( &ta_status.poly_vertex[1], &ta_status.poly_vertex[2],
   596 			sizeof(struct pvr2_ta_vertex) );
   597 		ta_status.poly_parity = 0;
   598 	    }
   599 	} else {
   600 	    /* Everything else just uses the last 2 vertexes in order */
   601 	    memcpy( &ta_status.poly_vertex[0], &ta_status.poly_vertex[ta_status.vertex_count-2], 
   602 		    sizeof(struct pvr2_ta_vertex)*2 );
   603 	    ta_status.poly_parity = 0;
   604 	}
   605 	ta_status.vertex_count = 2;
   606     } else {
   607 	ta_status.vertex_count = 0;
   608     }
   609 }
   611 /**
   612  * Parse the polygon context block and setup the internal state to receive
   613  * vertexes.
   614  * @param data 32 bytes of parameter data.
   615  */
   616 static void ta_parse_polygon_context( union ta_data *data ) {
   617     int colourfmt = TA_POLYCMD_COLOURFMT(data[0].i);
   618     if( TA_POLYCMD_USELENGTH(data[0].i) ) {
   619 	ta_status.max_vertex = TA_POLYCMD_LENGTH(data[0].i);
   620     }
   621     ta_status.vertex_count = 0;
   622     ta_status.poly_context[0] = 
   623 	(data[1].i & 0xFC1FFFFF) | ((data[0].i & 0x0B) << 22);
   624     ta_status.poly_context[1] = data[2].i;
   625     ta_status.poly_context[3] = data[4].i;
   626     ta_status.poly_parity = 0;
   627     if( data[0].i & TA_POLYCMD_TEXTURED ) {
   628 	ta_status.current_vertex_type = data[0].i & 0x0D;
   629 	ta_status.poly_context[2] = data[3].i;
   630 	ta_status.poly_context[4] = data[5].i;
   631 	if( data[0].i & TA_POLYCMD_SPECULAR ) {
   632 	    ta_status.poly_context[0] |= 0x01000000;
   633 	    ta_status.poly_vertex_size = 4;
   634 	} else {
   635 	    ta_status.poly_vertex_size = 3;
   636 	}
   637 	if( data[0].i & TA_POLYCMD_UV16 ) {
   638 	    ta_status.poly_vertex_size--;
   639 	}
   640     } else {
   641 	ta_status.current_vertex_type = 0;
   642 	ta_status.poly_vertex_size = 1;
   643 	ta_status.poly_context[2] = 0;
   644 	ta_status.poly_context[4] = 0;
   645     }
   647     ta_status.poly_pointer = (ta_status.poly_vertex_size << 21);
   648     ta_status.poly_context_size = 3;
   649     if( data[0].i & TA_POLYCMD_MODIFIED ) {
   650 	ta_status.poly_pointer |= 0x01000000;
   651 	if( data[0].i & TA_POLYCMD_FULLMOD ) {
   652 	    ta_status.poly_context_size = 5;
   653 	    ta_status.poly_vertex_size <<= 1;
   654 	    ta_status.current_vertex_type |= 0x40;
   655 	    /* Modified/float not supported - behaves as per last intensity */
   656 	    if( colourfmt == TA_POLYCMD_COLOURFMT_FLOAT ) {
   657 		colourfmt = TA_POLYCMD_COLOURFMT_LASTINT;
   658 	    }
   659 	}
   660     }
   662     if( colourfmt == TA_POLYCMD_COLOURFMT_INTENSITY ) {
   663 	if( TA_POLYCMD_IS_FULLMOD(data[0].i) ||
   664 	    TA_POLYCMD_IS_SPECULAR(data[0].i) ) {
   665 	    ta_status.state = STATE_EXPECT_POLY_BLOCK2;
   666 	} else {
   667 	    ta_status.intensity1 = 
   668 		parse_float_colour( data[4].f, data[5].f, data[6].f, data[7].f );
   669 	}
   670     } else if( colourfmt == TA_POLYCMD_COLOURFMT_LASTINT ) {
   671 	colourfmt = TA_POLYCMD_COLOURFMT_INTENSITY;
   672     }
   674     ta_status.current_vertex_type |= colourfmt;
   675 }
   677 /**
   678  * Parse the modifier volume context block and setup the internal state to 
   679  * receive modifier vertexes.
   680  * @param data 32 bytes of parameter data.
   681  */
   682 static void ta_parse_modifier_context( union ta_data *data ) {
   683     ta_status.current_vertex_type = TA_VERTEX_MOD_VOLUME;
   684     ta_status.poly_vertex_size = 0;
   685     ta_status.poly_context_size = 3;
   686     ta_status.poly_context[0] = (data[1].i & 0xFC1FFFFF) |
   687 	((data[0].i & 0x0B)<<22);
   688     if( TA_POLYCMD_IS_SPECULAR(data[0].i) ) {
   689 	ta_status.poly_context[0] |= 0x01000000;
   690     }
   691     ta_status.poly_context[1] = 0;
   692     ta_status.poly_context[2] = 0;
   693     ta_status.vertex_count = 0;
   694     ta_status.max_vertex = 3;
   695     ta_status.poly_pointer = 0;
   696 }
   698 /**
   699  * Parse the sprite context block and setup the internal state to receive
   700  * vertexes.
   701  * @param data 32 bytes of parameter data.
   702  */
   703 static void ta_parse_sprite_context( union ta_data *data ) {
   704     ta_status.poly_context_size = 3;
   705     ta_status.poly_context[0] = (data[1].i & 0xFC1FFFFF) |
   706 	((data[0].i & 0x0B)<<22) | 0x00400000;
   707     if( TA_POLYCMD_IS_SPECULAR(data[0].i) ) {
   708 	ta_status.poly_context[0] |= 0x01000000;
   709     }
   710     ta_status.poly_context[1] = data[2].i;
   711     ta_status.poly_context[2] = data[3].i;
   712     if( data[0].i & TA_POLYCMD_TEXTURED ) {
   713 	ta_status.poly_vertex_size = 2;
   714 	ta_status.poly_vertex[2].detail[1] = data[4].i;
   715 	ta_status.current_vertex_type = TA_VERTEX_TEX_SPRITE;
   716     } else {
   717 	ta_status.poly_vertex_size = 1;
   718 	ta_status.poly_vertex[2].detail[0] = data[4].i;
   719 	ta_status.current_vertex_type = TA_VERTEX_SPRITE;
   720     }
   721     ta_status.vertex_count = 0;
   722     ta_status.max_vertex = 4;
   723     ta_status.poly_pointer = (ta_status.poly_vertex_size << 21);
   724 }
   726 /**
   727  * Copy the last read vertex into all vertexes up to max_vertex. Used for
   728  * Aborted polygons under some circumstances.
   729  */
   730 static void ta_fill_vertexes( ) {
   731     int i;
   732     for( i=ta_status.vertex_count; i<ta_status.max_vertex; i++ ) {
   733 	memcpy( &ta_status.poly_vertex[i], &ta_status.poly_vertex[ta_status.vertex_count-1],
   734 		sizeof( struct pvr2_ta_vertex ) );
   735     }
   736 }
   738 static void ta_parse_vertex( union ta_data *data ) {
   739     struct pvr2_ta_vertex *vertex = &ta_status.poly_vertex[ta_status.vertex_count];
   740     vertex->x = data[1].f;
   741     vertex->y = data[2].f;
   742     vertex->z = data[3].f;
   744     switch( ta_status.current_vertex_type ) {
   745     case TA_VERTEX_PACKED:
   746 	vertex->detail[0] = data[6].i;
   747 	break;
   748     case TA_VERTEX_FLOAT:
   749 	vertex->detail[0] = parse_float_colour( data[4].f, data[5].f, data[6].f, data[7].f );
   750 	break;
   751     case TA_VERTEX_INTENSITY:
   752 	vertex->detail[0] = parse_intensity_colour( ta_status.intensity1, data[6].f );
   753 	break;
   755     case TA_VERTEX_TEX_SPEC_PACKED:
   756 	vertex->detail[3] = data[7].i; /* ARGB */
   757 	/* Fallthrough */
   758     case TA_VERTEX_TEX_PACKED:
   759 	vertex->detail[0] = data[4].i; /* U */
   760 	vertex->detail[1] = data[5].i; /* V */
   761 	vertex->detail[2] = data[6].i; /* ARGB */
   762 	break;
   763     case TA_VERTEX_TEX_UV16_SPEC_PACKED:
   764 	vertex->detail[2] = data[7].i; /* ARGB */
   765 	/* Fallthrough */
   766     case TA_VERTEX_TEX_UV16_PACKED:
   767 	vertex->detail[0] = data[4].i; /* UV */
   768 	vertex->detail[1] = data[6].i; /* ARGB */
   769 	break;
   771     case TA_VERTEX_TEX_FLOAT:
   772     case TA_VERTEX_TEX_SPEC_FLOAT:
   773 	vertex->detail[0] = data[4].i; /* U */
   774 	vertex->detail[1] = data[5].i; /* UV */
   775 	ta_status.state = STATE_EXPECT_VERTEX_BLOCK2;
   776 	break;
   777     case TA_VERTEX_TEX_UV16_FLOAT:
   778     case TA_VERTEX_TEX_UV16_SPEC_FLOAT:
   779 	vertex->detail[0] = data[4].i; /* UV */
   780 	ta_status.state = STATE_EXPECT_VERTEX_BLOCK2;
   781 	break;
   783     case TA_VERTEX_TEX_SPEC_INTENSITY:
   784 	vertex->detail[3] = parse_intensity_colour( ta_status.intensity2, data[7].f );
   785 	/* Fallthrough */
   786     case TA_VERTEX_TEX_INTENSITY:
   787 	vertex->detail[0] = data[4].i; /* U */
   788 	vertex->detail[1] = data[5].i; /* V */
   789 	vertex->detail[2] = parse_intensity_colour( ta_status.intensity1, data[6].f );
   790 	break;
   791     case TA_VERTEX_TEX_UV16_SPEC_INTENSITY:
   792 	vertex->detail[2] = parse_intensity_colour( ta_status.intensity2, data[7].f );
   793 	/* Fallthrough */
   794     case TA_VERTEX_TEX_UV16_INTENSITY:
   795 	vertex->detail[0] = data[4].i; /* UV */
   796 	vertex->detail[1] = parse_intensity_colour( ta_status.intensity1, data[6].f );
   797 	break;
   799     case TA_VERTEX_PACKED_MOD:
   800 	vertex->detail[0] = data[4].i; /* ARGB */
   801 	vertex->detail[1] = data[5].i; /* ARGB */
   802 	break;
   803     case TA_VERTEX_INTENSITY_MOD:
   804 	vertex->detail[0] = parse_intensity_colour( ta_status.intensity1, data[4].f );
   805 	vertex->detail[1] = parse_intensity_colour( ta_status.intensity2, data[5].f );
   806 	break;
   808     case TA_VERTEX_TEX_SPEC_PACKED_MOD:
   809 	vertex->detail[3] = data[7].i; /* ARGB0 */
   810 	/* Fallthrough */
   811     case TA_VERTEX_TEX_PACKED_MOD:
   812 	vertex->detail[0] = data[4].i; /* U0 */
   813 	vertex->detail[1] = data[5].i; /* V0 */
   814 	vertex->detail[2] = data[6].i; /* ARGB0 */
   815 	ta_status.state = STATE_EXPECT_VERTEX_BLOCK2;
   816 	break;
   817     case TA_VERTEX_TEX_UV16_SPEC_PACKED_MOD:
   818 	vertex->detail[2] = data[7].i; /* ARGB0 */
   819 	/* Fallthrough */
   820     case TA_VERTEX_TEX_UV16_PACKED_MOD:
   821 	vertex->detail[0] = data[4].i; /* UV0 */
   822 	vertex->detail[1] = data[6].i; /* ARGB0 */
   823 	ta_status.state = STATE_EXPECT_VERTEX_BLOCK2;
   824 	break;
   826     case TA_VERTEX_TEX_SPEC_INTENSITY_MOD:
   827 	vertex->detail[3] = parse_intensity_colour( ta_status.intensity1, data[7].f );
   828 	/* Fallthrough */
   829     case TA_VERTEX_TEX_INTENSITY_MOD:
   830 	vertex->detail[0] = data[4].i; /* U0 */
   831 	vertex->detail[1] = data[5].i; /* V0 */
   832 	vertex->detail[2] = parse_intensity_colour( ta_status.intensity1, data[6].f );
   833 	ta_status.state = STATE_EXPECT_VERTEX_BLOCK2;
   834 	break;
   835     case TA_VERTEX_TEX_UV16_SPEC_INTENSITY_MOD:
   836 	vertex->detail[2] = parse_intensity_colour( ta_status.intensity1, data[7].f );
   837 	/* Fallthrough */
   838     case TA_VERTEX_TEX_UV16_INTENSITY_MOD:
   839 	vertex->detail[0] = data[4].i; /* UV0 */
   840 	vertex->detail[1] = parse_intensity_colour( ta_status.intensity1, data[6].f );
   841 	ta_status.state = STATE_EXPECT_VERTEX_BLOCK2;
   842 	break;
   844     case TA_VERTEX_SPRITE:
   845     case TA_VERTEX_TEX_SPRITE:
   846     case TA_VERTEX_MOD_VOLUME:
   847 	vertex++;
   848 	vertex->x = data[4].f;
   849 	vertex->y = data[5].f;
   850 	vertex->z = data[6].f;
   851 	vertex++;
   852 	vertex->x = data[7].f;
   853 	ta_status.vertex_count += 2;
   854 	ta_status.state = STATE_EXPECT_VERTEX_BLOCK2;
   855 	break;
   856     }
   857     ta_status.vertex_count++;
   858 }
   860 static void ta_parse_vertex_block2( union ta_data *data ) {
   861     struct pvr2_ta_vertex *vertex = &ta_status.poly_vertex[ta_status.vertex_count-1];
   863     switch( ta_status.current_vertex_type ) {
   864     case TA_VERTEX_TEX_SPEC_FLOAT:
   865 	vertex->detail[3] = parse_float_colour( data[4].f, data[5].f, data[6].f, data[7].f );
   866 	/* Fallthrough */
   867     case TA_VERTEX_TEX_FLOAT:
   868 	vertex->detail[2] = parse_float_colour( data[0].f, data[1].f, data[2].f, data[3].f );
   869 	break;
   870     case TA_VERTEX_TEX_UV16_SPEC_FLOAT:
   871 	vertex->detail[2] = parse_float_colour( data[4].f, data[5].f, data[6].f, data[7].f );
   872 	/* Fallthrough */
   873     case TA_VERTEX_TEX_UV16_FLOAT:
   874 	vertex->detail[1] = parse_float_colour( data[0].f, data[1].f, data[2].f, data[3].f );
   875 	break;
   876     case TA_VERTEX_TEX_PACKED_MOD:
   877 	vertex->detail[3] = data[0].i; /* U1 */
   878 	vertex->detail[4] = data[1].i; /* V1 */
   879 	vertex->detail[5] = data[2].i; /* ARGB1 */
   880 	break;
   881     case TA_VERTEX_TEX_SPEC_PACKED_MOD:
   882 	vertex->detail[4] = data[0].i; /* U1 */
   883 	vertex->detail[5] = data[1].i; /* V1 */
   884 	vertex->detail[6] = data[2].i; /* ARGB1 */
   885 	vertex->detail[7] = data[3].i; /* ARGB1 */
   886 	break;
   887     case TA_VERTEX_TEX_UV16_PACKED_MOD:
   888 	vertex->detail[2] = data[0].i; /* UV1 */
   889 	vertex->detail[3] = data[2].i; /* ARGB1 */
   890 	break;
   891     case TA_VERTEX_TEX_UV16_SPEC_PACKED_MOD:
   892 	vertex->detail[3] = data[0].i; /* UV1 */
   893 	vertex->detail[4] = data[2].i; /* ARGB1 */
   894 	vertex->detail[5] = data[3].i; /* ARGB1 */
   895 	break;
   897     case TA_VERTEX_TEX_INTENSITY_MOD:
   898 	vertex->detail[3] = data[0].i; /* U1 */
   899 	vertex->detail[4] = data[1].i; /* V1 */
   900 	vertex->detail[5] = parse_intensity_colour( ta_status.intensity2, data[2].f ); /* ARGB1 */
   901 	break;
   902     case TA_VERTEX_TEX_SPEC_INTENSITY_MOD:
   903 	vertex->detail[4] = data[0].i; /* U1 */
   904 	vertex->detail[5] = data[1].i; /* V1 */
   905 	vertex->detail[6] = parse_intensity_colour( ta_status.intensity2, data[2].f ); /* ARGB1 */
   906 	vertex->detail[7] = parse_intensity_colour( ta_status.intensity2, data[3].f ); /* ARGB1 */
   907 	break;
   908     case TA_VERTEX_TEX_UV16_INTENSITY_MOD:
   909 	vertex->detail[2] = data[0].i; /* UV1 */
   910 	vertex->detail[3] = parse_intensity_colour( ta_status.intensity2, data[2].f ); /* ARGB1 */
   911 	break;
   912     case TA_VERTEX_TEX_UV16_SPEC_INTENSITY_MOD:
   913 	vertex->detail[3] = data[0].i; /* UV1 */
   914 	vertex->detail[4] = parse_intensity_colour( ta_status.intensity2, data[2].f ); /* ARGB1 */
   915 	vertex->detail[5] = parse_intensity_colour( ta_status.intensity2, data[3].f ); /* ARGB1 */
   916 	break;
   918     case TA_VERTEX_SPRITE:
   919 	vertex->y = data[0].f;
   920 	vertex->z = data[1].f;
   921 	vertex++;
   922 	ta_status.vertex_count++;
   923 	vertex->x = data[2].f;
   924 	vertex->y = data[3].f;
   925 	vertex->z = 0;
   926 	vertex->detail[0] = 0;
   927 	ta_status.poly_vertex[0].detail[0] = 0;
   928 	ta_status.poly_vertex[1].detail[0] = 0;
   929 	break;
   930     case TA_VERTEX_TEX_SPRITE:
   931 	vertex->y = data[0].f;
   932 	vertex->z = data[1].f;
   933 	vertex++;
   934 	ta_status.vertex_count++;
   935 	vertex->x = data[2].f;
   936 	vertex->y = data[3].f;
   937 	vertex->z = 0;
   938 	vertex->detail[0] = 0;
   939 	vertex->detail[1] = 0;
   940 	ta_status.poly_vertex[0].detail[0] = data[5].i;
   941 	ta_status.poly_vertex[0].detail[1] = 0;
   942 	ta_status.poly_vertex[1].detail[0] = data[6].i;
   943 	ta_status.poly_vertex[1].detail[1] = 0;
   944 	ta_status.poly_vertex[2].detail[0] = data[7].i;
   945 	break;
   946     case TA_VERTEX_MOD_VOLUME:
   947 	vertex->y = data[0].f;
   948 	vertex->z = data[1].f;
   949 	break;
   950     }
   951     ta_status.state = STATE_IN_POLYGON;
   952 }
   954 /**
   955  * Process 1 32-byte block of ta data
   956  */
   957 void pvr2_ta_process_block( char *input ) {
   958     union ta_data *data = (union ta_data *)input;
   960     switch( ta_status.state ) {
   961     case STATE_ERROR:
   962 	/* Error raised - stop processing until reset */
   963 	return;
   965     case STATE_EXPECT_POLY_BLOCK2:
   966 	/* This is always a pair of floating-point colours */
   967 	ta_status.intensity1 = 
   968 	    parse_float_colour( data[0].f, data[1].f, data[2].f, data[3].f );
   969 	ta_status.intensity2 =
   970 	    parse_float_colour( data[4].f, data[5].f, data[6].f, data[7].f );
   971 	ta_status.state = STATE_IN_LIST;
   972 	break;
   974     case STATE_EXPECT_VERTEX_BLOCK2:
   975 	ta_parse_vertex_block2( data );
   976 	if( ta_status.vertex_count == ta_status.max_vertex ) {
   977 	    ta_split_polygon();
   978 	}
   979 	break;
   981     case STATE_EXPECT_END_VERTEX_BLOCK2:
   982 	ta_parse_vertex_block2( data );
   983 	ta_commit_polygon();
   984 	ta_status.vertex_count = 0;
   985 	ta_status.poly_parity = 0;
   986 	ta_status.state = STATE_IN_LIST;
   987 	break;
   988     case STATE_IN_LIST:
   989     case STATE_IN_POLYGON:
   990     case STATE_IDLE:
   991 	switch( TA_CMD( data->i ) ) {
   992 	case TA_CMD_END_LIST:
   993 	    ta_end_list();
   994 	    break;
   995 	case TA_CMD_CLIP:
   996 	    if( ta_status.state == STATE_IN_POLYGON ) {
   997 		asic_event( EVENT_PVR_BAD_INPUT );
   998 		asic_event( EVENT_TA_ERROR );
   999 		/* Enter stuffed up mode */
  1001 	    ta_status.clip.x1 = data[4].i & 0x3F;
  1002 	    ta_status.clip.y1 = data[5].i & 0x0F;
  1003 	    ta_status.clip.x2 = data[6].i & 0x3F;
  1004 	    ta_status.clip.y2 = data[7].i & 0x0F;
  1005 	    break;
  1006 	case TA_CMD_POLYGON_CONTEXT:
  1007 	    if( ta_status.state == STATE_IDLE ) {
  1008 		ta_init_list( TA_POLYCMD_LISTTYPE( data->i ) );
  1011 	    if( ta_status.vertex_count != 0 ) {
  1012 		/* Error, and not a very well handled one either */
  1013 		asic_event( EVENT_PVR_BAD_INPUT );
  1014 		asic_event( EVENT_TA_ERROR );
  1015 		ta_status.accept_vertexes = FALSE;
  1016 		ta_fill_vertexes();
  1017 	    } else {
  1018 		if( TA_IS_MODIFIER_LIST( ta_status.current_list_type ) ) {
  1019 		    ta_parse_modifier_context(data);
  1020 		} else {
  1021 		    ta_parse_polygon_context(data);
  1024 	    break;
  1025 	case TA_CMD_SPRITE_CONTEXT:
  1026 	    if( ta_status.state == STATE_IDLE ) {
  1027 		ta_init_list( TA_POLYCMD_LISTTYPE( data->i ) );
  1030 	    if( ta_status.vertex_count != 0 ) {
  1031 		ta_fill_vertexes();
  1032 		ta_commit_polygon();
  1035 	    ta_parse_sprite_context(data);
  1036 	    break;
  1037 	case TA_CMD_VERTEX:
  1038 	    ta_status.state = STATE_IN_POLYGON;
  1039 	    ta_parse_vertex(data);
  1041 	    if( ta_status.state == STATE_EXPECT_VERTEX_BLOCK2 ) {
  1042 		if( TA_IS_END_VERTEX(data[0].i) ) {
  1043 		    ta_status.state = STATE_EXPECT_END_VERTEX_BLOCK2;
  1045 	    } else if( TA_IS_END_VERTEX(data->i) ) {
  1046 		ta_commit_polygon();
  1047 		ta_status.vertex_count = 0;
  1048 		ta_status.poly_parity = 0;
  1049 		ta_status.state = STATE_IN_LIST;
  1050 	    } else if( ta_status.vertex_count == ta_status.max_vertex ) {
  1051 		ta_split_polygon();
  1053 	    break;
  1055 	break;
  1062 /**
  1063  * Write a block of data to the tile accelerator, adding the data to the 
  1064  * current scene. We don't make any particular attempt to interpret the data
  1065  * at this stage, deferring that until render time.
  1067  * Currently copies the data verbatim to the vertex buffer, processing only
  1068  * far enough to generate the correct end-of-list events. Tile buffer is
  1069  * entirely ignored.
  1070  */
  1071 void pvr2_ta_write( char *buf, uint32_t length )
  1073     if( ta_status.debug_output ) {
  1074 	fwrite_dump32( (uint32_t *)buf, length, stderr );
  1077     for( ; length >=32; length -= 32 ) {
  1078 	pvr2_ta_process_block( buf );
  1079 	buf += 32;
.