filename | src/pvr2/tacore.c |
changeset | 1145:45674791c6ad |
prev | 1067:d3c00ffccfcd |
author | nkeynes |
date | Mon Mar 05 11:41:03 2012 +1000 (12 years ago) |
permissions | -rw-r--r-- |
last change | Small cleanups: Refactor the post-windowing setup into gl_init_driver() in video_gl.c Move gl_sl.c into src/drivers and tidy up a bit. Fix OS X compiling plugins with -mdynamic-no-pic |
view | annotate | diff | log | raw |
1 /**
2 * $Id$
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 <string.h>
19 #include "lxdream.h"
20 #include "pvr2/pvr2.h"
21 #include "pvr2/pvr2mmio.h"
22 #include "asic.h"
23 #include "dream.h"
25 #define STATE_IDLE 0
26 #define STATE_IN_LIST 1
27 #define STATE_IN_POLYGON 2
28 #define STATE_EXPECT_POLY_BLOCK2 3
29 #define STATE_EXPECT_VERTEX_BLOCK2 4
30 #define STATE_ERROR 5
31 #define STATE_EXPECT_END_VERTEX_BLOCK2 7
33 #define TA_CMD(i) ( (i) >> 29 )
34 #define TA_CMD_END_LIST 0
35 #define TA_CMD_CLIP 1
36 #define TA_CMD_POLYGON_CONTEXT 4
37 #define TA_CMD_SPRITE_CONTEXT 5
38 #define TA_CMD_VERTEX 7
40 #define TA_LIST_NONE -1
41 #define TA_LIST_OPAQUE 0
42 #define TA_LIST_OPAQUE_MOD 1
43 #define TA_LIST_TRANS 2
44 #define TA_LIST_TRANS_MOD 3
45 #define TA_LIST_PUNCH_OUT 4
46 #define TA_IS_MODIFIER_LIST(list) (list == TA_LIST_OPAQUE_MOD || list == TA_LIST_TRANS_MOD)
48 #define TA_GROW_UP 0
49 #define TA_GROW_DOWN 1
51 #define TA_VERTEX_NONE -1
52 #define TA_VERTEX_PACKED 0x00
53 #define TA_VERTEX_TEX_PACKED 0x08
54 #define TA_VERTEX_TEX_SPEC_PACKED 0x0C
55 #define TA_VERTEX_TEX_UV16_PACKED 0x09
56 #define TA_VERTEX_TEX_UV16_SPEC_PACKED 0x0D
57 #define TA_VERTEX_FLOAT 0x10
58 #define TA_VERTEX_TEX_FLOAT 0x18
59 #define TA_VERTEX_TEX_SPEC_FLOAT 0x1C
60 #define TA_VERTEX_TEX_UV16_FLOAT 0x19
61 #define TA_VERTEX_TEX_UV16_SPEC_FLOAT 0x1D
62 #define TA_VERTEX_INTENSITY 0x20
63 #define TA_VERTEX_TEX_INTENSITY 0x28
64 #define TA_VERTEX_TEX_SPEC_INTENSITY 0x2C
65 #define TA_VERTEX_TEX_UV16_INTENSITY 0x29
66 #define TA_VERTEX_TEX_UV16_SPEC_INTENSITY 0x2D
67 #define TA_VERTEX_PACKED_MOD 0x40
68 #define TA_VERTEX_TEX_PACKED_MOD 0x48
69 #define TA_VERTEX_TEX_SPEC_PACKED_MOD 0x4C
70 #define TA_VERTEX_TEX_UV16_PACKED_MOD 0x49
71 #define TA_VERTEX_TEX_UV16_SPEC_PACKED_MOD 0x4D
72 #define TA_VERTEX_INTENSITY_MOD 0x60
73 #define TA_VERTEX_TEX_INTENSITY_MOD 0x68
74 #define TA_VERTEX_TEX_SPEC_INTENSITY_MOD 0x6C
75 #define TA_VERTEX_TEX_UV16_INTENSITY_MOD 0x69
76 #define TA_VERTEX_TEX_UV16_SPEC_INTENSITY_MOD 0x6D
77 #define TA_VERTEX_SPRITE 0x80
78 #define TA_VERTEX_TEX_SPRITE 0x88
79 #define TA_VERTEX_MOD_VOLUME 0x81
80 #define TA_VERTEX_LISTLESS 0xFF
82 #define TA_IS_NORMAL_POLY() (ta_status.current_vertex_type < TA_VERTEX_SPRITE)
84 static int strip_lengths[4] = {3,4,6,8}; /* in vertexes */
85 #define TA_POLYCMD_LISTTYPE(i) ( ((i) >> 24) & 0x0F )
86 #define TA_POLYCMD_USELENGTH(i) ( i & 0x00800000 )
87 #define TA_POLYCMD_LENGTH(i) strip_lengths[((i >> 18) & 0x03)]
88 #define TA_POLYCMD_CLIP(i) ((i>>16)&0x03)
89 #define TA_POLYCMD_CLIP_NONE 0
90 #define TA_POLYCMD_CLIP_INSIDE 2
91 #define TA_POLYCMD_CLIP_OUTSIDE 3
92 #define TA_POLYCMD_COLOURFMT(i) (i & 0x00000030)
93 #define TA_POLYCMD_COLOURFMT_ARGB32 0x00000000
94 #define TA_POLYCMD_COLOURFMT_FLOAT 0x00000010
95 #define TA_POLYCMD_COLOURFMT_INTENSITY 0x00000020
96 #define TA_POLYCMD_COLOURFMT_LASTINT 0x00000030
98 #define TA_POLYCMD_MODIFIED 0x00000080
99 #define TA_POLYCMD_FULLMOD 0x00000040
100 #define TA_POLYCMD_TEXTURED 0x00000008
101 #define TA_POLYCMD_SPECULAR 0x00000004
102 #define TA_POLYCMD_SHADED 0x00000002
103 #define TA_POLYCMD_UV16 0x00000001
105 #define TA_POLYCMD_IS_SPECULAR(i) ((i & 0x0000000C)==0x0000000C) /* Only applies to textured polys */
106 #define TA_POLYCMD_IS_FULLMOD(i) ((i & 0x000000C0)==0x000000C0)
109 #define TA_IS_END_VERTEX(i) (i & 0x10000000)
111 /** Note these are not the IEEE 754 definitions - the TA treats NANs
112 * as if they were INFs of the appropriate sign.
113 */
114 #define TA_IS_INF(f) (((*((uint32_t *)&f)) & 0xFF800000) == 0x7F800000)
115 #define TA_IS_NINF(f) (((*((uint32_t *)&f)) & 0xFF800000) == 0xFF800000)
117 #define MIN3( x1, x2, x3 ) ( (x1)<(x2)? ((x1)<(x3)?(x1):(x3)) : ((x2)<(x3)?(x2):(x3)) )
118 #define MAX3( x1, x2, x3 ) ( (x1)>(x2)? ((x1)>(x3)?(x1):(x3)) : ((x2)>(x3)?(x2):(x3)) )
120 #define TILESLOT( x, y ) (ta_status.current_tile_matrix + (ta_status.current_tile_size * (y * ta_status.width+ x) << 2))
122 #define PVRRAM(addr) (*(uint32_t *)(pvr2_main_ram + ((addr)&PVR2_RAM_MASK)))
124 struct pvr2_ta_vertex {
125 float x,y,z;
126 uint32_t detail[8]; /* 0-8 detail words */
127 };
129 struct pvr2_ta_status {
130 int32_t state;
131 int32_t width, height; /* Tile resolution, ie 20x15 */
132 int32_t tilelist_dir; /* Growth direction of the tilelist, 0 = up, 1 = down */
133 uint32_t tilelist_size; /* Size of the tilelist segments */
134 uint32_t tilelist_start; /* Initial address of the tilelist */
135 uint32_t polybuf_start; /* Initial bank address of the polygon buffer (ie &0x00F00000) */
136 int32_t current_vertex_type;
137 uint32_t accept_vertexes; /* 0 = NO, 1 = YES */
138 int32_t vertex_count; /* index of last start-vertex seen, or -1 if no vertexes
139 * are present
140 */
141 uint32_t max_vertex; /* Maximum number of vertexes in the current polygon (3/4/6/8) */
142 uint32_t current_list_type;
143 uint32_t current_tile_matrix; /* Memory location of the first tile for the current list. */
144 uint32_t current_tile_size; /* Size of the tile matrix space in 32-bit words (0/8/16/32)*/
145 uint32_t intensity1, intensity2;
146 struct tile_bounds clip;
147 int32_t clip_mode;
148 /**
149 * Current working object
150 */
151 int32_t poly_context_size;
152 int32_t poly_vertex_size;
153 int32_t poly_parity;
154 uint32_t poly_context[5];
155 uint32_t poly_pointer;
156 struct tile_bounds last_triangle_bounds;
157 struct pvr2_ta_vertex poly_vertex[8];
158 uint32_t debug_output;
159 };
161 static struct pvr2_ta_status ta_status;
163 static int tilematrix_sizes[4] = {0,8,16,32};
165 /**
166 * Convenience union - ta data is either 32-bit integer or 32-bit float.
167 */
168 union ta_data {
169 unsigned int i;
170 float f;
171 };
174 void pvr2_ta_reset() {
175 ta_status.state = STATE_ERROR; /* State not valid until initialized */
176 ta_status.debug_output = 0;
177 }
179 void pvr2_ta_save_state( FILE *f )
180 {
181 fwrite( &ta_status, sizeof(ta_status), 1, f );
182 }
184 int pvr2_ta_load_state( FILE *f )
185 {
186 if( fread( &ta_status, sizeof(ta_status), 1, f ) != 1 )
187 return 1;
188 return 0;
189 }
191 void pvr2_ta_init() {
192 ta_status.state = STATE_IDLE;
193 ta_status.current_list_type = -1;
194 ta_status.current_vertex_type = -1;
195 ta_status.poly_parity = 0;
196 ta_status.vertex_count = 0;
197 ta_status.max_vertex = 3;
198 ta_status.current_vertex_type = TA_VERTEX_LISTLESS;
199 ta_status.poly_vertex_size = 0;
200 memset(&ta_status.poly_context[1], 0, 4);
201 ta_status.last_triangle_bounds.x1 = -1;
202 ta_status.accept_vertexes = TRUE;
203 ta_status.clip.x1 = 0;
204 ta_status.clip.y1 = 0;
205 ta_status.clip_mode = TA_POLYCMD_CLIP_NONE;
207 uint32_t size = MMIO_READ( PVR2, TA_TILESIZE );
208 ta_status.width = (size & 0xFFFF) + 1;
209 ta_status.height = (size >> 16) + 1;
210 ta_status.clip.x2 = ta_status.width-1;
211 ta_status.clip.y2 = ta_status.height-1;
212 uint32_t control = MMIO_READ( PVR2, TA_TILECFG );
213 ta_status.tilelist_dir = (control >> 20) & 0x01;
214 ta_status.tilelist_size = tilematrix_sizes[ (control & 0x03) ];
215 MMIO_WRITE( PVR2, TA_POLYPOS, MMIO_READ( PVR2, TA_POLYBASE ) );
216 uint32_t plistpos = MMIO_READ( PVR2, TA_LISTBASE ) >> 2;
217 if( ta_status.tilelist_dir == TA_GROW_DOWN ) {
218 plistpos -= ta_status.tilelist_size;
219 }
220 MMIO_WRITE( PVR2, TA_LISTPOS, plistpos );
221 ta_status.tilelist_start = plistpos;
222 ta_status.polybuf_start = MMIO_READ( PVR2, TA_POLYBASE ) & 0x00F00000;
223 }
225 static uint32_t parse_float_colour( float a, float r, float g, float b ) {
226 int ai,ri,gi,bi;
228 if( TA_IS_INF(a) ) {
229 ai = 255;
230 } else {
231 ai = 256 * CLAMP(a,0.0,1.0) - 1;
232 if( ai < 0 ) ai = 0;
233 }
234 if( TA_IS_INF(r) ) {
235 ri = 255;
236 } else {
237 ri = 256 * CLAMP(r,0.0,1.0) - 1;
238 if( ri < 0 ) ri = 0;
239 }
240 if( TA_IS_INF(g) ) {
241 gi = 255;
242 } else {
243 gi = 256 * CLAMP(g,0.0,1.0) - 1;
244 if( gi < 0 ) gi = 0;
245 }
246 if( TA_IS_INF(b) ) {
247 bi = 255;
248 } else {
249 bi = 256 * CLAMP(b,0.0,1.0) - 1;
250 if( bi < 0 ) bi = 0;
251 }
252 return (ai << 24) | (ri << 16) | (gi << 8) | bi;
253 }
255 static uint32_t parse_intensity_colour( uint32_t base, float intensity )
256 {
257 unsigned int i = (unsigned int)(256 * CLAMP(intensity, 0.0,1.0));
259 return
260 (((((base & 0xFF) * i) & 0xFF00) |
261 (((base & 0xFF00) * i) & 0xFF0000) |
262 (((base & 0xFF0000) * i) & 0xFF000000)) >> 8) |
263 (base & 0xFF000000);
264 }
266 /**
267 * Initialize the specified TA list.
268 */
269 static void ta_init_list( unsigned int listtype ) {
270 int config = MMIO_READ( PVR2, TA_TILECFG );
271 int tile_matrix = MMIO_READ( PVR2, TA_TILEBASE );
272 int list_end = MMIO_READ( PVR2, TA_LISTEND );
274 ta_status.current_tile_matrix = tile_matrix;
276 /* If the list grows down, the end must be < tile matrix start.
277 * If it grows up, the end must be > tile matrix start.
278 * Don't ask me why, it just does...
279 */
280 if( ((ta_status.tilelist_dir == TA_GROW_DOWN && list_end <= tile_matrix) ||
281 (ta_status.tilelist_dir == TA_GROW_UP && list_end >= tile_matrix )) &&
282 listtype <= TA_LIST_PUNCH_OUT ) {
283 int i;
284 uint32_t *p;
285 for( i=0; i < listtype; i++ ) {
286 int size = tilematrix_sizes[(config & 0x03)] << 2;
287 ta_status.current_tile_matrix += ta_status.width * ta_status.height * size;
288 config >>= 4;
289 }
290 ta_status.current_tile_size = tilematrix_sizes[(config & 0x03)];
292 /* Initialize each tile to 0xF0000000 */
293 if( ta_status.current_tile_size != 0 ) {
294 p = (uint32_t *)(pvr2_main_ram + ta_status.current_tile_matrix);
295 for( i=0; i< ta_status.width * ta_status.height; i++ ) {
296 *p = 0xF0000000;
297 p += ta_status.current_tile_size;
298 }
299 }
300 } else {
301 ta_status.current_tile_size = 0;
302 }
304 if( tile_matrix == list_end ) {
305 ta_status.current_tile_size = 0;
306 }
308 ta_status.state = STATE_IN_LIST;
309 ta_status.current_list_type = listtype;
310 ta_status.last_triangle_bounds.x1 = -1;
311 }
313 static int list_events[5] = {EVENT_PVR_OPAQUE_DONE, EVENT_PVR_OPAQUEMOD_DONE,
314 EVENT_PVR_TRANS_DONE, EVENT_PVR_TRANSMOD_DONE,
315 EVENT_PVR_PUNCHOUT_DONE };
317 static void ta_end_list() {
318 if( ta_status.current_list_type != TA_LIST_NONE ) {
319 asic_event( list_events[ta_status.current_list_type] );
320 }
321 ta_status.current_list_type = TA_LIST_NONE;
322 ta_status.current_vertex_type = TA_VERTEX_LISTLESS;
323 ta_status.poly_vertex_size = 0;
324 memset(&ta_status.poly_context[1], 0, 4);
325 ta_status.state = STATE_IDLE;
326 }
328 static void ta_bad_input_error() {
329 asic_event( EVENT_PVR_BAD_INPUT );
330 }
332 /**
333 * Write data out to the polygon buffer.
334 * If the end-of-buffer is reached, asserts EVENT_PVR_PRIM_ALLOC_FAIL
335 * @param data to be written
336 * @param length Number of 32-bit words to write.
337 * @return number of words actually written
338 */
339 static int ta_write_polygon_buffer( uint32_t *data, int length )
340 {
341 int rv;
342 int posn = MMIO_READ( PVR2, TA_POLYPOS );
343 int end = MMIO_READ( PVR2, TA_POLYEND );
344 uint32_t *target = (uint32_t *)(pvr2_main_ram + posn);
345 for( rv=0; rv < length; rv++ ) {
346 if( posn == end ) {
347 asic_event( EVENT_PVR_PRIM_ALLOC_FAIL );
348 // ta_status.state = STATE_ERROR;
349 break;
350 }
351 if( posn < PVR2_RAM_SIZE ) {
352 *target++ = *data++;
353 }
354 posn += 4;
355 }
357 MMIO_WRITE( PVR2, TA_POLYPOS, posn );
358 return rv;
359 }
361 #define TA_NO_ALLOC 0xFFFFFFFF
363 /**
364 * Allocate a new tile list block from the grow space and update the
365 * word at reference to be a link to the new block.
366 */
367 static uint32_t ta_alloc_tilelist( uint32_t reference ) {
368 uint32_t posn = MMIO_READ( PVR2, TA_LISTPOS );
369 uint32_t limit = MMIO_READ( PVR2, TA_LISTEND ) >> 2;
370 uint32_t newposn;
371 if( ta_status.tilelist_dir == TA_GROW_DOWN ) {
372 newposn = posn - ta_status.tilelist_size;
373 if( posn == limit ) {
374 PVRRAM(posn<<2) = 0xF0000000;
375 PVRRAM(reference) = 0xE0000000 | (posn<<2);
376 return TA_NO_ALLOC;
377 } else if( posn < limit ) {
378 PVRRAM(reference) = 0xE0000000 | (posn<<2);
379 return TA_NO_ALLOC;
380 } else if( newposn <= limit ) {
381 } else if( newposn <= (limit + ta_status.tilelist_size) ) {
382 asic_event( EVENT_PVR_MATRIX_ALLOC_FAIL );
383 MMIO_WRITE( PVR2, TA_LISTPOS, newposn );
384 } else {
385 MMIO_WRITE( PVR2, TA_LISTPOS, newposn );
386 }
387 PVRRAM(reference) = 0xE0000000 | (posn<<2);
388 return posn << 2;
389 } else {
390 newposn = posn + ta_status.tilelist_size;
391 if( posn == limit ) {
392 PVRRAM(posn<<2) = 0xF0000000;
393 PVRRAM(reference) = 0xE0000000 | (posn<<2);
394 return TA_NO_ALLOC;
395 } else if ( posn > limit ) {
396 PVRRAM(reference) = 0xE0000000 | (posn<<2);
397 return TA_NO_ALLOC;
398 } else if( newposn >= limit ) {
399 } else if( newposn >= (limit - ta_status.tilelist_size) ) {
400 asic_event( EVENT_PVR_MATRIX_ALLOC_FAIL );
401 MMIO_WRITE( PVR2, TA_LISTPOS, newposn );
402 } else {
403 MMIO_WRITE( PVR2, TA_LISTPOS, newposn );
404 }
405 PVRRAM(reference) = 0xE0000000 | (posn<<2);
406 return posn << 2;
407 }
408 }
410 /**
411 * Write a tile entry out to the matrix.
412 */
413 static void ta_write_tile_entry( int x, int y, uint32_t tile_entry ) {
414 uint32_t tile = TILESLOT(x,y);
415 uint32_t tilestart = tile;
416 uint32_t value;
417 uint32_t lasttri = 0;
418 int i;
420 if( ta_status.clip_mode == TA_POLYCMD_CLIP_OUTSIDE &&
421 x >= ta_status.clip.x1 && x <= ta_status.clip.x2 &&
422 y >= ta_status.clip.y1 && y <= ta_status.clip.y2 ) {
423 /* Tile clipped out */
424 return;
425 }
427 if( (tile_entry & 0x80000000) &&
428 ta_status.last_triangle_bounds.x1 != -1 &&
429 ta_status.last_triangle_bounds.x1 <= x &&
430 ta_status.last_triangle_bounds.x2 >= x &&
431 ta_status.last_triangle_bounds.y1 <= y &&
432 ta_status.last_triangle_bounds.y2 >= y ) {
433 /* potential for triangle stacking */
434 lasttri = tile_entry & 0xE1E00000;
435 }
438 if( PVRRAM(tile) == 0xF0000000 ) {
439 PVRRAM(tile) = tile_entry;
440 PVRRAM(tile+4) = 0xF0000000;
441 return;
442 }
444 while(1) {
445 value = PVRRAM(tile);
446 for( i=1; i<ta_status.current_tile_size; i++ ) {
447 tile += 4;
448 uint32_t nextval = PVRRAM(tile);
449 if( nextval == 0xF0000000 ) {
450 if( lasttri != 0 && lasttri == (value&0xE1E00000) ) {
451 int count = (value & 0x1E000000) + 0x02000000;
452 if( count < 0x20000000 ) {
453 PVRRAM(tile-4) = (value & 0xE1FFFFFF) | count;
454 return;
455 }
456 }
457 if( i < ta_status.current_tile_size-1 ) {
458 PVRRAM(tile) = tile_entry;
459 PVRRAM(tile+4) = 0xF0000000;
460 return;
461 }
462 }
463 value = nextval;
464 }
466 if( value == 0xF0000000 ) {
467 tile = ta_alloc_tilelist(tile);
468 if( tile != TA_NO_ALLOC ) {
469 PVRRAM(tile) = tile_entry;
470 PVRRAM(tile+4) = 0xF0000000;
471 }
472 return;
473 } else if( (value & 0xFF000000) == 0xE0000000 ) {
474 value &= 0x00FFFFFF;
475 if( value == tilestart )
476 return; /* Loop */
477 tilestart = tile = value;
478 } else {
479 /* This should never happen */
480 return;
481 }
482 }
483 }
485 /**
486 * Write a completed polygon out to the memory buffers
487 * OPTIMIZEME: This is not terribly efficient at the moment.
488 */
489 static void ta_commit_polygon( ) {
490 int i, x, y;
491 int tx[ta_status.vertex_count], ty[ta_status.vertex_count];
492 struct tile_bounds triangle_bound[ta_status.vertex_count - 2];
493 struct tile_bounds polygon_bound;
494 uint32_t poly_context[5];
496 memcpy( poly_context, ta_status.poly_context, ta_status.poly_context_size * 4 );
498 /* Compute the tile coordinates for each vertex (need to be careful with
499 * clamping here)
500 */
501 for( i=0; i<ta_status.vertex_count; i++ ) {
502 if( ta_status.poly_vertex[i].x < 0.0 || TA_IS_NINF(ta_status.poly_vertex[i].x) ) {
503 tx[i] = -1;
504 } else if( ta_status.poly_vertex[i].x > (float)INT_MAX || TA_IS_INF(ta_status.poly_vertex[i].x) ) {
505 tx[i] = INT_MAX/32;
506 } else {
507 tx[i] = (int)(ta_status.poly_vertex[i].x / 32.0);
508 }
509 if( ta_status.poly_vertex[i].y < 0.0 || TA_IS_NINF(ta_status.poly_vertex[i].y)) {
510 ty[i] = -1;
511 } else if( ta_status.poly_vertex[i].y > (float)INT_MAX || TA_IS_INF(ta_status.poly_vertex[i].y) ) {
512 ty[i] = INT_MAX/32;
513 } else {
514 ty[i] = (int)(ta_status.poly_vertex[i].y / 32.0);
515 }
517 }
519 /* Compute bounding box for each triangle individually, as well
520 * as the overall polygon.
521 */
523 triangle_bound[0].x1 = MIN3(tx[0],tx[1],tx[2]);
524 triangle_bound[0].x2 = MAX3(tx[0],tx[1],tx[2]);
525 triangle_bound[0].y1 = MIN3(ty[0],ty[1],ty[2]);
526 triangle_bound[0].y2 = MAX3(ty[0],ty[1],ty[2]);
527 polygon_bound.x1 = triangle_bound[0].x1;
528 polygon_bound.y1 = triangle_bound[0].y1;
529 polygon_bound.x2 = triangle_bound[0].x2;
530 polygon_bound.y2 = triangle_bound[0].y2;
532 for( i=1; i<ta_status.vertex_count-2; i++ ) {
533 triangle_bound[i].x1 = MIN3(tx[i],tx[i+1],tx[i+2]);
534 triangle_bound[i].x2 = MAX3(tx[i],tx[i+1],tx[i+2]);
535 triangle_bound[i].y1 = MIN3(ty[i],ty[i+1],ty[i+2]);
536 triangle_bound[i].y2 = MAX3(ty[i],ty[i+1],ty[i+2]);
537 polygon_bound.x1 = MIN(polygon_bound.x1, triangle_bound[i].x1);
538 polygon_bound.x2 = MAX(polygon_bound.x2, triangle_bound[i].x2);
539 polygon_bound.y1 = MIN(polygon_bound.y1, triangle_bound[i].y1);
540 polygon_bound.y2 = MAX(polygon_bound.y2, triangle_bound[i].y2);
541 }
543 /* Clamp the polygon bounds to the frustum */
544 if( polygon_bound.x1 < 0 ) polygon_bound.x1 = 0;
545 if( polygon_bound.x2 >= ta_status.width ) polygon_bound.x2 = ta_status.width-1;
546 if( polygon_bound.y1 < 0 ) polygon_bound.y1 = 0;
547 if( polygon_bound.y2 >= ta_status.width ) polygon_bound.y2 = ta_status.height-1;
549 /* Set the "single tile" flag if it's entirely contained in 1 tile */
550 if( polygon_bound.x1 == polygon_bound.x2 &&
551 polygon_bound.y1 == polygon_bound.y2 ) {
552 poly_context[0] |= 0x00200000;
553 }
555 /* If the polygon is entirely clipped, don't even write the polygon data */
556 switch( ta_status.clip_mode ) {
557 case TA_POLYCMD_CLIP_NONE:
558 if( polygon_bound.x2 < 0 || polygon_bound.x1 >= ta_status.width ||
559 polygon_bound.y2 < 0 || polygon_bound.y1 >= ta_status.height ) {
560 return;
561 }
562 break;
563 case TA_POLYCMD_CLIP_INSIDE:
564 if( polygon_bound.x2 < ta_status.clip.x1 || polygon_bound.x1 > ta_status.clip.x2 ||
565 polygon_bound.y2 < ta_status.clip.y1 || polygon_bound.y1 > ta_status.clip.y2 ) {
566 return;
567 } else {
568 /* Clamp to clip bounds */
569 if( polygon_bound.x1 < ta_status.clip.x1 ) polygon_bound.x1 = ta_status.clip.x1;
570 if( polygon_bound.x2 > ta_status.clip.x2 ) polygon_bound.x2 = ta_status.clip.x2;
571 if( polygon_bound.y1 < ta_status.clip.y1 ) polygon_bound.y1 = ta_status.clip.y1;
572 if( polygon_bound.y2 > ta_status.clip.y2 ) polygon_bound.y2 = ta_status.clip.y2;
573 }
574 break;
575 case TA_POLYCMD_CLIP_OUTSIDE:
576 if( polygon_bound.x1 >= ta_status.clip.x1 && polygon_bound.x2 <= ta_status.clip.x2 &&
577 polygon_bound.y1 >= ta_status.clip.y1 && polygon_bound.y2 <= ta_status.clip.y2 ) {
578 return;
579 }
580 break;
581 }
583 /* Ok, we're good to go - write out the polygon first */
584 uint32_t tile_entry = (MMIO_READ( PVR2, TA_POLYPOS ) - ta_status.polybuf_start) >> 2 |
585 ta_status.poly_pointer;
587 int status = ta_write_polygon_buffer( poly_context, ta_status.poly_context_size );
588 if( status == 0 ) {
589 /* No memory available - abort */
590 return;
591 } else {
592 for( i=0; i<ta_status.vertex_count && status != 0; i++ ) {
593 status = ta_write_polygon_buffer( (uint32_t *)(&ta_status.poly_vertex[i]), 3 + ta_status.poly_vertex_size );
594 }
595 }
597 if( ta_status.current_tile_size == 0 ) {
598 /* No memory for tile entry, so don't write anything */
599 return;
600 }
602 /* And now the tile entries. Triangles are different from everything else */
603 if( ta_status.vertex_count == 3 ) {
604 tile_entry |= 0x80000000;
605 for( y=polygon_bound.y1; y<=polygon_bound.y2; y++ ) {
606 for( x=polygon_bound.x1; x<=polygon_bound.x2; x++ ) {
607 ta_write_tile_entry( x,y,tile_entry );
608 }
609 }
610 ta_status.last_triangle_bounds.x1 = polygon_bound.x1;
611 ta_status.last_triangle_bounds.y1 = polygon_bound.y1;
612 ta_status.last_triangle_bounds.x2 = polygon_bound.x2;
613 ta_status.last_triangle_bounds.y2 = polygon_bound.y2;
614 } else if( ta_status.current_vertex_type == TA_VERTEX_SPRITE ||
615 ta_status.current_vertex_type == TA_VERTEX_TEX_SPRITE ) {
616 tile_entry |= 0xA0000000;
617 for( y=polygon_bound.y1; y<=polygon_bound.y2; y++ ) {
618 for( x=polygon_bound.x1; x<=polygon_bound.x2; x++ ) {
619 ta_write_tile_entry( x,y,tile_entry );
620 }
621 }
622 ta_status.last_triangle_bounds.x1 = polygon_bound.x1;
623 ta_status.last_triangle_bounds.y1 = polygon_bound.y1;
624 ta_status.last_triangle_bounds.x2 = polygon_bound.x2;
625 ta_status.last_triangle_bounds.y2 = polygon_bound.y2;
626 } else {
627 for( y=polygon_bound.y1; y<=polygon_bound.y2; y++ ) {
628 for( x=polygon_bound.x1; x<=polygon_bound.x2; x++ ) {
629 uint32_t entry = tile_entry;
630 for( i=0; i<ta_status.vertex_count-2; i++ ) {
631 if( triangle_bound[i].x1 <= x && triangle_bound[i].x2 >= x &&
632 triangle_bound[i].y1 <= y && triangle_bound[i].y2 >= y ) {
633 entry |= (0x40000000>>i);
634 }
635 }
636 ta_write_tile_entry( x, y, entry );
637 }
638 }
639 ta_status.last_triangle_bounds.x1 = -1;
640 }
641 }
643 /**
644 * Variant of ta_split_polygon called when vertex_count == max_vertex, but
645 * the client hasn't sent the LAST VERTEX flag. Commit the poly as normal
646 * first, then start a new poly with the first 2 vertexes taken from the
647 * current one.
648 */
649 static void ta_split_polygon() {
650 ta_commit_polygon();
651 if( TA_IS_NORMAL_POLY() ) {
652 /* This only applies to ordinary polys - Sprites + modifier lists are
653 * handled differently
654 */
655 if( ta_status.vertex_count == 3 ) {
656 /* Triangles use an odd/even scheme */
657 if( ta_status.poly_parity == 0 ) {
658 memcpy( &ta_status.poly_vertex[0], &ta_status.poly_vertex[2],
659 sizeof(struct pvr2_ta_vertex) );
660 ta_status.poly_parity = 1;
661 } else {
662 memcpy( &ta_status.poly_vertex[1], &ta_status.poly_vertex[2],
663 sizeof(struct pvr2_ta_vertex) );
664 ta_status.poly_parity = 0;
665 }
666 } else {
667 /* Everything else just uses the last 2 vertexes in order */
668 memcpy( &ta_status.poly_vertex[0], &ta_status.poly_vertex[ta_status.vertex_count-2],
669 sizeof(struct pvr2_ta_vertex)*2 );
670 ta_status.poly_parity = 0;
671 }
672 ta_status.vertex_count = 2;
673 } else {
674 ta_status.vertex_count = 0;
675 }
676 }
678 /**
679 * Parse the polygon context block and setup the internal state to receive
680 * vertexes.
681 * @param data 32 bytes of parameter data.
682 */
683 static void ta_parse_polygon_context( union ta_data *data ) {
684 int colourfmt = TA_POLYCMD_COLOURFMT(data[0].i);
685 if( TA_POLYCMD_USELENGTH(data[0].i) ) {
686 ta_status.max_vertex = TA_POLYCMD_LENGTH(data[0].i);
687 }
688 ta_status.clip_mode = TA_POLYCMD_CLIP(data[0].i);
689 if( ta_status.clip_mode == 1 ) { /* Reserved - treat as CLIP_INSIDE */
690 ta_status.clip_mode = TA_POLYCMD_CLIP_INSIDE;
691 }
692 ta_status.vertex_count = 0;
693 ta_status.poly_context[0] =
694 (data[1].i & 0xFC1FFFFF) | ((data[0].i & 0x0B) << 22);
695 ta_status.poly_context[1] = data[2].i;
696 ta_status.poly_context[3] = data[4].i;
697 ta_status.poly_parity = 0;
698 if( data[0].i & TA_POLYCMD_TEXTURED ) {
699 ta_status.current_vertex_type = data[0].i & 0x0D;
700 ta_status.poly_context[2] = data[3].i;
701 ta_status.poly_context[4] = data[5].i;
702 if( data[0].i & TA_POLYCMD_SPECULAR ) {
703 ta_status.poly_context[0] |= 0x01000000;
704 ta_status.poly_vertex_size = 4;
705 } else {
706 ta_status.poly_vertex_size = 3;
707 }
708 if( data[0].i & TA_POLYCMD_UV16 ) {
709 ta_status.poly_vertex_size--;
710 }
711 } else {
712 ta_status.current_vertex_type = 0;
713 ta_status.poly_vertex_size = 1;
714 ta_status.poly_context[2] = 0;
715 ta_status.poly_context[4] = 0;
716 }
718 ta_status.poly_pointer = (ta_status.poly_vertex_size << 21);
719 ta_status.poly_context_size = 3;
720 if( data[0].i & TA_POLYCMD_MODIFIED ) {
721 ta_status.poly_pointer |= 0x01000000;
722 if( data[0].i & TA_POLYCMD_FULLMOD ) {
723 ta_status.poly_context_size = 5;
724 ta_status.poly_vertex_size <<= 1;
725 ta_status.current_vertex_type |= 0x40;
726 /* Modified/float not supported - behaves as per last intensity */
727 if( colourfmt == TA_POLYCMD_COLOURFMT_FLOAT ) {
728 colourfmt = TA_POLYCMD_COLOURFMT_LASTINT;
729 }
730 }
731 }
733 if( colourfmt == TA_POLYCMD_COLOURFMT_INTENSITY ) {
734 if( TA_POLYCMD_IS_FULLMOD(data[0].i) ||
735 TA_POLYCMD_IS_SPECULAR(data[0].i) ) {
736 ta_status.state = STATE_EXPECT_POLY_BLOCK2;
737 } else {
738 ta_status.intensity1 =
739 parse_float_colour( data[4].f, data[5].f, data[6].f, data[7].f );
740 }
741 } else if( colourfmt == TA_POLYCMD_COLOURFMT_LASTINT ) {
742 colourfmt = TA_POLYCMD_COLOURFMT_INTENSITY;
743 }
745 ta_status.current_vertex_type |= colourfmt;
746 }
748 /**
749 * Parse the modifier volume context block and setup the internal state to
750 * receive modifier vertexes.
751 * @param data 32 bytes of parameter data.
752 */
753 static void ta_parse_modifier_context( union ta_data *data ) {
754 ta_status.current_vertex_type = TA_VERTEX_MOD_VOLUME;
755 ta_status.poly_vertex_size = 0;
756 ta_status.clip_mode = TA_POLYCMD_CLIP(data[0].i);
757 if( ta_status.clip_mode == 1 ) { /* Reserved - treat as CLIP_INSIDE */
758 ta_status.clip_mode = TA_POLYCMD_CLIP_INSIDE;
759 }
760 ta_status.poly_context_size = 3;
761 ta_status.poly_context[0] = (data[1].i & 0xFC1FFFFF) |
762 ((data[0].i & 0x0B)<<22);
763 if( TA_POLYCMD_IS_SPECULAR(data[0].i) ) {
764 ta_status.poly_context[0] |= 0x01000000;
765 }
766 ta_status.poly_context[1] = 0;
767 ta_status.poly_context[2] = 0;
768 ta_status.vertex_count = 0;
769 ta_status.max_vertex = 3;
770 ta_status.poly_pointer = 0;
771 }
773 /**
774 * Parse the sprite context block and setup the internal state to receive
775 * vertexes.
776 * @param data 32 bytes of parameter data.
777 */
778 static void ta_parse_sprite_context( union ta_data *data ) {
779 ta_status.poly_context_size = 3;
780 ta_status.poly_context[0] = (data[1].i & 0xFC1FFFFF) |
781 ((data[0].i & 0x0B)<<22) | 0x00400000;
782 ta_status.clip_mode = TA_POLYCMD_CLIP(data[0].i);
783 if( ta_status.clip_mode == 1 ) { /* Reserved - treat as CLIP_INSIDE */
784 ta_status.clip_mode = TA_POLYCMD_CLIP_INSIDE;
785 }
786 if( TA_POLYCMD_IS_SPECULAR(data[0].i) ) {
787 ta_status.poly_context[0] |= 0x01000000;
788 }
789 ta_status.poly_context[1] = data[2].i;
790 ta_status.poly_context[2] = data[3].i;
791 if( data[0].i & TA_POLYCMD_TEXTURED ) {
792 ta_status.poly_vertex_size = 2;
793 ta_status.poly_vertex[2].detail[1] = data[4].i;
794 ta_status.current_vertex_type = TA_VERTEX_TEX_SPRITE;
795 } else {
796 ta_status.poly_vertex_size = 1;
797 ta_status.poly_vertex[2].detail[0] = data[4].i;
798 ta_status.current_vertex_type = TA_VERTEX_SPRITE;
799 }
800 ta_status.vertex_count = 0;
801 ta_status.max_vertex = 4;
802 ta_status.poly_pointer = (ta_status.poly_vertex_size << 21);
803 }
805 /**
806 * Copy the last read vertex into all vertexes up to max_vertex. Used for
807 * Aborted polygons under some circumstances.
808 */
809 static void ta_fill_vertexes( ) {
810 int i;
811 for( i=ta_status.vertex_count; i<ta_status.max_vertex; i++ ) {
812 memcpy( &ta_status.poly_vertex[i], &ta_status.poly_vertex[ta_status.vertex_count-1],
813 sizeof( struct pvr2_ta_vertex ) );
814 }
815 }
817 static void ta_parse_vertex( union ta_data *data ) {
818 struct pvr2_ta_vertex *vertex = &ta_status.poly_vertex[ta_status.vertex_count];
819 vertex->x = data[1].f;
820 vertex->y = data[2].f;
821 vertex->z = data[3].f;
823 switch( ta_status.current_vertex_type ) {
824 case TA_VERTEX_PACKED:
825 vertex->detail[0] = data[6].i;
826 break;
827 case TA_VERTEX_FLOAT:
828 vertex->detail[0] = parse_float_colour( data[4].f, data[5].f, data[6].f, data[7].f );
829 break;
830 case TA_VERTEX_INTENSITY:
831 vertex->detail[0] = parse_intensity_colour( ta_status.intensity1, data[6].f );
832 break;
834 case TA_VERTEX_TEX_SPEC_PACKED:
835 vertex->detail[3] = data[7].i; /* ARGB */
836 /* Fallthrough */
837 case TA_VERTEX_TEX_PACKED:
838 vertex->detail[0] = data[4].i; /* U */
839 vertex->detail[1] = data[5].i; /* V */
840 vertex->detail[2] = data[6].i; /* ARGB */
841 break;
842 case TA_VERTEX_TEX_UV16_SPEC_PACKED:
843 vertex->detail[2] = data[7].i; /* ARGB */
844 /* Fallthrough */
845 case TA_VERTEX_TEX_UV16_PACKED:
846 vertex->detail[0] = data[4].i; /* UV */
847 vertex->detail[1] = data[6].i; /* ARGB */
848 break;
850 case TA_VERTEX_TEX_FLOAT:
851 case TA_VERTEX_TEX_SPEC_FLOAT:
852 vertex->detail[0] = data[4].i; /* U */
853 vertex->detail[1] = data[5].i; /* UV */
854 ta_status.state = STATE_EXPECT_VERTEX_BLOCK2;
855 break;
856 case TA_VERTEX_TEX_UV16_FLOAT:
857 case TA_VERTEX_TEX_UV16_SPEC_FLOAT:
858 vertex->detail[0] = data[4].i; /* UV */
859 ta_status.state = STATE_EXPECT_VERTEX_BLOCK2;
860 break;
862 case TA_VERTEX_TEX_SPEC_INTENSITY:
863 vertex->detail[3] = parse_intensity_colour( ta_status.intensity2, data[7].f );
864 /* Fallthrough */
865 case TA_VERTEX_TEX_INTENSITY:
866 vertex->detail[0] = data[4].i; /* U */
867 vertex->detail[1] = data[5].i; /* V */
868 vertex->detail[2] = parse_intensity_colour( ta_status.intensity1, data[6].f );
869 break;
870 case TA_VERTEX_TEX_UV16_SPEC_INTENSITY:
871 vertex->detail[2] = parse_intensity_colour( ta_status.intensity2, data[7].f );
872 /* Fallthrough */
873 case TA_VERTEX_TEX_UV16_INTENSITY:
874 vertex->detail[0] = data[4].i; /* UV */
875 vertex->detail[1] = parse_intensity_colour( ta_status.intensity1, data[6].f );
876 break;
878 case TA_VERTEX_PACKED_MOD:
879 vertex->detail[0] = data[4].i; /* ARGB */
880 vertex->detail[1] = data[5].i; /* ARGB */
881 break;
882 case TA_VERTEX_INTENSITY_MOD:
883 vertex->detail[0] = parse_intensity_colour( ta_status.intensity1, data[4].f );
884 vertex->detail[1] = parse_intensity_colour( ta_status.intensity2, data[5].f );
885 break;
887 case TA_VERTEX_TEX_SPEC_PACKED_MOD:
888 vertex->detail[3] = data[7].i; /* ARGB0 */
889 /* Fallthrough */
890 case TA_VERTEX_TEX_PACKED_MOD:
891 vertex->detail[0] = data[4].i; /* U0 */
892 vertex->detail[1] = data[5].i; /* V0 */
893 vertex->detail[2] = data[6].i; /* ARGB0 */
894 ta_status.state = STATE_EXPECT_VERTEX_BLOCK2;
895 break;
896 case TA_VERTEX_TEX_UV16_SPEC_PACKED_MOD:
897 vertex->detail[2] = data[7].i; /* ARGB0 */
898 /* Fallthrough */
899 case TA_VERTEX_TEX_UV16_PACKED_MOD:
900 vertex->detail[0] = data[4].i; /* UV0 */
901 vertex->detail[1] = data[6].i; /* ARGB0 */
902 ta_status.state = STATE_EXPECT_VERTEX_BLOCK2;
903 break;
905 case TA_VERTEX_TEX_SPEC_INTENSITY_MOD:
906 vertex->detail[3] = parse_intensity_colour( ta_status.intensity1, data[7].f );
907 /* Fallthrough */
908 case TA_VERTEX_TEX_INTENSITY_MOD:
909 vertex->detail[0] = data[4].i; /* U0 */
910 vertex->detail[1] = data[5].i; /* V0 */
911 vertex->detail[2] = parse_intensity_colour( ta_status.intensity1, data[6].f );
912 ta_status.state = STATE_EXPECT_VERTEX_BLOCK2;
913 break;
914 case TA_VERTEX_TEX_UV16_SPEC_INTENSITY_MOD:
915 vertex->detail[2] = parse_intensity_colour( ta_status.intensity1, data[7].f );
916 /* Fallthrough */
917 case TA_VERTEX_TEX_UV16_INTENSITY_MOD:
918 vertex->detail[0] = data[4].i; /* UV0 */
919 vertex->detail[1] = parse_intensity_colour( ta_status.intensity1, data[6].f );
920 ta_status.state = STATE_EXPECT_VERTEX_BLOCK2;
921 break;
923 case TA_VERTEX_SPRITE:
924 case TA_VERTEX_TEX_SPRITE:
925 case TA_VERTEX_MOD_VOLUME:
926 case TA_VERTEX_LISTLESS:
927 vertex++;
928 vertex->x = data[4].f;
929 vertex->y = data[5].f;
930 vertex->z = data[6].f;
931 vertex++;
932 vertex->x = data[7].f;
933 ta_status.vertex_count += 2;
934 ta_status.state = STATE_EXPECT_VERTEX_BLOCK2;
935 break;
936 }
937 ta_status.vertex_count++;
938 }
940 static void ta_parse_vertex_block2( union ta_data *data ) {
941 struct pvr2_ta_vertex *vertex = &ta_status.poly_vertex[ta_status.vertex_count-1];
943 switch( ta_status.current_vertex_type ) {
944 case TA_VERTEX_TEX_SPEC_FLOAT:
945 vertex->detail[3] = parse_float_colour( data[4].f, data[5].f, data[6].f, data[7].f );
946 /* Fallthrough */
947 case TA_VERTEX_TEX_FLOAT:
948 vertex->detail[2] = parse_float_colour( data[0].f, data[1].f, data[2].f, data[3].f );
949 break;
950 case TA_VERTEX_TEX_UV16_SPEC_FLOAT:
951 vertex->detail[2] = parse_float_colour( data[4].f, data[5].f, data[6].f, data[7].f );
952 /* Fallthrough */
953 case TA_VERTEX_TEX_UV16_FLOAT:
954 vertex->detail[1] = parse_float_colour( data[0].f, data[1].f, data[2].f, data[3].f );
955 break;
956 case TA_VERTEX_TEX_PACKED_MOD:
957 vertex->detail[3] = data[0].i; /* U1 */
958 vertex->detail[4] = data[1].i; /* V1 */
959 vertex->detail[5] = data[2].i; /* ARGB1 */
960 break;
961 case TA_VERTEX_TEX_SPEC_PACKED_MOD:
962 vertex->detail[4] = data[0].i; /* U1 */
963 vertex->detail[5] = data[1].i; /* V1 */
964 vertex->detail[6] = data[2].i; /* ARGB1 */
965 vertex->detail[7] = data[3].i; /* ARGB1 */
966 break;
967 case TA_VERTEX_TEX_UV16_PACKED_MOD:
968 vertex->detail[2] = data[0].i; /* UV1 */
969 vertex->detail[3] = data[2].i; /* ARGB1 */
970 break;
971 case TA_VERTEX_TEX_UV16_SPEC_PACKED_MOD:
972 vertex->detail[3] = data[0].i; /* UV1 */
973 vertex->detail[4] = data[2].i; /* ARGB1 */
974 vertex->detail[5] = data[3].i; /* ARGB1 */
975 break;
977 case TA_VERTEX_TEX_INTENSITY_MOD:
978 vertex->detail[3] = data[0].i; /* U1 */
979 vertex->detail[4] = data[1].i; /* V1 */
980 vertex->detail[5] = parse_intensity_colour( ta_status.intensity2, data[2].f ); /* ARGB1 */
981 break;
982 case TA_VERTEX_TEX_SPEC_INTENSITY_MOD:
983 vertex->detail[4] = data[0].i; /* U1 */
984 vertex->detail[5] = data[1].i; /* V1 */
985 vertex->detail[6] = parse_intensity_colour( ta_status.intensity2, data[2].f ); /* ARGB1 */
986 vertex->detail[7] = parse_intensity_colour( ta_status.intensity2, data[3].f ); /* ARGB1 */
987 break;
988 case TA_VERTEX_TEX_UV16_INTENSITY_MOD:
989 vertex->detail[2] = data[0].i; /* UV1 */
990 vertex->detail[3] = parse_intensity_colour( ta_status.intensity2, data[2].f ); /* ARGB1 */
991 break;
992 case TA_VERTEX_TEX_UV16_SPEC_INTENSITY_MOD:
993 vertex->detail[3] = data[0].i; /* UV1 */
994 vertex->detail[4] = parse_intensity_colour( ta_status.intensity2, data[2].f ); /* ARGB1 */
995 vertex->detail[5] = parse_intensity_colour( ta_status.intensity2, data[3].f ); /* ARGB1 */
996 break;
998 case TA_VERTEX_SPRITE:
999 vertex->y = data[0].f;
1000 vertex->z = data[1].f;
1001 vertex++;
1002 ta_status.vertex_count++;
1003 vertex->x = data[2].f;
1004 vertex->y = data[3].f;
1005 vertex->z = 0;
1006 vertex->detail[0] = 0;
1007 ta_status.poly_vertex[0].detail[0] = 0;
1008 ta_status.poly_vertex[1].detail[0] = 0;
1009 break;
1010 case TA_VERTEX_TEX_SPRITE:
1011 vertex->y = data[0].f;
1012 vertex->z = data[1].f;
1013 vertex++;
1014 ta_status.vertex_count++;
1015 vertex->x = data[2].f;
1016 vertex->y = data[3].f;
1017 vertex->z = 0;
1018 vertex->detail[0] = 0;
1019 vertex->detail[1] = 0;
1020 ta_status.poly_vertex[0].detail[0] = data[5].i;
1021 ta_status.poly_vertex[0].detail[1] = 0;
1022 ta_status.poly_vertex[1].detail[0] = data[6].i;
1023 ta_status.poly_vertex[1].detail[1] = 0;
1024 ta_status.poly_vertex[2].detail[0] = data[7].i;
1025 break;
1026 case TA_VERTEX_MOD_VOLUME:
1027 case TA_VERTEX_LISTLESS:
1028 vertex->y = data[0].f;
1029 vertex->z = data[1].f;
1030 break;
1031 }
1032 ta_status.state = STATE_IN_POLYGON;
1033 }
1035 /**
1036 * Process 1 32-byte block of ta data
1037 */
1038 void pvr2_ta_process_block( unsigned char *input ) {
1039 union ta_data *data = (union ta_data *)input;
1041 switch( ta_status.state ) {
1042 case STATE_ERROR:
1043 /* Fatal error raised - stop processing until reset */
1044 return;
1046 case STATE_EXPECT_POLY_BLOCK2:
1047 /* This is always a pair of floating-point colours */
1048 ta_status.intensity1 =
1049 parse_float_colour( data[0].f, data[1].f, data[2].f, data[3].f );
1050 ta_status.intensity2 =
1051 parse_float_colour( data[4].f, data[5].f, data[6].f, data[7].f );
1052 ta_status.state = STATE_IN_LIST;
1053 break;
1055 case STATE_EXPECT_VERTEX_BLOCK2:
1056 ta_parse_vertex_block2( data );
1057 if( ta_status.vertex_count == ta_status.max_vertex ) {
1058 ta_split_polygon();
1059 }
1060 break;
1062 case STATE_EXPECT_END_VERTEX_BLOCK2:
1063 ta_parse_vertex_block2( data );
1064 if( ta_status.vertex_count < 3 ) {
1065 ta_bad_input_error();
1066 } else {
1067 ta_commit_polygon();
1068 }
1069 ta_status.vertex_count = 0;
1070 ta_status.poly_parity = 0;
1071 ta_status.state = STATE_IN_LIST;
1072 break;
1073 case STATE_IN_LIST:
1074 case STATE_IN_POLYGON:
1075 case STATE_IDLE:
1076 switch( TA_CMD( data->i ) ) {
1077 case TA_CMD_END_LIST:
1078 if( ta_status.state == STATE_IN_POLYGON ) {
1079 ta_bad_input_error();
1080 ta_end_list();
1081 ta_status.state = STATE_ERROR; /* Abort further processing */
1082 } else {
1083 ta_end_list();
1084 }
1085 break;
1086 case TA_CMD_CLIP:
1087 if( ta_status.state == STATE_IN_POLYGON ) {
1088 ta_bad_input_error();
1089 ta_status.accept_vertexes = FALSE;
1090 /* Enter stuffed up mode */
1091 }
1092 ta_status.clip.x1 = data[4].i & 0x3F;
1093 ta_status.clip.y1 = data[5].i & 0x0F;
1094 ta_status.clip.x2 = data[6].i & 0x3F;
1095 ta_status.clip.y2 = data[7].i & 0x0F;
1096 if( ta_status.clip.x2 >= ta_status.width )
1097 ta_status.clip.x2 = ta_status.width - 1;
1098 if( ta_status.clip.y2 >= ta_status.height )
1099 ta_status.clip.y2 = ta_status.height - 1;
1100 break;
1101 case TA_CMD_POLYGON_CONTEXT:
1102 if( ta_status.state == STATE_IDLE ) {
1103 ta_init_list( TA_POLYCMD_LISTTYPE( data->i ) );
1104 }
1106 if( ta_status.vertex_count != 0 ) {
1107 /* Error, and not a very well handled one either */
1108 ta_bad_input_error();
1109 ta_status.accept_vertexes = FALSE;
1110 } else {
1111 if( TA_IS_MODIFIER_LIST( ta_status.current_list_type ) ) {
1112 ta_parse_modifier_context(data);
1113 } else {
1114 ta_parse_polygon_context(data);
1115 }
1116 }
1117 break;
1118 case TA_CMD_SPRITE_CONTEXT:
1119 if( ta_status.state == STATE_IDLE ) {
1120 ta_init_list( TA_POLYCMD_LISTTYPE( data->i ) );
1121 }
1123 if( ta_status.vertex_count != 0 ) {
1124 ta_fill_vertexes();
1125 ta_commit_polygon();
1126 }
1128 ta_parse_sprite_context(data);
1129 break;
1130 case TA_CMD_VERTEX:
1131 ta_status.state = STATE_IN_POLYGON;
1132 ta_parse_vertex(data);
1134 if( ta_status.state == STATE_EXPECT_VERTEX_BLOCK2 ) {
1135 if( TA_IS_END_VERTEX(data[0].i) ) {
1136 ta_status.state = STATE_EXPECT_END_VERTEX_BLOCK2;
1137 }
1138 } else if( TA_IS_END_VERTEX(data->i) ) {
1139 if( ta_status.vertex_count < 3 ) {
1140 ta_bad_input_error();
1141 } else {
1142 ta_commit_polygon();
1143 }
1144 ta_status.vertex_count = 0;
1145 ta_status.poly_parity = 0;
1146 ta_status.state = STATE_IN_LIST;
1147 } else if( ta_status.vertex_count == ta_status.max_vertex ) {
1148 ta_split_polygon();
1149 }
1150 break;
1151 default:
1152 if( ta_status.state == STATE_IN_POLYGON ) {
1153 ta_bad_input_error();
1154 }
1155 }
1156 break;
1157 }
1159 }
1161 /**
1162 * Find the first polygon or sprite context in the supplied buffer of TA
1163 * data.
1164 * @return A pointer to the context, or NULL if it cannot be found
1165 */
1166 uint32_t *pvr2_ta_find_polygon_context( uint32_t *buf, uint32_t length )
1167 {
1168 uint32_t *poly;
1169 for( poly = buf; poly < buf+(length>>2); poly += 8 ) {
1170 if( TA_CMD(*poly) == TA_CMD_POLYGON_CONTEXT ||
1171 TA_CMD(*poly) == TA_CMD_SPRITE_CONTEXT ) {
1172 return poly;
1173 }
1174 }
1175 return NULL;
1176 }
1178 /**
1179 * Write a block of data to the tile accelerator, adding the data to the
1180 * current scene. We don't make any particular attempt to interpret the data
1181 * at this stage, deferring that until render time.
1182 *
1183 * Currently copies the data verbatim to the vertex buffer, processing only
1184 * far enough to generate the correct end-of-list events. Tile buffer is
1185 * entirely ignored.
1186 */
1187 void pvr2_ta_write( unsigned char *buf, uint32_t length )
1188 {
1189 if( ta_status.debug_output ) {
1190 fwrite_dump32( (uint32_t *)buf, length, stderr );
1191 }
1193 for( ; length >=32; length -= 32 ) {
1194 pvr2_ta_process_block( buf );
1195 buf += 32;
1196 }
1197 }
1199 void FASTCALL pvr2_ta_write_burst( sh4addr_t addr, unsigned char *data )
1200 {
1201 if( ta_status.debug_output ) {
1202 fwrite_dump32( (uint32_t *)data, 32, stderr );
1203 }
1204 pvr2_ta_process_block( data );
1205 }
.