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 Thu Dec 23 18:14:29 2010 +1000 (13 years ago)
permissions -rw-r--r--
last change Revert changes from r1151 that went in by accident (not ready from
prime-time yet)
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 */
.