Search
lxdream.org :: lxdream/src/pvr2/rendcore.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/pvr2/rendcore.c
changeset 319:5392aed6a982
prev318:363935d31859
next322:354407942957
author nkeynes
date Wed Jan 24 08:11:14 2007 +0000 (14 years ago)
permissions -rw-r--r--
last change Add support for quads (auto-calculated 4th vertex)
file annotate diff log raw
nkeynes@189
     1
/**
nkeynes@319
     2
 * $Id: rendcore.c,v 1.12 2007-01-24 08:11:14 nkeynes Exp $
nkeynes@189
     3
 *
nkeynes@189
     4
 * PVR2 renderer core.
nkeynes@189
     5
 *
nkeynes@189
     6
 * Copyright (c) 2005 Nathan Keynes.
nkeynes@189
     7
 *
nkeynes@189
     8
 * This program is free software; you can redistribute it and/or modify
nkeynes@189
     9
 * it under the terms of the GNU General Public License as published by
nkeynes@189
    10
 * the Free Software Foundation; either version 2 of the License, or
nkeynes@189
    11
 * (at your option) any later version.
nkeynes@189
    12
 *
nkeynes@189
    13
 * This program is distributed in the hope that it will be useful,
nkeynes@189
    14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
nkeynes@189
    15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
nkeynes@189
    16
 * GNU General Public License for more details.
nkeynes@189
    17
 */
nkeynes@215
    18
#include <sys/time.h>
nkeynes@189
    19
#include "pvr2/pvr2.h"
nkeynes@189
    20
#include "asic.h"
nkeynes@189
    21
nkeynes@221
    22
int pvr2_poly_depthmode[8] = { GL_NEVER, GL_LESS, GL_EQUAL, GL_LEQUAL,
nkeynes@189
    23
				      GL_GREATER, GL_NOTEQUAL, GL_GEQUAL, 
nkeynes@189
    24
				      GL_ALWAYS };
nkeynes@221
    25
int pvr2_poly_srcblend[8] = { 
nkeynes@189
    26
    GL_ZERO, GL_ONE, GL_DST_COLOR, GL_ONE_MINUS_DST_COLOR,
nkeynes@189
    27
    GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_DST_ALPHA, 
nkeynes@189
    28
    GL_ONE_MINUS_DST_ALPHA };
nkeynes@221
    29
int pvr2_poly_dstblend[8] = {
nkeynes@189
    30
    GL_ZERO, GL_ONE, GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR,
nkeynes@189
    31
    GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_DST_ALPHA,
nkeynes@189
    32
    GL_ONE_MINUS_DST_ALPHA };
nkeynes@221
    33
int pvr2_poly_texblend[4] = {
nkeynes@298
    34
    GL_REPLACE, GL_MODULATE, GL_DECAL, GL_MODULATE };
nkeynes@221
    35
int pvr2_render_colour_format[8] = {
nkeynes@189
    36
    COLFMT_ARGB1555, COLFMT_RGB565, COLFMT_ARGB4444, COLFMT_ARGB1555,
nkeynes@189
    37
    COLFMT_RGB888, COLFMT_ARGB8888, COLFMT_ARGB8888, COLFMT_ARGB4444 };
nkeynes@189
    38
nkeynes@189
    39
nkeynes@189
    40
#define CULL_NONE 0
nkeynes@189
    41
#define CULL_SMALL 1
nkeynes@189
    42
#define CULL_CCW 2
nkeynes@189
    43
#define CULL_CW 3
nkeynes@189
    44
nkeynes@189
    45
#define SEGMENT_END         0x80000000
nkeynes@298
    46
#define SEGMENT_ZCLEAR      0x40000000
nkeynes@189
    47
#define SEGMENT_SORT_TRANS  0x20000000
nkeynes@189
    48
#define SEGMENT_START       0x10000000
nkeynes@189
    49
#define SEGMENT_X(c)        (((c) >> 2) & 0x3F)
nkeynes@189
    50
#define SEGMENT_Y(c)        (((c) >> 8) & 0x3F)
nkeynes@189
    51
#define NO_POINTER          0x80000000
nkeynes@189
    52
nkeynes@189
    53
extern char *video_base;
nkeynes@189
    54
nkeynes@318
    55
gboolean pvr2_force_fragment_alpha;
nkeynes@318
    56
nkeynes@189
    57
