ALL: Huge upstream synch + PerRom DelaySI & CountPerOp parameters
[mupen64plus-pandora.git] / source / gles2glide64 / src / Glide64 / TexBuffer.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// Hardware frame buffer emulation
41// Dec 2003 created by Gonetz
42//
43//****************************************************************
44
45#include "Gfx_1.3.h"
46#include "TexBuffer.h"
47#include "CRC.h"
48
49//#include "ticks.h"
50
51static TBUFF_COLOR_IMAGE * AllocateTextureBuffer(COLOR_IMAGE & cimage)
52{
53 TBUFF_COLOR_IMAGE texbuf;
54 texbuf.addr = cimage.addr;
55 texbuf.end_addr = cimage.addr + ((cimage.width*cimage.height)<<cimage.size>>1);
56 texbuf.width = cimage.width;
57 texbuf.height = cimage.height;
58 texbuf.format = cimage.format;
59 texbuf.size = cimage.size;
60 texbuf.scr_width = min(cimage.width * rdp.scale_x, settings.scr_res_x);
61 float height = min(rdp.vi_height,cimage.height);
62 if (cimage.status == ci_copy_self || (cimage.status == ci_copy && cimage.width == rdp.frame_buffers[rdp.main_ci_index].width))
63 height = rdp.vi_height;
64 texbuf.scr_height = height * rdp.scale_y;
65// texbuf.scr_height = texbuf.height * rdp.scale_y;
66
67 wxUint16 max_size = max((wxUint16)texbuf.scr_width, (wxUint16)texbuf.scr_height);
68 if (max_size > voodoo.max_tex_size) //texture size is too large
69 return 0;
70 wxUint32 tex_size;
71 //calculate LOD
72 switch ((max_size-1) >> 6)
73 {
74 case 0:
75 texbuf.info.smallLodLog2 = texbuf.info.largeLodLog2 = GR_LOD_LOG2_64;
76 tex_size = 64;
77 break;
78 case 1:
79 texbuf.info.smallLodLog2 = texbuf.info.largeLodLog2 = GR_LOD_LOG2_128;
80 tex_size = 128;
81 break;
82 case 2:
83 case 3:
84 texbuf.info.smallLodLog2 = texbuf.info.largeLodLog2 = GR_LOD_LOG2_256;
85 tex_size = 256;
86 break;
87 case 4:
88 case 5:
89 case 6:
90 case 7:
91 texbuf.info.smallLodLog2 = texbuf.info.largeLodLog2 = GR_LOD_LOG2_512;
92 tex_size = 512;
93 break;
94 case 8:
95 case 9:
96 case 10:
97 case 11:
98 case 12:
99 case 13:
100 case 14:
101 case 15:
102 texbuf.info.smallLodLog2 = texbuf.info.largeLodLog2 = GR_LOD_LOG2_1024;
103 tex_size = 1024;
104 break;
105 default:
106 texbuf.info.smallLodLog2 = texbuf.info.largeLodLog2 = GR_LOD_LOG2_2048;
107 tex_size = 2048;
108 }
109 //calculate aspect
110 if (texbuf.scr_width >= texbuf.scr_height)
111 {
112 if ((texbuf.scr_width/texbuf.scr_height) >= 2)
113 {
114 texbuf.info.aspectRatioLog2 = GR_ASPECT_LOG2_2x1;
115 texbuf.tex_width = tex_size;
116 texbuf.tex_height = tex_size >> 1;
117 }
118 else
119 {
120 texbuf.info.aspectRatioLog2 = GR_ASPECT_LOG2_1x1;
121 texbuf.tex_width = texbuf.tex_height = tex_size;
122 }
123 }
124 else
125 {
126 if ((texbuf.scr_height/texbuf.scr_width) >= 2)
127 {
128 texbuf.info.aspectRatioLog2 = GR_ASPECT_LOG2_1x2;
129 texbuf.tex_width = tex_size >> 1;
130 texbuf.tex_height = tex_size;
131 }
132 else
133 {
134 texbuf.info.aspectRatioLog2 = GR_ASPECT_LOG2_1x1;
135 texbuf.tex_width = texbuf.tex_height = tex_size;
136 }
137 }
138 if ((cimage.format != 0))// && (cimage.width <= 64))
139 texbuf.info.format = GR_TEXFMT_ALPHA_INTENSITY_88;
140 else
141 texbuf.info.format = GR_TEXFMT_RGB_565;
142
143 texbuf.lr_u = 256.0f * texbuf.scr_width / (float)tex_size;// + 1.0f;
144 texbuf.lr_v = 256.0f * texbuf.scr_height / (float)tex_size;// + 1.0f;
145 texbuf.tile = 0;
146 texbuf.tile_uls = 0;
147 texbuf.tile_ult = 0;
148 texbuf.u_shift = 0;
149 texbuf.v_shift = 0;
150 texbuf.drawn = FALSE;
151 texbuf.u_scale = texbuf.lr_u / (float)(texbuf.width);
152 texbuf.v_scale = texbuf.lr_v / (float)(texbuf.height);
153 texbuf.cache = 0;
154 texbuf.crc = 0;
155 texbuf.t_mem = 0;
156
157 FRDP("\nAllocateTextureBuffer. width: %d, height: %d, scr_width: %f, scr_height: %f, vi_width: %f, vi_height:%f, scale_x: %f, scale_y: %f, lr_u: %f, lr_v: %f, u_scale: %f, v_scale: %f\n", texbuf.width, texbuf.height, texbuf.scr_width, texbuf.scr_height, rdp.vi_width, rdp.vi_height, rdp.scale_x, rdp.scale_y, texbuf.lr_u, texbuf.lr_v, texbuf.u_scale, texbuf.v_scale);
158
159 wxUint32 required = grTexCalcMemRequired(texbuf.info.smallLodLog2, texbuf.info.largeLodLog2,
160 texbuf.info.aspectRatioLog2, texbuf.info.format);
161 //find free space
162 for (int i = 0; i < voodoo.num_tmu; i++)
163 {
164 wxUint32 available = 0;
165 wxUint32 top = 0;
166 if (rdp.texbufs[i].count)
167 {
168 TBUFF_COLOR_IMAGE & t = rdp.texbufs[i].images[rdp.texbufs[i].count - 1];
169 if (rdp.read_whole_frame || rdp.motionblur)
170 {
171 if ((cimage.status == ci_aux) && (rdp.cur_tex_buf == i))
172 {
173 top = t.tex_addr + t.tex_width * (int)(t.scr_height+1) * 2;
174 if (rdp.texbufs[i].end - top < required)
175 return 0;
176 }
177 else
178 top = rdp.texbufs[i].end;
179 }
180 else
181 top = t.tex_addr + t.tex_width * t.tex_height * 2;
182 available = rdp.texbufs[i].end - top;
183 }
184 else
185 {
186 available = rdp.texbufs[i].end - rdp.texbufs[i].begin;
187 top = rdp.texbufs[i].begin;
188 }
189 if (available >= required)
190 {
191 rdp.texbufs[i].count++;
192 rdp.texbufs[i].clear_allowed = FALSE;
193 texbuf.tex_addr = top;
194 rdp.cur_tex_buf = i;
195 texbuf.tmu = rdp.texbufs[i].tmu;
196 rdp.texbufs[i].images[rdp.texbufs[i].count - 1] = texbuf;
197 return &(rdp.texbufs[i].images[rdp.texbufs[i].count - 1]);
198 }
199 }
200 //not found. keep recently accessed bank, clear second one
201 if (!rdp.texbufs[rdp.cur_tex_buf^1].clear_allowed) //can't clear => can't allocate
202 return 0;
203 rdp.cur_tex_buf ^= 1;
204 rdp.texbufs[rdp.cur_tex_buf].count = 1;
205 rdp.texbufs[rdp.cur_tex_buf].clear_allowed = FALSE;
206 texbuf.tmu = rdp.texbufs[rdp.cur_tex_buf].tmu;
207 texbuf.tex_addr = rdp.texbufs[rdp.cur_tex_buf].begin;
208 rdp.texbufs[rdp.cur_tex_buf].images[0] = texbuf;
209 return &(rdp.texbufs[rdp.cur_tex_buf].images[0]);
210}
211
212int OpenTextureBuffer(COLOR_IMAGE & cimage)
213{
214//printf("OpenTextureBuffer. cur_tex_buf: %d, addr: %08lx, width: %d, height: %d\n", rdp.cur_tex_buf, cimage.addr, cimage.width, cimage.height);
215//unsigned int ticks = ticksGetTicks();
216 FRDP("OpenTextureBuffer. cur_tex_buf: %d, addr: %08lx, width: %d, height: %d", rdp.cur_tex_buf, cimage.addr, cimage.width, cimage.height);
217 if (!fullscreen) return FALSE;
218
219 int found = FALSE, search = TRUE;
220 TBUFF_COLOR_IMAGE *texbuf = 0;
221 wxUint32 addr = cimage.addr;
222 if ((settings.hacks&hack_Banjo2) && cimage.status == ci_copy_self)
223 addr = rdp.frame_buffers[rdp.copy_ci_index].addr;
224 wxUint32 end_addr = addr + ((cimage.width*cimage.height)<<cimage.size>>1);
225 if (rdp.motionblur)
226 {
227// if (cimage.format != 0)
228// return FALSE;
229 search = FALSE;
230 }
231 if (rdp.read_whole_frame)
232 {
233 if (settings.hacks&hack_PMario) //motion blur effects in Paper Mario
234 {
235 rdp.cur_tex_buf = rdp.acc_tex_buf;
236 FRDP("\nread_whole_frame. last allocated bank: %d\n", rdp.acc_tex_buf);
237 }
238// else
239 {
240 if (!rdp.texbufs[0].clear_allowed || !rdp.texbufs[1].clear_allowed)
241 {
242 if (cimage.status == ci_main)
243 {
244 texbuf = &(rdp.texbufs[rdp.cur_tex_buf].images[0]);
245 found = TRUE;
246 }
247 else
248 {
249 for (int t = 0; (t < rdp.texbufs[rdp.cur_tex_buf].count) && !found; t++)
250 {
251 texbuf = &(rdp.texbufs[rdp.cur_tex_buf].images[t]);
252 if (addr == texbuf->addr && cimage.width == texbuf->width)
253 {
254 texbuf->drawn = FALSE;
255 found = TRUE;
256 }
257 }
258 }
259 }
260 search = FALSE;
261 }
262 }
263 if (search)
264 {
265//printf("search ! (%i) : ", voodoo.num_tmu);
266 for (int i = 0; (i < voodoo.num_tmu) && !found; i++)
267 {
268//printf("[%i] ", rdp.texbufs[i].count);
269 for (int j = 0; (j < rdp.texbufs[i].count) && !found; j++)
270 {
271 texbuf = &(rdp.texbufs[i].images[j]);
272 if (addr == texbuf->addr && cimage.width == texbuf->width)
273 {
274 //texbuf->height = cimage.height;
275 //texbuf->end_addr = end_addr;
276 texbuf->drawn = FALSE;
277 texbuf->format = (wxUint16)cimage.format;
278 if ((cimage.format != 0))
279 texbuf->info.format = GR_TEXFMT_ALPHA_INTENSITY_88;
280 else
281 texbuf->info.format = GR_TEXFMT_RGB_565;
282 texbuf->crc = 0;
283 texbuf->t_mem = 0;
284 texbuf->tile = 0;
285 found = TRUE;
286 rdp.cur_tex_buf = i;
287 rdp.texbufs[i].clear_allowed = FALSE;
288 }
289 else //check intersection
290 {
291 if (!((end_addr <= texbuf->addr) || (addr >= texbuf->end_addr))) //intersected, remove
292 {
293 grRenderBuffer( GR_BUFFER_TEXTUREBUFFER_EXT );
294 grTextureBufferExt( texbuf->tmu, texbuf->tex_addr, texbuf->info.smallLodLog2, texbuf->info.largeLodLog2,
295 texbuf->info.aspectRatioLog2, texbuf->info.format, GR_MIPMAPLEVELMASK_BOTH );
296 grDepthMask (FXFALSE);
297 grBufferClear (0, 0, 0xFFFF);
298 grDepthMask (FXTRUE);
299 grRenderBuffer( GR_BUFFER_BACKBUFFER );
300 rdp.texbufs[i].count--;
301 if (j < rdp.texbufs[i].count)
302 memcpy(&(rdp.texbufs[i].images[j]), &(rdp.texbufs[i].images[j+1]), sizeof(TBUFF_COLOR_IMAGE)*(rdp.texbufs[i].count-j));
303 }
304 }
305 }
306 }
307 }
308 else
309 {
310 LRDP(" not searched");
311 }
312
313 if (!found)
314 {
315 LRDP(" not found");
316 texbuf = AllocateTextureBuffer(cimage);
317//printf(" not found\n");
318 }
319 else
320 {
321 LRDP(" found");
322//printf(" found\n");
323 }
324
325 if (!texbuf)
326 {
327 LRDP(" KO\n");
328 return FALSE;
329 }
330
331//unsigned int tticks=ticksGetTicks();
332 rdp.acc_tex_buf = rdp.cur_tex_buf;
333 rdp.cur_image = texbuf;
334 grRenderBuffer( GR_BUFFER_TEXTUREBUFFER_EXT );
335 grTextureBufferExt( rdp.cur_image->tmu, rdp.cur_image->tex_addr, rdp.cur_image->info.smallLodLog2, rdp.cur_image->info.largeLodLog2,
336 rdp.cur_image->info.aspectRatioLog2, rdp.cur_image->info.format, GR_MIPMAPLEVELMASK_BOTH );
337 ///*
338//printf("mesured %u ms\n", ticksGetTicks()-tticks);
339 if (rdp.cur_image->clear && (settings.frame_buffer&fb_hwfbe_buf_clear) && cimage.changed)
340 {
341 rdp.cur_image->clear = FALSE;
342 grDepthMask (FXFALSE);
343 grBufferClear (0, 0, 0xFFFF);
344 grDepthMask (FXTRUE);
345 }
346
347 //*/
348 // memset(gfx.RDRAM+cimage.addr, 0, cimage.width*cimage.height*cimage.size);
349 FRDP(" texaddr: %08lx, tex_width: %d, tex_height: %d, cur_tex_buf: %d, texformat: %d, motionblur: %d\n", rdp.cur_image->tex_addr, rdp.cur_image->tex_width, rdp.cur_image->tex_height, rdp.cur_tex_buf, rdp.cur_image->info.format, rdp.motionblur);
350//printf(" time = %u ms, texaddr: %08x, tex_width: %d, tex_height: %d, cur_tex_buf: %d, texformat: %d, motionblur: %d\n", ticksGetTicks()-ticks, rdp.cur_image->tex_addr, rdp.cur_image->tex_width, rdp.cur_image->tex_height, rdp.cur_tex_buf, rdp.cur_image->info.format, rdp.motionblur);
351 if (!rdp.offset_x_bak)
352 {
353 rdp.offset_x_bak = rdp.offset_x;
354 rdp.offset_x = 0;
355 }
356 if (!rdp.offset_y_bak)
357 {
358 rdp.offset_y_bak = rdp.offset_y;
359 rdp.offset_y = 0;
360 }
361 rdp.update |= UPDATE_VIEWPORT | UPDATE_SCISSOR;
362
363 return TRUE;
364}
365
366static GrTextureFormat_t TexBufSetupCombiner(int force_rgb = FALSE)
367{
368 grColorCombine( GR_COMBINE_FUNCTION_SCALE_OTHER,
369 GR_COMBINE_FACTOR_ONE,
370 GR_COMBINE_LOCAL_NONE,
371 GR_COMBINE_OTHER_TEXTURE,
372// GR_COMBINE_OTHER_CONSTANT,
373 FXFALSE);
374 grAlphaCombine (GR_COMBINE_FUNCTION_SCALE_OTHER,
375 GR_COMBINE_FACTOR_ONE,
376 GR_COMBINE_LOCAL_NONE,
377 GR_COMBINE_OTHER_TEXTURE,
378 FXFALSE);
379// grConstantColorValue (0xFFFFFFFF);
380 grAlphaBlendFunction (GR_BLEND_ONE, // use alpha compare, but not T0 alpha
381 GR_BLEND_ZERO,
382 GR_BLEND_ONE,
383 GR_BLEND_ZERO);
384 grClipWindow (0, 0, settings.scr_res_x, settings.scr_res_y);
385 grDepthBufferFunction (GR_CMP_ALWAYS);
386 grDepthMask (FXFALSE);
387 grCullMode (GR_CULL_DISABLE);
388 grFogMode (GR_FOG_DISABLE);
389 GrTextureFormat_t buf_format = (rdp.tbuff_tex) ? rdp.tbuff_tex->info.format : GR_TEXFMT_RGB_565;
390 GrCombineFunction_t color_source = GR_COMBINE_FUNCTION_LOCAL;
391 if (!force_rgb && rdp.black_ci_index > 0 && rdp.black_ci_index <= rdp.copy_ci_index)
392 {
393 color_source = GR_COMBINE_FUNCTION_LOCAL_ALPHA;
394 buf_format = GR_TEXFMT_ALPHA_INTENSITY_88;
395 }
396 if (rdp.tbuff_tex->tmu == GR_TMU0)
397 {
398 grTexCombine( GR_TMU1,
399 GR_COMBINE_FUNCTION_NONE,
400 GR_COMBINE_FACTOR_NONE,
401 GR_COMBINE_FUNCTION_NONE,
402 GR_COMBINE_FACTOR_NONE,
403 FXFALSE,
404 FXFALSE );
405 grTexCombine( GR_TMU0,
406 color_source,
407 GR_COMBINE_FACTOR_NONE,
408 GR_COMBINE_FUNCTION_ZERO,
409 GR_COMBINE_FACTOR_NONE,
410 FXFALSE,
411 FXTRUE );
412 }
413 else
414 {
415 grTexCombine( GR_TMU1,
416 color_source,
417 GR_COMBINE_FACTOR_NONE,
418 GR_COMBINE_FUNCTION_ZERO,
419 GR_COMBINE_FACTOR_NONE,
420 FXFALSE,
421 FXTRUE );
422 grTexCombine( GR_TMU0,
423 GR_COMBINE_FUNCTION_SCALE_OTHER,
424 GR_COMBINE_FACTOR_ONE,
425 GR_COMBINE_FUNCTION_SCALE_OTHER,
426 GR_COMBINE_FACTOR_ONE,
427 FXFALSE,
428 FXFALSE );
429 }
430 return buf_format;
431}
432
433int CloseTextureBuffer(int draw)
434{
435 if (!fullscreen || !rdp.cur_image)
436 {
437 LRDP("CloseTextureBuffer KO\n");
438 return FALSE;
439 }
440 grRenderBuffer( GR_BUFFER_BACKBUFFER );
441 rdp.offset_x = rdp.offset_x_bak;
442 rdp.offset_y = rdp.offset_y_bak;
443 rdp.offset_x_bak = rdp.offset_y_bak = 0;
444 rdp.update |= UPDATE_VIEWPORT | UPDATE_SCISSOR;
445 if (!draw)
446 {
447 LRDP("CloseTextureBuffer no draw, OK\n");
448 rdp.cur_image = 0;
449 return TRUE;
450 }
451 rdp.tbuff_tex = rdp.cur_image;
452 rdp.cur_image = 0;
453 rdp.tbuff_tex->info.format = TexBufSetupCombiner();
454 float zero = 0.0f;
455 float ul_x = rdp.offset_x;
456 float ul_y = rdp.offset_y;
457 float lr_x = rdp.tbuff_tex->scr_width + rdp.offset_x;
458 float lr_y = rdp.tbuff_tex->scr_height + rdp.offset_y;
459 float lr_u = rdp.tbuff_tex->lr_u;
460 float lr_v = rdp.tbuff_tex->lr_v;
461 FRDP("lr_x: %f, lr_y: %f, lr_u: %f, lr_v: %f\n", lr_x, lr_y, lr_u, lr_v);
462
463
464 // Make the vertices
465 VERTEX v[4] = {
466 { ul_x, ul_y, 1, 1, zero, zero, zero, zero, {zero, zero, zero, zero} },
467 { lr_x, ul_y, 1, 1, lr_u, zero, lr_u, zero, {lr_u, zero, lr_u, zero} },
468 { ul_x, lr_y, 1, 1, zero, lr_v, zero, lr_v, {zero, lr_v, zero, lr_v} },
469 { lr_x, lr_y, 1, 1, lr_u, lr_v, lr_u, lr_v, {lr_u, lr_v, lr_u, lr_v} }
470 };
471
472 grTexSource( rdp.tbuff_tex->tmu, rdp.tbuff_tex->tex_addr, GR_MIPMAPLEVELMASK_BOTH, &(rdp.tbuff_tex->info) );
473 grClipWindow (0, 0, settings.res_x, settings.res_y);
474 grDrawTriangle (&v[0], &v[2], &v[1]);
475 grDrawTriangle (&v[2], &v[3], &v[1]);
476 rdp.update |= UPDATE_ZBUF_ENABLED | UPDATE_COMBINE | UPDATE_TEXTURE | UPDATE_ALPHA_COMPARE;
477 if (settings.fog && (rdp.flags & FOG_ENABLED))
478 {
479 grFogMode (GR_FOG_WITH_TABLE_ON_FOGCOORD_EXT);
480 }
481 LRDP("CloseTextureBuffer draw, OK\n");
482 rdp.tbuff_tex = 0;
483 return TRUE;
484}
485
486int CopyTextureBuffer(COLOR_IMAGE & fb_from, COLOR_IMAGE & fb_to)
487{
488 if (!fullscreen)
489 return FALSE;
490 FRDP("CopyTextureBuffer from %08x to %08x\n", fb_from.addr, fb_to.addr);
491 if (rdp.cur_image)
492 {
493 rdp.cur_image->crc = 0;
494 if (rdp.cur_image->addr == fb_to.addr)
495 return CloseTextureBuffer(TRUE);
496 rdp.tbuff_tex = rdp.cur_image;
497 }
498 else if (!FindTextureBuffer(fb_from.addr, (wxUint16)fb_from.width))
499 {
500 LRDP("Can't find 'from' buffer.\n");
501 return FALSE;
502 }
503 if (!OpenTextureBuffer(fb_to))
504 {
505 LRDP("Can't open new buffer.\n");
506 return CloseTextureBuffer(TRUE);
507 }
508 rdp.tbuff_tex->crc = 0;
509 GrTextureFormat_t buf_format = rdp.tbuff_tex->info.format;
510 rdp.tbuff_tex->info.format = GR_TEXFMT_RGB_565;
511 TexBufSetupCombiner(TRUE);
512 float ul_x = 0.0f;
513 float ul_y = 0.0f;
514 float lr_x = rdp.tbuff_tex->scr_width;
515 float lr_y = rdp.tbuff_tex->scr_height;
516 float zero = 0.0f;
517 float lr_u = rdp.tbuff_tex->lr_u;
518 float lr_v = rdp.tbuff_tex->lr_v;
519 FRDP("lr_x: %f, lr_y: %f\n", lr_x, lr_y);
520
521
522 // Make the vertices
523 VERTEX v[4] = {
524 { ul_x, ul_y, 1, 1, zero, zero, zero, zero, {zero, zero, zero, zero} },
525 { lr_x, ul_y, 1, 1, lr_u, zero, lr_u, zero, {lr_u, zero, lr_u, zero} },
526 { ul_x, lr_y, 1, 1, zero, lr_v, zero, lr_v, {zero, lr_v, zero, lr_v} },
527 { lr_x, lr_y, 1, 1, lr_u, lr_v, lr_u, lr_v, {lr_u, lr_v, lr_u, lr_v} }
528 };
529
530 grTexSource( rdp.tbuff_tex->tmu, rdp.tbuff_tex->tex_addr, GR_MIPMAPLEVELMASK_BOTH, &(rdp.tbuff_tex->info) );
531 grDrawTriangle (&v[0], &v[2], &v[1]);
532 grDrawTriangle (&v[2], &v[3], &v[1]);
533 grRenderBuffer( GR_BUFFER_BACKBUFFER );
534 rdp.offset_x = rdp.offset_x_bak;
535 rdp.offset_y = rdp.offset_y_bak;
536 rdp.offset_x_bak = rdp.offset_y_bak = 0;
537 AddOffset(v, 4);
538 grClipWindow (0, 0, settings.res_x, settings.res_y);
539 grDrawTriangle (&v[0], &v[2], &v[1]);
540 grDrawTriangle (&v[2], &v[3], &v[1]);
541 rdp.tbuff_tex->info.format = buf_format;
542
543 rdp.update |= UPDATE_ZBUF_ENABLED | UPDATE_COMBINE | UPDATE_TEXTURE | UPDATE_ALPHA_COMPARE;
544 rdp.update |= UPDATE_VIEWPORT | UPDATE_SCISSOR;
545 if (settings.fog && (rdp.flags & FOG_ENABLED))
546 grFogMode (GR_FOG_WITH_TABLE_ON_FOGCOORD_EXT);
547 LRDP("CopyTextureBuffer draw, OK\n");
548 rdp.tbuff_tex = 0;
549 rdp.cur_image = 0;
550 return TRUE;
551}
552
553int CopyDepthBuffer()
554{
555 if (!fullscreen)
556 return FALSE;
557 LRDP("CopyDepthBuffer. ");
558 float bound = 1024.0f;
559 GrLOD_t LOD = GR_LOD_LOG2_1024;
560 if (settings.scr_res_x > 1024)
561 {
562 bound = 2048.0f;
563 LOD = GR_LOD_LOG2_2048;
564 }
565 rdp.tbuff_tex = &(rdp.texbufs[0].images[0]);
566 rdp.tbuff_tex->tmu = rdp.texbufs[0].tmu;
567 rdp.tbuff_tex->info.format = GR_TEXFMT_RGB_565;
568 rdp.tbuff_tex->info.smallLodLog2 = rdp.tbuff_tex->info.largeLodLog2 = LOD;
569 rdp.tbuff_tex->info.aspectRatioLog2 = GR_ASPECT_LOG2_1x1;
570 TexBufSetupCombiner(TRUE);
571 float ul_x = 0.0f;
572 float ul_y = 0.0f;
573 float lr_x = bound;
574 float lr_y = bound;
575 float zero = 0.0f;
576 float lr_u = 255.5f;
577 float lr_v = 255.5f;
578 FRDP("lr_x: %f, lr_y: %f\n", lr_x, lr_y);
579
580
581 // Make the vertices
582 VERTEX v[4] = {
583 { ul_x, ul_y, 1, 1, zero, zero, zero, zero, {zero, zero, zero, zero} },
584 { lr_x, ul_y, 1, 1, lr_u, zero, lr_u, zero, {lr_u, zero, lr_u, zero} },
585 { ul_x, lr_y, 1, 1, zero, lr_v, zero, lr_v, {zero, lr_v, zero, lr_v} },
586 { lr_x, lr_y, 1, 1, lr_u, lr_v, lr_u, lr_v, {lr_u, lr_v, lr_u, lr_v} }
587 };
588
589 grAuxBufferExt( GR_BUFFER_AUXBUFFER );
590 grTexSource( rdp.texbufs[0].tmu, rdp.texbufs[0].begin, GR_MIPMAPLEVELMASK_BOTH, &(rdp.tbuff_tex->info) );
591 grRenderBuffer( GR_BUFFER_TEXTUREBUFFER_EXT );
592 grTextureBufferExt( rdp.texbufs[1].tmu, rdp.texbufs[1].begin, LOD, LOD,
593 GR_ASPECT_LOG2_1x1, GR_TEXFMT_RGB_565, GR_MIPMAPLEVELMASK_BOTH );
594 grDrawTriangle (&v[0], &v[2], &v[1]);
595 grDrawTriangle (&v[2], &v[3], &v[1]);
596 grRenderBuffer( GR_BUFFER_BACKBUFFER );
597 grTextureAuxBufferExt( rdp.texbufs[1].tmu, rdp.texbufs[1].begin, LOD, LOD,
598 GR_ASPECT_LOG2_1x1, GR_TEXFMT_RGB_565, GR_MIPMAPLEVELMASK_BOTH );
599 grAuxBufferExt( GR_BUFFER_TEXTUREAUXBUFFER_EXT );
600
601 rdp.update |= UPDATE_ZBUF_ENABLED | UPDATE_COMBINE | UPDATE_TEXTURE | UPDATE_ALPHA_COMPARE;
602 if (settings.fog && (rdp.flags & FOG_ENABLED))
603 grFogMode (GR_FOG_WITH_TABLE_ON_FOGCOORD_EXT);
604 LRDP("CopyDepthBuffer draw, OK\n");
605 rdp.tbuff_tex = 0;
606 return TRUE;
607}
608
609int SwapTextureBuffer()
610{
611 if (!fullscreen || !rdp.tbuff_tex)
612 return FALSE;
613 LRDP("SwapTextureBuffer.");
614 COLOR_IMAGE ci;
615 ci.addr = rdp.tbuff_tex->addr;
616 ci.format = rdp.tbuff_tex->format;
617 ci.width = rdp.tbuff_tex->width;
618 ci.height = rdp.tbuff_tex->height;
619 ci.size = 2;
620 ci.status = ci_main;
621 ci.changed = FALSE;
622 TBUFF_COLOR_IMAGE * texbuf = AllocateTextureBuffer(ci);
623 if (!texbuf)
624 {
625 LRDP("Failed!\n");
626 return FALSE;
627 }
628 TexBufSetupCombiner();
629
630 float ul_x = 0.0f;
631 float ul_y = 0.0f;
632 float lr_x = rdp.tbuff_tex->scr_width;
633 float lr_y = rdp.tbuff_tex->scr_height;
634 float zero = 0.0f;
635 float lr_u = rdp.tbuff_tex->lr_u;
636 float lr_v = rdp.tbuff_tex->lr_v;
637
638 // Make the vertices
639 VERTEX v[4] = {
640 { ul_x, ul_y, 1, 1, zero, zero, zero, zero, {zero, zero, zero, zero} },
641 { lr_x, ul_y, 1, 1, lr_u, zero, lr_u, zero, {lr_u, zero, lr_u, zero} },
642 { ul_x, lr_y, 1, 1, zero, lr_v, zero, lr_v, {zero, lr_v, zero, lr_v} },
643 { lr_x, lr_y, 1, 1, lr_u, lr_v, lr_u, lr_v, {lr_u, lr_v, lr_u, lr_v} }
644 };
645
646 grTexSource( rdp.tbuff_tex->tmu, rdp.tbuff_tex->tex_addr, GR_MIPMAPLEVELMASK_BOTH, &(rdp.tbuff_tex->info) );
647 texbuf->tile_uls = rdp.tbuff_tex->tile_uls;
648 texbuf->tile_ult = rdp.tbuff_tex->tile_ult;
649 texbuf->v_shift = rdp.tbuff_tex->v_shift;
650 grRenderBuffer( GR_BUFFER_TEXTUREBUFFER_EXT );
651 grTextureBufferExt( texbuf->tmu, texbuf->tex_addr, texbuf->info.smallLodLog2, texbuf->info.largeLodLog2,
652 texbuf->info.aspectRatioLog2, texbuf->info.format, GR_MIPMAPLEVELMASK_BOTH );
653 grDrawTriangle (&v[0], &v[2], &v[1]);
654 grDrawTriangle (&v[2], &v[3], &v[1]);
655 rdp.texbufs[rdp.tbuff_tex->tmu].clear_allowed = TRUE;
656 rdp.texbufs[rdp.tbuff_tex->tmu].count = 0;
657 texbuf->tile_uls = rdp.tbuff_tex->tile_uls;
658 texbuf->tile_ult = rdp.tbuff_tex->tile_ult;
659 texbuf->u_shift = rdp.tbuff_tex->u_shift;
660 texbuf->v_shift = rdp.tbuff_tex->v_shift;
661 rdp.tbuff_tex = texbuf;
662 if (rdp.cur_image)
663 {
664 grTextureBufferExt( rdp.cur_image->tmu, rdp.cur_image->tex_addr, rdp.cur_image->info.smallLodLog2, rdp.cur_image->info.largeLodLog2,
665 rdp.cur_image->info.aspectRatioLog2, rdp.cur_image->info.format, GR_MIPMAPLEVELMASK_BOTH );
666 }
667 else
668 {
669 grRenderBuffer( GR_BUFFER_BACKBUFFER );
670 rdp.offset_x = rdp.offset_x_bak;
671 rdp.offset_y = rdp.offset_y_bak;
672 rdp.offset_x_bak = rdp.offset_y_bak = 0;
673 rdp.update |= UPDATE_VIEWPORT | UPDATE_SCISSOR;
674 }
675 rdp.update |= UPDATE_ZBUF_ENABLED | UPDATE_COMBINE | UPDATE_TEXTURE | UPDATE_ALPHA_COMPARE;
676 if (settings.fog && (rdp.flags & FOG_ENABLED))
677 {
678 grFogMode (GR_FOG_WITH_TABLE_ON_FOGCOORD_EXT);
679 }
680 LRDP("SwapTextureBuffer draw, OK\n");
681 return TRUE;
682}
683
684static wxUint32 CalcCRC(TBUFF_COLOR_IMAGE * pTCI)
685{
686 wxUint32 result = 0;
687 if ((settings.frame_buffer&fb_ref) > 0)
688 pTCI->crc = 0; //Since fb content changes each frame, crc check is meaningless.
689 else if (settings.fb_crc_mode == SETTINGS::fbcrcFast)
690 result = *((wxUint32*)(gfx.RDRAM + pTCI->addr + (pTCI->end_addr-pTCI->addr)/2));
691 else if (settings.fb_crc_mode == SETTINGS::fbcrcSafe)
692 {
693 wxUint8 * pSrc = gfx.RDRAM + pTCI->addr;
694 const wxUint32 nSize = pTCI->end_addr-pTCI->addr;
695 result = CRC32(0xFFFFFFFF, pSrc, 32);
696 result = CRC32(result, pSrc + (nSize>>1), 32);
697 result = CRC32(result, pSrc + nSize - 32, 32);
698 }
699 return result;
700}
701
702int FindTextureBuffer(wxUint32 addr, wxUint16 width)
703{
704 if (rdp.skip_drawing)
705 return FALSE;
706 FRDP("FindTextureBuffer. addr: %08lx, width: %d, scale_x: %f\n", addr, width, rdp.scale_x);
707 int found = FALSE;
708 wxUint32 shift = 0;
709 for (int i = 0; i < voodoo.num_tmu && !found; i++)
710 {
711 wxUint8 index = rdp.cur_tex_buf^i;
712 for (int j = 0; j < rdp.texbufs[index].count && !found; j++)
713 {
714 rdp.tbuff_tex = &(rdp.texbufs[index].images[j]);
715 if(addr >= rdp.tbuff_tex->addr && addr < rdp.tbuff_tex->end_addr)// && rdp.timg.format == 0)
716 {
717 bool bCorrect;
718 if (rdp.tbuff_tex->crc == 0)
719 {
720 rdp.tbuff_tex->crc = CalcCRC(rdp.tbuff_tex);
721 bCorrect = width == 1 || rdp.tbuff_tex->width == width || (rdp.tbuff_tex->width > 320 && rdp.tbuff_tex->width == width*2);
722 }
723 else
724 bCorrect = rdp.tbuff_tex->crc == CalcCRC(rdp.tbuff_tex);
725 if (bCorrect)
726 {
727 shift = addr - rdp.tbuff_tex->addr;
728 // if (!rdp.motionblur)
729 if (!rdp.cur_image)
730 rdp.cur_tex_buf = index;
731 found = TRUE;
732 // FRDP("FindTextureBuffer, found in TMU%d buffer: %d\n", rdp.tbuff_tex->tmu, j);
733 }
734 else //new texture is loaded into this place, texture buffer is not valid anymore
735 {
736 rdp.texbufs[index].count--;
737 if (j < rdp.texbufs[index].count)
738 memcpy(&(rdp.texbufs[index].images[j]), &(rdp.texbufs[index].images[j+1]), sizeof(TBUFF_COLOR_IMAGE)*(rdp.texbufs[index].count-j));
739 }
740 }
741 }
742 }
743 if (found)
744 {
745 rdp.tbuff_tex->tile_uls = 0;
746 rdp.tbuff_tex->tile_ult = 0;
747 if (shift > 0)
748 {
749 shift >>= 1;
750 rdp.tbuff_tex->v_shift = shift / rdp.tbuff_tex->width;
751 rdp.tbuff_tex->u_shift = shift % rdp.tbuff_tex->width;
752 }
753 else
754 {
755 rdp.tbuff_tex->v_shift = 0;
756 rdp.tbuff_tex->u_shift = 0;
757 }
758 FRDP("FindTextureBuffer, found, u_shift: %d, v_shift: %d, format: %s\n", rdp.tbuff_tex->u_shift, rdp.tbuff_tex->v_shift, str_format[rdp.tbuff_tex->format]);
759 //FRDP("Buffer, addr=%08lx, end_addr=%08lx, width: %d, height: %d\n", rdp.tbuff_tex->addr, rdp.tbuff_tex->end_addr, rdp.tbuff_tex->width, rdp.tbuff_tex->height);
760 return TRUE;
761 }
762 rdp.tbuff_tex = 0;
763 LRDP("FindTextureBuffer, not found\n");
764 return FALSE;
765}