attempt to make gles plugin work under RPi
[pcsx_rearmed.git] / plugins / gpu_unai / gpu_raster_polygon.h
1 /***************************************************************************
2 *   Copyright (C) 2010 PCSX4ALL Team                                      *
3 *   Copyright (C) 2010 Unai                                               *
4 *                                                                         *
5 *   This program is free software; you can redistribute it and/or modify  *
6 *   it under the terms of the GNU General Public License as published by  *
7 *   the Free Software Foundation; either version 2 of the License, or     *
8 *   (at your option) any later version.                                   *
9 *                                                                         *
10 *   This program is distributed in the hope that it will be useful,       *
11 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
12 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
13 *   GNU General Public License for more details.                          *
14 *                                                                         *
15 *   You should have received a copy of the GNU General Public License     *
16 *   along with this program; if not, write to the                         *
17 *   Free Software Foundation, Inc.,                                       *
18 *   51 Franklin Street, Fifth Floor, Boston, MA 02111-1307 USA.           *
19 ***************************************************************************/
20
21 #define GPU_TESTRANGE3() \
22 { \
23         if(x0<0) { if((x1-x0)>CHKMAX_X) return; if((x2-x0)>CHKMAX_X) return; } \
24         if(x1<0) { if((x0-x1)>CHKMAX_X) return; if((x2-x1)>CHKMAX_X) return; } \
25         if(x2<0) { if((x0-x2)>CHKMAX_X) return; if((x1-x2)>CHKMAX_X) return; } \
26         if(y0<0) { if((y1-y0)>CHKMAX_Y) return; if((y2-y0)>CHKMAX_Y) return; } \
27         if(y1<0) { if((y0-y1)>CHKMAX_Y) return; if((y2-y1)>CHKMAX_Y) return; } \
28         if(y2<0) { if((y0-y2)>CHKMAX_Y) return; if((y1-y2)>CHKMAX_Y) return; } \
29 }
30
31 ///////////////////////////////////////////////////////////////////////////////
32 //  GPU internal polygon drawing functions
33
34 ///////////////////////////////////////////////////////////////////////////////
35 void gpuDrawF3(const PP gpuPolySpanDriver)
36 {
37         const int li=linesInterlace;
38         s32 temp;
39         s32 xa, xb, xmin, xmax;
40         s32 ya, yb, ymin, ymax;
41         s32 x0, x1, x2, x3, dx3=0, x4, dx4=0, dx;
42         s32 y0, y1, y2;
43
44         x0 = GPU_EXPANDSIGN(PacketBuffer.S2[2]);
45         y0 = GPU_EXPANDSIGN(PacketBuffer.S2[3]);
46         x1 = GPU_EXPANDSIGN(PacketBuffer.S2[4]);
47         y1 = GPU_EXPANDSIGN(PacketBuffer.S2[5]);
48         x2 = GPU_EXPANDSIGN(PacketBuffer.S2[6]);
49         y2 = GPU_EXPANDSIGN(PacketBuffer.S2[7]);
50
51         GPU_TESTRANGE3();
52
53         x0 += DrawingOffset[0];   x1 += DrawingOffset[0];   x2 += DrawingOffset[0];
54         y0 += DrawingOffset[1];   y1 += DrawingOffset[1];   y2 += DrawingOffset[1];
55
56         xmin = DrawingArea[0];  xmax = DrawingArea[2];
57         ymin = DrawingArea[1];  ymax = DrawingArea[3];
58
59         {
60                 int rx0 = Max2(xmin,Min3(x0,x1,x2));
61                 int ry0 = Max2(ymin,Min3(y0,y1,y2));
62                 int rx1 = Min2(xmax,Max3(x0,x1,x2));
63                 int ry1 = Min2(ymax,Max3(y0,y1,y2));
64                 if( rx0>=rx1 || ry0>=ry1) return;
65         }
66         
67         PixelData = GPU_RGB16(PacketBuffer.U4[0]);
68
69         if (y0 >= y1)
70         {
71                 if( y0!=y1 || x0>x1 )
72                 {
73                         GPU_SWAP(x0, x1, temp);
74                         GPU_SWAP(y0, y1, temp);
75                 }
76         }
77         if (y1 >= y2)
78         {
79                 if( y1!=y2 || x1>x2 )
80                 {
81                         GPU_SWAP(x1, x2, temp);
82                         GPU_SWAP(y1, y2, temp);
83                 }
84         }
85         if (y0 >= y1)
86         {
87                 if( y0!=y1 || x0>x1 )
88                 {
89                         GPU_SWAP(x0, x1, temp);
90                         GPU_SWAP(y0, y1, temp);
91                 }
92         }
93
94         ya = y2 - y0;
95         yb = y2 - y1;
96         dx =(x2 - x1) * ya - (x2 - x0) * yb;
97
98         for (s32 loop0 = 2; loop0; --loop0)
99         {
100                 if (loop0 == 2)
101                 {
102                         ya = y0;
103                         yb = y1;
104                         x3 = i2x(x0);
105                         x4 = y0!=y1 ? x3 : i2x(x1);
106                         if (dx < 0)
107                         {
108                                 dx3 = xLoDivx((x2 - x0), (y2 - y0));
109                                 dx4 = xLoDivx((x1 - x0), (y1 - y0));
110                         }
111                         else
112                         {
113                                 dx3 = xLoDivx((x1 - x0), (y1 - y0));
114                                 dx4 = xLoDivx((x2 - x0), (y2 - y0));
115                         }
116                 }
117                 else
118                 {
119                         ya = y1;
120                         yb = y2;
121                         if (dx < 0)
122                         {
123                                 x4  = i2x(x1);
124                                 x3  = i2x(x0) + (dx3 * (y1 - y0));
125                                 dx4 = xLoDivx((x2 - x1), (y2 - y1));
126                         }
127                         else
128                         {
129                                 x3  = i2x(x1);
130                                 x4  = i2x(x0) + (dx4 * (y1 - y0));
131                                 dx3 = xLoDivx((x2 - x1), (y2 - y1));
132                         }
133                 }
134
135                 temp = ymin - ya;
136                 if (temp > 0)
137                 {
138                         ya  = ymin;
139                         x3 += dx3*temp;
140                         x4 += dx4*temp;
141                 }
142                 if (yb > ymax) yb = ymax;
143                 if (ya>=yb) continue;
144
145                 x3+= fixed_HALF;
146                 x4+= fixed_HALF;
147
148                 u16* PixelBase  = &((u16*)GPU_FrameBuffer)[FRAME_OFFSET(0, ya)];
149                 
150                 for(;ya<yb;++ya, PixelBase += FRAME_WIDTH, x3+=dx3, x4+=dx4)
151                 {
152                         if (ya&li) continue;
153                         xa = x2i(x3);
154                         xb = x2i(x4);
155                         if( (xa>xmax) || (xb<xmin) ) continue;
156                         if(xa < xmin) xa = xmin;
157                         if(xb > xmax) xb = xmax;
158                         xb-=xa;
159                         if(xb>0) gpuPolySpanDriver(PixelBase + xa,xb);
160                 }
161         }
162 }
163
164 /*----------------------------------------------------------------------
165 FT3
166 ----------------------------------------------------------------------*/
167
168 void gpuDrawFT3(const PP gpuPolySpanDriver)
169 {
170         const int li=linesInterlace;
171         s32 temp;
172         s32 xa, xb, xmin, xmax;
173         s32 ya, yb, ymin, ymax;
174         s32 x0, x1, x2, x3, dx3=0, x4, dx4=0, dx;
175         s32 y0, y1, y2;
176         s32 u0, u1, u2, u3, du3=0;
177         s32 v0, v1, v2, v3, dv3=0;
178
179         x0 = GPU_EXPANDSIGN(PacketBuffer.S2[2] );
180         y0 = GPU_EXPANDSIGN(PacketBuffer.S2[3] );
181         x1 = GPU_EXPANDSIGN(PacketBuffer.S2[6] );
182         y1 = GPU_EXPANDSIGN(PacketBuffer.S2[7] );
183         x2 = GPU_EXPANDSIGN(PacketBuffer.S2[10]);
184         y2 = GPU_EXPANDSIGN(PacketBuffer.S2[11]);
185
186         GPU_TESTRANGE3();
187
188         x0 += DrawingOffset[0];   x1 += DrawingOffset[0];   x2 += DrawingOffset[0];
189         y0 += DrawingOffset[1];   y1 += DrawingOffset[1];   y2 += DrawingOffset[1];
190
191         xmin = DrawingArea[0];  xmax = DrawingArea[2];
192         ymin = DrawingArea[1];  ymax = DrawingArea[3];
193
194         {
195                 int rx0 = Max2(xmin,Min3(x0,x1,x2));
196                 int ry0 = Max2(ymin,Min3(y0,y1,y2));
197                 int rx1 = Min2(xmax,Max3(x0,x1,x2));
198                 int ry1 = Min2(ymax,Max3(y0,y1,y2));
199                 if( rx0>=rx1 || ry0>=ry1) return;
200         }
201         
202         u0 = PacketBuffer.U1[8];  v0 = PacketBuffer.U1[9];
203         u1 = PacketBuffer.U1[16]; v1 = PacketBuffer.U1[17];
204         u2 = PacketBuffer.U1[24]; v2 = PacketBuffer.U1[25];
205
206         r4 = s32(PacketBuffer.U1[0]);
207         g4 = s32(PacketBuffer.U1[1]);
208         b4 = s32(PacketBuffer.U1[2]);
209         dr4 = dg4 = db4 = 0;
210
211         if (y0 >= y1)
212         {
213                 if( y0!=y1 || x0>x1 )
214                 {
215                         GPU_SWAP(x0, x1, temp);
216                         GPU_SWAP(y0, y1, temp);
217                         GPU_SWAP(u0, u1, temp);
218                         GPU_SWAP(v0, v1, temp);
219                 }
220         }
221         if (y1 >= y2)
222         {
223                 if( y1!=y2 || x1>x2 )
224                 {
225                         GPU_SWAP(x1, x2, temp);
226                         GPU_SWAP(y1, y2, temp);
227                         GPU_SWAP(u1, u2, temp);
228                         GPU_SWAP(v1, v2, temp);
229                 }
230         }
231         if (y0 >= y1)
232         {
233                 if( y0!=y1 || x0>x1 )
234                 {
235                         GPU_SWAP(x0, x1, temp);
236                         GPU_SWAP(y0, y1, temp);
237                         GPU_SWAP(u0, u1, temp);
238                         GPU_SWAP(v0, v1, temp);
239                 }
240         }
241
242         ya  = y2 - y0;
243         yb  = y2 - y1;
244         dx  = (x2 - x1) * ya - (x2 - x0) * yb;
245         du4 = (u2 - u1) * ya - (u2 - u0) * yb;
246         dv4 = (v2 - v1) * ya - (v2 - v0) * yb;
247
248         s32 iF,iS;
249         xInv( dx, iF, iS);
250         du4 = xInvMulx( du4, iF, iS);
251         dv4 = xInvMulx( dv4, iF, iS);
252         tInc = ((u32)(du4<<7)&0x7fff0000) | ((u32)(dv4>>9)&0x00007fff);
253         tMsk = (TextureWindow[2]<<23) | (TextureWindow[3]<<7) | 0x00ff00ff;
254
255         for (s32 loop0 = 2; loop0; --loop0)
256         {
257                 if (loop0 == 2)
258                 {
259                         ya = y0;
260                         yb = y1;
261                         u3 = i2x(u0);
262                         v3 = i2x(v0);
263                         x3 = i2x(x0);
264                         x4 = y0!=y1 ? x3 : i2x(x1);
265                         if (dx < 0)
266                         {
267                                 xInv( (y2 - y0), iF, iS);
268                                 dx3 = xInvMulx( (x2 - x0), iF, iS);
269                                 du3 = xInvMulx( (u2 - u0), iF, iS);
270                                 dv3 = xInvMulx( (v2 - v0), iF, iS);
271                                 dx4 = xLoDivx ( (x1 - x0), (y1 - y0));
272                         }
273                         else
274                         {
275                                 xInv( (y1 - y0), iF, iS);
276                                 dx3 = xInvMulx( (x1 - x0), iF, iS);
277                                 du3 = xInvMulx( (u1 - u0), iF, iS);
278                                 dv3 = xInvMulx( (v1 - v0), iF, iS);
279                                 dx4 = xLoDivx ( (x2 - x0), (y2 - y0));
280                         }
281                 }
282                 else
283                 {
284                         ya = y1;
285                         yb = y2;
286                         if (dx < 0)
287                         {
288                                 temp = y1 - y0;
289                                 u3 = i2x(u0) + (du3 * temp);
290                                 v3 = i2x(v0) + (dv3 * temp);
291                                 x3 = i2x(x0) + (dx3 * temp);
292                                 x4 = i2x(x1);
293                                 dx4 = xLoDivx((x2 - x1), (y2 - y1));
294                         }
295                         else
296                         {
297                                 u3 = i2x(u1);
298                                 v3 = i2x(v1);
299                                 x3 = i2x(x1);
300                                 x4 = i2x(x0) + (dx4 * (y1 - y0));
301                                 xInv( (y2 - y1), iF, iS);
302                                 dx3 = xInvMulx( (x2 - x1), iF, iS);
303                                 du3 = xInvMulx( (u2 - u1), iF, iS);
304                                 dv3 = xInvMulx( (v2 - v1), iF, iS);
305                         }
306                 }
307
308                 temp = ymin - ya;
309                 if (temp > 0)
310                 {
311                         ya  = ymin;
312                         x3 += dx3*temp;
313                         x4 += dx4*temp;
314                         u3 += du3*temp;
315                         v3 += dv3*temp;
316                 }
317                 if (yb > ymax) yb = ymax;
318                 if (ya>=yb) continue;
319
320                 x3+= fixed_HALF;
321                 x4+= fixed_HALF;
322                 u3+= fixed_HALF;
323                 v4+= fixed_HALF;
324
325                 u16* PixelBase  = &((u16*)GPU_FrameBuffer)[FRAME_OFFSET(0, ya)];
326
327                 for(;ya<yb;++ya, PixelBase += FRAME_WIDTH, x3+=dx3, x4+=dx4, u3+=du3, v3+=dv3)
328                 {
329                         if (ya&li) continue;
330                         xa = x2i(x3);
331                         xb = x2i(x4);
332                         if( (xa>xmax) || (xb<xmin) ) continue;
333
334                         temp = xmin - xa;
335                         if(temp > 0)
336                         {
337                                 xa  = xmin;
338                                 u4 = u3 + du4*temp;
339                                 v4 = v3 + dv4*temp;
340                         }
341                         else
342                         {
343                                 u4 = u3;
344                                 v4 = v3;
345                         }
346                         if(xb > xmax) xb = xmax;
347                         xb-=xa;
348                         if(xb>0) gpuPolySpanDriver(PixelBase + xa,xb);
349                 }
350         }
351 }
352
353 /*----------------------------------------------------------------------
354 G3
355 ----------------------------------------------------------------------*/
356
357 void gpuDrawG3(const PP gpuPolySpanDriver)
358 {
359         const int li=linesInterlace;
360         s32 temp;
361         s32 xa, xb, xmin, xmax;
362         s32 ya, yb, ymin, ymax;
363         s32 x0, x1, x2, x3, dx3=0, x4, dx4=0, dx;
364         s32 y0, y1, y2;
365         s32 r0, r1, r2, r3, dr3=0;
366         s32 g0, g1, g2, g3, dg3=0;
367         s32 b0, b1, b2, b3, db3=0;
368
369         x0 = GPU_EXPANDSIGN(PacketBuffer.S2[2] );
370         y0 = GPU_EXPANDSIGN(PacketBuffer.S2[3] );
371         x1 = GPU_EXPANDSIGN(PacketBuffer.S2[6] );
372         y1 = GPU_EXPANDSIGN(PacketBuffer.S2[7] );
373         x2 = GPU_EXPANDSIGN(PacketBuffer.S2[10]);
374         y2 = GPU_EXPANDSIGN(PacketBuffer.S2[11]);
375
376         GPU_TESTRANGE3();
377
378         x0 += DrawingOffset[0];   x1 += DrawingOffset[0];   x2 += DrawingOffset[0];
379         y0 += DrawingOffset[1];   y1 += DrawingOffset[1];   y2 += DrawingOffset[1];
380
381         xmin = DrawingArea[0];  xmax = DrawingArea[2];
382         ymin = DrawingArea[1];  ymax = DrawingArea[3];
383
384         {
385                 int rx0 = Max2(xmin,Min3(x0,x1,x2));
386                 int ry0 = Max2(ymin,Min3(y0,y1,y2));
387                 int rx1 = Min2(xmax,Max3(x0,x1,x2));
388                 int ry1 = Min2(ymax,Max3(y0,y1,y2));
389                 if( rx0>=rx1 || ry0>=ry1) return;
390         }
391         
392         r0 = PacketBuffer.U1[0];        g0 = PacketBuffer.U1[1];        b0 = PacketBuffer.U1[2];
393         r1 = PacketBuffer.U1[8];        g1 = PacketBuffer.U1[9];        b1 = PacketBuffer.U1[10];
394         r2 = PacketBuffer.U1[16];       g2 = PacketBuffer.U1[17];       b2 = PacketBuffer.U1[18];
395
396         if (y0 >= y1)
397         {
398                 if( y0!=y1 || x0>x1 )
399                 {
400                         GPU_SWAP(x0, x1, temp);         GPU_SWAP(y0, y1, temp);
401                         GPU_SWAP(r0, r1, temp);         GPU_SWAP(g0, g1, temp);         GPU_SWAP(b0, b1, temp);
402                 }
403         }
404         if (y1 >= y2)
405         {
406                 if( y1!=y2 || x1>x2 )
407                 {
408                         GPU_SWAP(x1, x2, temp);         GPU_SWAP(y1, y2, temp);
409                         GPU_SWAP(r1, r2, temp);         GPU_SWAP(g1, g2, temp);   GPU_SWAP(b1, b2, temp);
410                 }
411         }
412         if (y0 >= y1)
413         {
414                 if( y0!=y1 || x0>x1 )
415                 {
416                         GPU_SWAP(x0, x1, temp);         GPU_SWAP(y0, y1, temp);
417                         GPU_SWAP(r0, r1, temp);   GPU_SWAP(g0, g1, temp);               GPU_SWAP(b0, b1, temp);
418                 }
419         }
420
421         ya  = y2 - y0;
422         yb  = y2 - y1;
423         dx  = (x2 - x1) * ya - (x2 - x0) * yb;
424         dr4 = (r2 - r1) * ya - (r2 - r0) * yb;
425         dg4 = (g2 - g1) * ya - (g2 - g0) * yb;
426         db4 = (b2 - b1) * ya - (b2 - b0) * yb;
427
428         s32 iF,iS;
429         xInv(            dx, iF, iS);
430         dr4 = xInvMulx( dr4, iF, iS);
431         dg4 = xInvMulx( dg4, iF, iS);
432         db4 = xInvMulx( db4, iF, iS);
433         u32 dr = (u32)(dr4<< 8)&(0xffffffff<<21);   if(dr4<0) dr+= 1<<21;
434         u32 dg = (u32)(dg4>> 3)&(0xffffffff<<10);   if(dg4<0) dg+= 1<<10;
435         u32 db = (u32)(db4>>14)&(0xffffffff    );   if(db4<0) db+= 1<< 0;
436         lInc = db + dg + dr;
437
438         for (s32 loop0 = 2; loop0; --loop0)
439         {
440                 if (loop0 == 2)
441                 {
442                         ya = y0;
443                         yb = y1;
444                         r3 = i2x(r0);
445                         g3 = i2x(g0);
446                         b3 = i2x(b0);
447                         x3 = i2x(x0);
448                         x4 = y0!=y1 ? x3 : i2x(x1);
449                         if (dx < 0)
450                         {
451                                 xInv(           (y2 - y0), iF, iS);
452                                 dx3 = xInvMulx( (x2 - x0), iF, iS);
453                                 dr3 = xInvMulx( (r2 - r0), iF, iS);
454                                 dg3 = xInvMulx( (g2 - g0), iF, iS);
455                                 db3 = xInvMulx( (b2 - b0), iF, iS);
456                                 dx4 = xLoDivx ( (x1 - x0), (y1 - y0));
457                         }
458                         else
459                         {
460                                 xInv(           (y1 - y0), iF, iS);
461                                 dx3 = xInvMulx( (x1 - x0), iF, iS);
462                                 dr3 = xInvMulx( (r1 - r0), iF, iS);
463                                 dg3 = xInvMulx( (g1 - g0), iF, iS);
464                                 db3 = xInvMulx( (b1 - b0), iF, iS);
465                                 dx4 = xLoDivx ( (x2 - x0), (y2 - y0));
466                         }
467                 }
468                 else
469                 {
470                         ya = y1;
471                         yb = y2;
472                         if (dx < 0)
473                         {
474                                 temp = y1 - y0;
475                                 r3  = i2x(r0) + (dr3 * temp);
476                                 g3  = i2x(g0) + (dg3 * temp);
477                                 b3  = i2x(b0) + (db3 * temp);
478                                 x3  = i2x(x0) + (dx3 * temp);
479                                 x4  = i2x(x1);
480                                 dx4 = xLoDivx((x2 - x1), (y2 - y1));
481                         }
482                         else
483                         {
484                                 r3 = i2x(r1);
485                                 g3 = i2x(g1);
486                                 b3 = i2x(b1);
487                                 x3 = i2x(x1);
488                                 x4 = i2x(x0) + (dx4 * (y1 - y0));
489
490                                 xInv(           (y2 - y1), iF, iS);
491                                 dx3 = xInvMulx( (x2 - x1), iF, iS);
492                                 dr3 = xInvMulx( (r2 - r1), iF, iS);
493                                 dg3 = xInvMulx( (g2 - g1), iF, iS);
494                                 db3 = xInvMulx( (b2 - b1), iF, iS);
495                         }
496                 }
497
498                 temp = ymin - ya;
499                 if (temp > 0)
500                 {
501                         ya  = ymin;
502                         x3 += dx3*temp;   x4 += dx4*temp;
503                         r3 += dr3*temp;   g3 += dg3*temp;   b3 += db3*temp;
504                 }
505                 if (yb > ymax) yb = ymax;
506                 if (ya>=yb) continue;
507
508                 x3+= fixed_HALF;  x4+= fixed_HALF;
509                 r3+= fixed_HALF;  g3+= fixed_HALF;  b3+= fixed_HALF;
510
511                 u16* PixelBase  = &((u16*)GPU_FrameBuffer)[FRAME_OFFSET(0, ya)];
512                 
513                 for(;ya<yb;++ya, PixelBase += FRAME_WIDTH, x3+=dx3, x4+=dx4, r3+=dr3, g3+=dg3, b3+=db3)
514                 {
515                         if (ya&li) continue;
516                         xa = x2i(x3);
517                         xb = x2i(x4);
518                         if( (xa>xmax) || (xb<xmin) ) continue;
519
520                         temp = xmin - xa;
521                         if(temp > 0)
522                         {
523                                 xa  = xmin;
524                                 r4 = r3 + dr4*temp;   g4 = g3 + dg4*temp;   b4 = b3 + db4*temp;
525                         }
526                         else
527                         {
528                                 r4 = r3;  g4 = g3;  b4 = b3;
529                         }
530                         if(xb > xmax) xb = xmax;
531                         xb-=xa;
532                         if(xb>0) gpuPolySpanDriver(PixelBase + xa,xb);
533                 }
534         }
535 }
536
537 /*----------------------------------------------------------------------
538 GT3
539 ----------------------------------------------------------------------*/
540
541 void gpuDrawGT3(const PP gpuPolySpanDriver)
542 {
543         const int li=linesInterlace;
544         s32 temp;
545         s32 xa, xb, xmin, xmax;
546         s32 ya, yb, ymin, ymax;
547         s32 x0, x1, x2, x3, dx3=0, x4, dx4=0, dx;
548         s32 y0, y1, y2;
549         s32 u0, u1, u2, u3, du3=0;
550         s32 v0, v1, v2, v3, dv3=0;
551         s32 r0, r1, r2, r3, dr3=0;
552         s32 g0, g1, g2, g3, dg3=0;
553         s32 b0, b1, b2, b3, db3=0;
554
555         x0 = GPU_EXPANDSIGN(PacketBuffer.S2[2] );
556         y0 = GPU_EXPANDSIGN(PacketBuffer.S2[3] );
557         x1 = GPU_EXPANDSIGN(PacketBuffer.S2[8] );
558         y1 = GPU_EXPANDSIGN(PacketBuffer.S2[9] );
559         x2 = GPU_EXPANDSIGN(PacketBuffer.S2[14]);
560         y2 = GPU_EXPANDSIGN(PacketBuffer.S2[15]);
561
562         GPU_TESTRANGE3();
563
564         x0 += DrawingOffset[0];   x1 += DrawingOffset[0];   x2 += DrawingOffset[0];
565         y0 += DrawingOffset[1];   y1 += DrawingOffset[1];   y2 += DrawingOffset[1];
566
567         xmin = DrawingArea[0];  xmax = DrawingArea[2];
568         ymin = DrawingArea[1];  ymax = DrawingArea[3];
569
570         {
571                 int rx0 = Max2(xmin,Min3(x0,x1,x2));
572                 int ry0 = Max2(ymin,Min3(y0,y1,y2));
573                 int rx1 = Min2(xmax,Max3(x0,x1,x2));
574                 int ry1 = Min2(ymax,Max3(y0,y1,y2));
575                 if( rx0>=rx1 || ry0>=ry1) return;
576         }
577
578         r0 = PacketBuffer.U1[0];        g0 = PacketBuffer.U1[1];        b0 = PacketBuffer.U1[2];
579         u0 = PacketBuffer.U1[8];        v0 = PacketBuffer.U1[9];
580         r1 = PacketBuffer.U1[12];       g1 = PacketBuffer.U1[13];       b1 = PacketBuffer.U1[14];
581         u1 = PacketBuffer.U1[20];       v1 = PacketBuffer.U1[21];
582         r2 = PacketBuffer.U1[24];       g2 = PacketBuffer.U1[25];       b2 = PacketBuffer.U1[26];
583         u2 = PacketBuffer.U1[32];       v2 = PacketBuffer.U1[33];
584
585         if (y0 >= y1)
586         {
587                 if( y0!=y1 || x0>x1 )
588                 {
589                         GPU_SWAP(x0, x1, temp);         GPU_SWAP(y0, y1, temp);
590                         GPU_SWAP(u0, u1, temp);         GPU_SWAP(v0, v1, temp);
591                         GPU_SWAP(r0, r1, temp);         GPU_SWAP(g0, g1, temp);   GPU_SWAP(b0, b1, temp);
592                 }
593         }
594         if (y1 >= y2)
595         {
596                 if( y1!=y2 || x1>x2 )
597                 {
598                         GPU_SWAP(x1, x2, temp);         GPU_SWAP(y1, y2, temp);
599                         GPU_SWAP(u1, u2, temp);         GPU_SWAP(v1, v2, temp);
600                         GPU_SWAP(r1, r2, temp);   GPU_SWAP(g1, g2, temp);               GPU_SWAP(b1, b2, temp);
601                 }
602         }
603         if (y0 >= y1)
604         {
605                 if( y0!=y1 || x0>x1 )
606                 {
607                         GPU_SWAP(x0, x1, temp);         GPU_SWAP(y0, y1, temp);
608                         GPU_SWAP(u0, u1, temp);         GPU_SWAP(v0, v1, temp);
609                         GPU_SWAP(r0, r1, temp);         GPU_SWAP(g0, g1, temp);         GPU_SWAP(b0, b1, temp);
610                 }
611         }
612
613         ya  = y2 - y0;
614         yb  = y2 - y1;
615         dx  = (x2 - x1) * ya - (x2 - x0) * yb;
616         du4 = (u2 - u1) * ya - (u2 - u0) * yb;
617         dv4 = (v2 - v1) * ya - (v2 - v0) * yb;
618         dr4 = (r2 - r1) * ya - (r2 - r0) * yb;
619         dg4 = (g2 - g1) * ya - (g2 - g0) * yb;
620         db4 = (b2 - b1) * ya - (b2 - b0) * yb;
621
622         s32 iF,iS;
623
624         xInv(            dx, iF, iS);
625         du4 = xInvMulx( du4, iF, iS);
626         dv4 = xInvMulx( dv4, iF, iS);
627         dr4 = xInvMulx( dr4, iF, iS);
628         dg4 = xInvMulx( dg4, iF, iS);
629         db4 = xInvMulx( db4, iF, iS);
630         u32 dr = (u32)(dr4<< 8)&(0xffffffff<<21);   if(dr4<0) dr+= 1<<21;
631         u32 dg = (u32)(dg4>> 3)&(0xffffffff<<10);   if(dg4<0) dg+= 1<<10;
632         u32 db = (u32)(db4>>14)&(0xffffffff    );   if(db4<0) db+= 1<< 0;
633         lInc = db + dg + dr;
634         tInc = ((u32)(du4<<7)&0x7fff0000) | ((u32)(dv4>>9)&0x00007fff);
635         tMsk = (TextureWindow[2]<<23) | (TextureWindow[3]<<7) | 0x00ff00ff;
636
637         for (s32 loop0 = 2; loop0; --loop0)
638         {
639                 if (loop0 == 2)
640                 {
641                         ya = y0;
642                         yb = y1;
643                         u3 = i2x(u0);
644                         v3 = i2x(v0);
645                         r3 = i2x(r0);
646                         g3 = i2x(g0);
647                         b3 = i2x(b0);
648                         x3 = i2x(x0);
649                         x4 = y0!=y1 ? x3 : i2x(x1);
650                         if (dx < 0)
651                         {
652                                 xInv(           (y2 - y0), iF, iS);
653                                 dx3 = xInvMulx( (x2 - x0), iF, iS);
654                                 du3 = xInvMulx( (u2 - u0), iF, iS);
655                                 dv3 = xInvMulx( (v2 - v0), iF, iS);
656                                 dr3 = xInvMulx( (r2 - r0), iF, iS);
657                                 dg3 = xInvMulx( (g2 - g0), iF, iS);
658                                 db3 = xInvMulx( (b2 - b0), iF, iS);
659                                 dx4 = xLoDivx ( (x1 - x0), (y1 - y0));
660                         }
661                         else
662                         {
663                                 xInv(           (y1 - y0), iF, iS);
664                                 dx3 = xInvMulx( (x1 - x0), iF, iS);
665                                 du3 = xInvMulx( (u1 - u0), iF, iS);
666                                 dv3 = xInvMulx( (v1 - v0), iF, iS);
667                                 dr3 = xInvMulx( (r1 - r0), iF, iS);
668                                 dg3 = xInvMulx( (g1 - g0), iF, iS);
669                                 db3 = xInvMulx( (b1 - b0), iF, iS);
670                                 dx4 = xLoDivx ( (x2 - x0), (y2 - y0));
671                         }
672                 }
673                 else
674                 {
675                         ya = y1;
676                         yb = y2;
677                         if (dx < 0)
678                         {
679                                 temp = y1 - y0;
680                                 u3  = i2x(u0) + (du3 * temp);
681                                 v3  = i2x(v0) + (dv3 * temp);
682                                 r3  = i2x(r0) + (dr3 * temp);
683                                 g3  = i2x(g0) + (dg3 * temp);
684                                 b3  = i2x(b0) + (db3 * temp);
685                                 x3  = i2x(x0) + (dx3 * temp);
686                                 x4  = i2x(x1);
687                                 dx4 = xLoDivx((x2 - x1), (y2 - y1));
688                         }
689                         else
690                         {
691                                 u3 = i2x(u1);
692                                 v3 = i2x(v1);
693                                 r3 = i2x(r1);
694                                 g3 = i2x(g1);
695                                 b3 = i2x(b1);
696                                 x3 = i2x(x1);
697                                 x4 = i2x(x0) + (dx4 * (y1 - y0));
698
699                                 xInv(           (y2 - y1), iF, iS);
700                                 dx3 = xInvMulx( (x2 - x1), iF, iS);
701                                 du3 = xInvMulx( (u2 - u1), iF, iS);
702                                 dv3 = xInvMulx( (v2 - v1), iF, iS);
703                                 dr3 = xInvMulx( (r2 - r1), iF, iS);
704                                 dg3 = xInvMulx( (g2 - g1), iF, iS);
705                                 db3 = xInvMulx( (b2 - b1), iF, iS);
706                         }
707                 }
708
709                 temp = ymin - ya;
710                 if (temp > 0)
711                 {
712                         ya  = ymin;
713                         x3 += dx3*temp;   x4 += dx4*temp;
714                         u3 += du3*temp;   v3 += dv3*temp;
715                         r3 += dr3*temp;   g3 += dg3*temp;   b3 += db3*temp;
716                 }
717                 if (yb > ymax) yb = ymax;
718                 if (ya>=yb) continue;
719
720                 x3+= fixed_HALF;  x4+= fixed_HALF;
721                 u3+= fixed_HALF;  v4+= fixed_HALF;
722                 r3+= fixed_HALF;  g3+= fixed_HALF;  b3+= fixed_HALF;
723                 u16* PixelBase  = &((u16*)GPU_FrameBuffer)[FRAME_OFFSET(0, ya)];
724                 
725                 for(;ya<yb;++ya, PixelBase += FRAME_WIDTH, x3+=dx3, x4+=dx4, u3+=du3, v3+=dv3, r3+=dr3, g3+=dg3,        b3+=db3)
726                 {
727                         if (ya&li) continue;
728                         xa = x2i(x3);
729                         xb = x2i(x4);
730                         if( (xa>xmax) || (xb<xmin))     continue;
731
732                         temp = xmin - xa;
733                         if(temp > 0)
734                         {
735                                 xa  = xmin;
736                                 u4 = u3 + du4*temp;   v4 = v3 + dv4*temp;
737                                 r4 = r3 + dr4*temp;   g4 = g3 + dg4*temp;   b4 = b3 + db4*temp;
738                         }
739                         else
740                         {
741                                 u4 = u3;  v4 = v3;
742                                 r4 = r3;  g4 = g3;  b4 = b3;
743                         }
744                         if(xb > xmax) xb = xmax;
745                         xb-=xa;
746                         if(xb>0) gpuPolySpanDriver(PixelBase + xa,xb);
747                 }
748         }
749 }