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