Search
lxdream.org :: lxdream/src/pvr2/rendsort.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/pvr2/rendsort.c
changeset 865:e10c081f4b81
prev862:d3b2066d5daa
next876:78cd32021472
author nkeynes
date Mon Sep 29 06:34:25 2008 +0000 (14 years ago)
permissions -rw-r--r--
last change Tidy up punchout handling slightly (doesn't really seem to need sorting...)
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
#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@653
    28
struct sort_triangle {
nkeynes@653
    29
    struct polygon_struct *poly;
nkeynes@653
    30
    int triangle_num; // triangle number in the poly, from 0
nkeynes@653
    31
    float maxz;
nkeynes@222
    32
};
nkeynes@222
    33
nkeynes@318
    34
#define SENTINEL 0xDEADBEEF
nkeynes@318
    35
nkeynes@222
    36
/**
nkeynes@222
    37
 * Count the number of triangles in the list starting at the given 
nkeynes@222
    38
 * pvr memory address.
nkeynes@222
    39
 */
nkeynes@653
    40
int sort_count_triangles( pvraddr_t tile_entry ) {
nkeynes@222
    41
    uint32_t *tile_list = (uint32_t *)(video_base+tile_entry);
nkeynes@222
    42
    int count = 0;
nkeynes@222
    43
    while(1) {
nkeynes@736
    44
        uint32_t entry = *tile_list++;
nkeynes@736
    45
        if( entry >> 28 == 0x0F ) {
nkeynes@736
    46
            break;
nkeynes@736
    47
        } else if( entry >> 28 == 0x0E ) {
nkeynes@736
    48
            tile_list = (uint32_t *)(video_base+(entry&0x007FFFFF));
nkeynes@736
    49
        } else if( entry >> 29 == 0x04 ) { /* Triangle array */
nkeynes@736
    50
            count += ((entry >> 25) & 0x0F)+1;
nkeynes@736
    51
        } else if( entry >> 29 == 0x05 ) { /* Quad array */
nkeynes@736
    52
            count += ((((entry >> 25) & 0x0F)+1)<<1);
nkeynes@736
    53
        } else { /* Polygon */
nkeynes@736
    54
            int i;
nkeynes@736
    55
            for( i=0; i<6; i++ ) {
nkeynes@736
    56
                if( entry & (0x40000000>>i) ) {
nkeynes@736
    57
                    count++;
nkeynes@736
    58
                }
nkeynes@736
    59
            }
nkeynes@736
    60
        }
nkeynes@222
    61
    }
nkeynes@222
    62
    return count;
nkeynes@222
    63
}
nkeynes@222
    64
nkeynes@653
    65
/**
nkeynes@653
    66
 * Extract a triangle list from the tile (basically indexes into the polygon list, plus
nkeynes@653
    67
 * computing maxz while we go through it
nkeynes@653
    68
 */
nkeynes@653
    69
int sort_extract_triangles( pvraddr_t tile_entry, struct sort_triangle *triangles )
nkeynes@222
    70
{
nkeynes@222
    71
    uint32_t *tile_list = (uint32_t *)(video_base+tile_entry);
nkeynes@862
    72
    int strip_count;
nkeynes@862
    73
    struct polygon_struct *poly;
nkeynes@862
    74
    int count = 0, i;
nkeynes@862
    75
nkeynes@222
    76
    while(1) {
nkeynes@736
    77
        uint32_t entry = *tile_list++;
nkeynes@862
    78
        switch( entry >> 28 ) {
nkeynes@862
    79
        case 0x0F:
nkeynes@862
    80
            return count; // End-of-list
nkeynes@862
    81
        case 0x0E:
nkeynes@862
    82
            tile_list = (uint32_t *)(video_base + (entry&0x007FFFFF));
nkeynes@736
    83
            break;
nkeynes@862
    84
        case 0x08: case 0x09: case 0x0A: case 0x0B:
nkeynes@862
    85
            strip_count = ((entry >> 25) & 0x0F)+1;
nkeynes@862
    86
            poly = pvr2_scene.buf_to_poly_map[entry&0x000FFFFF];
nkeynes@862
    87
            while( strip_count > 0 ) {
nkeynes@862
    88
                assert( poly != NULL );
nkeynes@862
    89
                for( i=0; i<poly->vertex_count-2; i++ ) { 
nkeynes@736
    90
                    triangles[count].poly = poly;
nkeynes@862
    91
                    triangles[count].triangle_num = i;
nkeynes@862
    92
                    triangles[count].maxz = MAX3( pvr2_scene.vertex_array[poly->vertex_index+i].z,
nkeynes@862
    93
                            pvr2_scene.vertex_array[poly->vertex_index+i+1].z,
nkeynes@862
    94
                            pvr2_scene.vertex_array[poly->vertex_index+i+2].z );
nkeynes@736
    95
                    count++;
nkeynes@736
    96
                }
nkeynes@862
    97
                poly = poly->next;
nkeynes@862
    98
                strip_count--;
nkeynes@862
    99
            }
nkeynes@862
   100
            break;
nkeynes@862
   101
        default:
nkeynes@862
   102
            if( entry & 0x7E000000 ) {
nkeynes@862
   103
                poly = pvr2_scene.buf_to_poly_map[entry&0x000FFFFF];
nkeynes@736
   104
                for( i=0; i<6; i++ ) {
nkeynes@736
   105
                    if( entry & (0x40000000>>i) ) {
nkeynes@736
   106
                        triangles[count].poly = poly;
nkeynes@736
   107
                        triangles[count].triangle_num = i;
nkeynes@736
   108
                        triangles[count].maxz = MAX3( pvr2_scene.vertex_array[poly->vertex_index+i].z,
nkeynes@736
   109
                                pvr2_scene.vertex_array[poly->vertex_index+i+1].z,
nkeynes@736
   110
                                pvr2_scene.vertex_array[poly->vertex_index+i+2].z );
nkeynes@736
   111
                        count++;
nkeynes@736
   112
                    }
nkeynes@736
   113
                }
nkeynes@736
   114
            }
nkeynes@736
   115
        }
nkeynes@862
   116
    }       
nkeynes@862
   117
nkeynes@222
   118
}
nkeynes@222
   119
nkeynes@653
   120
void sort_render_triangles( struct sort_triangle *triangles, int num_triangles,
nkeynes@736
   121
                            int render_mode )
nkeynes@222
   122
{
nkeynes@429
   123
    int i;
nkeynes@222
   124
    for( i=0; i<num_triangles; i++ ) {
nkeynes@736
   125
        struct polygon_struct *poly = triangles[i].poly;
nkeynes@736
   126
        if( poly->tex_id != -1 ) {
nkeynes@736
   127
            glBindTexture(GL_TEXTURE_2D, poly->tex_id);
nkeynes@736
   128
        }
nkeynes@865
   129
        render_set_context( poly->context, GL_GEQUAL );
nkeynes@736
   130
        glDepthMask(GL_FALSE);
nkeynes@736
   131
        /* Fix cull direction */
nkeynes@736
   132
        if( triangles[i].triangle_num & 1 ) {
nkeynes@736
   133
            glCullFace(GL_FRONT);
nkeynes@736
   134
        } else {
nkeynes@736
   135
            glCullFace(GL_BACK);
nkeynes@736
   136
        }
nkeynes@736
   137
nkeynes@736
   138
        glDrawArrays(GL_TRIANGLE_STRIP, poly->vertex_index + triangles[i].triangle_num, 3 );
nkeynes@222
   139
    }
nkeynes@222
   140
}
nkeynes@222
   141
nkeynes@429
   142
int compare_triangles( const void *a, const void *b ) 
nkeynes@222
   143
{
nkeynes@653
   144
    const struct sort_triangle *tri1 = a;
nkeynes@653
   145
    const struct sort_triangle *tri2 = b;
nkeynes@653
   146
    return tri2->maxz - tri1->maxz;
nkeynes@222
   147
}
nkeynes@222
   148
nkeynes@653
   149
void sort_triangles( struct sort_triangle *triangles, int num_triangles )
nkeynes@222
   150
{
nkeynes@653
   151
    qsort( triangles, num_triangles, sizeof(struct sort_triangle), compare_triangles );
nkeynes@222
   152
} 
nkeynes@736
   153
nkeynes@653
   154
void render_autosort_tile( pvraddr_t tile_entry, int render_mode ) 
nkeynes@222
   155
{
nkeynes@653
   156
    int num_triangles = sort_count_triangles(tile_entry);
nkeynes@222
   157
    if( num_triangles == 0 ) {
nkeynes@736
   158
        return; /* nothing to do */
nkeynes@222
   159
    } else if( num_triangles == 1 ) { /* Triangle can hardly overlap with itself */
nkeynes@865
   160
        gl_render_tilelist(tile_entry, GL_LEQUAL);
nkeynes@222
   161
    } else { /* Ooh boy here we go... */
nkeynes@736
   162
        struct sort_triangle triangles[num_triangles+1];
nkeynes@736
   163
        // Reserve space for num_triangles / 2 * 4 vertexes (maximum possible number of
nkeynes@736
   164
        // quad vertices)
nkeynes@736
   165
        triangles[num_triangles].poly = (void *)SENTINEL;
nkeynes@736
   166
        int extracted_triangles = sort_extract_triangles(tile_entry, triangles);
nkeynes@736
   167
        assert( extracted_triangles == num_triangles );
nkeynes@736
   168
        sort_triangles( triangles, num_triangles );
nkeynes@736
   169
        sort_render_triangles(triangles, num_triangles, render_mode);
nkeynes@736
   170
        glCullFace(GL_BACK);
nkeynes@736
   171
        assert( triangles[num_triangles].poly == (void *)SENTINEL );
nkeynes@222
   172
    }
nkeynes@222
   173
}
.