Search
lxdream.org :: lxdream/src/pvr2/tacore.c :: diff
lxdream 0.9.1
released Jun 29
Download Now
filename src/pvr2/tacore.c
changeset 189:615b70cfd729
next193:31151fcc3cb7
author nkeynes
date Wed Aug 02 04:06:45 2006 +0000 (15 years ago)
permissions -rw-r--r--
last change Issue 0003: TA Vertex compiler
Initial implementation of the TA.
Renderer hooked up to the TA "properly" now as well
file annotate diff log raw
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/src/pvr2/tacore.c Wed Aug 02 04:06:45 2006 +0000
1.3 @@ -0,0 +1,975 @@
1.4 +/**
1.5 + * $Id: tacore.c,v 1.1 2006-08-02 04:06:45 nkeynes Exp $
1.6 + *
1.7 + * PVR2 Tile Accelerator implementation
1.8 + *
1.9 + * Copyright (c) 2005 Nathan Keynes.
1.10 + *
1.11 + * This program is free software; you can redistribute it and/or modify
1.12 + * it under the terms of the GNU General Public License as published by
1.13 + * the Free Software Foundation; either version 2 of the License, or
1.14 + * (at your option) any later version.
1.15 + *
1.16 + * This program is distributed in the hope that it will be useful,
1.17 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1.18 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1.19 + * GNU General Public License for more details.
1.20 + */
1.21 +#include "pvr2.h"
1.22 +#include "asic.h"
1.23 +
1.24 +#define STATE_IDLE 0
1.25 +#define STATE_IN_LIST 1
1.26 +#define STATE_EXPECT_POLY_BLOCK2 2
1.27 +#define STATE_EXPECT_VERTEX_BLOCK2 3
1.28 +#define STATE_ERROR 4
1.29 +#define STATE_EXPECT_END_VERTEX_BLOCK2 7
1.30 +
1.31 +#define TA_CMD(i) ( (i) >> 29 )
1.32 +#define TA_CMD_END_LIST 0
1.33 +#define TA_CMD_CLIP 1
1.34 +#define TA_CMD_POLYGON_CONTEXT 4
1.35 +#define TA_CMD_SPRITE_CONTEXT 5
1.36 +#define TA_CMD_VERTEX 7
1.37 +
1.38 +#define TA_LIST_NONE -1
1.39 +#define TA_LIST_OPAQUE 0
1.40 +#define TA_LIST_OPAQUE_MOD 1
1.41 +#define TA_LIST_TRANS 2
1.42 +#define TA_LIST_TRANS_MOD 3
1.43 +#define TA_LIST_PUNCH_OUT 4
1.44 +#define TA_IS_MODIFIER_LIST(list) (list == TA_LIST_OPAQUE_MOD || list == TA_LIST_TRANS_MOD)
1.45 +
1.46 +#define TA_GROW_UP 0
1.47 +#define TA_GROW_DOWN 1
1.48 +
1.49 +#define TA_VERTEX_NONE -1
1.50 +#define TA_VERTEX_PACKED 0x00
1.51 +#define TA_VERTEX_TEX_PACKED 0x08
1.52 +#define TA_VERTEX_TEX_SPEC_PACKED 0x0C
1.53 +#define TA_VERTEX_TEX_UV16_PACKED 0x09
1.54 +#define TA_VERTEX_TEX_UV16_SPEC_PACKED 0x0D
1.55 +#define TA_VERTEX_FLOAT 0x10
1.56 +#define TA_VERTEX_TEX_FLOAT 0x18
1.57 +#define TA_VERTEX_TEX_SPEC_FLOAT 0x1C
1.58 +#define TA_VERTEX_TEX_UV16_FLOAT 0x19
1.59 +#define TA_VERTEX_TEX_UV16_SPEC_FLOAT 0x1D
1.60 +#define TA_VERTEX_INTENSITY 0x20
1.61 +#define TA_VERTEX_TEX_INTENSITY 0x28
1.62 +#define TA_VERTEX_TEX_SPEC_INTENSITY 0x2C
1.63 +#define TA_VERTEX_TEX_UV16_INTENSITY 0x29
1.64 +#define TA_VERTEX_TEX_UV16_SPEC_INTENSITY 0x2D
1.65 +#define TA_VERTEX_PACKED_MOD 0x40
1.66 +#define TA_VERTEX_TEX_PACKED_MOD 0x48
1.67 +#define TA_VERTEX_TEX_SPEC_PACKED_MOD 0x4C
1.68 +#define TA_VERTEX_TEX_UV16_PACKED_MOD 0x49
1.69 +#define TA_VERTEX_TEX_UV16_SPEC_PACKED_MOD 0x4D
1.70 +#define TA_VERTEX_INTENSITY_MOD 0x60
1.71 +#define TA_VERTEX_TEX_INTENSITY_MOD 0x68
1.72 +#define TA_VERTEX_TEX_SPEC_INTENSITY_MOD 0x6C
1.73 +#define TA_VERTEX_TEX_UV16_INTENSITY_MOD 0x69
1.74 +#define TA_VERTEX_TEX_UV16_SPEC_INTENSITY_MOD 0x6D
1.75 +#define TA_VERTEX_SPRITE 0x80
1.76 +#define TA_VERTEX_TEX_SPRITE 0x88
1.77 +#define TA_VERTEX_MOD_VOLUME 0x81
1.78 +
1.79 +#define TA_IS_NORMAL_POLY() (ta_status.current_vertex_type < TA_VERTEX_SPRITE)
1.80 +
1.81 +static int strip_lengths[4] = {3,4,6,8}; /* in vertexes */
1.82 +#define TA_POLYCMD_LISTTYPE(i) ( ((i) >> 24) & 0x0F )
1.83 +#define TA_POLYCMD_LENGTH(i) strip_lengths[((i >> 18) & 0x03)]
1.84 +#define TA_POLYCMD_CLIP(i) ((i>>16)&0x03)
1.85 +#define TA_POLYCMD_COLOURFMT(i) (i & 0x00000030)
1.86 +#define TA_POLYCMD_COLOURFMT_ARGB32 0x00000000
1.87 +#define TA_POLYCMD_COLOURFMT_FLOAT 0x00000010
1.88 +#define TA_POLYCMD_COLOURFMT_INTENSITY 0x00000020
1.89 +#define TA_POLYCMD_COLOURFMT_LASTINT 0x00000030
1.90 +
1.91 +#define TA_POLYCMD_MODIFIED 0x00000080
1.92 +#define TA_POLYCMD_FULLMOD 0x00000040
1.93 +#define TA_POLYCMD_TEXTURED 0x00000008
1.94 +#define TA_POLYCMD_SPECULAR 0x00000004
1.95 +#define TA_POLYCMD_SHADED 0x00000002
1.96 +#define TA_POLYCMD_UV16 0x00000001
1.97 +
1.98 +#define TA_POLYCMD_IS_SPECULAR(i) ((i & 0x0000000C)==0x0000000C) /* Only applies to textured polys */
1.99 +#define TA_POLYCMD_IS_FULLMOD(i) ((i & 0x000000C0)==0x000000C0)
1.100 +
1.101 +
1.102 +#define TA_IS_END_VERTEX(i) (i & 0x10000000)
1.103 +
1.104 +#define MIN3( x1, x2, x3 ) ( (x1)<(x2)? ((x1)<(x3)?(x1):(x3)) : ((x2)<(x3)?(x2):(x3)) )
1.105 +#define MAX3( x1, x2, x3 ) ( (x1)>(x2)? ((x1)>(x3)?(x1):(x3)) : ((x2)>(x3)?(x2):(x3)) )
1.106 +
1.107 +#define TILESLOT( x, y ) (ta_status.current_tile_matrix + (ta_status.current_tile_size * (y * ta_status.width+ x) << 2))
1.108 +
1.109 +extern char *video_base;
1.110 +#define PVRRAM(addr) (*(uint32_t *)(video_base + ((addr)&PVR2_RAM_MASK)))
1.111 +
1.112 +struct pvr2_ta_vertex {
1.113 + float x,y,z;
1.114 + uint32_t detail[8]; /* 0-8 detail words */
1.115 +};
1.116 +
1.117 +struct tile_bounds {
1.118 + int x1, y1, x2, y2;
1.119 +};
1.120 +
1.121 +struct pvr2_ta_status {
1.122 + int state;
1.123 + int width, height; /* Tile resolution, ie 20x15 */
1.124 + int tilelist_dir; /* Growth direction of the tilelist, 0 = up, 1 = down */
1.125 + uint32_t tilelist_size; /* Size of the tilelist segments */
1.126 + int current_vertex_type;
1.127 + int vertex_count; /* index of last start-vertex seen, or -1 if no vertexes
1.128 + * are present
1.129 + */
1.130 + int max_vertex; /* Maximum number of vertexes in the current polygon (3/4/6/8) */
1.131 + int current_list_type;
1.132 + uint32_t current_tile_matrix; /* Memory location of the first tile for the current list. */
1.133 + uint32_t current_tile_size; /* Size of the tile matrix space in 32-bit words (0/8/16/32)*/
1.134 + uint32_t intensity1, intensity2;
1.135 + /**
1.136 + * Current working object
1.137 + */
1.138 + int poly_context_size;
1.139 + int poly_vertex_size;
1.140 + int poly_parity;
1.141 + uint32_t poly_context[5];
1.142 + uint32_t poly_pointer;
1.143 + struct tile_bounds last_triangle_bounds;
1.144 + struct pvr2_ta_vertex poly_vertex[8];
1.145 + int debug_output;
1.146 +};
1.147 +
1.148 +static struct pvr2_ta_status ta_status;
1.149 +
1.150 +static int tilematrix_sizes[4] = {0,8,16,32};
1.151 +
1.152 +/**
1.153 + * Convenience union - ta data is either 32-bit integer or 32-bit float.
1.154 + */
1.155 +union ta_data {
1.156 + unsigned int i;
1.157 + float f;
1.158 +};
1.159 +
1.160 +
1.161 +void pvr2_ta_reset() {
1.162 + ta_status.state = STATE_ERROR; /* State not valid until initialized */
1.163 + ta_status.debug_output = 0;
1.164 +}
1.165 +
1.166 +void pvr2_ta_init() {
1.167 + ta_status.state = STATE_IDLE;
1.168 + ta_status.current_list_type = -1;
1.169 + ta_status.current_vertex_type = -1;
1.170 + ta_status.poly_parity = 0;
1.171 + ta_status.vertex_count = 0;
1.172 + ta_status.max_vertex = 3;
1.173 + ta_status.last_triangle_bounds.x1 = -1;
1.174 +
1.175 + uint32_t size = MMIO_READ( PVR2, TA_TILESIZE );
1.176 + ta_status.width = (size & 0xFFFF) + 1;
1.177 + ta_status.height = (size >> 16) + 1;
1.178 + uint32_t control = MMIO_READ( PVR2, TA_TILECFG );
1.179 + ta_status.tilelist_dir = (control >> 20) & 0x01;
1.180 + ta_status.tilelist_size = tilematrix_sizes[ (control & 0x03) ];
1.181 + MMIO_WRITE( PVR2, TA_POLYPOS, MMIO_READ( PVR2, TA_POLYBASE ) );
1.182 + uint32_t plistpos = MMIO_READ( PVR2, TA_LISTBASE ) >> 2;
1.183 + if( ta_status.tilelist_dir == TA_GROW_DOWN ) {
1.184 + plistpos -= ta_status.tilelist_size;
1.185 + }
1.186 + MMIO_WRITE( PVR2, TA_LISTPOS, plistpos );
1.187 +}
1.188 +
1.189 +static uint32_t parse_float_colour( float a, float r, float g, float b ) {
1.190 + return
1.191 + (((unsigned int)((256 * CLAMP(a,0.0,1.0))-1))<<24) |
1.192 + (((unsigned int)((256 * CLAMP(r,0.0,1.0))-1))<<16) |
1.193 + (((unsigned int)((256 * CLAMP(g,0.0,1.0))-1))<<8) |
1.194 + (((unsigned int)((256 * CLAMP(b,0.0,1.0))-1)));
1.195 +}
1.196 +
1.197 +static uint32_t parse_intensity_colour( uint32_t base, float intensity )
1.198 +{
1.199 + unsigned int i = (unsigned int)(256 * CLAMP(intensity, 0.0,1.0));
1.200 +
1.201 + return
1.202 + (((((base & 0xFF) * i) & 0xFF00) |
1.203 + (((base & 0xFF00) * i) & 0xFF0000) |
1.204 + (((base & 0xFF0000) * i) & 0xFF000000)) >> 8) |
1.205 + base & 0xFF000000;
1.206 +}
1.207 +
1.208 +/**
1.209 + * Initialize the specified TA list.
1.210 + */
1.211 +static void ta_init_list( unsigned int listtype ) {
1.212 + int config = MMIO_READ( PVR2, TA_TILECFG );
1.213 + int tile_matrix = MMIO_READ( PVR2, TA_TILEBASE );
1.214 + if( listtype <= TA_LIST_PUNCH_OUT ) {
1.215 + int i;
1.216 + uint32_t *p;
1.217 + for( i=0; i < listtype; i++ ) {
1.218 + int size = tilematrix_sizes[(config & 0x03)] << 2;
1.219 + tile_matrix += ta_status.width * ta_status.height * size;
1.220 + config >>= 4;
1.221 + }
1.222 + ta_status.current_tile_matrix = tile_matrix;
1.223 + ta_status.current_tile_size = tilematrix_sizes[(config & 0x03)];
1.224 +
1.225 + /* Initialize each tile to 0xF0000000 */
1.226 + if( ta_status.current_tile_size != 0 ) {
1.227 + p = (uint32_t *)(video_base + tile_matrix);
1.228 + for( i=0; i< ta_status.width * ta_status.height; i++ ) {
1.229 + *p = 0xF0000000;
1.230 + p += ta_status.current_tile_size;
1.231 + }
1.232 + }
1.233 + }
1.234 + ta_status.state = STATE_IN_LIST;
1.235 + ta_status.current_list_type = listtype;
1.236 + ta_status.last_triangle_bounds.x1 = -1;
1.237 +}
1.238 +
1.239 +static int list_events[5] = {EVENT_PVR_OPAQUE_DONE, EVENT_PVR_OPAQUEMOD_DONE,
1.240 + EVENT_PVR_TRANS_DONE, EVENT_PVR_TRANSMOD_DONE,
1.241 + EVENT_PVR_PUNCHOUT_DONE };
1.242 +
1.243 +static void ta_end_list() {
1.244 + if( ta_status.current_list_type != TA_LIST_NONE ) {
1.245 + asic_event( list_events[ta_status.current_list_type] );
1.246 + ta_status.current_list_type = TA_LIST_NONE;
1.247 + ta_status.current_vertex_type = -1;
1.248 + ta_status.state = STATE_IDLE;
1.249 + }
1.250 +}
1.251 +
1.252 +/**
1.253 + * Write data out to the polygon buffer.
1.254 + * If the end-of-buffer is reached, asserts EVENT_PVR_PRIM_ALLOC_FAIL
1.255 + * @param data to be written
1.256 + * @param length Number of 32-bit words to write.
1.257 + * @return number of words actually written
1.258 + */
1.259 +static int ta_write_polygon_buffer( uint32_t *data, int length )
1.260 +{
1.261 + int rv;
1.262 + int posn = MMIO_READ( PVR2, TA_POLYPOS );
1.263 + int end = MMIO_READ( PVR2, TA_POLYEND );
1.264 + uint32_t *target = (uint32_t *)(video_base + posn);
1.265 + for( rv=0; rv < length; rv++ ) {
1.266 + if( posn == end ) {
1.267 + asic_event( EVENT_PVR_PRIM_ALLOC_FAIL );
1.268 + asic_event( EVENT_TA_ERROR );
1.269 + // ta_status.state = STATE_ERROR;
1.270 + break;
1.271 + }
1.272 + *target++ = *data++;
1.273 + posn += 4;
1.274 + }
1.275 +
1.276 + MMIO_WRITE( PVR2, TA_POLYPOS, posn );
1.277 + return rv;
1.278 +}
1.279 +
1.280 +/**
1.281 + * Allocate a new tile list from the grow space
1.282 + */
1.283 +static uint32_t ta_alloc_tilelist() {
1.284 + uint32_t posn = MMIO_READ( PVR2, TA_LISTPOS );
1.285 + uint32_t newposn;
1.286 + if( ta_status.tilelist_dir == TA_GROW_DOWN ) {
1.287 + newposn = posn - ta_status.tilelist_size;
1.288 + } else {
1.289 + newposn = posn + ta_status.tilelist_size;
1.290 + }
1.291 + MMIO_WRITE( PVR2, TA_LISTPOS, newposn );
1.292 + return posn << 2;
1.293 +}
1.294 +
1.295 +/**
1.296 + * Write a tile entry out to the matrix.
1.297 + */
1.298 +static int ta_write_tile_entry( int x, int y, uint32_t tile_entry ) {
1.299 + uint32_t tile = TILESLOT(x,y);
1.300 + uint32_t value;
1.301 + uint32_t lasttri = 0;
1.302 + int i,l;
1.303 +
1.304 + if( (tile_entry & 0x80000000) &&
1.305 + ta_status.last_triangle_bounds.x1 != -1 &&
1.306 + ta_status.last_triangle_bounds.x1 <= x &&
1.307 + ta_status.last_triangle_bounds.x2 >= x &&
1.308 + ta_status.last_triangle_bounds.y1 <= y &&
1.309 + ta_status.last_triangle_bounds.y2 >= y ) {
1.310 + /* potential for triangle stacking */
1.311 + lasttri = tile_entry & 0xE1E00000;
1.312 + }
1.313 +
1.314 +
1.315 + if( PVRRAM(tile) == 0xF0000000 ) {
1.316 + PVRRAM(tile) = tile_entry;
1.317 + PVRRAM(tile+4) = 0xF0000000;
1.318 + return;
1.319 + }
1.320 +
1.321 + while(1) {
1.322 + value = PVRRAM(tile);
1.323 + for( i=1; i<ta_status.current_tile_size; i++ ) {
1.324 + tile += 4;
1.325 + uint32_t nextval = PVRRAM(tile);
1.326 + if( nextval == 0xF0000000 ) {
1.327 + if( lasttri != 0 && lasttri == (value&0xE1E00000) ) {
1.328 + int count = (value & 0x1E000000) + 0x02000000;
1.329 + if( count < 0x20000000 ) {
1.330 + PVRRAM(tile-4) = (value & 0xE1FFFFFF) | count;
1.331 + return;
1.332 + }
1.333 + }
1.334 + if( i < ta_status.current_tile_size-1 ) {
1.335 + PVRRAM(tile) = tile_entry;
1.336 + PVRRAM(tile+4) = 0xF0000000;
1.337 + return;
1.338 + }
1.339 + }
1.340 + value = nextval;
1.341 + }
1.342 +
1.343 + if( value == 0xF0000000 ) {
1.344 + value = ta_alloc_tilelist();
1.345 + PVRRAM(tile) = value | 0xE0000000;
1.346 + tile = value;
1.347 + PVRRAM(tile) = tile_entry;
1.348 + PVRRAM(tile+4) = 0xF0000000;
1.349 + return;
1.350 + } else if( (value & 0xFF000000) == 0xE0000000 ) {
1.351 + tile = (value & 0x00FFFFFF);
1.352 + } else {
1.353 + /* This should never happen */
1.354 + return 0;
1.355 + }
1.356 + }
1.357 +}
1.358 +
1.359 +/**
1.360 + * Write a completed polygon out to the memory buffers
1.361 + * OPTIMIZEME: This is not terribly efficient at the moment.
1.362 + */
1.363 +static void ta_commit_polygon( ) {
1.364 + int i, x, y;
1.365 + int tx[ta_status.vertex_count], ty[ta_status.vertex_count];
1.366 + struct tile_bounds triangle_bound[ta_status.vertex_count - 2];
1.367 + struct tile_bounds polygon_bound;
1.368 + uint32_t poly_context[5];
1.369 +
1.370 + if( ta_status.vertex_count < 2 ) {
1.371 + return; /* No polygons - ignore */
1.372 + }
1.373 + memcpy( poly_context, ta_status.poly_context, ta_status.poly_context_size * 4 );
1.374 +
1.375 + /* Compute the tile coordinates for each vertex (need to be careful with
1.376 + * clamping here)
1.377 + */
1.378 + for( i=0; i<ta_status.vertex_count; i++ ) {
1.379 + if( ta_status.poly_vertex[i].x < 0.0 ) {
1.380 + tx[i] = -1;
1.381 + } else if( ta_status.poly_vertex[i].x > (float)INT_MAX ) {
1.382 + tx[i] = INT_MAX/32;
1.383 + } else {
1.384 + tx[i] = (int)(ta_status.poly_vertex[i].x / 32.0);
1.385 + }
1.386 + if( ta_status.poly_vertex[i].y < 0.0 ) {
1.387 + ty[i] = -1;
1.388 + } else if( ta_status.poly_vertex[i].y > (float)INT_MAX ) {
1.389 + ty[i] = INT_MAX/32;
1.390 + } else {
1.391 + ty[i] = (int)(ta_status.poly_vertex[i].y / 32.0);
1.392 + }
1.393 +
1.394 + }
1.395 +
1.396 + /* Compute bounding box for each triangle individually, as well
1.397 + * as the overall polygon.
1.398 + */
1.399 +
1.400 + for( i=0; i<ta_status.vertex_count-2; i++ ) {
1.401 + triangle_bound[i].x1 = MIN3(tx[i],tx[i+1],tx[i+2]);
1.402 + triangle_bound[i].x2 = MAX3(tx[i],tx[i+1],tx[i+2]);
1.403 + triangle_bound[i].y1 = MIN3(ty[i],ty[i+1],ty[i+2]);
1.404 + triangle_bound[i].y2 = MAX3(ty[i],ty[i+1],ty[i+2]);
1.405 + if( i == 0 ) {
1.406 + polygon_bound.x1 = triangle_bound[0].x1;
1.407 + polygon_bound.y1 = triangle_bound[0].y1;
1.408 + polygon_bound.x2 = triangle_bound[0].x2;
1.409 + polygon_bound.y2 = triangle_bound[0].y2;
1.410 + } else {
1.411 + polygon_bound.x1 = MIN(polygon_bound.x1, triangle_bound[i].x1);
1.412 + polygon_bound.x2 = MAX(polygon_bound.x2, triangle_bound[i].x2);
1.413 + polygon_bound.y1 = MIN(polygon_bound.y1, triangle_bound[i].y1);
1.414 + polygon_bound.y2 = MAX(polygon_bound.y2, triangle_bound[i].y2);
1.415 + }
1.416 + }
1.417 +
1.418 + /* If the polygon is actually entirely out of the frustum, clip it entirely */
1.419 + if( polygon_bound.x2 < 0 || polygon_bound.x1 > ta_status.width ||
1.420 + polygon_bound.y2 < 0 || polygon_bound.y1 > ta_status.height ) {
1.421 + return;
1.422 + }
1.423 +
1.424 + /* Clamp the polygon bounds to the frustum */
1.425 + if( polygon_bound.x1 < 0 ) polygon_bound.x1 = 0;
1.426 + if( polygon_bound.x2 >= ta_status.width ) polygon_bound.x2 = ta_status.width-1;
1.427 + if( polygon_bound.y1 < 0 ) polygon_bound.y1 = 0;
1.428 + if( polygon_bound.y2 >= ta_status.width ) polygon_bound.y2 = ta_status.height-1;
1.429 +
1.430 + /* Set the "single tile" flag if it's entirely contained in 1 tile */
1.431 + if( polygon_bound.x1 == polygon_bound.x2 &&
1.432 + polygon_bound.y1 == polygon_bound.y2 ) {
1.433 + poly_context[0] |= 0x00200000;
1.434 + }
1.435 +
1.436 + /* Ok, we're good to go - write out the polygon first */
1.437 + uint32_t tile_entry = MMIO_READ( PVR2, TA_POLYPOS ) >> 2 | ta_status.poly_pointer;
1.438 +
1.439 + int status = ta_write_polygon_buffer( poly_context, ta_status.poly_context_size );
1.440 + if( status == 0 ) {
1.441 + /* No memory available - abort */
1.442 + return;
1.443 + } else {
1.444 + for( i=0; i<ta_status.vertex_count && status != 0; i++ ) {
1.445 + status = ta_write_polygon_buffer( (uint32_t *)(&ta_status.poly_vertex[i]), 3 + ta_status.poly_vertex_size );
1.446 + }
1.447 + }
1.448 +
1.449 + /* And now the tile entries. Triangles are different from everything else */
1.450 + if( ta_status.vertex_count == 3 ) {
1.451 + tile_entry |= 0x80000000;
1.452 + for( y=polygon_bound.y1; y<=polygon_bound.y2; y++ ) {
1.453 + for( x=polygon_bound.x1; x<=polygon_bound.x2; x++ ) {
1.454 + ta_write_tile_entry( x,y,tile_entry );
1.455 + }
1.456 + }
1.457 + ta_status.last_triangle_bounds.x1 = polygon_bound.x1;
1.458 + ta_status.last_triangle_bounds.y1 = polygon_bound.y1;
1.459 + ta_status.last_triangle_bounds.x2 = polygon_bound.x2;
1.460 + ta_status.last_triangle_bounds.y2 = polygon_bound.y2;
1.461 + } else if( ta_status.current_vertex_type == TA_VERTEX_SPRITE ||
1.462 + ta_status.current_vertex_type == TA_VERTEX_TEX_SPRITE ) {
1.463 + tile_entry |= 0xA0000000;
1.464 + for( y=polygon_bound.y1; y<=polygon_bound.y2; y++ ) {
1.465 + for( x=polygon_bound.x1; x<=polygon_bound.x2; x++ ) {
1.466 + ta_write_tile_entry( x,y,tile_entry );
1.467 + }
1.468 + }
1.469 + ta_status.last_triangle_bounds.x1 = polygon_bound.x1;
1.470 + ta_status.last_triangle_bounds.y1 = polygon_bound.y1;
1.471 + ta_status.last_triangle_bounds.x2 = polygon_bound.x2;
1.472 + ta_status.last_triangle_bounds.y2 = polygon_bound.y2;
1.473 + } else {
1.474 + for( y=polygon_bound.y1; y<=polygon_bound.y2; y++ ) {
1.475 + for( x=polygon_bound.x1; x<=polygon_bound.x2; x++ ) {
1.476 + uint32_t entry = tile_entry;
1.477 + for( i=0; i<ta_status.vertex_count-2; i++ ) {
1.478 + if( triangle_bound[i].x1 <= x && triangle_bound[i].x2 >= x &&
1.479 + triangle_bound[i].y1 <= y && triangle_bound[i].y2 >= y ) {
1.480 + entry |= (0x40000000>>i);
1.481 + }
1.482 + }
1.483 + ta_write_tile_entry( x, y, entry );
1.484 + }
1.485 + }
1.486 + ta_status.last_triangle_bounds.x1 = -1;
1.487 + }
1.488 +}
1.489 +
1.490 +/**
1.491 + * Variant of ta_split_polygon called when vertex_count == max_vertex, but
1.492 + * the client hasn't sent the LAST VERTEX flag. Commit the poly as normal
1.493 + * first, then start a new poly with the first 2 vertexes taken from the
1.494 + * current one.
1.495 + */
1.496 +static void ta_split_polygon() {
1.497 + ta_commit_polygon();
1.498 + if( TA_IS_NORMAL_POLY() ) {
1.499 + /* This only applies to ordinary polys - Sprites + modifier lists are
1.500 + * handled differently
1.501 + */
1.502 + if( ta_status.vertex_count == 3 ) {
1.503 + /* Triangles use an odd/even scheme */
1.504 + if( ta_status.poly_parity == 0 ) {
1.505 + memcpy( &ta_status.poly_vertex[0], &ta_status.poly_vertex[2],
1.506 + sizeof(struct pvr2_ta_vertex) );
1.507 + ta_status.poly_parity = 1;
1.508 + } else {
1.509 + memcpy( &ta_status.poly_vertex[1], &ta_status.poly_vertex[2],
1.510 + sizeof(struct pvr2_ta_vertex) );
1.511 + ta_status.poly_parity = 0;
1.512 + }
1.513 + } else {
1.514 + /* Everything else just uses the last 2 vertexes in order */
1.515 + memcpy( &ta_status.poly_vertex[0], &ta_status.poly_vertex[ta_status.vertex_count-2],
1.516 + sizeof(struct pvr2_ta_vertex)*2 );
1.517 + ta_status.poly_parity = 0;
1.518 + }
1.519 + ta_status.vertex_count = 2;
1.520 + } else {
1.521 + ta_status.vertex_count = 0;
1.522 + }
1.523 +}
1.524 +
1.525 +/**
1.526 + * Parse the polygon context block and setup the internal state to receive
1.527 + * vertexes.
1.528 + * @param data 32 bytes of parameter data.
1.529 + */
1.530 +static void ta_parse_polygon_context( union ta_data *data ) {
1.531 + int colourfmt = TA_POLYCMD_COLOURFMT(data[0].i);
1.532 + ta_status.max_vertex = TA_POLYCMD_LENGTH(data[0].i);
1.533 + ta_status.vertex_count = 0;
1.534 + ta_status.poly_context[0] =
1.535 + (data[1].i & 0xFC1FFFFF) | ((data[0].i & 0x0B) << 22);
1.536 + ta_status.poly_context[1] = data[2].i;
1.537 + ta_status.poly_context[3] = data[4].i;
1.538 + ta_status.poly_parity = 0;
1.539 + if( data[0].i & TA_POLYCMD_TEXTURED ) {
1.540 + ta_status.current_vertex_type = data[0].i & 0x0D;
1.541 + ta_status.poly_context[2] = data[3].i;
1.542 + ta_status.poly_context[4] = data[5].i;
1.543 + if( data[0].i & TA_POLYCMD_SPECULAR ) {
1.544 + ta_status.poly_context[0] |= 0x01000000;
1.545 + ta_status.poly_vertex_size = 4;
1.546 + } else {
1.547 + ta_status.poly_vertex_size = 3;
1.548 + }
1.549 + if( data[0].i & TA_POLYCMD_UV16 ) {
1.550 + ta_status.poly_vertex_size--;
1.551 + }
1.552 + } else {
1.553 + ta_status.current_vertex_type = 0;
1.554 + ta_status.poly_vertex_size = 1;
1.555 + ta_status.poly_context[2] = 0;
1.556 + ta_status.poly_context[4] = 0;
1.557 + }
1.558 +
1.559 + ta_status.poly_pointer = (ta_status.poly_vertex_size << 21);
1.560 + ta_status.poly_context_size = 3;
1.561 + if( data[0].i & TA_POLYCMD_MODIFIED ) {
1.562 + ta_status.poly_pointer |= 0x01000000;
1.563 + if( data[0].i & TA_POLYCMD_FULLMOD ) {
1.564 + ta_status.poly_context_size = 5;
1.565 + ta_status.poly_vertex_size <<= 1;
1.566 + ta_status.current_vertex_type |= 0x40;
1.567 + /* Modified/float not supported - behaves as per last intensity */
1.568 + if( colourfmt == TA_POLYCMD_COLOURFMT_FLOAT ) {
1.569 + colourfmt = TA_POLYCMD_COLOURFMT_LASTINT;
1.570 + }
1.571 + }
1.572 + }
1.573 +
1.574 + if( colourfmt == TA_POLYCMD_COLOURFMT_INTENSITY ) {
1.575 + if( TA_POLYCMD_IS_FULLMOD(data[0].i) ||
1.576 + TA_POLYCMD_IS_SPECULAR(data[0].i) ) {
1.577 + ta_status.state = STATE_EXPECT_POLY_BLOCK2;
1.578 + } else {
1.579 + ta_status.intensity1 =
1.580 + parse_float_colour( data[4].f, data[5].f, data[6].f, data[7].f );
1.581 + }
1.582 + } else if( colourfmt == TA_POLYCMD_COLOURFMT_LASTINT ) {
1.583 + colourfmt = TA_POLYCMD_COLOURFMT_INTENSITY;
1.584 + }
1.585 +
1.586 + ta_status.current_vertex_type |= colourfmt;
1.587 +}
1.588 +
1.589 +/**
1.590 + * Parse the modifier volume context block and setup the internal state to
1.591 + * receive modifier vertexes.
1.592 + * @param data 32 bytes of parameter data.
1.593 + */
1.594 +static void ta_parse_modifier_context( union ta_data *data ) {
1.595 + ta_status.current_vertex_type = TA_VERTEX_MOD_VOLUME;
1.596 + ta_status.poly_vertex_size = 0;
1.597 + ta_status.poly_context_size = 3;
1.598 + ta_status.poly_context[0] = (data[1].i & 0xFC1FFFFF) |
1.599 + ((data[0].i & 0x0B)<<22);
1.600 + if( TA_POLYCMD_IS_SPECULAR(data[0].i) ) {
1.601 + ta_status.poly_context[0] |= 0x01000000;
1.602 + }
1.603 + ta_status.poly_context[1] = 0;
1.604 + ta_status.poly_context[2] = 0;
1.605 + ta_status.vertex_count = 0;
1.606 + ta_status.max_vertex = 3;
1.607 + ta_status.poly_pointer = 0;
1.608 +}
1.609 +
1.610 +/**
1.611 + * Parse the sprite context block and setup the internal state to receive
1.612 + * vertexes.
1.613 + * @param data 32 bytes of parameter data.
1.614 + */
1.615 +static void ta_parse_sprite_context( union ta_data *data ) {
1.616 + ta_status.poly_context_size = 3;
1.617 + ta_status.poly_context[0] = (data[1].i & 0xFC1FFFFF) |
1.618 + ((data[0].i & 0x0B)<<22) | 0x00400000;
1.619 + if( TA_POLYCMD_IS_SPECULAR(data[0].i) ) {
1.620 + ta_status.poly_context[0] |= 0x01000000;
1.621 + }
1.622 + ta_status.poly_context[1] = data[2].i;
1.623 + ta_status.poly_context[2] = data[3].i;
1.624 + if( data[0].i & TA_POLYCMD_TEXTURED ) {
1.625 + ta_status.poly_vertex_size = 2;
1.626 + ta_status.poly_vertex[2].detail[1] = data[4].i;
1.627 + ta_status.current_vertex_type = TA_VERTEX_TEX_SPRITE;
1.628 + } else {
1.629 + ta_status.poly_vertex_size = 1;
1.630 + ta_status.poly_vertex[2].detail[0] = data[4].i;
1.631 + ta_status.current_vertex_type = TA_VERTEX_SPRITE;
1.632 + }
1.633 + ta_status.vertex_count = 0;
1.634 + ta_status.max_vertex = 4;
1.635 + ta_status.poly_pointer = (ta_status.poly_vertex_size << 21);
1.636 +}
1.637 +
1.638 +/**
1.639 + * Copy the last read vertex into all vertexes up to max_vertex. Used for
1.640 + * Aborted polygons under some circumstances.
1.641 + */
1.642 +static void ta_fill_vertexes( ) {
1.643 + int i;
1.644 + for( i=ta_status.vertex_count; i<ta_status.max_vertex; i++ ) {
1.645 + memcpy( &ta_status.poly_vertex[i], &ta_status.poly_vertex[ta_status.vertex_count-1],
1.646 + sizeof( struct pvr2_ta_vertex ) );
1.647 + }
1.648 + ta_status.vertex_count = ta_status.max_vertex;
1.649 +}
1.650 +
1.651 +static void ta_parse_vertex( union ta_data *data ) {
1.652 + struct pvr2_ta_vertex *vertex = &ta_status.poly_vertex[ta_status.vertex_count];
1.653 + vertex->x = data[1].f;
1.654 + vertex->y = data[2].f;
1.655 + vertex->z = data[3].f;
1.656 +
1.657 + switch( ta_status.current_vertex_type ) {
1.658 + case TA_VERTEX_PACKED:
1.659 + vertex->detail[0] = data[6].i;
1.660 + break;
1.661 + case TA_VERTEX_FLOAT:
1.662 + vertex->detail[0] = parse_float_colour( data[4].f, data[5].f, data[6].f, data[7].f );
1.663 + break;
1.664 + case TA_VERTEX_INTENSITY:
1.665 + vertex->detail[0] = parse_intensity_colour( ta_status.intensity1, data[6].f );
1.666 + break;
1.667 +
1.668 + case TA_VERTEX_TEX_SPEC_PACKED:
1.669 + vertex->detail[3] = data[7].i; /* ARGB */
1.670 + /* Fallthrough */
1.671 + case TA_VERTEX_TEX_PACKED:
1.672 + vertex->detail[0] = data[4].i; /* U */
1.673 + vertex->detail[1] = data[5].i; /* V */
1.674 + vertex->detail[2] = data[6].i; /* ARGB */
1.675 + break;
1.676 + case TA_VERTEX_TEX_UV16_SPEC_PACKED:
1.677 + vertex->detail[2] = data[7].i; /* ARGB */
1.678 + /* Fallthrough */
1.679 + case TA_VERTEX_TEX_UV16_PACKED:
1.680 + vertex->detail[0] = data[4].i; /* UV */
1.681 + vertex->detail[1] = data[6].i; /* ARGB */
1.682 + break;
1.683 +
1.684 + case TA_VERTEX_TEX_FLOAT:
1.685 + case TA_VERTEX_TEX_SPEC_FLOAT:
1.686 + vertex->detail[0] = data[4].i; /* U */
1.687 + vertex->detail[1] = data[5].i; /* UV */
1.688 + ta_status.state = STATE_EXPECT_VERTEX_BLOCK2;
1.689 + break;
1.690 + case TA_VERTEX_TEX_UV16_FLOAT:
1.691 + case TA_VERTEX_TEX_UV16_SPEC_FLOAT:
1.692 + vertex->detail[0] = data[4].i; /* UV */
1.693 + ta_status.state = STATE_EXPECT_VERTEX_BLOCK2;
1.694 + break;
1.695 +
1.696 + case TA_VERTEX_TEX_SPEC_INTENSITY:
1.697 + vertex->detail[3] = parse_intensity_colour( ta_status.intensity2, data[7].f );
1.698 + /* Fallthrough */
1.699 + case TA_VERTEX_TEX_INTENSITY:
1.700 + vertex->detail[0] = data[4].i; /* U */
1.701 + vertex->detail[1] = data[5].i; /* V */
1.702 + vertex->detail[2] = parse_intensity_colour( ta_status.intensity1, data[6].f );
1.703 + break;
1.704 + case TA_VERTEX_TEX_UV16_SPEC_INTENSITY:
1.705 + vertex->detail[2] = parse_intensity_colour( ta_status.intensity2, data[7].f );
1.706 + /* Fallthrough */
1.707 + case TA_VERTEX_TEX_UV16_INTENSITY:
1.708 + vertex->detail[0] = data[4].i; /* UV */
1.709 + vertex->detail[1] = parse_intensity_colour( ta_status.intensity1, data[6].f );
1.710 + break;
1.711 +
1.712 + case TA_VERTEX_PACKED_MOD:
1.713 + vertex->detail[0] = data[4].i; /* ARGB */
1.714 + vertex->detail[1] = data[5].i; /* ARGB */
1.715 + break;
1.716 + case TA_VERTEX_INTENSITY_MOD:
1.717 + vertex->detail[0] = parse_intensity_colour( ta_status.intensity1, data[4].f );
1.718 + vertex->detail[1] = parse_intensity_colour( ta_status.intensity2, data[5].f );
1.719 + break;
1.720 +
1.721 + case TA_VERTEX_TEX_SPEC_PACKED_MOD:
1.722 + vertex->detail[3] = data[7].i; /* ARGB0 */
1.723 + /* Fallthrough */
1.724 + case TA_VERTEX_TEX_PACKED_MOD:
1.725 + vertex->detail[0] = data[4].i; /* U0 */
1.726 + vertex->detail[1] = data[5].i; /* V0 */
1.727 + vertex->detail[2] = data[6].i; /* ARGB0 */
1.728 + ta_status.state = STATE_EXPECT_VERTEX_BLOCK2;
1.729 + break;
1.730 + case TA_VERTEX_TEX_UV16_SPEC_PACKED_MOD:
1.731 + vertex->detail[2] = data[7].i; /* ARGB0 */
1.732 + /* Fallthrough */
1.733 + case TA_VERTEX_TEX_UV16_PACKED_MOD:
1.734 + vertex->detail[0] = data[4].i; /* UV0 */
1.735 + vertex->detail[1] = data[6].i; /* ARGB0 */
1.736 + ta_status.state = STATE_EXPECT_VERTEX_BLOCK2;
1.737 + break;
1.738 +
1.739 + case TA_VERTEX_TEX_SPEC_INTENSITY_MOD:
1.740 + vertex->detail[3] = parse_intensity_colour( ta_status.intensity1, data[7].f );
1.741 + /* Fallthrough */
1.742 + case TA_VERTEX_TEX_INTENSITY_MOD:
1.743 + vertex->detail[0] = data[4].i; /* U0 */
1.744 + vertex->detail[1] = data[5].i; /* V0 */
1.745 + vertex->detail[2] = parse_intensity_colour( ta_status.intensity1, data[6].f );
1.746 + ta_status.state = STATE_EXPECT_VERTEX_BLOCK2;
1.747 + break;
1.748 + case TA_VERTEX_TEX_UV16_SPEC_INTENSITY_MOD:
1.749 + vertex->detail[2] = parse_intensity_colour( ta_status.intensity1, data[7].f );
1.750 + /* Fallthrough */
1.751 + case TA_VERTEX_TEX_UV16_INTENSITY_MOD:
1.752 + vertex->detail[0] = data[4].i; /* UV0 */
1.753 + vertex->detail[1] = parse_intensity_colour( ta_status.intensity1, data[6].f );
1.754 + ta_status.state = STATE_EXPECT_VERTEX_BLOCK2;
1.755 + break;
1.756 +
1.757 + case TA_VERTEX_SPRITE:
1.758 + case TA_VERTEX_TEX_SPRITE:
1.759 + case TA_VERTEX_MOD_VOLUME:
1.760 + vertex++;
1.761 + vertex->x = data[4].f;
1.762 + vertex->y = data[5].f;
1.763 + vertex->z = data[6].f;
1.764 + vertex++;
1.765 + vertex->x = data[7].f;
1.766 + ta_status.vertex_count += 2;
1.767 + ta_status.state = STATE_EXPECT_VERTEX_BLOCK2;
1.768 + break;
1.769 + }
1.770 + ta_status.vertex_count++;
1.771 +}
1.772 +
1.773 +static void ta_parse_vertex_block2( union ta_data *data ) {
1.774 + struct pvr2_ta_vertex *vertex = &ta_status.poly_vertex[ta_status.vertex_count-1];
1.775 +
1.776 + switch( ta_status.current_vertex_type ) {
1.777 + case TA_VERTEX_TEX_SPEC_FLOAT:
1.778 + vertex->detail[3] = parse_float_colour( data[4].f, data[5].f, data[6].f, data[7].f );
1.779 + /* Fallthrough */
1.780 + case TA_VERTEX_TEX_FLOAT:
1.781 + vertex->detail[2] = parse_float_colour( data[0].f, data[1].f, data[2].f, data[3].f );
1.782 + break;
1.783 + case TA_VERTEX_TEX_UV16_SPEC_FLOAT:
1.784 + vertex->detail[2] = parse_float_colour( data[4].f, data[5].f, data[6].f, data[7].f );
1.785 + /* Fallthrough */
1.786 + case TA_VERTEX_TEX_UV16_FLOAT:
1.787 + vertex->detail[1] = parse_float_colour( data[0].f, data[1].f, data[2].f, data[3].f );
1.788 + break;
1.789 + case TA_VERTEX_TEX_PACKED_MOD:
1.790 + vertex->detail[3] = data[0].i; /* U1 */
1.791 + vertex->detail[4] = data[1].i; /* V1 */
1.792 + vertex->detail[5] = data[2].i; /* ARGB1 */
1.793 + break;
1.794 + case TA_VERTEX_TEX_SPEC_PACKED_MOD:
1.795 + vertex->detail[4] = data[0].i; /* U1 */
1.796 + vertex->detail[5] = data[1].i; /* V1 */
1.797 + vertex->detail[6] = data[2].i; /* ARGB1 */
1.798 + vertex->detail[7] = data[3].i; /* ARGB1 */
1.799 + break;
1.800 + case TA_VERTEX_TEX_UV16_PACKED_MOD:
1.801 + vertex->detail[2] = data[0].i; /* UV1 */
1.802 + vertex->detail[3] = data[2].i; /* ARGB1 */
1.803 + break;
1.804 + case TA_VERTEX_TEX_UV16_SPEC_PACKED_MOD:
1.805 + vertex->detail[3] = data[0].i; /* UV1 */
1.806 + vertex->detail[4] = data[2].i; /* ARGB1 */
1.807 + vertex->detail[5] = data[3].i; /* ARGB1 */
1.808 + break;
1.809 +
1.810 + case TA_VERTEX_TEX_INTENSITY_MOD:
1.811 + vertex->detail[3] = data[0].i; /* U1 */
1.812 + vertex->detail[4] = data[1].i; /* V1 */
1.813 + vertex->detail[5] = parse_intensity_colour( ta_status.intensity2, data[2].f ); /* ARGB1 */
1.814 + break;
1.815 + case TA_VERTEX_TEX_SPEC_INTENSITY_MOD:
1.816 + vertex->detail[4] = data[0].i; /* U1 */
1.817 + vertex->detail[5] = data[1].i; /* V1 */
1.818 + vertex->detail[6] = parse_intensity_colour( ta_status.intensity2, data[2].f ); /* ARGB1 */
1.819 + vertex->detail[7] = parse_intensity_colour( ta_status.intensity2, data[3].f ); /* ARGB1 */
1.820 + break;
1.821 + case TA_VERTEX_TEX_UV16_INTENSITY_MOD:
1.822 + vertex->detail[2] = data[0].i; /* UV1 */
1.823 + vertex->detail[3] = parse_intensity_colour( ta_status.intensity2, data[2].f ); /* ARGB1 */
1.824 + break;
1.825 + case TA_VERTEX_TEX_UV16_SPEC_INTENSITY_MOD:
1.826 + vertex->detail[3] = data[0].i; /* UV1 */
1.827 + vertex->detail[4] = parse_intensity_colour( ta_status.intensity2, data[2].f ); /* ARGB1 */
1.828 + vertex->detail[5] = parse_intensity_colour( ta_status.intensity2, data[3].f ); /* ARGB1 */
1.829 + break;
1.830 +
1.831 + case TA_VERTEX_SPRITE:
1.832 + vertex->y = data[0].f;
1.833 + vertex->z = data[1].f;
1.834 + vertex++;
1.835 + ta_status.vertex_count++;
1.836 + vertex->x = data[2].f;
1.837 + vertex->y = data[3].f;
1.838 + vertex->z = 0;
1.839 + vertex->detail[0] = 0;
1.840 + ta_status.poly_vertex[0].detail[0] = 0;
1.841 + ta_status.poly_vertex[1].detail[0] = 0;
1.842 + break;
1.843 + case TA_VERTEX_TEX_SPRITE:
1.844 + vertex->y = data[0].f;
1.845 + vertex->z = data[1].f;
1.846 + vertex++;
1.847 + ta_status.vertex_count++;
1.848 + vertex->x = data[2].f;
1.849 + vertex->y = data[3].f;
1.850 + vertex->z = 0;
1.851 + vertex->detail[0] = 0;
1.852 + vertex->detail[1] = 0;
1.853 + ta_status.poly_vertex[0].detail[0] = data[5].i;
1.854 + ta_status.poly_vertex[0].detail[1] = 0;
1.855 + ta_status.poly_vertex[1].detail[0] = data[6].i;
1.856 + ta_status.poly_vertex[1].detail[1] = 0;
1.857 + ta_status.poly_vertex[2].detail[0] = data[7].i;
1.858 + break;
1.859 + case TA_VERTEX_MOD_VOLUME:
1.860 + vertex->y = data[0].f;
1.861 + vertex->z = data[1].f;
1.862 + break;
1.863 + }
1.864 + ta_status.state = STATE_IN_LIST;
1.865 +}
1.866 +
1.867 +/**
1.868 + * Process 1 32-byte block of ta data
1.869 + */
1.870 +void pvr2_ta_process_block( char *input ) {
1.871 + union ta_data *data = (union ta_data *)input;
1.872 +
1.873 + switch( ta_status.state ) {
1.874 + case STATE_ERROR:
1.875 + /* Error raised - stop processing until reset */
1.876 + return;
1.877 +
1.878 + case STATE_EXPECT_POLY_BLOCK2:
1.879 + /* This is always a pair of floating-point colours */
1.880 + ta_status.intensity1 =
1.881 + parse_float_colour( data[0].f, data[1].f, data[2].f, data[3].f );
1.882 + ta_status.intensity2 =
1.883 + parse_float_colour( data[4].f, data[5].f, data[6].f, data[7].f );
1.884 + ta_status.state = STATE_IN_LIST;
1.885 + break;
1.886 +
1.887 + case STATE_EXPECT_VERTEX_BLOCK2:
1.888 + ta_parse_vertex_block2( data );
1.889 + if( ta_status.vertex_count == ta_status.max_vertex ) {
1.890 + ta_split_polygon();
1.891 + }
1.892 + break;
1.893 +
1.894 + case STATE_EXPECT_END_VERTEX_BLOCK2:
1.895 + ta_parse_vertex_block2( data );
1.896 + ta_commit_polygon();
1.897 + ta_status.vertex_count = 0;
1.898 + ta_status.poly_parity = 0;
1.899 +
1.900 + case STATE_IN_LIST:
1.901 + case STATE_IDLE:
1.902 + switch( TA_CMD( data->i ) ) {
1.903 + case TA_CMD_END_LIST:
1.904 + ta_end_list();
1.905 + break;
1.906 + case TA_CMD_CLIP: /* TODO */
1.907 + break;
1.908 + case TA_CMD_POLYGON_CONTEXT:
1.909 + if( ta_status.state == STATE_IDLE ) {
1.910 + ta_init_list( TA_POLYCMD_LISTTYPE( data->i ) );
1.911 + }
1.912 +
1.913 + if( ta_status.vertex_count != 0 ) {
1.914 + ta_fill_vertexes();
1.915 + ta_commit_polygon();
1.916 + }
1.917 +
1.918 + if( TA_IS_MODIFIER_LIST( ta_status.current_list_type ) ) {
1.919 + ta_parse_modifier_context(data);
1.920 + } else {
1.921 + ta_parse_polygon_context(data);
1.922 + }
1.923 + break;
1.924 + case TA_CMD_SPRITE_CONTEXT:
1.925 + if( ta_status.state == STATE_IDLE ) {
1.926 + ta_init_list( TA_POLYCMD_LISTTYPE( data->i ) );
1.927 + }
1.928 +
1.929 + if( ta_status.vertex_count != 0 ) {
1.930 + ta_fill_vertexes();
1.931 + ta_commit_polygon();
1.932 + }
1.933 +
1.934 + ta_parse_sprite_context(data);
1.935 + break;
1.936 + case TA_CMD_VERTEX:
1.937 + ta_parse_vertex(data);
1.938 +
1.939 + if( ta_status.state == STATE_EXPECT_VERTEX_BLOCK2 ) {
1.940 + if( TA_IS_END_VERTEX(data[0].i) ) {
1.941 + ta_status.state = STATE_EXPECT_END_VERTEX_BLOCK2;
1.942 + }
1.943 + } else if( TA_IS_END_VERTEX(data->i) ) {
1.944 + ta_commit_polygon();
1.945 + ta_status.vertex_count = 0;
1.946 + ta_status.poly_parity = 0;
1.947 + } else if( ta_status.vertex_count == ta_status.max_vertex ) {
1.948 + ta_split_polygon();
1.949 + }
1.950 + break;
1.951 + }
1.952 + break;
1.953 + }
1.954 +
1.955 +}
1.956 +
1.957 +
1.958 +
1.959 +/**
1.960 + * Write a block of data to the tile accelerator, adding the data to the
1.961 + * current scene. We don't make any particular attempt to interpret the data
1.962 + * at this stage, deferring that until render time.
1.963 + *
1.964 + * Currently copies the data verbatim to the vertex buffer, processing only
1.965 + * far enough to generate the correct end-of-list events. Tile buffer is
1.966 + * entirely ignored.
1.967 + */
1.968 +void pvr2_ta_write( char *buf, uint32_t length )
1.969 +{
1.970 + if( ta_status.debug_output ) {
1.971 + fwrite_dump32( (uint32_t *)buf, length, stderr );
1.972 + }
1.973 +
1.974 + for( ; length >=32; length -= 32 ) {
1.975 + pvr2_ta_process_block( buf );
1.976 + buf += 32;
1.977 + }
1.978 +}
.