4 * PVR2 renderer routines for depth sorted polygons
6 * Copyright (c) 2005 Nathan Keynes.
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.
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.
21 #include "pvr2/pvr2.h"
22 #include "pvr2/scene.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
34 #define SENTINEL 0xDEADBEEF
37 * Count the number of triangles in the list starting at the given
40 int sort_count_triangles( pvraddr_t tile_entry ) {
41 uint32_t *tile_list = (uint32_t *)(video_base+tile_entry);
44 uint32_t entry = *tile_list++;
45 if( entry >> 28 == 0x0F ) {
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 */
55 for( i=0; i<6; i++ ) {
56 if( entry & (0x40000000>>i) ) {
66 * Extract a triangle list from the tile (basically indexes into the polygon list, plus
67 * computing maxz while we go through it
69 int sort_extract_triangles( pvraddr_t tile_entry, struct sort_triangle *triangles )
71 uint32_t *tile_list = (uint32_t *)(video_base+tile_entry);
73 struct polygon_struct *poly;
77 uint32_t entry = *tile_list++;
78 switch( entry >> 28 ) {
80 return count; // End-of-list
82 tile_list = (uint32_t *)(video_base + (entry&0x007FFFFF));
84 case 0x08: case 0x09: case 0x0A: case 0x0B:
85 strip_count = ((entry >> 25) & 0x0F)+1;
86 poly = pvr2_scene.buf_to_poly_map[entry&0x000FFFFF];
87 while( strip_count > 0 ) {
88 assert( poly != NULL );
89 for( i=0; i<poly->vertex_count-2; i++ ) {
90 triangles[count].poly = poly;
91 triangles[count].triangle_num = i;
92 triangles[count].maxz = MAX3( pvr2_scene.vertex_array[poly->vertex_index+i].z,
93 pvr2_scene.vertex_array[poly->vertex_index+i+1].z,
94 pvr2_scene.vertex_array[poly->vertex_index+i+2].z );
102 if( entry & 0x7E000000 ) {
103 poly = pvr2_scene.buf_to_poly_map[entry&0x000FFFFF];
104 for( i=0; i<6; i++ ) {
105 if( entry & (0x40000000>>i) ) {
106 triangles[count].poly = poly;
107 triangles[count].triangle_num = i;
108 triangles[count].maxz = MAX3( pvr2_scene.vertex_array[poly->vertex_index+i].z,
109 pvr2_scene.vertex_array[poly->vertex_index+i+1].z,
110 pvr2_scene.vertex_array[poly->vertex_index+i+2].z );
120 void sort_render_triangles( struct sort_triangle *triangles, int num_triangles,
124 for( i=0; i<num_triangles; i++ ) {
125 struct polygon_struct *poly = triangles[i].poly;
126 if( poly->tex_id != -1 ) {
127 glBindTexture(GL_TEXTURE_2D, poly->tex_id);
129 render_set_context( poly->context, RENDER_NORMAL );
130 glDepthMask(GL_FALSE);
131 glDepthFunc(GL_GEQUAL);
132 /* Fix cull direction */
133 if( triangles[i].triangle_num & 1 ) {
134 glCullFace(GL_FRONT);
139 glDrawArrays(GL_TRIANGLE_STRIP, poly->vertex_index + triangles[i].triangle_num, 3 );
143 int compare_triangles( const void *a, const void *b )
145 const struct sort_triangle *tri1 = a;
146 const struct sort_triangle *tri2 = b;
147 return tri2->maxz - tri1->maxz;
150 void sort_triangles( struct sort_triangle *triangles, int num_triangles )
152 qsort( triangles, num_triangles, sizeof(struct sort_triangle), compare_triangles );
155 void render_autosort_tile( pvraddr_t tile_entry, int render_mode )
157 int num_triangles = sort_count_triangles(tile_entry);
158 if( num_triangles == 0 ) {
159 return; /* nothing to do */
160 } else if( num_triangles == 1 ) { /* Triangle can hardly overlap with itself */
161 gl_render_tilelist(tile_entry);
162 } else { /* Ooh boy here we go... */
163 struct sort_triangle triangles[num_triangles+1];
164 // Reserve space for num_triangles / 2 * 4 vertexes (maximum possible number of
166 triangles[num_triangles].poly = (void *)SENTINEL;
167 int extracted_triangles = sort_extract_triangles(tile_entry, triangles);
168 assert( extracted_triangles == num_triangles );
169 sort_triangles( triangles, num_triangles );
170 sort_render_triangles(triangles, num_triangles, render_mode);
172 assert( triangles[num_triangles].poly == (void *)SENTINEL );
.