struct tile_segment {
nkeynes@189
    58
    uint32_t control;
nkeynes@189
    59
    pvraddr_t opaque_ptr;
nkeynes@189
    60
    pvraddr_t opaquemod_ptr;
nkeynes@189
    61
    pvraddr_t trans_ptr;
nkeynes@189
    62
    pvraddr_t transmod_ptr;
nkeynes@189
    63
    pvraddr_t punchout_ptr;
nkeynes@189
    64
};
nkeynes@189
    65
nkeynes@189
    66
/**
nkeynes@189
    67
 * Convert a half-float (16-bit) FP number to a regular 32-bit float.
nkeynes@189
    68
 * Source is 1-bit sign, 5-bit exponent, 10-bit mantissa.
nkeynes@189
    69
 * TODO: Check the correctness of this.
nkeynes@189
    70
 */
nkeynes@189
    71
float halftofloat( uint16_t half )
nkeynes@189
    72
{
nkeynes@189
    73
    union {
nkeynes@189
    74
        float f;
nkeynes@189
    75
        uint32_t i;
nkeynes@189
    76
    } temp;
nkeynes@308
    77
    /* int e = ((half & 0x7C00) >> 10) - 15 + 127;
nkeynes@189
    78
nkeynes@189
    79
    temp.i = ((half & 0x8000) << 16) | (e << 23) |
nkeynes@308
    80
    ((half & 0x03FF) << 13); */
nkeynes@308
    81
    temp.i = ((uint32_t)half)<<16;
nkeynes@189
    82
    return temp.f;
nkeynes@189
    83
}
nkeynes@189
    84
nkeynes@189
    85
nkeynes@189
    86
/**
nkeynes@189
    87
 * Setup the GL context for the supplied polygon context.
nkeynes@189
    88
 * @param context pointer to 3 or 5 words of polygon context
nkeynes@189
    89
 * @param modified boolean flag indicating that the modified
nkeynes@189
    90
 *  version should be used, rather than the normal version.
nkeynes@189
    91
 */
nkeynes@189
    92
void render_set_context( uint32_t *context, int render_mode )
nkeynes@189
    93
{
nkeynes@189
    94
    uint32_t poly1 = context[0], poly2, texture;
nkeynes@189
    95
    if( render_mode == RENDER_FULLMOD ) {
nkeynes@189
    96
	poly2 = context[3];
nkeynes@189
    97
	texture = context[4];
nkeynes@189
    98
    } else {
nkeynes@189
    99
	poly2 = context[1];
nkeynes@189
   100
	texture = context[2];
nkeynes@189
   101
    }
nkeynes@189
   102
nkeynes@189
   103
    if( POLY1_DEPTH_ENABLE(poly1) ) {
nkeynes@189
   104
	glEnable( GL_DEPTH_TEST );
nkeynes@189
   105
	glDepthFunc( POLY1_DEPTH_MODE(poly1) );
nkeynes@189
   106
    } else {
nkeynes@189
   107
	glDisable( GL_DEPTH_TEST );
nkeynes@189
   108
    }
nkeynes@189
   109
    
nkeynes@189
   110
    switch( POLY1_CULL_MODE(poly1) ) {
nkeynes@189
   111
    case CULL_NONE:
nkeynes@189
   112
    case CULL_SMALL:
nkeynes@189
   113
	glDisable( GL_CULL_FACE );
nkeynes@189
   114
	break;
nkeynes@189
   115
    case CULL_CCW:
nkeynes@189
   116
	glEnable( GL_CULL_FACE );
nkeynes@189
   117
	glFrontFace( GL_CW );
nkeynes@189
   118
	break;
nkeynes@189
   119
    case CULL_CW:
nkeynes@189
   120
	glEnable( GL_CULL_FACE );
nkeynes@189
   121
	glFrontFace( GL_CCW );
nkeynes@189
   122
	break;
nkeynes@189
   123
    }
nkeynes@189
   124
nkeynes@318
   125
    if( POLY1_SPECULAR(poly1) ) {
nkeynes@318
   126
	glEnable(GL_COLOR_SUM);
nkeynes@318
   127
    } else {
nkeynes@318
   128
	glDisable(GL_COLOR_SUM);
nkeynes@318
   129
    }
nkeynes@318
   130
nkeynes@189
   131
    if( POLY1_TEXTURED(poly1) ) {
nkeynes@189
   132
	int width = POLY2_TEX_WIDTH(poly2);
nkeynes@189
   133
	int height = POLY2_TEX_HEIGHT(poly2);
nkeynes@189
   134
	glEnable(GL_TEXTURE_2D);
nkeynes@286
   135
	texcache_get_texture( (texture&0x000FFFFF)<<3, width, height, texture );
nkeynes@189
   136
	glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, POLY2_TEX_BLEND(poly2) );
nkeynes@308
   137
	if( POLY2_TEX_CLAMP_U(poly2) ) {
nkeynes@308
   138
	    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP );
nkeynes@308
   139
	} else {
nkeynes@308
   140
	    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
nkeynes@308
   141
	}	    
