📄 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-2000 Microsoft Corporation. All rights reserved.
Copyright (c) 2002-2003 BSQUARE Corporation. All rights reserved.
Module Name: surface allocation/manipulation/free routines
Abstract:
Functions:
Notes:
--*/
#include "headers.h"
#ifdef DDRAW_ENABLE
/********************************************************************/
void Au1100LCD::CheckVisibleSurface(void)
{
unsigned long tickCount = GetTickCount();
if( tickCount - m_nTicksAtFlip > m_nTicksPerFrame + 1 )
{
m_pOldVisibleSurface = m_pNewVisibleSurface;
return;
}
DEBUGMSG (GPE_ZONE_FLIP,
(TEXT("Remaining ticks per frame:%d\n\r"), (tickCount-m_nTicksAtFlip)) );
WaitForVBlank();
return;
}
/********************************************************************/
int Au1100LCD::SurfaceBusyFlipping( DDGPESurf *pSurf )
{
if( pSurf == m_pOldVisibleSurface || pSurf == m_pNewVisibleSurface )
CheckVisibleSurface();
return ( pSurf == m_pOldVisibleSurface || pSurf == m_pNewVisibleSurface );
}
/********************************************************************/
int Au1100LCD::FlipInProgress(void)
{
if( m_pOldVisibleSurface != m_pNewVisibleSurface )
CheckVisibleSurface();
else
return 0;
if( m_pOldVisibleSurface != m_pNewVisibleSurface )
{
DEBUGMSG (GPE_ZONE_FLIP, ( TEXT("Flip from surf 0x%08x to 0x%08x in progress\r\n"),
m_pOldVisibleSurface, m_pNewVisibleSurface ));
}
return ( m_pOldVisibleSurface != m_pNewVisibleSurface );
}
void Au1100LCD::VBlankReceived()
{
m_nTicksAtFlip = m_nTicksAtResync = GetTickCount();
m_pOldVisibleSurface = m_pNewVisibleSurface;
}
/********************************************************************/
// wait to get into/out of vertical blank signal
void Au1100LCD::WaitForVBlank()
{
DEBUGMSG(GPE_ZONE_FLIP, (TEXT("WaitForVBlank: wait to be out of vblank\r\n")));
while (InVBlank())
{
DEBUGMSG(GPE_ZONE_FLIP, (TEXT("-")));
};
DEBUGMSG(GPE_ZONE_FLIP, (TEXT("\r\nWaitForVBlank: wait to get into vblank\r\n")));
while (!InVBlank())
{
DEBUGMSG(GPE_ZONE_FLIP, (TEXT("+")));
};
DEBUGMSG(GPE_ZONE_FLIP, (TEXT("\r\n")));
VBlankReceived(); // Reset counters etc
}
/********************************************************************/
// display the surface
void Au1100LCD::SetVisibleSurface( GPESurf *pSurf, BOOL bWaitForVBlank )
{
if (bWaitForVBlank)
WaitForVBlank();
DEBUGMSG (GPE_ZONE_FLIP, (TEXT("SetVisibleSurface after WaitForVBlank\r\n")));
SetVisibleSurface(pSurf);
}
/********************************************************************/
// surface constructor
Au1100LCDSurf::Au1100LCDSurf(
int width,
int height,
unsigned long offset,
void *pBits, // virtual address of allocated bits
int stride,
EGPEFormat format,
EDDGPEPixelFormat pixelFormat,
SurfaceHeap *pNode
)
: DDGPESurf( width, height, pBits, stride, format, pixelFormat )
{
m_pSurfaceHeap = pNode;
m_fInVideoMemory = TRUE;
m_nOffsetInVideoMemory = offset;
}
/********************************************************************/
// surface destructor
Au1100LCDSurf::~Au1100LCDSurf(void)
{
m_pSurfaceHeap->Free();
}
/********************************************************************/
SCODE
Au1100LCD::AllocSurface(
DDGPESurf **ppSurf,
int width,
int height,
EGPEFormat format,
EDDGPEPixelFormat pixelFormat,
int surfaceFlags
)
{
if ( surfaceFlags & (GPE_REQUIRE_VIDEO_MEMORY|GPE_PREFER_VIDEO_MEMORY) )
{
if( ( format != m_pMode->format ) )
{
RETAILMSG(1, (TEXT("Alloc: format != m_pMode->format. \n\r")));
return E_INVALIDARG;
}
// Attempt to allocate from video memory
DWORD ulStride = ((width + 7) & (int) ~0x7) * m_nBytesPerPixel;
DWORD ulHeapSize = ulStride * height;
ULONG memAvail = m_pVideoMemory->Available();
DEBUGMSG(1, (TEXT("Alloc: Vmem avail: 0x%x(%u)\r\n"), memAvail, memAvail));
DEBUGMSG(1, (TEXT("Alloc: width, height, request size (%u,%u,%u)\r\n"), width, height, ulHeapSize));
SurfaceHeap *pNode = m_pVideoMemory->Alloc(ulHeapSize);
if (pNode)
{
ULONG offset = pNode->Address() - (DWORD)m_pLAW;
*ppSurf = new Au1100LCDSurf(width, height, offset, (void *)pNode->Address(), ulStride, format, pixelFormat, pNode);
if (!(*ppSurf))
{
pNode->Free();
return E_OUTOFMEMORY;
}
DEBUGMSG(1, (TEXT("Alloc: ppSurf=%x\r\n"), ppSurf));
DEBUGMSG(1, (TEXT("Alloc: Vmem addr, offs, size: 0x%x, 0x%x, %u\r\n"),
pNode->Address(), offset, pNode->NodeSize()));
return S_OK;
}
if (surfaceFlags & GPE_REQUIRE_VIDEO_MEMORY)
{
*ppSurf = (DDGPESurf *)NULL;
return E_OUTOFMEMORY;
}
} // endif ( surfaceFlags & (GPE_REQUIRE_VIDEO_MEMORY|GPE_PREFER_VIDEO_MEMORY) )
// Allocate from system memory
DEBUGMSG(1, (L"Alloc: Creating a DDGPESurf in system memory."));
DEBUGMSG(1, (L" EGPEFormat %d, width %d, height %d.\r\n",
(int)format, width, height));
*ppSurf = new DDGPESurf(width, height, format);
if (*ppSurf != NULL)
{
// check we allocated bits succesfully
if (((*ppSurf)->Buffer()) == NULL)
{
RETAILMSG(1, (L"Alloc: failed to allocate from system memory\r\n"));
delete *ppSurf;
}
else
{
DEBUGMSG(1, (L"Alloc: *ppSurf->Buffer() %x\r\n", (*ppSurf)->Buffer()));
return S_OK;
}
} // allocation from system memory succeeded
return E_OUTOFMEMORY;
}
#else // not DDRAW_ENABLE
/********************************************************************/
Au1100LCDSurf::Au1100LCDSurf(int width, int height, ULONG offset, PVOID pBits, int stride, EGPEFormat format, Node2D *pNode)
: GPESurf(width, height, pBits, stride, format)
{
m_pNode2D = pNode;
m_fInVideoMemory = TRUE;
m_nOffsetInVideoMemory = offset;
}
/********************************************************************/
Au1100LCDSurf::~Au1100LCDSurf(void)
{
m_pNode2D->Free();
}
#endif DDRAW_ENABLE
/********************************************************************/
SCODE
Au1100LCD::AllocSurface(GPESurf **ppSurf, int width, int height, EGPEFormat format, int surfaceFlags)
{
#ifdef DDRAW_ENABLE
EDDGPEPixelFormat pixelFormat;
GPEModeEx modeInfoEx;
GetModeInfoEx(&modeInfoEx, GetModeId());
// GDI Issue Work-Around
// There is an issue with GDI where if you have a printer device context
// that has the same number of bits per pixel as the display, but
// different bit masks, you will get the display's masks.
// This is because in this function, when we are passed
// the gpeDeviceCompatible constant, it refers to the current device,
// which we have no knowledge of, not the display.
if ( (format == modeInfoEx.modeInfo.format) || (format == gpeDeviceCompatible) )
{
pixelFormat = modeInfoEx.ePixelFormat;
DEBUGMSG(1,
(TEXT("Display Compatible requested: format, ")
TEXT("pixelFormat = 0x%x, 0x%x\r\n"), format, pixelFormat));
}
else
{
pixelFormat = EGPEFormatToEDDGPEPixelFormat[format];
DEBUGMSG(1,
(TEXT("Explicitly requested: format, ")
TEXT("pixelFormat = 0x%x, 0x%x\r\n"), format, pixelFormat));
}
return AllocSurface((DDGPESurf**)ppSurf, width, height, format, pixelFormat, surfaceFlags);
#else // not DDRAW_ENABLE
if ((surfaceFlags & GPE_REQUIRE_VIDEO_MEMORY) || (format == m_pMode->format) && (surfaceFlags & GPE_PREFER_VIDEO_MEMORY))
{
if (!(format == m_pMode->format))
return E_INVALIDARG;
// Attempt to allocate from video memory
Node2D *pNode = m_p2DVideoMemory->Alloc(width, height);
if (pNode)
{
ULONG offset = m_LineSizeInBytes * pNode->Top() + (pNode->Left() * EGPEFormatToBpp[format]) / 8 ;
*ppSurf = new Au1100LCDSurf(width, height, offset, m_pLAW + offset, m_LineSizeInBytes, format, pNode);
if (!(*ppSurf))
{
pNode->Free();
return E_OUTOFMEMORY;
}
return S_OK;
}
if (surfaceFlags & GPE_REQUIRE_VIDEO_MEMORY)
{
*ppSurf = (GPESurf *)NULL;
return E_OUTOFMEMORY;
}
}
if (surfaceFlags & GPE_REQUIRE_VIDEO_MEMORY)
{
*ppSurf = (GPESurf*)NULL;
return E_OUTOFMEMORY;
}
// Allocate from system memory
RETAILMSG(1, (TEXT("Creating a GPESurf in system memory. EGPEFormat = %d\r\n"), (int) format));
*ppSurf = new GPESurf(width, height, format);
if (*ppSurf != NULL)
{
// check we allocated bits succesfully
if (((*ppSurf)->Buffer()) == NULL)
{
delete *ppSurf;
}
else
{
return S_OK;
}
}
return E_OUTOFMEMORY;
#endif DDRAW_ENABLE
}
#if DEBUG
int tickCountValid = 0;
unsigned int lastTickCount;
int frameCount = 0;
#endif
void Au1100LCD::SetVisibleSurface( GPESurf *pSurf )
{
ULONG offset = pSurf->OffsetInVideoMemory();
// display debug message before switching surface
DEBUGMSG (GPE_ZONE_FLIP, (TEXT("SetVisibleSurface: vid mem start=%x, offset=%x\r\n"),
m_pFb, offset ));
m_pNewVisibleSurface = (Au1100LCDSurf *)pSurf;
if (isDSTN(m_mode->mode_control))
{
m_Reg->dmaaddr0 = m_pFb + offset + ((m_words * 4) / 2);
m_Reg->dmaaddr1 = m_pFb + offset;
}
else
{
m_Reg->dmaaddr0 = m_pFb + offset;
}
m_nTicksAtFlip = GetTickCount();
#if DEBUG
if( tickCountValid )
{
frameCount++;
if( m_nTicksAtFlip - lastTickCount > 10000 )
{
int framesPerTenSecs = frameCount * 10000 / ( m_nTicksAtFlip - lastTickCount );
if( framesPerTenSecs < 2000 )
{
DEBUGMSG( 1, (TEXT("Frames per second: %d.%1d\r\n"),
framesPerTenSecs/10, framesPerTenSecs%10 ));
}
lastTickCount = m_nTicksAtFlip;
frameCount = 0;
}
}
else
{
tickCountValid = 1;
lastTickCount = m_nTicksAtFlip;
frameCount = 0;
}
#endif DEBUG
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -