Search
lxdream.org :: lxdream/src/pvr2/untile.c :: diff
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 (9 years ago)
permissions -rw-r--r--
last change Updated pt_BR translation from Arthonis
file annotate diff log raw
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/src/pvr2/untile.c Wed Dec 08 18:33:23 2010 +1000
1.3 @@ -0,0 +1,143 @@
1.4 +/**
1.5 + * $Id$
1.6 + *
1.7 + * Process the tile + polygon data to extract a list of polygons that can
1.8 + * be rendered directly without tiling.
1.9 + *
1.10 + * Copyright (c) 2010 Nathan Keynes.
1.11 + *
1.12 + * This program is free software; you can redistribute it and/or modify
1.13 + * it under the terms of the GNU General Public License as published by
1.14 + * the Free Software Foundation; either version 2 of the License, or
1.15 + * (at your option) any later version.
1.16 + *
1.17 + * This program is distributed in the hope that it will be useful,
1.18 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1.19 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1.20 + * GNU General Public License for more details.
1.21 + */
1.22 +
1.23 +#include <stdlib.h>
1.24 +#include "pvr2/pvr2.h"
1.25 +#include "pvr2/scene.h"
1.26 +#include "pvr2/tileiter.h"
1.27 +
1.28 +static int sort_polydata( const void *a, const void *b )
1.29 +{
1.30 + uint32_t idxa = *(const uint32_t*)a;
1.31 + uint32_t idxb = *(const uint32_t*)b;
1.32 + return pvr2_scene.poly_array[idxa].context - pvr2_scene.poly_array[idxb].context;
1.33 +}
1.34 +
1.35 +gboolean untile_list( struct tile_segment *segment, int pass, int list )
1.36 +{
1.37 + int tile_width = pvr2_scene.buffer_width >> 5;
1.38 + int tile_height = pvr2_scene.buffer_height >> 5;
1.39 + tileiter tile_map[tile_width][tile_height];
1.40 +
1.41 + memset(tile_map, 0, tile_width*tile_height*sizeof(uint32_t *));
1.42 +
1.43 + /* 1. Construct the tile map for the last/pass */
1.44 + int last_x = -1, last_y = -1, tile_pass;
1.45 + do {
1.46 + int tile_x = SEGMENT_X(segment->control);
1.47 + int tile_y = SEGMENT_Y(segment->control);
1.48 + if( last_x == tile_x && last_y == tile_y ) {
1.49 + tile_pass++;
1.50 + } else {
1.51 + tile_pass = 0;
1.52 + last_x = tile_x;
1.53 + last_y = tile_y;
1.54 + }
1.55 +
1.56 + if( tile_pass == pass ) {
1.57 + uint32_t ptr = ((uint32_t *)segment)[list+1];
1.58 + if( IS_TILE_PTR(ptr) )
1.59 + TILEITER_BEGIN(tile_map[tile_x][tile_y], ptr);
1.60 + }
1.61 + } while( !IS_LAST_SEGMENT(segment++) );
1.62 +
1.63 + /* 2. Extract the polygon list, sorted by appearance. We assume the list
1.64 + * can be sorted by address, which makes this a lot simpler/faster.
1.65 + */
1.66 + uint32_t poly_present[pvr2_scene.poly_count];
1.67 + memset( poly_present, 0, sizeof(poly_present) );
1.68 + unsigned x,y, i, j, poly_count = 0;
1.69 + for( x = 0; x < tile_width; x++ ) {
1.70 + for( y = 0; y < tile_height; y++ ) {
1.71 + tileiter list = tile_map[x][y];
1.72 + while( !TILEITER_DONE(list) ) {
1.73 + struct polygon_struct *poly = pvr2_scene.buf_to_poly_map[TILEITER_POLYADDR(list)];
1.74 + if( poly ) {
1.75 + poly_present[POLY_NO(poly)] = 1;
1.76 + }
1.77 + TILEITER_NEXT(list);
1.78 + }
1.79 + }
1.80 + }
1.81 + /* Collapse array into a set of polygon indexes and then sort it */
1.82 + for( x=0; x<pvr2_scene.poly_count; x++ ) {
1.83 + if( poly_present[x] ) {
1.84 + poly_present[poly_count++] = x;
1.85 + }
1.86 + }
1.87 + qsort(poly_present, poly_count, sizeof(uint32_t), sort_polydata);
1.88 +
1.89 + /* 3. Process each polygon in the list. Extract the bounds, and check
1.90 + * each tile in which it should appear - if missing, the poly is clipped
1.91 + * (and we need to construct appropriate bounds).
1.92 + */
1.93 + for( i=0; i<poly_count; i++ ) {
1.94 + struct tile_bounds poly_bounds = {tile_width, tile_height, -1, -1};
1.95 + struct tile_bounds clip_bounds = {0, 0, tile_width, tile_height};
1.96 + struct polygon_struct *poly = &pvr2_scene.poly_array[poly_present[i]];
1.97 + uint32_t poly_addr = poly->context - ((uint32_t *)pvr2_main_ram);
1.98 + do {
1.99 + /* Extract tile bounds for the poly - we assume (since we have the
1.100 + * polygon at all) that it appears correctly in at least one tile.
1.101 + */
1.102 + struct vertex_struct *vert = &pvr2_scene.vertex_array[poly->vertex_index];
1.103 + for( j=0; j<poly->vertex_count; j++ ) {
1.104 + int tx, ty;
1.105 + if( vert[j].x < 0 ) tx = 0;
1.106 + else if( vert[j].x >= pvr2_scene.buffer_width ) tx = tile_width-1;
1.107 + else tx = ((int)vert[j].x)>>5;
1.108 + if( tx < poly_bounds.x1 ) poly_bounds.x1 = tx;
1.109 + if( tx > poly_bounds.x2 ) poly_bounds.x2 = tx;
1.110 + if( vert[j].y < 0 ) ty = 0;
1.111 + else if( vert[j].y >= pvr2_scene.buffer_height ) ty = tile_height-1;
1.112 + else ty = ((int)vert[j].y)>>5;
1.113 + if( ty < poly_bounds.y1 ) poly_bounds.y1 = ty;
1.114 + if( ty > poly_bounds.y2 ) poly_bounds.y2 = ty;
1.115 + }
1.116 + poly = poly->sub_next;
1.117 + } while( poly != NULL );
1.118 + if( poly_bounds.x1 == tile_width ) {
1.119 + continue; /* Polygon has been culled */
1.120 + }
1.121 +
1.122 + gl_render_poly(&pvr2_scene.poly_array[poly_present[i]], TRUE);
1.123 +#if 0
1.124 + /* Search the tile map for the polygon */
1.125 + for( x = poly_bounds.x1; x <= poly_bounds.x2; x++ ) {
1.126 + for( y = poly_bounds.y1; y <= poly_bounds.y2; y++ ) {
1.127 + tileiter *list = &tile_map[x][y];
1.128 +
1.129 +
1.130 + /* Skip over earlier entries in the list, if any (can happen if
1.131 + * we culled something, or had an empty polygon
1.132 + */
1.133 + while( !TILEITER_DONE(*list) && TILEITER_POLYADDR(*list) < poly_addr )
1.134 + TILEITER_NEXT(*list);
1.135 + if( TILEITER_POLYADDR(*list) == poly_addr ) {
1.136 + /* Match */
1.137 + } else {
1.138 + /* Clipped */
1.139 + }
1.140 + }
1.141 + }
1.142 +#endif
1.143 + }
1.144 +}
1.145 +
1.146 +
.