nkeynes@308
   142
	if( POLY2_TEX_CLAMP_V(poly2) ) {
nkeynes@308
   143
	    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );
nkeynes@308
   144
	} else {
nkeynes@308
   145
	    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
nkeynes@308
   146
	}
nkeynes@189
   147
    } else {
nkeynes@189
   148
	glDisable( GL_TEXTURE_2D );
nkeynes@189
   149
    }
nkeynes@189
   150
nkeynes@189
   151
    glShadeModel( POLY1_SHADE_MODEL(poly1) );
nkeynes@189
   152
nkeynes@221
   153
    int srcblend = POLY2_SRC_BLEND(poly2);
nkeynes@221
   154
    int destblend = POLY2_DEST_BLEND(poly2);
nkeynes@221
   155
    glBlendFunc( srcblend, destblend );
nkeynes@318
   156
nkeynes@318
   157
    pvr2_force_fragment_alpha = POLY2_ALPHA_ENABLE(poly2) ? FALSE : TRUE;
nkeynes@318
   158
nkeynes@189
   159
}
nkeynes@189
   160
nkeynes@319
   161
#define FARGB_A(x) (((float)(((x)>>24)+1))/256.0)
nkeynes@319
   162
#define FARGB_R(x) (((float)((((x)>>16)&0xFF)+1))/256.0)
nkeynes@319
   163
#define FARGB_G(x) (((float)((((x)>>8)&0xFF)+1))/256.0)
nkeynes@319
   164
#define FARGB_B(x) (((float)(((x)&0xFF)+1))/256.0)
nkeynes@319
   165
nkeynes@319
   166
void render_unpack_vertexes( struct vertex_unpacked *out, uint32_t poly1, 
nkeynes@319
   167
			     uint32_t *vertexes, int num_vertexes,
nkeynes@319
   168
			     int vertex_size, int render_mode )
nkeynes@319
   169
{
nkeynes@319
   170
    int m = 0, i;
nkeynes@319
   171
    if( render_mode == RENDER_FULLMOD ) {
nkeynes@319
   172
	m = (vertex_size - 3)/2;
nkeynes@319
   173
    }
nkeynes@319
   174
nkeynes@319
   175
    for( i=0; i<num_vertexes; i++ ) {
nkeynes@319
   176
	float *vertexf = (float *)vertexes;
nkeynes@319
   177
	int k = m + 3;
nkeynes@319
   178
	out[i].x = vertexf[0];
nkeynes@319
   179
	out[i].y = vertexf[1];
nkeynes@319
   180
	out[i].z = vertexf[2];
nkeynes@319
   181
    	if( POLY1_TEXTURED(poly1) ) {
nkeynes@319
   182
	    if( POLY1_UV16(poly1) ) {
nkeynes@319
   183
		out[i].u = halftofloat(vertexes[k]>>16);
nkeynes@319
   184
		out[i].v = halftofloat(vertexes[k]);
nkeynes@319
   185
		k++;
nkeynes@319
   186
	    } else {
nkeynes@319
   187
		out[i].u = vertexf[k];
nkeynes@319
   188
		out[i].v = vertexf[k+1];
nkeynes@319
   189
		k+=2;
nkeynes@319
   190
	    }
nkeynes@319
   191
	} else {
nkeynes@319
   192
	    out[i].u = 0;
nkeynes@319
   193
	    out[i].v = 0;
nkeynes@319
   194
	}
nkeynes@319
   195
	uint32_t argb = vertexes[k++];
nkeynes@319
   196
	out[i].rgba[0] = FARGB_R(argb);
nkeynes@319
   197
	out[i].rgba[1] = FARGB_G(argb);
nkeynes@319
   198
        out[i].rgba[2] = FARGB_B(argb);
nkeynes@319
   199
	out[i].rgba[3] = FARGB_A(argb);
nkeynes@319
   200
	if( POLY1_SPECULAR(poly1) ) {
nkeynes@319
   201
	    uint32_t offset = vertexes[k++];
nkeynes@319
   202
	    out[i].offset_rgba[0] = FARGB_R(argb);
nkeynes@319
   203
	    out[i].offset_rgba[1] = FARGB_G(argb);
nkeynes@319
   204
	    out[i].offset_rgba[2] = FARGB_B(argb);
nkeynes@319
   205
	    out[i].offset_rgba[3] = FARGB_A(argb);
nkeynes@319
   206
	}
nkeynes@319
   207
	vertexes += vertex_size;
nkeynes@319
   208
    }
nkeynes@319
   209
}
nkeynes@319
   210
