4 * Tile iterator ADT. Defines an iterator that can be used to iterate through
5 * a PVR2 tile list a polygon at a time.
7 * Note: The iterator functions are defined here to allow the compiler to
8 * inline them if it wants to, but it's not always beneficial to do so
9 * (hence we don't force them to be inlined)
11 * Copyright (c) 2010 Nathan Keynes.
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
24 #ifndef lxdream_tileiter_H
25 #define lxdream_tileiter_H 1
28 #include "pvr2/pvr2.h"
36 * tileiter: iterator over individual polygons in a tile list.
38 typedef struct tileiter {
46 #define TILEITER_IS_MODIFIED(it) ((*(it).ptr) & 0x01000000)
47 #define TILEITER_IS_TRIANGLE(it) (((*(it).ptr) >> 29) == 4)
48 #define TILEITER_IS_QUAD(it) (((*(it).ptr) >> 29) == 5)
49 #define TILEITER_IS_POLY(it) (((*(it).ptr) >> 31) == 0)
51 #define TILEITER_POLYADDR(it) ((it).poly_addr)
52 #define TILEITER_STRIPCOUNT(it) ((it).strip_count)
53 #define TILEITER_DONE(it) ((it).ptr == 0)
54 #define TILEITER_BEGIN(it, tileent) (tileiter_init(&it, tileent))
55 #define TILEITER_NEXT(it) (tileiter_next(&it))
56 #define FOREACH_TILE(it, seg) for( TILEITER_BEGIN(it, seg); !TILEITER_DONE(it); TILEITER_NEXT(it) )
60 * tileentryiter: iterator over entries in the tile list, where each entry is
61 * a polygon, triangle set, or quad set.
63 typedef struct tileentryiter {
68 #define TILEENTRYITER_POLYADDR(it) ((*((it).ptr)) & 0x001FFFFF)
69 #define TILEENTRYITER_STRIPCOUNT(it) ((it).strip_count)
70 #define TILEENTRYITER_DONE(it) ((it).ptr == 0)
71 #define TILEENTRYITER_BEGIN(it, tileent) (tileentryiter_init(&(it),tileent))
72 #define TILEENTRYITER_NEXT(it) (tileentryiter_next(&(it)))
73 #define FOREACH_TILEENTRY(it,seg) for( TILEENTRYITER_BEGIN(it,seg); !TILEENTRYITER_DONE(it); TILEENTRYITER_NEXT(it) )
75 /**************************** tileiter functions ****************************/
78 * Read the entry pointed to by it->ptr into the tileiter structure. If the
79 * entry if a list pointer or invalid entry, the pointer will first be
80 * updated to the next real entry. On end-of-list, sets ptr to NULL
82 static void tileiter_read( tileiter *it )
85 uint32_t entry = *it->ptr;
86 uint32_t tag = entry >> 29;
88 if( tag & 0x10000000 ) {
92 it->ptr = (uint32_t *)(pvr2_main_ram + (entry&0x007FFFFF));
96 } else if( tag == 6 ) {
99 } else if( tag & 0x04 ) {
100 int vertex_count = tag-1; /* 4 == tri, 5 == quad */
101 int vertex_length = (entry >> 21) & 0x07;
102 if( (entry & 0x01000000) && (pvr2_scene.shadow_mode == SHADOW_FULL) ) {
103 it->poly_size = 5 + (vertex_length<<1) * vertex_count;
105 it->poly_size = 3 + vertex_length * vertex_count;
107 it->strip_count = ((entry >> 25) & 0x0F);
108 it->poly_addr = entry & 0x001FFFFF;
113 it->poly_addr = entry & 0x001FFFFF;
119 static void tileiter_init( tileiter *it, uint32_t segptr )
121 if( IS_TILE_PTR(segptr) ) {
122 it->ptr = (uint32_t *)(pvr2_main_ram + (segptr & 0x007FFFFF));
129 static inline void tileiter_next( tileiter *it )
131 assert( it->ptr != NULL );
132 if( it->strip_count > 0 ) {
134 it->poly_addr += it->poly_size;
142 /************************* tileentryiter functions **************************/
145 * Read the entry pointed to by it->ptr, updating the pointer to point
146 * to the next real element if the current value is not a polygon entry.
148 static void tileentryiter_read( tileentryiter *it )
151 uint32_t entry = *it->ptr;
152 uint32_t tag = entry >> 28;
155 it->strip_count = ((entry >> 25) & 0x0F);
164 } else if( tag == 0x0E ) {
165 it->ptr = (uint32_t *)(pvr2_main_ram + (entry&0x007FFFFF));
176 static void tileentryiter_init( tileentryiter *it, uint32_t segptr )
178 if( IS_TILE_PTR(segptr) ) {
179 it->ptr = (uint32_t *)(pvr2_main_ram + (segptr & 0x007FFFFF));
180 tileentryiter_read(it);
186 static void inline tileentryiter_next( tileentryiter *it )
189 tileentryiter_read(it);
197 #endif /* !lxdream_tileiter_H */
.