📄 halsurf.c
字号:
/******************************************************************************
<module>
* Name : halsurf.c
* Title : DDraw surface functionality
* Author(s) : Imagination Technologies
* Created : 26 May 2004
*
* Copyright : 2004 by Imagination Technologies Limited.
* All rights reserved. No part of this software, either
* material or conceptual may be copied or distributed,
* transmitted, transcribed, stored in a retrieval system
* or translated into any human or computer language in any
* form by any means, electronic, mechanical, manual or
* other-wise, or disclosed to third parties without the
* express written permission of Imagination Technologies
* Limited, Unit 8, HomePark Industrial Estate,
* King's Langley, Hertfordshire, WD4 8LZ, U.K.
*
* Description : ddraw surface functionality
*
* Platform : Windows CE
*
$Log: halsurf.c $
********************************************************************************/
#include "ddraw_headers.h"
#include "overlay.h"
extern DISP_STATE g_DISPState;
/*****************************************************************************
<function>
FUNCTION : CreateSurfaces
PARAMETERS : psDevInfo - pointer to our per device structure
dwBPP - number of bits per pixel for these surfaces
psPixelFormat - pointer to pixel format of surface
psData - pointer to structure passed to MBXCreateSurface() by DirectDraw
RETURNS : DD_OK if successful or a DirectDraw error code
<function/>
*****************************************************************************/
LONG CreateSurfaces(DWORD dwBPP, DDPIXELFORMAT *psPixelFormat, LPDDHAL_CREATESURFACEDATA psData)
{
DWORD dwFirstSurfCaps;
DWORD dwSize;
DWORD dwIndex;
DWORD dwWidth;
PPVRSRV_MEM_INFO psMemInfo;
PSURFDATA psSurfData;
DWORD dwNewSurfIndex=0;
DWORD dwSurfIndex;
LPDDRAWI_DDRAWSURFACE_LCL psSurfLcl;
DWORD i;
LONG lErrorCode;
PVRSRV_ERROR eError;
/* Store the caps for the first surface */
dwFirstSurfCaps = psData->lplpSList[0]->ddsCaps.dwCaps;
/* Create each surface in this request */
for(i = 0; i < psData->dwSCnt; i++)
{
psSurfLcl = psData->lplpSList[i];
psSurfData = (PSURFDATA) psSurfLcl->lpGbl->dwReserved1;
/* Init some of the surface data */
psSurfData->dwFlags = 0;
/* Check if this surface/surface chain is for the primary surface */
if(dwFirstSurfCaps & DDSCAPS_PRIMARYSURFACE)
{
/* Check if this is the primary surface */
if(psSurfLcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
{
psSurfData->dwFlags = SURFDATAFLAGS_PRIMARY;
}
else
{
/* These are already setup for primary in top level create surface FN. */
psData->lplpSList[0]->lpGbl->fpVidMem = GET_VMIDATA_ELEMENT(gpsDriverData, psData->lpDD, fpPrimary);
#ifdef FIXME // I Think this whole else block is irrelevant
psSurfData->dwPhysAddress = gpsDriverData->psDisplayDriverSharedData->dwPrimaryPhyBase;
#endif //FIXME
}
/* Surface dimension stuff. (Stride is in pixels) */
psSurfData->dwWidth = GET_VMIDATA_ELEMENT(gpsDriverData, psData->lpDD, dwDisplayWidth);
psSurfData->dwHeight = GET_VMIDATA_ELEMENT(gpsDriverData, psData->lpDD, dwDisplayHeight);
psSurfData->lStride = ((GET_VMIDATA_ELEMENT(gpsDriverData, psData->lpDD, lDisplayPitch) << 3) /
GET_VMIDATA_ELEMENT(gpsDriverData, psData->lpDD, ddpfDisplay).dwRGBBitCount);
/* Check if this is the primary surface */
if(dwNewSurfIndex == 0)
{
DPFLX(DBG_SURFACE, "Creating primary surface (0x%lx)", psSurfData);
/* Init the primary flip table */
gpsDriverData->sPrimFlipTable.dwActiveSurfaces = 0;
for (dwIndex = 0; dwIndex < MAX_FLIP_SURFACES; dwIndex++)
{
gpsDriverData->sPrimFlipTable.asSurfaceInfo[dwIndex].pvSurfaceData = (PVOID) NULL;
}
}
/* Check if this is part of a flipperable chain */
if (psData->dwSCnt > 1)
{
/* Store the fact that this is part of a primary flip chain */
psSurfData->dwFlags |= SURFDATAFLAGS_PRIMARY_FLIP_CHAIN;
/* Check if this is the primary surface in a flip chain */
if (dwNewSurfIndex != 0)
{
DPFLX(DBG_SURFACE, "Creating surface in primary flip chain (0x%lx)", psSurfData);
/* Allocate card memory for surface */
dwWidth = ((DWORD) psSurfLcl->lpGbl->wWidth + 31) & 0xFFFFFFE0;
dwSize = (dwBPP * dwWidth * (DWORD) psSurfLcl->lpGbl->wHeight) >> 3;
DPFL2("%d,%d,%d",dwBPP,dwWidth,(DWORD) psSurfLcl->lpGbl->wHeight);
DPFL2("Allocating 0x%8.8lX bytes for primary back buffer",dwSize);
psSurfData->psMemInfo = NULL;
/* FIXME - Flags/alignment may need to be different */
if((eError = PVRHALAllocDeviceMem (&gpsDriverData->sDisplayDevData,
0,
dwSize+256,
MBX1_TSPPL2_TEXADDRALIGNSIZE,
&psMemInfo)) != PVRSRV_OK)
{
DPF("Failed to allocate surface memory...");
if(eError == PVRSRV_ERROR_OUT_OF_MEMORY)
{
lErrorCode = DDERR_OUTOFVIDEOMEMORY;
}
else
{
lErrorCode = DDERR_GENERIC;
}
goto CreateSurfaceError;
}
/*
Set where the surface was allocated from if it has not
already been done so by the calling app
*/
psSurfLcl->ddsCaps.dwCaps |= DDSCAPS_LOCALVIDMEM;
/* Set up surface data */
psSurfData->psMemInfo = psMemInfo;
psSurfData->pvLinAddress = psSurfData->psMemInfo->pvLinAddr;
psSurfLcl->lpGbl->lPitch = (LONG) ((dwWidth * dwBPP) >> 3);
psSurfLcl->lpGbl->fpVidMem = (DWORD) psSurfData->pvLinAddress;
}
/* Update primary flip table */
gpsDriverData->sPrimFlipTable.dwActiveSurfaces++;
gpsDriverData->sPrimFlipTable.asSurfaceInfo[dwNewSurfIndex].pvSurfaceData = (PVOID) psSurfData;
/* Store this surfaces flip surface number in surface data */
psSurfData->dwSurfaceIndex = dwNewSurfIndex;
/* Move to next surface */
dwNewSurfIndex++;
}
else
{
/* Update primary flip table */
gpsDriverData->sPrimFlipTable.dwActiveSurfaces = 1;
gpsDriverData->sPrimFlipTable.asSurfaceInfo[0].pvSurfaceData=(PVOID)psSurfData;
}
}
else
{
DPFLX(DBG_SURFACE, "Creating non-primary and non-textured surface (0x%lx)", psSurfData);
/* Round width up to a multiple of 32 pixels */
dwWidth = ((DWORD) psSurfLcl->lpGbl->wWidth + 31) & 0xFFFFFFE0;
/* Create size of required surface in bytes. */
dwSize = (dwBPP * dwWidth * (DWORD) psSurfLcl->lpGbl->wHeight) >> 3;
DPFL2("%d,%d,%d",dwBPP,dwWidth,(DWORD) psSurfLcl->lpGbl->wHeight);
DPFL2("Allocating 0x%8.8lX bytes",dwSize);
psSurfData->psMemInfo = NULL;
/* Allocate Device mem */
if((eError = PVRHALAllocDeviceMem(&gpsDriverData->sDisplayDevData,
0,
dwSize,
MBX1_TSPPL2_TEXADDRALIGNSIZE,
&psMemInfo)) != PVRSRV_OK)
{
DPF("Failed to allocate surface memory...");
if (eError == PVRSRV_ERROR_OUT_OF_MEMORY)
{
lErrorCode = DDERR_OUTOFVIDEOMEMORY;
}
else
{
lErrorCode = DDERR_GENERIC;
}
goto CreateSurfaceError;
}
DPFL2("Mem handle - 0x%8.8lX",psMemInfo);
/* Record where the surface was allocated */
psSurfLcl->ddsCaps.dwCaps |= DDSCAPS_LOCALVIDMEM;
/* Setup some surface data entries. */
psSurfData->psMemInfo = psMemInfo;
psSurfData->lStride = (LONG) dwWidth;
psSurfData->dwWidth = (DWORD) psSurfLcl->lpGbl->wWidth;
psSurfData->dwHeight = (DWORD) psSurfLcl->lpGbl->wHeight;
psSurfData->pvLinAddress = psSurfData->psMemInfo->pvLinAddr;
if(dwBPP != 12)
{
psSurfLcl->lpGbl->lPitch = (LONG) ((dwWidth * dwBPP) >> 3);
}
else
{
psSurfLcl->lpGbl->lPitch = (LONG) dwWidth;
}
psSurfLcl->lpGbl->fpVidMem = (DWORD) psSurfData->pvLinAddress;
/* initialise surface with it's physical (FB Base offset) address */
*((DWORD *)psSurfData->pvLinAddress) = psSurfData->psMemInfo->uiDevAddr.uiAddr;
/* Now sort out the overlay stuff */
if(dwFirstSurfCaps & DDSCAPS_OVERLAY)
{
/* setup per-surface overlay details */
DWORD dwSurfBase = psSurfData->psMemInfo->uiDevAddr.uiAddr;// - dwPhysBase;
psSurfData->sOverlaySurface.wWidth = (WORD)psSurfData->dwWidth;
psSurfData->sOverlaySurface.wHeight = (WORD)psSurfData->dwHeight;
psSurfData->sOverlaySurface.wStride = (WORD)psSurfData->lStride;
psSurfData->sOverlaySurface.pvOvlBase = (PVOID)(dwSurfBase);
/* for the planar formats setup the additional base addresses */
if(psSurfData->dwMBXFormat == MBXDD_FORMAT_IMC2)
{
dwSurfBase+=psSurfData->dwHeight*psSurfData->lStride;
psSurfData->sOverlaySurface.pvOvlUBase = (PVOID)(dwSurfBase);
psSurfData->sOverlaySurface.pvOvlVBase = (PVOID)(dwSurfBase + psSurfData->lStride/2);
}
else if(psSurfData->dwMBXFormat == MBXDD_FORMAT_YV12)
{
dwSurfBase+=psSurfData->dwHeight*psSurfData->lStride;
psSurfData->sOverlaySurface.pvOvlVBase = (PVOID)(dwSurfBase);
psSurfData->sOverlaySurface.pvOvlUBase = (PVOID)(dwSurfBase + psSurfData->dwHeight*psSurfData->lStride/4);
}
/* by default assume no de-interlacing */
psSurfData->sOverlaySurface.DeInterlace = PDP_WEAVE;
/* Update Overlay flip table */
gpsDriverData->sOvlFlipTable.dwActiveSurfaces++;
gpsDriverData->sOvlFlipTable.asSurfaceInfo[dwNewSurfIndex].pvSurfaceData = (PVOID) psSurfData;
/* Store this surfaces flip surface number in surface data */
psSurfData->dwSurfaceIndex = dwNewSurfIndex;
/* mark the surface flippable */
psSurfLcl->ddsCaps.dwCaps |= DDSCAPS_FLIP;
/* mark the surface as an overlay */
psSurfData->dwFlags |= SURFDATAFLAGS_OVERLAY;
/* Move to next surface */
dwNewSurfIndex++;
}
}
}
return (DD_OK);
CreateSurfaceError:
/*
Ok an error occurred, we need to clean up any mess..
'i' will hold the surface number that was being processed then the error occured
*/
/* Check if this was a primary surface chain */
if(dwFirstSurfCaps & DDSCAPS_PRIMARYSURFACE)
{
/* For each surface */
while (i != 0xffffffff)
{
/* Find surface data */
psSurfLcl = psData->lplpSList[i];
psSurfData = (PSURFDATA) psSurfLcl->lpGbl->dwReserved1;
/* Free card memory if it was allocated and indicate that it has been freed */
if (i != 0 && psSurfData->psMemInfo != NULL)
{
PVRHALFreeDeviceMem(&gpsDriverData->sDisplayDevData, psSurfData->psMemInfo);
psSurfData->psMemInfo=NULL;
}
/* Move to previous surface */
i--;
}
/* Reset primary flip table */
gpsDriverData->sPrimFlipTable.dwActiveSurfaces=0;
for (dwSurfIndex=0; dwSurfIndex < MAX_FLIP_SURFACES; dwSurfIndex++)
{
gpsDriverData->sPrimFlipTable.asSurfaceInfo[dwSurfIndex].pvSurfaceData=NULL;
}
}
else
{
if(dwFirstSurfCaps & DDSCAPS_OVERLAY)
{
/* we were setting up an overlay and it failed */
gpsDriverData->sOvlFlipTable.dwActiveSurfaces = 0;
}
/*For each surface*/
while (i != 0xffffffff)
{
/* Find surface data */
psSurfLcl = psData->lplpSList[i];
psSurfData = (PSURFDATA) psSurfLcl->lpGbl->dwReserved1;
/* Check if card memory was allocated */
if(psSurfData->psMemInfo != NULL)
{
/* Release card memory and indicate that is has been freed */
PVRHALFreeDeviceMem(&gpsDriverData->sDisplayDevData, psSurfData->psMemInfo);
psSurfData->psMemInfo=NULL;
}
/*Move to previous surface*/
i--;
}
}
return(lErrorCode);
}
/*****************************************************************************
<function>
FUNCTION : HALCreateSurface
PARAMETERS : LPDDHAL_CREATESURFACEDATA structure
RETURNS : DDHAL return code
<function/>
*****************************************************************************/
DWORD WINAPI HALCreateSurface( LPDDHAL_CREATESURFACEDATA psData )
{
DWORD i;
DWORD dwBPP;
DWORD dwSurfaceCaps;
PVRSRV_DEV_INFO *psDevInfo;
PVRSRV_DEV_DATA *psDevData;
DDPIXELFORMAT sPixelFormat;
DWORD dwMBXFormat;
LPDDRAWI_DDRAWSURFACE_LCL psSurfLcl;
LONG lRet;
DWORD dwResult;
PSURFDATA psSurfData;
DDSURFACEDESC *lpDDSurfDesc;
DPFLX(DBG_DD_ENTRY, "HALCreateSurface() called");
psDevData = &gpsDriverData->sDisplayDevData;
psDevInfo = psDevData->psDevInfoKM;
lRet = DD_OK;
dwResult = DDHAL_DRIVER_HANDLED;
lpDDSurfDesc = psData->lpDDSurfaceDesc;
dwSurfaceCaps = psData->lpDDSurfaceDesc->ddsCaps.dwCaps;
/*
Ignore system-memory surface-destroy notifications - we get told about
destroyed sys-mem surfaces via a call to CreateSurfaceEx.
*/
/* if(dwSurfaceCaps & DDSCAPS_SYSTEMMEMORY)
{
psData->ddRVal = DD_OK;
dwResult = DDHAL_DRIVER_HANDLED;
goto HALCreateSurfaceExit;
}*/
DPFLX(DBG_SURFACE, "Surfaces %d",psData->dwSCnt);
DPFLX(DBG_SURFACE, "Flags 0x%8.8lX",psData->lpDDSurfaceDesc->dwFlags);
DPFLX(DBG_SURFACE, "ddsCaps 0x%8.8lX",dwSurfaceCaps);
DPFLX(DBG_SURFACE, "Height %d",psData->lpDDSurfaceDesc->dwHeight);
DPFLX(DBG_SURFACE, "Width %d",psData->lpDDSurfaceDesc->dwWidth);
DPFLX(DBG_SURFACE, "BPP %d",psData->lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount);
/* Driver name should be valid here so copy into driver data */
memcpy(&gpsDriverData->pszDriverName, &psData->lpDD->cDriverName, MAX_DRIVER_NAME);
/* Make sure our reserved words are NULL to avoid confusion later */
for(i = 0; i < psData->dwSCnt; i++)
{
psSurfLcl = psData->lplpSList[i];
psSurfLcl->lpGbl->dwReserved1 = 0;
}
/* Extract pixel format information - if not available, use primary surface type */
if(psData->lpDDSurfaceDesc->dwFlags & DDSD_PIXELFORMAT)
{
/* Has valid pixel format */
sPixelFormat = psData->lpDDSurfaceDesc->ddpfPixelFormat;
}
else
{
/* No valid pixel format, use primary type */
DPFL2("Pixel format not valid, pull from primary, 0x%8.8lX", GET_VMIDATA_ELEMENT(gpsDriverData, psData->lpDD,ddpfDisplay));
/* Copy complete structure */
sPixelFormat = GET_VMIDATA_ELEMENT(gpsDriverData, psData->lpDD, ddpfDisplay);
}
/* Convert DirectDraw pixel format to MBX format */
dwMBXFormat = ConvertPixelFormatToMBX(&sPixelFormat);
/* Check if valid value returned, i.e. not */
if(dwMBXFormat == 0)
{
psData->ddRVal = DDERR_INVALIDPIXELFORMAT;
dwResult = DDHAL_DRIVER_HANDLED;
goto HALCreateSurfaceExit;
}
/* Check for FOURCC's */
if(sPixelFormat.dwFlags & DDPF_FOURCC)
{
dwBPP = GetBPPFromFOURCC(sPixelFormat.dwFourCC);
/* Change the dwRGBBitCount value since this is the actual value */
sPixelFormat.dwRGBBitCount = dwBPP;
}
else
{
dwBPP = sPixelFormat.dwRGBBitCount;
}
/* Allocate surface local data blocks */
for (i = 0; i < psData->dwSCnt; i++)
{
psSurfLcl = psData->lplpSList[i];
/* Allocate our internal surface data struct */
psSurfData = (PSURFDATA) AllocSharedMem(sizeof(SURFDATA));
if(!psSurfData)
{
psData->ddRVal = DDERR_OUTOFMEMORY;
dwResult = DDHAL_DRIVER_HANDLED;
goto HALCreateSurfaceExit;
}
DPFLX(DBG_SURFACE, "Allocated surface data (0x%lx)", psSurfData);
if(psSurfLcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -