Search
lxdream.org :: lxdream/src/pvr2/rendsort.c :: diff
lxdream 0.9.1
released Jun 29
Download Now
filename src/pvr2/rendsort.c
changeset 222:541d9d899aba
next276:1e594c2804f8
author nkeynes
date Tue Sep 12 11:54:19 2006 +0000 (13 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 ^_^
file annotate diff log raw
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/src/pvr2/rendsort.c Tue Sep 12 11:54:19 2006 +0000
1.3 @@ -0,0 +1,243 @@
1.4 +/**
1.5 + * $Id: rendsort.c,v 1.1 2006-09-12 11:54:19 nkeynes Exp $
1.6 + *
1.7 + * PVR2 renderer routines for depth sorted polygons
1.8 + *
1.9 + * Copyright (c) 2005 Nathan Keynes.
1.10 + *
1.11 + * This program is free software; you can redistribute it and/or modify
1.12 + * it under the terms of the GNU General Public License as published by
1.13 + * the Free Software Foundation; either version 2 of the License, or
1.14 + * (at your option) any later version.
1.15 + *
1.16 + * This program is distributed in the hope that it will be useful,
1.17 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1.18 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1.19 + * GNU General Public License for more details.
1.20 + */
1.21 +#include <sys/time.h>
1.22 +#include "pvr2/pvr2.h"
1.23 +#include "asic.h"
1.24 +
1.25 +extern char *video_base;
1.26 +
1.27 +#define MIN3( a,b,c ) ((a) < (b) ? ( (a) < (c) ? (a) : (c) ) : ((b) < (c) ? (b) : (c)) )
1.28 +#define MAX3( a,b,c ) ((a) > (b) ? ( (a) > (c) ? (a) : (c) ) : ((b) > (c) ? (b) : (c)) )
1.29 +
1.30 +struct pvr_vertex {
1.31 + float x,y,z;
1.32 + uint32_t detail[1];
1.33 +};
1.34 +
1.35 +struct render_triangle {
1.36 + uint32_t *polygon;
1.37 + int vertex_length;
1.38 + float minx,miny,minz;
1.39 + float maxx,maxy,maxz;
1.40 + float *vertexes[3];
1.41 +};
1.42 +
1.43 +/**
1.44 + * Count the number of triangles in the list starting at the given
1.45 + * pvr memory address.
1.46 + */
1.47 +int render_count_triangles( pvraddr_t tile_entry ) {
1.48 + uint32_t *tile_list = (uint32_t *)(video_base+tile_entry);
1.49 + int count = 0;
1.50 + while(1) {
1.51 + uint32_t entry = *tile_list++;
1.52 + if( entry >> 28 == 0x0F ) {
1.53 + break;
1.54 + } else if( entry >> 28 == 0x0E ) {
1.55 + tile_list = (uint32_t *)(video_base+(entry&0x007FFFFF));
1.56 + } else if( entry >> 29 == 0x04 ) { /* Triangle array */
1.57 + count += ((entry >> 25) & 0x0F)+1;
1.58 + } else if( entry >> 29 == 0x05 ) { /* Quad array */
1.59 + count += ((((entry >> 25) & 0x0F)+1)<<1);
1.60 + } else { /* Polygon */
1.61 + int i;
1.62 + for( i=0; i<6; i++ ) {
1.63 + if( entry & (0x40000000>>i) ) {
1.64 + count++;
1.65 + }
1.66 + }
1.67 + }
1.68 + }
1.69 + return count;
1.70 +}
1.71 +
1.72 +static void compute_triangle_boxes( struct render_triangle *triangle, int num_triangles )
1.73 +{
1.74 + int i;
1.75 + for( i=0; i<num_triangles; i++ ) {
1.76 + triangle[i].minx = MIN3(triangle[i].vertexes[0][0],triangle[i].vertexes[1][0],triangle[i].vertexes[2][0]);
1.77 + triangle[i].maxx = MAX3(triangle[i].vertexes[0][0],triangle[i].vertexes[1][0],triangle[i].vertexes[2][0]);
1.78 + triangle[i].miny = MIN3(triangle[i].vertexes[0][1],triangle[i].vertexes[1][1],triangle[i].vertexes[2][1]);
1.79 + triangle[i].maxy = MAX3(triangle[i].vertexes[0][1],triangle[i].vertexes[1][1],triangle[i].vertexes[2][1]);
1.80 + triangle[i].minz = MIN3(triangle[i].vertexes[0][2],triangle[i].vertexes[1][2],triangle[i].vertexes[2][2]);
1.81 + triangle[i].maxz = MAX3(triangle[i].vertexes[0][2],triangle[i].vertexes[1][2],triangle[i].vertexes[2][2]);
1.82 + }
1.83 +}
1.84 +
1.85 +void render_extract_triangles( pvraddr_t tile_entry, gboolean cheap_modifier_mode,
1.86 + struct render_triangle *triangles )
1.87 +{
1.88 + uint32_t poly_bank = MMIO_READ(PVR2,RENDER_POLYBASE);
1.89 + uint32_t *tile_list = (uint32_t *)(video_base+tile_entry);
1.90 + int count = 0;
1.91 + while(1) {
1.92 + uint32_t entry = *tile_list++;
1.93 + if( entry >> 28 == 0x0F ) {
1.94 + break;
1.95 + } else if( entry >> 28 == 0x0E ) {
1.96 + tile_list = (uint32_t *)(video_base+(entry&0x007FFFFF));
1.97 + } else {
1.98 + uint32_t *polygon = (uint32_t *)(video_base + poly_bank + ((entry & 0x000FFFFF) << 2));
1.99 + int is_modified = entry & 0x01000000;
1.100 + int vertex_length = (entry >> 21) & 0x07;
1.101 + int context_length = 3;
1.102 + if( is_modified && !cheap_modifier_mode ) {
1.103 + context_length = 5;
1.104 + vertex_length *= 2 ;
1.105 + }
1.106 + vertex_length += 3;
1.107 +
1.108 + if( (entry & 0xE0000000) == 0x80000000 ) {
1.109 + /* Triangle(s) */
1.110 + int strip_count = ((entry >> 25) & 0x0F)+1;
1.111 + int polygon_length = 3 * vertex_length + context_length;
1.112 + int i;
1.113 + for( i=0; i<strip_count; i++ ) {
1.114 + float *vertex = (float *)(polygon+context_length);
1.115 + triangles[count].polygon = polygon;
1.116 + triangles[count].vertex_length = vertex_length;
1.117 + triangles[count].vertexes[0] = vertex;
1.118 + vertex+=vertex_length;
1.119 + triangles[count].vertexes[1] = vertex;
1.120 + vertex+=vertex_length;
1.121 + triangles[count].vertexes[2] = vertex;
1.122 + polygon += polygon_length;
1.123 + count++;
1.124 + }
1.125 + } else if( (entry & 0xE0000000) == 0xA0000000 ) {
1.126 + /* Sprite(s) */
1.127 + int strip_count = (entry >> 25) & 0x0F;
1.128 + int polygon_length = 4 * vertex_length + context_length;
1.129 + int i;
1.130 + for( i=0; i<strip_count; i++ ) {
1.131 + float *vertex = (float *)(polygon+context_length);
1.132 + triangles[count].polygon = polygon;
1.133 + triangles[count].vertex_length = vertex_length;
1.134 + triangles[count].vertexes[0] = vertex;
1.135 + vertex+=vertex_length;
1.136 + triangles[count].vertexes[1] = vertex;
1.137 + vertex+=vertex_length;
1.138 + triangles[count].vertexes[2] = vertex;
1.139 + count++;
1.140 + /* Preserve face direction */
1.141 + triangles[count].polygon = polygon;
1.142 + triangles[count].vertex_length = vertex_length;
1.143 + triangles[count].vertexes[0] = vertex;
1.144 + triangles[count].vertexes[1] = vertex - vertex_length;
1.145 + triangles[count].vertexes[2] = vertex + vertex_length;
1.146 + count++;
1.147 + polygon += polygon_length;
1.148 + }
1.149 + } else {
1.150 + /* Polygon */
1.151 + int i, first=-1, last = -1;
1.152 + float *vertex = (float *)polygon+context_length;
1.153 + for( i=0; i<6; i++ ) {
1.154 + if( entry & (0x40000000>>i) ) {
1.155 + triangles[count].polygon = polygon;
1.156 + triangles[count].vertex_length = vertex_length;
1.157 + if( i&1 ) {
1.158 + triangles[count].vertexes[0] = vertex + vertex_length;
1.159 + triangles[count].vertexes[1] = vertex;
1.160 + triangles[count].vertexes[2] = vertex + (vertex_length<<1);
1.161 + } else {
1.162 + triangles[count].vertexes[0] = vertex;
1.163 + triangles[count].vertexes[1] = vertex + vertex_length;
1.164 + triangles[count].vertexes[2] = vertex + (vertex_length<<1);
1.165 + }
1.166 + count++;
1.167 + }
1.168 + vertex += vertex_length;
1.169 + }
1.170 + }
1.171 + }
1.172 + }
1.173 +}
1.174 +
1.175 +void render_triangles( struct render_triangle *triangles, int num_triangles,
1.176 + int render_mode )
1.177 +{
1.178 + int i,j, m = 0;
1.179 + for( i=0; i<num_triangles; i++ ) {
1.180 + render_set_context( triangles[i].polygon, render_mode );
1.181 + if( render_mode == RENDER_FULLMOD ) {
1.182 + m = (triangles[i].vertex_length - 3)/2;
1.183 + }
1.184 +
1.185 + glBegin( GL_TRIANGLE_STRIP );
1.186 +
1.187 + for( j=0; j<3; j++ ) {
1.188 + uint32_t *vertexes = (uint32_t *)triangles[i].vertexes[j];
1.189 + float *vertexf = (float *)vertexes;
1.190 + uint32_t argb;
1.191 + if( POLY1_TEXTURED(*triangles[i].polygon) ) {
1.192 + if( POLY1_UV16(*triangles[i].polygon) ) {
1.193 + glTexCoord2f( halftofloat(vertexes[m+3]>>16),
1.194 + halftofloat(vertexes[m+3]) );
1.195 + argb = vertexes[m+4];
1.196 + } else {
1.197 + glTexCoord2f( vertexf[m+3], vertexf[m+4] );
1.198 + argb = vertexes[m+5];
1.199 + }
1.200 + } else {
1.201 + argb = vertexes[m+3];
1.202 + }
1.203 +
1.204 + glColor4ub( (GLubyte)(argb >> 16), (GLubyte)(argb >> 8),
1.205 + (GLubyte)argb, (GLubyte)(argb >> 24) );
1.206 + glVertex3f( vertexf[0], vertexf[1], vertexf[2] );
1.207 + }
1.208 + glEnd();
1.209 + }
1.210 +
1.211 +
1.212 +}
1.213 +
1.214 +int compare_triangles( void *a, void *b )
1.215 +{
1.216 + struct render_triangle *tri1 = a;
1.217 + struct render_triangle *tri2 = b;
1.218 + if( tri1->minz < tri2->minz ) {
1.219 + return -1;
1.220 + } else if( tri1->minz > tri2->minz ) {
1.221 + return 1;
1.222 + } else {
1.223 + return 0;
1.224 + }
1.225 +}
1.226 +
1.227 +void sort_triangles( struct render_triangle *triangles, int num_triangles )
1.228 +{
1.229 + qsort( triangles, num_triangles, sizeof(struct render_triangle), compare_triangles );
1.230 +}
1.231 +
1.232 +void render_autosort_tile( pvraddr_t tile_entry, int render_mode, gboolean cheap_modifier_mode )
1.233 +{
1.234 + int num_triangles = render_count_triangles(tile_entry);
1.235 + if( num_triangles == 0 ) {
1.236 + return; /* nothing to do */
1.237 + } else if( num_triangles == 1 ) { /* Triangle can hardly overlap with itself */
1.238 + render_tile( tile_entry, render_mode, cheap_modifier_mode );
1.239 + } else { /* Ooh boy here we go... */
1.240 + struct render_triangle triangles[num_triangles];
1.241 + render_extract_triangles(tile_entry, cheap_modifier_mode, triangles);
1.242 + compute_triangle_boxes(triangles, num_triangles);
1.243 + sort_triangles( triangles, num_triangles );
1.244 + render_triangles(triangles, num_triangles, render_mode);
1.245 + }
1.246 +}
.