nkeynes@319
   211
/**
nkeynes@319
   212
 * Unpack the vertexes for a quad, calculating the values for the last
nkeynes@319
   213
 * vertex.
nkeynes@319
   214
 * FIXME: Integrate this with rendbkg somehow
nkeynes@319
   215
 */
nkeynes@319
   216
void render_unpack_quad( struct vertex_unpacked *unpacked, uint32_t poly1, 
nkeynes@319
   217
			 uint32_t *vertexes, int vertex_size,
nkeynes@319
   218
			 int render_mode )
nkeynes@319
   219
{
nkeynes@319
   220
    int i;
nkeynes@319
   221
    struct vertex_unpacked diff0, diff1;
nkeynes@319
   222
nkeynes@319
   223
    render_unpack_vertexes( unpacked, poly1, vertexes, 3, vertex_size, render_mode );
nkeynes@319
   224
    
nkeynes@319
   225
    diff0.x = unpacked[0].x - unpacked[1].x;
nkeynes@319
   226
    diff0.y = unpacked[0].y - unpacked[1].y;
nkeynes@319
   227
    diff1.x = unpacked[2].x - unpacked[1].x;
nkeynes@319
   228
    diff1.y = unpacked[2].y - unpacked[1].y;
nkeynes@319
   229
nkeynes@319
   230
    float detxy = ((diff1.y) * (diff0.x)) - ((diff0.y) * (diff1.x));
nkeynes@319
   231
    float *vertexf = (float *)(vertexes+(vertex_size*3));
nkeynes@319
   232
    if( detxy == 0 ) {
nkeynes@319
   233
	memcpy( &unpacked[3], &unpacked[2], sizeof(struct vertex_unpacked) );
nkeynes@319
   234
	unpacked[3].x = vertexf[0];
nkeynes@319
   235
	unpacked[3].y = vertexf[1];
nkeynes@319
   236
	return;
nkeynes@319
   237
    }	
nkeynes@319
   238
nkeynes@319
   239
    unpacked[3].x = vertexf[0];
nkeynes@319
   240
    unpacked[3].y = vertexf[1];
nkeynes@319
   241
    float t = ((unpacked[3].x - unpacked[1].x) * diff1.y -
nkeynes@319
   242
	       (unpacked[3].y - unpacked[1].y) * diff1.x) / detxy;
nkeynes@319
   243
    float s = ((unpacked[3].y - unpacked[1].y) * diff0.x -
nkeynes@319
   244
	       (unpacked[3].x - unpacked[1].x) * diff0.y) / detxy;
nkeynes@319
   245
    diff0.z = unpacked[0].z - unpacked[1].z;
nkeynes@319
   246
    diff1.z = unpacked[2].z - unpacked[1].z;
nkeynes@319
   247
    unpacked[3].z = unpacked[1].z + (t*diff0.z) + (s*diff1.z);
nkeynes@319
   248
nkeynes@319
   249
    diff0.u = unpacked[0].u - unpacked[1].u;
nkeynes@319
   250
    diff0.v = unpacked[0].v - unpacked[1].v;
nkeynes@319
   251
    diff1.u = unpacked[2].u - unpacked[1].u;
nkeynes@319
   252
    diff1.v = unpacked[2].v - unpacked[1].v;
nkeynes@319
   253
    unpacked[3].u = unpacked[1].u + (t*diff0.u) + (s*diff1.u);
nkeynes@319
   254
    unpacked[3].v = unpacked[1].v + (t*diff0.v) + (s*diff1.v);
nkeynes@319
   255
nkeynes@319
   256
    if( !POLY1_GOURAUD_SHADED(poly1) ) {
nkeynes@319
   257
	memcpy( unpacked[3].rgba, unpacked[2].rgba, sizeof(unpacked[2].rgba) );
nkeynes@319
   258
	memcpy( unpacked[3].offset_rgba, unpacked[2].offset_rgba, sizeof(unpacked[2].offset_rgba) );
nkeynes@319
   259
    } else {
nkeynes@319
   260
	for( i=0; i<4; i++ ) {
nkeynes@319
   261
	    float d0 = unpacked[0].rgba[i] - unpacked[1].rgba[i];
nkeynes@319
   262
	    float d1 = unpacked[2].rgba[i] - unpacked[1].rgba[i];
nkeynes@319
   263
	    unpacked[3].rgba[i] = unpacked[1].rgba[i] + (t*d0) + (s*d1);
nkeynes@319
   264
	    d0 = unpacked[0].offset_rgba[i] - unpacked[1].offset_rgba[i];
nkeynes@319
   265
	    d1 = unpacked[2].offset_rgba[i] - unpacked[1].offset_rgba[i];
nkeynes@319
   266
	    unpacked[3].offset_rgba[i] = unpacked[1].offset_rgba[i] + (t*d0) + (s*d1);
nkeynes@319
   267
	}
nkeynes@319
   268
    }    
nkeynes@319
   269
}
nkeynes@319
   270
