Search
lxdream.org :: lxdream/src/pvr2/rendsort.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/pvr2/rendsort.c
changeset 222:541d9d899aba
next276:1e594c2804f8
author nkeynes
date Fri Dec 15 10:17:30 2006 +0000 (17 years ago)
permissions -rw-r--r--
last change Add some explanatory comments as to how this stuff is supposed to work
view annotate diff log raw
     1 /**
     2  * $Id: rendsort.c,v 1.1 2006-09-12 11:54:19 nkeynes Exp $
     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;
    24 #define MIN3( a,b,c ) ((a) < (b) ? ( (a) < (c) ? (a) : (c) ) : ((b) < (c) ? (b) : (c)) )
    25 #define MAX3( a,b,c ) ((a) > (b) ? ( (a) > (c) ? (a) : (c) ) : ((b) > (c) ? (b) : (c)) )
    27 struct pvr_vertex {
    28     float x,y,z;
    29     uint32_t detail[1];
    30 };
    32 struct render_triangle {
    33     uint32_t *polygon;
    34     int vertex_length;
    35     float minx,miny,minz;
    36     float maxx,maxy,maxz;
    37     float *vertexes[3];
    38 };
    40 /**
    41  * Count the number of triangles in the list starting at the given 
    42  * pvr memory address.
    43  */
    44 int render_count_triangles( pvraddr_t tile_entry ) {
    45     uint32_t *tile_list = (uint32_t *)(video_base+tile_entry);
    46     int count = 0;
    47     while(1) {
    48 	uint32_t entry = *tile_list++;
    49 	if( entry >> 28 == 0x0F ) {
    50 	    break;
    51 	} else if( entry >> 28 == 0x0E ) {
    52 	    tile_list = (uint32_t *)(video_base+(entry&0x007FFFFF));
    53 	} else if( entry >> 29 == 0x04 ) { /* Triangle array */
    54 	    count += ((entry >> 25) & 0x0F)+1;
    55 	} else if( entry >> 29 == 0x05 ) { /* Quad array */
    56 	    count += ((((entry >> 25) & 0x0F)+1)<<1);
    57 	} else { /* Polygon */
    58 	    int i;
    59 	    for( i=0; i<6; i++ ) {
    60 		if( entry & (0x40000000>>i) ) {
    61 		    count++;
    62 		}
    63 	    }
    64 	}
    65     }
    66     return count;
    67 }
    69 static void compute_triangle_boxes( struct render_triangle *triangle, int num_triangles )
    70 {
    71     int i;
    72     for( i=0; i<num_triangles; i++ ) {
    73 	triangle[i].minx = MIN3(triangle[i].vertexes[0][0],triangle[i].vertexes[1][0],triangle[i].vertexes[2][0]);
    74 	triangle[i].maxx = MAX3(triangle[i].vertexes[0][0],triangle[i].vertexes[1][0],triangle[i].vertexes[2][0]);
    75 	triangle[i].miny = MIN3(triangle[i].vertexes[0][1],triangle[i].vertexes[1][1],triangle[i].vertexes[2][1]);
    76 	triangle[i].maxy = MAX3(triangle[i].vertexes[0][1],triangle[i].vertexes[1][1],triangle[i].vertexes[2][1]);
    77 	triangle[i].minz = MIN3(triangle[i].vertexes[0][2],triangle[i].vertexes[1][2],triangle[i].vertexes[2][2]);
    78 	triangle[i].maxz = MAX3(triangle[i].vertexes[0][2],triangle[i].vertexes[1][2],triangle[i].vertexes[2][2]);
    79     }
    80 }
    82 void render_extract_triangles( pvraddr_t tile_entry, gboolean cheap_modifier_mode, 
    83 			       struct render_triangle *triangles )
    84 {
    85     uint32_t poly_bank = MMIO_READ(PVR2,RENDER_POLYBASE);
    86     uint32_t *tile_list = (uint32_t *)(video_base+tile_entry);
    87     int count = 0;
    88     while(1) {
    89 	uint32_t entry = *tile_list++;
    90 	if( entry >> 28 == 0x0F ) {
    91 	    break;
    92 	} else if( entry >> 28 == 0x0E ) {
    93 	    tile_list = (uint32_t *)(video_base+(entry&0x007FFFFF));
    94 	} else {
    95 	    uint32_t *polygon = (uint32_t *)(video_base + poly_bank + ((entry & 0x000FFFFF) << 2));
    96 	    int is_modified = entry & 0x01000000;
    97 	    int vertex_length = (entry >> 21) & 0x07;
    98 	    int context_length = 3;
    99 	    if( is_modified && !cheap_modifier_mode ) {
   100 		context_length = 5;
   101 		vertex_length *= 2 ;
   102 	    }
   103 	    vertex_length += 3;
   105 	    if( (entry & 0xE0000000) == 0x80000000 ) {
   106 		/* Triangle(s) */
   107 		int strip_count = ((entry >> 25) & 0x0F)+1;
   108 		int polygon_length = 3 * vertex_length + context_length;
   109 		int i;
   110 		for( i=0; i<strip_count; i++ ) {
   111 		    float *vertex = (float *)(polygon+context_length);
   112 		    triangles[count].polygon = polygon;
   113 		    triangles[count].vertex_length = vertex_length;
   114 		    triangles[count].vertexes[0] = vertex;
   115 		    vertex+=vertex_length;
   116 		    triangles[count].vertexes[1] = vertex;
   117 		    vertex+=vertex_length;
   118 		    triangles[count].vertexes[2] = vertex;
   119 		    polygon += polygon_length;
   120 		    count++;
   121 		}
   122 	    } else if( (entry & 0xE0000000) == 0xA0000000 ) {
   123 		/* Sprite(s) */
   124 		int strip_count = (entry >> 25) & 0x0F;
   125 		int polygon_length = 4 * vertex_length + context_length;
   126 		int i;
   127 		for( i=0; i<strip_count; i++ ) {
   128 		    float *vertex = (float *)(polygon+context_length);
   129 		    triangles[count].polygon = polygon;
   130 		    triangles[count].vertex_length = vertex_length;
   131 		    triangles[count].vertexes[0] = vertex;
   132 		    vertex+=vertex_length;
   133 		    triangles[count].vertexes[1] = vertex;
   134 		    vertex+=vertex_length;
   135 		    triangles[count].vertexes[2] = vertex;
   136 		    count++;
   137 		    /* Preserve face direction */
   138 		    triangles[count].polygon = polygon;
   139 		    triangles[count].vertex_length = vertex_length;
   140 		    triangles[count].vertexes[0] = vertex;
   141 		    triangles[count].vertexes[1] = vertex - vertex_length;
   142 		    triangles[count].vertexes[2] = vertex + vertex_length;
   143 		    count++;
   144 		    polygon += polygon_length;
   145 		}
   146 	    } else {
   147 		/* Polygon */
   148 		int i, first=-1, last = -1;
   149 		float *vertex = (float *)polygon+context_length;
   150 		for( i=0; i<6; i++ ) {
   151 		    if( entry & (0x40000000>>i) ) {
   152 			triangles[count].polygon = polygon;
   153 			triangles[count].vertex_length = vertex_length;
   154 			if( i&1 ) {
   155 			    triangles[count].vertexes[0] = vertex + vertex_length;
   156 			    triangles[count].vertexes[1] = vertex;
   157 			    triangles[count].vertexes[2] = vertex + (vertex_length<<1);
   158 			} else {
   159 			    triangles[count].vertexes[0] = vertex;
   160 			    triangles[count].vertexes[1] = vertex + vertex_length;
   161 			    triangles[count].vertexes[2] = vertex + (vertex_length<<1);
   162 			}
   163 			count++;
   164 		    }
   165 		    vertex += vertex_length;
   166 		}
   167 	    }
   168 	}
   169     }
   170 }
   172 void render_triangles( struct render_triangle *triangles, int num_triangles,
   173 		       int render_mode )
   174 {
   175     int i,j, m = 0;
   176     for( i=0; i<num_triangles; i++ ) {
   177 	render_set_context( triangles[i].polygon, render_mode );
   178 	if( render_mode == RENDER_FULLMOD ) {
   179 	    m = (triangles[i].vertex_length - 3)/2;
   180 	}
   182 	glBegin( GL_TRIANGLE_STRIP );
   184 	for( j=0; j<3; j++ ) {
   185 	    uint32_t *vertexes = (uint32_t *)triangles[i].vertexes[j];
   186 	    float *vertexf = (float *)vertexes;
   187 	    uint32_t argb;
   188 	    if( POLY1_TEXTURED(*triangles[i].polygon) ) {
   189 		if( POLY1_UV16(*triangles[i].polygon) ) {
   190 		    glTexCoord2f( halftofloat(vertexes[m+3]>>16),
   191 				  halftofloat(vertexes[m+3]) );
   192 		    argb = vertexes[m+4];
   193 		} else {
   194 		    glTexCoord2f( vertexf[m+3], vertexf[m+4] );
   195 		    argb = vertexes[m+5];
   196 		}
   197 	    } else {
   198 		argb = vertexes[m+3];
   199 	    }
   201 	    glColor4ub( (GLubyte)(argb >> 16), (GLubyte)(argb >> 8), 
   202 			(GLubyte)argb, (GLubyte)(argb >> 24) );
   203 	    glVertex3f( vertexf[0], vertexf[1], vertexf[2] );
   204 	}
   205 	glEnd();
   206     }
   209 }
   211 int compare_triangles( void *a, void *b ) 
   212 {
   213     struct render_triangle *tri1 = a;
   214     struct render_triangle *tri2 = b;
   215     if( tri1->minz < tri2->minz ) {
   216 	return -1;
   217     } else if( tri1->minz > tri2->minz ) {
   218 	return 1;
   219     } else {
   220 	return 0;
   221     }
   222 }
   224 void sort_triangles( struct render_triangle *triangles, int num_triangles )
   225 {
   226     qsort( triangles, num_triangles, sizeof(struct render_triangle), compare_triangles );
   227 } 
   229 void render_autosort_tile( pvraddr_t tile_entry, int render_mode, gboolean cheap_modifier_mode ) 
   230 {
   231     int num_triangles = render_count_triangles(tile_entry);
   232     if( num_triangles == 0 ) {
   233 	return; /* nothing to do */
   234     } else if( num_triangles == 1 ) { /* Triangle can hardly overlap with itself */
   235 	render_tile( tile_entry, render_mode, cheap_modifier_mode );
   236     } else { /* Ooh boy here we go... */
   237 	struct render_triangle triangles[num_triangles];
   238 	render_extract_triangles(tile_entry, cheap_modifier_mode, triangles);
   239 	compute_triangle_boxes(triangles, num_triangles);
   240 	sort_triangles( triangles, num_triangles );
   241 	render_triangles(triangles, num_triangles, render_mode);
   242     }
   243 }
.