filename | src/pvr2/rendsort.c |
changeset | 222:541d9d899aba |
next | 276:1e594c2804f8 |
author | nkeynes |
date | Tue Sep 12 11:54:19 2006 +0000 (15 years ago) |
permissions | -rw-r--r-- |
last change | Bug #0005 Implement translucent poly sorting Implement quick-and-dirty sorting based on min-z. It's not remotely complete but damn that looks so much better ^_^ |
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 }
.