Glide Plugin GLES2 port from mupen64plus-ae, but with special FrameSkip code
[mupen64plus-pandora.git] / source / gles2glide64 / src / Glide64 / FBtoScreen.cpp
CommitLineData
98e75f2d 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
50static 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
130static 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
150static 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
195static 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
311bool 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
437static 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
509static 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
578void 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}