📄 dispdrvr.c
字号:
// so that we may set the bufferable bit. This enables write coalescing
// for frame buffer writes when using the section mapped address.
//
// GAPI uses the section mapped address always.
// Now configure the frame buffer's section descriptor.
// The function GetDescriptorAddress shows how to obtain the correct descriptor address.
// This descriptor is one of two descriptors that map the the frame buffer.
// The first descriptor found maps the cached virtual address, while the second
// descriptor found maps the uncached virtual address. We want to modify the
// second descriptor, that which maps the uncached virtual address since the uncached virtual
// address is the address we've chosen to use throughout the codebase.
//
// NOTE:
// The section descriptor covers a 1MB section. If the frame buffer ever exceeds 1MB
// in size, you'll need to modify additional section descriptors.
//
// DDraw requires that the frame buffer pointer be in the shared memory space so
// is can be shared between processes.
{
PVOID pPhysAddr;
size_t offset;
size_t size;
pPhysAddr = (PVOID)(FRAME_BUFFER_0_BASE_PHYSICAL);
size = frameBufferSize * NUM_FRAME_BUFFERS;
offset = (unsigned)pPhysAddr & (0x1000 - 1);
size += (offset ? 0x1000 : 0);
pPhysAddr = (PVOID)((unsigned)pPhysAddr - offset);
if (size >= 1024*1024*2)
{
gFrameBuffer = (PBYTE)VirtualAlloc(NULL, size, MEM_RESERVE, PAGE_NOACCESS);
}
else
{
gFrameBuffer = (PBYTE)VirtualAlloc(NULL, 1024*1024*2, MEM_RESERVE, PAGE_NOACCESS);
}
if (!VirtualCopy(gFrameBuffer, (LPVOID)((unsigned long)pPhysAddr >> 8), size, (PAGE_READWRITE | PAGE_NOCACHE | PAGE_PHYSICAL)))
{
gFrameBuffer = NULL;
}
else
{
gFrameBuffer += offset;
}
}
if (!gFrameBuffer)
{
Cleanup();
return FALSE;
}
if (bDoRotation)
{
// if rotating the display, the actual frame buffer should be configured as bufferable for max write performance into the frame buffer.
VirtualSetAttributes(gFrameBuffer, frameBufferSize*NUM_FRAME_BUFFERS, 4, 4, NULL);
}
else
{
// if not rotating the dispay, we can draw directly into the frame buffer, and use write-through cache mode to improve frame buffer throughput
VirtualSetAttributes(gFrameBuffer, frameBufferSize*NUM_FRAME_BUFFERS, 8, 8, NULL);
}
gBlankFrameBuffer = (PBYTE) VirtualAlloc(0, frameBufferSize, MEM_RESERVE | MEM_COMMIT,PAGE_READWRITE);
if (!gBlankFrameBuffer)
{
Cleanup();
return FALSE;
}
return TRUE;
}
// Free all the global memory resources
void Cleanup(void)
{
DMA_ADAPTER_OBJECT Adapter;
PHYSICAL_ADDRESS PhysAddr;
if (v_pLcdRegs)
{
VirtualFree((PVOID)v_pLcdRegs,0,MEM_RELEASE);
v_pLcdRegs = NULL;
}
if (v_pClkRegs)
{
VirtualFree((PVOID)v_pClkRegs,0,MEM_RELEASE);
v_pLcdRegs = NULL;
}
if (v_pGPIORegs)
{
VirtualFree((PVOID)v_pGPIORegs,0,MEM_RELEASE);
v_pGPIORegs = NULL;
}
if (v_pSSPRegs)
{
VirtualFree((PVOID)v_pSSPRegs,0,MEM_RELEASE);
v_pSSPRegs = NULL;
}
if (gFrameBuffer)
{
VirtualFree((PVOID)gFrameBuffer,0,MEM_RELEASE);
gFrameBuffer = NULL;
}
if (frameDescriptorCh2_YCbCr_Y)
{
VirtualFree((PVOID)frameDescriptorCh2_YCbCr_Y,0,MEM_RELEASE);
frameDescriptorCh2_YCbCr_Y = NULL;
}
if (frameDescriptorCh3_YCbCr_Cb)
{
VirtualFree((PVOID)frameDescriptorCh3_YCbCr_Cb,0,MEM_RELEASE);
frameDescriptorCh3_YCbCr_Cb = NULL;
}
if (frameDescriptorCh4_YCbCr_Cr)
{
VirtualFree((PVOID)frameDescriptorCh4_YCbCr_Cr,0,MEM_RELEASE);
frameDescriptorCh4_YCbCr_Cr = NULL;
}
Adapter.ObjectSize = sizeof (DMA_ADAPTER_OBJECT);
Adapter.InterfaceType = Internal;
Adapter.BusNumber = 0;
PhysAddr.HighPart = 0;
PhysAddr.LowPart = g_DisplayBasePhysical;
HalFreeCommonBuffer(&Adapter, DISPLAY_BUFFER_SIZE, PhysAddr, (void *)g_DisplayBaseVirtual, FALSE);
}
void DispDrvrPowerHandler(BOOL bOff)
{
if(bOff)
{
XllpLCDSuspend(&XllpLCD, Suspend_Graceful);
// Put Controller in Standby Mode
SSPLinkSetup(&XllpLCD);
WriteLcdControllerData(PowerOffSequence);
WriteLcdControllerData(StandbySequence);
}
else
{
// Plato's display shows a bright blank white screen before the image appears
// turn the backlight off to prevent this visual glitch
v_pGPIORegs->GPCR0 |= XLLP_GPIO_BIT_PWM_OUT0; // turn backlight off
v_pGPIORegs->GPDR0 |= XLLP_GPIO_BIT_PWM_OUT0; // set GPIO 16 Dir to output
v_pGPIORegs->GAFR0_U &= ~(XLLP_GPIO_AF_BIT_PWM_OUT0_MASK); // Disable PWM
// Re-Init the LCD Controllers
SSPLinkSetup(&XllpLCD);
WriteLcdControllerData(InitSequence);
XllpLCDResume(&XllpLCD);
// And turn the backlight back on
v_pGPIORegs->GAFR0_U |= XLLP_GPIO_AF_BIT_PWM_OUT0; // Enable PWM
}
}
void CopyFrameBuffer(BOOL gDirection)
{
DWORD i;
unsigned * cfbp = (unsigned *)gBlankFrameBuffer;
unsigned * fbp = (unsigned *)gFrameBuffer + (activeFrameBuffer * frameBufferSize);
for(i = 0; i < (DispDrvr_cxScreen * DispDrvr_cyScreen * (bpp / 8) / 4); i++)
{
if (gDirection)
{
*cfbp++ = *fbp++;
}
else
{
*fbp++ = *cfbp++;
}
}
}
void ClearFrameBuffer(BOOL color)
{
DWORD i;
unsigned * fbp = (unsigned *)gFrameBuffer + (activeFrameBuffer * frameBufferSize);
for(i = 0; i < (DispDrvr_cxScreen * DispDrvr_cyScreen * (bpp / 8) / 4); i++)
{
if (color)
{
*fbp++ = 0xFFFFFFFF; // Ones turn it white
}
else
{
*fbp++ = 0x00000000; // Zeros turn it black
}
}
}
void SetFrameBuffer(DWORD color)
{
DWORD i;
unsigned *fbp;
fbp = (unsigned *) gFrameBuffer;
for ( i = 0; i < (DispDrvr_cxScreen*DispDrvr_cyScreen*(bpp/8)/4); i++ )
*fbp++ = color;
}
//**********************************************************************
//
//DispDrvrContrastControl:
//
// Modify the contrast according to the Cmd parameter.
// Not supported
//
BOOL DispDrvrContrastControl(int Cmd,DWORD *pValue)
{
// currently does not support changing contrast in software.
return TRUE;
}
void DirtyRectDumpPortraitLoop_C(BYTE *pDstBuf, BYTE *pSrcBuf, DWORD yTop, DWORD yBottom,
DWORD srcWidthB, DWORD bytesPerRow, DWORD bytesPerPixel,
DWORD srcMarginWidth, DWORD dstMarginWidth)
{
DWORD row;
DWORD i;
DWORD j;
if ( bytesPerPixel != 2 )
{
//not 16-bit
for (i = 0; i < srcWidthB / bytesPerPixel; i++)
{
for (row = yTop; row < yBottom; row++)
{
for (j = 0; j < bytesPerPixel; j++)
{
*pDstBuf++ = *(pSrcBuf + j);
}
pSrcBuf -= bytesPerRow;
}
pDstBuf += dstMarginWidth;
pSrcBuf += srcMarginWidth + 2;
}
}
else
{
WORD * pwDst;
WORD * pwSrc;
int rowLen;
//16-bit
srcWidthB >>= 1;
pwDst = (WORD *)pDstBuf;
pwSrc = (WORD *)pSrcBuf;
//first row for pwSrc, then column for pwDst
rowLen = yBottom - yTop;
#ifndef _OPT_ASM
bytesPerRow >>= 1;
dstMarginWidth >>= 1;
srcMarginWidth >>= 1;
for (i = 0; i < srcWidthB; i++)
{
for (row = 0; row < (rowLen >> 2); row++)
{
*pwDst++ = *pwSrc;
pwSrc -= bytesPerRow;
*pwDst++ = *pwSrc;
pwSrc -= bytesPerRow;
*pwDst++ = *pwSrc;
pwSrc -= bytesPerRow;
*pwDst++ = *pwSrc;
pwSrc -= bytesPerRow;
}
for (row = 0; row < (rowLen & 0x3); row++)
{
*pwDst++ = *pwSrc;
pwSrc -= bytesPerRow;
}
pwDst += dstMarginWidth;
pwSrc += srcMarginWidth + 1;
}
#else
dirtyRectDump_core_ASM(pwSrc, pwDst, rowLen, srcWidthB, bytesPerRow, srcMarginWidth, dstMarginWidth);
#endif
}
}
void DispDrvrDirtyRectDump(LPCRECT prc)
{
BYTE * pDstBuf;
BYTE * pSrcBuf;
DWORD xLeft;
DWORD yTop;
DWORD xRight;
DWORD yBottom;
DWORD bytesPerRow;
DWORD bytesPerPixel;
DWORD srcWidthB;
DWORD srcMarginWidth;
DWORD dstMarginWidth;
DWORD srcStartRow;
DWORD dstStartRow;
bytesPerPixel = bpp / 8;
xLeft = prc->left < 0 ? 0 : prc->left;
yTop = prc->top < 0 ? 0 : prc->top;
xRight = prc->right > DispDrvr_cxScreen ? DispDrvr_cxScreen : prc->right;
yBottom = prc->bottom > DispDrvr_cyScreen ? DispDrvr_cyScreen : prc->bottom;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -