Search
lxdream.org :: lxdream/src/pvr2/tacore.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/pvr2/tacore.c
changeset 189:615b70cfd729
next193:31151fcc3cb7
author nkeynes
date Wed Aug 02 04:06:45 2006 +0000 (13 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
view annotate diff log raw
     1 /**
     2  * $Id: tacore.c,v 1.1 2006-08-02 04:06:45 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_EXPECT_POLY_BLOCK2   2
    24 #define STATE_EXPECT_VERTEX_BLOCK2 3
    25 #define STATE_ERROR                4
    26 #define STATE_EXPECT_END_VERTEX_BLOCK2 7
    28 #define TA_CMD(i) ( (i) >> 29 )
    29 #define TA_CMD_END_LIST 0
    30 #define TA_CMD_CLIP 1
    31 #define TA_CMD_POLYGON_CONTEXT 4
    32 #define TA_CMD_SPRITE_CONTEXT 5
    33 #define TA_CMD_VERTEX 7
    35 #define TA_LIST_NONE -1
    36 #define TA_LIST_OPAQUE 0
    37 #define TA_LIST_OPAQUE_MOD 1
    38 #define TA_LIST_TRANS 2
    39 #define TA_LIST_TRANS_MOD 3
    40 #define TA_LIST_PUNCH_OUT 4
    41 #define TA_IS_MODIFIER_LIST(list) (list == TA_LIST_OPAQUE_MOD || list == TA_LIST_TRANS_MOD)
    43 #define TA_GROW_UP 0
    44 #define TA_GROW_DOWN 1
    46 #define TA_VERTEX_NONE                        -1
    47 #define TA_VERTEX_PACKED                      0x00
    48 #define TA_VERTEX_TEX_PACKED                  0x08
    49 #define TA_VERTEX_TEX_SPEC_PACKED             0x0C
    50 #define TA_VERTEX_TEX_UV16_PACKED             0x09
    51 #define TA_VERTEX_TEX_UV16_SPEC_PACKED        0x0D
    52 #define TA_VERTEX_FLOAT                       0x10
    53 #define TA_VERTEX_TEX_FLOAT                   0x18
    54 #define TA_VERTEX_TEX_SPEC_FLOAT              0x1C
    55 #define TA_VERTEX_TEX_UV16_FLOAT              0x19
    56 #define TA_VERTEX_TEX_UV16_SPEC_FLOAT         0x1D
    57 #define TA_VERTEX_INTENSITY                   0x20
    58 #define TA_VERTEX_TEX_INTENSITY               0x28
    59 #define TA_VERTEX_TEX_SPEC_INTENSITY          0x2C
    60 #define TA_VERTEX_TEX_UV16_INTENSITY          0x29
    61 #define TA_VERTEX_TEX_UV16_SPEC_INTENSITY     0x2D
    62 #define TA_VERTEX_PACKED_MOD                  0x40
    63 #define TA_VERTEX_TEX_PACKED_MOD              0x48
    64 #define TA_VERTEX_TEX_SPEC_PACKED_MOD         0x4C
    65 #define TA_VERTEX_TEX_UV16_PACKED_MOD         0x49
    66 #define TA_VERTEX_TEX_UV16_SPEC_PACKED_MOD    0x4D
    67 #define TA_VERTEX_INTENSITY_MOD               0x60
    68 #define TA_VERTEX_TEX_INTENSITY_MOD           0x68
    69 #define TA_VERTEX_TEX_SPEC_INTENSITY_MOD      0x6C
    70 #define TA_VERTEX_TEX_UV16_INTENSITY_MOD      0x69
    71 #define TA_VERTEX_TEX_UV16_SPEC_INTENSITY_MOD 0x6D
    72 #define TA_VERTEX_SPRITE                      0x80
    73 #define TA_VERTEX_TEX_SPRITE                  0x88
    74 #define TA_VERTEX_MOD_VOLUME                  0x81
    76 #define TA_IS_NORMAL_POLY() (ta_status.current_vertex_type < TA_VERTEX_SPRITE)
    78 static int strip_lengths[4] = {3,4,6,8}; /* in vertexes */
    79 #define TA_POLYCMD_LISTTYPE(i) ( ((i) >> 24) & 0x0F )
    80 #define TA_POLYCMD_LENGTH(i)  strip_lengths[((i >> 18) & 0x03)]
    81 #define TA_POLYCMD_CLIP(i)  ((i>>16)&0x03)
    82 #define TA_POLYCMD_COLOURFMT(i)  (i & 0x00000030)
    83 #define TA_POLYCMD_COLOURFMT_ARGB32 0x00000000
    84 #define TA_POLYCMD_COLOURFMT_FLOAT 0x00000010
    85 #define TA_POLYCMD_COLOURFMT_INTENSITY 0x00000020
    86 #define TA_POLYCMD_COLOURFMT_LASTINT 0x00000030
    88 #define TA_POLYCMD_MODIFIED 0x00000080
    89 #define TA_POLYCMD_FULLMOD  0x00000040
    90 #define TA_POLYCMD_TEXTURED 0x00000008
    91 #define TA_POLYCMD_SPECULAR 0x00000004
    92 #define TA_POLYCMD_SHADED 0x00000002
    93 #define TA_POLYCMD_UV16 0x00000001
    95 #define TA_POLYCMD_IS_SPECULAR(i) ((i & 0x0000000C)==0x0000000C) /* Only applies to textured polys */
    96 #define TA_POLYCMD_IS_FULLMOD(i) ((i & 0x000000C0)==0x000000C0)
    99 #define TA_IS_END_VERTEX(i) (i & 0x10000000)
   101 #define MIN3( x1, x2, x3 ) ( (x1)<(x2)? ((x1)<(x3)?(x1):(x3)) : ((x2)<(x3)?(x2):(x3)) )
   102 #define MAX3( x1, x2, x3 ) ( (x1)>(x2)? ((x1)>(x3)?(x1):(x3)) : ((x2)>(x3)?(x2):(x3)) )
   104 #define TILESLOT( x, y ) (ta_status.current_tile_matrix + (ta_status.current_tile_size * (y * ta_status.width+ x) << 2))
   106 extern char *video_base;
   107 #define PVRRAM(addr) (*(uint32_t *)(video_base + ((addr)&PVR2_RAM_MASK)))
   109 struct pvr2_ta_vertex {
   110     float x,y,z;
   111     uint32_t detail[8]; /* 0-8 detail words */
   112 };
   114 struct tile_bounds {
   115     int x1, y1, x2, y2;
   116 };
   118 struct pvr2_ta_status {
   119     int state;
   120     int width, height; /* Tile resolution, ie 20x15 */
   121     int tilelist_dir; /* Growth direction of the tilelist, 0 = up, 1 = down */
   122     uint32_t tilelist_size; /* Size of the tilelist segments */
   123     int current_vertex_type;
   124     int vertex_count; /* index of last start-vertex seen, or -1 if no vertexes 
   125 			 * are present
   126 			 */
   127     int max_vertex;     /* Maximum number of vertexes in the current polygon (3/4/6/8) */
   128     int current_list_type;
   129     uint32_t current_tile_matrix; /* Memory location of the first tile for the current list. */
   130     uint32_t current_tile_size; /* Size of the tile matrix space  in 32-bit words (0/8/16/32)*/
   131     uint32_t intensity1, intensity2;
   132     /**
   133      * Current working object
   134      */
   135     int poly_context_size;
   136     int poly_vertex_size;
   137     int poly_parity;
   138     uint32_t poly_context[5];
   139     uint32_t poly_pointer;
   140     struct tile_bounds last_triangle_bounds;
   141     struct pvr2_ta_vertex poly_vertex[8];
   142     int debug_output;
   143 };
   145 static struct pvr2_ta_status ta_status;
   147 static int tilematrix_sizes[4] = {0,8,16,32};
   149 /**
   150  * Convenience union - ta data is either 32-bit integer or 32-bit float.
   151  */
   152 union ta_data {
   153     unsigned int i;
   154     float f;
   155 };
   158 void pvr2_ta_reset() {
   159     ta_status.state = STATE_ERROR; /* State not valid until initialized */
   160     ta_status.debug_output = 0;
   161 }
   163 void pvr2_ta_init() {
   164     ta_status.state = STATE_IDLE;
   165     ta_status.current_list_type = -1;
   166     ta_status.current_vertex_type = -1;
   167     ta_status.poly_parity = 0;
   168     ta_status.vertex_count = 0;
   169     ta_status.max_vertex = 3;
   170     ta_status.last_triangle_bounds.x1 = -1;
   172     uint32_t size = MMIO_READ( PVR2, TA_TILESIZE );
   173     ta_status.width = (size & 0xFFFF) + 1;
   174     ta_status.height = (size >> 16) + 1;
   175     uint32_t control = MMIO_READ( PVR2, TA_TILECFG );
   176     ta_status.tilelist_dir = (control >> 20) & 0x01;
   177     ta_status.tilelist_size = tilematrix_sizes[ (control & 0x03) ];
   178     MMIO_WRITE( PVR2, TA_POLYPOS, MMIO_READ( PVR2, TA_POLYBASE ) );
   179     uint32_t plistpos = MMIO_READ( PVR2, TA_LISTBASE ) >> 2;
   180     if( ta_status.tilelist_dir == TA_GROW_DOWN ) {
   181 	plistpos -= ta_status.tilelist_size;
   182     }
   183     MMIO_WRITE( PVR2, TA_LISTPOS, plistpos );
   184 }
   186 static uint32_t parse_float_colour( float a, float r, float g, float b ) {
   187     return
   188     	(((unsigned int)((256 * CLAMP(a,0.0,1.0))-1))<<24) |
   189     	(((unsigned int)((256 * CLAMP(r,0.0,1.0))-1))<<16) |
   190     	(((unsigned int)((256 * CLAMP(g,0.0,1.0))-1))<<8) |
   191     	(((unsigned int)((256 * CLAMP(b,0.0,1.0))-1)));
   192 }
   194 static uint32_t parse_intensity_colour( uint32_t base, float intensity )
   195 {
   196     unsigned int i = (unsigned int)(256 * CLAMP(intensity, 0.0,1.0));
   198     return
   199 	(((((base & 0xFF) * i) & 0xFF00) |
   200 	  (((base & 0xFF00) * i) & 0xFF0000) |
   201 	  (((base & 0xFF0000) * i) & 0xFF000000)) >> 8) |
   202 	base & 0xFF000000;
   203 }
   205 /**
   206  * Initialize the specified TA list.
   207  */
   208 static void ta_init_list( unsigned int listtype ) {
   209     int config = MMIO_READ( PVR2, TA_TILECFG );
   210     int tile_matrix = MMIO_READ( PVR2, TA_TILEBASE );
   211     if( listtype <= TA_LIST_PUNCH_OUT ) {
   212 	int i;
   213 	uint32_t *p;
   214 	for( i=0; i < listtype; i++ ) {
   215 	    int size = tilematrix_sizes[(config & 0x03)] << 2;
   216 	    tile_matrix += ta_status.width * ta_status.height * size;
   217 	    config >>= 4;
   218 	}
   219 	ta_status.current_tile_matrix = tile_matrix;
   220 	ta_status.current_tile_size = tilematrix_sizes[(config & 0x03)];
   222 	/* Initialize each tile to 0xF0000000 */
   223 	if( ta_status.current_tile_size != 0 ) {
   224 	    p = (uint32_t *)(video_base + tile_matrix);
   225 	    for( i=0; i< ta_status.width * ta_status.height; i++ ) {
   226 		*p = 0xF0000000;
   227 		p += ta_status.current_tile_size;
   228 	    }
   229 	}
   230     }
   231     ta_status.state = STATE_IN_LIST;
   232     ta_status.current_list_type = listtype;
   233     ta_status.last_triangle_bounds.x1 = -1;
   234 }
   236 static int list_events[5] = {EVENT_PVR_OPAQUE_DONE, EVENT_PVR_OPAQUEMOD_DONE, 
   237 			     EVENT_PVR_TRANS_DONE, EVENT_PVR_TRANSMOD_DONE,
   238 			     EVENT_PVR_PUNCHOUT_DONE };
   240 static void ta_end_list() {
   241     if( ta_status.current_list_type != TA_LIST_NONE ) {
   242 	asic_event( list_events[ta_status.current_list_type] );
   243 	ta_status.current_list_type = TA_LIST_NONE;
   244 	ta_status.current_vertex_type = -1;
   245 	ta_status.state = STATE_IDLE;
   246     }
   247 }
   249 /**
   250  * Write data out to the polygon buffer.
   251  * If the end-of-buffer is reached, asserts EVENT_PVR_PRIM_ALLOC_FAIL
   252  * @param data to be written
   253  * @param length Number of 32-bit words to write.
   254  * @return number of words actually written
   255  */
   256 static int ta_write_polygon_buffer( uint32_t *data, int length )
   257 {
   258     int rv;
   259     int posn = MMIO_READ( PVR2, TA_POLYPOS );
   260     int end = MMIO_READ( PVR2, TA_POLYEND );
   261     uint32_t *target = (uint32_t *)(video_base + posn);
   262     for( rv=0; rv < length; rv++ ) {
   263 	if( posn == end ) {
   264 	    asic_event( EVENT_PVR_PRIM_ALLOC_FAIL );
   265 	    asic_event( EVENT_TA_ERROR );
   266 	    //	    ta_status.state = STATE_ERROR;
   267 	    break;
   268 	}
   269 	*target++ = *data++;
   270 	posn += 4;
   271     }
   273     MMIO_WRITE( PVR2, TA_POLYPOS, posn );
   274     return rv;
   275 }
   277 /**
   278  * Allocate a new tile list from the grow space
   279  */
   280 static uint32_t ta_alloc_tilelist() {
   281     uint32_t posn = MMIO_READ( PVR2, TA_LISTPOS );
   282     uint32_t newposn;
   283     if( ta_status.tilelist_dir == TA_GROW_DOWN ) {
   284 	newposn = posn - ta_status.tilelist_size;
   285     } else {
   286 	newposn = posn + ta_status.tilelist_size;
   287     }
   288     MMIO_WRITE( PVR2, TA_LISTPOS, newposn );
   289     return posn << 2;
   290 }
   292 /**
   293  * Write a tile entry out to the matrix.
   294  */
   295 static int ta_write_tile_entry( int x, int y, uint32_t tile_entry ) {
   296     uint32_t tile = TILESLOT(x,y);
   297     uint32_t value;
   298     uint32_t lasttri = 0;
   299     int i,l;
   301     if( (tile_entry & 0x80000000) && 
   302 	ta_status.last_triangle_bounds.x1 != -1 &&
   303 	ta_status.last_triangle_bounds.x1 <= x &&
   304 	ta_status.last_triangle_bounds.x2 >= x &&
   305 	ta_status.last_triangle_bounds.y1 <= y &&
   306 	ta_status.last_triangle_bounds.y2 >= y ) {
   307 	/* potential for triangle stacking */
   308 	lasttri = tile_entry & 0xE1E00000;
   309     }
   312     if( PVRRAM(tile) == 0xF0000000 ) {
   313 	PVRRAM(tile) = tile_entry;
   314 	PVRRAM(tile+4) = 0xF0000000;
   315 	return;
   316     }
   318     while(1) {
   319 	value = PVRRAM(tile);
   320 	for( i=1; i<ta_status.current_tile_size; i++ ) {
   321 	    tile += 4;
   322 	    uint32_t nextval = PVRRAM(tile);
   323 	    if( nextval == 0xF0000000 ) {
   324 		if( lasttri != 0 && lasttri == (value&0xE1E00000) ) {
   325 		    int count = (value & 0x1E000000) + 0x02000000;
   326 		    if( count < 0x20000000 ) {
   327 			PVRRAM(tile-4) = (value & 0xE1FFFFFF) | count;
   328 			return;
   329 		    }
   330 		}
   331 		if( i < ta_status.current_tile_size-1 ) {
   332 		    PVRRAM(tile) = tile_entry;
   333 		    PVRRAM(tile+4) = 0xF0000000;
   334 		    return;
   335 		}
   336 	    }
   337 	    value = nextval;
   338 	}
   340 	if( value == 0xF0000000 ) {
   341 	    value = ta_alloc_tilelist();
   342 	    PVRRAM(tile) = value | 0xE0000000;
   343 	    tile = value;
   344 	    PVRRAM(tile) = tile_entry;
   345 	    PVRRAM(tile+4) = 0xF0000000;
   346 	    return;
   347 	} else if( (value & 0xFF000000) == 0xE0000000 ) {
   348 	    tile = (value & 0x00FFFFFF);
   349 	} else {
   350 	    /* This should never happen */
   351 	    return 0;
   352 	}
   353     }
   354 }
   356 /**
   357  * Write a completed polygon out to the memory buffers 
   358  * OPTIMIZEME: This is not terribly efficient at the moment.
   359  */
   360 static void ta_commit_polygon( ) {
   361     int i, x, y;
   362     int tx[ta_status.vertex_count], ty[ta_status.vertex_count];
   363     struct tile_bounds triangle_bound[ta_status.vertex_count - 2];
   364     struct tile_bounds polygon_bound;
   365     uint32_t poly_context[5];
   367     if( ta_status.vertex_count < 2 ) {
   368 	return; /* No polygons - ignore */
   369     }
   370     memcpy( poly_context, ta_status.poly_context, ta_status.poly_context_size * 4 );
   372     /* Compute the tile coordinates for each vertex (need to be careful with
   373      * clamping here)
   374      */
   375     for( i=0; i<ta_status.vertex_count; i++ ) {
   376 	if( ta_status.poly_vertex[i].x < 0.0 ) {
   377 	    tx[i] = -1;
   378 	} else if( ta_status.poly_vertex[i].x > (float)INT_MAX ) {
   379 	    tx[i] = INT_MAX/32;
   380 	} else {
   381 	    tx[i] = (int)(ta_status.poly_vertex[i].x / 32.0);
   382 	}
   383 	if( ta_status.poly_vertex[i].y < 0.0 ) {
   384 	    ty[i] = -1;
   385 	} else if( ta_status.poly_vertex[i].y > (float)INT_MAX ) {
   386 	    ty[i] = INT_MAX/32;
   387 	} else {
   388 	    ty[i] = (int)(ta_status.poly_vertex[i].y / 32.0);
   389 	}
   391     }
   393     /* Compute bounding box for each triangle individually, as well
   394      * as the overall polygon.
   395      */
   397     for( i=0; i<ta_status.vertex_count-2; i++ ) {
   398 	triangle_bound[i].x1 = MIN3(tx[i],tx[i+1],tx[i+2]);
   399 	triangle_bound[i].x2 = MAX3(tx[i],tx[i+1],tx[i+2]);
   400 	triangle_bound[i].y1 = MIN3(ty[i],ty[i+1],ty[i+2]);
   401 	triangle_bound[i].y2 = MAX3(ty[i],ty[i+1],ty[i+2]);
   402 	if( i == 0 ) {
   403 	    polygon_bound.x1 = triangle_bound[0].x1;
   404 	    polygon_bound.y1 = triangle_bound[0].y1;
   405 	    polygon_bound.x2 = triangle_bound[0].x2;
   406 	    polygon_bound.y2 = triangle_bound[0].y2;
   407 	} else {
   408 	    polygon_bound.x1 = MIN(polygon_bound.x1, triangle_bound[i].x1);
   409 	    polygon_bound.x2 = MAX(polygon_bound.x2, triangle_bound[i].x2);
   410 	    polygon_bound.y1 = MIN(polygon_bound.y1, triangle_bound[i].y1);
   411 	    polygon_bound.y2 = MAX(polygon_bound.y2, triangle_bound[i].y2);
   412 	}
   413     }
   415     /* If the polygon is actually entirely out of the frustum, clip it entirely */
   416     if( polygon_bound.x2 < 0 || polygon_bound.x1 > ta_status.width ||
   417 	polygon_bound.y2 < 0 || polygon_bound.y1 > ta_status.height ) {
   418 	return;
   419     }
   421     /* Clamp the polygon bounds to the frustum */
   422     if( polygon_bound.x1 < 0 ) polygon_bound.x1 = 0;
   423     if( polygon_bound.x2 >= ta_status.width ) polygon_bound.x2 = ta_status.width-1;
   424     if( polygon_bound.y1 < 0 ) polygon_bound.y1 = 0;
   425     if( polygon_bound.y2 >= ta_status.width ) polygon_bound.y2 = ta_status.height-1;
   427     /* Set the "single tile" flag if it's entirely contained in 1 tile */
   428     if( polygon_bound.x1 == polygon_bound.x2 &&
   429 	polygon_bound.y1 == polygon_bound.y2 ) {
   430 	poly_context[0] |= 0x00200000;
   431     }
   433     /* Ok, we're good to go - write out the polygon first */
   434     uint32_t tile_entry = MMIO_READ( PVR2, TA_POLYPOS ) >> 2 | ta_status.poly_pointer;
   436     int status = ta_write_polygon_buffer( poly_context, ta_status.poly_context_size );
   437     if( status == 0 ) {
   438 	/* No memory available - abort */
   439 	return;
   440     } else {
   441 	for( i=0; i<ta_status.vertex_count && status != 0; i++ ) {
   442 	    status = ta_write_polygon_buffer( (uint32_t *)(&ta_status.poly_vertex[i]), 3 + ta_status.poly_vertex_size );
   443 	}
   444     }
   446     /* And now the tile entries. Triangles are different from everything else */
   447     if( ta_status.vertex_count == 3 ) {
   448 	tile_entry |= 0x80000000;
   449 	for( y=polygon_bound.y1; y<=polygon_bound.y2; y++ ) {
   450 	    for( x=polygon_bound.x1; x<=polygon_bound.x2; x++ ) {
   451 		ta_write_tile_entry( x,y,tile_entry );
   452 	    }
   453 	}
   454 	ta_status.last_triangle_bounds.x1 = polygon_bound.x1;
   455 	ta_status.last_triangle_bounds.y1 = polygon_bound.y1;
   456 	ta_status.last_triangle_bounds.x2 = polygon_bound.x2;
   457 	ta_status.last_triangle_bounds.y2 = polygon_bound.y2;
   458     } else if( ta_status.current_vertex_type == TA_VERTEX_SPRITE ||
   459 	       ta_status.current_vertex_type == TA_VERTEX_TEX_SPRITE ) {
   460 	tile_entry |= 0xA0000000;
   461 	for( y=polygon_bound.y1; y<=polygon_bound.y2; y++ ) {
   462 	    for( x=polygon_bound.x1; x<=polygon_bound.x2; x++ ) {
   463 		ta_write_tile_entry( x,y,tile_entry );
   464 	    }
   465 	}
   466 	ta_status.last_triangle_bounds.x1 = polygon_bound.x1;
   467 	ta_status.last_triangle_bounds.y1 = polygon_bound.y1;
   468 	ta_status.last_triangle_bounds.x2 = polygon_bound.x2;
   469 	ta_status.last_triangle_bounds.y2 = polygon_bound.y2;
   470     } else {
   471 	for( y=polygon_bound.y1; y<=polygon_bound.y2; y++ ) {
   472 	    for( x=polygon_bound.x1; x<=polygon_bound.x2; x++ ) {
   473 		uint32_t entry = tile_entry;
   474 		for( i=0; i<ta_status.vertex_count-2; i++ ) {
   475 		    if( triangle_bound[i].x1 <= x && triangle_bound[i].x2 >= x &&
   476 			triangle_bound[i].y1 <= y && triangle_bound[i].y2 >= y ) {
   477 			entry |= (0x40000000>>i);
   478 		    }
   479 		}
   480 		ta_write_tile_entry( x, y, entry );
   481 	    }
   482 	}
   483 	ta_status.last_triangle_bounds.x1 = -1;
   484     }
   485 }
   487 /**
   488  * Variant of ta_split_polygon called when vertex_count == max_vertex, but 
   489  * the client hasn't sent the LAST VERTEX flag. Commit the poly as normal
   490  * first, then start a new poly with the first 2 vertexes taken from the 
   491  * current one.
   492  */
   493 static void ta_split_polygon() {
   494     ta_commit_polygon();
   495     if( TA_IS_NORMAL_POLY() ) { 
   496 	/* This only applies to ordinary polys - Sprites + modifier lists are
   497 	 * handled differently
   498 	 */
   499 	if( ta_status.vertex_count == 3 ) {
   500 	    /* Triangles use an odd/even scheme */
   501 	    if( ta_status.poly_parity == 0 ) {
   502 		memcpy( &ta_status.poly_vertex[0], &ta_status.poly_vertex[2], 
   503 			sizeof(struct pvr2_ta_vertex) );
   504 		ta_status.poly_parity = 1;
   505 	    } else {
   506 		memcpy( &ta_status.poly_vertex[1], &ta_status.poly_vertex[2],
   507 			sizeof(struct pvr2_ta_vertex) );
   508 		ta_status.poly_parity = 0;
   509 	    }
   510 	} else {
   511 	    /* Everything else just uses the last 2 vertexes in order */
   512 	    memcpy( &ta_status.poly_vertex[0], &ta_status.poly_vertex[ta_status.vertex_count-2], 
   513 		    sizeof(struct pvr2_ta_vertex)*2 );
   514 	    ta_status.poly_parity = 0;
   515 	}
   516 	ta_status.vertex_count = 2;
   517     } else {
   518 	ta_status.vertex_count = 0;
   519     }
   520 }
   522 /**
   523  * Parse the polygon context block and setup the internal state to receive
   524  * vertexes.
   525  * @param data 32 bytes of parameter data.
   526  */
   527 static void ta_parse_polygon_context( union ta_data *data ) {
   528     int colourfmt = TA_POLYCMD_COLOURFMT(data[0].i);
   529     ta_status.max_vertex = TA_POLYCMD_LENGTH(data[0].i);
   530     ta_status.vertex_count = 0;
   531     ta_status.poly_context[0] = 
   532 	(data[1].i & 0xFC1FFFFF) | ((data[0].i & 0x0B) << 22);
   533     ta_status.poly_context[1] = data[2].i;
   534     ta_status.poly_context[3] = data[4].i;
   535     ta_status.poly_parity = 0;
   536     if( data[0].i & TA_POLYCMD_TEXTURED ) {
   537 	ta_status.current_vertex_type = data[0].i & 0x0D;
   538 	ta_status.poly_context[2] = data[3].i;
   539 	ta_status.poly_context[4] = data[5].i;
   540 	if( data[0].i & TA_POLYCMD_SPECULAR ) {
   541 	    ta_status.poly_context[0] |= 0x01000000;
   542 	    ta_status.poly_vertex_size = 4;
   543 	} else {
   544 	    ta_status.poly_vertex_size = 3;
   545 	}
   546 	if( data[0].i & TA_POLYCMD_UV16 ) {
   547 	    ta_status.poly_vertex_size--;
   548 	}
   549     } else {
   550 	ta_status.current_vertex_type = 0;
   551 	ta_status.poly_vertex_size = 1;
   552 	ta_status.poly_context[2] = 0;
   553 	ta_status.poly_context[4] = 0;
   554     }
   556     ta_status.poly_pointer = (ta_status.poly_vertex_size << 21);
   557     ta_status.poly_context_size = 3;
   558     if( data[0].i & TA_POLYCMD_MODIFIED ) {
   559 	ta_status.poly_pointer |= 0x01000000;
   560 	if( data[0].i & TA_POLYCMD_FULLMOD ) {
   561 	    ta_status.poly_context_size = 5;
   562 	    ta_status.poly_vertex_size <<= 1;
   563 	    ta_status.current_vertex_type |= 0x40;
   564 	    /* Modified/float not supported - behaves as per last intensity */
   565 	    if( colourfmt == TA_POLYCMD_COLOURFMT_FLOAT ) {
   566 		colourfmt = TA_POLYCMD_COLOURFMT_LASTINT;
   567 	    }
   568 	}
   569     }
   571     if( colourfmt == TA_POLYCMD_COLOURFMT_INTENSITY ) {
   572 	if( TA_POLYCMD_IS_FULLMOD(data[0].i) ||
   573 	    TA_POLYCMD_IS_SPECULAR(data[0].i) ) {
   574 	    ta_status.state = STATE_EXPECT_POLY_BLOCK2;
   575 	} else {
   576 	    ta_status.intensity1 = 
   577 		parse_float_colour( data[4].f, data[5].f, data[6].f, data[7].f );
   578 	}
   579     } else if( colourfmt == TA_POLYCMD_COLOURFMT_LASTINT ) {
   580 	colourfmt = TA_POLYCMD_COLOURFMT_INTENSITY;
   581     }
   583     ta_status.current_vertex_type |= colourfmt;
   584 }
   586 /**
   587  * Parse the modifier volume context block and setup the internal state to 
   588  * receive modifier vertexes.
   589  * @param data 32 bytes of parameter data.
   590  */
   591 static void ta_parse_modifier_context( union ta_data *data ) {
   592     ta_status.current_vertex_type = TA_VERTEX_MOD_VOLUME;
   593     ta_status.poly_vertex_size = 0;
   594     ta_status.poly_context_size = 3;
   595     ta_status.poly_context[0] = (data[1].i & 0xFC1FFFFF) |
   596 	((data[0].i & 0x0B)<<22);
   597     if( TA_POLYCMD_IS_SPECULAR(data[0].i) ) {
   598 	ta_status.poly_context[0] |= 0x01000000;
   599     }
   600     ta_status.poly_context[1] = 0;
   601     ta_status.poly_context[2] = 0;
   602     ta_status.vertex_count = 0;
   603     ta_status.max_vertex = 3;
   604     ta_status.poly_pointer = 0;
   605 }
   607 /**
   608  * Parse the sprite context block and setup the internal state to receive
   609  * vertexes.
   610  * @param data 32 bytes of parameter data.
   611  */
   612 static void ta_parse_sprite_context( union ta_data *data ) {
   613     ta_status.poly_context_size = 3;
   614     ta_status.poly_context[0] = (data[1].i & 0xFC1FFFFF) |
   615 	((data[0].i & 0x0B)<<22) | 0x00400000;
   616     if( TA_POLYCMD_IS_SPECULAR(data[0].i) ) {
   617 	ta_status.poly_context[0] |= 0x01000000;
   618     }
   619     ta_status.poly_context[1] = data[2].i;
   620     ta_status.poly_context[2] = data[3].i;
   621     if( data[0].i & TA_POLYCMD_TEXTURED ) {
   622 	ta_status.poly_vertex_size = 2;
   623 	ta_status.poly_vertex[2].detail[1] = data[4].i;
   624 	ta_status.current_vertex_type = TA_VERTEX_TEX_SPRITE;
   625     } else {
   626 	ta_status.poly_vertex_size = 1;
   627 	ta_status.poly_vertex[2].detail[0] = data[4].i;
   628 	ta_status.current_vertex_type = TA_VERTEX_SPRITE;
   629     }
   630     ta_status.vertex_count = 0;
   631     ta_status.max_vertex = 4;
   632     ta_status.poly_pointer = (ta_status.poly_vertex_size << 21);
   633 }
   635 /**
   636  * Copy the last read vertex into all vertexes up to max_vertex. Used for
   637  * Aborted polygons under some circumstances.
   638  */
   639 static void ta_fill_vertexes( ) {
   640     int i;
   641     for( i=ta_status.vertex_count; i<ta_status.max_vertex; i++ ) {
   642 	memcpy( &ta_status.poly_vertex[i], &ta_status.poly_vertex[ta_status.vertex_count-1],
   643 		sizeof( struct pvr2_ta_vertex ) );
   644     }
   645     ta_status.vertex_count = ta_status.max_vertex;
   646 }
   648 static void ta_parse_vertex( union ta_data *data ) {
   649     struct pvr2_ta_vertex *vertex = &ta_status.poly_vertex[ta_status.vertex_count];
   650     vertex->x = data[1].f;
   651     vertex->y = data[2].f;
   652     vertex->z = data[3].f;
   654     switch( ta_status.current_vertex_type ) {
   655     case TA_VERTEX_PACKED:
   656 	vertex->detail[0] = data[6].i;
   657 	break;
   658     case TA_VERTEX_FLOAT:
   659 	vertex->detail[0] = parse_float_colour( data[4].f, data[5].f, data[6].f, data[7].f );
   660 	break;
   661     case TA_VERTEX_INTENSITY:
   662 	vertex->detail[0] = parse_intensity_colour( ta_status.intensity1, data[6].f );
   663 	break;
   665     case TA_VERTEX_TEX_SPEC_PACKED:
   666 	vertex->detail[3] = data[7].i; /* ARGB */
   667 	/* Fallthrough */
   668     case TA_VERTEX_TEX_PACKED:
   669 	vertex->detail[0] = data[4].i; /* U */
   670 	vertex->detail[1] = data[5].i; /* V */
   671 	vertex->detail[2] = data[6].i; /* ARGB */
   672 	break;
   673     case TA_VERTEX_TEX_UV16_SPEC_PACKED:
   674 	vertex->detail[2] = data[7].i; /* ARGB */
   675 	/* Fallthrough */
   676     case TA_VERTEX_TEX_UV16_PACKED:
   677 	vertex->detail[0] = data[4].i; /* UV */
   678 	vertex->detail[1] = data[6].i; /* ARGB */
   679 	break;
   681     case TA_VERTEX_TEX_FLOAT:
   682     case TA_VERTEX_TEX_SPEC_FLOAT:
   683 	vertex->detail[0] = data[4].i; /* U */
   684 	vertex->detail[1] = data[5].i; /* UV */
   685 	ta_status.state = STATE_EXPECT_VERTEX_BLOCK2;
   686 	break;
   687     case TA_VERTEX_TEX_UV16_FLOAT:
   688     case TA_VERTEX_TEX_UV16_SPEC_FLOAT:
   689 	vertex->detail[0] = data[4].i; /* UV */
   690 	ta_status.state = STATE_EXPECT_VERTEX_BLOCK2;
   691 	break;
   693     case TA_VERTEX_TEX_SPEC_INTENSITY:
   694 	vertex->detail[3] = parse_intensity_colour( ta_status.intensity2, data[7].f );
   695 	/* Fallthrough */
   696     case TA_VERTEX_TEX_INTENSITY:
   697 	vertex->detail[0] = data[4].i; /* U */
   698 	vertex->detail[1] = data[5].i; /* V */
   699 	vertex->detail[2] = parse_intensity_colour( ta_status.intensity1, data[6].f );
   700 	break;
   701     case TA_VERTEX_TEX_UV16_SPEC_INTENSITY:
   702 	vertex->detail[2] = parse_intensity_colour( ta_status.intensity2, data[7].f );
   703 	/* Fallthrough */
   704     case TA_VERTEX_TEX_UV16_INTENSITY:
   705 	vertex->detail[0] = data[4].i; /* UV */
   706 	vertex->detail[1] = parse_intensity_colour( ta_status.intensity1, data[6].f );
   707 	break;
   709     case TA_VERTEX_PACKED_MOD:
   710 	vertex->detail[0] = data[4].i; /* ARGB */
   711 	vertex->detail[1] = data[5].i; /* ARGB */
   712 	break;
   713     case TA_VERTEX_INTENSITY_MOD:
   714 	vertex->detail[0] = parse_intensity_colour( ta_status.intensity1, data[4].f );
   715 	vertex->detail[1] = parse_intensity_colour( ta_status.intensity2, data[5].f );
   716 	break;
   718     case TA_VERTEX_TEX_SPEC_PACKED_MOD:
   719 	vertex->detail[3] = data[7].i; /* ARGB0 */
   720 	/* Fallthrough */
   721     case TA_VERTEX_TEX_PACKED_MOD:
   722 	vertex->detail[0] = data[4].i; /* U0 */
   723 	vertex->detail[1] = data[5].i; /* V0 */
   724 	vertex->detail[2] = data[6].i; /* ARGB0 */
   725 	ta_status.state = STATE_EXPECT_VERTEX_BLOCK2;
   726 	break;
   727     case TA_VERTEX_TEX_UV16_SPEC_PACKED_MOD:
   728 	vertex->detail[2] = data[7].i; /* ARGB0 */
   729 	/* Fallthrough */
   730     case TA_VERTEX_TEX_UV16_PACKED_MOD:
   731 	vertex->detail[0] = data[4].i; /* UV0 */
   732 	vertex->detail[1] = data[6].i; /* ARGB0 */
   733 	ta_status.state = STATE_EXPECT_VERTEX_BLOCK2;
   734 	break;
   736     case TA_VERTEX_TEX_SPEC_INTENSITY_MOD:
   737 	vertex->detail[3] = parse_intensity_colour( ta_status.intensity1, data[7].f );
   738 	/* Fallthrough */
   739     case TA_VERTEX_TEX_INTENSITY_MOD:
   740 	vertex->detail[0] = data[4].i; /* U0 */
   741 	vertex->detail[1] = data[5].i; /* V0 */
   742 	vertex->detail[2] = parse_intensity_colour( ta_status.intensity1, data[6].f );
   743 	ta_status.state = STATE_EXPECT_VERTEX_BLOCK2;
   744 	break;
   745     case TA_VERTEX_TEX_UV16_SPEC_INTENSITY_MOD:
   746 	vertex->detail[2] = parse_intensity_colour( ta_status.intensity1, data[7].f );
   747 	/* Fallthrough */
   748     case TA_VERTEX_TEX_UV16_INTENSITY_MOD:
   749 	vertex->detail[0] = data[4].i; /* UV0 */
   750 	vertex->detail[1] = parse_intensity_colour( ta_status.intensity1, data[6].f );
   751 	ta_status.state = STATE_EXPECT_VERTEX_BLOCK2;
   752 	break;
   754     case TA_VERTEX_SPRITE:
   755     case TA_VERTEX_TEX_SPRITE:
   756     case TA_VERTEX_MOD_VOLUME:
   757 	vertex++;
   758 	vertex->x = data[4].f;
   759 	vertex->y = data[5].f;
   760 	vertex->z = data[6].f;
   761 	vertex++;
   762 	vertex->x = data[7].f;
   763 	ta_status.vertex_count += 2;
   764 	ta_status.state = STATE_EXPECT_VERTEX_BLOCK2;
   765 	break;
   766     }
   767     ta_status.vertex_count++;
   768 }
   770 static void ta_parse_vertex_block2( union ta_data *data ) {
   771     struct pvr2_ta_vertex *vertex = &ta_status.poly_vertex[ta_status.vertex_count-1];
   773     switch( ta_status.current_vertex_type ) {
   774     case TA_VERTEX_TEX_SPEC_FLOAT:
   775 	vertex->detail[3] = parse_float_colour( data[4].f, data[5].f, data[6].f, data[7].f );
   776 	/* Fallthrough */
   777     case TA_VERTEX_TEX_FLOAT:
   778 	vertex->detail[2] = parse_float_colour( data[0].f, data[1].f, data[2].f, data[3].f );
   779 	break;
   780     case TA_VERTEX_TEX_UV16_SPEC_FLOAT:
   781 	vertex->detail[2] = parse_float_colour( data[4].f, data[5].f, data[6].f, data[7].f );
   782 	/* Fallthrough */
   783     case TA_VERTEX_TEX_UV16_FLOAT:
   784 	vertex->detail[1] = parse_float_colour( data[0].f, data[1].f, data[2].f, data[3].f );
   785 	break;
   786     case TA_VERTEX_TEX_PACKED_MOD:
   787 	vertex->detail[3] = data[0].i; /* U1 */
   788 	vertex->detail[4] = data[1].i; /* V1 */
   789 	vertex->detail[5] = data[2].i; /* ARGB1 */
   790 	break;
   791     case TA_VERTEX_TEX_SPEC_PACKED_MOD:
   792 	vertex->detail[4] = data[0].i; /* U1 */
   793 	vertex->detail[5] = data[1].i; /* V1 */
   794 	vertex->detail[6] = data[2].i; /* ARGB1 */
   795 	vertex->detail[7] = data[3].i; /* ARGB1 */
   796 	break;
   797     case TA_VERTEX_TEX_UV16_PACKED_MOD:
   798 	vertex->detail[2] = data[0].i; /* UV1 */
   799 	vertex->detail[3] = data[2].i; /* ARGB1 */
   800 	break;
   801     case TA_VERTEX_TEX_UV16_SPEC_PACKED_MOD:
   802 	vertex->detail[3] = data[0].i; /* UV1 */
   803 	vertex->detail[4] = data[2].i; /* ARGB1 */
   804 	vertex->detail[5] = data[3].i; /* ARGB1 */
   805 	break;
   807     case TA_VERTEX_TEX_INTENSITY_MOD:
   808 	vertex->detail[3] = data[0].i; /* U1 */
   809 	vertex->detail[4] = data[1].i; /* V1 */
   810 	vertex->detail[5] = parse_intensity_colour( ta_status.intensity2, data[2].f ); /* ARGB1 */
   811 	break;
   812     case TA_VERTEX_TEX_SPEC_INTENSITY_MOD:
   813 	vertex->detail[4] = data[0].i; /* U1 */
   814 	vertex->detail[5] = data[1].i; /* V1 */
   815 	vertex->detail[6] = parse_intensity_colour( ta_status.intensity2, data[2].f ); /* ARGB1 */
   816 	vertex->detail[7] = parse_intensity_colour( ta_status.intensity2, data[3].f ); /* ARGB1 */
   817 	break;
   818     case TA_VERTEX_TEX_UV16_INTENSITY_MOD:
   819 	vertex->detail[2] = data[0].i; /* UV1 */
   820 	vertex->detail[3] = parse_intensity_colour( ta_status.intensity2, data[2].f ); /* ARGB1 */
   821 	break;
   822     case TA_VERTEX_TEX_UV16_SPEC_INTENSITY_MOD:
   823 	vertex->detail[3] = data[0].i; /* UV1 */
   824 	vertex->detail[4] = parse_intensity_colour( ta_status.intensity2, data[2].f ); /* ARGB1 */
   825 	vertex->detail[5] = parse_intensity_colour( ta_status.intensity2, data[3].f ); /* ARGB1 */
   826 	break;
   828     case TA_VERTEX_SPRITE:
   829 	vertex->y = data[0].f;
   830 	vertex->z = data[1].f;
   831 	vertex++;
   832 	ta_status.vertex_count++;
   833 	vertex->x = data[2].f;
   834 	vertex->y = data[3].f;
   835 	vertex->z = 0;
   836 	vertex->detail[0] = 0;
   837 	ta_status.poly_vertex[0].detail[0] = 0;
   838 	ta_status.poly_vertex[1].detail[0] = 0;
   839 	break;
   840     case TA_VERTEX_TEX_SPRITE:
   841 	vertex->y = data[0].f;
   842 	vertex->z = data[1].f;
   843 	vertex++;
   844 	ta_status.vertex_count++;
   845 	vertex->x = data[2].f;
   846 	vertex->y = data[3].f;
   847 	vertex->z = 0;
   848 	vertex->detail[0] = 0;
   849 	vertex->detail[1] = 0;
   850 	ta_status.poly_vertex[0].detail[0] = data[5].i;
   851 	ta_status.poly_vertex[0].detail[1] = 0;
   852 	ta_status.poly_vertex[1].detail[0] = data[6].i;
   853 	ta_status.poly_vertex[1].detail[1] = 0;
   854 	ta_status.poly_vertex[2].detail[0] = data[7].i;
   855 	break;
   856     case TA_VERTEX_MOD_VOLUME:
   857 	vertex->y = data[0].f;
   858 	vertex->z = data[1].f;
   859 	break;
   860     }
   861     ta_status.state = STATE_IN_LIST;
   862 }
   864 /**
   865  * Process 1 32-byte block of ta data
   866  */
   867 void pvr2_ta_process_block( char *input ) {
   868     union ta_data *data = (union ta_data *)input;
   870     switch( ta_status.state ) {
   871     case STATE_ERROR:
   872 	/* Error raised - stop processing until reset */
   873 	return;
   875     case STATE_EXPECT_POLY_BLOCK2:
   876 	/* This is always a pair of floating-point colours */
   877 	ta_status.intensity1 = 
   878 	    parse_float_colour( data[0].f, data[1].f, data[2].f, data[3].f );
   879 	ta_status.intensity2 =
   880 	    parse_float_colour( data[4].f, data[5].f, data[6].f, data[7].f );
   881 	ta_status.state = STATE_IN_LIST;
   882 	break;
   884     case STATE_EXPECT_VERTEX_BLOCK2:
   885 	ta_parse_vertex_block2( data );
   886 	if( ta_status.vertex_count == ta_status.max_vertex ) {
   887 	    ta_split_polygon();
   888 	}
   889 	break;
   891     case STATE_EXPECT_END_VERTEX_BLOCK2:
   892 	ta_parse_vertex_block2( data );
   893 	ta_commit_polygon();
   894 	ta_status.vertex_count = 0;
   895 	ta_status.poly_parity = 0;
   897     case STATE_IN_LIST:
   898     case STATE_IDLE:
   899 	switch( TA_CMD( data->i ) ) {
   900 	case TA_CMD_END_LIST:
   901 	    ta_end_list();
   902 	    break;
   903 	case TA_CMD_CLIP: /* TODO */
   904 	    break;
   905 	case TA_CMD_POLYGON_CONTEXT:
   906 	    if( ta_status.state == STATE_IDLE ) {
   907 		ta_init_list( TA_POLYCMD_LISTTYPE( data->i ) );
   908 	    }
   910 	    if( ta_status.vertex_count != 0 ) {
   911 		ta_fill_vertexes();
   912 		ta_commit_polygon();
   913 	    }
   915 	    if( TA_IS_MODIFIER_LIST( ta_status.current_list_type ) ) {
   916 		ta_parse_modifier_context(data);
   917 	    } else {
   918 		ta_parse_polygon_context(data);
   919 	    }
   920 	    break;
   921 	case TA_CMD_SPRITE_CONTEXT:
   922 	    if( ta_status.state == STATE_IDLE ) {
   923 		ta_init_list( TA_POLYCMD_LISTTYPE( data->i ) );
   924 	    }
   926 	    if( ta_status.vertex_count != 0 ) {
   927 		ta_fill_vertexes();
   928 		ta_commit_polygon();
   929 	    }
   931 	    ta_parse_sprite_context(data);
   932 	    break;
   933 	case TA_CMD_VERTEX:
   934 	    ta_parse_vertex(data);
   936 	    if( ta_status.state == STATE_EXPECT_VERTEX_BLOCK2 ) {
   937 		if( TA_IS_END_VERTEX(data[0].i) ) {
   938 		    ta_status.state = STATE_EXPECT_END_VERTEX_BLOCK2;
   939 		}
   940 	    } else if( TA_IS_END_VERTEX(data->i) ) {
   941 		ta_commit_polygon();
   942 		ta_status.vertex_count = 0;
   943 		ta_status.poly_parity = 0;
   944 	    } else if( ta_status.vertex_count == ta_status.max_vertex ) {
   945 		ta_split_polygon();
   946 	    }
   947 	    break;
   948 	}
   949 	break;
   950     }
   952 }
   956 /**
   957  * Write a block of data to the tile accelerator, adding the data to the 
   958  * current scene. We don't make any particular attempt to interpret the data
   959  * at this stage, deferring that until render time.
   960  *
   961  * Currently copies the data verbatim to the vertex buffer, processing only
   962  * far enough to generate the correct end-of-list events. Tile buffer is
   963  * entirely ignored.
   964  */
   965 void pvr2_ta_write( char *buf, uint32_t length )
   966 {
   967     if( ta_status.debug_output ) {
   968 	fwrite_dump32( (uint32_t *)buf, length, stderr );
   969     }
   971     for( ; length >=32; length -= 32 ) {
   972 	pvr2_ta_process_block( buf );
   973 	buf += 32;
   974     }
   975 }
.