filename | src/pvr2/rendcore.c |
changeset | 189:615b70cfd729 |
next | 191:df4441cf3128 |
author | nkeynes |
date | Wed Aug 02 04:06:45 2006 +0000 (17 years ago) |
permissions | -rw-r--r-- |
last change | Issue 0003: TA Vertex compiler Initial implementation of the TA. Renderer hooked up to the TA "properly" now as well |
file | annotate | diff | log | raw |
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +00001.2 +++ b/src/pvr2/rendcore.c Wed Aug 02 04:06:45 2006 +00001.3 @@ -0,0 +1,341 @@1.4 +/**1.5 + * $Id: rendcore.c,v 1.1 2006-08-02 04:06:45 nkeynes Exp $1.6 + *1.7 + * PVR2 renderer core.1.8 + *1.9 + * Copyright (c) 2005 Nathan Keynes.1.10 + *1.11 + * This program is free software; you can redistribute it and/or modify1.12 + * it under the terms of the GNU General Public License as published by1.13 + * the Free Software Foundation; either version 2 of the License, or1.14 + * (at your option) any later version.1.15 + *1.16 + * This program is distributed in the hope that it will be useful,1.17 + * but WITHOUT ANY WARRANTY; without even the implied warranty of1.18 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1.19 + * GNU General Public License for more details.1.20 + */1.21 +#include "pvr2/pvr2.h"1.22 +#include "asic.h"1.23 +1.24 +static int pvr2_poly_depthmode[8] = { GL_NEVER, GL_LESS, GL_EQUAL, GL_LEQUAL,1.25 + GL_GREATER, GL_NOTEQUAL, GL_GEQUAL,1.26 + GL_ALWAYS };1.27 +static int pvr2_poly_srcblend[8] = {1.28 + GL_ZERO, GL_ONE, GL_DST_COLOR, GL_ONE_MINUS_DST_COLOR,1.29 + GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_DST_ALPHA,1.30 + GL_ONE_MINUS_DST_ALPHA };1.31 +static int pvr2_poly_dstblend[8] = {1.32 + GL_ZERO, GL_ONE, GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR,1.33 + GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_DST_ALPHA,1.34 + GL_ONE_MINUS_DST_ALPHA };1.35 +static int pvr2_poly_texblend[4] = {1.36 + GL_REPLACE, GL_BLEND, GL_DECAL, GL_MODULATE };1.37 +static int pvr2_render_colour_format[8] = {1.38 + COLFMT_ARGB1555, COLFMT_RGB565, COLFMT_ARGB4444, COLFMT_ARGB1555,1.39 + COLFMT_RGB888, COLFMT_ARGB8888, COLFMT_ARGB8888, COLFMT_ARGB4444 };1.40 +#define POLY1_DEPTH_MODE(poly1) ( pvr2_poly_depthmode[(poly1)>>29] )1.41 +#define POLY1_DEPTH_ENABLE(poly1) (((poly1)&0x04000000) == 0 )1.42 +#define POLY1_CULL_MODE(poly1) (((poly1)>>27)&0x03)1.43 +#define POLY1_TEXTURED(poly1) (((poly1)&0x02000000))1.44 +#define POLY1_SPECULAR(poly1) (((poly1)&0x01000000))1.45 +#define POLY1_SHADE_MODEL(poly1) (((poly1)&0x00800000) ? GL_SMOOTH : GL_FLAT)1.46 +#define POLY1_UV16(poly1) (((poly1)&0x00400000))1.47 +#define POLY1_SINGLE_TILE(poly1) (((poly1)&0x00200000))1.48 +1.49 +#define POLY2_SRC_BLEND(poly2) ( pvr2_poly_srcblend[(poly2) >> 29] )1.50 +#define POLY2_DEST_BLEND(poly2) ( pvr2_poly_dstblend[((poly2)>>26)&0x07] )1.51 +#define POLY2_SRC_BLEND_ENABLE(poly2) ((poly2)&0x02000000)1.52 +#define POLY2_DEST_BLEND_ENABLE(poly2) ((poly2)&0x01000000)1.53 +#define POLY2_COLOUR_CLAMP_ENABLE(poly2) ((poly2)&0x00200000)1.54 +#define POLY2_ALPHA_ENABLE(poly2) ((poly2)&0x001000000)1.55 +#define POLY2_TEX_ALPHA_ENABLE(poly2) (((poly2)&0x00080000) == 0 )1.56 +#define POLY2_TEX_WIDTH(poly2) ( 1<< ((((poly2) >> 3) & 0x07 ) + 3) )1.57 +#define POLY2_TEX_HEIGHT(poly2) ( 1<< (((poly2) & 0x07 ) + 3) )1.58 +#define POLY2_TEX_BLEND(poly2) ( pvr2_poly_texblend[((poly2) >> 6)&0x03] )1.59 +1.60 +#define RENDER_ZONLY 01.61 +#define RENDER_NORMAL 1 /* Render non-modified polygons */1.62 +#define RENDER_CHEAPMOD 2 /* Render cheap-modified polygons */1.63 +#define RENDER_FULLMOD 3 /* Render the fully-modified version of the polygons */1.64 +1.65 +#define CULL_NONE 01.66 +#define CULL_SMALL 11.67 +#define CULL_CCW 21.68 +#define CULL_CW 31.69 +1.70 +#define SEGMENT_END 0x800000001.71 +#define SEGMENT_SORT_TRANS 0x200000001.72 +#define SEGMENT_START 0x100000001.73 +#define SEGMENT_X(c) (((c) >> 2) & 0x3F)1.74 +#define SEGMENT_Y(c) (((c) >> 8) & 0x3F)1.75 +#define NO_POINTER 0x800000001.76 +1.77 +extern char *video_base;1.78 +1.79 +struct tile_segment {1.80 + uint32_t control;1.81 + pvraddr_t opaque_ptr;1.82 + pvraddr_t opaquemod_ptr;1.83 + pvraddr_t trans_ptr;1.84 + pvraddr_t transmod_ptr;1.85 + pvraddr_t punchout_ptr;1.86 +};1.87 +1.88 +/**1.89 + * Convert a half-float (16-bit) FP number to a regular 32-bit float.1.90 + * Source is 1-bit sign, 5-bit exponent, 10-bit mantissa.1.91 + * TODO: Check the correctness of this.1.92 + */1.93 +float halftofloat( uint16_t half )1.94 +{1.95 + union {1.96 + float f;1.97 + uint32_t i;1.98 + } temp;1.99 + int e = ((half & 0x7C00) >> 10) - 15 + 127;1.100 +1.101 + temp.i = ((half & 0x8000) << 16) | (e << 23) |1.102 + ((half & 0x03FF) << 13);1.103 + return temp.f;1.104 +}1.105 +1.106 +1.107 +/**1.108 + * Setup the GL context for the supplied polygon context.1.109 + * @param context pointer to 3 or 5 words of polygon context1.110 + * @param modified boolean flag indicating that the modified1.111 + * version should be used, rather than the normal version.1.112 + */1.113 +void render_set_context( uint32_t *context, int render_mode )1.114 +{1.115 + uint32_t poly1 = context[0], poly2, texture;1.116 + if( render_mode == RENDER_FULLMOD ) {1.117 + poly2 = context[3];1.118 + texture = context[4];1.119 + } else {1.120 + poly2 = context[1];1.121 + texture = context[2];1.122 + }1.123 +1.124 + if( POLY1_DEPTH_ENABLE(poly1) ) {1.125 + glEnable( GL_DEPTH_TEST );1.126 + glDepthFunc( POLY1_DEPTH_MODE(poly1) );1.127 + } else {1.128 + glDisable( GL_DEPTH_TEST );1.129 + }1.130 +1.131 + switch( POLY1_CULL_MODE(poly1) ) {1.132 + case CULL_NONE:1.133 + case CULL_SMALL:1.134 + glDisable( GL_CULL_FACE );1.135 + break;1.136 + case CULL_CCW:1.137 + glEnable( GL_CULL_FACE );1.138 + glFrontFace( GL_CW );1.139 + break;1.140 + case CULL_CW:1.141 + glEnable( GL_CULL_FACE );1.142 + glFrontFace( GL_CCW );1.143 + break;1.144 + }1.145 +1.146 + if( POLY1_TEXTURED(poly1) ) {1.147 + int width = POLY2_TEX_WIDTH(poly2);1.148 + int height = POLY2_TEX_HEIGHT(poly2);1.149 + glEnable(GL_TEXTURE_2D);1.150 + texcache_get_texture( (texture&0x001FFFFF)<<3, width, height, texture );1.151 + glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, POLY2_TEX_BLEND(poly2) );1.152 + } else {1.153 + glDisable( GL_TEXTURE_2D );1.154 + }1.155 +1.156 + glShadeModel( POLY1_SHADE_MODEL(poly1) );1.157 +1.158 + glBlendFunc( POLY2_SRC_BLEND(poly2), POLY2_DEST_BLEND(poly2) );1.159 + if( POLY2_TEX_ALPHA_ENABLE(poly2) ) {1.160 + glEnable(GL_BLEND);1.161 + } else {1.162 + glDisable(GL_BLEND);1.163 + }1.164 +}1.165 +1.166 +void render_vertexes( uint32_t poly1, uint32_t *vertexes, int num_vertexes, int vertex_size,1.167 + int render_mode )1.168 +{1.169 + int i, m=0;1.170 +1.171 + if( render_mode == RENDER_FULLMOD ) {1.172 + m = (vertex_size - 3)/2;1.173 + }1.174 +1.175 + glBegin( GL_TRIANGLE_STRIP );1.176 +1.177 + for( i=0; i<num_vertexes; i++ ) {1.178 + float *vertexf = (float *)vertexes;1.179 + uint32_t argb;1.180 + if( POLY1_TEXTURED(poly1) ) {1.181 + if( POLY1_UV16(poly1) ) {1.182 + glTexCoord2f( halftofloat(vertexes[m+3]>>16),1.183 + halftofloat(vertexes[m+3]) );1.184 + argb = vertexes[m+4];1.185 + } else {1.186 + glTexCoord2f( vertexf[m+3], vertexf[m+4] );1.187 + argb = vertexes[m+5];1.188 + }1.189 + } else {1.190 + argb = vertexes[m+3];1.191 + }1.192 +1.193 + glColor4ub( (GLubyte)(argb >> 16), (GLubyte)(argb >> 8),1.194 + (GLubyte)argb, (GLubyte)(argb >> 24) );1.195 + glVertex3f( vertexf[0], vertexf[1], vertexf[2] );1.196 + vertexes += vertex_size;1.197 + }1.198 +1.199 + glEnd();1.200 +}1.201 +1.202 +/**1.203 + * Render a simple (not auto-sorted) tile1.204 + */1.205 +void render_tile( pvraddr_t tile_entry, int render_mode, gboolean cheap_modifier_mode ) {1.206 +1.207 + uint32_t *tile_list = (uint32_t *)(video_base+tile_entry);1.208 + do {1.209 + uint32_t entry = *tile_list++;1.210 + if( entry >> 28 == 0x0F ) {1.211 + break;1.212 + } else if( entry >> 28 == 0x0E ) {1.213 + tile_list = (uint32_t *)(video_base + (entry&0x007FFFFF));1.214 + } else {1.215 + uint32_t *polygon = (uint32_t *)(video_base + ((entry & 0x001FFFFF) << 2));1.216 + int is_modified = entry & 0x01000000;1.217 + int vertex_length = (entry >> 21) & 0x07;1.218 + int context_length = 3;1.219 + if( is_modified && !cheap_modifier_mode ) {1.220 + context_length = 5;1.221 + vertex_length *= 2 ;1.222 + }1.223 + vertex_length += 3;1.224 +1.225 + if( (entry & 0xE0000000) == 0x80000000 ) {1.226 + /* Triangle(s) */1.227 + int strip_count = ((entry >> 25) & 0x0F)+1;1.228 + int polygon_length = 3 * vertex_length + context_length;1.229 + int i;1.230 + for( i=0; i<strip_count; i++ ) {1.231 + render_set_context( polygon, render_mode );1.232 + render_vertexes( *polygon, polygon+context_length, 3, vertex_length,1.233 + render_mode );1.234 + polygon += polygon_length;1.235 + }1.236 + } else if( (entry & 0xE0000000) == 0xA0000000 ) {1.237 + /* Sprite(s) */1.238 + int strip_count = (entry >> 25) & 0x0F;1.239 + int polygon_length = 4 * vertex_length + context_length;1.240 + int i;1.241 + for( i=0; i<strip_count; i++ ) {1.242 + render_set_context( polygon, render_mode );1.243 + render_vertexes( *polygon, polygon+context_length, 4, vertex_length,1.244 + render_mode );1.245 + polygon += polygon_length;1.246 + }1.247 + } else {1.248 + /* Polygon */1.249 + int i, first=-1, last = -1;1.250 + for( i=0; i<6; i++ ) {1.251 + if( entry & (0x40000000>>i) ) {1.252 + if( first == -1 ) first = i;1.253 + last = i;1.254 + }1.255 + }1.256 + if( first != -1 ) {1.257 + first = 0;1.258 + render_set_context(polygon, render_mode);1.259 + render_vertexes( *polygon, polygon+context_length + (first*vertex_length),1.260 + (last-first+3), vertex_length, render_mode );1.261 + }1.262 + }1.263 + }1.264 + } while( 1 );1.265 +}1.266 +1.267 +void render_autosort_tile( pvraddr_t tile_entry, int render_mode, gboolean cheap_modifier_mode ) {1.268 + //WARN( "Autosort not implemented yet" );1.269 + render_tile( tile_entry, render_mode, cheap_modifier_mode );1.270 +}1.271 +1.272 +void pvr2_render_tilebuffer( int width, int height, int clipx1, int clipy1,1.273 + int clipx2, int clipy2 ) {1.274 +1.275 + pvraddr_t segmentbase = MMIO_READ( PVR2, TILEBASE );1.276 + int tile_sort;1.277 + gboolean cheap_shadow;1.278 +1.279 + int obj_config = MMIO_READ( PVR2, OBJCFG );1.280 + int isp_config = MMIO_READ( PVR2, ISPCFG );1.281 + int shadow_cfg = MMIO_READ( PVR2, SHADOW );1.282 +1.283 + if( obj_config & 0x00200000 ) {1.284 + if( isp_config & 1 ) {1.285 + tile_sort = 0;1.286 + } else {1.287 + tile_sort = 2;1.288 + }1.289 + } else {1.290 + tile_sort = 1;1.291 + }1.292 +1.293 + cheap_shadow = shadow_cfg & 0x100 ? TRUE : FALSE;1.294 +1.295 + struct tile_segment *segment = (struct tile_segment *)(video_base + segmentbase);1.296 +1.297 + glEnable( GL_SCISSOR_TEST );1.298 + while( (segment->control & SEGMENT_END) == 0 ) {1.299 + int tilex = SEGMENT_X(segment->control);1.300 + int tiley = SEGMENT_Y(segment->control);1.301 +1.302 + int x1 = tilex << 5;1.303 + int y1 = tiley << 5;1.304 + if( x1 + 32 <= clipx1 ||1.305 + y1 + 32 <= clipy1 ||1.306 + x1 >= clipx2 ||1.307 + y1 >= clipy2 ) {1.308 + /* Tile completely clipped, skip */1.309 + segment++;1.310 + continue;1.311 + }1.312 +1.313 + /* Set a scissor on the visible part of the tile */1.314 + int w = MIN(x1+32, clipx2) - x1;1.315 + int h = MIN(y1+32, clipy2) - y1;1.316 + x1 = MAX(x1,clipx1);1.317 + y1 = MAX(y1,clipy1);1.318 + glScissor( x1, height-y1-h, w, h );1.319 +1.320 + if( (segment->opaque_ptr & NO_POINTER) == 0 ) {1.321 + if( (segment->opaquemod_ptr & NO_POINTER) == 0 ) {1.322 + /* TODO */1.323 + }1.324 + render_tile( segment->opaque_ptr, RENDER_NORMAL, cheap_shadow );1.325 + }1.326 +1.327 + if( (segment->trans_ptr & NO_POINTER) == 0 ) {1.328 + if( (segment->transmod_ptr & NO_POINTER) == 0 ) {1.329 + /* TODO */1.330 + }1.331 + if( tile_sort == 2 || (tile_sort == 1 && (segment->control & SEGMENT_SORT_TRANS)) ) {1.332 + render_autosort_tile( segment->trans_ptr, RENDER_NORMAL, cheap_shadow );1.333 + } else {1.334 + render_tile( segment->trans_ptr, RENDER_NORMAL, cheap_shadow );1.335 + }1.336 + }1.337 +1.338 + if( (segment->punchout_ptr & NO_POINTER) == 0 ) {1.339 + render_tile( segment->punchout_ptr, RENDER_NORMAL, cheap_shadow );1.340 + }1.341 + segment++;1.342 + }1.343 + glDisable( GL_SCISSOR_TEST );1.344 +}
.