filename | src/pvr2/rendsort.c |
changeset | 635:76c63aac3590 |
prev | 561:533f6b478071 |
next | 645:a7392098299c |
author | nkeynes |
date | Thu Feb 14 13:54:11 2008 +0000 (16 years ago) |
branch | lxdream-render |
permissions | -rw-r--r-- |
last change | Commit render work in progress. Main changes: * Preliminary OSMesa support * Move the generic gl code out to pvr2/ * Implement scene data structure + reader * Remove the 1/z adjustments |
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 "pvr2/pvr2.h"
20 #include "asic.h"
22 extern char *video_base;
23 extern gboolean pvr2_force_fragment_alpha;
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 render_triangle {
29 uint32_t *polygon;
30 int vertex_length; /* Number of 32-bit words in vertex, or 0 for an unpacked vertex */
31 float minx,miny,minz;
32 float maxx,maxy,maxz;
33 float *vertexes[3];
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 render_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 static void compute_triangle_boxes( struct render_triangle *triangle, int num_triangles )
68 {
69 int i;
70 for( i=0; i<num_triangles; i++ ) {
71 triangle[i].minx = MIN3(triangle[i].vertexes[0][0],triangle[i].vertexes[1][0],triangle[i].vertexes[2][0]);
72 triangle[i].maxx = MAX3(triangle[i].vertexes[0][0],triangle[i].vertexes[1][0],triangle[i].vertexes[2][0]);
73 triangle[i].miny = MIN3(triangle[i].vertexes[0][1],triangle[i].vertexes[1][1],triangle[i].vertexes[2][1]);
74 triangle[i].maxy = MAX3(triangle[i].vertexes[0][1],triangle[i].vertexes[1][1],triangle[i].vertexes[2][1]);
75 float az = triangle[i].vertexes[0][2];
76 float bz = triangle[i].vertexes[1][2];
77 float cz = triangle[i].vertexes[2][2];
78 triangle[i].minz = MIN3(az,bz,cz);
79 triangle[i].maxz = MAX3(az,bz,cz);
80 }
81 }
83 void render_extract_triangles( pvraddr_t tile_entry, gboolean cheap_modifier_mode,
84 struct render_triangle *triangles, int num_triangles,
85 struct vertex_unpacked *vertex_space, int render_mode )
86 {
87 uint32_t poly_bank = MMIO_READ(PVR2,RENDER_POLYBASE);
88 uint32_t *tile_list = (uint32_t *)(video_base+tile_entry);
89 int count = 0;
90 while(1) {
91 uint32_t entry = *tile_list++;
92 if( entry >> 28 == 0x0F ) {
93 break;
94 } else if( entry >> 28 == 0x0E ) {
95 tile_list = (uint32_t *)(video_base+(entry&0x007FFFFF));
96 } else {
97 uint32_t *polygon = (uint32_t *)(video_base + poly_bank + ((entry & 0x000FFFFF) << 2));
98 int is_modified = entry & 0x01000000;
99 int vertex_length = (entry >> 21) & 0x07;
100 int context_length = 3;
101 if( is_modified && !cheap_modifier_mode ) {
102 context_length = 5;
103 vertex_length *= 2 ;
104 }
105 vertex_length += 3;
107 if( (entry & 0xE0000000) == 0x80000000 ) {
108 /* Triangle(s) */
109 int strip_count = ((entry >> 25) & 0x0F)+1;
110 int polygon_length = 3 * vertex_length + context_length;
111 int i;
112 for( i=0; i<strip_count; i++ ) {
113 float *vertex = (float *)(polygon+context_length);
114 triangles[count].polygon = polygon;
115 triangles[count].vertex_length = vertex_length;
116 triangles[count].vertexes[0] = vertex;
117 vertex+=vertex_length;
118 triangles[count].vertexes[1] = vertex;
119 vertex+=vertex_length;
120 triangles[count].vertexes[2] = vertex;
121 polygon += polygon_length;
122 count++;
123 }
124 } else if( (entry & 0xE0000000) == 0xA0000000 ) {
125 /* Quad(s) */
126 int strip_count = ((entry >> 25) & 0x0F)+1;
127 int polygon_length = 4 * vertex_length + context_length;
129 int i;
130 for( i=0; i<strip_count; i++ ) {
131 render_unpack_quad( vertex_space, *polygon, (polygon+context_length),
132 vertex_length, render_mode );
133 triangles[count].polygon = polygon;
134 triangles[count].vertex_length = 0;
135 triangles[count].vertexes[0] = (float *)vertex_space;
136 triangles[count].vertexes[1] = (float *)(vertex_space + 1);
137 triangles[count].vertexes[2] = (float *)(vertex_space + 3);
138 count++;
139 /* Preserve face direction */
140 triangles[count].polygon = polygon;
141 triangles[count].vertex_length = 0;
142 triangles[count].vertexes[0] = (float *)(vertex_space + 1);
143 triangles[count].vertexes[1] = (float *)(vertex_space + 2);
144 triangles[count].vertexes[2] = (float *)(vertex_space + 3);
145 count++;
146 vertex_space += 4;
147 polygon += polygon_length;
148 }
149 } else {
150 /* Polygon */
151 int i;
152 float *vertex = (float *)polygon+context_length;
153 for( i=0; i<6; i++ ) {
154 if( entry & (0x40000000>>i) ) {
155 triangles[count].polygon = polygon;
156 triangles[count].vertex_length = vertex_length;
157 if( i&1 ) {
158 triangles[count].vertexes[0] = vertex + vertex_length;
159 triangles[count].vertexes[1] = vertex;
160 triangles[count].vertexes[2] = vertex + (vertex_length<<1);
161 } else {
162 triangles[count].vertexes[0] = vertex;
163 triangles[count].vertexes[1] = vertex + vertex_length;
164 triangles[count].vertexes[2] = vertex + (vertex_length<<1);
165 }
166 count++;
167 }
168 vertex += vertex_length;
169 }
170 }
171 }
172 }
173 if( count != num_triangles ) {
174 ERROR( "Extracted triangles do not match expected count!" );
175 }
176 }
178 void render_triangles( struct render_triangle *triangles, int num_triangles,
179 int render_mode )
180 {
181 int i;
182 for( i=0; i<num_triangles; i++ ) {
183 render_set_context( triangles[i].polygon, render_mode );
184 glEnable(GL_DEPTH_TEST);
185 glDepthFunc(GL_GEQUAL);
186 if( triangles[i].vertex_length == 0 ) {
187 render_unpacked_vertex_array( *triangles[i].polygon, (struct vertex_unpacked **)triangles[i].vertexes, 3 );
188 } else {
189 render_vertex_array( *triangles[i].polygon, (uint32_t **)triangles[i].vertexes, 3,
190 triangles[i].vertex_length, render_mode );
191 }
192 }
195 }
197 int compare_triangles( const void *a, const void *b )
198 {
199 const struct render_triangle *tri1 = a;
200 const struct render_triangle *tri2 = b;
201 if( tri1->minz > tri2->minz ) {
202 return 1;
203 } else if( tri1->minz < tri2->minz ) {
204 return -1;
205 } else {
206 return 0;
207 }
208 }
210 void sort_triangles( struct render_triangle *triangles, int num_triangles )
211 {
212 qsort( triangles, num_triangles, sizeof(struct render_triangle), compare_triangles );
213 }
215 void render_autosort_tile( pvraddr_t tile_entry, int render_mode, gboolean cheap_modifier_mode )
216 {
217 int num_triangles = render_count_triangles(tile_entry);
218 if( num_triangles == 0 ) {
219 return; /* nothing to do */
220 } else if( num_triangles == 1 ) { /* Triangle can hardly overlap with itself */
221 render_tile( tile_entry, render_mode, cheap_modifier_mode );
222 } else { /* Ooh boy here we go... */
223 struct render_triangle triangles[num_triangles+1];
224 struct vertex_unpacked vertex_space[num_triangles << 1];
225 // Reserve space for num_triangles / 2 * 4 vertexes (maximum possible number of
226 // quad vertices)
227 triangles[num_triangles].polygon = (void *)SENTINEL;
228 render_extract_triangles(tile_entry, cheap_modifier_mode, triangles, num_triangles, vertex_space, render_mode);
229 compute_triangle_boxes(triangles, num_triangles);
230 sort_triangles( triangles, num_triangles );
231 render_triangles(triangles, num_triangles, render_mode);
232 if( triangles[num_triangles].polygon != (void *)SENTINEL ) {
233 fprintf( stderr, "Triangle overflow in render_autosort_tile!" );
234 }
235 }
236 }
.