filename | src/pvr2/tacore.c |
changeset | 189:615b70cfd729 |
next | 193:31151fcc3cb7 |
author | nkeynes |
date | Wed Aug 02 04:06:45 2006 +0000 (17 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 +00001.2 +++ b/src/pvr2/tacore.c Wed Aug 02 04:06:45 2006 +00001.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 implementation1.8 + *1.9 + * Copyright (c) 2005 Nathan Keynes.1.10 + *1.11 + * This program is free software; you can redistribute it and/or modify1.12 + * it under the terms of the GNU General Public License as published by1.13 + * the Free Software Foundation; either version 2 of the License, or1.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 of1.18 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1.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 01.25 +#define STATE_IN_LIST 11.26 +#define STATE_EXPECT_POLY_BLOCK2 21.27 +#define STATE_EXPECT_VERTEX_BLOCK2 31.28 +#define STATE_ERROR 41.29 +#define STATE_EXPECT_END_VERTEX_BLOCK2 71.30 +1.31 +#define TA_CMD(i) ( (i) >> 29 )1.32 +#define TA_CMD_END_LIST 01.33 +#define TA_CMD_CLIP 11.34 +#define TA_CMD_POLYGON_CONTEXT 41.35 +#define TA_CMD_SPRITE_CONTEXT 51.36 +#define TA_CMD_VERTEX 71.37 +1.38 +#define TA_LIST_NONE -11.39 +#define TA_LIST_OPAQUE 01.40 +#define TA_LIST_OPAQUE_MOD 11.41 +#define TA_LIST_TRANS 21.42 +#define TA_LIST_TRANS_MOD 31.43 +#define TA_LIST_PUNCH_OUT 41.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 01.47 +#define TA_GROW_DOWN 11.48 +1.49 +#define TA_VERTEX_NONE -11.50 +#define TA_VERTEX_PACKED 0x001.51 +#define TA_VERTEX_TEX_PACKED 0x081.52 +#define TA_VERTEX_TEX_SPEC_PACKED 0x0C1.53 +#define TA_VERTEX_TEX_UV16_PACKED 0x091.54 +#define TA_VERTEX_TEX_UV16_SPEC_PACKED 0x0D1.55 +#define TA_VERTEX_FLOAT 0x101.56 +#define TA_VERTEX_TEX_FLOAT 0x181.57 +#define TA_VERTEX_TEX_SPEC_FLOAT 0x1C1.58 +#define TA_VERTEX_TEX_UV16_FLOAT 0x191.59 +#define TA_VERTEX_TEX_UV16_SPEC_FLOAT 0x1D1.60 +#define TA_VERTEX_INTENSITY 0x201.61 +#define TA_VERTEX_TEX_INTENSITY 0x281.62 +#define TA_VERTEX_TEX_SPEC_INTENSITY 0x2C1.63 +#define TA_VERTEX_TEX_UV16_INTENSITY 0x291.64 +#define TA_VERTEX_TEX_UV16_SPEC_INTENSITY 0x2D1.65 +#define TA_VERTEX_PACKED_MOD 0x401.66 +#define TA_VERTEX_TEX_PACKED_MOD 0x481.67 +#define TA_VERTEX_TEX_SPEC_PACKED_MOD 0x4C1.68 +#define TA_VERTEX_TEX_UV16_PACKED_MOD 0x491.69 +#define TA_VERTEX_TEX_UV16_SPEC_PACKED_MOD 0x4D1.70 +#define TA_VERTEX_INTENSITY_MOD 0x601.71 +#define TA_VERTEX_TEX_INTENSITY_MOD 0x681.72 +#define TA_VERTEX_TEX_SPEC_INTENSITY_MOD 0x6C1.73 +#define TA_VERTEX_TEX_UV16_INTENSITY_MOD 0x691.74 +#define TA_VERTEX_TEX_UV16_SPEC_INTENSITY_MOD 0x6D1.75 +#define TA_VERTEX_SPRITE 0x801.76 +#define TA_VERTEX_TEX_SPRITE 0x881.77 +#define TA_VERTEX_MOD_VOLUME 0x811.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 0x000000001.87 +#define TA_POLYCMD_COLOURFMT_FLOAT 0x000000101.88 +#define TA_POLYCMD_COLOURFMT_INTENSITY 0x000000201.89 +#define TA_POLYCMD_COLOURFMT_LASTINT 0x000000301.90 +1.91 +#define TA_POLYCMD_MODIFIED 0x000000801.92 +#define TA_POLYCMD_FULLMOD 0x000000401.93 +#define TA_POLYCMD_TEXTURED 0x000000081.94 +#define TA_POLYCMD_SPECULAR 0x000000041.95 +#define TA_POLYCMD_SHADED 0x000000021.96 +#define TA_POLYCMD_UV16 0x000000011.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 vertexes1.128 + * are present1.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 object1.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 + return1.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 + return1.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_FAIL1.255 + * @param data to be written1.256 + * @param length Number of 32-bit words to write.1.257 + * @return number of words actually written1.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 space1.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 buffers1.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 with1.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 well1.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, but1.492 + * the client hasn't sent the LAST VERTEX flag. Commit the poly as normal1.493 + * first, then start a new poly with the first 2 vertexes taken from the1.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 are1.500 + * handled differently1.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 receive1.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 to1.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 receive1.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 for1.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 data1.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 the1.961 + * current scene. We don't make any particular attempt to interpret the data1.962 + * at this stage, deferring that until render time.1.963 + *1.964 + * Currently copies the data verbatim to the vertex buffer, processing only1.965 + * far enough to generate the correct end-of-list events. Tile buffer is1.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 +}
.