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 | |
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 | } |