2
Copyright (C) 2005 Rice1964
4
This program is free software; you can redistribute it and/or
5
modify it under the terms of the GNU General Public License
6
as published by the Free Software Foundation; either version 2
7
of the License, or (at your option) any later version.
9
This program is distributed in the hope that it will be useful,
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
GNU General Public License for more details.
14
You should have received a copy of the GNU General Public License
15
along with this program; if not, write to the Free Software
16
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20
// ===========================================================================
24
#include "ConvertImage.h"
25
#include "DeviceBuilder.h"
26
#include "FrameBuffer.h"
27
#include "UcodeDefs.h"
28
#include "RSP_Parser.h"
31
extern TMEMLoadMapInfo g_tmemLoadAddrMap[0x200]; // Totally 4KB TMEM;
33
// 0 keeps the most recent CI info
34
// 1 keeps the frame buffer CI info which is being displayed now
35
// 2 keeps the older frame buffer CI info. This can be used if we are using triple buffer
36
/* Overview of framebuffer implementation
37
1) Check if backbuffer has changed, via different detection techniques
38
2) If changed, we copy the GFX card's backbuffer to main RAM
39
3) This is slow due to the reading process, not the writing
44
RecentCIInfo g_RecentCIInfo[5];
45
RecentCIInfo *g_uRecentCIInfoPtrs[5] =
54
int numOfRecentCIInfos = 5;
56
RecentViOriginInfo g_RecentVIOriginInfo[5];
57
uint32 dwBackBufferSavedAtFrame=0;
59
RenderTextureInfo gRenderTextureInfos[20];
60
int numOfTxtBufInfos = sizeof(gRenderTextureInfos)/sizeof(RenderTextureInfo);
61
RenderTextureInfo *g_pRenderTextureInfo = NULL;
63
FrameBufferManager* g_pFrameBufferManager = NULL;
65
bool LastCIIsNewCI=false;
67
FrameBufferManager::FrameBufferManager() :
68
m_isRenderingToTexture(false),
69
m_curRenderTextureIndex(-1),
70
m_lastTextureBufferIndex(-1)
74
FrameBufferManager::~FrameBufferManager()
78
void FrameBufferManager::CloseUp()
80
for( int i=0; i<numOfTxtBufInfos; i++ )
82
SAFE_DELETE(gRenderTextureInfos[i].pRenderTexture);
86
void FrameBufferManager::Initialize()
88
m_isRenderingToTexture = false;
89
m_lastTextureBufferIndex = -1;
90
m_curRenderTextureIndex = -1;
92
status.bCIBufferIsRendered = false;
93
status.bN64IsDrawingTextureBuffer = false;
94
status.bHandleN64RenderTexture = false;
95
status.bN64FrameBufferIsUsed = false;
97
memset(&gRenderTextureInfos[0], 0, sizeof(RenderTextureInfo)*numOfTxtBufInfos);
99
// ===========================================================================
101
uint16 ConvertRGBATo555(uint8 r, uint8 g, uint8 b, uint8 a)
103
uint8 ar = a>=0x20?1:0;
104
return ((r>>3)<<RGBA5551_RedShift) | ((g>>3)<<RGBA5551_GreenShift) | ((b>>3)<<RGBA5551_BlueShift) | ar;//(a>>7);
107
uint16 ConvertRGBATo555(uint32 color32)
109
return (uint16)((((color32>>19)&0x1F)<<RGBA5551_RedShift) | (((color32>>11)&0x1F)<<RGBA5551_GreenShift) | (((color32>>3)&0x1F)<<RGBA5551_BlueShift) | ((color32>>31)));;
112
void FrameBufferManager::UpdateRecentCIAddr(SetImgInfo &ciinfo)
114
if( ciinfo.dwAddr == g_uRecentCIInfoPtrs[0]->dwAddr )
120
for( i=1; i<numOfRecentCIInfos; i++ )
122
if( ciinfo.dwAddr == g_uRecentCIInfoPtrs[i]->dwAddr )
124
temp = g_uRecentCIInfoPtrs[i];
126
for( int j=i; j>0; j-- )
128
g_uRecentCIInfoPtrs[j] = g_uRecentCIInfoPtrs[j-1];
134
if( i >= numOfRecentCIInfos )
136
temp = g_uRecentCIInfoPtrs[4];
137
g_uRecentCIInfoPtrs[4] = g_uRecentCIInfoPtrs[3];
138
g_uRecentCIInfoPtrs[3] = g_uRecentCIInfoPtrs[2];
139
g_uRecentCIInfoPtrs[2] = g_uRecentCIInfoPtrs[1];
140
g_uRecentCIInfoPtrs[1] = g_uRecentCIInfoPtrs[0];
141
temp->dwCopiedAtFrame = 0;
142
temp->bCopied = false;
145
g_uRecentCIInfoPtrs[0] = temp;
147
// Fix me here for Mario Tennis
148
temp->dwLastWidth = windowSetting.uViWidth;
149
temp->dwLastHeight = windowSetting.uViHeight;
151
temp->dwFormat = ciinfo.dwFormat;
152
temp->dwAddr = ciinfo.dwAddr;
153
temp->dwSize = ciinfo.dwSize;
154
temp->dwWidth = ciinfo.dwWidth;
155
temp->dwHeight = gRDP.scissor.bottom;
156
temp->dwMemSize = (temp->dwWidth*temp->dwHeight/2)<<temp->dwSize;
157
temp->bCopied = false;
158
temp->lastUsedFrame = status.gDlistCount;
159
temp->lastSetAtUcode = status.gUcodeCount;
163
/************************************************************************/
164
/* Mark the ciinfo entry that the ciinfo is used by VI origin register */
165
/* in another word, this is a real frame buffer, not a fake frame buffer*/
166
/* Fake frame buffers are never really used by VI origin */
167
/************************************************************************/
168
void FrameBufferManager::SetAddrBeDisplayed(uint32 addr)
170
uint32 viwidth = *g_GraphicsInfo.VI_WIDTH_REG;
171
addr &= (g_dwRamSize-1);
173
for( i=0; i<numOfRecentCIInfos; i++ )
175
if( g_uRecentCIInfoPtrs[i]->dwAddr+2*viwidth == addr )
177
g_uRecentCIInfoPtrs[i]->bUsedByVIAtFrame = status.gDlistCount;
179
else if( addr >= g_uRecentCIInfoPtrs[i]->dwAddr && addr < g_uRecentCIInfoPtrs[i]->dwAddr+0x1000 )
181
g_uRecentCIInfoPtrs[i]->bUsedByVIAtFrame = status.gDlistCount;
185
for( i=0; i<numOfRecentCIInfos; i++ )
187
if( g_RecentVIOriginInfo[i].addr == addr )
189
g_RecentVIOriginInfo[i].FrameCount = status.gDlistCount;
194
for( i=0; i<numOfRecentCIInfos; i++ )
196
if( g_RecentVIOriginInfo[i].addr == 0 )
199
g_RecentVIOriginInfo[i].addr = addr;
200
g_RecentVIOriginInfo[i].FrameCount = status.gDlistCount;
206
uint32 minFrameCount = 0xffffffff;
208
for( i=0; i<numOfRecentCIInfos; i++ )
210
if( g_RecentVIOriginInfo[i].FrameCount < minFrameCount )
213
minFrameCount = g_RecentVIOriginInfo[i].FrameCount;
217
g_RecentVIOriginInfo[index].addr = addr;
218
g_RecentVIOriginInfo[index].FrameCount = status.gDlistCount;
221
bool FrameBufferManager::HasAddrBeenDisplayed(uint32 addr, uint32 width)
223
addr &= (g_dwRamSize-1);
225
for( i=0; i<numOfRecentCIInfos; i++ )
227
if( g_uRecentCIInfoPtrs[i]->dwAddr == 0 )
230
if( g_uRecentCIInfoPtrs[i]->dwAddr == addr )
232
if( status.gDlistCount-g_uRecentCIInfoPtrs[i]->bUsedByVIAtFrame < 20 )
233
//if( g_uRecentCIInfoPtrs[i]->bUsedByVIAtFrame != 0 )
239
TXTRBUF_DUMP(TRACE0("This is a new buffer address, the addr is never a displayed buffer"););
245
for( i=0; i<numOfRecentCIInfos; i++ )
247
if( g_RecentVIOriginInfo[i].addr != 0 )
249
if( g_RecentVIOriginInfo[i].addr > addr &&
250
(g_RecentVIOriginInfo[i].addr - addr)%width == 0 &&
251
(g_RecentVIOriginInfo[i].addr - addr)/width <= 4)
253
if( status.gDlistCount-g_RecentVIOriginInfo[i].FrameCount < 20 )
254
//if( g_RecentVIOriginInfo[i].FrameCount != 0 )
260
TXTRBUF_DUMP(DebuggerAppendMsg("This is a new buffer address, the addr is never a displayed buffer"););
267
if( status.gDlistCount > 20 )
271
TXTRBUF_DUMP({DebuggerAppendMsg("This is a new buffer address, the addr is never a displayed buffer");});
276
int FrameBufferManager::FindRecentCIInfoIndex(uint32 addr)
278
for( int i=0; i<numOfRecentCIInfos; i++ )
280
if( g_uRecentCIInfoPtrs[i]->dwAddr <= addr && addr < g_uRecentCIInfoPtrs[i]->dwAddr+g_uRecentCIInfoPtrs[i]->dwMemSize )
288
bool FrameBufferManager::IsDIaRenderTexture()
290
// Knowing g_CI and g_ZI
294
bool foundSetScissor=false;
295
bool foundFillRect=false;
296
bool foundSetFillColor=false;
297
bool foundSetCImg=false;
298
bool foundTxtRect=false;
300
uint32 newFillColor = 0;
302
uint32 dwPC = gDlistStack[gDlistStackPointer].pc; // This points to the next instruction
304
for( int i=0; i<10; i++ )
306
uint32 w0 = *(uint32 *)(g_pRDRAMu8 + dwPC + i*8);
307
uint32 w1 = *(uint32 *)(g_pRDRAMu8 + dwPC + 4 + i*8);
309
if( (w0>>24) == RDP_SETSCISSOR )
311
height = ((w1>>0 )&0xFFF)/4;
312
foundSetScissor = true;
316
if( (w0>>24) == RDP_SETFILLCOLOR )
318
height = ((w1>>0 )&0xFFF)/4;
319
foundSetFillColor = true;
324
if( (w0>>24) == RDP_FILLRECT )
326
uint32 x0 = ((w1>>12)&0xFFF)/4;
327
uint32 y0 = ((w1>>0 )&0xFFF)/4;
328
uint32 x1 = ((w0>>12)&0xFFF)/4;
329
uint32 y1 = ((w0>>0 )&0xFFF)/4;
331
if( x0 == 0 && y0 == 0 )
333
if( x1 == g_CI.dwWidth )
336
foundFillRect = true;
340
if(x1 == (unsigned int)(g_CI.dwWidth-1))
343
foundFillRect = true;
349
if( (w0>>24) == RDP_TEXRECT )
355
if( (w0>>24) == RDP_SETCIMG )
363
bool foundSetScissor=false;
364
bool foundFillRect=false;
365
bool foundSetFillColor=false;
366
bool foundSetCImg=false;
367
bool foundTxtRect=false;
374
if( foundSetFillColor )
376
if( newFillColor != 0xFFFCFFFC )
377
return true; // this is a render_texture
382
if( gRDP.fillColor != 0x00FFFFF7 )
383
return true; // this is a render_texture
385
return false; // this is a normal ZImg
387
else if( foundSetFillColor && newFillColor == 0xFFFCFFFC && foundSetCImg )
398
if( foundSetScissor )
402
int FrameBufferManager::CheckAddrInBackBuffers(uint32 addr, uint32 memsize, bool copyToRDRAM)
404
int r = FindRecentCIInfoIndex(addr);
408
// Also check if the address is overwritten by a recent render_texture
409
//int t = CheckAddrInRenderTextures(addr,false);
411
for( int i=0; i<numOfTxtBufInfos; i++ )
413
uint32 bufHeight = gRenderTextureInfos[i].knownHeight ? gRenderTextureInfos[i].N64Height : gRenderTextureInfos[i].maxUsedHeight;
414
uint32 bufMemSize = gRenderTextureInfos[i].CI_Info.dwSize*gRenderTextureInfos[i].N64Width*bufHeight;
415
if( addr >=gRenderTextureInfos[i].CI_Info.dwAddr && addr < gRenderTextureInfos[i].CI_Info.dwAddr+bufMemSize)
417
if( g_uRecentCIInfoPtrs[r]->lastSetAtUcode < gRenderTextureInfos[i].updateAtUcodeCount )
429
if( r >= 0 && status.gDlistCount - g_uRecentCIInfoPtrs[r]->lastUsedFrame <= 3 && g_uRecentCIInfoPtrs[r]->bCopied == false )
431
DEBUGGER_IF_DUMP((logTextureBuffer&&r==1),TRACE2("Hit current front buffer at %08X, size=0x%X", addr, memsize));
432
DEBUGGER_IF_DUMP((logTextureBuffer&&r==0),TRACE2("Hit current back buffer at %08X, size=0x%X", addr, memsize));
433
DEBUGGER_IF_DUMP((logTextureBuffer&&r>1),TRACE2("Hit old back buffer at %08X, size=0x%X", addr, memsize));
435
SaveBackBuffer(r, NULL, true);
442
uint8 CIFindIndex(uint16 val)
444
for( int i=0; i<=0xFF; i++ )
446
if( val == g_wRDPTlut[i] )
455
void TexRectToFrameBuffer_8b(uint32 dwXL, uint32 dwYL, uint32 dwXH, uint32 dwYH, float t0u0, float t0v0, float t0u1, float t0v1, uint32 dwTile)
457
// Copy the framebuffer texture into the N64 framebuffer memory
461
uint32 maxW = g_pRenderTextureInfo->CI_Info.dwWidth;
462
uint32 maxH = maxW*3/4;
463
if( status.dwTvSystem == TV_SYSTEM_PAL )
469
uint32 maxW = g_pRenderTextureInfo->N64Width;
470
uint32 maxH = g_pRenderTextureInfo->N64Height;
472
uint32 maxOff = maxW*maxH;
474
TMEMLoadMapInfo &info = g_tmemLoadAddrMap[gRDP.tiles[dwTile].dwTMem];
475
uint32 dwWidth = dwXH-dwXL;
476
uint32 dwHeight = dwYH-dwYL;
478
float xScale = (t0u1-t0u0)/dwWidth;
479
float yScale = (t0v1-t0v0)/dwHeight;
481
uint8* dwSrc = g_pRDRAMu8 + info.dwLoadAddress;
482
uint8* dwDst = g_pRDRAMu8 + g_pRenderTextureInfo->CI_Info.dwAddr;
484
uint32 dwSrcPitch = gRDP.tiles[dwTile].dwPitch;
485
uint32 dwDstPitch = g_pRenderTextureInfo->CI_Info.dwWidth;
487
uint32 dwSrcOffX = gRDP.tiles[dwTile].hilite_sl;
488
uint32 dwSrcOffY = gRDP.tiles[dwTile].hilite_tl;
490
uint32 dwLeft = dwXL;
493
dwWidth = min(dwWidth,maxW-dwLeft);
494
dwHeight = min(dwHeight, maxH-dwTop);
495
if( maxH <= dwTop ) return;
497
for (uint32 y = 0; y < dwHeight; y++)
499
uint32 dwByteOffset = (uint32)(((y*yScale+dwSrcOffY) * dwSrcPitch) + dwSrcOffX);
501
for (uint32 x = 0; x < dwWidth; x++)
503
if( (((y+dwTop)*dwDstPitch+x+dwLeft)^0x3) > maxOff )
506
TRACE0("Warning: Offset exceeds limit");
510
dwDst[((y+dwTop)*dwDstPitch+x+dwLeft)^0x3] = dwSrc[(uint32)(dwByteOffset+x*xScale) ^ 0x3];
514
TXTRBUF_DUMP(DebuggerAppendMsg("TexRect To FrameBuffer: X0=%d, Y0=%d, X1=%d, Y1=%d,\n\t\tfS0=%f, fT0=%f, fS1=%f, fT1=%f ",
515
dwXL, dwYL, dwXH, dwYH, t0v0, t0v0, t0u1, t0v1););
518
void TexRectToN64FrameBuffer_16b(uint32 x0, uint32 y0, uint32 width, uint32 height, uint32 dwTile)
520
// Copy the framebuffer texture into the N64 RDRAM framebuffer memory structure
523
if( g_textures[dwTile].m_pCTexture->StartUpdate(&srcInfo) == false )
525
DebuggerAppendMsg("Fail to lock texture:TexRectToN64FrameBuffer_16b" );
529
uint32 n64CIaddr = g_CI.dwAddr;
530
uint32 n64CIwidth = g_CI.dwWidth;
532
for (uint32 y = 0; y < height; y++)
534
uint32* pSrc = (uint32*)((uint8*)srcInfo.lpSurface + y * srcInfo.lPitch);
535
uint16* pN64Buffer = (uint16*)(g_pRDRAMu8+(n64CIaddr&(g_dwRamSize-1)))+(y+y0)*n64CIwidth;
537
for (uint32 x = 0; x < width; x++)
539
pN64Buffer[x+x0] = ConvertRGBATo555(pSrc[x]);
543
g_textures[dwTile].m_pCTexture->EndUpdate(&srcInfo);
546
#define FAST_CRC_CHECKING_INC_X 13
547
#define FAST_CRC_CHECKING_INC_Y 11
548
#define FAST_CRC_MIN_Y_INC 2
549
#define FAST_CRC_MIN_X_INC 2
550
#define FAST_CRC_MAX_X_INC 7
551
#define FAST_CRC_MAX_Y_INC 3
552
extern uint32 dwAsmHeight;
553
extern uint32 dwAsmPitch;
554
extern uint32 dwAsmdwBytesPerLine;
555
extern uint32 dwAsmCRC;
556
extern uint8* pAsmStart;
558
uint32 CalculateRDRAMCRC(void *pPhysicalAddress, uint32 left, uint32 top, uint32 width, uint32 height, uint32 size, uint32 pitchInBytes )
561
dwAsmdwBytesPerLine = ((width<<size)+1)/2;
563
if( currentRomOptions.bFastTexCRC && !options.bLoadHiResTextures && (height>=32 || (dwAsmdwBytesPerLine>>2)>=16))
565
uint32 realWidthInDWORD = dwAsmdwBytesPerLine>>2;
566
uint32 xinc = realWidthInDWORD / FAST_CRC_CHECKING_INC_X;
567
if( xinc < FAST_CRC_MIN_X_INC )
569
xinc = min(FAST_CRC_MIN_X_INC, width);
571
if( xinc > FAST_CRC_MAX_X_INC )
573
xinc = FAST_CRC_MAX_X_INC;
576
uint32 yinc = height / FAST_CRC_CHECKING_INC_Y;
577
if( yinc < FAST_CRC_MIN_Y_INC )
579
yinc = min(FAST_CRC_MIN_Y_INC, height);
581
if( yinc > FAST_CRC_MAX_Y_INC )
583
yinc = FAST_CRC_MAX_Y_INC;
586
uint32 pitch = pitchInBytes>>2;
587
register uint32 *pStart = (uint32*)(pPhysicalAddress);
588
pStart += (top * pitch) + (((left<<size)+1)>>3);
590
// The original assembly code had a bug in it (it incremented pStart by 'pitch' in bytes, not in dwords)
591
// This C code implements the same algorithm as the ASM but without the bug
596
while (x < realWidthInDWORD)
598
dwAsmCRC = (dwAsmCRC << 4) + ((dwAsmCRC >> 28) & 15);
599
dwAsmCRC += pStart[x];
612
dwAsmdwBytesPerLine = ((width<<size)+1)/2;
614
pAsmStart = (uint8*)(pPhysicalAddress);
615
pAsmStart += (top * pitchInBytes) + (((left<<size)+1)>>1);
617
dwAsmHeight = height - 1;
618
dwAsmPitch = pitchInBytes;
620
#if !defined(__GNUC__) && !defined(NO_ASM)
629
mov ecx, pAsmStart; // = pStart
630
mov edx, 0 // The CRC
631
mov eax, dwAsmHeight // = y
632
l2: mov ebx, dwAsmdwBytesPerLine // = x
634
l1: mov esi, [ecx+ebx]
654
#elif defined(__GNUC__) && defined(__x86_64__) && !defined(NO_ASM)
655
asm volatile(" xorl %k2, %k2 \n"
656
" movsxl %k4, %q4 \n"
658
" movsxl %3, %%rbx \n"
661
" movl (%0,%%rbx,1), %%eax \n"
662
" xorl %%ebx, %%eax \n"
664
" addl %%eax, %k2 \n"
667
" xorl %k1, %%eax \n"
668
" addl %%eax, %k2 \n"
672
: "+r"(pAsmStart), "+r"(dwAsmHeight), "=&r"(dwAsmCRC)
673
: "m"(dwAsmdwBytesPerLine), "r"(dwAsmPitch)
674
: "%rbx", "%rax", "memory", "cc"
676
#elif !defined(NO_ASM)
678
asm volatile("pusha \n"
679
"mov pAsmStart, %%ecx \n" // = pStart
680
"mov $0, %%edx \n" // The CRC
681
"mov dwAsmHeight, %%eax \n" // = y
683
"mov dwAsmdwBytesPerLine, %%ebx \n" // = x
686
"mov (%%ecx,%%ebx), %%esi \n"
687
"xor %%ebx, %%esi \n"
689
"add %%esi, %%edx \n"
692
"xor %%eax, %%esi \n"
693
"add %%esi, %%edx \n"
694
"add dwAsmPitch, %%ecx \n"
698
"mov %%edx, dwAsmCRC \n"
705
unsigned int saveEBX;
706
unsigned int saveEAX;
707
unsigned int saveECX;
708
unsigned int saveEDX;
709
unsigned int saveESI;
710
unsigned int asmdwBytesPerLine = dwAsmdwBytesPerLine;
711
unsigned int asmPitch = dwAsmPitch;
712
unsigned int asmHeight = dwAsmHeight;
714
asm volatile("mov %%ebx, %2 \n"
719
"mov %0, %%ecx \n" // = pStart
720
"mov $0, %%edx \n" // The CRC
721
"mov %1, %%eax \n" // = y
723
"mov %3, %%ebx \n" // = x
726
"mov (%%ecx,%%ebx), %%esi \n"
727
"xor %%ebx, %%esi \n"
729
"add %%esi, %%edx \n"
732
"xor %%eax, %%esi \n"
733
"add %%esi, %%edx \n"
745
: "m"(pAsmStart), "m"(asmHeight), "m"(saveEBX), "m"(asmdwBytesPerLine), "m"(asmPitch), "m"(saveEAX),
746
"m"(asmCRC), "m"(saveECX), "m"(saveEDX), "m"(saveESI)
755
TRACE0("Exception in texture CRC calculation");
760
unsigned char CalculateMaxCI(void *pPhysicalAddress, uint32 left, uint32 top, uint32 width, uint32 height, uint32 size, uint32 pitchInBytes )
764
unsigned char val = 0;
766
if( TXT_SIZE_8b == size )
768
for( y = 0; y<height; y++ )
770
buf = (unsigned char*)pPhysicalAddress + left + pitchInBytes * (y+top);
771
for( x=0; x<width; x++ )
773
if( buf[x] > val ) val = buf[x];
781
unsigned char val1,val2;
784
for( y = 0; y<height; y++ )
786
buf = (unsigned char*)pPhysicalAddress + left + pitchInBytes * (y+top);
787
for( x=0; x<width; x++ )
791
if( val1 > val ) val = val1;
792
if( val2 > val ) val = val2;
802
bool FrameBufferManager::FrameBufferInRDRAMCheckCRC()
804
RecentCIInfo &p = *(g_uRecentCIInfoPtrs[0]);
805
uint8 *pFrameBufferBase = (uint8*)(g_pRDRAMu8+p.dwAddr);
806
uint32 pitch = (p.dwWidth << p.dwSize ) >> 1;
807
uint32 crc = CalculateRDRAMCRC(pFrameBufferBase, 0, 0, p.dwWidth, p.dwHeight, p.dwSize, pitch);
811
TRACE0("Frame Buffer CRC mismitch, it is modified by CPU");
820
extern std::vector<uint32> frameWriteRecord;
821
void FrameBufferManager::FrameBufferWriteByCPU(uint32 addr, uint32 size)
823
if( !frameBufferOptions.bProcessCPUWrite ) return;
824
//WARNING(TRACE2("Frame Buffer Write, addr=%08X, CI Addr=%08X", addr, g_CI.dwAddr));
825
status.frameWriteByCPU = TRUE;
826
frameWriteRecord.push_back(addr&(g_dwRamSize-1));
829
extern RECT frameWriteByCPURect;
830
extern std::vector<RECT> frameWriteByCPURects;
831
extern RECT frameWriteByCPURectArray[20][20];
832
extern bool frameWriteByCPURectFlag[20][20];
833
#define FRAMEBUFFER_IN_BLOCK
834
bool FrameBufferManager::ProcessFrameWriteRecord()
836
int size = frameWriteRecord.size();
837
if( size == 0 ) return false;
839
int index = FindRecentCIInfoIndex(frameWriteRecord[0]);
842
LOG_TEXTURE(TRACE1("Frame Buffer Write to non-record addr = %08X", frameWriteRecord[0]));
843
frameWriteRecord.clear();
848
uint32 base = g_uRecentCIInfoPtrs[index]->dwAddr;
849
uint32 uwidth = g_uRecentCIInfoPtrs[index]->dwWidth;
850
uint32 uheight = g_uRecentCIInfoPtrs[index]->dwHeight;
851
uint32 upitch = uwidth<<1;
853
frameWriteByCPURect.left=uwidth-1;
854
frameWriteByCPURect.top = uheight-1;
856
frameWriteByCPURect.right=0;
857
frameWriteByCPURect.bottom = 0;
861
for( int i=0; i<size; i++ )
863
off = frameWriteRecord[i]-base;
864
if( off < (int)g_uRecentCIInfoPtrs[index]->dwMemSize )
867
x = (off - y*upitch)>>1;
869
#ifdef FRAMEBUFFER_IN_BLOCK
873
RECT &rect = frameWriteByCPURectArray[xidx][yidx];
875
if( !frameWriteByCPURectFlag[xidx][yidx] )
877
rect.left=rect.right=x;
878
rect.top=rect.bottom=y;
879
frameWriteByCPURectFlag[xidx][yidx]=true;
883
if( x < rect.left ) rect.left = x;
884
if( x > rect.right ) rect.right = x;
885
if( y < rect.top ) rect.top = y;
886
if( y > rect.bottom ) rect.bottom = y;
889
if( x < frameWriteByCPURect.left ) frameWriteByCPURect.left = x;
890
if( x > frameWriteByCPURect.right ) frameWriteByCPURect.right = x;
891
if( y < frameWriteByCPURect.top ) frameWriteByCPURect.top = y;
892
if( y > frameWriteByCPURect.bottom ) frameWriteByCPURect.bottom = y;
897
frameWriteRecord.clear();
898
LOG_TEXTURE(TRACE4("Frame Buffer Write: Left=%d, Top=%d, Right=%d, Bottom=%d", frameWriteByCPURect.left,
899
frameWriteByCPURect.top, frameWriteByCPURect.right, frameWriteByCPURect.bottom));
904
void FrameBufferManager::FrameBufferReadByCPU( uint32 addr )
906
///return; // it does not work very well anyway
909
if( !frameBufferOptions.bProcessCPURead ) return;
911
addr &= (g_dwRamSize-1);
912
int index = FindRecentCIInfoIndex(addr);
915
// Check if this is the depth buffer
916
uint32 size = 2*g_RecentCIInfo[0].dwWidth*g_RecentCIInfo[0].dwHeight;
919
if( addr >= g_ZI.dwAddr && addr < g_ZI.dwAddr + size )
921
TXTRBUF_OR_CI_DUMP(TRACE1("Depth Buffer read, reported by emulator, addr=%08X", addr));
929
if( status.gDlistCount - g_uRecentCIInfoPtrs[index]->lastUsedFrame > 3 )
931
// Ok, we don't have this frame anymore
935
//TXTRBUF_OR_CI_DUMP(TRACE1("FB Read By CPU at %08X", addr));
936
if( g_uRecentCIInfoPtrs[index]->bCopied ) return;
937
//if( addr != g_uRecentCIInfoPtrs[index]->dwAddr ) return;
939
TXTRBUF_OR_CI_DUMP(TRACE1("Frame Buffer read, reported by emulator, addr=%08X", addr));
940
uint32 size = 0x1000 - addr%0x1000;
941
CheckAddrInBackBuffers(addr, size, true);
943
DEBUGGER_IF_DUMP(pauseAtNext,{TRACE0("Frame Buffer read");});
944
DEBUGGER_PAUSE_AND_DUMP_NO_UPDATE(NEXT_RENDER_TEXTURE,
945
{DebuggerAppendMsg("Paused after setting Frame Buffer read:\n Cur CI Addr: 0x%08x, Fmt: %s Size: %s Width: %d",
946
g_CI.dwAddr, pszImgFormat[g_CI.dwFormat], pszImgSize[g_CI.dwSize], g_CI.dwWidth);});
951
extern RECT frameWriteByCPURect;
952
extern std::vector<RECT> frameWriteByCPURects;
953
extern RECT frameWriteByCPURectArray[20][20];
954
extern bool frameWriteByCPURectFlag[20][20];
955
#define FRAMEBUFFER_IN_BLOCK
957
void FrameBufferManager::UpdateFrameBufferBeforeUpdateFrame()
959
if( (frameBufferOptions.bProcessCPUWrite && status.frameWriteByCPU ) ||
960
(frameBufferOptions.bLoadBackBufFromRDRAM && !FrameBufferInRDRAMCheckCRC() ) )
961
// Checks if frame buffer has been modified by CPU
962
// Only happens to Dr. Mario
964
if( frameBufferOptions.bProcessCPUWrite )
966
if( ProcessFrameWriteRecord() )
968
#ifdef FRAMEBUFFER_IN_BLOCK
972
for( j=0; j<20; j++ )
974
if( frameWriteByCPURectFlag[i][j] )
976
CRender::GetRender()->DrawFrameBuffer(false, frameWriteByCPURectArray[i][j].left, frameWriteByCPURectArray[i][j].top,
977
frameWriteByCPURectArray[i][j].right-frameWriteByCPURectArray[i][j].left+1, frameWriteByCPURectArray[i][j].bottom-frameWriteByCPURectArray[i][j].top+1);
983
for( j=0; j<20; j++ )
985
if( frameWriteByCPURectFlag[i][j] )
987
ClearN64FrameBufferToBlack(frameWriteByCPURectArray[i][j].left, frameWriteByCPURectArray[i][j].top,
988
frameWriteByCPURectArray[i][j].right-frameWriteByCPURectArray[i][j].left+1, frameWriteByCPURectArray[i][j].bottom-frameWriteByCPURectArray[i][j].top+1);
989
frameWriteByCPURectFlag[i][j] = false;
993
//memset(frameWriteByCPURectArray, 0, sizeof(frameWriteByCPURectArray));
994
//memset(frameWriteByCPURectFlag, 0, sizeof(frameWriteByCPURectFlag));
996
CRender::GetRender()->DrawFrameBuffer(false, frameWriteByCPURect.left, frameWriteByCPURect.top,
997
frameWriteByCPURect.right-frameWriteByCPURect.left, frameWriteByCPURect.bottom-frameWriteByCPURect.top);
998
ClearN64FrameBufferToBlack(frameWriteByCPURect.left, frameWriteByCPURect.top,
999
frameWriteByCPURect.right-frameWriteByCPURect.left+1, frameWriteByCPURect.bottom-frameWriteByCPURect.top+1);
1002
int size = frameWriteByCPURects.size();
1003
for( int i=0; i<size; i++)
1005
CRender::GetRender()->DrawFrameBuffer(false, frameWriteByCPURects[i].left, frameWriteByCPURects[i].top,
1006
frameWriteByCPURects[i].right-frameWriteByCPURects[i].left, frameWriteByCPURects[i].bottom-frameWriteByCPURects[i].top);
1007
ClearN64FrameBufferToBlack(frameWriteByCPURects[i].left, frameWriteByCPURects[i].top,
1008
frameWriteByCPURects[i].right-frameWriteByCPURects[i].left+1, frameWriteByCPURects[i].bottom-frameWriteByCPURects[i].top+1);
1010
frameWriteByCPURects.clear();
1014
status.frameWriteByCPU = FALSE;
1018
if (CRender::IsAvailable())
1020
RecentCIInfo &p = *(g_uRecentCIInfoPtrs[0]);
1021
CRender::GetRender()->DrawFrameBuffer(false, 0,0,p.dwWidth,p.dwHeight);
1022
ClearN64FrameBufferToBlack();
1028
uint32 FrameBufferManager::ComputeCImgHeight(SetImgInfo &info, uint32 &height)
1030
uint32 dwPC = gDlistStack[gDlistStackPointer].pc; // This points to the next instruction
1032
for( int i=0; i<10; i++ )
1034
uint32 w0 = *(uint32 *)(g_pRDRAMu8 + dwPC + i*8);
1035
uint32 w1 = *(uint32 *)(g_pRDRAMu8 + dwPC + 4 + i*8);
1037
if( (w0>>24) == RDP_SETSCISSOR )
1039
height = ((w1>>0 )&0xFFF)/4;
1040
TXTRBUF_DETAIL_DUMP(TRACE1("buffer height = %d", height));
1041
return RDP_SETSCISSOR;
1044
if( (w0>>24) == RDP_FILLRECT )
1046
uint32 x0 = ((w1>>12)&0xFFF)/4;
1047
uint32 y0 = ((w1>>0 )&0xFFF)/4;
1048
uint32 x1 = ((w0>>12)&0xFFF)/4;
1049
uint32 y1 = ((w0>>0 )&0xFFF)/4;
1051
if( x0 == 0 && y0 == 0 )
1053
if( x1 == info.dwWidth )
1056
TXTRBUF_DETAIL_DUMP(TRACE1("buffer height = %d", height));
1057
return RDP_FILLRECT;
1060
if(x1 == (unsigned int)(info.dwWidth-1))
1063
TXTRBUF_DETAIL_DUMP(TRACE1("buffer height = %d", height));
1064
return RDP_FILLRECT;
1069
if( (w0>>24) == RDP_SETCIMG )
1074
if( (w0>>24) == RDP_SETCIMG )
1080
if( gRDP.scissor.left == 0 && gRDP.scissor.top == 0 && (unsigned int)gRDP.scissor.right == info.dwWidth )
1082
height = gRDP.scissor.bottom;
1083
TXTRBUF_DETAIL_DUMP(TRACE1("buffer height = %d", height));
1084
return RDP_SETSCISSOR+1;
1088
TXTRBUF_DETAIL_DUMP(TRACE0("Not sure about buffer height"));
1090
height = info.dwWidth*3/4;
1091
if( status.dwTvSystem == TV_SYSTEM_PAL )
1093
height = info.dwWidth*9/11;
1096
if( gRDP.scissor.bottom < (int)height && gRDP.scissor.bottom != 0 )
1098
height = gRDP.scissor.bottom;
1101
if( info.dwAddr + height*info.dwWidth*info.dwSize >= g_dwRamSize )
1103
height = info.dwWidth*3/4;
1104
if( status.dwTvSystem == TV_SYSTEM_PAL )
1106
height = info.dwWidth*9/11;
1109
if( gRDP.scissor.bottom < (int)height && gRDP.scissor.bottom != 0 )
1111
height = gRDP.scissor.bottom;
1114
if( info.dwAddr + height*info.dwWidth*info.dwSize >= g_dwRamSize )
1116
height = ( g_dwRamSize - info.dwAddr ) / info.dwWidth;
1120
TXTRBUF_DETAIL_DUMP(TRACE1("render_texture height = %d", height));
1124
int FrameBufferManager::CheckRenderTexturesWithNewCI(SetImgInfo &CIinfo, uint32 height, bool byNewTxtrBuf)
1127
uint32 memsize = ((height*CIinfo.dwWidth)>>1)<<CIinfo.dwSize;
1129
for( int i=0; i<numOfTxtBufInfos; i++ )
1131
RenderTextureInfo &info = gRenderTextureInfos[i];
1132
if( !info.isUsed ) continue;
1134
bool covered = false;
1136
if( info.CI_Info.dwAddr == CIinfo.dwAddr )
1138
if( info.CI_Info.dwSize == CIinfo.dwSize &&
1139
info.CI_Info.dwWidth == CIinfo.dwWidth &&
1140
info.CI_Info.dwFormat == CIinfo.dwFormat &&
1141
info.N64Height == height
1142
&& info.CI_Info.dwAddr == CIinfo.dwAddr
1145
// This is the same texture at the same address
1153
// At the same address, but not the same size
1154
//SAFE_DELETE(info.psurf);
1160
uint32 memsize2 = ((info.N64Height*info.N64Width)>>1)<<info.CI_Info.dwSize;
1162
if( info.CI_Info.dwAddr > CIinfo.dwAddr && info.CI_Info.dwAddr < CIinfo.dwAddr + memsize)
1164
else if( info.CI_Info.dwAddr+memsize2 > CIinfo.dwAddr && info.CI_Info.dwAddr+memsize2 < CIinfo.dwAddr + memsize)
1166
else if( CIinfo.dwAddr > info.CI_Info.dwAddr && CIinfo.dwAddr < info.CI_Info.dwAddr + memsize2 )
1168
else if( CIinfo.dwAddr+ memsize > info.CI_Info.dwAddr && CIinfo.dwAddr+ memsize < info.CI_Info.dwAddr + memsize2 )
1174
//SAFE_DELETE(info.psurf);
1175
if( info.pRenderTexture->IsBeingRendered() )
1177
TRACE0("Error, covering a render_texture which is being rendered");
1178
TRACE3("New addrr=%08X, width=%d, height=%d", CIinfo.dwAddr, CIinfo.dwWidth, height );
1179
TRACE3("Old addrr=%08X, width=%d, height=%d", info.CI_Info.dwAddr, info.N64Width, info.N64Height );
1181
info.isUsed = false;
1182
TXTRBUF_DUMP(TRACE5("Delete txtr buf %d at %08X, covered by new CI at %08X, Width=%d, Height=%d",
1183
i, info.CI_Info.dwAddr, CIinfo.dwAddr, CIinfo.dwWidth, height ));
1184
SAFE_DELETE(info.pRenderTexture);
1185
info.txtEntry.pTexture = NULL;
1193
extern RecentCIInfo *g_uRecentCIInfoPtrs[5];
1194
RenderTextureInfo newRenderTextureInfo;
1196
int FrameBufferManager::FindASlot(void)
1200
// Find an empty slot
1202
for( int i=0; i<numOfTxtBufInfos; i++ )
1204
if( !gRenderTextureInfos[i].isUsed && gRenderTextureInfos[i].updateAtFrame < status.gDlistCount )
1212
// If cannot find an empty slot, find the oldest slot and reuse the slot
1215
uint32 oldestCount=0xFFFFFFFF;
1216
uint32 oldestIdx = 0;
1217
for( int i=0; i<numOfTxtBufInfos; i++ )
1219
if( gRenderTextureInfos[i].updateAtUcodeCount < oldestCount )
1221
oldestCount = gRenderTextureInfos[i].updateAtUcodeCount;
1229
DEBUGGER_IF_DUMP((logTextureBuffer && gRenderTextureInfos[idx].pRenderTexture ),TRACE2("Delete txtr buf %d at %08X, to reuse it.", idx, gRenderTextureInfos[idx].CI_Info.dwAddr ));
1230
SAFE_DELETE(gRenderTextureInfos[idx].pRenderTexture) ;
1236
void FrameBufferManager::SetRenderTexture(void)
1238
memcpy(&(newRenderTextureInfo.CI_Info), &g_CI, sizeof(SetImgInfo));
1240
newRenderTextureInfo.N64Width = newRenderTextureInfo.CI_Info.dwWidth;
1241
newRenderTextureInfo.knownHeight = ComputeCImgHeight(g_CI, newRenderTextureInfo.N64Height);
1243
status.bHandleN64RenderTexture = true;
1244
newRenderTextureInfo.maxUsedHeight = 0;
1246
if( defaultRomOptions.bInN64Resolution )
1248
newRenderTextureInfo.bufferWidth = newRenderTextureInfo.N64Width;
1249
newRenderTextureInfo.bufferHeight = newRenderTextureInfo.N64Height;
1251
else if( defaultRomOptions.bDoubleSizeForSmallTxtrBuf && newRenderTextureInfo.N64Width<=128 && newRenderTextureInfo.N64Height<=128)
1253
newRenderTextureInfo.bufferWidth = newRenderTextureInfo.N64Width*2;
1254
newRenderTextureInfo.bufferHeight = newRenderTextureInfo.N64Height*2;
1258
newRenderTextureInfo.bufferWidth = newRenderTextureInfo.N64Width;
1259
newRenderTextureInfo.bufferHeight = newRenderTextureInfo.N64Height;
1262
newRenderTextureInfo.scaleX = newRenderTextureInfo.bufferWidth / float(newRenderTextureInfo.N64Width);
1263
newRenderTextureInfo.scaleY = newRenderTextureInfo.bufferHeight / float(newRenderTextureInfo.N64Height);
1265
status.bFrameBufferIsDrawn = false;
1266
status.bFrameBufferDrawnByTriangles = false;
1268
newRenderTextureInfo.updateAtFrame = status.gDlistCount;
1269
newRenderTextureInfo.updateAtUcodeCount = status.gUcodeCount;
1271
// Delay activation of the render_texture until the 1st rendering
1273
TXTRBUF_DUMP(TRACE1("Set render_texture: addr=%08X", g_CI.dwAddr));
1274
DEBUGGER_PAUSE_AND_DUMP_NO_UPDATE(NEXT_RENDER_TEXTURE,
1275
{DebuggerAppendMsg("Paused after setting render_texture:\nAddr: 0x%08x, Fmt: %s Size: %s Width: %d, Height:%d",
1276
g_CI.dwAddr, pszImgFormat[g_CI.dwFormat], pszImgSize[g_CI.dwSize], g_CI.dwWidth, g_pRenderTextureInfo->N64Height);});
1279
int FrameBufferManager::SetBackBufferAsRenderTexture(SetImgInfo &CIinfo, int ciInfoIdx)
1282
OK, heres the drill!
1283
* We set the graphics card's back buffer's contents as a render_texure
1284
* This is done due to how the current framebuffer implementation detects
1285
changes to the backbuffer memory pointer and then we do a texture
1286
copy. This might be slow since it doesnt use hardware auxillary buffers*/
1289
RenderTextureInfo tempRenderTextureInfo;
1291
memcpy(&(tempRenderTextureInfo.CI_Info), &CIinfo, sizeof(SetImgInfo));
1293
tempRenderTextureInfo.N64Width = g_uRecentCIInfoPtrs[ciInfoIdx]->dwLastWidth;
1294
tempRenderTextureInfo.N64Height = g_uRecentCIInfoPtrs[ciInfoIdx]->dwLastHeight;
1295
tempRenderTextureInfo.knownHeight = true;
1296
tempRenderTextureInfo.maxUsedHeight = 0;
1298
tempRenderTextureInfo.bufferWidth = windowSetting.uDisplayWidth;
1299
tempRenderTextureInfo.bufferHeight = windowSetting.uDisplayHeight;
1301
tempRenderTextureInfo.scaleX = tempRenderTextureInfo.bufferWidth / float(tempRenderTextureInfo.N64Width);
1302
tempRenderTextureInfo.scaleY = tempRenderTextureInfo.bufferHeight / float(tempRenderTextureInfo.N64Height);
1304
status.bFrameBufferIsDrawn = false;
1305
status.bFrameBufferDrawnByTriangles = false;
1307
tempRenderTextureInfo.updateAtFrame = status.gDlistCount;
1308
tempRenderTextureInfo.updateAtUcodeCount = status.gUcodeCount;
1310
// Checking against previous render_texture infos
1311
//uint32 memsize = ((tempRenderTextureInfo.N64Height*tempRenderTextureInfo.N64Width)>>1)<<tempRenderTextureInfo.CI_Info.dwSize;
1312
int matchidx = CheckRenderTexturesWithNewCI(CIinfo,tempRenderTextureInfo.N64Height,false);
1313
int idxToUse = (matchidx >= 0) ? matchidx : FindASlot();
1315
if( gRenderTextureInfos[idxToUse].pRenderTexture == NULL || matchidx < 0 )
1317
gRenderTextureInfos[idxToUse].pRenderTexture =
1318
new COGLRenderTexture(tempRenderTextureInfo.bufferWidth, tempRenderTextureInfo.bufferHeight, &gRenderTextureInfos[idxToUse], AS_BACK_BUFFER_SAVE);
1321
// Need to set all variables for gRenderTextureInfos[idxToUse]
1322
CRenderTexture *pRenderTexture = gRenderTextureInfos[idxToUse].pRenderTexture;
1323
memcpy(&gRenderTextureInfos[idxToUse], &tempRenderTextureInfo, sizeof(RenderTextureInfo) );
1324
gRenderTextureInfos[idxToUse].pRenderTexture = pRenderTexture;
1325
gRenderTextureInfos[idxToUse].isUsed = true;
1326
gRenderTextureInfos[idxToUse].txtEntry.pTexture = pRenderTexture->m_pTexture;
1327
gRenderTextureInfos[idxToUse].txtEntry.txtrBufIdx = idxToUse+1;
1329
TXTRBUF_DUMP(TRACE2("Set back buf as render_texture %d, addr=%08X", idxToUse, CIinfo.dwAddr));
1330
DEBUGGER_PAUSE_AND_DUMP_NO_UPDATE(NEXT_RENDER_TEXTURE,
1331
{DebuggerAppendMsg("Paused after setting render_texture:\nAddr: 0x%08x, Fmt: %s Size: %s Width: %d, Height:%d",
1332
CIinfo.dwAddr, pszImgFormat[CIinfo.dwFormat], pszImgSize[CIinfo.dwSize], CIinfo.dwWidth, g_pRenderTextureInfo->N64Height);});
1337
void FrameBufferManager::CloseRenderTexture(bool toSave)
1339
if( m_curRenderTextureIndex < 0 ) return;
1341
status.bHandleN64RenderTexture = false;
1342
if( status.bDirectWriteIntoRDRAM )
1347
RestoreNormalBackBuffer();
1348
if( !toSave || !status.bFrameBufferIsDrawn || !status.bFrameBufferDrawnByTriangles )
1350
TXTRBUF_DUMP(TRACE0("Closing render_texture without save"););
1351
SAFE_DELETE(gRenderTextureInfos[m_curRenderTextureIndex].pRenderTexture);
1352
gRenderTextureInfos[m_curRenderTextureIndex].isUsed = false;
1353
TXTRBUF_DUMP(TRACE1("Delete render_texture %d",m_curRenderTextureIndex););
1357
TXTRBUF_DUMP(TRACE1("Closing render_texture %d", m_curRenderTextureIndex););
1358
StoreRenderTextureToRDRAM();
1360
if( frameBufferOptions.bRenderTextureWriteBack )
1362
SAFE_DELETE(gRenderTextureInfos[m_curRenderTextureIndex].pRenderTexture);
1363
gRenderTextureInfos[m_curRenderTextureIndex].isUsed = false;
1364
TXTRBUF_DUMP(TRACE1("Delete render_texture %d after writing back to RDRAM",m_curRenderTextureIndex););
1368
g_pRenderTextureInfo->crcInRDRAM = ComputeRenderTextureCRCInRDRAM(m_curRenderTextureIndex);
1369
g_pRenderTextureInfo->crcCheckedAtFrame = status.gDlistCount;
1374
SetScreenMult(windowSetting.uDisplayWidth/windowSetting.fViWidth, windowSetting.uDisplayHeight/windowSetting.fViHeight);
1375
CRender::g_pRender->UpdateClipRectangle();
1376
CRender::g_pRender->ApplyScissorWithClipRatio();
1378
DEBUGGER_PAUSE_AND_DUMP_NO_UPDATE(NEXT_RENDER_TEXTURE,
1380
DebuggerAppendMsg("Paused after saving render_texture %d:\nAddr: 0x%08x, Fmt: %s Size: %s Width: %d", m_curRenderTextureIndex,
1381
g_pRenderTextureInfo->CI_Info.dwAddr, pszImgFormat[g_pRenderTextureInfo->CI_Info.dwFormat], pszImgSize[g_pRenderTextureInfo->CI_Info.dwSize], g_pRenderTextureInfo->CI_Info.dwWidth);
1385
void FrameBufferManager::ClearN64FrameBufferToBlack(uint32 left, uint32 top, uint32 width, uint32 height)
1387
RecentCIInfo &p = *(g_uRecentCIInfoPtrs[0]);
1388
uint16 *frameBufferBase = (uint16*)(g_pRDRAMu8+p.dwAddr);
1389
uint32 pitch = p.dwWidth;
1391
if( width == 0 || height == 0 )
1393
uint32 len = p.dwHeight*p.dwWidth*p.dwSize;
1394
if( p.dwSize == TXT_SIZE_4b ) len = (p.dwHeight*p.dwWidth)>>1;
1395
memset(frameBufferBase, 0, len);
1399
for( uint32 y=0; y<height; y++)
1401
for( uint32 x=0; x<width; x++ )
1403
*(frameBufferBase+(y+top)*pitch+x+left) = 0;
1409
uint8 RevTlutTable[0x10000];
1410
bool RevTlutTableNeedUpdate = false;
1411
void InitTlutReverseLookup(void)
1413
if( RevTlutTableNeedUpdate )
1415
memset(RevTlutTable, 0, 0x10000);
1416
for( int i=0; i<=0xFF; i++ )
1418
RevTlutTable[g_wRDPTlut[i]] = uint8(i);
1421
RevTlutTableNeedUpdate = false;
1426
//copies backbuffer to N64 framebuffer by notification by emu core
1428
void FrameBufferManager::CopyBackToFrameBufferIfReadByCPU(uint32 addr)
1430
int i = FindRecentCIInfoIndex(addr);
1433
//if( i == 0 ) CGraphicsContext::Get()->UpdateFrame();
1434
RecentCIInfo *info = g_uRecentCIInfoPtrs[i];
1435
StoreBackBufferToRDRAM( info->dwAddr, info->dwFormat, info->dwSize, info->dwWidth, info->dwHeight,
1436
windowSetting.uDisplayWidth, windowSetting.uDisplayHeight, addr, 0x1000-addr%0x1000);
1437
TRACE1("Copy back for CI Addr=%08X", info->dwAddr);
1440
//we do this checks to see if a render_texture operation is occuring...
1441
void FrameBufferManager::CheckRenderTextureCRCInRDRAM(void)
1443
for( int i=0; i<numOfTxtBufInfos; i++ )
1445
if( !gRenderTextureInfos[i].isUsed )
1448
if( gRenderTextureInfos[i].pRenderTexture->IsBeingRendered() )
1451
if( gRenderTextureInfos[i].crcCheckedAtFrame < status.gDlistCount )
1453
uint32 crc = ComputeRenderTextureCRCInRDRAM(i);
1454
if( gRenderTextureInfos[i].crcInRDRAM != crc )
1456
// RDRAM has been modified by CPU core
1457
TXTRBUF_DUMP(TRACE2("Delete txtr buf %d at %08X, CRC in RDRAM changed", i, gRenderTextureInfos[i].CI_Info.dwAddr ));
1458
SAFE_DELETE(gRenderTextureInfos[i].pRenderTexture);
1459
gRenderTextureInfos[i].isUsed = false;
1464
gRenderTextureInfos[i].crcCheckedAtFrame = status.gDlistCount;
1470
//check render_texture memory addresses
1471
int FrameBufferManager::CheckAddrInRenderTextures(uint32 addr, bool checkcrc)
1473
for( int i=0; i<numOfTxtBufInfos; i++ )
1475
if( !gRenderTextureInfos[i].isUsed )
1478
if( gRenderTextureInfos[i].pRenderTexture->IsBeingRendered() )
1481
uint32 bufHeight = gRenderTextureInfos[i].knownHeight ? gRenderTextureInfos[i].N64Height : gRenderTextureInfos[i].maxUsedHeight;
1482
uint32 bufMemSize = gRenderTextureInfos[i].CI_Info.dwSize*gRenderTextureInfos[i].N64Width*bufHeight;
1483
if( addr >=gRenderTextureInfos[i].CI_Info.dwAddr && addr < gRenderTextureInfos[i].CI_Info.dwAddr+bufMemSize)
1487
// Check the CRC in RDRAM
1488
if( gRenderTextureInfos[i].crcCheckedAtFrame < status.gDlistCount )
1490
uint32 crc = ComputeRenderTextureCRCInRDRAM(i);
1491
if( gRenderTextureInfos[i].crcInRDRAM != crc )
1493
// RDRAM has been modified by CPU core
1494
TRACE3("Buf %d CRC in RDRAM changed from %08X to %08X", i, gRenderTextureInfos[i].crcInRDRAM, crc );
1495
TXTRBUF_DUMP(TRACE2("Delete txtr buf %d at %08X, crcInRDRAM failed.", i, gRenderTextureInfos[i].CI_Info.dwAddr ));
1496
SAFE_DELETE(gRenderTextureInfos[i].pRenderTexture);
1497
gRenderTextureInfos[i].isUsed = false;
1502
gRenderTextureInfos[i].crcCheckedAtFrame = status.gDlistCount;
1507
TXTRBUF_DUMP(TRACE2("Loading texture addr = %08X from txtr buf %d", addr, i));
1515
//load texture from render_texture buffer
1516
void FrameBufferManager::LoadTextureFromRenderTexture(TxtrCacheEntry* pEntry, int infoIdx)
1518
if( infoIdx < 0 || infoIdx >= numOfTxtBufInfos )
1520
infoIdx = CheckAddrInRenderTextures(pEntry->ti.Address);
1523
if( infoIdx >= 0 && gRenderTextureInfos[infoIdx].isUsed && gRenderTextureInfos[infoIdx].pRenderTexture )
1525
TXTRBUF_DUMP(TRACE1("Loading from render_texture %d", infoIdx));
1526
gRenderTextureInfos[infoIdx].pRenderTexture->LoadTexture(pEntry);
1530
void FrameBufferManager::RestoreNormalBackBuffer()
1532
if( m_curRenderTextureIndex >= 0 && m_curRenderTextureIndex < numOfTxtBufInfos )
1534
if( gRenderTextureInfos[m_curRenderTextureIndex].pRenderTexture )
1535
gRenderTextureInfos[m_curRenderTextureIndex].pRenderTexture->SetAsRenderTarget(false);
1536
m_isRenderingToTexture = false;
1537
m_lastTextureBufferIndex = m_curRenderTextureIndex;
1540
if( !status.bFrameBufferIsDrawn || !status.bFrameBufferDrawnByTriangles )
1542
gRenderTextureInfos[m_curRenderTextureIndex].isUsed = false;
1543
TXTRBUF_DUMP(TRACE2("Delete txtr buf %d at %08X, it is never rendered", m_curRenderTextureIndex, gRenderTextureInfos[m_curRenderTextureIndex].CI_Info.dwAddr ));
1544
SAFE_DELETE(gRenderTextureInfos[m_curRenderTextureIndex].pRenderTexture);
1548
uint32 FrameBufferManager::ComputeRenderTextureCRCInRDRAM(int infoIdx)
1550
if( infoIdx >= numOfTxtBufInfos || infoIdx < 0 || !gRenderTextureInfos[infoIdx].isUsed )
1553
RenderTextureInfo &info = gRenderTextureInfos[infoIdx];
1554
uint32 height = info.knownHeight ? info.N64Height : info.maxUsedHeight;
1555
uint8 *pAddr = (uint8*)(g_pRDRAMu8+info.CI_Info.dwAddr);
1556
uint32 pitch = (info.N64Width << info.CI_Info.dwSize ) >> 1;
1558
return CalculateRDRAMCRC(pAddr, 0, 0, info.N64Width, height, info.CI_Info.dwSize, pitch);
1561
//activates texture buffer for drawing
1562
void FrameBufferManager::ActiveTextureBuffer(void)
1564
status.bCIBufferIsRendered = true;
1566
if( status.bHandleN64RenderTexture )
1568
// Checking against previous render_texture infos
1571
//uint32 memsize = ((newRenderTextureInfo.N64Height*newRenderTextureInfo.N64Width)>>1)<<newRenderTextureInfo.CI_Info.dwSize;
1573
matchidx = CheckRenderTexturesWithNewCI(g_CI,newRenderTextureInfo.N64Height,true);
1578
// Reuse the matched slot
1579
idxToUse = matchidx;
1583
idxToUse = FindASlot();
1586
if( gRenderTextureInfos[idxToUse].pRenderTexture == NULL || matchidx < 0 )
1588
int w = newRenderTextureInfo.bufferWidth;
1589
if( newRenderTextureInfo.knownHeight == RDP_SETSCISSOR && newRenderTextureInfo.CI_Info.dwAddr == g_ZI.dwAddr )
1591
w = gRDP.scissor.right;
1594
gRenderTextureInfos[idxToUse].pRenderTexture =
1595
new COGLRenderTexture(w, newRenderTextureInfo.bufferHeight, &gRenderTextureInfos[idxToUse], AS_RENDER_TARGET);
1598
// Need to set all variables for gRenderTextureInfos[idxToUse]
1599
CRenderTexture *pRenderTexture = gRenderTextureInfos[idxToUse].pRenderTexture;
1600
memcpy(&gRenderTextureInfos[idxToUse], &newRenderTextureInfo, sizeof(RenderTextureInfo) );
1601
gRenderTextureInfos[idxToUse].pRenderTexture = pRenderTexture;
1602
gRenderTextureInfos[idxToUse].isUsed = true;
1603
gRenderTextureInfos[idxToUse].txtEntry.pTexture = pRenderTexture->m_pTexture;
1604
gRenderTextureInfos[idxToUse].txtEntry.txtrBufIdx = idxToUse+1;
1606
g_pRenderTextureInfo = &gRenderTextureInfos[idxToUse];
1608
// Active the render_texture
1609
if( m_curRenderTextureIndex >= 0 && gRenderTextureInfos[m_curRenderTextureIndex].isUsed && gRenderTextureInfos[m_curRenderTextureIndex].pRenderTexture )
1611
gRenderTextureInfos[m_curRenderTextureIndex].pRenderTexture->SetAsRenderTarget(false);
1612
m_isRenderingToTexture = false;
1615
if( gRenderTextureInfos[idxToUse].pRenderTexture->SetAsRenderTarget(true) )
1617
m_isRenderingToTexture = true;
1619
//Clear(CLEAR_COLOR_AND_DEPTH_BUFFER,0x80808080,1.0f);
1620
if( frameBufferOptions.bFillRectNextTextureBuffer )
1621
CGraphicsContext::g_pGraphicsContext->Clear(CLEAR_COLOR_BUFFER,gRDP.fillColor,1.0f);
1622
else if( options.enableHackForGames == HACK_FOR_MARIO_TENNIS && g_pRenderTextureInfo->N64Width > 64 && g_pRenderTextureInfo->N64Width < 300 )
1624
CGraphicsContext::g_pGraphicsContext->Clear(CLEAR_COLOR_BUFFER,0,1.0f);
1626
else if( options.enableHackForGames == HACK_FOR_MARIO_TENNIS && g_pRenderTextureInfo->N64Width < 64 && g_pRenderTextureInfo->N64Width > 32 )
1628
CGraphicsContext::g_pGraphicsContext->Clear(CLEAR_COLOR_BUFFER,0,1.0f);
1631
m_curRenderTextureIndex = idxToUse;
1633
status.bDirectWriteIntoRDRAM = false;
1635
//SetScreenMult(1, 1);
1636
SetScreenMult(gRenderTextureInfos[m_curRenderTextureIndex].scaleX, gRenderTextureInfos[m_curRenderTextureIndex].scaleY);
1637
CRender::g_pRender->UpdateClipRectangle();
1639
// If needed, draw RDRAM into the render_texture
1640
//if( frameBufferOptions.bLoadRDRAMIntoRenderTexture )
1642
// CRender::GetRender()->LoadTxtrBufFromRDRAM();
1647
if( CDeviceBuilder::m_deviceGeneralType == DIRECTX_DEVICE )
1649
TRACE1("Error to set Render Target: %d", idxToUse);
1650
TRACE1("Addr = %08X", gRenderTextureInfos[idxToUse].CI_Info.dwAddr);
1651
TRACE2("Width = %d, Height=%d", gRenderTextureInfos[idxToUse].N64Width, gRenderTextureInfos[idxToUse].N64Height);
1656
TXTRBUF_DUMP(TRACE2("Rendering to render_texture %d, addr=%08X", idxToUse, g_CI.dwAddr));
1657
DEBUGGER_PAUSE_AND_DUMP_NO_UPDATE(NEXT_RENDER_TEXTURE,
1658
{DebuggerAppendMsg("Paused after activating render_texture:\nAddr: 0x%08x, Fmt: %s Size: %s Width: %d, Height:%d",
1659
g_CI.dwAddr, pszImgFormat[g_CI.dwFormat], pszImgSize[g_CI.dwSize], g_CI.dwWidth, g_pRenderTextureInfo->N64Height);});
1663
UpdateRecentCIAddr(g_CI);
1664
CheckRenderTexturesWithNewCI(g_CI,gRDP.scissor.bottom,false);
1668
#define SAVE_CI {g_CI.dwAddr = newCI.dwAddr;g_CI.dwFormat = newCI.dwFormat;g_CI.dwSize = newCI.dwSize;g_CI.dwWidth = newCI.dwWidth;g_CI.bpl=newCI.bpl;}
1670
//sets CI address for framebuffer copies
1671
void FrameBufferManager::Set_CI_addr(SetImgInfo &newCI)
1673
bool wasDrawingTextureBuffer = status.bN64IsDrawingTextureBuffer;
1674
status.bN64IsDrawingTextureBuffer = ( newCI.dwSize != TXT_SIZE_16b || newCI.dwFormat != TXT_FMT_RGBA || newCI.dwWidth < 200 || ( newCI.dwAddr != g_ZI.dwAddr && newCI.dwWidth != 512 && !g_pFrameBufferManager->HasAddrBeenDisplayed(newCI.dwAddr, newCI.dwWidth)) );
1675
status.bN64FrameBufferIsUsed = status.bN64IsDrawingTextureBuffer;
1677
if( !wasDrawingTextureBuffer && g_CI.dwAddr == g_ZI.dwAddr && status.bCIBufferIsRendered )
1679
TXTRBUF_DUMP(TRACE0("ZI is rendered"));
1681
if( options.enableHackForGames != HACK_FOR_CONKER && g_uRecentCIInfoPtrs[0]->bCopied == false )
1683
// Conker is not actually using a backbuffer
1684
g_pFrameBufferManager->UpdateRecentCIAddr(g_CI);
1685
if( status.leftRendered != -1 && status.topRendered != -1 && status.rightRendered != -1 && status.bottomRendered != -1 )
1687
RECT rect={status.leftRendered,status.topRendered,status.rightRendered,status.bottomRendered};
1688
g_pFrameBufferManager->SaveBackBuffer(0,&rect);
1692
g_pFrameBufferManager->SaveBackBuffer(0,NULL);
1697
frameBufferOptions.bFillRectNextTextureBuffer = false;
1698
if( g_CI.dwAddr == newCI.dwAddr && status.bHandleN64RenderTexture && (g_CI.dwFormat != newCI.dwFormat || g_CI.dwSize != newCI.dwSize || g_CI.dwWidth != newCI.dwWidth ) )
1700
// Mario Tennis player shadow
1701
g_pFrameBufferManager->CloseRenderTexture(true);
1702
if( options.enableHackForGames == HACK_FOR_MARIO_TENNIS )
1703
frameBufferOptions.bFillRectNextTextureBuffer = true; // Hack for Mario Tennis
1708
if( g_CI.dwAddr == g_ZI.dwAddr && !status.bN64IsDrawingTextureBuffer )
1710
if( g_pFrameBufferManager->IsDIaRenderTexture() )
1712
status.bN64IsDrawingTextureBuffer = true;
1713
status.bN64FrameBufferIsUsed = status.bN64IsDrawingTextureBuffer;
1717
status.bCIBufferIsRendered = false;
1718
status.leftRendered = status.topRendered = status.rightRendered = status.bottomRendered = -1;
1720
if( currentRomOptions.screenUpdateSetting==SCREEN_UPDATE_AT_CI_CHANGE && !status.bN64IsDrawingTextureBuffer )
1722
if( status.curRenderBuffer == 0 )
1724
status.curRenderBuffer = g_CI.dwAddr;
1726
else if( status.curRenderBuffer != g_CI.dwAddr )
1728
status.curDisplayBuffer = status.curRenderBuffer;
1729
CGraphicsContext::Get()->UpdateFrame();
1730
status.curRenderBuffer = g_CI.dwAddr;
1731
DEBUGGER_IF_DUMP(pauseAtNext,{DebuggerAppendMsg("Screen Update because CI change to %08X, Display Buf=%08X", status.curRenderBuffer, status.curDisplayBuffer);});
1735
if( frameBufferOptions.bAtEachFrameUpdate && !status.bHandleN64RenderTexture )
1737
if( status.curRenderBuffer != g_CI.dwAddr )
1739
if( status.gDlistCount%(currentRomOptions.N64FrameBufferWriteBackControl+1) == 0 )
1741
g_pFrameBufferManager->StoreBackBufferToRDRAM(status.curRenderBuffer,
1742
newCI.dwFormat, newCI.dwSize, windowSetting.uViWidth, windowSetting.uViHeight,
1743
windowSetting.uDisplayWidth, windowSetting.uDisplayHeight);
1747
//status.curDisplayBuffer = status.curRenderBuffer;
1748
status.curRenderBuffer = g_CI.dwAddr;
1752
switch( currentRomOptions.N64RenderToTextureEmuType )
1755
if( status.bHandleN64RenderTexture )
1756
g_pFrameBufferManager->CloseRenderTexture(false);
1757
status.bHandleN64RenderTexture = false; // Don't handle N64 render_texture stuffs
1758
if( !status.bN64IsDrawingTextureBuffer )
1759
g_pFrameBufferManager->UpdateRecentCIAddr(g_CI);
1762
if( status.bHandleN64RenderTexture )
1765
if( pauseAtNext && eventToPause == NEXT_RENDER_TEXTURE )
1768
eventToPause = NEXT_RENDER_TEXTURE;
1771
g_pFrameBufferManager->CloseRenderTexture(true);
1774
status.bHandleN64RenderTexture = status.bN64IsDrawingTextureBuffer;
1775
if( status.bHandleN64RenderTexture )
1777
if( options.enableHackForGames != HACK_FOR_BANJO_TOOIE )
1779
g_pFrameBufferManager->SetRenderTexture();
1785
if( g_CI.dwWidth == 512 && pauseAtNext && (eventToPause==NEXT_OBJ_BG || eventToPause==NEXT_SET_CIMG) )
1787
DebuggerAppendMsg("Warning SetCImg: new Addr=0x%08X, fmt:%s size=%sb, Width=%d\n",
1788
g_CI.dwAddr, pszImgFormat[newCI.dwFormat], pszImgSize[newCI.dwSize], newCI.dwWidth);
1791
//g_pFrameBufferManager->UpdateRecentCIAddr(g_CI); // Delay this until the CI buffer is actally drawn
1796
TXTRBUF_DUMP(TRACE4("SetCImg : Addr=0x%08X, Fmt:%s-%sb, Width=%d\n",
1797
g_CI.dwAddr, pszImgFormat[newCI.dwFormat], pszImgSize[newCI.dwSize], newCI.dwWidth));
1799
DEBUGGER_PAUSE_AND_DUMP_NO_UPDATE(NEXT_SET_CIMG,
1801
DebuggerAppendMsg("Pause after SetCImg: Addr=0x%08X, Fmt:%s-%sb, Width=%d\n",
1802
g_CI.dwAddr, pszImgFormat[newCI.dwFormat], pszImgSize[newCI.dwSize], newCI.dwWidth);
1808
void FrameBufferManager::StoreRenderTextureToRDRAM(int infoIdx)
1810
if( !frameBufferOptions.bRenderTextureWriteBack ) return;
1813
infoIdx = m_lastTextureBufferIndex;
1815
if( !gRenderTextureInfos[infoIdx].pRenderTexture )
1818
if( gRenderTextureInfos[infoIdx].pRenderTexture->IsBeingRendered() )
1820
TXTRBUF_DUMP(TRACE1("Cannot SaveTextureBuffer %d, it is being rendered", infoIdx));
1824
gRenderTextureInfos[infoIdx].pRenderTexture->StoreToRDRAM(infoIdx);
1828
//does FB copy to N64 RDAM structure
1829
void FrameBufferManager::CopyBufferToRDRAM(uint32 addr, uint32 fmt, uint32 siz, uint32 width, uint32 height, uint32 bufWidth, uint32 bufHeight, uint32 startaddr, uint32 memsize, uint32 pitch, TextureFmt bufFmt, void *buffer, uint32 bufPitch)
1832
if( startaddr == 0xFFFFFFFF ) startaddr = addr;
1834
startline = (startaddr-addr)/siz/pitch;
1835
if( startline >= height )
1837
//TRACE0("Warning: check me");
1841
uint32 endline = height;
1842
if( memsize != 0xFFFFFFFF )
1844
endline = (startaddr+memsize-addr)/siz;
1845
if( endline % pitch == 0 )
1848
endline = endline/pitch+1;
1850
if( endline > height )
1855
if( memsize != 0xFFFFFFFF )
1857
TXTRBUF_DUMP(DebuggerAppendMsg("Start at: 0x%X, from line %d to %d", startaddr-addr, startline, endline););
1864
float ratio = bufWidth/(float)width;
1865
for( uint32 j=0; j<width; j++ )
1873
if( siz == TXT_SIZE_16b )
1875
uint16 *frameBufferBase = (uint16*)(g_pRDRAMu8+addr);
1877
if( bufFmt==TEXTURE_FMT_A8R8G8B8 )
1880
float ratio = bufHeight/(float)height;
1882
for( uint32 i=startline; i<endline; i++ )
1884
sy0 = int(i*ratio+0.5);
1886
uint16 *pD = frameBufferBase + i * pitch;
1887
uint8 *pS0 = (uint8 *)buffer + sy0 * bufPitch;
1889
for( uint32 j=0; j<width; j++ )
1892
uint8 r = pS0[indexes[j]+2];
1893
uint8 g = pS0[indexes[j]+1];
1894
uint8 b = pS0[indexes[j]+0];
1895
uint8 a = pS0[indexes[j]+3];
1898
*(pD+(j^1)) = ConvertRGBATo555( r, g, b, a);
1905
TRACE1("Copy %sb FrameBuffer to Rdram, not implemented", pszImgSize[siz]);
1908
else if( siz == TXT_SIZE_8b && fmt == TXT_FMT_CI )
1910
uint8 *frameBufferBase = (uint8*)(g_pRDRAMu8+addr);
1912
if( bufFmt==TEXTURE_FMT_A8R8G8B8 )
1915
InitTlutReverseLookup();
1917
for( uint32 i=startline; i<endline; i++ )
1919
uint8 *pD = frameBufferBase + i * width;
1920
uint8 *pS = (uint8 *)buffer + i*bufHeight/height * bufPitch;
1921
for( uint32 j=0; j<width; j++ )
1923
int pos = 4*(j*bufWidth/width);
1924
tempword = ConvertRGBATo555((pS[pos+2]), // Red
1927
(pS[pos+3])); // Alpha
1928
//*pD = CIFindIndex(tempword);
1929
*(pD+(j^3)) = RevTlutTable[tempword];
1935
TRACE1("Copy %sb FrameBuffer to Rdram, not implemented", pszImgSize[siz]);
1937
DEBUGGER_IF_DUMP(pauseAtNext,{DebuggerAppendMsg("Copy %sb FrameBuffer to Rdram", pszImgSize[siz]);});
1939
else if( siz == TXT_SIZE_8b && fmt == TXT_FMT_I )
1941
uint8 *frameBufferBase = (uint8*)(g_pRDRAMu8+addr);
1943
if( bufFmt==TEXTURE_FMT_A8R8G8B8 )
1946
float ratio = bufHeight/(float)height;
1948
for( uint32 i=startline; i<endline; i++ )
1950
sy0 = int(i*ratio+0.5);
1952
uint8 *pD = frameBufferBase + i * width;
1953
uint8 *pS0 = (uint8 *)buffer + sy0 * bufPitch;
1955
for( uint32 j=0; j<width; j++ )
1958
uint32 r = pS0[indexes[j]+2];
1959
uint32 g = pS0[indexes[j]+1];
1960
uint32 b = pS0[indexes[j]+0];
1963
*(pD+(j^3)) = (uint8)((r+b+g)/3);
1970
//DebuggerAppendMsg("Copy %sb FrameBuffer to Rdram, not implemented", pszImgSize[siz]);
1972
DEBUGGER_IF_DUMP(pauseAtNext,{DebuggerAppendMsg("Copy %sb FrameBuffer to Rdram", pszImgSize[siz]);});
1978
void FrameBufferManager::DisplayRenderTexture(int infoIdx)
1981
infoIdx = m_lastTextureBufferIndex;
1983
if( gRenderTextureInfos[infoIdx].pRenderTexture )
1985
if( gRenderTextureInfos[infoIdx].pRenderTexture->IsBeingRendered() )
1987
TRACE1("Render texture %d is being rendered, cannot display", infoIdx);
1991
TRACE1("Texture buffer %d:", infoIdx);
1992
TRACE1("Addr=%08X", gRenderTextureInfos[infoIdx].CI_Info.dwAddr);
1993
TRACE2("Width=%d, Created Height=%d", gRenderTextureInfos[infoIdx].N64Width,gRenderTextureInfos[infoIdx].N64Height);
1994
TRACE2("Fmt=%d, Size=%d", gRenderTextureInfos[infoIdx].CI_Info.dwFormat,gRenderTextureInfos[infoIdx].CI_Info.dwSize);
1999
TRACE1("Texture buffer %d is not used", infoIdx);
2007
//this is the core to the current framebuffer code
2008
//We need to save backbuffer when changed by framebuffer
2009
//so that we can use it for framebuffer effects
2010
void FrameBufferManager::SaveBackBuffer(int ciInfoIdx, RECT* pSrcRect, bool forceToSaveToRDRAM)
2012
RecentCIInfo &ciInfo = *g_uRecentCIInfoPtrs[ciInfoIdx];
2014
if( ciInfoIdx == 1 ) // to save the current front buffer
2016
CGraphicsContext::g_pGraphicsContext->UpdateFrame(true);
2019
if( frameBufferOptions.bWriteBackBufToRDRAM || forceToSaveToRDRAM )
2021
uint32 width = ciInfo.dwWidth;
2022
uint32 height = ciInfo.dwHeight;
2024
if( ciInfo.dwWidth == *g_GraphicsInfo.VI_WIDTH_REG && ciInfo.dwWidth != windowSetting.uViWidth )
2026
width = windowSetting.uViWidth;
2027
height = windowSetting.uViHeight;
2030
StoreBackBufferToRDRAM( ciInfo.dwAddr, ciInfo.dwFormat, ciInfo.dwSize, width, height,
2031
windowSetting.uDisplayWidth, windowSetting.uDisplayHeight);
2033
g_uRecentCIInfoPtrs[ciInfoIdx]->bCopied = true;
2034
if( ciInfoIdx == 1 ) // to save the current front buffer
2036
CGraphicsContext::g_pGraphicsContext->UpdateFrame(true);
2042
SetImgInfo tempinfo;
2043
tempinfo.dwAddr = ciInfo.dwAddr;
2044
tempinfo.dwFormat = ciInfo.dwFormat;
2045
tempinfo.dwSize = ciInfo.dwSize;
2046
tempinfo.dwWidth = ciInfo.dwWidth;
2048
int idx = SetBackBufferAsRenderTexture(tempinfo, ciInfoIdx);
2050
CopyBackBufferToRenderTexture(idx, ciInfo, pSrcRect);
2052
gRenderTextureInfos[idx].crcCheckedAtFrame = status.gDlistCount;
2053
gRenderTextureInfos[idx].crcInRDRAM = ComputeRenderTextureCRCInRDRAM(idx);
2055
DEBUGGER_IF_DUMP((logTextureBuffer&&pSrcRect==NULL),TRACE1("SaveBackBuffer at 0x%08X", ciInfo.dwAddr));
2056
DEBUGGER_IF_DUMP((logTextureBuffer&&pSrcRect),TRACE5("SaveBackBuffer at 0x%08X, {%d,%d -%d,%d)", ciInfo.dwAddr,
2057
pSrcRect->left,pSrcRect->top,pSrcRect->right,pSrcRect->bottom));
2058
DEBUGGER_IF_DUMP(( pauseAtNext && eventToPause == NEXT_RENDER_TEXTURE),{g_pFrameBufferManager->DisplayRenderTexture(idx);});
2060
g_uRecentCIInfoPtrs[ciInfoIdx]->bCopied = true;