📄 surf.cpp
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
/*++
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.
Module Name: surface allocation/manipulation/free routines
Abstract:
Functions:
Notes:
--*/
#include "precomp.h"
#define ALIGN(x, align) (((x) + ((align) - 1)) & ~((align) - 1))
#define PIXEL_ALIGN_BPP16 2
#define PIXEL_ALIGN_YV12 16
static DWORD dwSurfaceCount = 0;
// This method is called for all normal surface allocations from ddgpe and gpe
SCODE
S3C6410Disp::AllocSurface(
GPESurf **ppSurf,
int width,
int height,
EGPEFormat format,
int surfaceFlags)
{
RETAILMSG(0, (TEXT("[AS] %dx%d FMT:%d F:%08x\n\r"), width, height, format, surfaceFlags));
// This method is only for surface in system memory
if (surfaceFlags & GPE_REQUIRE_VIDEO_MEMORY)
{
DISPDRV_ERR((_T("[DISPDRV:ERR] AllocSurface() : Can not allocate GPE_REQUIRE_VIDEO_MEMORY Surface in system memory\n\r")));
return E_OUTOFMEMORY;
}
#if G2D_ACCELERATE
#if USE_PACSURF
/// Only Support 16bpp, 24bpp, 32bpp
if( ( (format == gpe16Bpp || format == gpeDeviceCompatible)
#if G2D_BLT_OPTIMIZE
&& (width*height*2 > PAC_ALLOCATION_BOUNDARY)
#endif //< G2D_BLT_OPTIMIZE
)
||
( (format == gpe24Bpp || format == gpe32Bpp)
#if G2D_BLT_OPTIMIZE
&& (width*height*4 > PAC_ALLOCATION_BOUNDARY )
#endif //< G2D_BLT_OPTIMIZE
)
)
{
/// try to allocate physically linear address
*ppSurf = new PACSurf(width, height, format);
if (*ppSurf == NULL)
{
DISPDRV_ERR((_T("[DISPDRV:ERR] AllocSurface() : PACSurface allocate Failed -> Try to allocate Normal GPE Surface\n\r")));
}
else if ((*ppSurf)->Buffer() == NULL)
{
delete *ppSurf;
*ppSurf = NULL;
DISPDRV_ERR((_T("[DISPDRV:ERR] AllocSurface() : PACSurface Buffer is NULL -> Try to allocate Normal GPE Surface\n\r")));
}
else /// PAC Allocation succeeded.
{
RETAILMSG(0,(_T("[DISPDRV] AllocSurface() : PACSurf() Allocated in System Memory\n\r")));
return S_OK;
}
}
#endif //< USE_PACSURF
#endif //< G2D_ACCELERATE
/// if allocation is failed or boundary condition is not met, just create GPESurf in normal system memory that can be non-linear physically.
// Allocate surface from system memory
*ppSurf = new GPESurf(width, height, format);
if (*ppSurf != NULL)
{
if (((*ppSurf)->Buffer()) == NULL)
{
DISPDRV_ERR((_T("[DISPDRV:ERR] AllocSurface() : Surface Buffer is NULL\n\r")));
delete *ppSurf;
return E_OUTOFMEMORY;
}
else
{
RETAILMSG(0,(_T("[DISPDRV] AllocSurface() : GPESurf() Allocated in System Memory\n\r")));
return S_OK;
}
}
DISPDRV_ERR((_T("[DISPDRV:ERR] AllocSurface() : Surface allocate Failed\n\r")));
return E_OUTOFMEMORY;
}
// This method is used for DirectDraw enabled surfaces
SCODE
S3C6410Disp::AllocSurface(
DDGPESurf **ppSurf,
int width,
int height,
EGPEFormat format,
EDDGPEPixelFormat pixelFormat,
int surfaceFlags)
{
DISPDRV_MSG((_T("[DISPDRV] S3C6410Disp::AllocSurface(%d, %d, %d, %d, 0x%08x)\n\r"), width, height, format, pixelFormat, surfaceFlags));
unsigned int bpp;
unsigned int stride;
unsigned int align_width;
if (pixelFormat == ddgpePixelFormat_I420 || pixelFormat == ddgpePixelFormat_YV12)
{
// in this case, stride can't be calculated. because of planar format (non-interleaved...)
bpp = 12;
align_width = ALIGN(width, 16);
}
else if (pixelFormat == ddgpePixelFormat_YVYU || pixelFormat == ddgpePixelFormat_VYUY)
{
bpp = 16;
align_width = width;
}
else
{
bpp = EGPEFormatToBpp[format];
align_width = width;
}
//DISPDRV_ERR((_T("[AS] %dx%d %dbpp FMT:%d F:%08x\n\r"), width, height, bpp, format, surfaceFlags));
//--------------------------------------
// Try to allocate surface from video memory
//--------------------------------------
// stride are all 32bit aligned for Video Memory
stride = ((bpp * align_width + 31) >> 5) << 2;
if ((surfaceFlags & GPE_REQUIRE_VIDEO_MEMORY)
|| (surfaceFlags & GPE_BACK_BUFFER)
//|| ((surfaceFlags & GPE_PREFER_VIDEO_MEMORY) && (format == m_pMode->format)))
|| (surfaceFlags & GPE_PREFER_VIDEO_MEMORY) && (format == m_pMode->format))
{
SCODE rv = AllocSurfaceVideo(ppSurf, width, height, stride, format, pixelFormat);
if (rv == S_OK)
{
return S_OK;
}
else
{
if (surfaceFlags & (GPE_REQUIRE_VIDEO_MEMORY|GPE_BACK_BUFFER))
{
DISPDRV_ERR((_T("[DISPDRV:ERR] AllocSurface() : AllocSurfaceVideo() failed\n\r")));
return E_OUTOFMEMORY;
}
}
}
//--------------------------------------
// Try to allocate surface from system memory
//--------------------------------------
// stride and surface size for system memory surfaces
stride = ((bpp * width + 31) >> 5) << 2;
unsigned int surface_size = stride*height;
// Allocate from system memory
*ppSurf = new DDGPESurf(width, height, stride, format, pixelFormat);
if (*ppSurf) // check we allocated bits succesfully
{
if (!((*ppSurf)->Buffer()))
{
delete *ppSurf;
return E_OUTOFMEMORY;
}
}
return S_OK;
}
SCODE
S3C6410Disp::AllocSurfaceVideo(
DDGPESurf **ppSurf,
int width,
int height,
int stride,
EGPEFormat format,
EDDGPEPixelFormat pixelFormat)
{
// align frame buffer size with 4-word unit
DWORD dwSize = ALIGN(stride * height, 16);
// Try to allocate surface from video memory
SurfaceHeap *pHeap = m_pVideoMemoryHeap->Alloc(dwSize);
if (pHeap != NULL)
{
DWORD dwVideoMemoryOffset = pHeap->Address() - (DWORD)m_VideoMemoryVirtualBase;
DISPDRV_MSG((_T("[DISPDRV] AllocSurfaceVideo() : Allocated PA = 0x%08x\n\r"), dwVideoMemoryOffset+m_VideoMemoryPhysicalBase));
*ppSurf = new S3C6410Surf(width, height, dwVideoMemoryOffset, (PVOID)pHeap->Address(), stride, format, pixelFormat, pHeap);
if (*ppSurf == NULL)
{
DISPDRV_ERR((_T("[DISPDRV:ERR] AllocSurfaceVideo() : Create S3C6410Surf() Failed\n\r")));
pHeap->Free();
return E_OUTOFMEMORY;
}
DISPDRV_MSG((_T("[DISPDRV] AllocSurfaceVideo() : S3C6410Surf() Allocated in Video Memory\n\r")));
return S_OK;
}
else
{
DISPDRV_ERR((_T("[DISPDRV:ERR] AllocSurfaceVideo() : SurfaceHeap Alloc() Failed\n\r")));
*ppSurf = (DDGPESurf *)NULL;
return E_OUTOFMEMORY;
}
}
void S3C6410Disp::SetVisibleSurface(GPESurf *pSurf, BOOL bWaitForVBlank)
{
S3C6410Surf *pDDSurf = (S3C6410Surf *)pSurf;
if(pDDSurf->IsOverlay() == TRUE)
{
m_OverlayCtxt.pPrevSurface = m_OverlayCtxt.pSurface; // Being Flipped Surface
m_OverlayCtxt.pSurface = pDDSurf;
}
else
{
m_pVisibleSurface = pDDSurf;
}
EnterCriticalSection(&m_csDevice);
DevSetVisibleSurface(pDDSurf, bWaitForVBlank);
LeaveCriticalSection(&m_csDevice);
}
//-----------------------------------------------------------------------------
S3C6410Surf::S3C6410Surf(int width, int height, DWORD offset, VOID *pBits, int stride,
EGPEFormat format, EDDGPEPixelFormat pixelFormat, SurfaceHeap *pHeap)
: DDGPESurf(width, height, pBits, stride, format, pixelFormat)
{
dwSurfaceCount++;
m_fInVideoMemory = TRUE;
m_nOffsetInVideoMemory = offset;
m_pSurfHeap = pHeap;
if (pixelFormat == ddgpePixelFormat_I420)
{
m_uiOffsetCb = width*height;
m_uiOffsetCr = m_uiOffsetCb+width*height/4;
}
else if (pixelFormat == ddgpePixelFormat_YV12)
{
m_uiOffsetCr = width*height;
m_uiOffsetCb = m_uiOffsetCr+width*height/4;
}
else
{
m_uiOffsetCr = 0;
m_uiOffsetCb = 0;
}
DISPDRV_INF((_T("[DISPDRV:INF] S3C6410Surf::S3C6410Surf() : @ 0x%08x, %d\n\r"), m_nOffsetInVideoMemory, dwSurfaceCount));
}
S3C6410Surf::~S3C6410Surf()
{
dwSurfaceCount--;
m_pSurfHeap->Free();
DISPDRV_INF((_T("[DISPDRV:INF] S3C6410Surf::~S3C6410Surf() : @ 0x%08x, %d\n\r"), m_nOffsetInVideoMemory, dwSurfaceCount));
}
#if G2D_ACCELERATE
#if USE_PACSURF
/**
* @class PACSurf
* @desc This Surface will try to allocate physically linear address
*
**/
/**
* @fn PACSurf::PACSurf
* @brief try to allocate memory region that is physically linear
* @param GPESurf **ppSurf, INT width, INT height, EGPEFormat format, int surfaceFlags
* @sa GPESurf
* @note This Surface format is compatible to GPESurf
**/
PACSurf::PACSurf(int width, int height, EGPEFormat format)
{
RETAILMSG(0, (_T("[DISPDRV] PACSurf Constructor(%d, %d, %d, 0x%08x)\n\r"), width, height, format));
// Even though "width" and "height" are int's, they must be positive.
ASSERT(width > 0);
ASSERT(height > 0);
memset( &m_Format, 0, sizeof ( m_Format ) );
m_pVirtAddr = NULL;
m_nStrideBytes = 0;
m_eFormat = gpeUndefined;
m_fInVideoMemory = 0;
m_fInUserMemory = FALSE;
m_fOwnsBuffer = 0;
m_nWidth = 0;
m_nHeight = 0;
m_nOffsetInVideoMemory = 0;
m_iRotate = DMDO_0;
m_ScreenWidth = 0;
m_ScreenHeight = 0;
m_BytesPixel = 0;
m_nHandle = NULL;
m_fPLAllocated = 0;
if (width > 0 && height > 0)
{
m_nWidth = width;
m_nHeight = height;
m_eFormat = format;
m_nStrideBytes = ( (EGPEFormatToBpp[ format ] * width + 7 )/ 8 + 3 ) & ~3L;
m_pVirtAddr = (ADDRESS) AllocPhysMem( m_nStrideBytes * height, PAGE_READWRITE, 0, 0,&m_pPhysAddr);
if(m_pVirtAddr != NULL)
{
m_fPLAllocated = 1;
CeSetMemoryAttributes((void *)m_pVirtAddr, (void *)(m_pPhysAddr >>8), m_nStrideBytes * height, PAGE_WRITECOMBINE);
RETAILMSG(0,(TEXT("\nPAC Surf PA Base : 0x%x VA Base : 0x%x STRIDE : %d"), m_pPhysAddr, m_pVirtAddr, m_nStrideBytes));
}
else
{
m_fPLAllocated = 0;
RETAILMSG(0,(TEXT("\nPAC Surf PA Base : 0x%x VA Base : 0x%x STRIDE : %d new unsigned char"), m_pPhysAddr, m_pVirtAddr, m_nStrideBytes));
m_pVirtAddr = (ADDRESS) new unsigned char[ m_nStrideBytes * height ];
}
m_fOwnsBuffer = 1;
m_BytesPixel = EGPEFormatToBpp[m_eFormat] >> 3;
}
}
PACSurf::~PACSurf()
{
if( m_fOwnsBuffer )
{
if(m_fPLAllocated)
{
if(m_pVirtAddr)
{
if( !FreePhysMem((LPVOID)m_pVirtAddr) )
{
RETAILMSG(TRUE,(TEXT("PACSurface deallocation is failed\r\n")));
}
else
{
m_pVirtAddr = NULL;
m_fPLAllocated = 0;
m_fOwnsBuffer = 0;
RETAILMSG(0,(TEXT("PACSurface deallocation is succeeded\r\n")));
}
}
}
else if( m_pVirtAddr )
{
RETAILMSG(TRUE,(TEXT("PACSurface dealloc is trying for non-contigious\r\n")));
delete [] (void *)m_pVirtAddr;
m_pVirtAddr = NULL;
m_fOwnsBuffer = 0;
}
}
}
#endif //< USE_PACSURF
#endif //< G2D_ACCELERATE
//-----------------------------------------------------------------------------
#if 0
//------------------------------------------------------------------------------
//
// Method: WriteBack
//
// Flush surface memory in cache.
//
VOID S3C6410Surf::WriteBack()
{
ASSERT(m_pSurface != NULL);
RETAILMSG(DBGLCD, (TEXT("S3C6410Surf::WriteBack\n")));
if (m_pSurface != NULL)
CacheRangeFlush((VOID*)m_pSurface, m_nStrideBytes * m_nHeight, CACHE_SYNC_WRITEBACK);
}
//------------------------------------------------------------------------------
//
// Method: Discard
//
// Flush and invalidate surface memory in cache.
//
VOID S3C6410Surf::Discard()
{
ASSERT(m_pSurface != NULL);
RETAILMSG(DBGLCD, (TEXT("S3C6410Surf::Discard\n")));
if (m_pSurface != NULL)
CacheRangeFlush((VOID*)m_pSurface, m_nStrideBytes * m_nHeight, CACHE_SYNC_DISCARD);
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -