Search
lxdream.org :: lxdream/src/pvr2/rendsort.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/pvr2/rendsort.c
changeset 862:d3b2066d5daa
prev736:a02d1475ccfd
next865:e10c081f4b81
author nkeynes
date Sun Sep 28 00:31:58 2008 +0000 (13 years ago)
permissions -rw-r--r--
last change Simplify triangle extraction (using scene data properly)
view annotate diff log raw
     1 /**
     2  * $Id$
     3  *
     4  * PVR2 renderer routines for depth sorted polygons
     5  *
     6  * Copyright (c) 2005 Nathan Keynes.
     7  *
     8  * This program is free software; you can redistribute it and/or modify
     9  * it under the terms of the GNU General Public License as published by
    10  * the Free Software Foundation; either version 2 of the License, or
    11  * (at your option) any later version.
    12  *
    13  * This program is distributed in the hope that it will be useful,
    14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    16  * GNU General Public License for more details.
    17  */
    18 #include <sys/time.h>
    19 #include <string.h>
    20 #include <assert.h>
    21 #include "pvr2/pvr2.h"
    22 #include "pvr2/scene.h"
    23 #include "asic.h"
    25 #define MIN3( a,b,c ) ((a) < (b) ? ( (a) < (c) ? (a) : (c) ) : ((b) < (c) ? (b) : (c)) )
    26 #define MAX3( a,b,c ) ((a) > (b) ? ( (a) > (c) ? (a) : (c) ) : ((b) > (c) ? (b) : (c)) )
    28 struct sort_triangle {
    29     struct polygon_struct *poly;
    30     int triangle_num; // triangle number in the poly, from 0
    31     float maxz;
    32 };
    34 #define SENTINEL 0xDEADBEEF
    36 /**
    37  * Count the number of triangles in the list starting at the given 
    38  * pvr memory address.
    39  */
    40 int sort_count_triangles( pvraddr_t tile_entry ) {
    41     uint32_t *tile_list = (uint32_t *)(video_base+tile_entry);
    42     int count = 0;
    43     while(1) {
    44         uint32_t entry = *tile_list++;
    45         if( entry >> 28 == 0x0F ) {
    46             break;
    47         } else if( entry >> 28 == 0x0E ) {
    48             tile_list = (uint32_t *)(video_base+(entry&0x007FFFFF));
    49         } else if( entry >> 29 == 0x04 ) { /* Triangle array */
    50             count += ((entry >> 25) & 0x0F)+1;
    51         } else if( entry >> 29 == 0x05 ) { /* Quad array */
    52             count += ((((entry >> 25) & 0x0F)+1)<<1);
    53         } else { /* Polygon */
    54             int i;
    55             for( i=0; i<6; i++ ) {
    56                 if( entry & (0x40000000>>i) ) {
    57                     count++;
    58                 }
    59             }
    60         }
    61     }
    62     return count;
    63 }
    65 /**
    66  * Extract a triangle list from the tile (basically indexes into the polygon list, plus
    67  * computing maxz while we go through it
    68  */
    69 int sort_extract_triangles( pvraddr_t tile_entry, struct sort_triangle *triangles )
    70 {
    71     uint32_t *tile_list = (uint32_t *)(video_base+tile_entry);
    72     int strip_count;
    73     struct polygon_struct *poly;
    74     int count = 0, i;
    76     while(1) {
    77         uint32_t entry = *tile_list++;
    78         switch( entry >> 28 ) {
    79         case 0x0F:
    80             return count; // End-of-list
    81         case 0x0E:
    82             tile_list = (uint32_t *)(video_base + (entry&0x007FFFFF));
    83             break;
    84         case 0x08: case 0x09: case 0x0A: case 0x0B:
    85             strip_count = ((entry >> 25) & 0x0F)+1;
    86             poly = pvr2_scene.buf_to_poly_map[entry&0x000FFFFF];
    87             while( strip_count > 0 ) {
    88                 assert( poly != NULL );
    89                 for( i=0; i<poly->vertex_count-2; i++ ) { 
    90                     triangles[count].poly = poly;
    91                     triangles[count].triangle_num = i;
    92                     triangles[count].maxz = MAX3( pvr2_scene.vertex_array[poly->vertex_index+i].z,
    93                             pvr2_scene.vertex_array[poly->vertex_index+i+1].z,
    94                             pvr2_scene.vertex_array[poly->vertex_index+i+2].z );
    95                     count++;
    96                 }
    97                 poly = poly->next;
    98                 strip_count--;
    99             }
   100             break;
   101         default:
   102             if( entry & 0x7E000000 ) {
   103                 poly = pvr2_scene.buf_to_poly_map[entry&0x000FFFFF];
   104                 for( i=0; i<6; i++ ) {
   105                     if( entry & (0x40000000>>i) ) {
   106                         triangles[count].poly = poly;
   107                         triangles[count].triangle_num = i;
   108                         triangles[count].maxz = MAX3( pvr2_scene.vertex_array[poly->vertex_index+i].z,
   109                                 pvr2_scene.vertex_array[poly->vertex_index+i+1].z,
   110                                 pvr2_scene.vertex_array[poly->vertex_index+i+2].z );
   111                         count++;
   112                     }
   113                 }
   114             }
   115         }
   116     }       
   118 }
   120 void sort_render_triangles( struct sort_triangle *triangles, int num_triangles,
   121                             int render_mode )
   122 {
   123     int i;
   124     for( i=0; i<num_triangles; i++ ) {
   125         struct polygon_struct *poly = triangles[i].poly;
   126         if( poly->tex_id != -1 ) {
   127             glBindTexture(GL_TEXTURE_2D, poly->tex_id);
   128         }
   129         render_set_context( poly->context, RENDER_NORMAL );
   130         glDepthMask(GL_FALSE);
   131         glDepthFunc(GL_GEQUAL);
   132         /* Fix cull direction */
   133         if( triangles[i].triangle_num & 1 ) {
   134             glCullFace(GL_FRONT);
   135         } else {
   136             glCullFace(GL_BACK);
   137         }
   139         glDrawArrays(GL_TRIANGLE_STRIP, poly->vertex_index + triangles[i].triangle_num, 3 );
   140     }
   141 }
   143 int compare_triangles( const void *a, const void *b ) 
   144 {
   145     const struct sort_triangle *tri1 = a;
   146     const struct sort_triangle *tri2 = b;
   147     return tri2->maxz - tri1->maxz;
   148 }
   150 void sort_triangles( struct sort_triangle *triangles, int num_triangles )
   151 {
   152     qsort( triangles, num_triangles, sizeof(struct sort_triangle), compare_triangles );
   153 } 
   155 void render_autosort_tile( pvraddr_t tile_entry, int render_mode ) 
   156 {
   157     int num_triangles = sort_count_triangles(tile_entry);
   158     if( num_triangles == 0 ) {
   159         return; /* nothing to do */
   160     } else if( num_triangles == 1 ) { /* Triangle can hardly overlap with itself */
   161         gl_render_tilelist(tile_entry);
   162     } else { /* Ooh boy here we go... */
   163         struct sort_triangle triangles[num_triangles+1];
   164         // Reserve space for num_triangles / 2 * 4 vertexes (maximum possible number of
   165         // quad vertices)
   166         triangles[num_triangles].poly = (void *)SENTINEL;
   167         int extracted_triangles = sort_extract_triangles(tile_entry, triangles);
   168         assert( extracted_triangles == num_triangles );
   169         sort_triangles( triangles, num_triangles );
   170         sort_render_triangles(triangles, num_triangles, render_mode);
   171         glCullFace(GL_BACK);
   172         assert( triangles[num_triangles].poly == (void *)SENTINEL );
   173     }
   174 }
.