Search
lxdream.org :: lxdream/src/pvr2/rendsort.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/pvr2/rendsort.c
changeset 736:a02d1475ccfd
prev669:ab344e42bca9
next862:d3b2066d5daa
author nkeynes
date Wed Jul 30 22:50:44 2008 +0000 (15 years ago)
permissions -rw-r--r--
last change Bug #61: OpenBSD support
(Modified) patch from bsdmaniak, thanks!
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@222
    72
    int count = 0;
nkeynes@222
    73
    while(1) {
nkeynes@736
    74
        uint32_t entry = *tile_list++;
nkeynes@736
    75
        if( entry >> 28 == 0x0F ) {
nkeynes@736
    76
            break;
nkeynes@736
    77
        } else if( entry >> 28 == 0x0E ) {
nkeynes@736
    78
            tile_list = (uint32_t *)(video_base+(entry&0x007FFFFF));
nkeynes@736
    79
        } else {
nkeynes@736
    80
            uint32_t poly_addr = entry & 0x000FFFFF;
nkeynes@736
    81
            int is_modified = entry & 0x01000000;
nkeynes@736
    82
            int vertex_length = (entry >> 21) & 0x07;
nkeynes@736
    83
            int context_length = 3;
nkeynes@736
    84
            if( is_modified && pvr2_scene.full_shadow ) {
nkeynes@736
    85
                context_length = 5;
nkeynes@736
    86
                vertex_length *= 2 ;
nkeynes@736
    87
            }
nkeynes@736
    88
            vertex_length += 3;
nkeynes@222
    89
nkeynes@736
    90
            if( (entry & 0xE0000000) == 0x80000000 ) {
nkeynes@736
    91
                /* Triangle(s) */
nkeynes@736
    92
                int strip_count = ((entry >> 25) & 0x0F)+1;
nkeynes@736
    93
                int polygon_length = 3 * vertex_length + context_length;
nkeynes@736
    94
                int i;
nkeynes@736
    95
                for( i=0; i<strip_count; i++ ) {
nkeynes@736
    96
                    struct polygon_struct *poly = pvr2_scene.buf_to_poly_map[poly_addr];
nkeynes@736
    97
                    triangles[count].poly = poly;
nkeynes@736
    98
                    triangles[count].triangle_num = 0;
nkeynes@736
    99
                    triangles[count].maxz = MAX3( pvr2_scene.vertex_array[poly->vertex_index].z,
nkeynes@736
   100
                            pvr2_scene.vertex_array[poly->vertex_index+1].z,
nkeynes@736
   101
                            pvr2_scene.vertex_array[poly->vertex_index+2].z );
nkeynes@736
   102
                    poly_addr += polygon_length;
nkeynes@736
   103
                    count++;
nkeynes@736
   104
                }
nkeynes@736
   105
            } else if( (entry & 0xE0000000) == 0xA0000000 ) {
nkeynes@736
   106
                /* Quad(s) */
nkeynes@736
   107
                int strip_count = ((entry >> 25) & 0x0F)+1;
nkeynes@736
   108
                int polygon_length = 4 * vertex_length + context_length;
nkeynes@736
   109
                int i;
nkeynes@736
   110
                for( i=0; i<strip_count; i++ ) {
nkeynes@736
   111
                    struct polygon_struct *poly = pvr2_scene.buf_to_poly_map[poly_addr];
nkeynes@736
   112
                    triangles[count].poly = poly;
nkeynes@736
   113
                    triangles[count].triangle_num = 0;
nkeynes@736
   114
                    triangles[count].maxz = MAX3( pvr2_scene.vertex_array[poly->vertex_index].z,
nkeynes@736
   115
                            pvr2_scene.vertex_array[poly->vertex_index+1].z,
nkeynes@736
   116
                            pvr2_scene.vertex_array[poly->vertex_index+2].z );
nkeynes@736
   117
                    count++;
nkeynes@736
   118
                    triangles[count].poly = poly;
nkeynes@736
   119
                    triangles[count].triangle_num = 1;
nkeynes@736
   120
                    triangles[count].maxz = MAX3( pvr2_scene.vertex_array[poly->vertex_index+1].z,
nkeynes@736
   121
                            pvr2_scene.vertex_array[poly->vertex_index+2].z,
nkeynes@736
   122
                            pvr2_scene.vertex_array[poly->vertex_index+3].z );
nkeynes@736
   123
                    count++;
nkeynes@736
   124
                    poly_addr += polygon_length;
nkeynes@736
   125
                }
nkeynes@736
   126
            } else {
nkeynes@736
   127
                /* Polygon */
nkeynes@736
   128
                int i;
nkeynes@736
   129
                struct polygon_struct *poly = pvr2_scene.buf_to_poly_map[poly_addr];
nkeynes@736
   130
                for( i=0; i<6; i++ ) {
nkeynes@736
   131
                    if( entry & (0x40000000>>i) ) {
nkeynes@736
   132
                        triangles[count].poly = poly;
nkeynes@736
   133
                        triangles[count].triangle_num = i;
nkeynes@736
   134
                        triangles[count].maxz = MAX3( pvr2_scene.vertex_array[poly->vertex_index+i].z,
nkeynes@736
   135
                                pvr2_scene.vertex_array[poly->vertex_index+i+1].z,
nkeynes@736
   136
                                pvr2_scene.vertex_array[poly->vertex_index+i+2].z );
nkeynes@736
   137
                        count++;
nkeynes@736
   138
                    }
nkeynes@736
   139
                }
nkeynes@736
   140
            }
nkeynes@736
   141
        }
nkeynes@222
   142
    }
