Search
lxdream.org :: lxdream/src/pvr2/tileiter.h
lxdream 0.9.1
released Jun 29
Download Now
filename src/pvr2/tileiter.h
changeset 1151:e1848ca9b5b1
prev1145:45674791c6ad
next1153:00e507e4025c
author nkeynes
date Wed Dec 08 18:33:23 2010 +1000 (13 years ago)
permissions -rw-r--r--
last change Updated pt_BR translation from Arthonis
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@1151
    87
        if( tag < 6 ) {
nkeynes@1151
    88
            if( tag & 0x04 ) {
nkeynes@1151
    89
                int vertex_count = tag-1; /* 4 == tri, 5 == quad */
nkeynes@1151
    90
                int vertex_length = (entry >> 21) & 0x07;
nkeynes@1151
    91
                if( (entry & 0x01000000) && (pvr2_scene.shadow_mode == SHADOW_FULL) ) {
nkeynes@1151
    92
                    it->poly_size = 5 + (vertex_length<<1) * vertex_count;
nkeynes@1151
    93
                } else {
nkeynes@1151
    94
                    it->poly_size = 3 + vertex_length * vertex_count;
nkeynes@1151
    95
                }
nkeynes@1151
    96
                it->strip_count = ((entry >> 25) & 0x0F);
nkeynes@1151
    97
                it->poly_addr = entry & 0x001FFFFF;
nkeynes@1145
    98
                return;
nkeynes@1145
    99
            } else {
nkeynes@1151
   100
                /* Other polygon */
nkeynes@1151
   101
                it->strip_count = 0;
nkeynes@1151
   102
                it->poly_addr = entry & 0x001FFFFF;
nkeynes@1151
   103
                return;
nkeynes@1145
   104
            }
nkeynes@1151
   105
        } else {
nkeynes@1151
   106
            if( tag == 0x07 ) {
nkeynes@1151
   107
                if( entry & 0x10000000 ) {
nkeynes@1151
   108
                    it->ptr = NULL;
nkeynes@1151
   109
                    return;
nkeynes@1151
   110
                } else {
nkeynes@1151
   111
                    it->ptr = (uint32_t *)(pvr2_main_ram + (entry&0x007FFFFF));
nkeynes@1151
   112
                }
nkeynes@1151
   113
            } else if( tag == 6 ) {
nkeynes@1151
   114
                /* Illegal? Skip */
nkeynes@1151
   115
                it->ptr++;
nkeynes@1145
   116
            }
nkeynes@1145
   117
        }
nkeynes@1145
   118
    }
nkeynes@1145
   119
}
nkeynes@1145
   120
nkeynes@1145
   121
static void tileiter_init( tileiter *it, uint32_t segptr )
nkeynes@1145
   122
{
nkeynes@1145
   123
    if( IS_TILE_PTR(segptr) ) {
nkeynes@1145
   124
        it->ptr = (uint32_t *)(pvr2_main_ram + (segptr & 0x007FFFFF));
nkeynes@1145
   125
        tileiter_read(it);
nkeynes@1145
   126
    } else {
nkeynes@1145
   127
        it->ptr = 0;
nkeynes@1145
   128
    }
nkeynes@1145
   129
}
nkeynes@1145
   130
nkeynes@1145
   131
static inline void tileiter_next( tileiter *it )
nkeynes@1145
   132
{
nkeynes@1145
   133
    assert( it->ptr != NULL );
nkeynes@1145
   134
    if( it->strip_count > 0 ) {
nkeynes@1145
   135
        it->strip_count--;
nkeynes@1145
   136
        it->poly_addr += it->poly_size;
nkeynes@1145
   137
    } else {
nkeynes@1145
   138
        it->ptr++;
nkeynes@1145
   139
        tileiter_read(it);
nkeynes@1145
   140
    }
nkeynes@1145
   141
}
nkeynes@1145
   142
nkeynes@1145
   143
nkeynes@1145
   144
/************************* tileentryiter functions **************************/
nkeynes@1145
   145
nkeynes@1145
   146
/**
nkeynes@1145
   147
 * Read the entry pointed to by it->ptr, updating the pointer to point
nkeynes@1145
   148
 * to the next real element if the current value is not a polygon entry.
nkeynes@1145
   149
 */
nkeynes@1145
   150
static void tileentryiter_read( tileentryiter *it )
nkeynes@1145
   151
{
nkeynes@1145
   152
    for(;;){
nkeynes@1145
   153
        uint32_t entry = *it->ptr;
nkeynes@1145
   154
        uint32_t tag = entry >> 28;
nkeynes@1145
   155
        if( tag < 0x0C ) {
nkeynes@1145
   156
            if( tag & 0x08 ) {
nkeynes@1145
   157
                it->strip_count = ((entry >> 25) & 0x0F);
nkeynes@1145
   158
            } else {
nkeynes@1145
   159
                it->strip_count = 0;
nkeynes@1145
   160
            }
nkeynes@1145
   161
            return;
nkeynes@1145
   162
        } else {
nkeynes@1145
   163
            if( tag == 0x0F ) {
nkeynes@1145
   164
                it->ptr = NULL;
nkeynes@1145
   165
                return;
nkeynes@1145
   166
            } else if( tag == 0x0E ) {
nkeynes@1145
   167
                it->ptr = (uint32_t *)(pvr2_main_ram + (entry&0x007FFFFF));
nkeynes@1145
   168
                entry = *it->ptr;
nkeynes@1145
   169
            } else {
nkeynes@1145
   170
                /* Illegal? Skip */
nkeynes@1145
   171
                it->ptr++;
nkeynes@1145
   172
            }
nkeynes@1145
   173
        }
nkeynes@1145
   174
    }
nkeynes@1145
   175
}
nkeynes@1145
   176
nkeynes@1145
   177
nkeynes@1145
   178
static void tileentryiter_init( tileentryiter *it, uint32_t segptr )
nkeynes@1145
   179
{
nkeynes@1145
   180
    if( IS_TILE_PTR(segptr) ) {
nkeynes@1145
   181
        it->ptr = (uint32_t *)(pvr2_main_ram + (segptr & 0x007FFFFF));
nkeynes@1145
   182
        tileentryiter_read(it);
nkeynes@1145
   183
    } else {
nkeynes@1145
   184
        it->ptr = 0;
nkeynes@1145
   185
    }
nkeynes@1145
   186
}
nkeynes@1145
   187
nkeynes@1145
   188
static void inline tileentryiter_next( tileentryiter *it )
nkeynes@1145
   189
{
nkeynes@1145
   190
    it->ptr++;
nkeynes@1145
   191
    tileentryiter_read(it);
nkeynes@1145
   192
}
nkeynes@1145
   193
nkeynes@1145
   194
nkeynes@1145
   195
#ifdef __cplusplus
nkeynes@1145
   196
}
nkeynes@1145
   197
#endif
nkeynes@1145
   198
nkeynes@1145
   199
#endif /* !lxdream_tileiter_H */
.