Search
lxdream.org :: lxdream/src/pvr2/rendsort.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/pvr2/rendsort.c
changeset 653:3202ff01d48e
prev561:533f6b478071
next669:ab344e42bca9
author nkeynes
date Fri Mar 28 12:32:25 2008 +0000 (13 years ago)
permissions -rw-r--r--
last change Merge lxdream-render branch (643:670) to trunk
file annotate diff log raw
nkeynes@222
     1
/**
nkeynes@561
     2
 * $Id$
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@653
    19
#include <string.h>
nkeynes@653
    20
#include <assert.h>
nkeynes@222
    21
#include "pvr2/pvr2.h"
nkeynes@653
    22
#include "pvr2/scene.h"
nkeynes@222
    23
#include "asic.h"
nkeynes@222
    24
nkeynes@222
    25
extern char *video_base;
nkeynes@222
    26
nkeynes@222
    27
#define MIN3( a,b,c ) ((a) < (b) ? ( (a) < (c) ? (a) : (c) ) : ((b) < (c) ? (b) : (c)) )
nkeynes@222
    28
#define MAX3( a,b,c ) ((a) > (b) ? ( (a) > (c) ? (a) : (c) ) : ((b) > (c) ? (b) : (c)) )
nkeynes@222
    29
nkeynes@653
    30
struct sort_triangle {
nkeynes@653
    31
    struct polygon_struct *poly;
nkeynes@653
    32
    int triangle_num; // triangle number in the poly, from 0
nkeynes@653
    33
    float maxz;
nkeynes@222
    34
};
nkeynes@222
    35
nkeynes@318
    36
#define SENTINEL 0xDEADBEEF
nkeynes@318
    37
nkeynes@222
    38
/**
nkeynes@222
    39
 * Count the number of triangles in the list starting at the given 
nkeynes@222
    40
 * pvr memory address.
nkeynes@222
    41
 */
nkeynes@653
    42
int sort_count_triangles( pvraddr_t tile_entry ) {
nkeynes@222
    43
    uint32_t *tile_list = (uint32_t *)(video_base+tile_entry);
nkeynes@222
    44
    int count = 0;
nkeynes@222
    45
    while(1) {
nkeynes@222
    46
	uint32_t entry = *tile_list++;
nkeynes@222
    47
	if( entry >> 28 == 0x0F ) {
nkeynes@222
    48
	    break;
nkeynes@222
    49
	} else if( entry >> 28 == 0x0E ) {
nkeynes@222
    50
	    tile_list = (uint32_t *)(video_base+(entry&0x007FFFFF));
nkeynes@222
    51
	} else if( entry >> 29 == 0x04 ) { /* Triangle array */
nkeynes@222
    52
	    count += ((entry >> 25) & 0x0F)+1;
nkeynes@222
    53
	} else if( entry >> 29 == 0x05 ) { /* Quad array */
nkeynes@222
    54
	    count += ((((entry >> 25) & 0x0F)+1)<<1);
nkeynes@222
    55
	} else { /* Polygon */
nkeynes@222
    56
	    int i;
nkeynes@222
    57
	    for( i=0; i<6; i++ ) {
nkeynes@222
    58
		if( entry & (0x40000000>>i) ) {
nkeynes@222
    59
		    count++;
nkeynes@222
    60
		}
nkeynes@222
    61
	    }
nkeynes@222
    62
	}
nkeynes@222
    63
    }
nkeynes@222
    64
    return count;
nkeynes@222
    65
}
nkeynes@222
    66
nkeynes@653
    67
/**
nkeynes@653
    68
 * Extract a triangle list from the tile (basically indexes into the polygon list, plus
nkeynes@653
    69
 * computing maxz while we go through it
nkeynes@653
    70
 */
nkeynes@653
    71
int sort_extract_triangles( pvraddr_t tile_entry, struct sort_triangle *triangles )
nkeynes@222
    72
{
nkeynes@222
    73
    uint32_t *tile_list = (uint32_t *)(video_base+tile_entry);
nkeynes@222
    74
    int count = 0;
nkeynes@222
    75
    while(1) {
nkeynes@222
    76
	uint32_t entry = *tile_list++;
nkeynes@222
    77
	if( entry >> 28 == 0x0F ) {
nkeynes@222
    78
	    break;
nkeynes@222
    79
	} else if( entry >> 28 == 0x0E ) {
nkeynes@222
    80
	    tile_list = (uint32_t *)(video_base+(entry&0x007FFFFF));
nkeynes@222
    81
	} else {
nkeynes@653
    82
	    uint32_t poly_addr = entry & 0x000FFFFF;
nkeynes@222
    83
	    int is_modified = entry & 0x01000000;
nkeynes@222
    84
	    int vertex_length = (entry >> 21) & 0x07;
nkeynes@222
    85
	    int context_length = 3;
nkeynes@653
    86
	    if( is_modified && pvr2_scene.full_shadow ) {
nkeynes@222
    87
		context_length = 5;
nkeynes@222
    88
		vertex_length *= 2 ;
nkeynes@222
    89
	    }
nkeynes@222
    90
	    vertex_length += 3;
nkeynes@222
    91
nkeynes@222
    92
	    if( (entry & 0xE0000000) == 0x80000000 ) {
nkeynes@222
    93
		/* Triangle(s) */
nkeynes@222
    94
		int strip_count = ((entry >> 25) & 0x0F)+1;
nkeynes@222
    95
		int polygon_length = 3 * vertex_length + context_length;
nkeynes@222
    96
		int i;
nkeynes@222
    97
		for( i=0; i<strip_count; i++ ) {
nkeynes@653
    98
		    struct polygon_struct *poly = pvr2_scene.buf_to_poly_map[poly_addr];
nkeynes@653
    99
		    triangles[count].poly = poly;
nkeynes@653
   100
		    triangles[count].triangle_num = 0;
nkeynes@653
   101
		    triangles[count].maxz = MAX3( pvr2_scene.vertex_array[poly->vertex_index].z,
nkeynes@653
   102
						  pvr2_scene.vertex_array[poly->vertex_index+1].z,
nkeynes@653
   103
						  pvr2_scene.vertex_array[poly->vertex_index+2].z );
nkeynes@653
   104
		    poly_addr += polygon_length;
nkeynes@222
   105
		    count++;
nkeynes@222
   106
		}
nkeynes@222
   107
	    } else if( (entry & 0xE0000000) == 0xA0000000 ) {
nkeynes@319
   108
		/* Quad(s) */
nkeynes@276
   109
		int strip_count = ((entry >> 25) & 0x0F)+1;
nkeynes@222
   110
		int polygon_length = 4 * vertex_length + context_length;
nkeynes@222
   111
		int i;
nkeynes@222
   112
		for( i=0; i<strip_count; i++ ) {
nkeynes@653
   113
		    struct polygon_struct *poly = pvr2_scene.buf_to_poly_map[poly_addr];
nkeynes@653
   114
		    triangles[count].poly = poly;
nkeynes@653
   115
		    triangles[count].triangle_num = 0;
nkeynes@653
   116
		    triangles[count].maxz = MAX3( pvr2_scene.vertex_array[poly->vertex_index].z,
nkeynes@653
   117
						  pvr2_scene.vertex_array[poly->vertex_index+1].z,
nkeynes@653
   118
						  pvr2_scene.vertex_array[poly->vertex_index+2].z );
nkeynes@222
   119
		    count++;
nkeynes@653
   120
		    triangles[count].poly = poly;
nkeynes@653
   121
		    triangles[count].triangle_num = 1;
nkeynes@653
   122
		    triangles[count].maxz = MAX3( pvr2_scene.vertex_array[poly->vertex_index+1].z,
nkeynes@653
   123
						  pvr2_scene.vertex_array[poly->vertex_index+2].z,
nkeynes@653
   124
						  pvr2_scene.vertex_array[poly->vertex_index+3].z );
nkeynes@222
   125
		    count++;
nkeynes@653
   126
		    poly_addr += polygon_length;
nkeynes@222
   127
		}
nkeynes@222
   128
	    } else {
nkeynes@222
   129
		/* Polygon */
nkeynes@429
   130
		int i;
nkeynes@653
   131
		struct polygon_struct *poly = pvr2_scene.buf_to_poly_map[poly_addr];
nkeynes@222
   132
		for( i=0; i<6; i++ ) {
nkeynes@222
   133
		    if( entry & (0x40000000>>i) ) {
nkeynes@653
   134
			triangles[count].poly = poly;
nkeynes@653
   135
			triangles[count].triangle_num = i;
nkeynes@653
   136
			triangles[count].maxz = MAX3( pvr2_scene.vertex_array[poly->vertex_index+i].z,
nkeynes@653
   137
						      pvr2_scene.vertex_array[poly->vertex_index+i+1].z,
nkeynes@653
   138
						      pvr2_scene.vertex_array[poly->vertex_index+i+2].z );
nkeynes@222
   139
			count++;
nkeynes@222
   140
		    }
nkeynes@222
   141
		}
nkeynes@222
   142
	    }
nkeynes@222
   143
	}
nkeynes@222
   144
    }
nkeynes@653
   145
    return count;
nkeynes@222
   146
}
nkeynes@222
   147
