filename | src/pvr2/tileiter.h |
changeset | 1153:00e507e4025c |
prev | 1151:e1848ca9b5b1 |
next | 1298:d0eb2307b847 |
author | nkeynes |
date | Mon Dec 12 21:15:44 2011 +1000 (12 years ago) |
permissions | -rw-r--r-- |
last change | Handle branch delay-slot instruction that falls on the next page correctly. - Generate the right end PC in the first place (sh4trans.c) - Allow blocks to be marked as both entry point + continuation, and specifically handle invalidation when first entry of a page is a continuation == flush previous page as well. |
view | annotate | diff | log | raw |
1 /**
2 * $Id$
3 *
4 * Tile iterator ADT. Defines an iterator that can be used to iterate through
5 * a PVR2 tile list a polygon at a time.
6 *
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)
10 *
11 * Copyright (c) 2010 Nathan Keynes.
12 *
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.
17 *
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.
22 */
24 #ifndef lxdream_tileiter_H
25 #define lxdream_tileiter_H 1
27 #include <assert.h>
28 #include "pvr2/pvr2.h"
30 #ifdef __cplusplus
31 extern "C" {
32 #endif
35 /**
36 * tileiter: iterator over individual polygons in a tile list.
37 */
38 typedef struct tileiter {
39 uint32_t *ptr;
40 unsigned strip_count;
41 unsigned poly_size;
42 uint32_t poly_addr;
43 } 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) )
59 /**
60 * tileentryiter: iterator over entries in the tile list, where each entry is
61 * a polygon, triangle set, or quad set.
62 */
63 typedef struct tileentryiter {
64 uint32_t *ptr;
65 unsigned strip_count;
66 } 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 ****************************/
77 /**
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
81 */
82 static void tileiter_read( tileiter *it )
83 {
84 for(;;){
85 uint32_t entry = *it->ptr;
86 uint32_t tag = entry >> 29;
87 if( tag == 0x07 ) {
88 if( tag & 0x10000000 ) {
89 it->ptr = NULL;
90 return;
91 } else {
92 it->ptr = (uint32_t *)(pvr2_main_ram + (entry&0x007FFFFF));
93 it->poly_addr = -1;
94 entry = *it->ptr;
95 }
96 } else if( tag == 6 ) {
97 /* Illegal? Skip */
98 it->ptr++;
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;
104 } else {
105 it->poly_size = 3 + vertex_length * vertex_count;
106 }
107 it->strip_count = ((entry >> 25) & 0x0F);
108 it->poly_addr = entry & 0x001FFFFF;
109 return;
110 } else {
111 /* Other polygon */
112 it->strip_count = 0;
113 it->poly_addr = entry & 0x001FFFFF;
114 return;
115 }
116 }
117 }
119 static void tileiter_init( tileiter *it, uint32_t segptr )
120 {
121 if( IS_TILE_PTR(segptr) ) {
122 it->ptr = (uint32_t *)(pvr2_main_ram + (segptr & 0x007FFFFF));
123 tileiter_read(it);
124 } else {
125 it->ptr = 0;
126 }
127 }
129 static inline void tileiter_next( tileiter *it )
130 {
131 assert( it->ptr != NULL );
132 if( it->strip_count > 0 ) {
133 it->strip_count--;
134 it->poly_addr += it->poly_size;
135 } else {
136 it->ptr++;
137 tileiter_read(it);
138 }
139 }
142 /************************* tileentryiter functions **************************/
144 /**
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.
147 */
148 static void tileentryiter_read( tileentryiter *it )
149 {
150 for(;;){
151 uint32_t entry = *it->ptr;
152 uint32_t tag = entry >> 28;
153 if( tag < 0x0C ) {
154 if( tag & 0x08 ) {
155 it->strip_count = ((entry >> 25) & 0x0F);
156 } else {
157 it->strip_count = 0;
158 }
159 return;
160 } else {
161 if( tag == 0x0F ) {
162 it->ptr = NULL;
163 return;
164 } else if( tag == 0x0E ) {
165 it->ptr = (uint32_t *)(pvr2_main_ram + (entry&0x007FFFFF));
166 entry = *it->ptr;
167 } else {
168 /* Illegal? Skip */
169 it->ptr++;
170 }
171 }
172 }
173 }
176 static void tileentryiter_init( tileentryiter *it, uint32_t segptr )
177 {
178 if( IS_TILE_PTR(segptr) ) {
179 it->ptr = (uint32_t *)(pvr2_main_ram + (segptr & 0x007FFFFF));
180 tileentryiter_read(it);
181 } else {
182 it->ptr = 0;
183 }
184 }
186 static void inline tileentryiter_next( tileentryiter *it )
187 {
188 it->ptr++;
189 tileentryiter_read(it);
190 }
193 #ifdef __cplusplus
194 }
195 #endif
197 #endif /* !lxdream_tileiter_H */
.