Search
lxdream.org :: lxdream/src/pvr2/rendsort.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/pvr2/rendsort.c
changeset 318:363935d31859
prev276:1e594c2804f8
next319:5392aed6a982
author nkeynes
date Tue Jan 23 12:03:57 2007 +0000 (16 years ago)
permissions -rw-r--r--
last change Add initial offset color support
Honor the "enable fragment alpha" bit
file annotate diff log raw
nkeynes@222
     1
/**
nkeynes@318
     2
 * $Id: rendsort.c,v 1.3 2007-01-23 12:03:57 nkeynes Exp $
nkeynes@222
     3
 *
nkeynes@222
     4
 * PVR2 renderer routines for depth sorted polygons
nkeynes@222
     5
 *
nkeynes@222
     6
 * Copyright (c) 2005 Nathan Keynes.
nkeynes@222
     7
 *
nkeynes@222
     8
 * This program is free software; you can redistribute it and/or modify
nkeynes@222
     9
 * it under the terms of the GNU General Public License as published by
nkeynes@222
    10
 * the Free Software Foundation; either version 2 of the License, or
nkeynes@222
    11
 * (at your option) any later version.
nkeynes@222
    12
 *
nkeynes@222
    13
 * This program is distributed in the hope that it will be useful,
nkeynes@222
    14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
nkeynes@222
    15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
nkeynes@222
    16
 * GNU General Public License for more details.
nkeynes@222
    17
 */
nkeynes@222
    18
#include <sys/time.h>
nkeynes@222
    19
#include "pvr2/pvr2.h"
nkeynes@222
    20
#include "asic.h"
nkeynes@222
    21
nkeynes@222
    22
extern char *video_base;
nkeynes@318
    23
extern gboolean pvr2_force_fragment_alpha;
nkeynes@222
    24
nkeynes@222
    25
#define MIN3( a,b,c ) ((a) < (b) ? ( (a) < (c) ? (a) : (c) ) : ((b) < (c) ? (b) : (c)) )
nkeynes@222
    26
#define MAX3( a,b,c ) ((a) > (b) ? ( (a) > (c) ? (a) : (c) ) : ((b) > (c) ? (b) : (c)) )
nkeynes@222
    27
nkeynes@222
    28
struct pvr_vertex {
nkeynes@222
    29
    float x,y,z;
nkeynes@222
    30
    uint32_t detail[1];
nkeynes@222
    31
};
nkeynes@222
    32
nkeynes@222
    33
struct render_triangle {
nkeynes@222
    34
    uint32_t *polygon;
nkeynes@222
    35
    int vertex_length;
nkeynes@222
    36
    float minx,miny,minz;
nkeynes@222
    37
    float maxx,maxy,maxz;
nkeynes@222
    38
    float *vertexes[3];
nkeynes@222
    39
};
nkeynes@222
    40
nkeynes@318
    41
#define SENTINEL 0xDEADBEEF
nkeynes@318
    42
nkeynes@222
    43
/**
nkeynes@222
    44
 * Count the number of triangles in the list starting at the given 
nkeynes@222
    45
 * pvr memory address.
nkeynes@222
    46
 */
nkeynes@222
    47
int render_count_triangles( pvraddr_t tile_entry ) {
nkeynes@222
    48
    uint32_t *tile_list = (uint32_t *)(video_base+tile_entry);
nkeynes@222
    49
    int count = 0;
nkeynes@222
    50
    while(1) {
nkeynes@222
    51
	uint32_t entry = *tile_list++;
nkeynes@222
    52
	if( entry >> 28 == 0x0F ) {
nkeynes@222
    53
	    break;
nkeynes@222
    54
	} else if( entry >> 28 == 0x0E ) {
nkeynes@222
    55
	    tile_list = (uint32_t *)(video_base+(entry&0x007FFFFF));
nkeynes@222
    56
	} else if( entry >> 29 == 0x04 ) { /* Triangle array */
nkeynes@222
    57
	    count += ((entry >> 25) & 0x0F)+1;
nkeynes@222
    58
	} else if( entry >> 29 == 0x05 ) { /* Quad array */
nkeynes@222
    59
	    count += ((((entry >> 25) & 0x0F)+1)<<1);
nkeynes@222
    60
	} else { /* Polygon */
nkeynes@222
    61
	    int i;
nkeynes@222
    62
	    for( i=0; i<6; i++ ) {
nkeynes@222
    63
		if( entry & (0x40000000>>i) ) {
nkeynes@222
    64
		    count++;
nkeynes@222
    65
		}
nkeynes@222
    66
	    }
nkeynes@222
    67
	}
nkeynes@222
    68
    }
nkeynes@222
    69
    return count;
nkeynes@222
    70
}
nkeynes@222
    71
