Search
lxdream.org :: lxdream/src/pvr2/untile.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/pvr2/untile.c
changeset 1151:e1848ca9b5b1
author nkeynes
date Wed Dec 08 18:33:23 2010 +1000 (13 years ago)
permissions -rw-r--r--
last change Updated pt_BR translation from Arthonis
file annotate diff log raw
nkeynes@1151
     1
/**
nkeynes@1151
     2
 * $Id$
nkeynes@1151
     3
 *
nkeynes@1151
     4
 * Process the tile + polygon data to extract a list of polygons that can
nkeynes@1151
     5
 * be rendered directly without tiling.
nkeynes@1151
     6
 *
nkeynes@1151
     7
 * Copyright (c) 2010 Nathan Keynes.
nkeynes@1151
     8
 *
nkeynes@1151
     9
 * This program is free software; you can redistribute it and/or modify
nkeynes@1151
    10
 * it under the terms of the GNU General Public License as published by
nkeynes@1151
    11
 * the Free Software Foundation; either version 2 of the License, or
nkeynes@1151
    12
 * (at your option) any later version.
nkeynes@1151
    13
 *
nkeynes@1151
    14
 * This program is distributed in the hope that it will be useful,
nkeynes@1151
    15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
nkeynes@1151
    16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
nkeynes@1151
    17
 * GNU General Public License for more details.
nkeynes@1151
    18
 */
nkeynes@1151
    19
nkeynes@1151
    20
#include <stdlib.h>
nkeynes@1151
    21
#include "pvr2/pvr2.h"
nkeynes@1151
    22
#include "pvr2/scene.h"
nkeynes@1151
    23
#include "pvr2/tileiter.h"
nkeynes@1151
    24
nkeynes@1151
    25
static int sort_polydata( const void *a, const void *b )
nkeynes@1151
    26
{
nkeynes@1151
    27
    uint32_t idxa = *(const uint32_t*)a;
nkeynes@1151
    28
    uint32_t idxb = *(const uint32_t*)b;
nkeynes@1151
    29
    return pvr2_scene.poly_array[idxa].context - pvr2_scene.poly_array[idxb].context;
nkeynes@1151
    30
}
nkeynes@1151
    31
nkeynes@1151
    32
