⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 surf.cpp

📁 SM501基于ARMV4/ARMV4I平台
💻 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 + -