nkeynes@319
   271
void render_unpacked_vertex_array( uint32_t poly1, struct vertex_unpacked *vertexes[], 
nkeynes@319
   272
				   int num_vertexes ) {
nkeynes@319
   273
    int i;
nkeynes@319
   274
nkeynes@319
   275
    glBegin( GL_TRIANGLE_STRIP );
nkeynes@319
   276
nkeynes@319
   277
    for( i=0; i<num_vertexes; i++ ) {
nkeynes@319
   278
	if( POLY1_TEXTURED(poly1) ) {
nkeynes@319
   279
	    glTexCoord2f( vertexes[i]->u, vertexes[i]->v );
nkeynes@319
   280
	}
nkeynes@319
   281
nkeynes@319
   282
	glColor4f( vertexes[i]->rgba[0], vertexes[i]->rgba[1], vertexes[i]->rgba[2],
nkeynes@319
   283
		   (pvr2_force_fragment_alpha ? 1.0 : vertexes[i]->rgba[3]) );
nkeynes@319
   284
nkeynes@319
   285
	if( POLY1_SPECULAR(poly1) ) {
nkeynes@319
   286
	    glSecondaryColor3fEXT( vertexes[i]->offset_rgba[0],
nkeynes@319
   287
				   vertexes[i]->offset_rgba[1],
nkeynes@319
   288
				   vertexes[i]->offset_rgba[2] );
nkeynes@319
   289
	}
nkeynes@319
   290
	glVertex3f( vertexes[i]->x, vertexes[i]->y, vertexes[i]->z );
nkeynes@319
   291
    }
nkeynes@319
   292
nkeynes@319
   293
    glEnd();
nkeynes@319
   294
}
nkeynes@319
   295
nkeynes@319
   296
void render_quad_vertexes( uint32_t poly1, uint32_t *vertexes, int vertex_size, int render_mode )
nkeynes@319
   297
{
nkeynes@319
   298
    struct vertex_unpacked unpacked[4];
nkeynes@319
   299
    struct vertex_unpacked *pt[4] = {&unpacked[0], &unpacked[1], &unpacked[3], &unpacked[2]};
nkeynes@319
   300
    render_unpack_quad( unpacked, poly1, vertexes, vertex_size, render_mode );
nkeynes@319
   301
    render_unpacked_vertex_array( poly1, pt, 4 );
nkeynes@319
   302
}
nkeynes@319
   303
nkeynes@319
   304
void render_vertex_array( uint32_t poly1, uint32_t *vert_array[], int num_vertexes, int vertex_size,
nkeynes@319
   305
			  int render_mode ) 