nkeynes@222
    72
static void compute_triangle_boxes( struct render_triangle *triangle, int num_triangles )
nkeynes@222
    73
{
nkeynes@222
    74
    int i;
nkeynes@222
    75
    for( i=0; i<num_triangles; i++ ) {
nkeynes@222
    76
	triangle[i].minx = MIN3(triangle[i].vertexes[0][0],triangle[i].vertexes[1][0],triangle[i].vertexes[2][0]);
nkeynes@222
    77
	triangle[i].maxx = MAX3(triangle[i].vertexes[0][0],triangle[i].vertexes[1][0],triangle[i].vertexes[2][0]);
nkeynes@222
    78
	triangle[i].miny = MIN3(triangle[i].vertexes[0][1],triangle[i].vertexes[1][1],triangle[i].vertexes[2][1]);
nkeynes@222
    79
	triangle[i].maxy = MAX3(triangle[i].vertexes[0][1],triangle[i].vertexes[1][1],triangle[i].vertexes[2][1]);
nkeynes@222
    80
	triangle[i].minz = MIN3(triangle[i].vertexes[0][2],triangle[i].vertexes[1][2],triangle[i].vertexes[2][2]);
nkeynes@222
    81
	triangle[i].maxz = MAX3(triangle[i].vertexes[0][2],triangle[i].vertexes[1][2],triangle[i].vertexes[2][2]);
nkeynes@222
    82
    }
nkeynes@222
    83
}
nkeynes@222
    84
nkeynes@222
    85
void render_extract_triangles( pvraddr_t tile_entry, gboolean cheap_modifier_mode, 
nkeynes@318
    86
			       struct render_triangle *triangles, int num_triangles )
