Glide Plugin GLES2 port from mupen64plus-ae, but with special FrameSkip code
[mupen64plus-pandora.git] / source / gles2glide64 / src / Glide64 / FBtoScreen.cpp
1 /*
2 * Glide64 - Glide video plugin for Nintendo 64 emulators.
3 * Copyright (c) 2002  Dave2001
4 * Copyright (c) 2003-2009  Sergey 'Gonetz' Lipski
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 */
20
21 //****************************************************************
22 //
23 // Glide64 - Glide Plugin for Nintendo 64 emulators
24 // Project started on December 29th, 2001
25 //
26 // Authors:
27 // Dave2001, original author, founded the project in 2001, left it in 2002
28 // Gugaman, joined the project in 2002, left it in 2002
29 // Sergey 'Gonetz' Lipski, joined the project in 2002, main author since fall of 2002
30 // Hiroshi 'KoolSmoky' Morii, joined the project in 2007
31 //
32 //****************************************************************
33 //
34 // To modify Glide64:
35 // * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me.
36 // * Do NOT send me the whole project or file that you modified.  Take out your modified code sections, and tell me where to put them.  If people sent the whole thing, I would have many different versions, but no idea how to combine them all.
37 //
38 //****************************************************************
39 //
40 // Draw N64 frame buffer to screen.
41 // Created by Gonetz, 2007
42 //
43 //****************************************************************
44
45
46 #include "Gfx_1.3.h"
47 #include "FBtoScreen.h"
48 #include "TexCache.h"
49
50 static int SetupFBtoScreenCombiner(wxUint32 texture_size, wxUint32 opaque)
51 {
52   int tmu;
53   if (voodoo.tmem_ptr[GR_TMU0]+texture_size < voodoo.tex_max_addr[0])
54   {
55     tmu = GR_TMU0;
56     grTexCombine( GR_TMU1,
57       GR_COMBINE_FUNCTION_NONE,
58       GR_COMBINE_FACTOR_NONE,
59       GR_COMBINE_FUNCTION_NONE,
60       GR_COMBINE_FACTOR_NONE,
61       FXFALSE,
62       FXFALSE );
63     grTexCombine( GR_TMU0,
64       GR_COMBINE_FUNCTION_LOCAL,
65       GR_COMBINE_FACTOR_NONE,
66       GR_COMBINE_FUNCTION_LOCAL,
67       GR_COMBINE_FACTOR_NONE,
68       FXFALSE,
69       FXFALSE );
70   }
71   else
72   {
73     if (voodoo.tmem_ptr[GR_TMU1]+texture_size >= voodoo.tex_max_addr[1])
74       ClearCache ();
75     tmu = GR_TMU1;
76     grTexCombine( GR_TMU1,
77       GR_COMBINE_FUNCTION_LOCAL,
78       GR_COMBINE_FACTOR_NONE,
79       GR_COMBINE_FUNCTION_LOCAL,
80       GR_COMBINE_FACTOR_NONE,
81       FXFALSE,
82       FXFALSE );
83     grTexCombine( GR_TMU0,
84       GR_COMBINE_FUNCTION_SCALE_OTHER,
85       GR_COMBINE_FACTOR_ONE,
86       GR_COMBINE_FUNCTION_SCALE_OTHER,
87       GR_COMBINE_FACTOR_ONE,
88       FXFALSE,
89       FXFALSE );
90   }
91   int filter = (rdp.filter_mode!=2)?GR_TEXTUREFILTER_POINT_SAMPLED:GR_TEXTUREFILTER_BILINEAR;
92   grTexFilterMode (tmu, filter, filter);
93   grTexClampMode (tmu,
94         GR_TEXTURECLAMP_CLAMP,
95         GR_TEXTURECLAMP_CLAMP);
96 //  grConstantColorValue (0xFFFFFFFF);
97   grColorCombine (GR_COMBINE_FUNCTION_SCALE_OTHER,
98     GR_COMBINE_FACTOR_ONE,
99     GR_COMBINE_LOCAL_NONE,
100     GR_COMBINE_OTHER_TEXTURE,
101 //    GR_COMBINE_OTHER_CONSTANT,
102     FXFALSE);
103   grAlphaCombine (GR_COMBINE_FUNCTION_SCALE_OTHER,
104     GR_COMBINE_FACTOR_ONE,
105     GR_COMBINE_LOCAL_NONE,
106     GR_COMBINE_OTHER_TEXTURE,
107     FXFALSE);
108   if (opaque)
109   {
110     grAlphaTestFunction (GR_CMP_ALWAYS);
111     grAlphaBlendFunction( GR_BLEND_ONE,
112       GR_BLEND_ZERO,
113       GR_BLEND_ONE,
114       GR_BLEND_ZERO);
115   }
116   else
117   {
118     grAlphaBlendFunction( GR_BLEND_SRC_ALPHA,
119       GR_BLEND_ONE_MINUS_SRC_ALPHA,
120       GR_BLEND_ONE,
121       GR_BLEND_ZERO);
122   }
123   grDepthBufferFunction (GR_CMP_ALWAYS);
124   grCullMode(GR_CULL_DISABLE);
125   grDepthMask (FXFALSE);
126   rdp.update |= UPDATE_COMBINE | UPDATE_ZBUF_ENABLED | UPDATE_CULL_MODE;
127   return tmu;
128 }
129
130 static void DrawRE2Video(FB_TO_SCREEN_INFO & fb_info, float scale)
131 {
132   float scale_y = (float)fb_info.width/rdp.vi_height;
133   float height = settings.scr_res_x/scale_y;
134   float ul_x = 0.5f;
135   float ul_y = (settings.scr_res_y - height)/2.0f;
136   float lr_y = settings.scr_res_y - ul_y - 1.0f;
137   float lr_x = settings.scr_res_x - 1.0f;
138   float lr_u = (fb_info.width - 1)*scale;
139   float lr_v = (fb_info.height - 1)*scale;
140   VERTEX v[4] = {
141     { ul_x, ul_y, 1, 1, 0.5f, 0.5f, 0.5f, 0.5f, {0.5f, 0.5f, 0.5f, 0.5f} },
142     { lr_x, ul_y, 1, 1, lr_u, 0.5f, lr_u, 0.5f, {lr_u, 0.5f, lr_u, 0.5f} },
143     { ul_x, lr_y, 1, 1, 0.5f, lr_v, 0.5f, lr_v, {0.5f, lr_v, 0.5f, lr_v} },
144     { lr_x, lr_y, 1, 1, lr_u, lr_v, lr_u, lr_v, {lr_u, lr_v, lr_u, lr_v} }
145   };
146   grDrawTriangle (&v[0], &v[2], &v[1]);
147   grDrawTriangle (&v[2], &v[3], &v[1]);
148 }
149
150 static void DrawRE2Video256(FB_TO_SCREEN_INFO & fb_info)
151 {
152   FRDP("DrawRE2Video256. ul_x=%d, ul_y=%d, lr_x=%d, lr_y=%d, size=%d, addr=%08lx\n", fb_info.ul_x, fb_info.ul_y, fb_info.lr_x, fb_info.lr_y, fb_info.size, fb_info.addr);
153   wxUint32 * src = (wxUint32*)(gfx.RDRAM+fb_info.addr);
154   GrTexInfo t_info;
155   t_info.smallLodLog2 = GR_LOD_LOG2_256;
156   t_info.largeLodLog2 = GR_LOD_LOG2_256;
157   t_info.aspectRatioLog2 = GR_ASPECT_LOG2_1x1;
158   wxUint16 * tex = (wxUint16*)texture_buffer;
159   wxUint16 * dst = tex;
160   wxUint32 col;
161   wxUint8 r, g, b;
162   fb_info.height = min(256, fb_info.height);
163   for (wxUint32 h = 0; h < fb_info.height; h++)
164   {
165     for (wxUint32 w = 0; w < 256; w++)
166     {
167       col = *(src++);
168       r = (wxUint8)((col >> (24+3))&0x1F);
169       g = (wxUint8)((col >> (16+2))&0x3F);
170       b = (wxUint8)((col >>  (8+3))&0x1F);
171 /*      r = (wxUint8)((col >> 24)&0xFF);
172       r = (wxUint8)((float)r / 255.0f * 31.0f);
173       g = (wxUint8)((col >> 16)&0xFF);
174       g = (wxUint8)((float)g / 255.0f * 63.0f);
175       b = (wxUint8)((col >>  8)&0xFF);
176       b = (wxUint8)((float)b / 255.0f * 31.0f);*/       //*SEB*
177       *(dst++) = (r << 11) | (g << 5) | b;
178     }
179     src += (fb_info.width - 256);
180   }
181   t_info.format = GR_TEXFMT_RGB_565;
182   t_info.data = tex;
183   int tmu = SetupFBtoScreenCombiner(grTexTextureMemRequired(GR_MIPMAPLEVELMASK_BOTH, &t_info), fb_info.opaque);
184   grTexDownloadMipMap (tmu,
185     voodoo.tex_min_addr[tmu]+voodoo.tmem_ptr[tmu],
186     GR_MIPMAPLEVELMASK_BOTH,
187     &t_info);
188   grTexSource (tmu,
189       voodoo.tex_min_addr[tmu]+voodoo.tmem_ptr[tmu],
190       GR_MIPMAPLEVELMASK_BOTH,
191       &t_info);
192   DrawRE2Video(fb_info, 1.0f);
193 }
194
195 static void DrawFrameBufferToScreen256(FB_TO_SCREEN_INFO & fb_info)
196 {
197   if (settings.hacks&hack_RE2)
198   {
199     DrawRE2Video256(fb_info);
200     return;
201   }
202   FRDP("DrawFrameBufferToScreen256. ul_x=%d, ul_y=%d, lr_x=%d, lr_y=%d, size=%d, addr=%08lx\n", fb_info.ul_x, fb_info.ul_y, fb_info.lr_x, fb_info.lr_y, fb_info.size, fb_info.addr);
203   wxUint32 width = fb_info.lr_x - fb_info.ul_x + 1;
204   wxUint32 height = fb_info.lr_y - fb_info.ul_y + 1;
205   GrTexInfo t_info;
206   wxUint8 * image = gfx.RDRAM+fb_info.addr;
207   wxUint32 width256 = ((width-1) >> 8) + 1;
208   wxUint32 height256 = ((height-1) >> 8) + 1;
209   t_info.smallLodLog2 = t_info.largeLodLog2 = GR_LOD_LOG2_256;
210   t_info.aspectRatioLog2 = GR_ASPECT_LOG2_1x1;
211   t_info.format = GR_TEXFMT_ARGB_1555;
212   wxUint16 * tex = (wxUint16*)texture_buffer;
213   t_info.data = tex;
214   wxUint32 tex_size = grTexTextureMemRequired (GR_MIPMAPLEVELMASK_BOTH, &t_info);
215   int tmu = SetupFBtoScreenCombiner(tex_size*width256*height256, fb_info.opaque);
216   wxUint16 * src = (wxUint16*)image;
217   src += fb_info.ul_x + fb_info.ul_y * fb_info.width;
218   wxUint32 * src32 = (wxUint32*)image;
219   src32 += fb_info.ul_x + fb_info.ul_y * fb_info.width;
220   wxUint32 w_tail = width%256;
221   wxUint32 h_tail = height%256;
222   wxUint16 c;
223   wxUint32 c32;
224   wxUint32 idx;
225   wxUint32 bound = BMASK+1-fb_info.addr;
226   bound = fb_info.size == 2 ? bound >> 1 : bound >> 2;
227   wxUint8 r, g, b, a;
228   wxUint32 cur_width, cur_height, cur_tail;
229   wxUint32 tex_adr = voodoo.tex_min_addr[tmu]+voodoo.tmem_ptr[tmu];
230   if ((voodoo.tmem_ptr[tmu] < TEXMEM_2MB_EDGE) && (voodoo.tmem_ptr[tmu]+tex_size*width256*height256 > TEXMEM_2MB_EDGE))
231   {
232     tex_adr = TEXMEM_2MB_EDGE;
233   }
234   for (wxUint32 h = 0; h < height256; h++)
235   {
236     for (wxUint32 w = 0; w < width256; w++)
237     {
238       cur_width = (256*(w+1) < width) ? 256 : w_tail;
239       cur_height = (256*(h+1) < height) ? 256 : h_tail;
240       cur_tail = 256 - cur_width;
241       wxUint16 * dst = tex;
242       if (fb_info.size == 2)
243       {
244         for (wxUint32 y=0; y < cur_height; y++)
245         {
246           for (wxUint32 x=0; x < cur_width; x++)
247           {
248             idx = (x+256*w+(y+256*h)*fb_info.width)^1;
249             if (idx >= bound)
250               break;
251             c = src[idx];
252             *(dst++) = (c >> 1) | ((c&1)<<15);
253           }
254           dst += cur_tail;
255         }
256       }
257       else
258       {
259         for (wxUint32 y=0; y < cur_height; y++)
260         {
261           for (wxUint32 x=0; x < cur_width; x++)
262           {
263             idx = (x+256*w+(y+256*h)*fb_info.width);
264             if (idx >= bound)
265               break;
266             c32 = src32[idx];
267             r = (wxUint8)((c32 >> (24+3))&0x1F);
268             g = (wxUint8)((c32 >> (16+2))&0x3F);
269             b = (wxUint8)((c32 >>  (8+3))&0x1F);
270 /*            r = (wxUint8)((c32 >> 24)&0xFF);
271             r = (wxUint8)((float)r / 255.0f * 31.0f);
272             g = (wxUint8)((c32 >> 16)&0xFF);
273             g = (wxUint8)((float)g / 255.0f * 63.0f);
274             b = (wxUint8)((c32 >>  8)&0xFF);
275             b = (wxUint8)((float)b / 255.0f * 31.0f);*/ //*SEB*
276             a = (c32&0xFF) ? 1 : 0;
277             *(dst++) = (a<<15) | (r << 10) | (g << 5) | b;
278           }
279           dst += cur_tail;
280         }
281       }
282       grTexDownloadMipMap (tmu, tex_adr, GR_MIPMAPLEVELMASK_BOTH, &t_info);
283       grTexSource (tmu, tex_adr, GR_MIPMAPLEVELMASK_BOTH, &t_info);
284       tex_adr += tex_size;
285       float ul_x = (float)(fb_info.ul_x + 256*w);
286       float ul_y = (float)(fb_info.ul_y + 256*h);
287       float lr_x = (ul_x + (float)(cur_width)) * rdp.scale_x;
288       float lr_y = (ul_y + (float)(cur_height)) * rdp.scale_y;
289       ul_x *= rdp.scale_x;
290       ul_y *= rdp.scale_y;
291       ul_x += rdp.offset_x;
292       ul_y += rdp.offset_y;
293       lr_x += rdp.offset_x;
294       lr_y += rdp.offset_y;
295
296       float lr_u = (float)(cur_width-1);
297       float lr_v = (float)(cur_height-1);
298       // Make the vertices
299       VERTEX v[4] = {
300         { ul_x, ul_y, 1, 1, 0.5f, 0.5f, 0.5f, 0.5f, {0.5f, 0.5f, 0.5f, 0.5f} },
301         { lr_x, ul_y, 1, 1, lr_u, 0.5f, lr_u, 0.5f, {lr_u, 0.5f, lr_u, 0.5f} },
302         { ul_x, lr_y, 1, 1, 0.5f, lr_v, 0.5f, lr_v, {0.5f, lr_v, 0.5f, lr_v} },
303         { lr_x, lr_y, 1, 1, lr_u, lr_v, lr_u, lr_v, {lr_u, lr_v, lr_u, lr_v} }
304       };
305       grDrawTriangle (&v[0], &v[2], &v[1]);
306       grDrawTriangle (&v[2], &v[3], &v[1]);
307     }
308   }
309 }
310
311 bool DrawFrameBufferToScreen(FB_TO_SCREEN_INFO & fb_info)
312 {
313   if (fb_info.width < 200 || fb_info.size < 2)
314     return false;
315   wxUint32 width = fb_info.lr_x - fb_info.ul_x + 1;
316   wxUint32 height = fb_info.lr_y - fb_info.ul_y + 1;
317   wxUint32 max_size = min(voodoo.max_tex_size, 512);
318   if (width > (wxUint32)max_size || height > (wxUint32)max_size)
319   {
320     DrawFrameBufferToScreen256(fb_info);
321     return true;
322   }
323   FRDP("DrawFrameBufferToScreen. ul_x=%d, ul_y=%d, lr_x=%d, lr_y=%d, size=%d, addr=%08lx\n", fb_info.ul_x, fb_info.ul_y, fb_info.lr_x, fb_info.lr_y, fb_info.size, fb_info.addr);
324   GrTexInfo t_info;
325   wxUint8 * image = gfx.RDRAM+fb_info.addr;
326   wxUint32 texwidth;
327   float scale;
328   if (width <= 256)
329   {
330     texwidth = 256;
331     scale = 1.0f;
332     t_info.smallLodLog2 = t_info.largeLodLog2 = GR_LOD_LOG2_256;
333   }
334   else
335   {
336     texwidth = 512;
337     scale = 0.5f;
338     t_info.smallLodLog2 = t_info.largeLodLog2 = GR_LOD_LOG2_512;
339   }
340
341   if (height <= (texwidth>>1))
342   {
343     t_info.aspectRatioLog2 = GR_ASPECT_LOG2_2x1;
344   }
345   else
346   {
347     t_info.aspectRatioLog2 = GR_ASPECT_LOG2_1x1;
348   }
349
350   if (fb_info.size == 2)
351   {
352     wxUint16 * tex = (wxUint16*)texture_buffer;
353     wxUint16 * dst = tex;
354     wxUint16 * src = (wxUint16*)image;
355     src += fb_info.ul_x + fb_info.ul_y * fb_info.width;
356     wxUint16 c;
357     wxUint32 idx;
358     const wxUint32 bound = (BMASK+1-fb_info.addr) >> 1;
359     bool empty = true;
360     for (wxUint32 y=0; y < height; y++)
361     {
362       for (wxUint32 x=0; x < width; x++)
363       {
364         idx = (x+y*fb_info.width)^1;
365         if (idx >= bound)
366           break;
367         c = src[idx];
368         if (c) empty = false;
369         *(dst++) = (c >> 1) | ((c&1)<<15);
370       }
371       dst += texwidth-width;
372     }
373     if (empty)
374       return false;
375     t_info.format = GR_TEXFMT_ARGB_1555;
376     t_info.data = tex;
377   }
378   else
379   {
380     wxUint32 * tex = (wxUint32*)texture_buffer;
381     wxUint32 * dst = tex;
382     wxUint32 * src = (wxUint32*)image;
383     src += fb_info.ul_x + fb_info.ul_y * fb_info.width;
384     wxUint32 col;
385     wxUint32 idx;
386     const wxUint32 bound = (BMASK+1-fb_info.addr) >> 2;
387     for (wxUint32 y=0; y < height; y++)
388     {
389       for (wxUint32 x=0; x < width; x++)
390       {
391         idx = x+y*fb_info.width;
392         if (idx >= bound)
393           break;
394         col = src[idx];
395         *(dst++) = (col >> 8) | 0xFF000000;
396       }
397       dst += texwidth-width;
398     }
399     t_info.format = GR_TEXFMT_ARGB_8888;
400     t_info.data = tex;
401   }
402
403   int tmu = SetupFBtoScreenCombiner(grTexTextureMemRequired(GR_MIPMAPLEVELMASK_BOTH, &t_info), fb_info.opaque);
404   grTexDownloadMipMap (tmu,
405     voodoo.tex_min_addr[tmu]+voodoo.tmem_ptr[tmu],
406     GR_MIPMAPLEVELMASK_BOTH,
407     &t_info);
408   grTexSource (tmu,
409     voodoo.tex_min_addr[tmu]+voodoo.tmem_ptr[tmu],
410     GR_MIPMAPLEVELMASK_BOTH,
411     &t_info);
412   if (settings.hacks&hack_RE2)
413   {
414     DrawRE2Video(fb_info, scale);
415   }
416   else
417   {
418     float ul_x = fb_info.ul_x * rdp.scale_x + rdp.offset_x;
419     float ul_y = fb_info.ul_y * rdp.scale_y + rdp.offset_y;
420     float lr_x = fb_info.lr_x * rdp.scale_x + rdp.offset_x;
421     float lr_y = fb_info.lr_y * rdp.scale_y + rdp.offset_y;
422     float lr_u = (width-1)*scale;
423     float lr_v = (height-1)*scale;
424     // Make the vertices
425     VERTEX v[4] = {
426       { ul_x, ul_y, 1, 1, 0.5f, 0.5f, 0.5f, 0.5f, {0.5f, 0.5f, 0.5f, 0.5f} },
427       { lr_x, ul_y, 1, 1, lr_u, 0.5f, lr_u, 0.5f, {lr_u, 0.5f, lr_u, 0.5f} },
428       { ul_x, lr_y, 1, 1, 0.5f, lr_v, 0.5f, lr_v, {0.5f, lr_v, 0.5f, lr_v} },
429       { lr_x, lr_y, 1, 1, lr_u, lr_v, lr_u, lr_v, {lr_u, lr_v, lr_u, lr_v} }
430     };
431     grDrawTriangle (&v[0], &v[2], &v[1]);
432     grDrawTriangle (&v[2], &v[3], &v[1]);
433   }
434   return true;
435 }
436
437 static void DrawDepthBufferToScreen256(FB_TO_SCREEN_INFO & fb_info)
438 {
439   FRDP("DrawDepthBufferToScreen256. ul_x=%d, ul_y=%d, lr_x=%d, lr_y=%d, size=%d, addr=%08lx\n", fb_info.ul_x, fb_info.ul_y, fb_info.lr_x, fb_info.lr_y, fb_info.size, fb_info.addr);
440   wxUint32 width = fb_info.lr_x - fb_info.ul_x + 1;
441   wxUint32 height = fb_info.lr_y - fb_info.ul_y + 1;
442   GrTexInfo t_info;
443   wxUint8 * image = gfx.RDRAM+fb_info.addr;
444   wxUint32 width256 = ((width-1) >> 8) + 1;
445   wxUint32 height256 = ((height-1) >> 8) + 1;
446   t_info.smallLodLog2 = t_info.largeLodLog2 = GR_LOD_LOG2_256;
447   t_info.aspectRatioLog2 = GR_ASPECT_LOG2_1x1;
448   t_info.format = GR_TEXFMT_ALPHA_INTENSITY_88;
449   wxUint16 * tex = (wxUint16*)texture_buffer;
450   t_info.data = tex;
451   wxUint32 tex_size = grTexTextureMemRequired (GR_MIPMAPLEVELMASK_BOTH, &t_info);
452   int tmu = SetupFBtoScreenCombiner(tex_size*width256*height256, fb_info.opaque);
453   grConstantColorValue (rdp.fog_color);
454   grColorCombine (GR_COMBINE_FUNCTION_SCALE_OTHER,
455     GR_COMBINE_FACTOR_ONE,
456     GR_COMBINE_LOCAL_NONE,
457     GR_COMBINE_OTHER_CONSTANT,
458     FXFALSE);
459   wxUint16 * src = (wxUint16*)image;
460   src += fb_info.ul_x + fb_info.ul_y * fb_info.width;
461   wxUint32 w_tail = width%256;
462   wxUint32 h_tail = height%256;
463   wxUint32 cur_width, cur_height, cur_tail;
464   wxUint32 tex_adr = voodoo.tex_min_addr[tmu]+voodoo.tmem_ptr[tmu];
465   if ((voodoo.tmem_ptr[tmu] < TEXMEM_2MB_EDGE) && (voodoo.tmem_ptr[tmu]+tex_size*width256*height256 > TEXMEM_2MB_EDGE))
466   {
467     tex_adr = TEXMEM_2MB_EDGE;
468   }
469   for (wxUint32 h = 0; h < height256; h++)
470   {
471     for (wxUint32 w = 0; w < width256; w++)
472     {
473       cur_width = (256*(w+1) < width) ? 256 : w_tail;
474       cur_height = (256*(h+1) < height) ? 256 : h_tail;
475       cur_tail = 256 - cur_width;
476       wxUint16 * dst = tex;
477       for (wxUint32 y=0; y < cur_height; y++)
478       {
479         for (wxUint32 x=0; x < cur_width; x++)
480         {
481           *(dst++) = rdp.pal_8[src[(x+256*w+(y+256*h)*fb_info.width)^1]>>8];
482         }
483         dst += cur_tail;
484       }
485       grTexDownloadMipMap (tmu, tex_adr, GR_MIPMAPLEVELMASK_BOTH, &t_info);
486       grTexSource (tmu, tex_adr, GR_MIPMAPLEVELMASK_BOTH, &t_info);
487       tex_adr += tex_size;
488       float ul_x = (float)(fb_info.ul_x + 256*w);
489       float ul_y = (float)(fb_info.ul_y + 256*h);
490       float lr_x = (ul_x + (float)(cur_width)) * rdp.scale_x + rdp.offset_x;
491       float lr_y = (ul_y + (float)(cur_height)) * rdp.scale_y + rdp.offset_y;
492       ul_x = ul_x * rdp.scale_x + rdp.offset_x;
493       ul_y = ul_y * rdp.scale_y + rdp.offset_y;
494       float lr_u = (float)(cur_width-1);
495       float lr_v = (float)(cur_height-1);
496       // Make the vertices
497       VERTEX v[4] = {
498         { ul_x, ul_y, 1, 1, 0.5f, 0.5f, 0.5f, 0.5f, {0.5f, 0.5f, 0.5f, 0.5f} },
499         { lr_x, ul_y, 1, 1, lr_u, 0.5f, lr_u, 0.5f, {lr_u, 0.5f, lr_u, 0.5f} },
500         { ul_x, lr_y, 1, 1, 0.5f, lr_v, 0.5f, lr_v, {0.5f, lr_v, 0.5f, lr_v} },
501         { lr_x, lr_y, 1, 1, lr_u, lr_v, lr_u, lr_v, {lr_u, lr_v, lr_u, lr_v} }
502       };
503       grDrawTriangle (&v[0], &v[2], &v[1]);
504       grDrawTriangle (&v[2], &v[3], &v[1]);
505     }
506   }
507 }
508
509 static void DrawHiresDepthBufferToScreen(FB_TO_SCREEN_INFO & fb_info)
510 {
511   FRDP("DrawHiresDepthBufferToScreen. ul_x=%d, ul_y=%d, lr_x=%d, lr_y=%d, size=%d, addr=%08lx\n", fb_info.ul_x, fb_info.ul_y, fb_info.lr_x, fb_info.lr_y, fb_info.size, fb_info.addr);
512   GrTexInfo t_info;
513   float scale = 0.25f;
514   GrLOD_t LOD = GR_LOD_LOG2_1024;
515   if (settings.scr_res_x > 1024)
516   {
517     scale = 0.125f;
518     LOD = GR_LOD_LOG2_2048;
519   }
520   t_info.format = GR_TEXFMT_ALPHA_INTENSITY_88;
521   t_info.smallLodLog2 = t_info.largeLodLog2 = LOD;
522   t_info.aspectRatioLog2 = GR_ASPECT_LOG2_1x1;
523   grConstantColorValue (rdp.fog_color);
524   grColorCombine (GR_COMBINE_FUNCTION_LOCAL,
525     GR_COMBINE_FACTOR_NONE,
526     GR_COMBINE_LOCAL_CONSTANT,
527     GR_COMBINE_OTHER_NONE,
528     FXFALSE);
529   grAlphaCombine (GR_COMBINE_FUNCTION_SCALE_OTHER,
530     GR_COMBINE_FACTOR_ONE,
531     GR_COMBINE_LOCAL_NONE,
532     GR_COMBINE_OTHER_TEXTURE,
533     FXFALSE);
534   grAlphaBlendFunction( GR_BLEND_SRC_ALPHA,
535     GR_BLEND_ONE_MINUS_SRC_ALPHA,
536     GR_BLEND_ONE,
537     GR_BLEND_ZERO);
538   grDepthBufferFunction (GR_CMP_ALWAYS);
539   grDepthMask (FXFALSE);
540   grCullMode (GR_CULL_DISABLE);
541   grTexCombine( GR_TMU1,
542     GR_COMBINE_FUNCTION_NONE,
543     GR_COMBINE_FACTOR_NONE,
544     GR_COMBINE_FUNCTION_NONE,
545     GR_COMBINE_FACTOR_NONE,
546     FXFALSE,
547     FXFALSE );
548   grTexCombine( GR_TMU0,
549     GR_COMBINE_FUNCTION_LOCAL,
550     GR_COMBINE_FACTOR_NONE,
551     GR_COMBINE_FUNCTION_LOCAL,
552     GR_COMBINE_FACTOR_NONE,
553     FXFALSE,
554     FXFALSE);
555 //  grAuxBufferExt( GR_BUFFER_AUXBUFFER );
556   grTexSource( rdp.texbufs[0].tmu, rdp.texbufs[0].begin, GR_MIPMAPLEVELMASK_BOTH, &(t_info) );
557   float ul_x = (float)rdp.scissor.ul_x;
558   float ul_y = (float)rdp.scissor.ul_y;
559   float lr_x = (float)rdp.scissor.lr_x;
560   float lr_y = (float)rdp.scissor.lr_y;
561   float ul_u = (float)rdp.scissor.ul_x * scale;
562   float ul_v = (float)rdp.scissor.ul_y * scale;
563   float lr_u = (float)rdp.scissor.lr_x * scale;
564   float lr_v = (float)rdp.scissor.lr_y * scale;
565   // Make the vertices
566   VERTEX v[4] = {
567     { ul_x, ul_y, 1, 1, ul_u, ul_v, ul_u, ul_v, {ul_u, ul_v, ul_u, ul_v} },
568     { lr_x, ul_y, 1, 1, lr_u, ul_v, lr_u, ul_v, {lr_u, ul_v, lr_u, ul_v} },
569     { ul_x, lr_y, 1, 1, ul_u, lr_v, ul_u, lr_v, {ul_u, lr_v, ul_u, lr_v} },
570     { lr_x, lr_y, 1, 1, lr_u, lr_v, lr_u, lr_v, {lr_u, lr_v, lr_u, lr_v} }
571   };
572   grDrawTriangle (&v[0], &v[2], &v[1]);
573   grDrawTriangle (&v[2], &v[3], &v[1]);
574 //  grAuxBufferExt( GR_BUFFER_TEXTUREAUXBUFFER_EXT );
575   rdp.update |= UPDATE_COMBINE | UPDATE_ZBUF_ENABLED | UPDATE_CULL_MODE;
576 }
577
578 void DrawDepthBufferToScreen(FB_TO_SCREEN_INFO & fb_info)
579 {
580   wxUint32 width = fb_info.lr_x - fb_info.ul_x + 1;
581   wxUint32 height = fb_info.lr_y - fb_info.ul_y + 1;
582   if (width > (wxUint32)voodoo.max_tex_size || height > (wxUint32)voodoo.max_tex_size || width > 512)
583   {
584     DrawDepthBufferToScreen256(fb_info);
585     return;
586   }
587   if (fb_hwfbe_enabled && !evoodoo)
588   {
589     DrawHiresDepthBufferToScreen(fb_info);
590     return;
591   }
592   FRDP("DrawDepthBufferToScreen. ul_x=%d, ul_y=%d, lr_x=%d, lr_y=%d, size=%d, addr=%08lx\n", fb_info.ul_x, fb_info.ul_y, fb_info.lr_x, fb_info.lr_y, fb_info.size, fb_info.addr);
593   GrTexInfo t_info;
594   wxUint8 * image = gfx.RDRAM+fb_info.addr;
595   wxUint32 texwidth;
596   float scale;
597   if (width <= 256)
598   {
599     texwidth = 256;
600     scale = 1.0f;
601     t_info.smallLodLog2 = t_info.largeLodLog2 = GR_LOD_LOG2_256;
602   }
603   else
604   {
605     texwidth = 512;
606     scale = 0.5f;
607     t_info.smallLodLog2 = t_info.largeLodLog2 = GR_LOD_LOG2_512;
608   }
609
610   if (height <= (texwidth>>1))
611   {
612     t_info.aspectRatioLog2 = GR_ASPECT_LOG2_2x1;
613   }
614   else
615   {
616     t_info.aspectRatioLog2 = GR_ASPECT_LOG2_1x1;
617   }
618
619   wxUint16 * tex = (wxUint16*)texture_buffer;
620   wxUint16 * dst = tex;
621   wxUint16 * src = (wxUint16*)image;
622   src += fb_info.ul_x + fb_info.ul_y * fb_info.width;
623   for (wxUint32 y=0; y < height; y++)
624   {
625     for (wxUint32 x=0; x < width; x++)
626     {
627       *(dst++) = rdp.pal_8[src[(x+y*fb_info.width)^1]>>8];
628     }
629     dst += texwidth-width;
630   }
631   t_info.format = GR_TEXFMT_ALPHA_INTENSITY_88;
632   t_info.data = tex;
633
634   int tmu = SetupFBtoScreenCombiner(grTexTextureMemRequired(GR_MIPMAPLEVELMASK_BOTH, &t_info), fb_info.opaque);
635   grConstantColorValue (rdp.fog_color);
636   grColorCombine (GR_COMBINE_FUNCTION_SCALE_OTHER,
637     GR_COMBINE_FACTOR_ONE,
638     GR_COMBINE_LOCAL_NONE,
639     GR_COMBINE_OTHER_CONSTANT,
640     FXFALSE);
641   grTexDownloadMipMap (tmu,
642     voodoo.tex_min_addr[tmu]+voodoo.tmem_ptr[tmu],
643     GR_MIPMAPLEVELMASK_BOTH,
644     &t_info);
645   grTexSource (tmu,
646     voodoo.tex_min_addr[tmu]+voodoo.tmem_ptr[tmu],
647     GR_MIPMAPLEVELMASK_BOTH,
648     &t_info);
649   float ul_x = fb_info.ul_x * rdp.scale_x + rdp.offset_x;
650   float ul_y = fb_info.ul_y * rdp.scale_y + rdp.offset_y;
651   float lr_x = fb_info.lr_x * rdp.scale_x + rdp.offset_x;
652   float lr_y = fb_info.lr_y * rdp.scale_y + rdp.offset_y;
653   float lr_u = (width-1)*scale;
654   float lr_v = (height-1)*scale;
655   float zero = scale*0.5f;
656   // Make the vertices
657   VERTEX v[4] = {
658     { ul_x, ul_y, 1, 1, zero, zero, zero, zero, {zero, zero, zero, zero} },
659     { lr_x, ul_y, 1, 1, lr_u, zero, lr_u, zero, {lr_u, zero, lr_u, zero} },
660     { ul_x, lr_y, 1, 1, zero, lr_v, zero, lr_v, {zero, lr_v, zero, lr_v} },
661     { lr_x, lr_y, 1, 1, lr_u, lr_v, lr_u, lr_v, {lr_u, lr_v, lr_u, lr_v} }
662   };
663   grDrawTriangle (&v[0], &v[2], &v[1]);
664   grDrawTriangle (&v[2], &v[3], &v[1]);
665 }