gboolean untile_list( struct tile_segment *segment, int pass, int list )
nkeynes@1151
    33
{
nkeynes@1151
    34
    int tile_width = pvr2_scene.buffer_width >> 5;
nkeynes@1151
    35
    int tile_height = pvr2_scene.buffer_height >> 5;
nkeynes@1151
    36
    tileiter tile_map[tile_width][tile_height];
nkeynes@1151
    37
nkeynes@1151
    38
    memset(tile_map, 0, tile_width*tile_height*sizeof(uint32_t *));
nkeynes@1151
    39
nkeynes@1151
    40
    /* 1. Construct the tile map for the last/pass */
nkeynes@1151
    41
    int last_x = -1, last_y = -1, tile_pass;
nkeynes@1151
    42
    do {
nkeynes@1151
    43
        int tile_x = SEGMENT_X(segment->control);
nkeynes@1151
    44
        int tile_y = SEGMENT_Y(segment->control);
nkeynes@1151
    45
        if( last_x == tile_x && last_y == tile_y ) {
nkeynes@1151
    46
            tile_pass++;
nkeynes@1151
    47
        } else {
nkeynes@1151
    48
            tile_pass = 0;
nkeynes@1151
    49
            last_x = tile_x;
nkeynes@1151
    50
            last_y = tile_y;
nkeynes@1151
    51
        }
nkeynes@1151
    52
nkeynes@1151
    53
        if( tile_pass == pass ) {
nkeynes@1151
    54
            uint32_t ptr = ((uint32_t *)segment)[list+1];
nkeynes@1151
    55
            if( IS_TILE_PTR(ptr) )
nkeynes@1151
    56
                TILEITER_BEGIN(tile_map[tile_x][tile_y], ptr);
nkeynes@1151
    57
        }
nkeynes@1151
    58
    } while( !IS_LAST_SEGMENT(segment++) );
nkeynes@1151
    59
nkeynes@1151
    60
    /* 2. Extract the polygon list, sorted by appearance. We assume the list
nkeynes@1151
    61
     * can be sorted by address, which makes this a lot simpler/faster.
nkeynes@1151
    62
     */
nkeynes@1151
    63
    uint32_t poly_present[pvr2_scene.poly_count];
nkeynes@1151
    64
    memset( poly_present, 0, sizeof(poly_present) );
nkeynes@1151
    65
    unsigned x,y, i, j, poly_count = 0;
nkeynes@1151
    66
    for( x = 0; x < tile_width; x++ ) {
nkeynes@1151
    67
        for( y = 0; y < tile_height; y++ ) {
nkeynes@1151
    68
            tileiter list = tile_map[x][y];
nkeynes@1151
    69
            while( !TILEITER_DONE(list) ) {
nkeynes@1151
    70
                struct polygon_struct *poly = pvr2_scene.buf_to_poly_map[TILEITER_POLYADDR(list)];
nkeynes@1151
    71
                if( poly ) {
nkeynes@1151
    72
                    poly_present[POLY_NO(poly)] = 1;
nkeynes@1151
    73
                }
nkeynes@1151
    74
                TILEITER_NEXT(list);
nkeynes@1151
    75
            }
nkeynes@1151
    76
        }
nkeynes@1151
    77
    }
nkeynes@1151
    78
    /* Collapse array into a set of polygon indexes and then sort it */
nkeynes@1151
    79
    for( x=0; x<pvr2_scene.poly_count; x++ ) {
nkeynes@1151
    80
        if( poly_present[x] ) {
nkeynes@1151
    81
            poly_present[poly_count++] = x;
nkeynes@1151
    82
        }
nkeynes@1151
    83
    }
nkeynes@1151
    84
    qsort(poly_present, poly_count, sizeof(uint32_t), sort_polydata);
nkeynes@1151
    85
nkeynes@1151
    86
    /* 3. Process each polygon in the list. Extract the bounds, and check
nkeynes@1151
    87
     * each tile in which it should appear - if missing, the poly is clipped
nkeynes@1151
    88
     * (and we need to construct appropriate bounds).
nkeynes@1151
    89
     */
nkeynes@1151
    90
    for( i=0; i<poly_count; i++ ) {
nkeynes@1151
    91
        struct tile_bounds poly_bounds = {tile_width, tile_height, -1, -1};
nkeynes@1151
    92
        struct tile_bounds clip_bounds = {0, 0, tile_width, tile_height};
nkeynes@1151
    93
        struct polygon_struct *poly = &pvr2_scene.poly_array[poly_present[i]];
nkeynes@1151
    94
        uint32_t poly_addr = poly->context - ((uint32_t *)pvr2_main_ram);
nkeynes@1151
    95
        do {
nkeynes@1151
    96
            /* Extract tile bounds for the poly - we assume (since we have the
nkeynes@1151
    97
             * polygon at all) that it appears correctly in at least one tile.
nkeynes@1151
    98
             */
nkeynes@1151
    99
            struct vertex_struct *vert = &pvr2_scene.vertex_array[poly->vertex_index];
nkeynes@1151
   100
            for( j=0; j<poly->vertex_count; j++ ) {
nkeynes@1151
   101
                int tx, ty;
nkeynes@1151
   102
                if( vert[j].x < 0 ) tx = 0;
nkeynes@1151
   103
                else if( vert[j].x >= pvr2_scene.buffer_width ) tx = tile_width-1;
nkeynes@1151
   104
                else tx = ((int)vert[j].x)>>5;
nkeynes@1151
   105
                if( tx < poly_bounds.x1 ) poly_bounds.x1 = tx;
nkeynes@1151
   106
                if( tx > poly_bounds.x2 ) poly_bounds.x2 = tx;
nkeynes@1151
   107
                if( vert[j].y < 0 ) ty = 0;
nkeynes@1151
   108
                else if( vert[j].y >= pvr2_scene.buffer_height ) ty = tile_height-1;
nkeynes@1151
   109
                else ty = ((int)vert[j].y)>>5;
nkeynes@1151
   110
                if( ty < poly_bounds.y1 ) poly_bounds.y1 = ty;
nkeynes@1151
   111
                if( ty > poly_bounds.y2 ) poly_bounds.y2 = ty;
nkeynes@1151
   112
            }
nkeynes@1151
   113
            poly = poly->sub_next;
nkeynes@1151
   114
        } while( poly != NULL );
nkeynes@1151
   115
        if( poly_bounds.x1 == tile_width ) {
nkeynes@1151
   116
            continue; /* Polygon has been culled */
nkeynes@1151
   117
        }
nkeynes@1151
   118
nkeynes@1151
   119
        gl_render_poly(&pvr2_scene.poly_array[poly_present[i]], TRUE);
nkeynes@1151
   120
#if 0
nkeynes@1151
   121
        /* Search the tile map for the polygon */
nkeynes@1151
   122
        for( x = poly_bounds.x1; x <= poly_bounds.x2; x++ ) {
nkeynes@1151
   123
            for( y = poly_bounds.y1; y <= poly_bounds.y2; y++ ) {
nkeynes@1151
   124
                tileiter *list = &tile_map[x][y];
nkeynes@1151
   125
nkeynes@1151
   126
nkeynes@1151
   127
                /* Skip over earlier entries in the list, if any (can happen if
nkeynes@1151
   128
                 * we culled something, or had an empty polygon
nkeynes@1151
   129
                 */
nkeynes@1151
   130
                while( !TILEITER_DONE(*list) && TILEITER_POLYADDR(*list) < poly_addr )
nkeynes@1151
   131
                    TILEITER_NEXT(*list);
nkeynes@1151
   132
                if( TILEITER_POLYADDR(*list) == poly_addr ) {
nkeynes@1151
   133
                    /* Match */
nkeynes@1151
   134
                } else {
nkeynes@1151
   135
                    /* Clipped */
nkeynes@1151
   136
                }
nkeynes@1151
   137
            }
nkeynes@1151
   138
        }
nkeynes@1151
   139
#endif
nkeynes@1151
   140
    }
nkeynes@1151
   141
}
nkeynes@1151
   142
nkeynes@1151
   143
.