nkeynes@189
   306
{
nkeynes@189
   307
    int i, m=0;
nkeynes@189
   308
nkeynes@189
   309
    if( render_mode == RENDER_FULLMOD ) {
nkeynes@189
   310
	m = (vertex_size - 3)/2;
nkeynes@189
   311
    }
nkeynes@189
   312
nkeynes@189
   313
    glBegin( GL_TRIANGLE_STRIP );
nkeynes@189
   314
    
nkeynes@189
   315
    for( i=0; i<num_vertexes; i++ ) {
nkeynes@319
   316
	uint32_t *vertexes = vert_array[i];
nkeynes@319
   317
	float *vertexf = (float *)vert_array[i];
nkeynes@189
   318
	uint32_t argb;
nkeynes@318
   319
	int k = m + 3;
nkeynes@189
   320
	if( POLY1_TEXTURED(poly1) ) {
nkeynes@189
   321
	    if( POLY1_UV16(poly1) ) {
nkeynes@318
   322
		glTexCoord2f( halftofloat(vertexes[k]>>16),
nkeynes@318
   323
			      halftofloat(vertexes[k]) );
nkeynes@318
   324
		k++;
nkeynes@189
   325
	    } else {
nkeynes@318
   326
		glTexCoord2f( vertexf[k], vertexf[k+1] );
nkeynes@318
   327
		k+=2;
nkeynes@189
   328
	    }
nkeynes@189
   329
	}
nkeynes@189
   330
nkeynes@318
   331
	argb = vertexes[k++];
nkeynes@318
   332
	if( pvr2_force_fragment_alpha ) {
nkeynes@318
   333
	    glColor4ub( (GLubyte)(argb >> 16), (GLubyte)(argb >> 8), 
nkeynes@318
   334
			(GLubyte)argb, 0xFF );
nkeynes@318
   335
	} else {
nkeynes@318
   336
	    glColor4ub( (GLubyte)(argb >> 16), (GLubyte)(argb >> 8), 
nkeynes@318
   337
			(GLubyte)argb, (GLubyte)(argb >> 24) );
nkeynes@318
   338
	}
nkeynes@318
   339
nkeynes@318
   340
	if( POLY1_SPECULAR(poly1) ) {
nkeynes@318
   341
	    uint32_t spec = vertexes[k++];
nkeynes@318
   342
	    glSecondaryColor3ubEXT( (GLubyte)(spec >> 16), (GLubyte)(spec >> 8), 
nkeynes@318
   343
				 (GLubyte)spec );
nkeynes@318
   344
	}
nkeynes@189
   345
	glVertex3f( vertexf[0], vertexf[1], vertexf[2] );
nkeynes@189
   346
	vertexes += vertex_size;
nkeynes@189
   347
    }
nkeynes@189
   348
nkeynes@189
   349
    glEnd();
nkeynes@189
   350
}
nkeynes@189
   351
nkeynes@319
   352
void render_vertexes( uint32_t poly1, uint32_t *vertexes, int num_vertexes, int vertex_size,
nkeynes@319
   353
		      int render_mode )
nkeynes@319
   354
{
nkeynes@319
   355
    uint32_t *vert_array[num_vertexes];
nkeynes@319
   356
    int i;
nkeynes@319
   357
    for( i=0; i<num_vertexes; i++ ) {
nkeynes@319
   358
	vert_array[i] = vertexes;
nkeynes@319
   359
	vertexes += vertex_size;
nkeynes@319
   360
    }
nkeynes@319
   361
    render_vertex_array( poly1, vert_array, num_vertexes, vertex_size, render_mode );
nkeynes@319
   362
}
nkeynes@319
   363
nkeynes@189
   364
/**
nkeynes@189
   365
 * Render a simple (not auto-sorted) tile
nkeynes@189
   366
 */
nkeynes@189
   367
