Search
lxdream.org :: lxdream/src/pvr2/rendsort.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/pvr2/rendsort.c
changeset 645:a7392098299c
prev635:76c63aac3590
next648:ef9aa5cba86f
author nkeynes
date Thu Mar 06 08:22:00 2008 +0000 (12 years ago)
branchlxdream-render
permissions -rw-r--r--
last change More refactor work in progress - nearly done 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 extern char *video_base;
    27 #define MIN3( a,b,c ) ((a) < (b) ? ( (a) < (c) ? (a) : (c) ) : ((b) < (c) ? (b) : (c)) )
    28 #define MAX3( a,b,c ) ((a) > (b) ? ( (a) > (c) ? (a) : (c) ) : ((b) > (c) ? (b) : (c)) )
    30 struct sort_triangle {
    31     struct polygon_struct *poly;
    32     int triangle_num; // triangle number in the poly, from 0
    33     float minz;
    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 sort_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 /**
    68  * Extract a triangle list from the tile (basically indexes into the polygon list, plus
    69  * computing minz while we go through it
    70  */
    71 int sort_extract_triangles( pvraddr_t tile_entry, struct sort_triangle *triangles )
    72 {
    73     uint32_t *tile_list = (uint32_t *)(video_base+tile_entry);
    74     int count = 0;
    75     while(1) {
    76 	uint32_t entry = *tile_list++;
    77 	if( entry >> 28 == 0x0F ) {
    78 	    break;
    79 	} else if( entry >> 28 == 0x0E ) {
    80 	    tile_list = (uint32_t *)(video_base+(entry&0x007FFFFF));
    81 	} else {
    82 	    uint32_t poly_addr = entry & 0x000FFFFF;
    83 	    int is_modified = entry & 0x01000000;
    84 	    int vertex_length = (entry >> 21) & 0x07;
    85 	    int context_length = 3;
    86 	    if( is_modified && pvr2_scene.full_shadow ) {
    87 		context_length = 5;
    88 		vertex_length *= 2 ;
    89 	    }
    90 	    vertex_length += 3;
    92 	    if( (entry & 0xE0000000) == 0x80000000 ) {
    93 		/* Triangle(s) */
    94 		int strip_count = ((entry >> 25) & 0x0F)+1;
    95 		int polygon_length = 3 * vertex_length + context_length;
    96 		int i;
    97 		for( i=0; i<strip_count; i++ ) {
    98 		    struct polygon_struct *poly = pvr2_scene.buf_to_poly_map[poly_addr];
    99 		    triangles[count].poly = poly;
   100 		    triangles[count].triangle_num = 0;
   101 		    triangles[count].minz = MIN3( pvr2_scene.vertex_array[poly->vertex_index].z,
   102 						  pvr2_scene.vertex_array[poly->vertex_index+1].z,
   103 						  pvr2_scene.vertex_array[poly->vertex_index+2].z );
   104 		    poly_addr += polygon_length;
   105 		    count++;
   106 		}
   107 	    } else if( (entry & 0xE0000000) == 0xA0000000 ) {
   108 		/* Quad(s) */
   109 		int strip_count = ((entry >> 25) & 0x0F)+1;
   110 		int polygon_length = 4 * vertex_length + context_length;
   111 		int i;
   112 		for( i=0; i<strip_count; i++ ) {
   113 		    struct polygon_struct *poly = pvr2_scene.buf_to_poly_map[poly_addr];
   114 		    triangles[count].poly = poly;
   115 		    triangles[count].triangle_num = 0;
   116 		    triangles[count].minz = MIN3( pvr2_scene.vertex_array[poly->vertex_index].z,
   117 						  pvr2_scene.vertex_array[poly->vertex_index+1].z,
   118 						  pvr2_scene.vertex_array[poly->vertex_index+2].z );
   119 		    count++;
   120 		    triangles[count].poly = poly;
   121 		    triangles[count].triangle_num = 1;
   122 		    triangles[count].minz = MIN3( pvr2_scene.vertex_array[poly->vertex_index+1].z,
   123 						  pvr2_scene.vertex_array[poly->vertex_index+2].z,
   124 						  pvr2_scene.vertex_array[poly->vertex_index+3].z );
   125 		    count++;
   126 		    poly_addr += polygon_length;
   127 		}
   128 	    } else {
   129 		/* Polygon */
   130 		int i;
   131 		struct polygon_struct *poly = pvr2_scene.buf_to_poly_map[poly_addr];
   132 		for( i=0; i<6; i++ ) {
   133 		    if( entry & (0x40000000>>i) ) {
   134 			triangles[count].poly = poly;
   135 			triangles[count].triangle_num = i;
   136 			triangles[count].minz = MIN3( pvr2_scene.vertex_array[poly->vertex_index+i].z,
   137 						      pvr2_scene.vertex_array[poly->vertex_index+i+1].z,
   138 						      pvr2_scene.vertex_array[poly->vertex_index+i+2].z );
   139 			count++;
   140 		    }
   141 		}
   142 	    }
   143 	}
   144     }
   145     return count;
   146 }
   148 void sort_render_triangles( struct sort_triangle *triangles, int num_triangles,
   149 			    int render_mode )
   150 {
   151     int i;
   152     for( i=0; i<num_triangles; i++ ) {
   153 	struct polygon_struct *poly = triangles[i].poly;
   154 	if( poly->tex_id != -1 ) {
   155 	    glBindTexture(GL_TEXTURE_2D, poly->tex_id);
   156 	}
   157 	render_set_context( poly->context, RENDER_NORMAL );
   158 	glEnable(GL_DEPTH_TEST);
   159 	glDepthFunc(GL_GEQUAL);
   160 	if( triangles[i].triangle_num & 1 ) {
   161 	    glCullFace(GL_FRONT);
   162 	} else {
   163 	    glCullFace(GL_BACK);
   164 	}
   165 	/* Fix cull direction */
   166 	glDrawArrays(GL_TRIANGLE_STRIP, poly->vertex_index + triangles[i].triangle_num, 3 );
   167     }
   168 }
   170 int compare_triangles( const void *a, const void *b ) 
   171 {
   172     const struct sort_triangle *tri1 = a;
   173     const struct sort_triangle *tri2 = b;
   174     return tri1->minz - tri2->minz;
   175 }
   177 void sort_triangles( struct sort_triangle *triangles, int num_triangles )
   178 {
   179     qsort( triangles, num_triangles, sizeof(struct sort_triangle), compare_triangles );
   180 } 
   182 void render_autosort_tile( pvraddr_t tile_entry, int render_mode, gboolean cheap_modifier_mode ) 
   183 {
   184     int num_triangles = sort_count_triangles(tile_entry);
   185     if( num_triangles == 0 ) {
   186 	return; /* nothing to do */
   187     } else if( num_triangles == 1 ) { /* Triangle can hardly overlap with itself */
   188 	gl_render_tilelist(tile_entry);
   189     } else { /* Ooh boy here we go... */
   190 	struct sort_triangle triangles[num_triangles+1];
   191 	// Reserve space for num_triangles / 2 * 4 vertexes (maximum possible number of
   192 	// quad vertices)
   193 	triangles[num_triangles].poly = (void *)SENTINEL;
   194 	sort_extract_triangles(tile_entry, 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 }
.