Search
lxdream.org :: lxdream :: r221:cf5c6d326162
lxdream 0.9.1
released Jun 29
Download Now
changeset221:cf5c6d326162
parent220:f72f8a7dff88
child222:541d9d899aba
authornkeynes
dateTue Sep 12 08:38:38 2006 +0000 (13 years ago)
Bug #0010
Move polygon macros to pvr2.h
Implement background rendering more fully
src/pvr2/pvr2.h
src/pvr2/rendbkg.c
src/pvr2/rendcore.c
src/pvr2/render.c
1.1 --- a/src/pvr2/pvr2.h Tue Sep 12 08:36:09 2006 +0000
1.2 +++ b/src/pvr2/pvr2.h Tue Sep 12 08:38:38 2006 +0000
1.3 @@ -1,5 +1,5 @@
1.4 /**
1.5 - * $Id: pvr2.h,v 1.16 2006-08-29 08:12:13 nkeynes Exp $
1.6 + * $Id: pvr2.h,v 1.17 2006-09-12 08:38:38 nkeynes Exp $
1.7 *
1.8 * PVR2 (video chip) functions and macros.
1.9 *
1.10 @@ -202,3 +202,31 @@
1.11 */
1.12 GLuint texcache_get_texture( uint32_t texture_addr, int width, int height,
1.13 int mode );
1.14 +
1.15 +/************************* Rendering support macros **************************/
1.16 +#define POLY1_DEPTH_MODE(poly1) ( pvr2_poly_depthmode[(poly1)>>29] )
1.17 +#define POLY1_DEPTH_ENABLE(poly1) (((poly1)&0x04000000) == 0 )
1.18 +#define POLY1_CULL_MODE(poly1) (((poly1)>>27)&0x03)
1.19 +#define POLY1_TEXTURED(poly1) (((poly1)&0x02000000))
1.20 +#define POLY1_SPECULAR(poly1) (((poly1)&0x01000000))
1.21 +#define POLY1_SHADE_MODEL(poly1) (((poly1)&0x00800000) ? GL_SMOOTH : GL_FLAT)
1.22 +#define POLY1_UV16(poly1) (((poly1)&0x00400000))
1.23 +#define POLY1_SINGLE_TILE(poly1) (((poly1)&0x00200000))
1.24 +
1.25 +#define POLY2_SRC_BLEND(poly2) ( pvr2_poly_srcblend[(poly2) >> 29] )
1.26 +#define POLY2_DEST_BLEND(poly2) ( pvr2_poly_dstblend[((poly2)>>26)&0x07] )
1.27 +#define POLY2_SRC_BLEND_ENABLE(poly2) ((poly2)&0x02000000)
1.28 +#define POLY2_DEST_BLEND_ENABLE(poly2) ((poly2)&0x01000000)
1.29 +#define POLY2_COLOUR_CLAMP_ENABLE(poly2) ((poly2)&0x00200000)
1.30 +#define POLY2_ALPHA_ENABLE(poly2) ((poly2)&0x001000000)
1.31 +#define POLY2_TEX_ALPHA_ENABLE(poly2) (((poly2)&0x00080000) == 0 )
1.32 +#define POLY2_TEX_WIDTH(poly2) ( 1<< ((((poly2) >> 3) & 0x07 ) + 3) )
1.33 +#define POLY2_TEX_HEIGHT(poly2) ( 1<< (((poly2) & 0x07 ) + 3) )
1.34 +#define POLY2_TEX_BLEND(poly2) ( pvr2_poly_texblend[((poly2) >> 6)&0x03] )
1.35 +extern int pvr2_poly_depthmode[8];
1.36 +extern int pvr2_poly_srcblend[8];
1.37 +extern int pvr2_poly_dstblend[8];
1.38 +extern int pvr2_poly_texblend[4];
1.39 +extern int pvr2_render_colour_format[8];
1.40 +
1.41 +float halftofloat(uint16_t half);
2.1 --- a/src/pvr2/rendbkg.c Tue Sep 12 08:36:09 2006 +0000
2.2 +++ b/src/pvr2/rendbkg.c Tue Sep 12 08:38:38 2006 +0000
2.3 @@ -1,11 +1,15 @@
2.4 /**
2.5 - * $Id: rendbkg.c,v 1.1 2006-08-29 08:12:13 nkeynes Exp $
2.6 + * $Id: rendbkg.c,v 1.2 2006-09-12 08:38:38 nkeynes Exp $
2.7 *
2.8 * PVR2 background renderer.
2.9 *
2.10 * Yes, it uses the same basic data structure. Yes, it needs to be handled
2.11 * completely differently.
2.12 *
2.13 + * Note: this would be really simple if GL did unclamped colour interpolation
2.14 + * but it doesn't (portably), which makes this roughly 2 orders of magnitude
2.15 + * more complicated than it otherwise would be.
2.16 + *
2.17 * Copyright (c) 2005 Nathan Keynes.
2.18 *
2.19 * This program is free software; you can redistribute it and/or modify
2.20 @@ -21,12 +25,16 @@
2.21
2.22 #include <sys/time.h>
2.23 #include "pvr2/pvr2.h"
2.24 +#include <GL/glext.h>
2.25 +#include <math.h>
2.26
2.27 -struct vertex_rgba {
2.28 - float x,y,z;
2.29 - uint32_t argb;
2.30 -};
2.31 +#define MAX_CLAMP_LINES 8
2.32 +#define MAX_VERTEXES 256
2.33 +#define MAX_REGIONS 256
2.34
2.35 +/**
2.36 + * Structure to hold an unpacked vertex
2.37 + */
2.38 struct vertex_all {
2.39 float x,y,z;
2.40 float u,v;
2.41 @@ -40,6 +48,398 @@
2.42 #define FARGB_B(x) (((float)(((x)&0xFF)+1))/256.0)
2.43
2.44 /**
2.45 + * Compute the line where k = target_k, (where k is normally one of
2.46 + * r,g,b,a, or z) and determines the points at which the line intersects
2.47 + * the viewport (0,0,width,height).
2.48 + *
2.49 + * @param center_x the x value for the center position
2.50 + * @param center_y the y value for the center position
2.51 + * @param center_k the k value for the center position
2.52 + * @param width Width of the viewport (ie 640)
2.53 + * @param height Height of the viewport (ie 480)
2.54 + * @param target_k determine the line where k = this value, ie 1.0
2.55 + * @param detxy
2.56 + * @param target Array to write the resultant x,y pairs to (note this
2.57 + * function only sets x and y values).
2.58 + * @return number of vertexes written to the target.
2.59 + */
2.60 +static int compute_colour_line( float center_x, float center_y, float center_k,
2.61 + int width, int height, float target_k,
2.62 + float detxy, float detxk, float detyk,
2.63 + struct vertex_all *target ) {
2.64 + int num_points = 0;
2.65 + float tmpk = (target_k - center_k) * detxy;
2.66 + float x0 = -1;
2.67 + float x1 = -1;
2.68 +
2.69 + if( detyk != 0 ) {
2.70 + x0 = (tmpk - ((0-center_y)*detxk))/detyk + center_x; /* x where y=0 */
2.71 + if( x0 >= 0.0 && x0 <= width ) {
2.72 + target[num_points].x = x0;
2.73 + target[num_points].y = 0.0;
2.74 + num_points++;
2.75 + }
2.76 +
2.77 + x1 = (tmpk - ((height-center_y)*detxk))/detyk + center_x; /* x where y=height */
2.78 + if( x1 >= 0.0 && x1 <= width ) {
2.79 + target[num_points].x = x1;
2.80 + target[num_points].y = height;
2.81 + num_points++;
2.82 + }
2.83 + }
2.84 +
2.85 + if( detxk != 0 ) {
2.86 + if( x0 != 0.0 && x1 != 0.0 ) { /* If x0 == 0 or x1 == 0, then we already have this one */
2.87 + float y0 = (tmpk - ((0-center_x)*detyk))/detxk + center_y; /* y where x=0 */
2.88 + if( y0 >= 0.0 && y0 <= height ) {
2.89 + target[num_points].x = 0.0;
2.90 + target[num_points].y = y0;
2.91 + num_points++;
2.92 + }
2.93 + }
2.94 +
2.95 + if( x0 != width && x1 != width ) {
2.96 + float y1 = (tmpk - ((width-center_x)*detyk))/detxk + center_y; /* y where x=width */
2.97 + if( y1 >= 0.0 && y1 <= height ) {
2.98 + target[num_points].x = width;
2.99 + target[num_points].y = y1;
2.100 + num_points++;
2.101 + }
2.102 + }
2.103 + }
2.104 +
2.105 + if( num_points == 0 || num_points == 2 ) {
2.106 + /* 0 = no points - line doesn't pass through the viewport */
2.107 + /* 2 = normal case - got 2 endpoints */
2.108 + return num_points;
2.109 + } else {
2.110 + ERROR( "compute_colour_line got bad number of points: %d", num_points );
2.111 + return 0;
2.112 + }
2.113 +}
2.114 +
2.115 +/**
2.116 + * A region describes a portion of the screen, possibly subdivided by a line.
2.117 + * if region_left and region_right are -1, this is a terminal region that can
2.118 + * be rendered directly. Otherwise region_left and region_right refer two
2.119 + * sub-regions that are separated by the line segment vertex1-vertex2.
2.120 + */
2.121 +struct bkg_region {
2.122 + /* Vertexes marking the line segment that splits this region */
2.123 + int vertex1;
2.124 + int vertex2;
2.125 + /* Index of the left sub-region */
2.126 + int region_left;
2.127 + /* Index of the right sub-region */
2.128 + int region_right;
2.129 +};
2.130 +
2.131 +/**
2.132 + * Convenience structure to bundle together the vertex and region data.
2.133 + */
2.134 +struct bkg_scene {
2.135 + int num_vertexes;
2.136 + int num_regions;
2.137 + struct vertex_all vertexes[MAX_VERTEXES];
2.138 + struct bkg_region regions[MAX_REGIONS];
2.139 +};
2.140 +
2.141 +void parse_vertexes( uint32_t *polygon, int num_vertexes, struct vertex_all *result )
2.142 +{
2.143 + uint32_t *vertexes = polygon + 3;
2.144 + int i,m = 0;
2.145 + for( i=0; i<num_vertexes; i++ ) {
2.146 + float *vertexf = (float *)vertexes;
2.147 + result[i].x = vertexf[0];
2.148 + result[i].y = vertexf[1];
2.149 + result[i].z = vertexf[2];
2.150 + uint32_t argb;
2.151 + if( POLY1_TEXTURED(*polygon) ) {
2.152 + if( POLY1_UV16(*polygon) ) {
2.153 + result[i].u = halftofloat(vertexes[m+3]>>16);
2.154 + result[i].v = halftofloat(vertexes[m+3]);
2.155 + argb = vertexes[m+4];
2.156 + vertexes += 5;
2.157 + } else {
2.158 + result[i].u = vertexf[m+3];
2.159 + result[i].v = vertexf[m+4];
2.160 + argb = vertexes[m+5];
2.161 + vertexes += 6;
2.162 + }
2.163 + } else {
2.164 + argb = vertexes[m+3];
2.165 + vertexes += 4;
2.166 + }
2.167 + result[i].rgba[0] = FARGB_R(argb);
2.168 + result[i].rgba[1] = FARGB_G(argb);
2.169 + result[i].rgba[2] = FARGB_B(argb);
2.170 + result[i].rgba[3] = FARGB_A(argb);
2.171 + }
2.172 +
2.173 +}
2.174 +
2.175 +/**
2.176 + * Constants returned by compute_line_intersection. Note that for these purposes,
2.177 + * "Left" means the point(s) result in a negative value in the line equation, while
2.178 + * "Right" means the points(s) result in a positive value in the line equation. The
2.179 + * exact meaning isn't particularly important though, as long as we're consistent
2.180 + * throughout this process
2.181 + */
2.182 +#define LINE_COLLINEAR 0 /* The line segments are part of the same line */
2.183 +#define LINE_SIDE_LEFT 1 /* The second line is entirely to the "left" of the first line */
2.184 +#define LINE_SIDE_RIGHT 2 /* The second line is entirely to the "right" of the first line */
2.185 +#define LINE_INTERSECT_FROM_LEFT 3 /* The lines intersect, and (x3,y3) is to the "left" of the first line */
2.186 +#define LINE_INTERSECT_FROM_RIGHT 4 /* The lines intersect, and (x3,y3) is to the "right" of the first line */
2.187 +#define LINE_SKEW 5 /* The line segments neither intersect nor do any of the above apply (should never happen here) */
2.188 +
2.189 +/**
2.190 + * Compute the intersection of two line segments, where
2.191 + * (x1,y1)-(x2,y2) defines the target segment, and
2.192 + * (x3,y3)-(x4,y4) defines the line intersecting it.
2.193 + *
2.194 + * Based off work by Mukesh Prasad (http://www.acm.org/pubs/tog/GraphicsGems/index.html)
2.195 + *
2.196 + * @return one of the above LINE_* constants
2.197 + */
2.198 +static int compute_line_intersection( float x1, float y1, /* First line segment */
2.199 + float x2, float y2,
2.200 + float x3, float y3, /* Second line segment */
2.201 + float x4, float y4,
2.202 + float *x, float *y ) /* Output value: */
2.203 +{
2.204 + float a1, a2, b1, b2, c1, c2; /* Coefficients of line eqns. */
2.205 + float r1, r2, r3, r4; /* test values */
2.206 + float denom; /* Intermediate values */
2.207 +
2.208 + /* Compute a1, b1, c1, where line joining points 1 and 2
2.209 + * is "a1 x + b1 y + c1 = 0".
2.210 + */
2.211 +
2.212 + a1 = y2 - y1;
2.213 + b1 = x1 - x2;
2.214 + c1 = x2 * y1 - x1 * y2;
2.215 +
2.216 + /* Compute r3 and r4. */
2.217 +
2.218 + r3 = a1 * x3 + b1 * y3 + c1;
2.219 + r4 = a1 * x4 + b1 * y4 + c1;
2.220 +
2.221 + /* Check signs of r3 and r4. If both point 3 and point 4 lie on
2.222 + * same side of line 1, the line segments do not intersect.
2.223 + */
2.224 +
2.225 + if( r3 == 0 && r4 == 0 ) {
2.226 + return LINE_COLLINEAR;
2.227 + } else if( r3 <= 0 && r4 <= 0 ) {
2.228 + return LINE_SIDE_LEFT;
2.229 + } else if( r3 >= 0 && r4 >= 0 ) {
2.230 + return LINE_SIDE_RIGHT;
2.231 + }
2.232 +
2.233 + /* Compute a2, b2, c2 */
2.234 +
2.235 + a2 = y4 - y3;
2.236 + b2 = x3 - x4;
2.237 + c2 = x4 * y3 - x3 * y4;
2.238 +
2.239 + /* Compute r1 and r2 */
2.240 +
2.241 + r1 = a2 * x1 + b2 * y1 + c2;
2.242 + r2 = a2 * x2 + b2 * y2 + c2;
2.243 +
2.244 + /* Check signs of r1 and r2. If both point 1 and point 2 lie
2.245 + * on same side of second line segment, the line segments do
2.246 + * not intersect.
2.247 + */
2.248 +
2.249 + if ( r1 != 0 && r2 != 0 &&
2.250 + signbit(r1) == signbit(r2) ) {
2.251 + return LINE_SKEW; /* Should never happen */
2.252 + }
2.253 +
2.254 + /* Cmpute intersection point.
2.255 + */
2.256 + denom = a1 * b2 - a2 * b1;
2.257 + if ( denom == 0 )
2.258 + return LINE_COLLINEAR; /* Should never get to this point either */
2.259 +
2.260 + *x = (b1 * c2 - b2 * c1) / denom;
2.261 + *y = (a2 * c1 - a1 * c2) / denom;
2.262 +
2.263 + if( r3 <= 0 && r4 >= 0 ) {
2.264 + return LINE_INTERSECT_FROM_LEFT;
2.265 + } else {
2.266 + return LINE_INTERSECT_FROM_RIGHT;
2.267 + }
2.268 +}
2.269 +
2.270 +/**
2.271 + * Given a set of vertexes and a line segment to use to split them, generates
2.272 + * two sets of vertexes representing the polygon on either side of the line
2.273 + * segment. This method preserves the winding direction of the input vertexes.
2.274 + */
2.275 +static void compute_subregions( struct bkg_scene *scene,
2.276 + int splitv1, int splitv2,
2.277 + int *vertex_in, int num_vertex_in,
2.278 + int *left_vertex_out, int *num_left_vertex_out,
2.279 + int *right_vertex_out, int *num_right_vertex_out )
2.280 +{
2.281 + float x1 = scene->vertexes[splitv1].x;
2.282 + float y1 = scene->vertexes[splitv1].y;
2.283 + float x2 = scene->vertexes[splitv2].x;
2.284 + float y2 = scene->vertexes[splitv2].y;
2.285 +
2.286 + float a1 = y2 - y1;
2.287 + float b1 = x1 - x2;
2.288 + float c1 = x2 * y1 - x1 * y2;
2.289 + int i;
2.290 +
2.291 + *num_left_vertex_out = 0;
2.292 + *num_right_vertex_out = 0;
2.293 + int last = 0;
2.294 + for( i=0; i<num_vertex_in; i++ ) {
2.295 + struct vertex_all *vertex = &scene->vertexes[vertex_in[i]];
2.296 + float r = a1 * vertex->x + b1 * vertex->y + c1;
2.297 + if( r <= 0 ) {
2.298 + if( last == 1 ) {
2.299 + /* cross-point. add the split vertexes */
2.300 + int v1 = vertex_in[i-1];
2.301 + int v2 = vertex_in[i];
2.302 + /* Determine which point is closer to the line. Strictly speaking
2.303 + * one of them must be ON the line, but this way allows for floating
2.304 + * point inaccuracies.
2.305 + */
2.306 + float a2 = scene->vertexes[v2].y - scene->vertexes[v1].y;
2.307 + float b2 = scene->vertexes[v1].x - scene->vertexes[v2].x;
2.308 + float c2 = scene->vertexes[v2].x * scene->vertexes[v1].y -
2.309 + scene->vertexes[v1].x * scene->vertexes[v2].y;
2.310 + float r1 = a2 * x1 + b2 * y1 + c2;
2.311 + float r2 = a2 * x2 + b2 * y2 + c2;
2.312 + if( fabsf(r1) > fabs(r2) ) {
2.313 + int tmp = splitv1;
2.314 + splitv1 = splitv2;
2.315 + splitv2 = tmp;
2.316 + }
2.317 + right_vertex_out[(*num_right_vertex_out)++] = splitv1;
2.318 + right_vertex_out[(*num_right_vertex_out)++] = splitv2;
2.319 + left_vertex_out[(*num_left_vertex_out)++] = splitv2;
2.320 + left_vertex_out[(*num_left_vertex_out)++] = splitv1;
2.321 + last = 2;
2.322 + } else if( last != 2 ) {
2.323 + last = -1;
2.324 + }
2.325 + left_vertex_out[(*num_left_vertex_out)++] = vertex_in[i];
2.326 + } else {
2.327 + if( last == -1 ) {
2.328 + /* cross-point. add the split vertexes */
2.329 + int v1 = vertex_in[i-1];
2.330 + int v2 = vertex_in[i];
2.331 + /* Determine which point is closer to the line. Strictly speaking
2.332 + * one of them must be ON the line, but this way allows for floating
2.333 + * point inaccuracies.
2.334 + */
2.335 + float a2 = scene->vertexes[v2].y - scene->vertexes[v1].y;
2.336 + float b2 = scene->vertexes[v1].x - scene->vertexes[v2].x;
2.337 + float c2 = scene->vertexes[v2].x * scene->vertexes[v1].y -
2.338 + scene->vertexes[v1].x * scene->vertexes[v2].y;
2.339 + float r1 = a2 * x1 + b2 * y1 + c2;
2.340 + float r2 = a2 * x2 + b2 * y2 + c2;
2.341 + if( fabsf(r1) > fabs(r2) ) {
2.342 + int tmp = splitv1;
2.343 + splitv1 = splitv2;
2.344 + splitv2 = tmp;
2.345 + }
2.346 + left_vertex_out[(*num_left_vertex_out)++] = splitv1;
2.347 + left_vertex_out[(*num_left_vertex_out)++] = splitv2;
2.348 + right_vertex_out[(*num_right_vertex_out)++] = splitv2;
2.349 + right_vertex_out[(*num_right_vertex_out)++] = splitv1;
2.350 + last = 2;
2.351 + } else if( last != 2 ) {
2.352 + last = 1;
2.353 + }
2.354 + right_vertex_out[(*num_right_vertex_out)++] = vertex_in[i];
2.355 + }
2.356 + }
2.357 +}
2.358 +
2.359 +/**
2.360 + * Subdivide the region tree by splitting it along a given line.
2.361 + *
2.362 + * @param scene current bkg scene data
2.363 + * @param region current region under examination
2.364 + * @param vertex1 first vertex of the new line segment
2.365 + * @param vertex2 second vertex of the new line segment
2.366 + */
2.367 +static void bkg_region_subdivide( struct bkg_scene *scene, int region, int vertex1, int vertex2 ) {
2.368 + struct bkg_region *this_region = &scene->regions[region];
2.369 +
2.370 + if( scene->regions[region].region_left == -1 || scene->regions[region].region_right == -1 ) {
2.371 + /* Reached the end of the tree. Setup new left+right regions */
2.372 + int i = scene->num_regions;
2.373 + scene->regions[i].region_left = scene->regions[i].region_right = -1;
2.374 + scene->regions[i+1].region_left = scene->regions[i+1].region_right = -1;
2.375 + this_region->region_left = i;
2.376 + this_region->region_right = i+1;
2.377 + this_region->vertex1 = vertex1;
2.378 + this_region->vertex2 = vertex2;
2.379 + scene->num_regions += 2;
2.380 + } else {
2.381 + float x,y;
2.382 + int thisv1 = this_region->vertex1;
2.383 + int thisv2 = this_region->vertex2;
2.384 + int vertex3;
2.385 + int status =
2.386 + compute_line_intersection( scene->vertexes[thisv1].x, scene->vertexes[thisv1].y,
2.387 + scene->vertexes[thisv2].x, scene->vertexes[thisv2].y,
2.388 + scene->vertexes[vertex1].x, scene->vertexes[vertex1].y,
2.389 + scene->vertexes[vertex2].x, scene->vertexes[vertex2].y,
2.390 + &x, &y );
2.391 + switch( status ) {
2.392 + case LINE_INTERSECT_FROM_LEFT:
2.393 + /* if new line segment intersects our current line segment,
2.394 + * subdivide the segment (add a new vertex) and recurse on both
2.395 + * sub trees
2.396 + */
2.397 + /* Compute split-point vertex */
2.398 + vertex3 = scene->num_vertexes++;
2.399 + scene->vertexes[vertex3].x = x;
2.400 + scene->vertexes[vertex3].y = y;
2.401 + /* Recurse */
2.402 + bkg_region_subdivide( scene, scene->regions[region].region_left, vertex1,vertex3 );
2.403 + bkg_region_subdivide( scene, scene->regions[region].region_right, vertex3, vertex2 );
2.404 + break;
2.405 + case LINE_INTERSECT_FROM_RIGHT:
2.406 + /* Same except line runs in the opposite direction */
2.407 + vertex3 = scene->num_vertexes++;
2.408 + scene->vertexes[vertex3].x = x;
2.409 + scene->vertexes[vertex3].y = y;
2.410 + /* Recurse */
2.411 + bkg_region_subdivide( scene, scene->regions[region].region_left, vertex2,vertex3 );
2.412 + bkg_region_subdivide( scene, scene->regions[region].region_right, vertex3, vertex1 );
2.413 + break;
2.414 + case LINE_COLLINEAR:
2.415 + case LINE_SKEW:
2.416 + /* Collinear - ignore */
2.417 + break;
2.418 + case LINE_SIDE_LEFT:
2.419 + /* else if line segment passes through the left sub-region alone,
2.420 + * left-recurse only.
2.421 + */
2.422 + bkg_region_subdivide( scene, scene->regions[region].region_left, vertex1, vertex2 );
2.423 + break;
2.424 + case LINE_SIDE_RIGHT:
2.425 + /* Otherwise line segment passes through the right sub-region alone,
2.426 + * so right-recurse.
2.427 + */
2.428 + bkg_region_subdivide( scene, scene->regions[region].region_right, vertex1, vertex2 );
2.429 + break;
2.430 + }
2.431 + }
2.432 +}
2.433 +
2.434 +
2.435 +
2.436 +/**
2.437 * Compute the values for an array of vertexes, given x,y for each
2.438 * vertex and the base 3-vertex triple used to define the background
2.439 * plane. Essentially the base vertexes are used to find the
2.440 @@ -49,69 +449,183 @@
2.441 * @param base The 3 vertexes supplied as the background definition
2.442 * @param compute An array of vertexes to compute. x and y must be
2.443 * preset, other values are computed.
2.444 - * @param num_compute number of vertexes in the compute array.
2.445 */
2.446 -void compute_vertexes( struct vertex_rgba *base,
2.447 - struct vertex_all *compute,
2.448 - int num_compute )
2.449 +static void bkg_compute_scene( struct vertex_all *base, int width, int height,
2.450 + struct bkg_scene *scene )
2.451 {
2.452 struct vertex_all center;
2.453 struct vertex_all diff0, diff1;
2.454 - int i;
2.455 + int i,k;
2.456
2.457 center.x = base[1].x;
2.458 center.y = base[1].y;
2.459 center.z = base[1].z;
2.460 - center.rgba[0] = FARGB_R(base[1].argb);
2.461 - center.rgba[1] = FARGB_G(base[1].argb);
2.462 - center.rgba[2] = FARGB_B(base[1].argb);
2.463 - center.rgba[3] = FARGB_A(base[1].argb);
2.464 diff0.x = base[0].x - base[1].x;
2.465 diff0.y = base[0].y - base[1].y;
2.466 diff0.z = base[0].z - base[1].z;
2.467 diff1.x = base[2].x - base[1].x;
2.468 diff1.y = base[2].y - base[1].y;
2.469 diff1.z = base[2].z - base[1].z;
2.470 - diff0.rgba[0] = FARGB_R(base[0].argb) - center.rgba[0];
2.471 - diff0.rgba[1] = FARGB_G(base[0].argb) - center.rgba[1];
2.472 - diff0.rgba[2] = FARGB_B(base[0].argb) - center.rgba[2];
2.473 - diff0.rgba[3] = FARGB_A(base[0].argb) - center.rgba[3];
2.474 - diff1.rgba[0] = FARGB_R(base[2].argb) - center.rgba[0];
2.475 - diff1.rgba[1] = FARGB_G(base[2].argb) - center.rgba[1];
2.476 - diff1.rgba[2] = FARGB_B(base[2].argb) - center.rgba[2];
2.477 - diff1.rgba[3] = FARGB_A(base[2].argb) - center.rgba[3];
2.478
2.479 - float divisor = ((diff1.y) * (diff0.x)) - ((diff0.y) * (diff1.x));
2.480 - if( divisor == 0 ) {
2.481 - /* The points lie on a single line - no plane for you. *shrugs* */
2.482 + float detxy = ((diff1.y) * (diff0.x)) - ((diff0.y) * (diff1.x));
2.483 +
2.484 + /* Corner points first */
2.485 + scene->vertexes[0].x = 0.0;
2.486 + scene->vertexes[0].y = 0.0;
2.487 + scene->vertexes[1].x = width;
2.488 + scene->vertexes[1].y = 0.0;
2.489 + scene->vertexes[2].x = width;
2.490 + scene->vertexes[2].y = height;
2.491 + scene->vertexes[3].x = 0.0;
2.492 + scene->vertexes[3].y = height;
2.493 + scene->regions[0].region_left = -1;
2.494 + scene->regions[0].region_right = -1;
2.495 + scene->num_vertexes = 4;
2.496 + scene->num_regions = 1;
2.497 +
2.498 + if( detxy == 0 ) {
2.499 + /* The points lie on a single line - no plane for you. Use the values
2.500 + * from the 3rd point for the whole screen.
2.501 + */
2.502 + for( i=0; i<4; i++ ) {
2.503 + scene->vertexes[i].rgba[0] = base[2].rgba[0];
2.504 + scene->vertexes[i].rgba[1] = base[2].rgba[1];
2.505 + scene->vertexes[i].rgba[2] = base[2].rgba[2];
2.506 + scene->vertexes[i].rgba[3] = base[2].rgba[3];
2.507 + scene->vertexes[i].u = base[2].u;
2.508 + scene->vertexes[i].v = base[2].v;
2.509 + }
2.510 } else {
2.511 - for( i=0; i<num_compute; i++ ) {
2.512 - float t = ((compute[i].x - center.x) * diff1.y -
2.513 - (compute[i].y - center.y) * diff1.x) / divisor;
2.514 - float s = ((compute[i].y - center.y) * diff0.x -
2.515 - (compute[i].x - center.x) * diff0.y) / divisor;
2.516 - compute[i].z = center.z + (t*diff0.z) + (s*diff1.z);
2.517 - compute[i].rgba[0] = center.rgba[0] + (t*diff0.rgba[0]) + (s*diff1.rgba[0]);
2.518 - compute[i].rgba[1] = center.rgba[1] + (t*diff0.rgba[1]) + (s*diff1.rgba[1]);
2.519 - compute[i].rgba[2] = center.rgba[2] + (t*diff0.rgba[2]) + (s*diff1.rgba[2]);
2.520 - compute[i].rgba[3] = center.rgba[3] + (t*diff0.rgba[3]) + (s*diff1.rgba[3]);
2.521 + /* Compute the colour values at each corner */
2.522 + center.rgba[0] = base[1].rgba[0];
2.523 + center.rgba[1] = base[1].rgba[1];
2.524 + center.rgba[2] = base[1].rgba[2];
2.525 + center.rgba[3] = base[1].rgba[3];
2.526 + diff0.rgba[0] = base[0].rgba[0] - center.rgba[0];
2.527 + diff0.rgba[1] = base[0].rgba[1] - center.rgba[1];
2.528 + diff0.rgba[2] = base[0].rgba[2] - center.rgba[2];
2.529 + diff0.rgba[3] = base[0].rgba[3] - center.rgba[3];
2.530 + diff0.u = base[0].u - center.u;
2.531 + diff0.v = base[0].v - center.v;
2.532 + diff1.rgba[0] = base[2].rgba[0] - center.rgba[0];
2.533 + diff1.rgba[1] = base[2].rgba[1] - center.rgba[1];
2.534 + diff1.rgba[2] = base[2].rgba[2] - center.rgba[2];
2.535 + diff1.rgba[3] = base[2].rgba[3] - center.rgba[3];
2.536 + diff1.u = base[2].u - center.u;
2.537 + diff1.v = base[2].v - center.v;
2.538 + for( i=0; i<4; i++ ) {
2.539 + float t = ((scene->vertexes[i].x - center.x) * diff1.y -
2.540 + (scene->vertexes[i].y - center.y) * diff1.x) / detxy;
2.541 + float s = ((scene->vertexes[i].y - center.y) * diff0.x -
2.542 + (scene->vertexes[i].x - center.x) * diff0.y) / detxy;
2.543 + scene->vertexes[i].z = center.z + (t*diff0.z) + (s*diff1.z);
2.544 + scene->vertexes[i].rgba[0] = center.rgba[0] + (t*diff0.rgba[0]) + (s*diff1.rgba[0]);
2.545 + scene->vertexes[i].rgba[1] = center.rgba[1] + (t*diff0.rgba[1]) + (s*diff1.rgba[1]);
2.546 + scene->vertexes[i].rgba[2] = center.rgba[2] + (t*diff0.rgba[2]) + (s*diff1.rgba[2]);
2.547 + scene->vertexes[i].rgba[3] = center.rgba[3] + (t*diff0.rgba[3]) + (s*diff1.rgba[3]);
2.548 + scene->vertexes[i].u = center.u + (t*diff0.u) + (s*diff1.u);
2.549 + scene->vertexes[i].v = center.v + (t*diff0.v) + (s*diff1.v);
2.550 + }
2.551 +
2.552 + /* Check for values > 1.0 | < 0.0 */
2.553 + for( k=0; k<4; k++ ) {
2.554 + float detyk = ((diff1.y) * (diff0.rgba[k])) - ((diff0.y)*(diff1.rgba[k]));
2.555 + float detxk = ((diff0.x) * (diff1.rgba[k])) - ((diff1.x)*(diff0.rgba[k]));
2.556 + if( scene->vertexes[0].rgba[k] > 1.0 || scene->vertexes[1].rgba[k] > 1.0 ||
2.557 + scene->vertexes[2].rgba[k] > 1.0 || scene->vertexes[3].rgba[k] > 1.0 ) {
2.558 + int v1 = scene->num_vertexes;
2.559 + scene->num_vertexes += compute_colour_line(center.x, center.y, center.rgba[k],
2.560 + width, height, 1.0,
2.561 + detxy, detxk, detyk,
2.562 + scene->vertexes+scene->num_vertexes );
2.563 + if( scene->num_vertexes != v1 ) {
2.564 + bkg_region_subdivide( scene, 0, v1, v1+1 );
2.565 + }
2.566 + }
2.567 +
2.568 + if( scene->vertexes[0].rgba[k] < 0.0 || scene->vertexes[1].rgba[k] < 0.0 ||
2.569 + scene->vertexes[2].rgba[k] < 0.0 || scene->vertexes[3].rgba[k] < 0.0 ) {
2.570 + int v1 = scene->num_vertexes;
2.571 + scene->num_vertexes += compute_colour_line(center.x, center.y, center.rgba[k],
2.572 + width, height, 0.0,
2.573 + detxy, detxk, detyk,
2.574 + scene->vertexes+scene->num_vertexes );
2.575 + if( scene->num_vertexes != v1 ) {
2.576 + bkg_region_subdivide( scene, 0, v1, v1+1 );
2.577 + }
2.578 +
2.579 + }
2.580 + }
2.581 +
2.582 + /* Finally compute the colour values for all vertexes
2.583 + * (excluding the 4 we did upfront) */
2.584 + for( i=4; i<scene->num_vertexes; i++ ) {
2.585 + float t = ((scene->vertexes[i].x - center.x) * diff1.y -
2.586 + (scene->vertexes[i].y - center.y) * diff1.x) / detxy;
2.587 + float s = ((scene->vertexes[i].y - center.y) * diff0.x -
2.588 + (scene->vertexes[i].x - center.x) * diff0.y) / detxy;
2.589 + scene->vertexes[i].z = center.z + (t*diff0.z) + (s*diff1.z);
2.590 + scene->vertexes[i].rgba[0] = center.rgba[0] + (t*diff0.rgba[0]) + (s*diff1.rgba[0]);
2.591 + scene->vertexes[i].rgba[1] = center.rgba[1] + (t*diff0.rgba[1]) + (s*diff1.rgba[1]);
2.592 + scene->vertexes[i].rgba[2] = center.rgba[2] + (t*diff0.rgba[2]) + (s*diff1.rgba[2]);
2.593 + scene->vertexes[i].rgba[3] = center.rgba[3] + (t*diff0.rgba[3]) + (s*diff1.rgba[3]);
2.594 + scene->vertexes[i].u = center.u + (t*diff0.u) + (s*diff1.u);
2.595 + scene->vertexes[i].v = center.v + (t*diff0.v) + (s*diff1.v);
2.596 }
2.597 }
2.598 }
2.599
2.600 +/**
2.601 + * Render a bkg_region.
2.602 + * @param scene the background scene data
2.603 + * @param region the region to render
2.604 + * @param vertexes the vertexes surrounding the region
2.605 + * @param num_vertexes the number of vertexes in the vertex array
2.606 + */
2.607 +void bkg_render_region( struct bkg_scene *scene, int region, int *vertexes, int num_vertexes,
2.608 + uint32_t poly1 )
2.609 +{
2.610 + if( scene->regions[region].region_left == -1 && scene->regions[region].region_right == -1 ) {
2.611 + /* Leaf node - render the points as given */
2.612 + int i,k;
2.613 + glBegin(GL_POLYGON);
2.614 + for( i=0; i<num_vertexes; i++ ) {
2.615 + k = vertexes[i];
2.616 + glColor4fv(scene->vertexes[k].rgba);
2.617 + if( POLY1_TEXTURED(poly1) ) {
2.618 + glTexCoord2f(scene->vertexes[k].u, scene->vertexes[k].v);
2.619 + }
2.620 + glVertex3f(scene->vertexes[k].x, scene->vertexes[k].y, scene->vertexes[k].z);
2.621 + }
2.622 + glEnd();
2.623 + } else {
2.624 + /* split the region into left and right regions */
2.625 + int left_vertexes[num_vertexes+1];
2.626 + int right_vertexes[num_vertexes+1];
2.627 + int num_left = 0;
2.628 + int num_right = 0;
2.629 + struct bkg_region *reg = &scene->regions[region];
2.630 + compute_subregions( scene, reg->vertex1, reg->vertex2, vertexes, num_vertexes,
2.631 + left_vertexes, &num_left, right_vertexes, &num_right );
2.632 + bkg_render_region( scene, reg->region_left, left_vertexes, num_left, poly1 );
2.633 + bkg_render_region( scene, reg->region_right, right_vertexes, num_right, poly1 );
2.634 + }
2.635 +
2.636 +}
2.637 +
2.638 +
2.639 void render_backplane( uint32_t *polygon, uint32_t width, uint32_t height, uint32_t mode ) {
2.640 - struct vertex_rgba *vertex = (struct vertex_rgba *)(polygon + 3);
2.641 - struct vertex_all compute[4] = { {0.0,0.0}, {width,0.0}, {width, height}, {0.0,height} };
2.642 - int i;
2.643 + struct vertex_all vertex[3];
2.644 + int screen_vertexes[4] = {0,1,2,3};
2.645 + struct bkg_scene scene;
2.646 + int i,j,k, num_vertexes;
2.647
2.648 + parse_vertexes(polygon, 3, vertex);
2.649 render_set_context(polygon, 0);
2.650 - compute_vertexes( vertex, compute, 4 );
2.651 - glBegin(GL_QUADS);
2.652 - for( i=0; i<4; i++ ) {
2.653 - glColor4fv(compute[i].rgba);
2.654 - glVertex3f(compute[i].x, compute[i].y, compute[i].z);
2.655 - fprintf( stderr, "BG %d,%d: %f %f %f\n", (int)compute[i].x, (int)compute[i].y,
2.656 - compute[i].rgba[0], compute[i].rgba[1], compute[i].rgba[2] );
2.657 - }
2.658 - glEnd();
2.659 + glDisable(GL_CULL_FACE);
2.660 + glDisable(GL_DEPTH_TEST);
2.661 + glBlendFunc(GL_ONE, GL_ZERO); /* For now, just disable alpha blending on the bkg */
2.662 + fwrite_dump32( polygon, 48, stderr );
2.663 + bkg_compute_scene(vertex, width, height, &scene);
2.664 + bkg_render_region(&scene, 0, screen_vertexes, 4, *polygon);
2.665 }
3.1 --- a/src/pvr2/rendcore.c Tue Sep 12 08:36:09 2006 +0000
3.2 +++ b/src/pvr2/rendcore.c Tue Sep 12 08:38:38 2006 +0000
3.3 @@ -1,5 +1,5 @@
3.4 /**
3.5 - * $Id: rendcore.c,v 1.3 2006-08-18 12:43:24 nkeynes Exp $
3.6 + * $Id: rendcore.c,v 1.4 2006-09-12 08:38:38 nkeynes Exp $
3.7 *
3.8 * PVR2 renderer core.
3.9 *
3.10 @@ -19,41 +19,23 @@
3.11 #include "pvr2/pvr2.h"
3.12 #include "asic.h"
3.13
3.14 -static int pvr2_poly_depthmode[8] = { GL_NEVER, GL_LESS, GL_EQUAL, GL_LEQUAL,
3.15 +int pvr2_poly_depthmode[8] = { GL_NEVER, GL_LESS, GL_EQUAL, GL_LEQUAL,
3.16 GL_GREATER, GL_NOTEQUAL, GL_GEQUAL,
3.17 GL_ALWAYS };
3.18 -static int pvr2_poly_srcblend[8] = {
3.19 +int pvr2_poly_srcblend[8] = {
3.20 GL_ZERO, GL_ONE, GL_DST_COLOR, GL_ONE_MINUS_DST_COLOR,
3.21 GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_DST_ALPHA,
3.22 GL_ONE_MINUS_DST_ALPHA };
3.23 -static int pvr2_poly_dstblend[8] = {
3.24 +int pvr2_poly_dstblend[8] = {
3.25 GL_ZERO, GL_ONE, GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR,
3.26 GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_DST_ALPHA,
3.27 GL_ONE_MINUS_DST_ALPHA };
3.28 -static int pvr2_poly_texblend[4] = {
3.29 +int pvr2_poly_texblend[4] = {
3.30 GL_REPLACE, GL_BLEND, GL_DECAL, GL_MODULATE };
3.31 -static int pvr2_render_colour_format[8] = {
3.32 +int pvr2_render_colour_format[8] = {
3.33 COLFMT_ARGB1555, COLFMT_RGB565, COLFMT_ARGB4444, COLFMT_ARGB1555,
3.34 COLFMT_RGB888, COLFMT_ARGB8888, COLFMT_ARGB8888, COLFMT_ARGB4444 };
3.35 -#define POLY1_DEPTH_MODE(poly1) ( pvr2_poly_depthmode[(poly1)>>29] )
3.36 -#define POLY1_DEPTH_ENABLE(poly1) (((poly1)&0x04000000) == 0 )
3.37 -#define POLY1_CULL_MODE(poly1) (((poly1)>>27)&0x03)
3.38 -#define POLY1_TEXTURED(poly1) (((poly1)&0x02000000))
3.39 -#define POLY1_SPECULAR(poly1) (((poly1)&0x01000000))
3.40 -#define POLY1_SHADE_MODEL(poly1) (((poly1)&0x00800000) ? GL_SMOOTH : GL_FLAT)
3.41 -#define POLY1_UV16(poly1) (((poly1)&0x00400000))
3.42 -#define POLY1_SINGLE_TILE(poly1) (((poly1)&0x00200000))
3.43
3.44 -#define POLY2_SRC_BLEND(poly2) ( pvr2_poly_srcblend[(poly2) >> 29] )
3.45 -#define POLY2_DEST_BLEND(poly2) ( pvr2_poly_dstblend[((poly2)>>26)&0x07] )
3.46 -#define POLY2_SRC_BLEND_ENABLE(poly2) ((poly2)&0x02000000)
3.47 -#define POLY2_DEST_BLEND_ENABLE(poly2) ((poly2)&0x01000000)
3.48 -#define POLY2_COLOUR_CLAMP_ENABLE(poly2) ((poly2)&0x00200000)
3.49 -#define POLY2_ALPHA_ENABLE(poly2) ((poly2)&0x001000000)
3.50 -#define POLY2_TEX_ALPHA_ENABLE(poly2) (((poly2)&0x00080000) == 0 )
3.51 -#define POLY2_TEX_WIDTH(poly2) ( 1<< ((((poly2) >> 3) & 0x07 ) + 3) )
3.52 -#define POLY2_TEX_HEIGHT(poly2) ( 1<< (((poly2) & 0x07 ) + 3) )
3.53 -#define POLY2_TEX_BLEND(poly2) ( pvr2_poly_texblend[((poly2) >> 6)&0x03] )
3.54
3.55 #define RENDER_ZONLY 0
3.56 #define RENDER_NORMAL 1 /* Render non-modified polygons */
3.57 @@ -153,7 +135,9 @@
3.58
3.59 glShadeModel( POLY1_SHADE_MODEL(poly1) );
3.60
3.61 - glBlendFunc( POLY2_SRC_BLEND(poly2), POLY2_DEST_BLEND(poly2) );
3.62 + int srcblend = POLY2_SRC_BLEND(poly2);
3.63 + int destblend = POLY2_DEST_BLEND(poly2);
3.64 + glBlendFunc( srcblend, destblend );
3.65 if( POLY2_TEX_ALPHA_ENABLE(poly2) ) {
3.66 glEnable(GL_BLEND);
3.67 } else {
3.68 @@ -297,6 +281,7 @@
3.69 fprintf( stderr, "Start render at %d.%d\n", tv_start.tv_sec, tv_start.tv_usec );
3.70 glEnable( GL_SCISSOR_TEST );
3.71 while( (segment->control & SEGMENT_END) == 0 ) {
3.72 + // fwrite_dump32v( (uint32_t *)segment, sizeof(struct tile_segment), 6, stderr );
3.73 int tilex = SEGMENT_X(segment->control);
3.74 int tiley = SEGMENT_Y(segment->control);
3.75
4.1 --- a/src/pvr2/render.c Tue Sep 12 08:36:09 2006 +0000
4.2 +++ b/src/pvr2/render.c Tue Sep 12 08:38:38 2006 +0000
4.3 @@ -1,5 +1,5 @@
4.4 /**
4.5 - * $Id: render.c,v 1.13 2006-08-29 08:12:13 nkeynes Exp $
4.6 + * $Id: render.c,v 1.14 2006-09-12 08:38:38 nkeynes Exp $
4.7 *
4.8 * PVR2 Renderer support. This part is primarily
4.9 *
4.10 @@ -19,11 +19,6 @@
4.11 #include "pvr2/pvr2.h"
4.12 #include "asic.h"
4.13
4.14 -static int pvr2_render_colour_format[8] = {
4.15 - COLFMT_ARGB1555, COLFMT_RGB565, COLFMT_ARGB4444, COLFMT_ARGB1555,
4.16 - COLFMT_RGB888, COLFMT_ARGB8888, COLFMT_ARGB8888, COLFMT_ARGB4444 };
4.17 -
4.18 -
4.19 /**
4.20 * Describes a rendering buffer that's actually held in GL, for when we need
4.21 * to fetch the bits back to vram.
.