nkeynes@653
   143
    return count;
nkeynes@222
   144
}
nkeynes@222
   145
nkeynes@653
   146
void sort_render_triangles( struct sort_triangle *triangles, int num_triangles,
nkeynes@736
   147
                            int render_mode )
nkeynes@222
   148
{
nkeynes@429
   149
    int i;
nkeynes@222
   150
    for( i=0; i<num_triangles; i++ ) {
nkeynes@736
   151
        struct polygon_struct *poly = triangles[i].poly;
nkeynes@736
   152
        if( poly->tex_id != -1 ) {
nkeynes@736
   153
            glBindTexture(GL_TEXTURE_2D, poly->tex_id);
nkeynes@736
   154
        }
nkeynes@736
   155
        render_set_context( poly->context, RENDER_NORMAL );
nkeynes@736
   156
        glDepthMask(GL_FALSE);
nkeynes@736
   157
        glDepthFunc(GL_GEQUAL);
nkeynes@736
   158
        /* Fix cull direction */
nkeynes@736
   159
        if( triangles[i].triangle_num & 1 ) {
nkeynes@736
   160
            glCullFace(GL_FRONT);
nkeynes@736
   161
        } else {
nkeynes@736
   162
            glCullFace(GL_BACK);
nkeynes@736
   163
        }
nkeynes@736
   164
nkeynes@736
   165
        glDrawArrays(GL_TRIANGLE_STRIP, poly->vertex_index + triangles[i].triangle_num, 3 );
nkeynes@222
   166
    }
nkeynes@222
   167
}
nkeynes@222
   168
nkeynes@429
   169
int compare_triangles( const void *a, const void *b ) 
nkeynes@222
   170
{
nkeynes@653
   171
    const struct sort_triangle *tri1 = a;
nkeynes@653
   172
    const struct sort_triangle *tri2 = b;
nkeynes@653
   173
    return tri2->maxz - tri1->maxz;
nkeynes@222
   174
}
nkeynes@222
   175
nkeynes@653
   176
void sort_triangles( struct sort_triangle *triangles, int num_triangles )
nkeynes@222
   177
{
nkeynes@653
   178
    qsort( triangles, num_triangles, sizeof(struct sort_triangle), compare_triangles );
nkeynes@222
   179
} 
nkeynes@736
   180
nkeynes@653
   181
void render_autosort_tile( pvraddr_t tile_entry, int render_mode ) 
nkeynes@222
   182
{
nkeynes@653
   183
    int num_triangles = sort_count_triangles(tile_entry);
nkeynes@222
   184
    if( num_triangles == 0 ) {
nkeynes@736
   185
        return; /* nothing to do */
nkeynes@222
   186
    } else if( num_triangles == 1 ) { /* Triangle can hardly overlap with itself */
nkeynes@736
   187
        gl_render_tilelist(tile_entry);
nkeynes@222
   188
    } else { /* Ooh boy here we go... */
nkeynes@736
   189
        struct sort_triangle triangles[num_triangles+1];
nkeynes@736
   190
        // Reserve space for num_triangles / 2 * 4 vertexes (maximum possible number of
nkeynes@736
   191
        // quad vertices)
nkeynes@736
   192
        triangles[num_triangles].poly = (void *)SENTINEL;
nkeynes@736
   193
        int extracted_triangles = sort_extract_triangles(tile_entry, triangles);
nkeynes@736
   194
        assert( extracted_triangles == num_triangles );
nkeynes@736
   195
        sort_triangles( triangles, num_triangles );
nkeynes@736
   196
        sort_render_triangles(triangles, num_triangles, render_mode);
nkeynes@736
   197
        glCullFace(GL_BACK);
nkeynes@736
   198
        assert( triangles[num_triangles].poly == (void *)SENTINEL );
nkeynes@222
   199
    }
nkeynes@222
   200
}
.