void render_tile( pvraddr_t tile_entry, int render_mode, gboolean cheap_modifier_mode ) {
nkeynes@215
   368
    uint32_t poly_bank = MMIO_READ(PVR2,RENDER_POLYBASE);
nkeynes@189
   369
    uint32_t *tile_list = (uint32_t *)(video_base+tile_entry);
nkeynes@189
   370
    do {
nkeynes@189
   371
	uint32_t entry = *tile_list++;
nkeynes@189
   372
	if( entry >> 28 == 0x0F ) {
nkeynes@189
   373
	    break;
nkeynes@189
   374
	} else if( entry >> 28 == 0x0E ) {
nkeynes@189
   375
	    tile_list = (uint32_t *)(video_base + (entry&0x007FFFFF));
nkeynes@189
   376
	} else {
nkeynes@215
   377
	    uint32_t *polygon = (uint32_t *)(video_base + poly_bank + ((entry & 0x000FFFFF) << 2));
nkeynes@189
   378
	    int is_modified = entry & 0x01000000;
nkeynes@189
   379
	    int vertex_length = (entry >> 21) & 0x07;
nkeynes@189
   380
	    int context_length = 3;
nkeynes@189
   381
	    if( is_modified && !cheap_modifier_mode ) {
nkeynes@189
   382
		context_length = 5;
nkeynes@189
   383
		vertex_length *= 2 ;
nkeynes@189
   384
	    }
nkeynes@189
   385
	    vertex_length += 3;
nkeynes@308
   386
	    
nkeynes@189
   387
	    if( (entry & 0xE0000000) == 0x80000000 ) {
nkeynes@189
   388
		/* Triangle(s) */
nkeynes@189
   389
		int strip_count = ((entry >> 25) & 0x0F)+1;
nkeynes@189
   390
		int polygon_length = 3 * vertex_length + context_length;
nkeynes@189
   391
		int i;
nkeynes@189
   392
		for( i=0; i<strip_count; i++ ) {
nkeynes@189
   393
		    render_set_context( polygon, render_mode );
nkeynes@189
   394
		    render_vertexes( *polygon, polygon+context_length, 3, vertex_length,
nkeynes@189
   395
				     render_mode );
nkeynes@189
   396
		    polygon += polygon_length;
nkeynes@189
   397
		}
nkeynes@189
   398
	    } else if( (entry & 0xE0000000) == 0xA0000000 ) {
nkeynes@189
   399
		/* Sprite(s) */
nkeynes@319
   400
		int strip_count = ((entry >> 25) & 0x0F)+1;
nkeynes@189
   401
		int polygon_length = 4 * vertex_length + context_length;
nkeynes@189
   402
		int i;
nkeynes@189
   403
		for( i=0; i<strip_count; i++ ) {
nkeynes@189
   404
		    render_set_context( polygon, render_mode );
nkeynes@319
   405
		    render_quad_vertexes( *polygon, polygon+context_length, vertex_length,
nkeynes@319
   406
					  render_mode );
nkeynes@189
   407
		    polygon += polygon_length;
nkeynes@189
   408
		}
nkeynes@189
   409
	    } else {
nkeynes@189
   410
		/* Polygon */
nkeynes@189
   411
		int i, first=-1, last = -1;
nkeynes@189
   412
		for( i=0; i<6; i++ ) {
nkeynes@189
   413
		    if( entry & (0x40000000>>i) ) {
nkeynes@189
   414
			if( first == -1 ) first = i;
nkeynes@189
   415
			last = i;
nkeynes@189
   416
		    }
nkeynes@189
   417
		}
nkeynes@189
   418
		if( first != -1 ) {
nkeynes@189
   419
		    first = 0;
nkeynes@189
   420
		    render_set_context(polygon, render_mode);
nkeynes@189
   421
		    render_vertexes( *polygon, polygon+context_length + (first*vertex_length),
nkeynes@189
   422
				     (last-first+3), vertex_length, render_mode );
nkeynes@189
   423
		}
nkeynes@189
   424
	    }
nkeynes@189
   425
	}
nkeynes@189
   426
    } while( 1 );
nkeynes@189
   427
}
nkeynes@189
   428
nkeynes@189
   429
