filename | src/pvr2/rendbkg.c |
changeset | 653:3202ff01d48e |
prev | 561:533f6b478071 |
next | 677:3ee62740ff8f |
author | nkeynes |
date | Mon May 12 10:00:13 2008 +0000 (15 years ago) |
permissions | -rw-r--r-- |
last change | Cleanup most of the -Wall warnings (getting a bit sloppy...) Convert FP code to use fixed banks rather than indirect pointer (3-4% faster this way now) |
view | annotate | diff | log | raw |
1 /**
2 * $Id$
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 "display.h"
39 #include "pvr2/pvr2.h"
40 #include <math.h>
42 #define MAX_CLAMP_LINES 8
43 #define MAX_VERTEXES 256
44 #define MAX_REGIONS 256
46 #define FARGB_A(x) (((float)(((x)>>24)+1))/256.0)
47 #define FARGB_R(x) (((float)((((x)>>16)&0xFF)+1))/256.0)
48 #define FARGB_G(x) (((float)((((x)>>8)&0xFF)+1))/256.0)
49 #define FARGB_B(x) (((float)(((x)&0xFF)+1))/256.0)
51 /**
52 * Convert a half-float (16-bit) FP number to a regular 32-bit float.
53 * Source is 1-bit sign, 5-bit exponent, 10-bit mantissa.
54 * TODO: Check the correctness of this.
55 */
56 static float halftofloat( uint16_t half )
57 {
58 union {
59 float f;
60 uint32_t i;
61 } temp;
62 /* int e = ((half & 0x7C00) >> 10) - 15 + 127;
64 temp.i = ((half & 0x8000) << 16) | (e << 23) |
65 ((half & 0x03FF) << 13); */
66 temp.i = ((uint32_t)half)<<16;
67 return temp.f;
68 }
70 void render_unpack_vertexes( struct vertex_unpacked *out, uint32_t poly1,
71 uint32_t *vertexes, int num_vertexes,
72 int vertex_size, int render_mode )
73 {
74 int m = 0, i;
75 if( render_mode == RENDER_FULLMOD ) {
76 m = (vertex_size - 3)/2;
77 }
79 for( i=0; i<num_vertexes; i++ ) {
80 float *vertexf = (float *)vertexes;
81 int k = m + 3;
82 out[i].x = vertexf[0];
83 out[i].y = vertexf[1];
84 out[i].z = vertexf[2];
85 if( POLY1_TEXTURED(poly1) ) {
86 if( POLY1_UV16(poly1) ) {
87 out[i].u = halftofloat(vertexes[k]>>16);
88 out[i].v = halftofloat(vertexes[k]);
89 k++;
90 } else {
91 out[i].u = vertexf[k];
92 out[i].v = vertexf[k+1];
93 k+=2;
94 }
95 } else {
96 out[i].u = 0;
97 out[i].v = 0;
98 }
99 uint32_t argb = vertexes[k++];
100 out[i].rgba[0] = FARGB_R(argb);
101 out[i].rgba[1] = FARGB_G(argb);
102 out[i].rgba[2] = FARGB_B(argb);
103 out[i].rgba[3] = FARGB_A(argb);
104 if( POLY1_SPECULAR(poly1) ) {
105 uint32_t offset = vertexes[k++];
106 out[i].offset_rgba[0] = FARGB_R(offset);
107 out[i].offset_rgba[1] = FARGB_G(offset);
108 out[i].offset_rgba[2] = FARGB_B(offset);
109 out[i].offset_rgba[3] = FARGB_A(offset);
110 }
111 vertexes += vertex_size;
112 }
113 }
115 /**
116 * Compute the line where k = target_k, (where k is normally one of
117 * r,g,b,a, or z) and determines the points at which the line intersects
118 * the viewport (0,0,width,height).
119 *
120 * @param center_x the x value for the center position
121 * @param center_y the y value for the center position
122 * @param center_k the k value for the center position
123 * @param width Width of the viewport (ie 640)
124 * @param height Height of the viewport (ie 480)
125 * @param target_k determine the line where k = this value, ie 1.0
126 * @param detxy
127 * @param target Array to write the resultant x,y pairs to (note this
128 * function only sets x and y values).
129 * @return number of vertexes written to the target.
130 */
131 static int compute_colour_line( float center_x, float center_y, float center_k,
132 int width, int height, float target_k,
133 float detxy, float detxk, float detyk,
134 struct vertex_unpacked *target ) {
135 int num_points = 0;
136 float tmpk = (target_k - center_k) * detxy;
137 float x0 = -1;
138 float x1 = -1;
140 if( detyk != 0 ) {
141 x0 = (tmpk - ((0-center_y)*detxk))/detyk + center_x; /* x where y=0 */
142 if( x0 >= 0.0 && x0 <= width ) {
143 target[num_points].x = x0;
144 target[num_points].y = 0.0;
145 num_points++;
146 }
148 x1 = (tmpk - ((height-center_y)*detxk))/detyk + center_x; /* x where y=height */
149 if( x1 >= 0.0 && x1 <= width ) {
150 target[num_points].x = x1;
151 target[num_points].y = height;
152 num_points++;
153 }
154 }
156 if( detxk != 0 ) {
157 if( x0 != 0.0 && x1 != 0.0 ) { /* If x0 == 0 or x1 == 0, then we already have this one */
158 float y0 = (tmpk - ((0-center_x)*detyk))/detxk + center_y; /* y where x=0 */
159 if( y0 >= 0.0 && y0 <= height ) {
160 target[num_points].x = 0.0;
161 target[num_points].y = y0;
162 num_points++;
163 }
164 }
166 if( x0 != width && x1 != width ) {
167 float y1 = (tmpk - ((width-center_x)*detyk))/detxk + center_y; /* y where x=width */
168 if( y1 >= 0.0 && y1 <= height ) {
169 target[num_points].x = width;
170 target[num_points].y = y1;
171 num_points++;
172 }
173 }
174 }
176 if( num_points == 0 || num_points == 2 ) {
177 /* 0 = no points - line doesn't pass through the viewport */
178 /* 2 = normal case - got 2 endpoints */
179 return num_points;
180 } else {
181 ERROR( "compute_colour_line got bad number of points: %d", num_points );
182 return 0;
183 }
184 }
186 /**
187 * A region describes a portion of the screen, possibly subdivided by a line.
188 * if region_left and region_right are -1, this is a terminal region that can
189 * be rendered directly. Otherwise region_left and region_right refer two
190 * sub-regions that are separated by the line segment vertex1-vertex2.
191 */
192 struct bkg_region {
193 /* Vertexes marking the line segment that splits this region */
194 int vertex1;
195 int vertex2;
196 /* Index of the left sub-region */
197 int region_left;
198 /* Index of the right sub-region */
199 int region_right;
200 };
202 /**
203 * Convenience structure to bundle together the vertex and region data.
204 */
205 struct bkg_scene {
206 int num_vertexes;
207 int num_regions;
208 struct vertex_unpacked vertexes[MAX_VERTEXES];
209 struct bkg_region regions[MAX_REGIONS];
210 };
212 /**
213 * Constants returned by compute_line_intersection. Note that for these purposes,
214 * "Left" means the point(s) result in a negative value in the line equation, while
215 * "Right" means the points(s) result in a positive value in the line equation. The
216 * exact meaning isn't particularly important though, as long as we're consistent
217 * throughout this process
218 */
219 #define LINE_COLLINEAR 0 /* The line segments are part of the same line */
220 #define LINE_SIDE_LEFT 1 /* The second line is entirely to the "left" of the first line */
221 #define LINE_SIDE_RIGHT 2 /* The second line is entirely to the "right" of the first line */
222 #define LINE_INTERSECT_FROM_LEFT 3 /* The lines intersect, and (x3,y3) is to the "left" of the first line */
223 #define LINE_INTERSECT_FROM_RIGHT 4 /* The lines intersect, and (x3,y3) is to the "right" of the first line */
224 #define LINE_SKEW 5 /* The line segments neither intersect nor do any of the above apply (should never happen here) */
226 /**
227 * Compute the intersection of two line segments, where
228 * (x1,y1)-(x2,y2) defines the target segment, and
229 * (x3,y3)-(x4,y4) defines the line intersecting it.
230 *
231 * Based off work by Mukesh Prasad (http://www.acm.org/pubs/tog/GraphicsGems/index.html)
232 *
233 * @return one of the above LINE_* constants
234 */
235 static int compute_line_intersection( float x1, float y1, /* First line segment */
236 float x2, float y2,
237 float x3, float y3, /* Second line segment */
238 float x4, float y4,
239 float *x, float *y ) /* Output value: */
240 {
241 float a1, a2, b1, b2, c1, c2; /* Coefficients of line eqns. */
242 float r1, r2, r3, r4; /* test values */
243 float denom; /* Intermediate values */
245 /* Compute a1, b1, c1, where line joining points 1 and 2
246 * is "a1 x + b1 y + c1 = 0".
247 */
249 a1 = y2 - y1;
250 b1 = x1 - x2;
251 c1 = x2 * y1 - x1 * y2;
253 /* Compute r3 and r4. */
255 r3 = a1 * x3 + b1 * y3 + c1;
256 r4 = a1 * x4 + b1 * y4 + c1;
258 /* Check signs of r3 and r4. If both point 3 and point 4 lie on
259 * same side of line 1, the line segments do not intersect.
260 */
262 if( r3 == 0 && r4 == 0 ) {
263 return LINE_COLLINEAR;
264 } else if( r3 <= 0 && r4 <= 0 ) {
265 return LINE_SIDE_LEFT;
266 } else if( r3 >= 0 && r4 >= 0 ) {
267 return LINE_SIDE_RIGHT;
268 }
270 /* Compute a2, b2, c2 */
272 a2 = y4 - y3;
273 b2 = x3 - x4;
274 c2 = x4 * y3 - x3 * y4;
276 /* Compute r1 and r2 */
278 r1 = a2 * x1 + b2 * y1 + c2;
279 r2 = a2 * x2 + b2 * y2 + c2;
281 /* Check signs of r1 and r2. If both point 1 and point 2 lie
282 * on same side of second line segment, the line segments do
283 * not intersect.
284 */
286 if ( r1 != 0 && r2 != 0 &&
287 signbit(r1) == signbit(r2) ) {
288 return LINE_SKEW; /* Should never happen */
289 }
291 /* Cmpute intersection point.
292 */
293 denom = a1 * b2 - a2 * b1;
294 if ( denom == 0 )
295 return LINE_COLLINEAR; /* Should never get to this point either */
297 *x = (b1 * c2 - b2 * c1) / denom;
298 *y = (a2 * c1 - a1 * c2) / denom;
300 if( r3 <= 0 && r4 >= 0 ) {
301 return LINE_INTERSECT_FROM_LEFT;
302 } else {
303 return LINE_INTERSECT_FROM_RIGHT;
304 }
305 }
307 /**
308 * Given a set of vertexes and a line segment to use to split them, generates
309 * two sets of vertexes representing the polygon on either side of the line
310 * segment. This method preserves the winding direction of the input vertexes.
311 */
312 static void compute_subregions( struct bkg_scene *scene,
313 int splitv1, int splitv2,
314 int *vertex_in, int num_vertex_in,
315 int *left_vertex_out, int *num_left_vertex_out,
316 int *right_vertex_out, int *num_right_vertex_out )
317 {
318 float x1 = scene->vertexes[splitv1].x;
319 float y1 = scene->vertexes[splitv1].y;
320 float x2 = scene->vertexes[splitv2].x;
321 float y2 = scene->vertexes[splitv2].y;
323 float a1 = y2 - y1;
324 float b1 = x1 - x2;
325 float c1 = x2 * y1 - x1 * y2;
326 int i;
328 *num_left_vertex_out = 0;
329 *num_right_vertex_out = 0;
330 int last = 0;
331 for( i=0; i<num_vertex_in; i++ ) {
332 struct vertex_unpacked *vertex = &scene->vertexes[vertex_in[i]];
333 float r = a1 * vertex->x + b1 * vertex->y + c1;
334 if( r <= 0 ) {
335 if( last == 1 ) {
336 /* cross-point. add the split vertexes */
337 int v1 = vertex_in[i-1];
338 int v2 = vertex_in[i];
339 /* Determine which point is closer to the line. Strictly speaking
340 * one of them must be ON the line, but this way allows for floating
341 * point inaccuracies.
342 */
343 float a2 = scene->vertexes[v2].y - scene->vertexes[v1].y;
344 float b2 = scene->vertexes[v1].x - scene->vertexes[v2].x;
345 float c2 = scene->vertexes[v2].x * scene->vertexes[v1].y -
346 scene->vertexes[v1].x * scene->vertexes[v2].y;
347 float r1 = a2 * x1 + b2 * y1 + c2;
348 float r2 = a2 * x2 + b2 * y2 + c2;
349 if( fabsf(r1) > fabs(r2) ) {
350 int tmp = splitv1;
351 splitv1 = splitv2;
352 splitv2 = tmp;
353 }
354 right_vertex_out[(*num_right_vertex_out)++] = splitv1;
355 right_vertex_out[(*num_right_vertex_out)++] = splitv2;
356 left_vertex_out[(*num_left_vertex_out)++] = splitv2;
357 left_vertex_out[(*num_left_vertex_out)++] = splitv1;
358 last = 2;
359 } else if( last != 2 ) {
360 last = -1;
361 }
362 left_vertex_out[(*num_left_vertex_out)++] = vertex_in[i];
363 } else {
364 if( last == -1 ) {
365 /* cross-point. add the split vertexes */
366 int v1 = vertex_in[i-1];
367 int v2 = vertex_in[i];
368 /* Determine which point is closer to the line. Strictly speaking
369 * one of them must be ON the line, but this way allows for floating
370 * point inaccuracies.
371 */
372 float a2 = scene->vertexes[v2].y - scene->vertexes[v1].y;
373 float b2 = scene->vertexes[v1].x - scene->vertexes[v2].x;
374 float c2 = scene->vertexes[v2].x * scene->vertexes[v1].y -
375 scene->vertexes[v1].x * scene->vertexes[v2].y;
376 float r1 = a2 * x1 + b2 * y1 + c2;
377 float r2 = a2 * x2 + b2 * y2 + c2;
378 if( fabsf(r1) > fabs(r2) ) {
379 int tmp = splitv1;
380 splitv1 = splitv2;
381 splitv2 = tmp;
382 }
383 left_vertex_out[(*num_left_vertex_out)++] = splitv1;
384 left_vertex_out[(*num_left_vertex_out)++] = splitv2;
385 right_vertex_out[(*num_right_vertex_out)++] = splitv2;
386 right_vertex_out[(*num_right_vertex_out)++] = splitv1;
387 last = 2;
388 } else if( last != 2 ) {
389 last = 1;
390 }
391 right_vertex_out[(*num_right_vertex_out)++] = vertex_in[i];
392 }
393 }
394 }
396 /**
397 * Subdivide the region tree by splitting it along a given line.
398 *
399 * @param scene current bkg scene data
400 * @param region current region under examination
401 * @param vertex1 first vertex of the new line segment
402 * @param vertex2 second vertex of the new line segment
403 */
404 static void bkg_region_subdivide( struct bkg_scene *scene, int region, int vertex1, int vertex2 ) {
405 struct bkg_region *this_region = &scene->regions[region];
407 if( scene->regions[region].region_left == -1 || scene->regions[region].region_right == -1 ) {
408 /* Reached the end of the tree. Setup new left+right regions */
409 int i = scene->num_regions;
410 scene->regions[i].region_left = scene->regions[i].region_right = -1;
411 scene->regions[i+1].region_left = scene->regions[i+1].region_right = -1;
412 this_region->region_left = i;
413 this_region->region_right = i+1;
414 this_region->vertex1 = vertex1;
415 this_region->vertex2 = vertex2;
416 scene->num_regions += 2;
417 } else {
418 float x,y;
419 int thisv1 = this_region->vertex1;
420 int thisv2 = this_region->vertex2;
421 int vertex3;
422 int status =
423 compute_line_intersection( scene->vertexes[thisv1].x, scene->vertexes[thisv1].y,
424 scene->vertexes[thisv2].x, scene->vertexes[thisv2].y,
425 scene->vertexes[vertex1].x, scene->vertexes[vertex1].y,
426 scene->vertexes[vertex2].x, scene->vertexes[vertex2].y,
427 &x, &y );
428 switch( status ) {
429 case LINE_INTERSECT_FROM_LEFT:
430 /* if new line segment intersects our current line segment,
431 * subdivide the segment (add a new vertex) and recurse on both
432 * sub trees
433 */
434 /* Compute split-point vertex */
435 vertex3 = scene->num_vertexes++;
436 scene->vertexes[vertex3].x = x;
437 scene->vertexes[vertex3].y = y;
438 /* Recurse */
439 bkg_region_subdivide( scene, scene->regions[region].region_left, vertex1,vertex3 );
440 bkg_region_subdivide( scene, scene->regions[region].region_right, vertex3, vertex2 );
441 break;
442 case LINE_INTERSECT_FROM_RIGHT:
443 /* Same except line runs in the opposite direction */
444 vertex3 = scene->num_vertexes++;
445 scene->vertexes[vertex3].x = x;
446 scene->vertexes[vertex3].y = y;
447 /* Recurse */
448 bkg_region_subdivide( scene, scene->regions[region].region_left, vertex2,vertex3 );
449 bkg_region_subdivide( scene, scene->regions[region].region_right, vertex3, vertex1 );
450 break;
451 case LINE_COLLINEAR:
452 case LINE_SKEW:
453 /* Collinear - ignore */
454 break;
455 case LINE_SIDE_LEFT:
456 /* else if line segment passes through the left sub-region alone,
457 * left-recurse only.
458 */
459 bkg_region_subdivide( scene, scene->regions[region].region_left, vertex1, vertex2 );
460 break;
461 case LINE_SIDE_RIGHT:
462 /* Otherwise line segment passes through the right sub-region alone,
463 * so right-recurse.
464 */
465 bkg_region_subdivide( scene, scene->regions[region].region_right, vertex1, vertex2 );
466 break;
467 }
468 }
469 }
473 /**
474 * Compute the values for an array of vertexes, given x,y for each
475 * vertex and the base 3-vertex triple used to define the background
476 * plane. Essentially the base vertexes are used to find the
477 * plane equation for each of z,a,r,g,b,etc, which is then solved for
478 * each of the required compute vertexes (normally the corner points).
479 *
480 * @param base The 3 vertexes supplied as the background definition
481 * @param compute An array of vertexes to compute. x and y must be
482 * preset, other values are computed.
483 */
484 static void bkg_compute_scene( struct vertex_unpacked *base, int width, int height,
485 struct bkg_scene *scene )
486 {
487 struct vertex_unpacked center;
488 struct vertex_unpacked diff0, diff1;
489 int i,k;
491 center.x = base[1].x;
492 center.y = base[1].y;
493 center.z = base[1].z;
494 center.u = base[1].u;
495 center.v = base[1].v;
496 diff0.x = base[0].x - center.x;
497 diff0.y = base[0].y - center.y;
498 diff0.z = base[0].z - center.z;
499 diff1.x = base[2].x - center.x;
500 diff1.y = base[2].y - center.y;
501 diff1.z = base[2].z - center.z;
503 float detxy = ((diff1.y) * (diff0.x)) - ((diff0.y) * (diff1.x));
505 /* Corner points first */
506 scene->vertexes[0].x = 0.0;
507 scene->vertexes[0].y = 0.0;
508 scene->vertexes[1].x = width;
509 scene->vertexes[1].y = 0.0;
510 scene->vertexes[2].x = width;
511 scene->vertexes[2].y = height;
512 scene->vertexes[3].x = 0.0;
513 scene->vertexes[3].y = height;
514 scene->regions[0].region_left = -1;
515 scene->regions[0].region_right = -1;
516 scene->num_vertexes = 4;
517 scene->num_regions = 1;
519 if( detxy == 0 ) {
520 /* The points lie on a single line - no plane for you. Use the values
521 * from the 3rd point for the whole screen.
522 */
523 for( i=0; i<4; i++ ) {
524 scene->vertexes[i].rgba[0] = base[2].rgba[0];
525 scene->vertexes[i].rgba[1] = base[2].rgba[1];
526 scene->vertexes[i].rgba[2] = base[2].rgba[2];
527 scene->vertexes[i].rgba[3] = base[2].rgba[3];
528 scene->vertexes[i].z = base[2].z;
529 scene->vertexes[i].u = base[2].u;
530 scene->vertexes[i].v = base[2].v;
531 }
532 } else {
533 /* Compute the colour values at each corner */
534 center.rgba[0] = base[1].rgba[0];
535 center.rgba[1] = base[1].rgba[1];
536 center.rgba[2] = base[1].rgba[2];
537 center.rgba[3] = base[1].rgba[3];
538 diff0.rgba[0] = base[0].rgba[0] - center.rgba[0];
539 diff0.rgba[1] = base[0].rgba[1] - center.rgba[1];
540 diff0.rgba[2] = base[0].rgba[2] - center.rgba[2];
541 diff0.rgba[3] = base[0].rgba[3] - center.rgba[3];
542 diff0.u = base[0].u - center.u;
543 diff0.v = base[0].v - center.v;
544 diff1.rgba[0] = base[2].rgba[0] - center.rgba[0];
545 diff1.rgba[1] = base[2].rgba[1] - center.rgba[1];
546 diff1.rgba[2] = base[2].rgba[2] - center.rgba[2];
547 diff1.rgba[3] = base[2].rgba[3] - center.rgba[3];
548 diff1.u = base[2].u - center.u;
549 diff1.v = base[2].v - center.v;
550 for( i=0; i<4; i++ ) {
551 float t = ((scene->vertexes[i].x - center.x) * diff1.y -
552 (scene->vertexes[i].y - center.y) * diff1.x) / detxy;
553 float s = ((scene->vertexes[i].y - center.y) * diff0.x -
554 (scene->vertexes[i].x - center.x) * diff0.y) / detxy;
555 scene->vertexes[i].z = center.z + (t*diff0.z) + (s*diff1.z);
556 scene->vertexes[i].rgba[0] = center.rgba[0] + (t*diff0.rgba[0]) + (s*diff1.rgba[0]);
557 scene->vertexes[i].rgba[1] = center.rgba[1] + (t*diff0.rgba[1]) + (s*diff1.rgba[1]);
558 scene->vertexes[i].rgba[2] = center.rgba[2] + (t*diff0.rgba[2]) + (s*diff1.rgba[2]);
559 scene->vertexes[i].rgba[3] = center.rgba[3] + (t*diff0.rgba[3]) + (s*diff1.rgba[3]);
560 scene->vertexes[i].u = center.u + (t*diff0.u) + (s*diff1.u);
561 scene->vertexes[i].v = center.v + (t*diff0.v) + (s*diff1.v);
562 }
564 /* Check for values > 1.0 | < 0.0 */
565 for( k=0; k<4; k++ ) {
566 float detyk = ((diff1.y) * (diff0.rgba[k])) - ((diff0.y)*(diff1.rgba[k]));
567 float detxk = ((diff0.x) * (diff1.rgba[k])) - ((diff1.x)*(diff0.rgba[k]));
568 if( scene->vertexes[0].rgba[k] > 1.0 || scene->vertexes[1].rgba[k] > 1.0 ||
569 scene->vertexes[2].rgba[k] > 1.0 || scene->vertexes[3].rgba[k] > 1.0 ) {
570 int v1 = scene->num_vertexes;
571 scene->num_vertexes += compute_colour_line(center.x, center.y, center.rgba[k],
572 width, height, 1.0,
573 detxy, detxk, detyk,
574 scene->vertexes+scene->num_vertexes );
575 if( scene->num_vertexes != v1 ) {
576 bkg_region_subdivide( scene, 0, v1, v1+1 );
577 }
578 }
580 if( scene->vertexes[0].rgba[k] < 0.0 || scene->vertexes[1].rgba[k] < 0.0 ||
581 scene->vertexes[2].rgba[k] < 0.0 || scene->vertexes[3].rgba[k] < 0.0 ) {
582 int v1 = scene->num_vertexes;
583 scene->num_vertexes += compute_colour_line(center.x, center.y, center.rgba[k],
584 width, height, 0.0,
585 detxy, detxk, detyk,
586 scene->vertexes+scene->num_vertexes );
587 if( scene->num_vertexes != v1 ) {
588 bkg_region_subdivide( scene, 0, v1, v1+1 );
589 }
591 }
592 }
594 /* Finally compute the colour values for all vertexes
595 * (excluding the 4 we did upfront) */
596 for( i=4; i<scene->num_vertexes; i++ ) {
597 float t = ((scene->vertexes[i].x - center.x) * diff1.y -
598 (scene->vertexes[i].y - center.y) * diff1.x) / detxy;
599 float s = ((scene->vertexes[i].y - center.y) * diff0.x -
600 (scene->vertexes[i].x - center.x) * diff0.y) / detxy;
601 scene->vertexes[i].z = center.z + (t*diff0.z) + (s*diff1.z);
602 scene->vertexes[i].rgba[0] = center.rgba[0] + (t*diff0.rgba[0]) + (s*diff1.rgba[0]);
603 scene->vertexes[i].rgba[1] = center.rgba[1] + (t*diff0.rgba[1]) + (s*diff1.rgba[1]);
604 scene->vertexes[i].rgba[2] = center.rgba[2] + (t*diff0.rgba[2]) + (s*diff1.rgba[2]);
605 scene->vertexes[i].rgba[3] = center.rgba[3] + (t*diff0.rgba[3]) + (s*diff1.rgba[3]);
606 scene->vertexes[i].u = center.u + (t*diff0.u) + (s*diff1.u);
607 scene->vertexes[i].v = center.v + (t*diff0.v) + (s*diff1.v);
608 }
609 }
610 }
612 /**
613 * Render a bkg_region.
614 * @param scene the background scene data
615 * @param region the region to render
616 * @param vertexes the vertexes surrounding the region
617 * @param num_vertexes the number of vertexes in the vertex array
618 */
619 void bkg_render_region( struct bkg_scene *scene, int region, int *vertexes, int num_vertexes,
620 uint32_t poly1 )
621 {
622 if( scene->regions[region].region_left == -1 && scene->regions[region].region_right == -1 ) {
623 /* Leaf node - render the points as given */
624 int i,k;
625 glBegin(GL_POLYGON);
626 for( i=0; i<num_vertexes; i++ ) {
627 k = vertexes[i];
628 glColor4fv(scene->vertexes[k].rgba);
629 if( POLY1_TEXTURED(poly1) ) {
630 glTexCoord2f(scene->vertexes[k].u, scene->vertexes[k].v);
631 }
632 glVertex3f(scene->vertexes[k].x, scene->vertexes[k].y, scene->vertexes[k].z);
633 }
634 glEnd();
635 } else {
636 /* split the region into left and right regions */
637 int left_vertexes[num_vertexes+1];
638 int right_vertexes[num_vertexes+1];
639 int num_left = 0;
640 int num_right = 0;
641 struct bkg_region *reg = &scene->regions[region];
642 compute_subregions( scene, reg->vertex1, reg->vertex2, vertexes, num_vertexes,
643 left_vertexes, &num_left, right_vertexes, &num_right );
644 bkg_render_region( scene, reg->region_left, left_vertexes, num_left, poly1 );
645 bkg_render_region( scene, reg->region_right, right_vertexes, num_right, poly1 );
646 }
648 }
651 void render_backplane( uint32_t *polygon, uint32_t width, uint32_t height, uint32_t mode ) {
652 struct vertex_unpacked vertex[3];
653 int screen_vertexes[4] = {0,1,2,3};
654 struct bkg_scene scene;
655 int vertex_length = (mode >> 24) & 0x07;
656 int cheap_shadow = MMIO_READ( PVR2, RENDER_SHADOW ) & 0x100;
657 int is_modified = mode & 0x08000000;
658 int context_length = 3;
659 if( is_modified && !cheap_shadow ) {
660 context_length = 5;
661 vertex_length *= 2;
662 }
663 vertex_length += 3;
664 context_length += (mode & 0x07) * vertex_length;
667 render_unpack_vertexes( vertex, *polygon, polygon+context_length, 3, vertex_length,
668 RENDER_NORMAL );
669 bkg_compute_scene(vertex, width, height, &scene);
670 render_set_context(polygon, RENDER_NORMAL);
671 glDisable(GL_CULL_FACE);
672 glDisable(GL_DEPTH_TEST);
673 glBlendFunc(GL_ONE, GL_ZERO); /* For now, just disable alpha blending on the bkg */
674 bkg_render_region(&scene, 0, screen_vertexes, 4, *polygon);
675 glEnable(GL_CULL_FACE);
676 glEnable(GL_DEPTH_TEST);
677 }
.