filename | src/pvr2/rendsort.c |
changeset | 650:80568a7a1ec7 |
prev | 648:ef9aa5cba86f |
next | 1066:ddffe9d2b332 |
author | nkeynes |
date | Sun Mar 16 04:49:19 2008 +0000 (16 years ago) |
branch | lxdream-render |
permissions | -rw-r--r-- |
last change | Use max-z rather than min-z for tri sort (still wrong for some cases of course, but consistent with prior behaviour) |
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 maxz;
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 maxz 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].maxz = MAX3( 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].maxz = MAX3( 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].maxz = MAX3( 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].maxz = MAX3( 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 glDepthMask(GL_FALSE);
159 glDepthFunc(GL_GEQUAL);
160 /* Fix cull direction */
161 if( triangles[i].triangle_num & 1 ) {
162 glCullFace(GL_FRONT);
163 } else {
164 glCullFace(GL_BACK);
165 }
167 glDrawArrays(GL_TRIANGLE_STRIP, poly->vertex_index + triangles[i].triangle_num, 3 );
168 }
169 }
171 int compare_triangles( const void *a, const void *b )
172 {
173 const struct sort_triangle *tri1 = a;
174 const struct sort_triangle *tri2 = b;
175 return tri2->maxz - tri1->maxz;
176 }
178 void sort_triangles( struct sort_triangle *triangles, int num_triangles )
179 {
180 qsort( triangles, num_triangles, sizeof(struct sort_triangle), compare_triangles );
181 }
183 void render_autosort_tile( pvraddr_t tile_entry, int render_mode )
184 {
185 int num_triangles = sort_count_triangles(tile_entry);
186 if( num_triangles == 0 ) {
187 return; /* nothing to do */
188 } else if( num_triangles == 1 ) { /* Triangle can hardly overlap with itself */
189 gl_render_tilelist(tile_entry);
190 } else { /* Ooh boy here we go... */
191 struct sort_triangle triangles[num_triangles+1];
192 // Reserve space for num_triangles / 2 * 4 vertexes (maximum possible number of
193 // quad vertices)
194 triangles[num_triangles].poly = (void *)SENTINEL;
195 int extracted_triangles = sort_extract_triangles(tile_entry, triangles);
196 assert( extracted_triangles == num_triangles );
197 sort_triangles( triangles, num_triangles );
198 sort_render_triangles(triangles, num_triangles, render_mode);
199 glCullFace(GL_BACK);
200 assert( triangles[num_triangles].poly == (void *)SENTINEL );
201 }
202 }
.