nkeynes@653
   148
void sort_render_triangles( struct sort_triangle *triangles, int num_triangles,
nkeynes@653
   149
			    int render_mode )
nkeynes@222
   150
{
nkeynes@429
   151
    int i;
nkeynes@222
   152
    for( i=0; i<num_triangles; i++ ) {
nkeynes@653
   153
	struct polygon_struct *poly = triangles[i].poly;
nkeynes@653
   154
	if( poly->tex_id != -1 ) {
nkeynes@653
   155
	    glBindTexture(GL_TEXTURE_2D, poly->tex_id);
nkeynes@653
   156
	}
nkeynes@653
   157
	render_set_context( poly->context, RENDER_NORMAL );
nkeynes@653
   158
	glDepthMask(GL_FALSE);
nkeynes@331
   159
	glDepthFunc(GL_GEQUAL);
nkeynes@653
   160
	/* Fix cull direction */
nkeynes@653
   161
	if( triangles[i].triangle_num & 1 ) {
nkeynes@653
   162
	    glCullFace(GL_FRONT);
nkeynes@319
   163
	} else {
nkeynes@653
   164
	    glCullFace(GL_BACK);
nkeynes@222
   165
	}
nkeynes@653
   166
	
nkeynes@653
   167
	glDrawArrays(GL_TRIANGLE_STRIP, poly->vertex_index + triangles[i].triangle_num, 3 );
nkeynes@222
   168
    }
nkeynes@222
   169
}
nkeynes@222
   170
nkeynes@429
   171
int compare_triangles( const void *a, const void *b ) 
nkeynes@222
   172
{
nkeynes@653
   173
    const struct sort_triangle *tri1 = a;
nkeynes@653
   174
    const struct sort_triangle *tri2 = b;
nkeynes@653
   175
    return tri2->maxz - tri1->maxz;
nkeynes@222
   176
}
nkeynes@222
   177
nkeynes@653
   178
void sort_triangles( struct sort_triangle *triangles, int num_triangles )
nkeynes@222
   179
{
nkeynes@653
   180
    qsort( triangles, num_triangles, sizeof(struct sort_triangle), compare_triangles );
nkeynes@222
   181
} 
nkeynes@222
   182
			
nkeynes@653
   183
void render_autosort_tile( pvraddr_t tile_entry, int render_mode ) 
nkeynes@222
   184
{
nkeynes@653
   185
    int num_triangles = sort_count_triangles(tile_entry);
nkeynes@222
   186
    if( num_triangles == 0 ) {
nkeynes@222
   187
	return; /* nothing to do */
nkeynes@222
   188
    } else if( num_triangles == 1 ) { /* Triangle can hardly overlap with itself */
nkeynes@653
   189
	gl_render_tilelist(tile_entry);
nkeynes@222
   190
    } else { /* Ooh boy here we go... */
nkeynes@653
   191
	struct sort_triangle triangles[num_triangles+1];
nkeynes@319
   192
	// Reserve space for num_triangles / 2 * 4 vertexes (maximum possible number of
nkeynes@319
   193
	// quad vertices)
nkeynes@653
   194
	triangles[num_triangles].poly = (void *)SENTINEL;
nkeynes@653
   195
	int extracted_triangles = sort_extract_triangles(tile_entry, triangles);
nkeynes@653
   196
	assert( extracted_triangles == num_triangles );
nkeynes@222
   197
	sort_triangles( triangles, num_triangles );
nkeynes@653
   198
	sort_render_triangles(triangles, num_triangles, render_mode);
nkeynes@653
   199
	glCullFace(GL_BACK);
nkeynes@653
   200
	assert( triangles[num_triangles].poly == (void *)SENTINEL );
nkeynes@222
   201
    }
nkeynes@222
   202
}
.