Search
lxdream.org :: lxdream/src/pvr2/rendsort.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/pvr2/rendsort.c
changeset 669:ab344e42bca9
prev653:3202ff01d48e
next736:a02d1475ccfd
author nkeynes
date Mon May 12 10:00:13 2008 +0000 (15 years ago)
permissions -rw-r--r--
last change Cleanup most of the -Wall warnings (getting a bit sloppy...)
Convert FP code to use fixed banks rather than indirect pointer
(3-4% faster this way now)
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 <string.h>
    20 #include <assert.h>
    21 #include "pvr2/pvr2.h"
    22 #include "pvr2/scene.h"
    23 #include "asic.h"
    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 sort_triangle {
    29     struct polygon_struct *poly;
    30     int triangle_num; // triangle number in the poly, from 0
    31     float maxz;
    32 };
    34 #define SENTINEL 0xDEADBEEF
    36 /**
    37  * Count the number of triangles in the list starting at the given 
    38  * pvr memory address.
    39  */
    40 int sort_count_triangles( pvraddr_t tile_entry ) {
    41     uint32_t *tile_list = (uint32_t *)(video_base+tile_entry);
    42     int count = 0;
    43     while(1) {
    44 	uint32_t entry = *tile_list++;
    45 	if( entry >> 28 == 0x0F ) {
    46 	    break;
    47 	} else if( entry >> 28 == 0x0E ) {
    48 	    tile_list = (uint32_t *)(video_base+(entry&0x007FFFFF));
    49 	} else if( entry >> 29 == 0x04 ) { /* Triangle array */
    50 	    count += ((entry >> 25) & 0x0F)+1;
    51 	} else if( entry >> 29 == 0x05 ) { /* Quad array */
    52 	    count += ((((entry >> 25) & 0x0F)+1)<<1);
    53 	} else { /* Polygon */
    54 	    int i;
    55 	    for( i=0; i<6; i++ ) {
    56 		if( entry & (0x40000000>>i) ) {
    57 		    count++;
    58 		}
    59 	    }
    60 	}
    61     }
    62     return count;
    63 }
    65 /**
    66  * Extract a triangle list from the tile (basically indexes into the polygon list, plus
    67  * computing maxz while we go through it
    68  */
    69 int sort_extract_triangles( pvraddr_t tile_entry, struct sort_triangle *triangles )
    70 {
    71     uint32_t *tile_list = (uint32_t *)(video_base+tile_entry);
    72     int count = 0;
    73     while(1) {
    74 	uint32_t entry = *tile_list++;
    75 	if( entry >> 28 == 0x0F ) {
    76 	    break;
    77 	} else if( entry >> 28 == 0x0E ) {
    78 	    tile_list = (uint32_t *)(video_base+(entry&0x007FFFFF));
    79 	} else {
    80 	    uint32_t poly_addr = entry & 0x000FFFFF;
    81 	    int is_modified = entry & 0x01000000;
    82 	    int vertex_length = (entry >> 21) & 0x07;
    83 	    int context_length = 3;
    84 	    if( is_modified && pvr2_scene.full_shadow ) {
    85 		context_length = 5;
    86 		vertex_length *= 2 ;
    87 	    }
    88 	    vertex_length += 3;
    90 	    if( (entry & 0xE0000000) == 0x80000000 ) {
    91 		/* Triangle(s) */
    92 		int strip_count = ((entry >> 25) & 0x0F)+1;
    93 		int polygon_length = 3 * vertex_length + context_length;
    94 		int i;
    95 		for( i=0; i<strip_count; i++ ) {
    96 		    struct polygon_struct *poly = pvr2_scene.buf_to_poly_map[poly_addr];
    97 		    triangles[count].poly = poly;
    98 		    triangles[count].triangle_num = 0;
    99 		    triangles[count].maxz = MAX3( pvr2_scene.vertex_array[poly->vertex_index].z,
   100 						  pvr2_scene.vertex_array[poly->vertex_index+1].z,
   101 						  pvr2_scene.vertex_array[poly->vertex_index+2].z );
   102 		    poly_addr += polygon_length;
   103 		    count++;
   104 		}
   105 	    } else if( (entry & 0xE0000000) == 0xA0000000 ) {
   106 		/* Quad(s) */
   107 		int strip_count = ((entry >> 25) & 0x0F)+1;
   108 		int polygon_length = 4 * vertex_length + context_length;
   109 		int i;
   110 		for( i=0; i<strip_count; i++ ) {
   111 		    struct polygon_struct *poly = pvr2_scene.buf_to_poly_map[poly_addr];
   112 		    triangles[count].poly = poly;
   113 		    triangles[count].triangle_num = 0;
   114 		    triangles[count].maxz = MAX3( pvr2_scene.vertex_array[poly->vertex_index].z,
   115 						  pvr2_scene.vertex_array[poly->vertex_index+1].z,
   116 						  pvr2_scene.vertex_array[poly->vertex_index+2].z );
   117 		    count++;
   118 		    triangles[count].poly = poly;
   119 		    triangles[count].triangle_num = 1;
   120 		    triangles[count].maxz = MAX3( pvr2_scene.vertex_array[poly->vertex_index+1].z,
   121 						  pvr2_scene.vertex_array[poly->vertex_index+2].z,
   122 						  pvr2_scene.vertex_array[poly->vertex_index+3].z );
   123 		    count++;
   124 		    poly_addr += polygon_length;
   125 		}
   126 	    } else {
   127 		/* Polygon */
   128 		int i;
   129 		struct polygon_struct *poly = pvr2_scene.buf_to_poly_map[poly_addr];
   130 		for( i=0; i<6; i++ ) {
   131 		    if( entry & (0x40000000>>i) ) {
   132 			triangles[count].poly = poly;
   133 			triangles[count].triangle_num = i;
   134 			triangles[count].maxz = MAX3( pvr2_scene.vertex_array[poly->vertex_index+i].z,
   135 						      pvr2_scene.vertex_array[poly->vertex_index+i+1].z,
   136 						      pvr2_scene.vertex_array[poly->vertex_index+i+2].z );
   137 			count++;
   138 		    }
   139 		}
   140 	    }
   141 	}
   142     }
   143     return count;
   144 }
   146 void sort_render_triangles( struct sort_triangle *triangles, int num_triangles,
   147 			    int render_mode )
   148 {
   149     int i;
   150     for( i=0; i<num_triangles; i++ ) {
   151 	struct polygon_struct *poly = triangles[i].poly;
   152 	if( poly->tex_id != -1 ) {
   153 	    glBindTexture(GL_TEXTURE_2D, poly->tex_id);
   154 	}
   155 	render_set_context( poly->context, RENDER_NORMAL );
   156 	glDepthMask(GL_FALSE);
   157 	glDepthFunc(GL_GEQUAL);
   158 	/* Fix cull direction */
   159 	if( triangles[i].triangle_num & 1 ) {
   160 	    glCullFace(GL_FRONT);
   161 	} else {
   162 	    glCullFace(GL_BACK);
   163 	}
   165 	glDrawArrays(GL_TRIANGLE_STRIP, poly->vertex_index + triangles[i].triangle_num, 3 );
   166     }
   167 }
   169 int compare_triangles( const void *a, const void *b ) 
   170 {
   171     const struct sort_triangle *tri1 = a;
   172     const struct sort_triangle *tri2 = b;
   173     return tri2->maxz - tri1->maxz;
   174 }
   176 void sort_triangles( struct sort_triangle *triangles, int num_triangles )
   177 {
   178     qsort( triangles, num_triangles, sizeof(struct sort_triangle), compare_triangles );
   179 } 
   181 void render_autosort_tile( pvraddr_t tile_entry, int render_mode ) 
   182 {
   183     int num_triangles = sort_count_triangles(tile_entry);
   184     if( num_triangles == 0 ) {
   185 	return; /* nothing to do */
   186     } else if( num_triangles == 1 ) { /* Triangle can hardly overlap with itself */
   187 	gl_render_tilelist(tile_entry);
   188     } else { /* Ooh boy here we go... */
   189 	struct sort_triangle triangles[num_triangles+1];
   190 	// Reserve space for num_triangles / 2 * 4 vertexes (maximum possible number of
   191 	// quad vertices)
   192 	triangles[num_triangles].poly = (void *)SENTINEL;
   193 	int extracted_triangles = sort_extract_triangles(tile_entry, triangles);
   194 	assert( extracted_triangles == num_triangles );
   195 	sort_triangles( triangles, num_triangles );
   196 	sort_render_triangles(triangles, num_triangles, render_mode);
   197 	glCullFace(GL_BACK);
   198 	assert( triangles[num_triangles].poly == (void *)SENTINEL );
   199     }
   200 }
.