Search
lxdream.org :: lxdream/src/pvr2/tileiter.h :: diff
lxdream 0.9.1
released Jun 29
Download Now
filename src/pvr2/tileiter.h
changeset 1145:45674791c6ad
next1151:e1848ca9b5b1
author nkeynes
date Mon Nov 08 14:33:38 2010 +1000 (10 years ago)
permissions -rw-r--r--
last change Introduce tile iterators to simplify processing of the tile lists
file annotate diff log raw
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/src/pvr2/tileiter.h Mon Nov 08 14:33:38 2010 +1000
1.3 @@ -0,0 +1,197 @@
1.4 +/**
1.5 + * $Id$
1.6 + *
1.7 + * Tile iterator ADT. Defines an iterator that can be used to iterate through
1.8 + * a PVR2 tile list a polygon at a time.
1.9 + *
1.10 + * Note: The iterator functions are defined here to allow the compiler to
1.11 + * inline them if it wants to, but it's not always beneficial to do so
1.12 + * (hence we don't force them to be inlined)
1.13 + *
1.14 + * Copyright (c) 2010 Nathan Keynes.
1.15 + *
1.16 + * This program is free software; you can redistribute it and/or modify
1.17 + * it under the terms of the GNU General Public License as published by
1.18 + * the Free Software Foundation; either version 2 of the License, or
1.19 + * (at your option) any later version.
1.20 + *
1.21 + * This program is distributed in the hope that it will be useful,
1.22 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1.23 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1.24 + * GNU General Public License for more details.
1.25 + */
1.26 +
1.27 +#ifndef lxdream_tileiter_H
1.28 +#define lxdream_tileiter_H 1
1.29 +
1.30 +#include <assert.h>
1.31 +#include "pvr2/pvr2.h"
1.32 +
1.33 +#ifdef __cplusplus
1.34 +extern "C" {
1.35 +#endif
1.36 +
1.37 +
1.38 +/**
1.39 + * tileiter: iterator over individual polygons in a tile list.
1.40 + */
1.41 +typedef struct tileiter {
1.42 + uint32_t *ptr;
1.43 + unsigned strip_count;
1.44 + unsigned poly_size;
1.45 + uint32_t poly_addr;
1.46 +} tileiter;
1.47 +
1.48 +
1.49 +#define TILEITER_IS_MODIFIED(it) ((*(it).ptr) & 0x01000000)
1.50 +#define TILEITER_IS_TRIANGLE(it) (((*(it).ptr) >> 29) == 4)
1.51 +#define TILEITER_IS_QUAD(it) (((*(it).ptr) >> 29) == 5)
1.52 +#define TILEITER_IS_POLY(it) (((*(it).ptr) >> 31) == 0)
1.53 +
1.54 +#define TILEITER_POLYADDR(it) ((it).poly_addr)
1.55 +#define TILEITER_STRIPCOUNT(it) ((it).strip_count)
1.56 +#define TILEITER_DONE(it) ((it).ptr == 0)
1.57 +#define TILEITER_BEGIN(it, tileent) (tileiter_init(&it, tileent))
1.58 +#define TILEITER_NEXT(it) (tileiter_next(&it))
1.59 +#define FOREACH_TILE(it, seg) for( TILEITER_BEGIN(it, seg); !TILEITER_DONE(it); TILEITER_NEXT(it) )
1.60 +
1.61 +
1.62 +/**
1.63 + * tileentryiter: iterator over entries in the tile list, where each entry is
1.64 + * a polygon, triangle set, or quad set.
1.65 + */
1.66 +typedef struct tileentryiter {
1.67 + uint32_t *ptr;
1.68 + unsigned strip_count;
1.69 +} tileentryiter;
1.70 +
1.71 +#define TILEENTRYITER_POLYADDR(it) ((*((it).ptr)) & 0x001FFFFF)
1.72 +#define TILEENTRYITER_STRIPCOUNT(it) ((it).strip_count)
1.73 +#define TILEENTRYITER_DONE(it) ((it).ptr == 0)
1.74 +#define TILEENTRYITER_BEGIN(it, tileent) (tileentryiter_init(&(it),tileent))
1.75 +#define TILEENTRYITER_NEXT(it) (tileentryiter_next(&(it)))
1.76 +#define FOREACH_TILEENTRY(it,seg) for( TILEENTRYITER_BEGIN(it,seg); !TILEENTRYITER_DONE(it); TILEENTRYITER_NEXT(it) )
1.77 +
1.78 +/**************************** tileiter functions ****************************/
1.79 +
1.80 +/**
1.81 + * Read the entry pointed to by it->ptr into the tileiter structure. If the
1.82 + * entry if a list pointer or invalid entry, the pointer will first be
1.83 + * updated to the next real entry. On end-of-list, sets ptr to NULL
1.84 + */
1.85 +static void tileiter_read( tileiter *it )
1.86 +{
1.87 + for(;;){
1.88 + uint32_t entry = *it->ptr;
1.89 + uint32_t tag = entry >> 29;
1.90 + if( tag == 0x07 ) {
1.91 + if( tag & 0x10000000 ) {
1.92 + it->ptr = NULL;
1.93 + return;
1.94 + } else {
1.95 + it->ptr = (uint32_t *)(pvr2_main_ram + (entry&0x007FFFFF));
1.96 + it->poly_addr = -1;
1.97 + entry = *it->ptr;
1.98 + }
1.99 + } else if( tag == 6 ) {
1.100 + /* Illegal? Skip */
1.101 + it->ptr++;
1.102 + } else if( tag & 0x04 ) {
1.103 + int vertex_count = tag-1; /* 4 == tri, 5 == quad */
1.104 + int vertex_length = (entry >> 21) & 0x07;
1.105 + if( (entry & 0x01000000) && (pvr2_scene.shadow_mode == SHADOW_FULL) ) {
1.106 + it->poly_size = 5 + (vertex_length<<1) * vertex_count;
1.107 + } else {
1.108 + it->poly_size = 3 + vertex_length * vertex_count;
1.109 + }
1.110 + it->strip_count = ((entry >> 25) & 0x0F);
1.111 + it->poly_addr = entry & 0x001FFFFF;
1.112 + return;
1.113 + } else {
1.114 + /* Other polygon */
1.115 + it->strip_count = 0;
1.116 + it->poly_addr = entry & 0x001FFFFF;
1.117 + return;
1.118 + }
1.119 + }
1.120 +}
1.121 +
1.122 +static void tileiter_init( tileiter *it, uint32_t segptr )
1.123 +{
1.124 + if( IS_TILE_PTR(segptr) ) {
1.125 + it->ptr = (uint32_t *)(pvr2_main_ram + (segptr & 0x007FFFFF));
1.126 + tileiter_read(it);
1.127 + } else {
1.128 + it->ptr = 0;
1.129 + }
1.130 +}
1.131 +
1.132 +static inline void tileiter_next( tileiter *it )
1.133 +{
1.134 + assert( it->ptr != NULL );
1.135 + if( it->strip_count > 0 ) {
1.136 + it->strip_count--;
1.137 + it->poly_addr += it->poly_size;
1.138 + } else {
1.139 + it->ptr++;
1.140 + tileiter_read(it);
1.141 + }
1.142 +}
1.143 +
1.144 +
1.145 +/************************* tileentryiter functions **************************/
1.146 +
1.147 +/**
1.148 + * Read the entry pointed to by it->ptr, updating the pointer to point
1.149 + * to the next real element if the current value is not a polygon entry.
1.150 + */
1.151 +static void tileentryiter_read( tileentryiter *it )
1.152 +{
1.153 + for(;;){
1.154 + uint32_t entry = *it->ptr;
1.155 + uint32_t tag = entry >> 28;
1.156 + if( tag < 0x0C ) {
1.157 + if( tag & 0x08 ) {
1.158 + it->strip_count = ((entry >> 25) & 0x0F);
1.159 + } else {
1.160 + it->strip_count = 0;
1.161 + }
1.162 + return;
1.163 + } else {
1.164 + if( tag == 0x0F ) {
1.165 + it->ptr = NULL;
1.166 + return;
1.167 + } else if( tag == 0x0E ) {
1.168 + it->ptr = (uint32_t *)(pvr2_main_ram + (entry&0x007FFFFF));
1.169 + entry = *it->ptr;
1.170 + } else {
1.171 + /* Illegal? Skip */
1.172 + it->ptr++;
1.173 + }
1.174 + }
1.175 + }
1.176 +}
1.177 +
1.178 +
1.179 +static void tileentryiter_init( tileentryiter *it, uint32_t segptr )
1.180 +{
1.181 + if( IS_TILE_PTR(segptr) ) {
1.182 + it->ptr = (uint32_t *)(pvr2_main_ram + (segptr & 0x007FFFFF));
1.183 + tileentryiter_read(it);
1.184 + } else {
1.185 + it->ptr = 0;
1.186 + }
1.187 +}
1.188 +
1.189 +static void inline tileentryiter_next( tileentryiter *it )
1.190 +{
1.191 + it->ptr++;
1.192 + tileentryiter_read(it);
1.193 +}
1.194 +
1.195 +
1.196 +#ifdef __cplusplus
1.197 +}
1.198 +#endif
1.199 +
1.200 +#endif /* !lxdream_tileiter_H */
.