Search
lxdream.org :: lxdream/src/pvr2/tileiter.h
lxdream 0.9.1
released Jun 29
Download Now
filename src/pvr2/tileiter.h
changeset 1153:00e507e4025c
prev1151:e1848ca9b5b1
next1298:d0eb2307b847
author nkeynes
date Tue Mar 20 17:54:58 2012 +1000 (12 years ago)
permissions -rw-r--r--
last change Fix missing return statement
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 */
.