📄 surf.cpp
字号:
/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
Copyright (c) 1995-1998 Microsoft Corporation
Copyright (c) 1999-2002 Silicon Motion, Inc.
Module Name: surface allocation/manipulation/free routines
Abstract:
Functions:
Notes:
--*/
#include "precomp.h"
extern BOOL g_bSaveSurface;
#ifdef DD_ENABLE
void SMI::SetVisibleSurface(GPESurf *pSurf, BOOL bWaitForVBlank)
#else
void SMI::SetVisibleSurface(GPESurf *pSurf)
#endif
{
#ifndef DD_ENABLE
BOOL bWaitForVBlank = FALSE;
#endif
#ifdef CMDLIST
VALIDATE_SLOT(cmd_ptr, 4);
INSERTCMD_LOADREG_D(cmd_ptr,
REG(PANEL_FB_ADDRESS),
FIELD_SET(0, PANEL_FB_ADDRESS, STATUS, PENDING) |
FIELD_SET(0, PANEL_FB_ADDRESS, EXT, LOCAL) |
FIELD_VALUE(0, PANEL_FB_ADDRESS, ADDRESS, pSurf->OffsetInVideoMemory()) |
0);
INSERTCMD_FINISH(cmd_ptr, 0);
STOP_CI();
WAIT_CI_STOP();
INSERTCMD_NOP(last_finish_ptr);
last_finish_ptr = cmd_ptr - CMD_STRIDE_DWORD;
FLUSH_CMD();
START_CI("CMDList SetVisibleSurface\r\n");
#else //------- CMDLIST --------
POKE_32(PANEL_FB_ADDRESS,
FIELD_SET(0, PANEL_FB_ADDRESS, STATUS, PENDING) |
FIELD_VALUE(0, PANEL_FB_ADDRESS, EXT, m_SMISettings.m_bUMA) |
FIELD_VALUE(0, PANEL_FB_ADDRESS, ADDRESS, VgxSurfAddr(pSurf->OffsetInVideoMemory())) |
0);
#ifdef x86
if (bWaitForVBlank)
{
while (FIELD_GET(PEEK_32(PANEL_FB_ADDRESS), PANEL_FB_ADDRESS, STATUS)
== PANEL_FB_ADDRESS_STATUS_PENDING);
}
#endif
#endif //CMDLIST
}
#ifdef DD_ENABLE
SCODE SMI::AllocSurface(GPESurf **ppSurf, int width, int height, EGPEFormat format, int surfaceFlags)
{
return AllocSurface((DDGPESurf**)ppSurf,
width,
height,
format,
EGPEFormatToEDDGPEPixelFormat[format],
surfaceFlags);
}
#endif
#ifdef DD_ENABLE
SCODE SMI::AllocSurface(DDGPESurf **ppSurf, int width, int height,
EGPEFormat format, EDDGPEPixelFormat pixelFormat, int surfaceFlags)
#else
SCODE SMI::AllocSurface(GPESurf **ppSurf, int width, int height,
EGPEFormat format, int surfaceFlags)
#endif
{
DWORD bpp = EGPEFormatToBpp[format];
#ifdef DD_ENABLE
LONG align = m_nSurfaceBitsAlign / 8;
DWORD alignedWidth = ((width + align - 1) & (- align));
DWORD nSurfaceSize = (bpp * (alignedWidth * height)) / 8;
DWORD stride = ((alignedWidth * bpp) / 8);
#endif
#if SMI_SURFACEPATCH
// Ezex Patch to speed up video overlay playback by forcing system memory allocation
if ((surfaceFlags & GPE_PREFER_VIDEO_MEMORY) &&
(nSurfaceSize > SMI_MAXPREFERSURFACESIZE)
)
{
// Force allocation of secondary surface to system memory
}
else
#endif
if ((surfaceFlags & GPE_REQUIRE_VIDEO_MEMORY) ||
((surfaceFlags & GPE_PREFER_VIDEO_MEMORY) && (format == m_pMode->format))
)
{
//if (!(format == m_pMode->format))
// return E_INVALIDARG;
// Attempt to allocate from video memory
#ifdef DD_ENABLE
SurfaceHeap *pStack = m_pVideoMemoryHeap->Alloc(nSurfaceSize);
#else
Node2D *pStack = m_p2DVideoMemory->Alloc(width, height);
#endif
if (pStack)
{
#ifdef DD_ENABLE
ULONG offset = pStack->Address();
*ppSurf = new SMISurf(width, alignedWidth, height, offset, m_pLAW + offset, stride,
format, pixelFormat, pStack, this);
#else
ULONG offset = m_nScreenStride * pStack->Top() + (pStack->Left() * EGPEFormatToBpp[format]) / 8;
*ppSurf = new SMISurf(width, height, offset, m_pLAW + offset, m_nScreenStride, format, pStack, this);
#endif
if (!(*ppSurf))
{
pStack->Free();
return E_OUTOFMEMORY;
}
// DEBUGMSG(GPE_ZONE_CREATE, (TEXT("Creating a SMISurf in video memory - ")
// TEXT("EGPEFormat = %d, DDGPEFormat = %d, Offset = 0x%08X, Size = %d\r\n"),
// (int) format, (int) pixelFormat,offset,nSurfaceSize));
return S_OK;
}
if (surfaceFlags & GPE_REQUIRE_VIDEO_MEMORY)
{
#ifdef DD_ENABLE
*ppSurf = (DDGPESurf *)NULL;
#else
*ppSurf = (GPESurf *)NULL;
#endif
return E_OUTOFMEMORY;
}
}
// Allocate from system memory
#ifdef DD_ENABLE
DEBUGMSG(GPE_ZONE_CREATE, (TEXT("Creating a DDGPESurf in system memory - ")
TEXT("EGPEFormat = %d, DDGPEFormat = %d\r\n"),
(int) format, (int) pixelFormat));
*ppSurf = new DDGPESurf(width, height, stride, format, pixelFormat);
#else
DEBUGMSG(GPE_ZONE_TEMP,
(TEXT("Creating a GPESurf in system memory. EGPEFormat = %d\r\n"),
format));
*ppSurf = new GPESurf(width, height, format);
#endif
if (*ppSurf)
{
// check we allocated bits succesfully
if (!((*ppSurf)->Buffer()))
{
delete *ppSurf;
return E_OUTOFMEMORY;
}
}
return S_OK;
}
#ifdef DD_ENABLE
SMISurf::SMISurf(int width, int alignedWidth, int height, ULONG offset, PVOID pBits,
int stride, EGPEFormat format, EDDGPEPixelFormat pixelFormat,
SurfaceHeap *pHeap, SMI *pSMI)
: DDGPESurf(width, height, pBits, stride, format, pixelFormat)
#elif ROTATION_ENABLE
SMISurf::SMISurf(int width, int height, ULONG offset, PVOID pBits, int stride,
EGPEFormat format, Node2D *pNode, SMI *pSMI)
: GPESurfRotate(width, height, pBits, stride, format)
#else // ! DD_ENABLE
SMISurf::SMISurf(int width, int height, ULONG offset, PVOID pBits, int stride,
EGPEFormat format, Node2D *pNode, SMI *pSMI)
: GPESurf(width, height, pBits, stride, format)
#endif // DD_ENABLE
{
#ifdef DD_ENABLE
m_pHeap = pHeap;
m_nAlignedWidth = alignedWidth;
#else // ! DD_ENABLE
m_pNode2D = pNode;
m_nAlignedWidth = stride / (EGPEFormatToBpp[format] / 8);
#endif // DD_ENABLE
m_fInVideoMemory = TRUE;
m_nOffsetInVideoMemory = offset;
m_pSMI = pSMI;
#if SMI_SURFACEDEBUG
#else
if (g_bSaveSurface)
#endif
m_pSMI->m_SMISurfList.Add(this);
}
DWORD SMI::VgxSurfAddr(DWORD dwAddr)
{
if (m_SMISettings.m_bUMA)
return dwAddr + m_SMISettings.m_nUMAOffset;
else
return dwAddr;
}
SMISurf::~SMISurf(void)
{
#ifdef DD_ENABLE
m_pHeap->Free();
#else // ! DD_ENABLE
m_pNode2D->Free();
#endif // DD_ENABLE
m_pSMI->m_SMISurfList.Remove(this);
}
int SMI::FlipInProgress(void)
{
DEBUGMSG(GPE_ZONE_FLIP, (TEXT("SMIVGX::FlipInProgress\r\n")));
return (0);
}
int SMI::SurfaceBusyFlipping(GPESurf *pSurf)
{
DEBUGMSG(GPE_ZONE_FLIP, (TEXT("SMIVGX::SurfaceBusyFlipping\r\n")));
// This implementation could probably cause the tearing in FoxBear
return (0);
}
SMISurfList::SMISurfList(void)
{
m_pSurf = NULL;
m_pSurfSystemBuffer = NULL;
m_pNext = NULL;
};
SMISurfList::~SMISurfList()
{
};
void SMISurfList::Add(SMISurf *pSurf)
{
ULONG nBufferSize;
SMISurfList *pSurfList = new SMISurfList;
if (pSurfList != NULL)
{
pSurfList->m_pSurf = pSurf;
SMISurfList *pCurrent = this;
while (pCurrent->m_pNext != NULL) pCurrent = pCurrent->m_pNext;
pCurrent->m_pNext = pSurfList;
nBufferSize = pSurf->Stride()*pSurf->Height();
if (g_bSaveSurface)
{
pSurfList->m_pSurfSystemBuffer =
(PUCHAR) VirtualAlloc(NULL, nBufferSize,MEM_COMMIT, PAGE_READWRITE);
if (pSurfList->m_pSurfSystemBuffer == NULL)
DEBUGMSG(GPE_ZONE_WARNING, (TEXT("SMISurfList::Add() - System memory allocation failed!\r\n")));
}
else
pSurfList->m_pSurfSystemBuffer = NULL;
}
else
DEBUGMSG(GPE_ZONE_WARNING, (TEXT("SMISurfList::Add - New SMISurfList allocation failed\r\n")));
};
void SMISurfList::Remove(SMISurf *pSurf)
{
ULONG nBufferSize;
SMISurfList *pCurrent = this;
while ((pCurrent->m_pNext != NULL) && (pCurrent->m_pNext->m_pSurf != pSurf))
pCurrent = pCurrent->m_pNext;
if (pCurrent->m_pNext != NULL)
{
class SMISurfList *pTemp = pCurrent->m_pNext;
pCurrent->m_pNext = pTemp->m_pNext;
nBufferSize = pSurf->Stride()*pSurf->Height();
if (pTemp->m_pSurfSystemBuffer != NULL)
{
if (!VirtualFree(pTemp->m_pSurfSystemBuffer, nBufferSize,MEM_DECOMMIT))
DEBUGMSG(GPE_ZONE_WARNING, (TEXT("SMISurfList::Remove() - System memory (%X) decommit failed!\r\n"), pTemp->m_pSurfSystemBuffer));
if (!VirtualFree(pTemp->m_pSurfSystemBuffer, 0,MEM_RELEASE))
DEBUGMSG(GPE_ZONE_WARNING, (TEXT("SMISurfList::Remove() - System memory (%X) release failed!\r\n"), pTemp->m_pSurfSystemBuffer));
}
delete pTemp;
}
};
#if SMI_SURFACEDEBUG
void SMISurfList::PrintList()
{
SMISurfList *pCurrent = this;
RETAILMSG(1, (TEXT("SMISurfList -> Printout = \r\n")));
int nTotal = 0;
while (pCurrent->m_pNext != NULL)
{
pCurrent = pCurrent->m_pNext;
int nSize = (pCurrent->m_pSurf->Stride()*pCurrent->m_pSurf->Height());
nTotal+=nSize;
RETAILMSG(1, (TEXT("Offset=0x%08X AlignWidth=%d Height=%d Bpp=%d Stride=%d Pixelformat=0x%08X Size=%d Address=0x%08X\r\n"),
pCurrent->m_pSurf->OffsetInVideoMemory(),
pCurrent->m_pSurf->AlignedWidth(),
pCurrent->m_pSurf->Height(),
pCurrent->m_pSurf->Bpp(),
pCurrent->m_pSurf->Stride(),
pCurrent->m_pSurf->PixelFormat(),
pCurrent->m_pSurf,
nSize
));
}
RETAILMSG(1, (TEXT("Total=%d \r\n"), nTotal));
};
#endif
void SMISurfList::Save()
{
SMISurfList *pCurrent = this;
ULONG nBufferSize;
SMISurf *pSurf;
DEBUGMSG(GPE_ZONE_INIT, (TEXT("SMISurfList -> Saving... \r\n")));
while (pCurrent->m_pNext != NULL)
{
pCurrent = pCurrent->m_pNext;
pSurf = pCurrent->m_pSurf;
// Allocate memory to save video buffer
nBufferSize = pSurf->Stride()*pSurf->Height();
DEBUGMSG(GPE_ZONE_INIT, (TEXT("%d[S%d,W%d,H%d,F%d,0x%08X,0x%08X]\r\n "), nBufferSize,pSurf->Stride(),
pSurf->Width(),pSurf->Height(),
EGPEFormatToBpp[pSurf->Format()],pSurf->Buffer(),pSurf->OffsetInVideoMemory()));
if (pCurrent->m_pSurfSystemBuffer != NULL)
memcpy(pCurrent->m_pSurfSystemBuffer, pSurf->Buffer(), nBufferSize);
else
DEBUGMSG(GPE_ZONE_WARNING, (TEXT("SMISurfList::Save() - Surface not saved!\r\n")));
}
};
void SMISurfList::Restore()
{
SMISurfList *pCurrent = this;
ULONG nBufferSize;
SMISurf *pSurf;
DEBUGMSG(GPE_ZONE_INIT, (TEXT("SMISurfList -> Restoring... \r\n")));
while (pCurrent->m_pNext != NULL)
{
pCurrent = pCurrent->m_pNext;
pSurf = pCurrent->m_pSurf;
// Restore video buffer
nBufferSize = pSurf->Stride()*pSurf->Height();
DEBUGMSG(GPE_ZONE_INIT, (TEXT("%d \r\n"), nBufferSize));
if (pCurrent->m_pSurfSystemBuffer != NULL)
{
memcpy(pSurf->Buffer(), pCurrent->m_pSurfSystemBuffer, nBufferSize);
}
}
};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -