Search
lxdream.org :: lxdream/src/pvr2/rendsort.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/pvr2/rendsort.c
changeset 561:533f6b478071
prev429:e581b90c3fb3
next635:76c63aac3590
next653:3202ff01d48e
author nkeynes
date Tue Jan 01 05:08:38 2008 +0000 (12 years ago)
branchlxdream-mmu
permissions -rw-r--r--
last change Enable Id keyword on all source files
view annotate diff log raw
     1 /**
     2  * $Id$
     3  *
     4  * PVR2 renderer routines for depth sorted polygons
     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 <sys/time.h>
    19 #include "pvr2/pvr2.h"
    20 #include "asic.h"
    22 extern char *video_base;
    23 extern gboolean pvr2_force_fragment_alpha;
    25 #define MIN3( a,b,c ) ((a) < (b) ? ( (a) < (c) ? (a) : (c) ) : ((b) < (c) ? (b) : (c)) )
    26 #define MAX3( a,b,c ) ((a) > (b) ? ( (a) > (c) ? (a) : (c) ) : ((b) > (c) ? (b) : (c)) )
    28 struct render_triangle {
    29     uint32_t *polygon;
    30     int vertex_length; /* Number of 32-bit words in vertex, or 0 for an unpacked vertex */
    31     float minx,miny,minz;
    32     float maxx,maxy,maxz;
    33     float *vertexes[3];
    34 };
    36 #define SENTINEL 0xDEADBEEF
    38 /**
    39  * Count the number of triangles in the list starting at the given 
    40  * pvr memory address.
    41  */
    42 int render_count_triangles( pvraddr_t tile_entry ) {
    43     uint32_t *tile_list = (uint32_t *)(video_base+tile_entry);
    44     int count = 0;
    45     while(1) {
    46 	uint32_t entry = *tile_list++;
    47 	if( entry >> 28 == 0x0F ) {
    48 	    break;
    49 	} else if( entry >> 28 == 0x0E ) {
    50 	    tile_list = (uint32_t *)(video_base+(entry&0x007FFFFF));
    51 	} else if( entry >> 29 == 0x04 ) { /* Triangle array */
    52 	    count += ((entry >> 25) & 0x0F)+1;
    53 	} else if( entry >> 29 == 0x05 ) { /* Quad array */
    54 	    count += ((((entry >> 25) & 0x0F)+1)<<1);
    55 	} else { /* Polygon */
    56 	    int i;
    57 	    for( i=0; i<6; i++ ) {
    58 		if( entry & (0x40000000>>i) ) {
    59 		    count++;
    60 		}
    61 	    }
    62 	}
    63     }
    64     return count;
    65 }
    67 static void compute_triangle_boxes( struct render_triangle *triangle, int num_triangles )
    68 {
    69     int i;
    70     for( i=0; i<num_triangles; i++ ) {
    71 	triangle[i].minx = MIN3(triangle[i].vertexes[0][0],triangle[i].vertexes[1][0],triangle[i].vertexes[2][0]);
    72 	triangle[i].maxx = MAX3(triangle[i].vertexes[0][0],triangle[i].vertexes[1][0],triangle[i].vertexes[2][0]);
    73 	triangle[i].miny = MIN3(triangle[i].vertexes[0][1],triangle[i].vertexes[1][1],triangle[i].vertexes[2][1]);
    74 	triangle[i].maxy = MAX3(triangle[i].vertexes[0][1],triangle[i].vertexes[1][1],triangle[i].vertexes[2][1]);
    75 	float az = 1/triangle[i].vertexes[0][2];
    76 	float bz = 1/triangle[i].vertexes[1][2];
    77 	float cz = 1/triangle[i].vertexes[2][2];
    78 	triangle[i].minz = MIN3(az,bz,cz);
    79 	triangle[i].maxz = MAX3(az,bz,cz);
    80     }
    81 }
    83 void render_extract_triangles( pvraddr_t tile_entry, gboolean cheap_modifier_mode, 
    84 			       struct render_triangle *triangles, int num_triangles,
    85 			       struct vertex_unpacked *vertex_space, int render_mode )
    86 {
    87     uint32_t poly_bank = MMIO_READ(PVR2,RENDER_POLYBASE);
    88     uint32_t *tile_list = (uint32_t *)(video_base+tile_entry);
    89     int count = 0;
    90     while(1) {
    91 	uint32_t entry = *tile_list++;
    92 	if( entry >> 28 == 0x0F ) {
    93 	    break;
    94 	} else if( entry >> 28 == 0x0E ) {
    95 	    tile_list = (uint32_t *)(video_base+(entry&0x007FFFFF));
    96 	} else {
    97 	    uint32_t *polygon = (uint32_t *)(video_base + poly_bank + ((entry & 0x000FFFFF) << 2));
    98 	    int is_modified = entry & 0x01000000;
    99 	    int vertex_length = (entry >> 21) & 0x07;
   100 	    int context_length = 3;
   101 	    if( is_modified && !cheap_modifier_mode ) {
   102 		context_length = 5;
   103 		vertex_length *= 2 ;
   104 	    }
   105 	    vertex_length += 3;
   107 	    if( (entry & 0xE0000000) == 0x80000000 ) {
   108 		/* Triangle(s) */
   109 		int strip_count = ((entry >> 25) & 0x0F)+1;
   110 		int polygon_length = 3 * vertex_length + context_length;
   111 		int i;
   112 		for( i=0; i<strip_count; i++ ) {
   113 		    float *vertex = (float *)(polygon+context_length);
   114 		    triangles[count].polygon = polygon;
   115 		    triangles[count].vertex_length = vertex_length;
   116 		    triangles[count].vertexes[0] = vertex;
   117 		    vertex+=vertex_length;
   118 		    triangles[count].vertexes[1] = vertex;
   119 		    vertex+=vertex_length;
   120 		    triangles[count].vertexes[2] = vertex;
   121 		    polygon += polygon_length;
   122 		    count++;
   123 		}
   124 	    } else if( (entry & 0xE0000000) == 0xA0000000 ) {
   125 		/* Quad(s) */
   126 		int strip_count = ((entry >> 25) & 0x0F)+1;
   127 		int polygon_length = 4 * vertex_length + context_length;
   129 		int i;
   130 		for( i=0; i<strip_count; i++ ) {
   131 		    render_unpack_quad( vertex_space, *polygon, (polygon+context_length),
   132 					vertex_length, render_mode );
   133 		    triangles[count].polygon = polygon;
   134 		    triangles[count].vertex_length = 0;
   135 		    triangles[count].vertexes[0] = (float *)vertex_space;
   136 		    triangles[count].vertexes[1] = (float *)(vertex_space + 1);
   137 		    triangles[count].vertexes[2] = (float *)(vertex_space + 3);
   138 		    count++;
   139 		    /* Preserve face direction */
   140 		    triangles[count].polygon = polygon;
   141 		    triangles[count].vertex_length = 0;
   142 		    triangles[count].vertexes[0] = (float *)(vertex_space + 1);
   143 		    triangles[count].vertexes[1] = (float *)(vertex_space + 2);
   144 		    triangles[count].vertexes[2] = (float *)(vertex_space + 3);
   145 		    count++;
   146 		    vertex_space += 4;
   147 		    polygon += polygon_length;
   148 		}
   149 	    } else {
   150 		/* Polygon */
   151 		int i;
   152 		float *vertex = (float *)polygon+context_length;
   153 		for( i=0; i<6; i++ ) {
   154 		    if( entry & (0x40000000>>i) ) {
   155 			triangles[count].polygon = polygon;
   156 			triangles[count].vertex_length = vertex_length;
   157 			if( i&1 ) {
   158 			    triangles[count].vertexes[0] = vertex + vertex_length;
   159 			    triangles[count].vertexes[1] = vertex;
   160 			    triangles[count].vertexes[2] = vertex + (vertex_length<<1);
   161 			} else {
   162 			    triangles[count].vertexes[0] = vertex;
   163 			    triangles[count].vertexes[1] = vertex + vertex_length;
   164 			    triangles[count].vertexes[2] = vertex + (vertex_length<<1);
   165 			}
   166 			count++;
   167 		    }
   168 		    vertex += vertex_length;
   169 		}
   170 	    }
   171 	}
   172     }
   173     if( count != num_triangles ) {
   174 	ERROR( "Extracted triangles do not match expected count!" );
   175     }
   176 }
   178 void render_triangles( struct render_triangle *triangles, int num_triangles,
   179 		       int render_mode )
   180 {
   181     int i;
   182     for( i=0; i<num_triangles; i++ ) {
   183 	render_set_context( triangles[i].polygon, render_mode );
   184 	glEnable(GL_DEPTH_TEST);
   185 	glDepthFunc(GL_GEQUAL);
   186 	if( triangles[i].vertex_length == 0 ) {
   187 	    render_unpacked_vertex_array( *triangles[i].polygon, (struct vertex_unpacked **)triangles[i].vertexes, 3 );
   188 	} else {
   189 	    render_vertex_array( *triangles[i].polygon, (uint32_t **)triangles[i].vertexes, 3,
   190 				 triangles[i].vertex_length, render_mode );
   191 	}
   192     }
   195 }
   197 int compare_triangles( const void *a, const void *b ) 
   198 {
   199     const struct render_triangle *tri1 = a;
   200     const struct render_triangle *tri2 = b;
   201     if( tri1->minz < tri2->minz ) {  
   202 	return 1; // No these _aren't_ back to front...
   203     } else if( tri1->minz > tri2->minz ) {
   204 	return -1;
   205     } else {
   206 	return 0;
   207     }
   208 }
   210 void sort_triangles( struct render_triangle *triangles, int num_triangles )
   211 {
   212     qsort( triangles, num_triangles, sizeof(struct render_triangle), compare_triangles );
   213 } 
   215 void render_autosort_tile( pvraddr_t tile_entry, int render_mode, gboolean cheap_modifier_mode ) 
   216 {
   217     int num_triangles = render_count_triangles(tile_entry);
   218     if( num_triangles == 0 ) {
   219 	return; /* nothing to do */
   220     } else if( num_triangles == 1 ) { /* Triangle can hardly overlap with itself */
   221 	render_tile( tile_entry, render_mode, cheap_modifier_mode );
   222     } else { /* Ooh boy here we go... */
   223 	struct render_triangle triangles[num_triangles+1];
   224 	struct vertex_unpacked vertex_space[num_triangles << 1]; 
   225 	// Reserve space for num_triangles / 2 * 4 vertexes (maximum possible number of
   226 	// quad vertices)
   227 	triangles[num_triangles].polygon = (void *)SENTINEL;
   228 	render_extract_triangles(tile_entry, cheap_modifier_mode, triangles, num_triangles, vertex_space, render_mode);
   229 	compute_triangle_boxes(triangles, num_triangles);
   230 	sort_triangles( triangles, num_triangles );
   231 	render_triangles(triangles, num_triangles, render_mode);
   232 	if( triangles[num_triangles].polygon != (void *)SENTINEL ) {
   233 	    fprintf( stderr, "Triangle overflow in render_autosort_tile!" );
   234 	}
   235     }
   236 }
.