Search
lxdream.org :: lxdream/src/pvr2/rendbkg.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/pvr2/rendbkg.c
changeset 239:e5cd6b2d4586
prev223:f6c28fa9076b
next331:a6048d3a9a79
author nkeynes
date Wed Jan 03 09:01:51 2007 +0000 (17 years ago)
permissions -rw-r--r--
last change Implement the main CRTC registers, along with the sync status register.
Timings are now pretty close to the real thing.
view annotate diff log raw
     1 /**
     2  * $Id: rendbkg.c,v 1.4 2006-12-15 10:17:30 nkeynes Exp $
     3  *
     4  * PVR2 background renderer. 
     5  *
     6  * Yes, it uses the same basic data structure. Yes, it needs to be handled
     7  * completely differently.
     8  *
     9  * PVR2 backgrounds are defined as a set of three fully specified vertexes,
    10  * stored in compiled-vertex format. The vertexes form a triangle which is
    11  * rendered in the normal fashion. Points outside the triangle are rendered
    12  * by extrapolating from the gradients established by the triangle, giving
    13  * an overall smooth gradient across the background. Points are colour-clamped
    14  * prior to output to the buffer.
    15  *
    16  * As a special case, if all three points lie on the same line (or are the same
    17  * point, the third point is used by itself to define the entire buffer (ie
    18  * effectively a solid colour).
    19  *
    20  * Note: this would be really simple if GL did unclamped colour interpolation
    21  * but it doesn't (portably), which makes this roughly 2 orders of magnitude
    22  * more complicated than it otherwise would be.
    23  *
    24  * Copyright (c) 2005 Nathan Keynes.
    25  *
    26  * This program is free software; you can redistribute it and/or modify
    27  * it under the terms of the GNU General Public License as published by
    28  * the Free Software Foundation; either version 2 of the License, or
    29  * (at your option) any later version.
    30  *
    31  * This program is distributed in the hope that it will be useful,
    32  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    33  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    34  * GNU General Public License for more details.
    35  */
    37 #include <sys/time.h>
    38 #include "pvr2/pvr2.h"
    39 #include <GL/glext.h>
    40 #include <math.h>
    42 #define MAX_CLAMP_LINES 8
    43 #define MAX_VERTEXES 256
    44 #define MAX_REGIONS  256
    46 /**
    47  * Structure to hold an unpacked vertex
    48  */
    49 struct vertex_all {
    50     float x,y,z;
    51     float u,v;
    52     float rgba[4];      /* Note - RGBA order, as preferred by GL */
    53     float spec_rgba[4];
    54 };
    56 #define FARGB_A(x) (((float)(((x)>>24)+1))/256.0)
    57 #define FARGB_R(x) (((float)((((x)>>16)&0xFF)+1))/256.0)
    58 #define FARGB_G(x) (((float)((((x)>>8)&0xFF)+1))/256.0)
    59 #define FARGB_B(x) (((float)(((x)&0xFF)+1))/256.0)
    61 /**
    62  * Compute the line where k = target_k, (where k is normally one of
    63  * r,g,b,a, or z) and determines the points at which the line intersects
    64  * the viewport (0,0,width,height).
    65  *
    66  * @param center_x the x value for the center position
    67  * @param center_y the y value for the center position
    68  * @param center_k the k value for the center position
    69  * @param width Width of the viewport (ie 640)
    70  * @param height Height of the viewport (ie 480)
    71  * @param target_k determine the line where k = this value, ie 1.0
    72  * @param detxy
    73  * @param target Array to write the resultant x,y pairs to (note this
    74  * function only sets x and y values).
    75  * @return number of vertexes written to the target.
    76  */
    77 static int compute_colour_line( float center_x, float center_y, float center_k, 
    78 		  int width, int height, float target_k,
    79 		  float detxy, float detxk, float detyk,
    80 		  struct vertex_all *target ) {
    81     int num_points = 0;
    82     float tmpk = (target_k - center_k) * detxy;
    83     float x0 = -1;
    84     float x1 = -1;
    86     if( detyk != 0 ) {
    87 	x0 = (tmpk - ((0-center_y)*detxk))/detyk + center_x; /* x where y=0 */
    88 	if( x0 >= 0.0 && x0 <= width ) {
    89 	    target[num_points].x = x0;
    90 	    target[num_points].y = 0.0;
    91 	    num_points++;
    92 	}
    94 	x1 = (tmpk - ((height-center_y)*detxk))/detyk + center_x; /* x where y=height */
    95 	if( x1 >= 0.0 && x1 <= width ) {
    96 	    target[num_points].x = x1;
    97 	    target[num_points].y = height;
    98 	    num_points++;
    99 	}
   100     }
   102     if( detxk != 0 ) {
   103 	if( x0 != 0.0 && x1 != 0.0 ) { /* If x0 == 0 or x1 == 0, then we already have this one */
   104 	    float y0 = (tmpk - ((0-center_x)*detyk))/detxk + center_y; /* y where x=0 */
   105 	    if( y0 >= 0.0 && y0 <= height ) {
   106 		target[num_points].x = 0.0;
   107 		target[num_points].y = y0;
   108 		num_points++;
   109 	    }
   110 	}
   112 	if( x0 != width && x1 != width ) {
   113 	    float y1 = (tmpk - ((width-center_x)*detyk))/detxk + center_y; /* y where x=width */
   114 	    if( y1 >= 0.0 && y1 <= height ) {
   115 		target[num_points].x = width;
   116 		target[num_points].y = y1;
   117 		num_points++;
   118 	    }
   119 	}
   120     }
   122     if( num_points == 0 || num_points == 2 ) {
   123 	/* 0 = no points - line doesn't pass through the viewport */
   124 	/* 2 = normal case - got 2 endpoints */
   125 	return num_points;
   126     } else {
   127 	ERROR( "compute_colour_line got bad number of points: %d", num_points );
   128 	return 0;
   129     }
   130 }
   132 /**
   133  * A region describes a portion of the screen, possibly subdivided by a line.
   134  * if region_left and region_right are -1, this is a terminal region that can
   135  * be rendered directly. Otherwise region_left and region_right refer two 
   136  * sub-regions that are separated by the line segment vertex1-vertex2.
   137  */
   138 struct bkg_region {
   139     /* Vertexes marking the line segment that splits this region */
   140     int vertex1;
   141     int vertex2;
   142     /* Index of the left sub-region */
   143     int region_left;
   144     /* Index of the right sub-region */
   145     int region_right;
   146 };
   148 /**
   149  * Convenience structure to bundle together the vertex and region data.
   150  */
   151 struct bkg_scene {
   152     int num_vertexes;
   153     int num_regions;
   154     struct vertex_all vertexes[MAX_VERTEXES];
   155     struct bkg_region regions[MAX_REGIONS];
   156 };
   158 void parse_vertexes( uint32_t *polygon, int num_vertexes, struct vertex_all *result )
   159 {
   160     uint32_t *vertexes = polygon + 3; 
   161     int i,m = 0;
   162     for( i=0; i<num_vertexes; i++ ) {
   163 	float *vertexf = (float *)vertexes;
   164 	result[i].x = vertexf[0];
   165 	result[i].y = vertexf[1];
   166 	result[i].z = vertexf[2];
   167 	uint32_t argb;
   168 	if( POLY1_TEXTURED(*polygon) ) {
   169 	    if( POLY1_UV16(*polygon) ) {
   170 		result[i].u = halftofloat(vertexes[m+3]>>16);
   171 		result[i].v = halftofloat(vertexes[m+3]);
   172 		argb = vertexes[m+4];
   173 		vertexes += 5;
   174 	    } else {
   175 		result[i].u = vertexf[m+3];
   176 		result[i].v = vertexf[m+4];
   177 		argb = vertexes[m+5];
   178 		vertexes += 6;
   179 	    }
   180 	} else {
   181 	    argb = vertexes[m+3];
   182 	    vertexes += 4;
   183 	}
   184 	result[i].rgba[0] = FARGB_R(argb);
   185 	result[i].rgba[1] = FARGB_G(argb);
   186         result[i].rgba[2] = FARGB_B(argb);
   187 	result[i].rgba[3] = FARGB_A(argb);
   188     }
   190 }
   192 /**
   193  * Constants returned by compute_line_intersection. Note that for these purposes,
   194  * "Left" means the point(s) result in a negative value in the line equation, while
   195  * "Right" means the points(s) result in a positive value in the line equation. The
   196  * exact meaning isn't particularly important though, as long as we're consistent
   197  * throughout this process
   198  */
   199 #define LINE_COLLINEAR 0   /* The line segments are part of the same line */
   200 #define LINE_SIDE_LEFT 1   /* The second line is entirely to the "left" of the first line */
   201 #define LINE_SIDE_RIGHT 2  /* The second line is entirely to the "right" of the first line */
   202 #define LINE_INTERSECT_FROM_LEFT 3 /* The lines intersect, and (x3,y3) is to the "left" of the first line */
   203 #define LINE_INTERSECT_FROM_RIGHT 4 /* The lines intersect, and (x3,y3) is to the "right" of the first line */
   204 #define LINE_SKEW 5        /* The line segments neither intersect nor do any of the above apply (should never happen here) */
   206 /**
   207  * Compute the intersection of two line segments, where 
   208  * (x1,y1)-(x2,y2) defines the target segment, and
   209  * (x3,y3)-(x4,y4) defines the line intersecting it.
   210  *
   211  * Based off work by Mukesh Prasad (http://www.acm.org/pubs/tog/GraphicsGems/index.html)
   212  *
   213  * @return one of the above LINE_* constants
   214  */
   215 static int compute_line_intersection( float x1, float y1,   /* First line segment */
   216 				      float x2, float y2,
   217 				      float x3, float y3,   /* Second line segment */
   218 				      float x4, float y4,
   219 				      float *x, float *y  )  /* Output value: */
   220 {
   221     float a1, a2, b1, b2, c1, c2; /* Coefficients of line eqns. */
   222     float r1, r2, r3, r4;         /* test values */
   223     float denom;     /* Intermediate values */
   225     /* Compute a1, b1, c1, where line joining points 1 and 2
   226      * is "a1 x  +  b1 y  +  c1  =  0".
   227      */
   229     a1 = y2 - y1;
   230     b1 = x1 - x2;
   231     c1 = x2 * y1 - x1 * y2;
   233     /* Compute r3 and r4. */
   235     r3 = a1 * x3 + b1 * y3 + c1;
   236     r4 = a1 * x4 + b1 * y4 + c1;
   238     /* Check signs of r3 and r4.  If both point 3 and point 4 lie on
   239      * same side of line 1, the line segments do not intersect.
   240      */
   242     if( r3 == 0 && r4 == 0 ) {
   243 	return LINE_COLLINEAR;
   244     } else if( r3 <= 0 && r4 <= 0 ) {
   245 	return LINE_SIDE_LEFT;
   246     } else if( r3 >= 0 && r4 >= 0 ) {
   247 	return LINE_SIDE_RIGHT;
   248     }
   250     /* Compute a2, b2, c2 */
   252     a2 = y4 - y3;
   253     b2 = x3 - x4;
   254     c2 = x4 * y3 - x3 * y4;
   256     /* Compute r1 and r2 */
   258     r1 = a2 * x1 + b2 * y1 + c2;
   259     r2 = a2 * x2 + b2 * y2 + c2;
   261     /* Check signs of r1 and r2.  If both point 1 and point 2 lie
   262      * on same side of second line segment, the line segments do
   263      * not intersect.
   264      */
   266     if ( r1 != 0 && r2 != 0 &&
   267          signbit(r1) == signbit(r2) ) {
   268         return LINE_SKEW; /* Should never happen */
   269     }
   271     /* Cmpute intersection point. 
   272      */
   273     denom = a1 * b2 - a2 * b1;
   274     if ( denom == 0 )
   275         return LINE_COLLINEAR; /* Should never get to this point either */
   277     *x = (b1 * c2 - b2 * c1) / denom;
   278     *y = (a2 * c1 - a1 * c2) / denom;
   280     if( r3 <= 0 && r4 >= 0 ) {
   281 	return LINE_INTERSECT_FROM_LEFT;
   282     } else {
   283 	return LINE_INTERSECT_FROM_RIGHT;
   284     }
   285 }
   287 /**
   288  * Given a set of vertexes and a line segment to use to split them, generates
   289  * two sets of vertexes representing the polygon on either side of the line
   290  * segment. This method preserves the winding direction of the input vertexes.
   291  */
   292 static void compute_subregions( struct bkg_scene *scene,
   293 				int splitv1, int splitv2,
   294 				int *vertex_in, int num_vertex_in,
   295 				int *left_vertex_out, int *num_left_vertex_out,
   296 				int *right_vertex_out, int *num_right_vertex_out )
   297 {
   298     float x1 = scene->vertexes[splitv1].x;
   299     float y1 = scene->vertexes[splitv1].y;
   300     float x2 = scene->vertexes[splitv2].x;
   301     float y2 = scene->vertexes[splitv2].y;
   303     float a1 = y2 - y1;
   304     float b1 = x1 - x2;
   305     float c1 = x2 * y1 - x1 * y2;
   306     int i;
   308     *num_left_vertex_out = 0;
   309     *num_right_vertex_out = 0;
   310     int last = 0;
   311     for( i=0; i<num_vertex_in; i++ ) {
   312 	struct vertex_all *vertex = &scene->vertexes[vertex_in[i]];
   313 	float r = a1 * vertex->x + b1 * vertex->y + c1;
   314 	if( r <= 0 ) {
   315 	    if( last == 1 ) {
   316 		/* cross-point. add the split vertexes */
   317 		int v1 = vertex_in[i-1];
   318 		int v2 = vertex_in[i];
   319 		/* Determine which point is closer to the line. Strictly speaking
   320 		 * one of them must be ON the line, but this way allows for floating
   321 		 * point inaccuracies.
   322 		 */
   323 		float a2 = scene->vertexes[v2].y - scene->vertexes[v1].y;
   324 		float b2 = scene->vertexes[v1].x - scene->vertexes[v2].x;
   325 		float c2 = scene->vertexes[v2].x * scene->vertexes[v1].y - 
   326 		    scene->vertexes[v1].x * scene->vertexes[v2].y;
   327 		float r1 = a2 * x1 + b2 * y1 + c2;
   328 		float r2 = a2 * x2 + b2 * y2 + c2;
   329 		if( fabsf(r1) > fabs(r2) ) {
   330 		    int tmp = splitv1;
   331 		    splitv1 = splitv2;
   332 		    splitv2 = tmp;
   333 		}
   334 		right_vertex_out[(*num_right_vertex_out)++] = splitv1;
   335 		right_vertex_out[(*num_right_vertex_out)++] = splitv2;
   336 		left_vertex_out[(*num_left_vertex_out)++] = splitv2;
   337 		left_vertex_out[(*num_left_vertex_out)++] = splitv1;
   338 		last = 2;
   339 	    } else if( last != 2 ) {
   340 		last = -1;
   341 	    }
   342 	    left_vertex_out[(*num_left_vertex_out)++] = vertex_in[i];
   343 	} else {
   344 	    if( last == -1 ) {
   345 		/* cross-point. add the split vertexes */
   346 		int v1 = vertex_in[i-1];
   347 		int v2 = vertex_in[i];
   348 		/* Determine which point is closer to the line. Strictly speaking
   349 		 * one of them must be ON the line, but this way allows for floating
   350 		 * point inaccuracies.
   351 		 */
   352 		float a2 = scene->vertexes[v2].y - scene->vertexes[v1].y;
   353 		float b2 = scene->vertexes[v1].x - scene->vertexes[v2].x;
   354 		float c2 = scene->vertexes[v2].x * scene->vertexes[v1].y - 
   355 		    scene->vertexes[v1].x * scene->vertexes[v2].y;
   356 		float r1 = a2 * x1 + b2 * y1 + c2;
   357 		float r2 = a2 * x2 + b2 * y2 + c2;
   358 		if( fabsf(r1) > fabs(r2) ) {
   359 		    int tmp = splitv1;
   360 		    splitv1 = splitv2;
   361 		    splitv2 = tmp;
   362 		}
   363 		left_vertex_out[(*num_left_vertex_out)++] = splitv1;
   364 		left_vertex_out[(*num_left_vertex_out)++] = splitv2;
   365 		right_vertex_out[(*num_right_vertex_out)++] = splitv2;
   366 		right_vertex_out[(*num_right_vertex_out)++] = splitv1;
   367 		last = 2;
   368 	    } else if( last != 2 ) {
   369 		last = 1;
   370 	    }
   371 	    right_vertex_out[(*num_right_vertex_out)++] = vertex_in[i];
   372 	}
   373     }
   374 }
   376 /**
   377  * Subdivide the region tree by splitting it along a given line.
   378  * 
   379  * @param scene  current bkg scene data
   380  * @param region current region under examination
   381  * @param vertex1 first vertex of the new line segment
   382  * @param vertex2 second vertex of the new line segment
   383  */
   384 static void bkg_region_subdivide( struct bkg_scene *scene, int region, int vertex1, int vertex2 ) {
   385     struct bkg_region *this_region = &scene->regions[region];
   387     if( scene->regions[region].region_left == -1 || scene->regions[region].region_right == -1 ) {
   388 	/* Reached the end of the tree. Setup new left+right regions */
   389 	int i = scene->num_regions;
   390 	scene->regions[i].region_left = scene->regions[i].region_right = -1;
   391 	scene->regions[i+1].region_left = scene->regions[i+1].region_right = -1;
   392 	this_region->region_left = i;
   393 	this_region->region_right = i+1;
   394 	this_region->vertex1 = vertex1;
   395 	this_region->vertex2 = vertex2;
   396 	scene->num_regions += 2;
   397     } else {
   398 	float x,y;
   399 	int thisv1 = this_region->vertex1;
   400 	int thisv2 = this_region->vertex2;
   401 	int vertex3;
   402 	int status = 
   403 	    compute_line_intersection( scene->vertexes[thisv1].x, scene->vertexes[thisv1].y,
   404 				       scene->vertexes[thisv2].x, scene->vertexes[thisv2].y,
   405 				       scene->vertexes[vertex1].x, scene->vertexes[vertex1].y,
   406 				       scene->vertexes[vertex2].x, scene->vertexes[vertex2].y,
   407 				       &x, &y );
   408 	switch( status ) {
   409 	case LINE_INTERSECT_FROM_LEFT:
   410 	    /* if new line segment intersects our current line segment,
   411 	     * subdivide the segment (add a new vertex) and recurse on both
   412 	     * sub trees 
   413 	     */
   414 	    /* Compute split-point vertex */
   415 	    vertex3 = scene->num_vertexes++;
   416 	    scene->vertexes[vertex3].x = x;
   417 	    scene->vertexes[vertex3].y = y;
   418 	    /* Recurse */
   419 	    bkg_region_subdivide( scene, scene->regions[region].region_left, vertex1,vertex3 );
   420 	    bkg_region_subdivide( scene, scene->regions[region].region_right, vertex3, vertex2 );
   421 	    break;
   422 	case LINE_INTERSECT_FROM_RIGHT:
   423 	    /* Same except line runs in the opposite direction */
   424 	    vertex3 = scene->num_vertexes++;
   425 	    scene->vertexes[vertex3].x = x;
   426 	    scene->vertexes[vertex3].y = y;
   427 	    /* Recurse */
   428 	    bkg_region_subdivide( scene, scene->regions[region].region_left, vertex2,vertex3 );
   429 	    bkg_region_subdivide( scene, scene->regions[region].region_right, vertex3, vertex1 );
   430 	    break;
   431 	case LINE_COLLINEAR:
   432 	case LINE_SKEW:
   433 	    /* Collinear - ignore */
   434 	    break;
   435 	case LINE_SIDE_LEFT:
   436 	    /* else if line segment passes through the left sub-region alone,
   437 	     * left-recurse only.
   438 	     */
   439 	    bkg_region_subdivide( scene, scene->regions[region].region_left, vertex1, vertex2 );
   440 	    break;
   441 	case LINE_SIDE_RIGHT:
   442 	    /* Otherwise line segment passes through the right sub-region alone,
   443 	     * so right-recurse.
   444 	     */
   445 	    bkg_region_subdivide( scene, scene->regions[region].region_right, vertex1, vertex2 );
   446 	    break;
   447 	}
   448     }
   449 }
   453 /**
   454  * Compute the values for an array of vertexes, given x,y for each
   455  * vertex and the base 3-vertex triple used to define the background
   456  * plane. Essentially the base vertexes are used to find the
   457  * plane equation for each of z,a,r,g,b,etc, which is then solved for
   458  * each of the required compute vertexes (normally the corner points).
   459  *
   460  * @param base The 3 vertexes supplied as the background definition
   461  * @param compute An array of vertexes to compute. x and y must be
   462  *   preset, other values are computed.
   463  */
   464 static void bkg_compute_scene( struct vertex_all *base, int width, int height,
   465 				struct bkg_scene *scene )
   466 {
   467     struct vertex_all center;
   468     struct vertex_all diff0, diff1;
   469     int i,k;
   471     center.x = base[1].x;
   472     center.y = base[1].y;
   473     center.z = base[1].z;
   474     diff0.x = base[0].x - base[1].x;
   475     diff0.y = base[0].y - base[1].y;
   476     diff0.z = base[0].z - base[1].z;
   477     diff1.x = base[2].x - base[1].x;
   478     diff1.y = base[2].y - base[1].y;
   479     diff1.z = base[2].z - base[1].z;
   481     float detxy = ((diff1.y) * (diff0.x)) - ((diff0.y) * (diff1.x));
   483     /* Corner points first */
   484     scene->vertexes[0].x = 0.0;
   485     scene->vertexes[0].y = 0.0;
   486     scene->vertexes[1].x = width;
   487     scene->vertexes[1].y = 0.0;
   488     scene->vertexes[2].x = width;
   489     scene->vertexes[2].y = height;
   490     scene->vertexes[3].x = 0.0;
   491     scene->vertexes[3].y = height;
   492     scene->regions[0].region_left = -1;
   493     scene->regions[0].region_right = -1;
   494     scene->num_vertexes = 4;
   495     scene->num_regions = 1;
   497     if( detxy == 0 ) {
   498 	/* The points lie on a single line - no plane for you. Use the values
   499 	 * from the 3rd point for the whole screen.
   500 	 */
   501 	for( i=0; i<4; i++ ) {
   502 	    scene->vertexes[i].rgba[0] = base[2].rgba[0];
   503 	    scene->vertexes[i].rgba[1] = base[2].rgba[1];
   504 	    scene->vertexes[i].rgba[2] = base[2].rgba[2];
   505 	    scene->vertexes[i].rgba[3] = base[2].rgba[3];
   506 	    scene->vertexes[i].u = base[2].u;
   507 	    scene->vertexes[i].v = base[2].v;
   508 	}
   509     } else {
   510 	/* Compute the colour values at each corner */
   511 	center.rgba[0] = base[1].rgba[0];
   512 	center.rgba[1] = base[1].rgba[1];
   513 	center.rgba[2] = base[1].rgba[2];
   514 	center.rgba[3] = base[1].rgba[3];
   515 	diff0.rgba[0] = base[0].rgba[0] - center.rgba[0];
   516 	diff0.rgba[1] = base[0].rgba[1] - center.rgba[1];
   517 	diff0.rgba[2] = base[0].rgba[2] - center.rgba[2];
   518 	diff0.rgba[3] = base[0].rgba[3] - center.rgba[3];
   519 	diff0.u = base[0].u - center.u;
   520 	diff0.v = base[0].v - center.v;
   521 	diff1.rgba[0] = base[2].rgba[0] - center.rgba[0];
   522 	diff1.rgba[1] = base[2].rgba[1] - center.rgba[1];
   523 	diff1.rgba[2] = base[2].rgba[2] - center.rgba[2];
   524 	diff1.rgba[3] = base[2].rgba[3] - center.rgba[3];
   525 	diff1.u = base[2].u - center.u;
   526 	diff1.v = base[2].v - center.v;
   527 	for( i=0; i<4; i++ ) {
   528 	    float t = ((scene->vertexes[i].x - center.x) * diff1.y -
   529 		       (scene->vertexes[i].y - center.y) * diff1.x) / detxy;
   530 	    float s = ((scene->vertexes[i].y - center.y) * diff0.x -
   531 		       (scene->vertexes[i].x - center.x) * diff0.y) / detxy;
   532 	    scene->vertexes[i].z = center.z + (t*diff0.z) + (s*diff1.z);
   533 	    scene->vertexes[i].rgba[0] = center.rgba[0] + (t*diff0.rgba[0]) + (s*diff1.rgba[0]);
   534 	    scene->vertexes[i].rgba[1] = center.rgba[1] + (t*diff0.rgba[1]) + (s*diff1.rgba[1]);
   535 	    scene->vertexes[i].rgba[2] = center.rgba[2] + (t*diff0.rgba[2]) + (s*diff1.rgba[2]);
   536 	    scene->vertexes[i].rgba[3] = center.rgba[3] + (t*diff0.rgba[3]) + (s*diff1.rgba[3]);
   537 	    scene->vertexes[i].u = center.u + (t*diff0.u) + (s*diff1.u);
   538 	    scene->vertexes[i].v = center.v + (t*diff0.v) + (s*diff1.v);
   539 	}
   541 	/* Check for values > 1.0 | < 0.0 */
   542 	for( k=0; k<4; k++ ) {
   543 	    float detyk = ((diff1.y) * (diff0.rgba[k])) - ((diff0.y)*(diff1.rgba[k]));
   544 	    float detxk = ((diff0.x) * (diff1.rgba[k])) - ((diff1.x)*(diff0.rgba[k]));
   545 	    if( scene->vertexes[0].rgba[k] > 1.0 || scene->vertexes[1].rgba[k] > 1.0 || 
   546 		scene->vertexes[2].rgba[k] > 1.0 || scene->vertexes[3].rgba[k] > 1.0 ) {
   547 		int v1 = scene->num_vertexes;
   548 		scene->num_vertexes += compute_colour_line(center.x, center.y, center.rgba[k],
   549 						    width, height, 1.0,
   550 						    detxy, detxk, detyk, 
   551 						    scene->vertexes+scene->num_vertexes );
   552 		if( scene->num_vertexes != v1 ) {
   553 		    bkg_region_subdivide( scene, 0, v1, v1+1 );
   554 		}
   555 	    }
   557 	    if( scene->vertexes[0].rgba[k] < 0.0 || scene->vertexes[1].rgba[k] < 0.0 || 
   558 		scene->vertexes[2].rgba[k] < 0.0 || scene->vertexes[3].rgba[k] < 0.0 ) {
   559 		int v1 = scene->num_vertexes;
   560 		scene->num_vertexes += compute_colour_line(center.x, center.y, center.rgba[k],
   561 						    width, height, 0.0,
   562 						    detxy, detxk, detyk, 
   563 						    scene->vertexes+scene->num_vertexes );
   564 		if( scene->num_vertexes != v1 ) {
   565 		    bkg_region_subdivide( scene, 0, v1, v1+1 );
   566 		}
   568 	    }
   569 	}
   571 	/* Finally compute the colour values for all vertexes 
   572 	 * (excluding the 4 we did upfront) */
   573 	for( i=4; i<scene->num_vertexes; i++ ) {
   574 	    float t = ((scene->vertexes[i].x - center.x) * diff1.y -
   575 		       (scene->vertexes[i].y - center.y) * diff1.x) / detxy;
   576 	    float s = ((scene->vertexes[i].y - center.y) * diff0.x -
   577 		       (scene->vertexes[i].x - center.x) * diff0.y) / detxy;
   578 	    scene->vertexes[i].z = center.z + (t*diff0.z) + (s*diff1.z);
   579 	    scene->vertexes[i].rgba[0] = center.rgba[0] + (t*diff0.rgba[0]) + (s*diff1.rgba[0]);
   580 	    scene->vertexes[i].rgba[1] = center.rgba[1] + (t*diff0.rgba[1]) + (s*diff1.rgba[1]);
   581 	    scene->vertexes[i].rgba[2] = center.rgba[2] + (t*diff0.rgba[2]) + (s*diff1.rgba[2]);
   582 	    scene->vertexes[i].rgba[3] = center.rgba[3] + (t*diff0.rgba[3]) + (s*diff1.rgba[3]);
   583 	    scene->vertexes[i].u = center.u + (t*diff0.u) + (s*diff1.u);
   584 	    scene->vertexes[i].v = center.v + (t*diff0.v) + (s*diff1.v);
   585 	}
   586     }
   587 }
   589 /**
   590  * Render a bkg_region.
   591  * @param scene the background scene data
   592  * @param region the region to render
   593  * @param vertexes the vertexes surrounding the region
   594  * @param num_vertexes the number of vertexes in the vertex array
   595  */
   596 void bkg_render_region( struct bkg_scene *scene, int region, int *vertexes, int num_vertexes,
   597 			uint32_t poly1 )
   598 {
   599     if( scene->regions[region].region_left == -1 && scene->regions[region].region_right == -1 ) {
   600 	/* Leaf node - render the points as given */
   601 	int i,k;
   602 	glBegin(GL_POLYGON);
   603 	for( i=0; i<num_vertexes; i++ ) {
   604 	    k = vertexes[i];
   605 	    glColor4fv(scene->vertexes[k].rgba);
   606 	    if( POLY1_TEXTURED(poly1) ) {
   607 		glTexCoord2f(scene->vertexes[k].u, scene->vertexes[k].v);
   608 	    }
   609 	    glVertex3f(scene->vertexes[k].x, scene->vertexes[k].y, scene->vertexes[k].z);
   610 	}
   611 	glEnd();
   612     } else {
   613 	/* split the region into left and right regions */
   614 	int left_vertexes[num_vertexes+1];
   615 	int right_vertexes[num_vertexes+1];
   616 	int num_left = 0;
   617 	int num_right = 0;
   618 	struct bkg_region *reg = &scene->regions[region];
   619 	compute_subregions( scene, reg->vertex1, reg->vertex2, vertexes, num_vertexes,
   620 			    left_vertexes, &num_left, right_vertexes, &num_right );
   621 	bkg_render_region( scene, reg->region_left, left_vertexes, num_left, poly1 );
   622 	bkg_render_region( scene, reg->region_right, right_vertexes, num_right, poly1 );
   623     }
   625 }
   628 void render_backplane( uint32_t *polygon, uint32_t width, uint32_t height, uint32_t mode ) {
   629     struct vertex_all vertex[3];
   630     int screen_vertexes[4] = {0,1,2,3};
   631     struct bkg_scene scene;
   632     int i,j,k, num_vertexes;
   634     parse_vertexes(polygon, 3, vertex);
   635     render_set_context(polygon, 0);
   636     glDisable(GL_CULL_FACE);
   637     glDisable(GL_DEPTH_TEST);
   638     glBlendFunc(GL_ONE, GL_ZERO); /* For now, just disable alpha blending on the bkg */
   639     bkg_compute_scene(vertex, width, height, &scene);
   640     bkg_render_region(&scene, 0, screen_vertexes, 4, *polygon);
   641 }
.