Search
lxdream.org :: lxdream/src/pvr2/rendsort.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/pvr2/rendsort.c
changeset 736:a02d1475ccfd
prev669:ab344e42bca9
next862:d3b2066d5daa
author nkeynes
date Wed Jul 30 22:50:44 2008 +0000 (12 years ago)
permissions -rw-r--r--
last change Bug #61: OpenBSD support
(Modified) patch from bsdmaniak, thanks!
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 count = 0;
    73     while(1) {
    74         uint32_t entry = *tile_list++;
    75         if( entry >> 28 == 0x0F ) {
    76             break;
    77         } else if( entry >> 28 == 0x0E ) {
    78             tile_list = (uint32_t *)(video_base+(entry&0x007FFFFF));
    79         } else {
    80             uint32_t poly_addr = entry & 0x000FFFFF;
    81             int is_modified = entry & 0x01000000;
    82             int vertex_length = (entry >> 21) & 0x07;
    83             int context_length = 3;
    84             if( is_modified && pvr2_scene.full_shadow ) {
    85                 context_length = 5;
    86                 vertex_length *= 2 ;
    87             }
    88             vertex_length += 3;
    90             if( (entry & 0xE0000000) == 0x80000000 ) {
    91                 /* Triangle(s) */
    92                 int strip_count = ((entry >> 25) & 0x0F)+1;
    93                 int polygon_length = 3 * vertex_length + context_length;
    94                 int i;
    95                 for( i=0; i<strip_count; i++ ) {
    96                     struct polygon_struct *poly = pvr2_scene.buf_to_poly_map[poly_addr];
    97                     triangles[count].poly = poly;
    98                     triangles[count].triangle_num = 0;
    99                     triangles[count].maxz = MAX3( pvr2_scene.vertex_array[poly->vertex_index].z,
   100                             pvr2_scene.vertex_array[poly->vertex_index+1].z,
   101                             pvr2_scene.vertex_array[poly->vertex_index+2].z );
   102                     poly_addr += polygon_length;
   103                     count++;
   104                 }
   105             } else if( (entry & 0xE0000000) == 0xA0000000 ) {
   106                 /* Quad(s) */
   107                 int strip_count = ((entry >> 25) & 0x0F)+1;
   108                 int polygon_length = 4 * vertex_length + context_length;
   109                 int i;
   110                 for( i=0; i<strip_count; i++ ) {
   111                     struct polygon_struct *poly = pvr2_scene.buf_to_poly_map[poly_addr];
   112                     triangles[count].poly = poly;
   113                     triangles[count].triangle_num = 0;
   114                     triangles[count].maxz = MAX3( pvr2_scene.vertex_array[poly->vertex_index].z,
   115                             pvr2_scene.vertex_array[poly->vertex_index+1].z,
   116                             pvr2_scene.vertex_array[poly->vertex_index+2].z );
   117                     count++;
   118                     triangles[count].poly = poly;
   119                     triangles[count].triangle_num = 1;
   120                     triangles[count].maxz = MAX3( pvr2_scene.vertex_array[poly->vertex_index+1].z,
   121                             pvr2_scene.vertex_array[poly->vertex_index+2].z,
   122                             pvr2_scene.vertex_array[poly->vertex_index+3].z );
   123                     count++;
   124                     poly_addr += polygon_length;
   125                 }
   126             } else {
   127                 /* Polygon */
   128                 int i;
   129                 struct polygon_struct *poly = pvr2_scene.buf_to_poly_map[poly_addr];
   130                 for( i=0; i<6; i++ ) {
   131                     if( entry & (0x40000000>>i) ) {
   132                         triangles[count].poly = poly;
   133                         triangles[count].triangle_num = i;
   134                         triangles[count].maxz = MAX3( pvr2_scene.vertex_array[poly->vertex_index+i].z,
   135                                 pvr2_scene.vertex_array[poly->vertex_index+i+1].z,
   136                                 pvr2_scene.vertex_array[poly->vertex_index+i+2].z );
   137                         count++;
   138                     }
   139                 }
   140             }
   141         }
   142     }
   143     return count;
   144 }
   146 void sort_render_triangles( struct sort_triangle *triangles, int num_triangles,
   147                             int render_mode )
   148 {
   149     int i;
   150     for( i=0; i<num_triangles; i++ ) {
   151         struct polygon_struct *poly = triangles[i].poly;
   152         if( poly->tex_id != -1 ) {
   153             glBindTexture(GL_TEXTURE_2D, poly->tex_id);
   154         }
   155         render_set_context( poly->context, RENDER_NORMAL );
   156         glDepthMask(GL_FALSE);
   157         glDepthFunc(GL_GEQUAL);
   158         /* Fix cull direction */
   159         if( triangles[i].triangle_num & 1 ) {
   160             glCullFace(GL_FRONT);
   161         } else {
   162             glCullFace(GL_BACK);
   163         }
   165         glDrawArrays(GL_TRIANGLE_STRIP, poly->vertex_index + triangles[i].triangle_num, 3 );
   166     }
   167 }
   169 int compare_triangles( const void *a, const void *b ) 
   170 {
   171     const struct sort_triangle *tri1 = a;
   172     const struct sort_triangle *tri2 = b;
   173     return tri2->maxz - tri1->maxz;
   174 }
   176 void sort_triangles( struct sort_triangle *triangles, int num_triangles )
   177 {
   178     qsort( triangles, num_triangles, sizeof(struct sort_triangle), compare_triangles );
   179 } 
   181 void render_autosort_tile( pvraddr_t tile_entry, int render_mode ) 
   182 {
   183     int num_triangles = sort_count_triangles(tile_entry);
   184     if( num_triangles == 0 ) {
   185         return; /* nothing to do */
   186     } else if( num_triangles == 1 ) { /* Triangle can hardly overlap with itself */
   187         gl_render_tilelist(tile_entry);
   188     } else { /* Ooh boy here we go... */
   189         struct sort_triangle triangles[num_triangles+1];
   190         // Reserve space for num_triangles / 2 * 4 vertexes (maximum possible number of
   191         // quad vertices)
   192         triangles[num_triangles].poly = (void *)SENTINEL;
   193         int extracted_triangles = sort_extract_triangles(tile_entry, triangles);
   194         assert( extracted_triangles == num_triangles );
   195         sort_triangles( triangles, num_triangles );
   196         sort_render_triangles(triangles, num_triangles, render_mode);
   197         glCullFace(GL_BACK);
   198         assert( triangles[num_triangles].poly == (void *)SENTINEL );
   199     }
   200 }
.