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 |
|