nkeynes@222
    87
{
nkeynes@222
    88
    uint32_t poly_bank = MMIO_READ(PVR2,RENDER_POLYBASE);
nkeynes@222
    89
    uint32_t *tile_list = (uint32_t *)(video_base+tile_entry);
nkeynes@222
    90
    int count = 0;
nkeynes@222
    91
    while(1) {
nkeynes@222
    92
	uint32_t entry = *tile_list++;
nkeynes@222
    93
	if( entry >> 28 == 0x0F ) {
nkeynes@222
    94
	    break;
nkeynes@222
    95
	} else if( entry >> 28 == 0x0E ) {
nkeynes@222
    96
	    tile_list = (uint32_t *)(video_base+(entry&0x007FFFFF));
nkeynes@222
    97
	} else {
nkeynes@222
    98
	    uint32_t *polygon = (uint32_t *)(video_base + poly_bank + ((entry & 0x000FFFFF) << 2));
nkeynes@222
    99
	    int is_modified = entry & 0x01000000;
nkeynes@222
   100
	    int vertex_length = (entry >> 21) & 0x07;
nkeynes@222
   101
	    int context_length = 3;
nkeynes@222
   102
	    if( is_modified && !cheap_modifier_mode ) {
nkeynes@222
   103
		context_length = 5;
nkeynes@222
   104
		vertex_length *= 2 ;
nkeynes@222
   105
	    }
nkeynes@222
   106
	    vertex_length += 3;
nkeynes@222
   107
nkeynes@222
   108
	    if( (entry & 0xE0000000) == 0x80000000 ) {
nkeynes@222
   109
		/* Triangle(s) */
nkeynes@222
   110
		int strip_count = ((entry >> 25) & 0x0F)+1;
nkeynes@222
   111
		int polygon_length = 3 * vertex_length + context_length;
nkeynes@222
   112
		int i;
nkeynes@222
   113
		for( i=0; i<strip_count; i++ ) {
nkeynes@222
   114
		    float *vertex = (float *)(polygon+context_length);
nkeynes@222
   115
		    triangles[count].polygon = polygon;
nkeynes@222
   116
		    triangles[count].vertex_length = vertex_length;
nkeynes@222
   117
		    triangles[count].vertexes[0] = vertex;
nkeynes@222
   118
		    vertex+=vertex_length;
nkeynes@222
   119
		    triangles[count].vertexes[1] = vertex;
nkeynes@222
   120
		    vertex+=vertex_length;
nkeynes@222
   121
		    triangles[count].vertexes[2] = vertex;
nkeynes@222
   122
		    polygon += polygon_length;
nkeynes@222
   123
		    count++;
nkeynes@222
   124
		}
nkeynes@222
   125
	    } else if( (entry & 0xE0000000) == 0xA0000000 ) {
nkeynes@222
   126
		/* Sprite(s) */
nkeynes@276
   127
		int strip_count = ((entry >> 25) & 0x0F)+1;
nkeynes@222
   128
		int polygon_length = 4 * vertex_length + context_length;
nkeynes@222
   129
		int i;
nkeynes@222
   130
		for( i=0; i<strip_count; i++ ) {
nkeynes@222
   131
		    float *vertex = (float *)(polygon+context_length);
nkeynes@222
   132
		    triangles[count].polygon = polygon;
nkeynes@222
   133
		    triangles[count].vertex_length = vertex_length;
nkeynes@222
   134
		    triangles[count].vertexes[0] = vertex;
nkeynes@222
   135
		    vertex+=vertex_length;
nkeynes@222
   136
		    triangles[count].vertexes[1] = vertex;
nkeynes@222
   137
		    vertex+=vertex_length;
nkeynes@222
   138
		    triangles[count].vertexes[2] = vertex;
nkeynes@222
   139
		    count++;
nkeynes@222
   140
		    /* Preserve face direction */
nkeynes@222
   141
		    triangles[count].polygon = polygon;
nkeynes@222
   142
		    triangles[count].vertex_length = vertex_length;
nkeynes@222
   143
		    triangles[count].vertexes[0] = vertex;
nkeynes@222
   144
		    triangles[count].vertexes[1] = vertex - vertex_length;
nkeynes@222
   145
		    triangles[count].vertexes[2] = vertex + vertex_length;
nkeynes@222
   146
		    count++;
nkeynes@222
   147
		    polygon += polygon_length;
nkeynes@222
   148
		}
nkeynes@222
   149
	    } else {
nkeynes@222
   150
		/* Polygon */
nkeynes@222
   151
		int i, first=-1, last = -1;
nkeynes@222
   152
		float *vertex = (float *)polygon+context_length;
nkeynes@222
   153
		for( i=0; i<6; i++ ) {
nkeynes@222
   154
		    if( entry & (0x40000000>>i) ) {
nkeynes@222
   155
			triangles[count].polygon = polygon;
nkeynes@222
   156
			triangles[count].vertex_length = vertex_length;
nkeynes@222
   157
			if( i&1 ) {
nkeynes@222
   158
			    triangles[count].vertexes[0] = vertex + vertex_length;
nkeynes@222
   159
			    triangles[count].vertexes[1] = vertex;
nkeynes@222
   160
			    triangles[count].vertexes[2] = vertex + (vertex_length<<1);
nkeynes@222
   161
			} else {
nkeynes@222
   162
			    triangles[count].vertexes[0] = vertex;
nkeynes@222
   163
			    triangles[count].vertexes[1] = vertex + vertex_length;
nkeynes@222
   164
			    triangles[count].vertexes[2] = vertex + (vertex_length<<1);
nkeynes@222
   165
			}
nkeynes@222
   166
			count++;
nkeynes@222
   167
		    }
nkeynes@222
   168
		    vertex += vertex_length;
nkeynes@222
   169
		}
nkeynes@222
   170
	    }
nkeynes@222
   171
	}
nkeynes@222
   172
    }
nkeynes@318
   173
    if( count != num_triangles ) {
nkeynes@318
   174
	ERROR( "Extracted triangles do not match expected count!" );
nkeynes@318
   175
    }
nkeynes@222
   176
}
nkeynes@222
   177
nkeynes@222
   178
void render_triangles( struct render_triangle *triangles, int num_triangles,
nkeynes@222
   179
		       int render_mode )
