filename | src/pvr2/tileiter.h |
changeset | 1153:00e507e4025c |
prev | 1151:e1848ca9b5b1 |
next | 1298:d0eb2307b847 |
author | nkeynes |
date | Wed Feb 15 17:54:51 2012 +1000 (12 years ago) |
permissions | -rw-r--r-- |
last change | Use GL_TEXTURE_2D instead of GL_TEXTURE_RECTANGLE_ARB for frame buffers, for systems that don't provide the latter (and there's not really much difference anyway). Add macro wrangling for GL_DEPTH24_STENCIL8 format |
file | annotate | diff | log | raw |
nkeynes@1145 | 1 | /** |
nkeynes@1145 | 2 | * $Id$ |
nkeynes@1145 | 3 | * |
nkeynes@1145 | 4 | * Tile iterator ADT. Defines an iterator that can be used to iterate through |
nkeynes@1145 | 5 | * a PVR2 tile list a polygon at a time. |
nkeynes@1145 | 6 | * |
nkeynes@1145 | 7 | * Note: The iterator functions are defined here to allow the compiler to |
nkeynes@1145 | 8 | * inline them if it wants to, but it's not always beneficial to do so |
nkeynes@1145 | 9 | * (hence we don't force them to be inlined) |
nkeynes@1145 | 10 | * |
nkeynes@1145 | 11 | * Copyright (c) 2010 Nathan Keynes. |
nkeynes@1145 | 12 | * |
nkeynes@1145 | 13 | * This program is free software; you can redistribute it and/or modify |
nkeynes@1145 | 14 | * it under the terms of the GNU General Public License as published by |
nkeynes@1145 | 15 | * the Free Software Foundation; either version 2 of the License, or |
nkeynes@1145 | 16 | * (at your option) any later version. |
nkeynes@1145 | 17 | * |
nkeynes@1145 | 18 | * This program is distributed in the hope that it will be useful, |
nkeynes@1145 | 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
nkeynes@1145 | 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
nkeynes@1145 | 21 | * GNU General Public License for more details. |
nkeynes@1145 | 22 | */ |
nkeynes@1145 | 23 | |
nkeynes@1145 | 24 | #ifndef lxdream_tileiter_H |
nkeynes@1145 | 25 | #define lxdream_tileiter_H 1 |
nkeynes@1145 | 26 | |
nkeynes@1145 | 27 | #include <assert.h> |
nkeynes@1145 | 28 | #include "pvr2/pvr2.h" |
nkeynes@1145 | 29 | |
nkeynes@1145 | 30 | #ifdef __cplusplus |
nkeynes@1145 | 31 | extern "C" { |
nkeynes@1145 | 32 | #endif |
nkeynes@1145 | 33 | |
nkeynes@1145 | 34 | |
nkeynes@1145 | 35 | /** |
nkeynes@1145 | 36 | * tileiter: iterator over individual polygons in a tile list. |
nkeynes@1145 | 37 | */ |
nkeynes@1145 | 38 | typedef struct tileiter { |
nkeynes@1145 | 39 | uint32_t *ptr; |
nkeynes@1145 | 40 | unsigned strip_count; |
nkeynes@1145 | 41 | unsigned poly_size; |
nkeynes@1145 | 42 | uint32_t poly_addr; |
nkeynes@1145 | 43 | } tileiter; |
nkeynes@1145 | 44 | |
nkeynes@1145 | 45 | |
nkeynes@1145 | 46 | #define TILEITER_IS_MODIFIED(it) ((*(it).ptr) & 0x01000000) |
nkeynes@1145 | 47 | #define TILEITER_IS_TRIANGLE(it) (((*(it).ptr) >> 29) == 4) |
nkeynes@1145 | 48 | #define TILEITER_IS_QUAD(it) (((*(it).ptr) >> 29) == 5) |
nkeynes@1145 | 49 | #define TILEITER_IS_POLY(it) (((*(it).ptr) >> 31) == 0) |
nkeynes@1145 | 50 | |
nkeynes@1145 | 51 | #define TILEITER_POLYADDR(it) ((it).poly_addr) |
nkeynes@1145 | 52 | #define TILEITER_STRIPCOUNT(it) ((it).strip_count) |
nkeynes@1145 | 53 | #define TILEITER_DONE(it) ((it).ptr == 0) |
nkeynes@1145 | 54 | #define TILEITER_BEGIN(it, tileent) (tileiter_init(&it, tileent)) |
nkeynes@1145 | 55 | #define TILEITER_NEXT(it) (tileiter_next(&it)) |
nkeynes@1145 | 56 | #define FOREACH_TILE(it, seg) for( TILEITER_BEGIN(it, seg); !TILEITER_DONE(it); TILEITER_NEXT(it) ) |
nkeynes@1145 | 57 | |
nkeynes@1145 | 58 | |
nkeynes@1145 | 59 | /** |
nkeynes@1145 | 60 | * tileentryiter: iterator over entries in the tile list, where each entry is |
nkeynes@1145 | 61 | * a polygon, triangle set, or quad set. |
nkeynes@1145 | 62 | */ |
nkeynes@1145 | 63 | typedef struct tileentryiter { |
nkeynes@1145 | 64 | uint32_t *ptr; |
nkeynes@1145 | 65 | unsigned strip_count; |
nkeynes@1145 | 66 | } tileentryiter; |
nkeynes@1145 | 67 | |
nkeynes@1145 | 68 | #define TILEENTRYITER_POLYADDR(it) ((*((it).ptr)) & 0x001FFFFF) |
nkeynes@1145 | 69 | #define TILEENTRYITER_STRIPCOUNT(it) ((it).strip_count) |
nkeynes@1145 | 70 | #define TILEENTRYITER_DONE(it) ((it).ptr == 0) |
nkeynes@1145 | 71 | #define TILEENTRYITER_BEGIN(it, tileent) (tileentryiter_init(&(it),tileent)) |
nkeynes@1145 | 72 | #define TILEENTRYITER_NEXT(it) (tileentryiter_next(&(it))) |
nkeynes@1145 | 73 | #define FOREACH_TILEENTRY(it,seg) for( TILEENTRYITER_BEGIN(it,seg); !TILEENTRYITER_DONE(it); TILEENTRYITER_NEXT(it) ) |
nkeynes@1145 | 74 | |
nkeynes@1145 | 75 | /**************************** tileiter functions ****************************/ |
nkeynes@1145 | 76 | |
nkeynes@1145 | 77 | /** |
nkeynes@1145 | 78 | * Read the entry pointed to by it->ptr into the tileiter structure. If the |
nkeynes@1145 | 79 | * entry if a list pointer or invalid entry, the pointer will first be |
nkeynes@1145 | 80 | * updated to the next real entry. On end-of-list, sets ptr to NULL |
nkeynes@1145 | 81 | */ |
nkeynes@1145 | 82 | static void tileiter_read( tileiter *it ) |
nkeynes@1145 | 83 | { |
nkeynes@1145 | 84 | for(;;){ |
nkeynes@1145 | 85 | uint32_t entry = *it->ptr; |
nkeynes@1145 | 86 | uint32_t tag = entry >> 29; |
nkeynes@1153 | 87 | if( tag == 0x07 ) { |
nkeynes@1153 | 88 | if( tag & 0x10000000 ) { |
nkeynes@1153 | 89 | it->ptr = NULL; |
nkeynes@1145 | 90 | return; |
nkeynes@1145 | 91 | } else { |
nkeynes@1153 | 92 | it->ptr = (uint32_t *)(pvr2_main_ram + (entry&0x007FFFFF)); |
nkeynes@1153 | 93 | it->poly_addr = -1; |
nkeynes@1153 | 94 | entry = *it->ptr; |
nkeynes@1145 | 95 | } |
nkeynes@1153 | 96 | } else if( tag == 6 ) { |
nkeynes@1153 | 97 | /* Illegal? Skip */ |
nkeynes@1153 | 98 | it->ptr++; |
nkeynes@1153 | 99 | } else if( tag & 0x04 ) { |
nkeynes@1153 | 100 | int vertex_count = tag-1; /* 4 == tri, 5 == quad */ |
nkeynes@1153 | 101 | int vertex_length = (entry >> 21) & 0x07; |
nkeynes@1153 | 102 | if( (entry & 0x01000000) && (pvr2_scene.shadow_mode == SHADOW_FULL) ) { |
nkeynes@1153 | 103 | it->poly_size = 5 + (vertex_length<<1) * vertex_count; |
nkeynes@1153 | 104 | } else { |
nkeynes@1153 | 105 | it->poly_size = 3 + vertex_length * vertex_count; |
nkeynes@1153 | 106 | } |
nkeynes@1153 | 107 | it->strip_count = ((entry >> 25) & 0x0F); |
nkeynes@1153 | 108 | it->poly_addr = entry & 0x001FFFFF; |
nkeynes@1153 | 109 | return; |
nkeynes@1151 | 110 | } else { |
nkeynes@1153 | 111 | /* Other polygon */ |
nkeynes@1153 | 112 | it->strip_count = 0; |
nkeynes@1153 | 113 | it->poly_addr = entry & 0x001FFFFF; |
nkeynes@1153 | 114 | return; |
nkeynes@1145 | 115 | } |
nkeynes@1145 | 116 | } |
nkeynes@1145 | 117 | } |
nkeynes@1145 | 118 | |
nkeynes@1145 | 119 | static void tileiter_init( tileiter *it, uint32_t segptr ) |
nkeynes@1145 | 120 | { |
nkeynes@1145 | 121 | if( IS_TILE_PTR(segptr) ) { |
nkeynes@1145 | 122 | it->ptr = (uint32_t *)(pvr2_main_ram + (segptr & 0x007FFFFF)); |
nkeynes@1145 | 123 | tileiter_read(it); |
nkeynes@1145 | 124 | } else { |
nkeynes@1145 | 125 | it->ptr = 0; |
nkeynes@1145 | 126 | } |
nkeynes@1145 | 127 | } |
nkeynes@1145 | 128 | |
nkeynes@1145 | 129 | static inline void tileiter_next( tileiter *it ) |
nkeynes@1145 | 130 | { |
nkeynes@1145 | 131 | assert( it->ptr != NULL ); |
nkeynes@1145 | 132 | if( it->strip_count > 0 ) { |
nkeynes@1145 | 133 | it->strip_count--; |
nkeynes@1145 | 134 | it->poly_addr += it->poly_size; |
nkeynes@1145 | 135 | } else { |
nkeynes@1145 | 136 | it->ptr++; |
nkeynes@1145 | 137 | tileiter_read(it); |
nkeynes@1145 | 138 | } |
nkeynes@1145 | 139 | } |
nkeynes@1145 | 140 | |
nkeynes@1145 | 141 | |
nkeynes@1145 | 142 | /************************* tileentryiter functions **************************/ |
nkeynes@1145 | 143 | |
nkeynes@1145 | 144 | /** |
nkeynes@1145 | 145 | * Read the entry pointed to by it->ptr, updating the pointer to point |
nkeynes@1145 | 146 | * to the next real element if the current value is not a polygon entry. |
nkeynes@1145 | 147 | */ |
nkeynes@1145 | 148 | static void tileentryiter_read( tileentryiter *it ) |
nkeynes@1145 | 149 | { |
nkeynes@1145 | 150 | for(;;){ |
nkeynes@1145 | 151 | uint32_t entry = *it->ptr; |
nkeynes@1145 | 152 | uint32_t tag = entry >> 28; |
nkeynes@1145 | 153 | if( tag < 0x0C ) { |
nkeynes@1145 | 154 | if( tag & 0x08 ) { |
nkeynes@1145 | 155 | it->strip_count = ((entry >> 25) & 0x0F); |
nkeynes@1145 | 156 | } else { |
nkeynes@1145 | 157 | it->strip_count = 0; |
nkeynes@1145 | 158 | } |
nkeynes@1145 | 159 | return; |
nkeynes@1145 | 160 | } else { |
nkeynes@1145 | 161 | if( tag == 0x0F ) { |
nkeynes@1145 | 162 | it->ptr = NULL; |
nkeynes@1145 | 163 | return; |
nkeynes@1145 | 164 | } else if( tag == 0x0E ) { |
nkeynes@1145 | 165 | it->ptr = (uint32_t *)(pvr2_main_ram + (entry&0x007FFFFF)); |
nkeynes@1145 | 166 | entry = *it->ptr; |
nkeynes@1145 | 167 | } else { |
nkeynes@1145 | 168 | /* Illegal? Skip */ |
nkeynes@1145 | 169 | it->ptr++; |
nkeynes@1145 | 170 | } |
nkeynes@1145 | 171 | } |
nkeynes@1145 | 172 | } |
nkeynes@1145 | 173 | } |
nkeynes@1145 | 174 | |
nkeynes@1145 | 175 | |
nkeynes@1145 | 176 | static void tileentryiter_init( tileentryiter *it, uint32_t segptr ) |
nkeynes@1145 | 177 | { |
nkeynes@1145 | 178 | if( IS_TILE_PTR(segptr) ) { |
nkeynes@1145 | 179 | it->ptr = (uint32_t *)(pvr2_main_ram + (segptr & 0x007FFFFF)); |
nkeynes@1145 | 180 | tileentryiter_read(it); |
nkeynes@1145 | 181 | } else { |
nkeynes@1145 | 182 | it->ptr = 0; |
nkeynes@1145 | 183 | } |
nkeynes@1145 | 184 | } |
nkeynes@1145 | 185 | |
nkeynes@1145 | 186 | static void inline tileentryiter_next( tileentryiter *it ) |
nkeynes@1145 | 187 | { |
nkeynes@1145 | 188 | it->ptr++; |
nkeynes@1145 | 189 | tileentryiter_read(it); |
nkeynes@1145 | 190 | } |
nkeynes@1145 | 191 | |
nkeynes@1145 | 192 | |
nkeynes@1145 | 193 | #ifdef __cplusplus |
nkeynes@1145 | 194 | } |
nkeynes@1145 | 195 | #endif |
nkeynes@1145 | 196 | |
nkeynes@1145 | 197 | #endif /* !lxdream_tileiter_H */ |
.