void pvr2_render_tilebuffer( int width, int height, int clipx1, int clipy1, 
nkeynes@189
   430
			int clipx2, int clipy2 ) {
nkeynes@189
   431
nkeynes@191
   432
    pvraddr_t segmentbase = MMIO_READ( PVR2, RENDER_TILEBASE );
nkeynes@189
   433
    int tile_sort;
nkeynes@189
   434
    gboolean cheap_shadow;
nkeynes@189
   435
nkeynes@191
   436
    int obj_config = MMIO_READ( PVR2, RENDER_OBJCFG );
nkeynes@191
   437
    int isp_config = MMIO_READ( PVR2, RENDER_ISPCFG );
nkeynes@191
   438
    int shadow_cfg = MMIO_READ( PVR2, RENDER_SHADOW );
nkeynes@189
   439
nkeynes@222
   440
    if( (obj_config & 0x00200000) == 0 ) {
nkeynes@189
   441
	if( isp_config & 1 ) {
nkeynes@189
   442
	    tile_sort = 0;
nkeynes@189
   443
	} else {
nkeynes@189
   444
	    tile_sort = 2;
nkeynes@189
   445
	}
nkeynes@189
   446
    } else {
nkeynes@189
   447
	tile_sort = 1;
nkeynes@189
   448
    }
nkeynes@189
   449
nkeynes@189
   450
    cheap_shadow = shadow_cfg & 0x100 ? TRUE : FALSE;
nkeynes@189
   451
nkeynes@189
   452
    struct tile_segment *segment = (struct tile_segment *)(video_base + segmentbase);
nkeynes@189
   453
nkeynes@215
   454
    struct timeval tv_start, tv_end;
nkeynes@215
   455
    gettimeofday(&tv_start, NULL);
nkeynes@189
   456
    glEnable( GL_SCISSOR_TEST );
nkeynes@268
   457
    do {
nkeynes@221
   458
	// fwrite_dump32v( (uint32_t *)segment, sizeof(struct tile_segment), 6, stderr );
nkeynes@189
   459
	int tilex = SEGMENT_X(segment->control);
nkeynes@189
   460
	int tiley = SEGMENT_Y(segment->control);
nkeynes@189
   461
	
nkeynes@189
   462
	int x1 = tilex << 5;
nkeynes@189
   463
	int y1 = tiley << 5;
nkeynes@189
   464
	if( x1 + 32 <= clipx1 ||
nkeynes@189
   465
	    y1 + 32 <= clipy1 ||
nkeynes@189
   466
	    x1 >= clipx2 ||
nkeynes@189
   467
	    y1 >= clipy2 ) {
nkeynes@189
   468
	    /* Tile completely clipped, skip */
nkeynes@189
   469
	    continue;
nkeynes@189
   470
	}
nkeynes@215
   471
nkeynes@189
   472
	/* Set a scissor on the visible part of the tile */
nkeynes@189
   473
	int w = MIN(x1+32, clipx2) - x1;
nkeynes@189
   474
	int h = MIN(y1+32, clipy2) - y1;
nkeynes@189
   475
	x1 = MAX(x1,clipx1);
nkeynes@189
   476
	y1 = MAX(y1,clipy1);
nkeynes@189
   477
	glScissor( x1, height-y1-h, w, h );
nkeynes@189
   478
nkeynes@189
   479
	if( (segment->opaque_ptr & NO_POINTER) == 0 ) {
nkeynes@189
   480
	    if( (segment->opaquemod_ptr & NO_POINTER) == 0 ) {
nkeynes@189
   481
		/* TODO */
nkeynes@189
   482
	    }
nkeynes@189
   483
	    render_tile( segment->opaque_ptr, RENDER_NORMAL, cheap_shadow );
nkeynes@189
   484
	}
nkeynes@189
   485
nkeynes@189
   486
	if( (segment->trans_ptr & NO_POINTER) == 0 ) {
nkeynes@189
   487
	    if( (segment->transmod_ptr & NO_POINTER) == 0 ) {
nkeynes@189
   488
		/* TODO */
nkeynes@189
   489
	    } 
nkeynes@222
   490
	    if( tile_sort == 2 || 
nkeynes@222
   491
		(tile_sort == 1 && ((segment->control & SEGMENT_SORT_TRANS)==0)) ) {
nkeynes@189
   492
		render_autosort_tile( segment->trans_ptr, RENDER_NORMAL, cheap_shadow );
nkeynes@189
   493
	    } else {
nkeynes@189
   494
		render_tile( segment->trans_ptr, RENDER_NORMAL, cheap_shadow );
nkeynes@189
   495
	    }
nkeynes@189
   496
	}
nkeynes@189
   497
nkeynes@189
   498
	if( (segment->punchout_ptr & NO_POINTER) == 0 ) {
nkeynes@189
   499
	    render_tile( segment->punchout_ptr, RENDER_NORMAL, cheap_shadow );
nkeynes@189
   500
	}
nkeynes@268
   501
    } while( ((segment++)->control & SEGMENT_END) == 0 );
nkeynes@189
   502
    glDisable( GL_SCISSOR_TEST );
nkeynes@215
   503
nkeynes@215
   504
    gettimeofday(&tv_end, NULL);
nkeynes@215
   505
    timersub(&tv_end,&tv_start, &tv_start);
nkeynes@189
   506
}
.