nkeynes@222
   180
{
nkeynes@318
   181
    int i,j, k, m = 0;
nkeynes@222
   182
    for( i=0; i<num_triangles; i++ ) {
nkeynes@222
   183
	render_set_context( triangles[i].polygon, render_mode );
nkeynes@222
   184
	if( render_mode == RENDER_FULLMOD ) {
nkeynes@222
   185
	    m = (triangles[i].vertex_length - 3)/2;
nkeynes@222
   186
	}
nkeynes@222
   187
nkeynes@222
   188
	glBegin( GL_TRIANGLE_STRIP );
nkeynes@222
   189
    
nkeynes@222
   190
	for( j=0; j<3; j++ ) {
nkeynes@222
   191
	    uint32_t *vertexes = (uint32_t *)triangles[i].vertexes[j];
nkeynes@222
   192
	    float *vertexf = (float *)vertexes;
nkeynes@222
   193
	    uint32_t argb;
nkeynes@318
   194
	    k = m + 3;
nkeynes@222
   195
	    if( POLY1_TEXTURED(*triangles[i].polygon) ) {
nkeynes@222
   196
		if( POLY1_UV16(*triangles[i].polygon) ) {
nkeynes@318
   197
		    glTexCoord2f( halftofloat(vertexes[k]>>16),
nkeynes@318
   198
				  halftofloat(vertexes[k]) );
nkeynes@318
   199
		    k++;
nkeynes@222
   200
		} else {
nkeynes@318
   201
		    glTexCoord2f( vertexf[k], vertexf[k+1] );
nkeynes@318
   202
		    k+=2;
nkeynes@222
   203
		}
nkeynes@318
   204
	    }
nkeynes@318
   205
	    argb = vertexes[k++];
nkeynes@318
   206
	    if( pvr2_force_fragment_alpha ) {
nkeynes@318
   207
		glColor4ub( (GLubyte)(argb >> 16), (GLubyte)(argb >> 8), 
nkeynes@318
   208
			    (GLubyte)argb, 0xFF );
nkeynes@222
   209
	    } else {
nkeynes@318
   210
		glColor4ub( (GLubyte)(argb >> 16), (GLubyte)(argb >> 8), 
nkeynes@318
   211
			    (GLubyte)argb, (GLubyte)(argb >> 24) );
nkeynes@222
   212
	    }
nkeynes@318
   213
nkeynes@318
   214
	    if( POLY1_SPECULAR(*triangles[i].polygon) ) {
nkeynes@318
   215
		uint32_t spec = vertexes[k];
nkeynes@318
   216
		glSecondaryColor3ubEXT( (GLubyte)(spec >> 16), (GLubyte)(spec >> 8), 
nkeynes@318
   217
				     (GLubyte)spec );
nkeynes@318
   218
	    }
nkeynes@222
   219
	    glVertex3f( vertexf[0], vertexf[1], vertexf[2] );
nkeynes@222
   220
	}
nkeynes@222
   221
	glEnd();
nkeynes@222
   222
    }
nkeynes@222
   223
nkeynes@222
   224
nkeynes@222
   225
}
nkeynes@222
   226
nkeynes@222
   227
int compare_triangles( void *a, void *b ) 
nkeynes@222
   228
{
nkeynes@222
   229
    struct render_triangle *tri1 = a;
nkeynes@222
   230
    struct render_triangle *tri2 = b;
nkeynes@222
   231
    if( tri1->minz < tri2->minz ) {
nkeynes@222
   232
	return -1;
nkeynes@222
   233
    } else if( tri1->minz > tri2->minz ) {
nkeynes@222
   234
	return 1;
nkeynes@222
   235
    } else {
nkeynes@222
   236
	return 0;
nkeynes@222
   237
    }
nkeynes@222
   238
}
nkeynes@222
   239
nkeynes@222
   240
void sort_triangles( struct render_triangle *triangles, int num_triangles )
nkeynes@222
   241
{
nkeynes@222
   242
    qsort( triangles, num_triangles, sizeof(struct render_triangle), compare_triangles );
nkeynes@222
   243
} 
nkeynes@222
   244
			
nkeynes@222
   245
void render_autosort_tile( pvraddr_t tile_entry, int render_mode, gboolean cheap_modifier_mode ) 
nkeynes@222
   246
{
nkeynes@222
   247
    int num_triangles = render_count_triangles(tile_entry);
nkeynes@222
   248
    if( num_triangles == 0 ) {
nkeynes@222
   249
	return; /* nothing to do */
nkeynes@222
   250
    } else if( num_triangles == 1 ) { /* Triangle can hardly overlap with itself */
nkeynes@222
   251
	render_tile( tile_entry, render_mode, cheap_modifier_mode );
nkeynes@222
   252
    } else { /* Ooh boy here we go... */
nkeynes@318
   253
	struct render_triangle triangles[num_triangles+1];
nkeynes@318
   254
	triangles[num_triangles].polygon = (void *)SENTINEL;
nkeynes@318
   255
	render_extract_triangles(tile_entry, cheap_modifier_mode, triangles, num_triangles);
nkeynes@222
   256
	compute_triangle_boxes(triangles, num_triangles);
nkeynes@222
   257
	sort_triangles( triangles, num_triangles );
nkeynes@222
   258
	render_triangles(triangles, num_triangles, render_mode);
nkeynes@318
   259
	if( triangles[num_triangles].polygon != (void *)SENTINEL ) {
nkeynes@318
   260
	    fprintf( stderr, "Triangle overflow in render_autosort_tile!" );
nkeynes@318
   261
	}
nkeynes@222
   262
    }
nkeynes@222
   263
}
.