Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1834 lines
72 KiB

/******************************Module*Header**********************************\
*
* **************************
* * DirectDraw SAMPLE CODE *
* **************************
*
* Module Name: ddsurf.c
*
* Content: DirectDraw surfaces creation/destructions callbacks
*
* Copyright (c) 1994-1999 3Dlabs Inc. Ltd. All rights reserved.
* Copyright (c) 1995-2003 Microsoft Corporation. All rights reserved.
\*****************************************************************************/
// This file needs the surface format table
#include "glint.h"
#include "dma.h"
// This enum is used to lookup the correct entry in the table
// for all the surface types the HAL cares about
typedef enum tagDeviceFormatNum
{
HAL_8888_ALPHA = 0,
HAL_8888_NOALPHA = 1,
HAL_5551_ALPHA = 2,
HAL_5551_NOALPHA = 3,
HAL_4444 = 4,
HAL_332 = 10,
HAL_2321 = 18,
HAL_CI8 = 28,
HAL_CI4 = 29,
HAL_565 = 30,
HAL_YUV444 = 34,
HAL_YUV422 = 35,
HAL_L8 = 36,
HAL_A8L8 = 37,
HAL_A4L4 = 38,
HAL_A8 = 39,
HAL_MVCA = 40,
HAL_MVSU = 41,
HAL_MVSB = 42,
HAL_UNKNOWN = 255,
} DeviceFormatNum;
static P3_SURF_FORMAT SurfaceFormats[MAX_SURFACE_FORMATS] =
{
// If there are multiple formats, the one with the alpha is listed first.
// Format 0 (32 bit 8888) // Always 3 components for 888(8) textures. Red Green Blue Alpha bAlpha, P3RX Filter format
/* 0 */ {SURF_8888, 32, __GLINT_32BITPIXEL, RGBA_COMPONENTS, LOG_2_32, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, TRUE, SURF_FILTER_8888_OR_YUV, SURF_DITHER_8888, "R8G8B8A8" },
/* 1 */ {SURF_8888, 32, __GLINT_32BITPIXEL, RGBA_COMPONENTS, LOG_2_32, 0xFF0000, 0xFF00, 0xFF, 0x00000000, FALSE, SURF_FILTER_888, SURF_DITHER_8888, "R8G8B8x8" },
// Format 1 (16 bit 5551)
/* 2 */ {SURF_5551_FRONT, 16, __GLINT_16BITPIXEL, RGBA_COMPONENTS, LOG_2_16, 0x7C00, 0x03E0, 0x001F, 0x8000, TRUE, SURF_FILTER_5551, SURF_DITHER_5551, "R5G5B5A1" },
/* 3 */ {SURF_5551_FRONT, 16, __GLINT_16BITPIXEL, RGB_COMPONENTS, LOG_2_16, 0x7C00, 0x03E0, 0x001F, 0x0, FALSE, SURF_FILTER_5551, SURF_DITHER_5551, "R5G5B5x1" },
// Format 2 (16 bit 4444)
/* 4 */ {SURF_4444, 16, __GLINT_16BITPIXEL, RGBA_COMPONENTS, LOG_2_16, 0xF00, 0xF0, 0xF, 0xF000, TRUE, SURF_FILTER_4444, SURF_DITHER_4444, "R4G4B4A4" },
/* 5 */ {SURF_4444, 16, __GLINT_16BITPIXEL, RGBA_COMPONENTS, LOG_2_16, 0xF00, 0xF0, 0xF, 0xF000, TRUE, SURF_FILTER_4444, SURF_DITHER_4444, "R4G4B4x4" },
// Format 3 (16 bit 4444 Front)
/* 6 */ {SURF_4444_FRONT, 0, 0, COMPONENTS_DONT_CARE, 0, 0, 0, 0, 0, 0, SURF_FILTER_4444, SURF_DITHER_4444, "R4G4B4A4" },
/* 7 */ {SURF_4444_FRONT, 0, 0, COMPONENTS_DONT_CARE, 0, 0, 0, 0, 0, 0, SURF_FILTER_4444, SURF_DITHER_4444, "R4G4B4x4" },
// Format 4 (16 bit 4444 Back)
/* 8 */ {SURF_4444_BACK, 0, 0, COMPONENTS_DONT_CARE, 0, 0, 0, 0, 0, 0, SURF_FILTER_4444, SURF_DITHER_4444, "R4G4B4A4" },
/* 9 */ {SURF_4444_BACK, 0, 0, COMPONENTS_DONT_CARE, 0, 0, 0, 0, 0, 0, SURF_FILTER_4444, SURF_DITHER_4444, "R4G4B4x4" },
// Format 5 (8 bit 332 Front)
/* 10 */ {SURF_332_FRONT, 8, __GLINT_8BITPIXEL, RGB_COMPONENTS, LOG_2_8, 0xE0, 0x1C, 0x3, 0, FALSE, SURF_FILTER_332, SURF_DITHER_332, "R3G3B2" },
/* 11 */ {SURF_332_FRONT, 0, 0, COMPONENTS_DONT_CARE, 0, 0, 0, 0, 0, 0, SURF_FILTER_332, SURF_DITHER_332, "R3G3B2" },
// Format 6 (8 bit 332 back)
/* 12 */ {SURF_332_BACK, 0, 0, COMPONENTS_DONT_CARE, 0, 0, 0, 0, 0, 0, SURF_FILTER_332, SURF_DITHER_332, "R3G3B2" },
/* 13 */ {SURF_332_BACK, 0, 0, COMPONENTS_DONT_CARE, 0, 0, 0, 0, 0, 0, SURF_FILTER_332, SURF_DITHER_332, "R3G3B2" },
// Format 7 (4 bit 121 front)
/* 14 */ {SURF_121_FRONT, 0, 0, COMPONENTS_DONT_CARE, 0, 0, 0, 0, 0, 0, SURF_FILTER_INVALID, SURF_DITHER_INVALID, "R1G2B1" },
/* 15 */ {SURF_121_FRONT, 0, 0, COMPONENTS_DONT_CARE, 0, 0, 0, 0, 0, 0, SURF_FILTER_INVALID, SURF_DITHER_INVALID, "R1G2B1" },
// Format 8 (4 bit 121 back)
/* 16 */ {SURF_121_BACK, 0, 0, COMPONENTS_DONT_CARE, 0, 0, 0, 0, 0, 0, SURF_FILTER_INVALID, SURF_DITHER_INVALID, "R1G2B1" },
/* 17 */ {SURF_121_BACK, 0, 0, COMPONENTS_DONT_CARE, 0, 0, 0, 0, 0, 0, SURF_FILTER_INVALID, SURF_DITHER_INVALID, "R1G2B1" },
// Format 9 (8 bit 2321 front)
/* 18 */ {SURF_2321_FRONT, 8, __GLINT_8BITPIXEL, RGBA_COMPONENTS, LOG_2_8, 0xC0, 0x38, 0x6, 0x1, TRUE, SURF_FILTER_INVALID, SURF_DITHER_INVALID, "R2G3B2A1" },
/* 19 */ {SURF_2321_FRONT, 0, 0, COMPONENTS_DONT_CARE, 0, 0, 0, 0, 0, 0, SURF_FILTER_INVALID, SURF_DITHER_INVALID, "R2G3B2x1" },
// Format 10 (8 bit 2321 back)
/* 20 */ {SURF_2321_BACK, 0, 0, COMPONENTS_DONT_CARE, 0, 0, 0, 0, 0, 0, SURF_FILTER_INVALID, SURF_DITHER_INVALID, "R2G3B2A1" },
/* 21 */ {SURF_2321_BACK, 0, 0, COMPONENTS_DONT_CARE, 0, 0, 0, 0, 0, 0, SURF_FILTER_INVALID, SURF_DITHER_INVALID, "R2G3B2x1" },
// Format 11 (8 bit 232 front off)
/* 22 */ {SURF_232_FRONTOFF, 0, 0, COMPONENTS_DONT_CARE, 0, 0, 0, 0, 0, 0, SURF_FILTER_INVALID, SURF_DITHER_INVALID, "R2G3B2x1" },
/* 23 */ {SURF_232_FRONTOFF, 0, 0, COMPONENTS_DONT_CARE, 0, 0, 0, 0, 0, 0, SURF_FILTER_INVALID, SURF_DITHER_INVALID, "R2G3B2x1" },
// Format 12 (8 bit 232 back off)
/* 24 */ {SURF_232_BACKOFF, 0, 0, COMPONENTS_DONT_CARE, 0, 0, 0, 0, 0, 0, SURF_FILTER_INVALID, SURF_DITHER_INVALID, "R2G3B2x1" },
/* 25 */ {SURF_232_BACKOFF, 0, 0, COMPONENTS_DONT_CARE, 0, 0, 0, 0, 0, 0, SURF_FILTER_INVALID, SURF_DITHER_INVALID, "R2G3B2x1" },
// Format 13 (5551 back)
/* 26 */ {SURF_5551_BACK, 0, 0, COMPONENTS_DONT_CARE, 0, 0, 0, 0, 0, 0, SURF_FILTER_5551, SURF_DITHER_5551, "R5G5B5A1" },
/* 27 */ {SURF_5551_BACK, 0, 0, COMPONENTS_DONT_CARE, 0, 0, 0, 0, 0, 0, SURF_FILTER_5551, SURF_DITHER_5551, "R5G5B5x1" },
// Format 14 (CI8)
/* 28 */ {SURF_CI8, 8, __GLINT_8BITPIXEL, RGBA_COMPONENTS, LOG_2_8, 0, 0, 0, 0, TRUE, SURF_FILTER_8888_OR_YUV, SURF_DITHER_I8, "I8" },
// Format 15 (CI4)
/* 29 */ {SURF_CI4, 4, __GLINT_4BITPIXEL, RGBA_COMPONENTS, LOG_2_4, 0, 0, 0, 0, TRUE, SURF_FILTER_8888_OR_YUV, SURF_DITHER_INVALID, "I4" },
// Format 16 (565 front)
/* 30 */ {SURF_565_FRONT, 16, __GLINT_16BITPIXEL, RGB_COMPONENTS, LOG_2_16, 0xF800, 0x07E0, 0x001F, 0, FALSE, SURF_FILTER_565, SURF_DITHER_565, "R5G6B5" },
/* 31 */ {SURF_565_FRONT, 0, 0, COMPONENTS_DONT_CARE, 0, 0, 0, 0, 0, 0, SURF_FILTER_565, SURF_DITHER_565, "R5G6B5" },
// Format 17 (565 back)
/* 32 */ {SURF_565_BACK, 0, 0, COMPONENTS_DONT_CARE, 0, 0, 0, 0, 0, 0, SURF_FILTER_565, SURF_DITHER_565, "R5G6B5" },
/* 33 */ {SURF_565_BACK, 0, 0, COMPONENTS_DONT_CARE, 0, 0, 0, 0, 0, 0, SURF_FILTER_565, SURF_DITHER_565, "R5G6B5" },
// Format 18 (YUV 444)
/* 34 */ {SURF_YUV444, 32, __GLINT_16BITPIXEL, RGBA_COMPONENTS, LOG_2_16, 0, 0, 0, 0, TRUE, SURF_FILTER_8888_OR_YUV, SURF_DITHER_INVALID, "YUV444" },
// Format 19 (YUV 422)
/* 35 */ {SURF_YUV422, 16, __GLINT_16BITPIXEL, RGB_COMPONENTS, LOG_2_32, 0, 0, 0, 0, FALSE, SURF_FILTER_8888_OR_YUV, SURF_DITHER_INVALID, "YUV422" },
// Format 100 (L8)
/* 36 */ {SURF_L8, 8, __GLINT_8BITPIXEL, RGB_COMPONENTS, LOG_2_8, 0, 0, 0, 0, FALSE, SURF_FILTER_L8, SURF_DITHER_INVALID, "L8" },
// Format 101 (A8L8)
/* 37 */ {SURF_A8L8, 16, __GLINT_16BITPIXEL, RGB_COMPONENTS, LOG_2_16, 0, 0, 0, 0, TRUE, SURF_FILTER_A8L8, SURF_DITHER_INVALID, "A8L8" },
// Format 102 (A4L4)
/* 38 */ {SURF_A4L4, 16, __GLINT_8BITPIXEL, RGB_COMPONENTS, LOG_2_8, 0, 0, 0, 0, TRUE, SURF_FILTER_A4L4, SURF_DITHER_INVALID, "A4L4" },
// Format 103 (A8)
/* 39 */ {SURF_A8, 8, __GLINT_8BITPIXEL, RGB_COMPONENTS, LOG_2_8, 0, 0, 0, 0, TRUE, SURF_FILTER_A8, SURF_DITHER_INVALID, "A8" },
// Format 104 (A8) MVCA
/* 40 */ {SURF_MVCA, 32, __GLINT_32BITPIXEL, RGB_COMPONENTS, LOG_2_32, 0, 0, 0, 0, TRUE, SURF_FILTER_8888_OR_YUV, SURF_DITHER_INVALID, "MVCA" },
// Format 105 (A8) MVSU
/* 41 */ {SURF_MVSU, 32, __GLINT_32BITPIXEL, RGB_COMPONENTS, LOG_2_32, 0, 0, 0, 0, TRUE, SURF_FILTER_8888_OR_YUV, SURF_DITHER_INVALID, "MVSU" },
// Format 106 (A8) MVSB
/* 42 */ {SURF_MVSB, 32, __GLINT_32BITPIXEL, RGB_COMPONENTS, LOG_2_32, 0, 0, 0, 0, TRUE, SURF_FILTER_8888_OR_YUV, SURF_DITHER_INVALID, "MVSB" }
};
#define MAKE_DWORD_ALIGNED(n) ( ((n) % 4) ? ((n) + 4 - ((n) % 4)) : (n) )
#define MAKE_QWORD_ALIGNED(n) ( ((n) % 8) ? ((n) + 8 - ((n) % 8)) : (n) )
//-----------------------------------------------------------------------------
//
// _DD_SUR_GetSurfaceFormat
//
//-----------------------------------------------------------------------------
P3_SURF_FORMAT*
_DD_SUR_GetSurfaceFormat(
LPDDRAWI_DDRAWSURFACE_LCL pLcl)
{
DeviceFormatNum HALDeviceFormat = HAL_UNKNOWN; // The default
if (pLcl)
{
DDPIXELFORMAT* pPixFormat = DDSurf_GetPixelFormat(pLcl);
if (pPixFormat->dwFlags & DDPF_FOURCC)
{
switch( pPixFormat->dwFourCC)
{
case FOURCC_MVCA:
HALDeviceFormat = HAL_MVCA;
break;
case FOURCC_MVSU:
HALDeviceFormat = HAL_MVSU;
break;
case FOURCC_MVSB:
HALDeviceFormat = HAL_MVSB;
break;
case FOURCC_YUV422:
HALDeviceFormat = HAL_YUV422;
break;
case FOURCC_YUV411:
HALDeviceFormat = HAL_YUV444;
break;
} //switch
}
else if (pPixFormat->dwFlags & DDPF_PALETTEINDEXED4)
{
HALDeviceFormat = HAL_CI4;
}
else if (pPixFormat->dwFlags & DDPF_PALETTEINDEXED8)
{
HALDeviceFormat = HAL_CI8;
}
else if (pPixFormat->dwFlags & DDPF_LUMINANCE)
{
switch(pPixFormat->dwRGBBitCount)
{
case 8:
if (pPixFormat->dwFlags & DDPF_ALPHAPIXELS)
{
HALDeviceFormat = HAL_A4L4;
}
else
{
HALDeviceFormat = HAL_L8;
}
break;
case 16:
HALDeviceFormat = HAL_A8L8;
break;
default:
HALDeviceFormat = HAL_UNKNOWN;
break;
} // switch
}
else if (pPixFormat->dwFlags & DDPF_ALPHA)
{
// Alpha only format
switch(pPixFormat->dwAlphaBitDepth)
{
case 8:
HALDeviceFormat = HAL_A8;
break;
default:
HALDeviceFormat = HAL_UNKNOWN;
break;
}
}
else
{
switch(pPixFormat->dwRGBBitCount)
{
case 32:
case 24:
if (pPixFormat->dwRGBAlphaBitMask != 0)
{
HALDeviceFormat = HAL_8888_ALPHA;
}
else
{
HALDeviceFormat = HAL_8888_NOALPHA;
}
break;
case 16:
switch (pPixFormat->dwRBitMask)
{
case 0xf00:
HALDeviceFormat = HAL_4444;
break;
case 0x7c00:
if (pPixFormat->dwRGBAlphaBitMask != 0)
{
HALDeviceFormat = HAL_5551_ALPHA;
}
else
{
HALDeviceFormat = HAL_5551_NOALPHA;
}
break;
default:
HALDeviceFormat = HAL_565;
break;
}
break;
case 8:
if (pPixFormat->dwRBitMask != 0xE0)
{
HALDeviceFormat = HAL_2321;
}
else
{
HALDeviceFormat = HAL_332;
}
break;
case 0:
HALDeviceFormat = HAL_CI8;
break;
default:
DISPDBG((ERRLVL,"_DD_SUR_GetSurfaceFormat: "
"Invalid Surface Format"));
break;
} // switch
} // if
}
#if DBG
if (HALDeviceFormat == HAL_UNKNOWN)
{
DISPDBG((ERRLVL,"ERROR: Failed to pick a valid surface format!"));
}
if(SurfaceFormats[HALDeviceFormat].dwBitsPerPixel == 0)
{
DISPDBG((ERRLVL,"ERROR: Chosen surface format that isn't defined "
"in the table!"));
}
#endif // DBG
if (HALDeviceFormat == HAL_UNKNOWN)
{
// Don't know what it is - return a valid type.
return &SurfaceFormats[0];
}
else
{
// Return a pointer to the correct line in the table
return &SurfaceFormats[HALDeviceFormat];
}
} // _DD_SUR_GetSurfaceFormat
//---------------------------------------------------------------------------
// BOOL __SUR_bComparePixelFormat
//
// Function used to compare 2 pixels formats for equality. This is a
// helper function to __SUR_bCheckTextureFormat. A return value of TRUE
// indicates equality
//
//---------------------------------------------------------------------------
BOOL
__SUR_bComparePixelFormat(
LPDDPIXELFORMAT lpddpf1,
LPDDPIXELFORMAT lpddpf2)
{
if (lpddpf1->dwFlags != lpddpf2->dwFlags)
{
return FALSE;
}
// same bitcount for non-YUV surfaces?
if (!(lpddpf1->dwFlags & (DDPF_YUV | DDPF_FOURCC)))
{
if (lpddpf1->dwRGBBitCount != lpddpf2->dwRGBBitCount )
{
return FALSE;
}
}
// same RGB properties?
if (lpddpf1->dwFlags & DDPF_RGB)
{
if ((lpddpf1->dwRBitMask != lpddpf2->dwRBitMask) ||
(lpddpf1->dwGBitMask != lpddpf2->dwGBitMask) ||
(lpddpf1->dwBBitMask != lpddpf2->dwBBitMask) ||
(lpddpf1->dwRGBAlphaBitMask != lpddpf2->dwRGBAlphaBitMask))
{
return FALSE;
}
}
// same YUV properties?
if (lpddpf1->dwFlags & DDPF_YUV)
{
if ((lpddpf1->dwFourCC != lpddpf2->dwFourCC) ||
(lpddpf1->dwYUVBitCount != lpddpf2->dwYUVBitCount) ||
(lpddpf1->dwYBitMask != lpddpf2->dwYBitMask) ||
(lpddpf1->dwUBitMask != lpddpf2->dwUBitMask) ||
(lpddpf1->dwVBitMask != lpddpf2->dwVBitMask) ||
(lpddpf1->dwYUVAlphaBitMask != lpddpf2->dwYUVAlphaBitMask))
{
return FALSE;
}
}
else if (lpddpf1->dwFlags & DDPF_FOURCC)
{
if (lpddpf1->dwFourCC != lpddpf2->dwFourCC)
{
return FALSE;
}
}
// If Interleaved Z then check Z bit masks are the same
if (lpddpf1->dwFlags & DDPF_ZPIXELS)
{
if (lpddpf1->dwRGBZBitMask != lpddpf2->dwRGBZBitMask)
{
return FALSE;
}
}
return TRUE;
} // __SUR_bComparePixelFormat
//---------------------------------------------------------------------------
//
// BOOL __SUR_bCheckTextureFormat
//
// Function used to determine if a texture format is supported. It traverses
// the deviceTextureFormats list. We use this in DdCanCreateSurface. A
// return value of TRUE indicates that we do support the requested texture
// format.
//
//---------------------------------------------------------------------------
BOOL
__SUR_bCheckTextureFormat(
P3_THUNKEDDATA *pThisDisplay,
LPDDPIXELFORMAT lpddpf)
{
DWORD i;
// Run the list for a matching format , we already built the list (when
// the driver was loaded) and stored it in pThisDisplay with
// __D3D_BuildTextureFormatsP3 in _D3DHALCreateDriver (d3d.c)
// Notice the special handling for paletted textures as described in
// __D3D_BuildTextureFormatsP3 (thats why we loop until <= , not just
// until < ).
for (i=0; i <= pThisDisplay->dwNumTextureFormats; i++)
{
if (__SUR_bComparePixelFormat(
lpddpf,
&pThisDisplay->TextureFormats[i].ddpfPixelFormat))
{
return TRUE;
}
}
return FALSE;
} // __SUR_bCheckTextureFormat
//---------------------------------------------------------------------------
//
// DWORD __SUR_bSurfPlacement
//
// Function used to determine if a surface should be placed at the front or
// at the back of our video memory heap.
// Returns the MEM3DL_FRONT and MEM3DL_BACK values.
//
//---------------------------------------------------------------------------
DWORD
__SUR_bSurfPlacement(
LPDDRAWI_DDRAWSURFACE_LCL psurf,
DDSURFACEDESC *lpDDSurfaceDesc)
{
static BOOL bBufferToggle = TRUE;
DWORD dwResult;
if (psurf->ddsCaps.dwCaps & DDSCAPS_TEXTURE)
{
DWORD dwTexturePlacement;
// They might have passed a DDSD2 in a DDSD1 structure.
if (lpDDSurfaceDesc && (lpDDSurfaceDesc->dwSize ==
sizeof(DDSURFACEDESC2)))
{
DDSURFACEDESC2* pDesc2 =
(DDSURFACEDESC2*)lpDDSurfaceDesc;
// Check for the application hint on texture stage placement
if (!(pDesc2->ddsCaps.dwCaps & DDSCAPS_MIPMAP))
{
if (pDesc2->dwFlags & DDSD_TEXTURESTAGE)
{
dwTexturePlacement = pDesc2->dwTextureStage;
// Put it somewhere sensible if it
// is in a large stage number
if (dwTexturePlacement > 1)
{
// Toggle all entries above 1 so that they
// jump between banks.
dwTexturePlacement =
(dwTexturePlacement ^ 1) & 0x1;
}
}
else
{
// No stage hint. PingPong
dwTexturePlacement = bBufferToggle;
bBufferToggle = !bBufferToggle;
}
}
else
{
// No stage hint. PingPong
dwTexturePlacement = bBufferToggle;
bBufferToggle = !bBufferToggle;
}
}
else
{
// No DDSD2, PingPong
dwTexturePlacement = bBufferToggle;
bBufferToggle = !bBufferToggle;
}
// Jump up and down in the one heap
if (dwTexturePlacement == 0)
{
dwResult = MEM3DL_FRONT;
}
else
{
dwResult = MEM3DL_BACK;
}
}
// Not a texture
else
{
dwResult = MEM3DL_FRONT;
}
return dwResult;
} // __SUR_bSurfPlacement
//-----------------------------Public Routine----------------------------------
//
// DdCanCreateSurface
//
// Indicates whether the driver can create a surface of the specified
// surface description
//
// DdCanCreateSurface should check the surface description to which
// lpDDSurfaceDesc points to determine if the driver can support the format and
// capabilities of the requested surface for the mode that the driver is
// currently in. The driver should return DD_OK in ddRVal if it supports the
// surface; otherwise, it should return the DDERR_Xxx error code that best
// describes why it does not support the surface.
//
// The bIsDifferentPixelFormat member is unreliable for z-buffers. Drivers
// should use bIsDifferentPixelFormat only when they have first checked that
// the specified surface is not a z-buffer. Drivers can perform this check by
// determining whether the DDSCAPS_ZBUFFER flag is set in lpDDSurfaceDesc
// ddsCaps.dwCaps.
//
// Parameters
//
// pccsd
// Points to the DD_CANCREATESURFACEDATA structure containing the
// information required for the driver to determine whether a surface
// can be created.
//
// .lpDD
// Points to the DD_DIRECTDRAW_GLOBAL structure representing the
// DirectDraw object.
// .lpDDSurfaceDesc
// Points to a DDSURFACEDESC structure that contains a
// description of the surface to be created.
// .bIsDifferentPixelFormat
// Indicates whether the pixel format of the surface to be
// created differs from the primary surface.
// .ddRVal
// Specifies the location in which the driver writes the return
// value of the DdCanCreateSurface callback. A return code of
// DD_OK indicates success.
// .CanCreateSurface
// This is unused on Windows 2000.
//
//-----------------------------------------------------------------------------
DWORD CALLBACK
DdCanCreateSurface(
LPDDHAL_CANCREATESURFACEDATA pccsd )
{
P3_THUNKEDDATA* pThisDisplay;
DBG_CB_ENTRY(DdCanCreateSurface);
GET_THUNKEDDATA(pThisDisplay, pccsd->lpDD);
VALIDATE_MODE_AND_STATE(pThisDisplay);
// ************************* Z BUFFERS *******************************
// We support 15,16,24 and 32 bits Z-buffers
// (wo accounting for stencil bits) on PERMEDIA3
if ((pccsd->lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_ZBUFFER) &&
(pccsd->lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
{
DWORD dwZBitDepth;
// Check out the case of a z buffer with a pixel format
// Complex surfaces aren't allowed to have stencil bits. In
// this case we take the pixel z depth from the old place - the
// surface desc.
if ((pccsd->lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_COMPLEX) ||
(pccsd->lpDDSurfaceDesc->dwFlags & DDSD_ZBUFFERBITDEPTH) )
{
dwZBitDepth = pccsd->lpDDSurfaceDesc->dwZBufferBitDepth;
}
else
{
// On DX 6 the Z Bit depth is stored in the Pixel Format.
dwZBitDepth =
pccsd->lpDDSurfaceDesc->ddpfPixelFormat.dwZBufferBitDepth;
}
// Notice we have to check for a dwZBitDepth of 16 or 32 even if a
// stencil buffer is present. dwZBufferBitDepth in this case will be
// the sum of the z buffer and the stencil buffer bit depth.
if ((dwZBitDepth == 16) || (dwZBitDepth == 32))
{
pccsd->ddRVal = DD_OK;
}
else
{
DISPDBG((WRNLVL,"DdCanCreateSurface ERROR: "
"Depth buffer not 16 or 32 Bits! (%d)",
dwZBitDepth));
pccsd->ddRVal = DDERR_INVALIDPIXELFORMAT;
}
DBG_CB_EXIT(DdCanCreateSurface, pccsd->ddRVal);
return DDHAL_DRIVER_HANDLED;
}
// *********************** 3D RENDER TARGETS ***************************
if (pccsd->lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_3DDEVICE)
{
// We are going to use this surface as a rendering target
// Notice that this will also cover the case when we're
// trying to create a vidmem texture that will also be used
// as a rendertarget (as we go thorugh this path before
// DDSCAPS_TEXTURE-cap surfaces are processed)
if (!pccsd->bIsDifferentPixelFormat)
{
// we have the same format as the primary . If this is true,
// on DX7 we won't have the ddpfPixelFormat fielded at all.
// But we do support rendertargets and textures of the same
// format as our possible primaries so we return DD_OK
DISPDBG((DBGLVL, "DdCanCreateSurface OK: "
"Same as primary format for "
"rendertarget surface" ));
pccsd->ddRVal = DD_OK;
}
else if( pccsd->lpDDSurfaceDesc->ddpfPixelFormat.dwFlags & DDPF_RGB )
{
DDPIXELFORMAT *pPixFmt =
&pccsd->lpDDSurfaceDesc->ddpfPixelFormat;
// Only 32 and 16 (565) RGB modes allowed.
switch (pPixFmt->dwRGBBitCount)
{
case 32:
DISPDBG((DBGLVL, "DdCanCreateSurface OK: "
"32-bit RGB format for "
"rendertarget surface" ));
pccsd->ddRVal = DD_OK;
break;
case 16:
if ((pPixFmt->dwRBitMask == 0xF800) &&
(pPixFmt->dwGBitMask == 0x07E0) &&
(pPixFmt->dwBBitMask == 0x001F))
{
DISPDBG((DBGLVL, "DdCanCreateSurface OK: "
"16-bit 565 RGB format for "
"rendertarget surface" ));
pccsd->ddRVal = DD_OK;
}
else
{
DISPDBG((WRNLVL, "DdCanCreateSurface ERROR: "
"NOT 16-bit 565 RGB format for "
"16BPP rendertarget surface" ));
pccsd->ddRVal = DDERR_INVALIDPIXELFORMAT;
}
break;
default:
DISPDBG((WRNLVL, "DdCanCreateSurface ERROR: "
"RGB rendertarget not 16 (565) "
"or 32 bit - wrong pixel format" ));
pccsd->ddRVal = DDERR_INVALIDPIXELFORMAT;
break;
}
}
else
{
DISPDBG((WRNLVL, "DdCanCreateSurface ERROR: "
"Rendertarget not an RGB Surface"
" - wrong pixel format" ));
pccsd->ddRVal = DDERR_INVALIDPIXELFORMAT;
}
DBG_CB_EXIT(DdCanCreateSurface, pccsd->ddRVal);
return DDHAL_DRIVER_HANDLED;
}
// *************************** TEXTURES **************************
if(pccsd->lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_TEXTURE)
{
// Notice that the case when we're trying to create a vidmem
// texture that will also be used as a rendertarget has already
// been taken care of when processing the 3D rendertargets case
// as their valid formats are a subset of the valid texture formats
if (!pccsd->bIsDifferentPixelFormat)
{
// we have the same format as the primary . If this is true,
// on DX7 we won't have the ddpfPixelFormat fielded at all.
// but all primary formats are valid for this driver as
// texture formats as well, so succeed this call
DISPDBG((DBGLVL, "DdCanCreateSurface OK: "
"Same as primary format for "
"texture surface" ));
pccsd->ddRVal = DD_OK;
}
// if the surface is going to be a texture verify it matches one
// of the supported texture formats (already stored in pThisDisplay)
else if (__SUR_bCheckTextureFormat(
pThisDisplay,
&pccsd->lpDDSurfaceDesc->ddpfPixelFormat))
{
// texture surface is in one or our supported texture formats
DISPDBG((DBGLVL, " Texture Surface - OK" ));
pccsd->ddRVal = DD_OK;
}
else
{
// we don't support this kind of texture format
DISPDBG((WRNLVL, "DdCanCreateSurface ERROR: "
"Texture Surface format not supported" ));
pccsd->ddRVal = DDERR_INVALIDPIXELFORMAT;
}
DBG_CB_EXIT(DdCanCreateSurface, pccsd->ddRVal);
return DDHAL_DRIVER_HANDLED;
}
// ***********************************************************************
// * OTHER OFFSCREEN SURFACES THAT ARE DIFFERENT FROM THE PRIMARY FORMAT *
// ***********************************************************************
if (pccsd->bIsDifferentPixelFormat)
{
DISPDBG((DBGLVL,"Pixel Format is different to primary"));
if(pccsd->lpDDSurfaceDesc->ddpfPixelFormat.dwFlags & DDPF_FOURCC)
{
DISPDBG((DBGLVL, " FourCC requested (%4.4hs, 0x%08lx)",
(LPSTR) &pccsd->lpDDSurfaceDesc->ddpfPixelFormat.dwFourCC,
pccsd->lpDDSurfaceDesc->ddpfPixelFormat.dwFourCC ));
switch (pccsd->lpDDSurfaceDesc->ddpfPixelFormat.dwFourCC)
{
case FOURCC_YUV422:
DISPDBG((WRNLVL,"DdCanCreateSurface OK: "
"Surface requested is YUV422"));
pccsd->lpDDSurfaceDesc->ddpfPixelFormat.dwYUVBitCount = 16;
pccsd->ddRVal = DD_OK;
break;
// Disabled for now.
case FOURCC_YUV411:
DISPDBG((WRNLVL,"DdCanCreateSurface ERROR: "
"Surface requested is YUV411 - Disabled"));
pccsd->lpDDSurfaceDesc->ddpfPixelFormat.dwYUVBitCount = 32;
pccsd->ddRVal = DDERR_INVALIDPIXELFORMAT;
break;
default:
DISPDBG((WRNLVL,"DdCanCreateSurface ERROR: "
"Invalid FOURCC requested, refusing"));
pccsd->ddRVal = DDERR_INVALIDPIXELFORMAT;
break;
}
DBG_CB_EXIT(DdCanCreateSurface, pccsd->ddRVal);
return DDHAL_DRIVER_HANDLED;
}
//@@BEGIN_DDKSPLIT
// azn check if the following variations are now still needed
//@@END_DDKSPLIT
// Luminance texture support
else if( (pccsd->lpDDSurfaceDesc->ddpfPixelFormat.dwFlags
& DDPF_LUMINANCE) &&
!(pccsd->lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_OVERLAY) )
{
DDPIXELFORMAT *pddpfCur;
// Only 16 and 8-bit modes allowed.
pddpfCur = &(pccsd->lpDDSurfaceDesc->ddpfPixelFormat);
if (pddpfCur->dwLuminanceBitCount == 8)
{
// Check for L8
if (!(pccsd->lpDDSurfaceDesc->ddpfPixelFormat.dwFlags &
DDPF_ALPHAPIXELS))
{
DISPDBG((DBGLVL, "DdCanCreateSurface OK: "
" 8 Bit Luminance surface"));
pccsd->ddRVal = DD_OK;
}
// Must be A4:L4
else
{
DISPDBG((DBGLVL, "DdCanCreateSurface OK: "
"4 Bit Luma + 4 Bit Alpha surface"));
pccsd->ddRVal = DD_OK;
}
}
// Check for A8L8
else if (pddpfCur->dwLuminanceBitCount == 16)
{
if (pccsd->lpDDSurfaceDesc->ddpfPixelFormat.dwFlags &
DDPF_ALPHAPIXELS)
{
DISPDBG((DBGLVL, "DdCanCreateSurface OK: "
" 16 Bit Luminance + Alpha Surface"));
pccsd->ddRVal = DD_OK;
}
else
{
DISPDBG((WRNLVL, "DdCanCreateSurface ERROR: "
"Bad A8L8 format" ));
pccsd->ddRVal = DDERR_INVALIDPIXELFORMAT;
}
}
else
{
DISPDBG((WRNLVL, "DdCanCreateSurface ERROR: "
"Unknown luminance texture" ));
pccsd->ddRVal = DDERR_INVALIDPIXELFORMAT;
}
DBG_CB_EXIT(DdCanCreateSurface, pccsd->ddRVal);
return DDHAL_DRIVER_HANDLED;
}
else if( (pccsd->lpDDSurfaceDesc->ddpfPixelFormat.dwFlags &
DDPF_ALPHA) &&
!(pccsd->lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_OVERLAY))
{
DDPIXELFORMAT *pddpfCur;
pddpfCur = &(pccsd->lpDDSurfaceDesc->ddpfPixelFormat);
if (pddpfCur->dwAlphaBitDepth == 8)
{
DISPDBG((DBGLVL, "DdCanCreateSurface OK: "
"8 Bit Alpha surface"));
pccsd->ddRVal = DD_OK;
}
else
{
DISPDBG((WRNLVL, "DdCanCreateSurface ERROR: "
"pddpfCur->dwAlphaBitDepth != 8" ));
pccsd->ddRVal = DDERR_INVALIDPIXELFORMAT;
}
DBG_CB_EXIT(DdCanCreateSurface, pccsd->ddRVal);
return DDHAL_DRIVER_HANDLED;
}
else if( pccsd->lpDDSurfaceDesc->ddpfPixelFormat.dwFlags & DDPF_RGB )
{
DDPIXELFORMAT *pddpfCur;
// Only 32, 16 and 8-bit modes allowed.
pddpfCur = &(pccsd->lpDDSurfaceDesc->ddpfPixelFormat);
switch ( pddpfCur->dwRGBBitCount )
{
case 32:
DISPDBG((DBGLVL, "DdCanCreateSurface OK: "
"RGB 32-bit surface" ));
pccsd->ddRVal = DD_OK;
break;
case 16:
DISPDBG((DBGLVL, "DdCanCreateSurface OK: "
"RGB 16-bit surface" ));
pccsd->ddRVal = DD_OK;
break;
case 8:
DISPDBG((DBGLVL, "DdCanCreateSurface OK: "
"RGB 8-bit Surface" ));
pccsd->ddRVal = DD_OK;
break;
default:
DISPDBG((WRNLVL, "DdCanCreateSurface ERROR: "
"RGB Surface - wrong pixel format" ));
pccsd->ddRVal = DDERR_INVALIDPIXELFORMAT;
break;
}
DBG_CB_EXIT(DdCanCreateSurface, pccsd->ddRVal);
return DDHAL_DRIVER_HANDLED;
}
// Since its a different from the primary surface and doesn't fall
// into any of the previous cases, we fail it
DISPDBG((WRNLVL, "DdCanCreateSurface ERROR: "
"Different from the primary surface but unknown" ));
pccsd->ddRVal = DDERR_INVALIDPIXELFORMAT;
DBG_CB_EXIT(DdCanCreateSurface, pccsd->ddRVal);
return DDHAL_DRIVER_HANDLED;
}
// Same format as the primary, we succeed it anyway
DISPDBG((DBGLVL, "DdCanCreateSurface OK: (Def) Same format as primary" ));
pccsd->ddRVal = DD_OK;
DBG_CB_EXIT(DdCanCreateSurface, pccsd->ddRVal);
return DDHAL_DRIVER_HANDLED;
} // DdCanCreateSurface
//-----------------------------Public Routine----------------------------------
//
// DdCreateSurface
//
// Creates a DirectDraw surface.
//
// The driver can allocate the surface memory itself or can request that
// DirectDraw perform the memory management. If the driver performs the
//allocation, it must do the following:
//
// Perform the allocation and write a valid pointer to the memory in the
// fpVidMem member of the DD_SURFACE_GLOBAL structure.
// If the surface has a FourCC format, write the pitch in the lPitch member of
// the DD_SURFACE_GLOBAL and DDSURFACEDESC structures, and update the flags
// accordingly.
//
// Otherwise, the driver can have DirectDraw allocate the surface by returning
// one of the following values in fpVidMem:
//
// DDHAL_PLEASEALLOC_BLOCKSIZE requests that DirectDraw allocate the
// surface memory from offscreen memory.
// DDHAL_PLEASEALLOC_USERMEM requests that DirectDraw allocate the
// surface memory from user memory. The
// driver must also return the size in
// bytes of the memory region in dwUserMemSize.
//
// For DirectDraw to perform the allocation of a surface with a FourCC format,
// the driver must also return the pitch and x- and y-block sizes in lPitch,
// dwBlockSizeX, and dwBlockSizeY, respectively. The pitch must be returned in
// the lPitch member of both the DD_SURFACE_GLOBAL and DDSURFACEDESC structures.
// For linear memory, the driver should set dwBlockSizeX to be the size in bytes
// of the memory region and set dwBlockSizeY to 1.
//
// By default, the driver is not notified when a primary surface is created on
// Windows 2000. However, if the driver supports GUID_NTPrivateDriverCaps and
// the DDHAL_PRIVATECAP_NOTIFYPRIMARYCREATION flag is set, then the driver will
// be notified.
//
// Parameters
//
// pcsd
// Points to a DD_CREATESURFACEDATA structure that contains the
// information required to create a surface.
//
// .lpDD
// Points to the DD_DIRECTDRAW_GLOBAL structure representing the
// driver.
// .lpDDSurfaceDesc
// Points to the DDSURFACEDESC structure describing the surface
// that the driver should create.
// .lplpSList
// Points to a list of DD_SURFACE_LOCAL structures describing
// the surface objects created by the driver. On Windows 2000,
// there is usually only one entry in this array. However, if
// the driver supports the Windows 95/98-style surface creation
// techniques using DdGetDriverInfo with GUID_NTPrivateDriverCaps,
// and the driver sets the DDHAL_PRIVATECAP_ATOMICSURFACECREATION
// flag, the member will contain a list of surfaces (usually more
// than one).
// .dwSCnt
// Specifies the number of surfaces in the list to which lplpSList
// points. This value is usually 1 on Windows 2000. However, if
// you support the Windows 95/Windows98-style surface creation
// techniques using DdGetDriverInfo with GUID_NTPrivateDriverCaps,
// the member will contain the actual number of surfaces in the
// list (usually more than one).
// .ddRVal
// Specifies the location in which the driver writes the return
// value of the DdCreateSurface callback. A return code of DD_OK
// indicates success.
// .CreateSurface
// This is unused on Windows 2000.
//
//-----------------------------------------------------------------------------
DWORD CALLBACK
DdCreateSurface(
LPDDHAL_CREATESURFACEDATA pcsd )
{
int i;
DWORD BitDepth;
LPDDRAWI_DDRAWSURFACE_LCL psurf;
LPDDRAWI_DDRAWSURFACE_GBL psurf_gbl;
LPDDRAWI_DDRAWSURFACE_MORE psurf_more;
BOOL bHandled = TRUE;
BOOL bResize = FALSE;
P3_THUNKEDDATA* pThisDisplay;
DWORD dwExtraBytes;
DBG_CB_ENTRY(DdCreateSurface);
GET_THUNKEDDATA(pThisDisplay, pcsd->lpDD);
VALIDATE_MODE_AND_STATE(pThisDisplay);
STOP_SOFTWARE_CURSOR(pThisDisplay);
DDRAW_OPERATION(pContext, pThisDisplay);
for( i=0; i<(int)pcsd->dwSCnt; i++ )
{
DDPIXELFORMAT* pPixFormat = NULL;
psurf = pcsd->lplpSList[i];
psurf_gbl = psurf->lpGbl;
psurf_more = psurf->lpSurfMore;
// Dump debug info about the surface to be created
DISPDBG((DBGLVL, "\nLooking at Surface %d of %d", i + 1, pcsd->dwSCnt));
DISPDBG((DBGLVL,"Surf dimensions: %d x %d", psurf_gbl->wWidth,
psurf_gbl->wHeight ));
DBGDUMP_DDRAWSURFACE_LCL(DBGLVL, psurf);
DISPDBG((DBGLVL, "DdCreateSurface setting NULL"));
psurf_gbl->fpVidMem = 0;
// Get the bitdepth of the surface
BitDepth = DDSurf_BitDepth(psurf);
// All Z buffers need adjusting, and setting the correct bit depth
if (DDSurf_HasPixelFormat(psurf->dwFlags))
{
if (psurf_gbl->ddpfSurface.dwFlags & DDPF_ZBUFFER)
{
DISPDBG((DBGLVL,"Surface is Z Buffer"));
BitDepth = psurf_gbl->ddpfSurface.dwZBufferBitDepth;
// Force the pitch to the correct value - the DX runtime
// sometimes sends us a duff value.
psurf_gbl->lPitch = psurf_gbl->wWidth << ( BitDepth >> 4 );
// Ddraw surfaces in IA64 have to be DWORD aligned in their
// pitch in order for emulation code to work correctly
// And on X86 we declared surfaces will be DWORD aligned in
// DrvGetDirectDrawInfo (vmiData.dwXXXXXAlign = 4)
psurf_gbl->lPitch = MAKE_DWORD_ALIGNED(psurf_gbl->lPitch);
}
}
// Determine if we need to resize the surface to make it fit.
bResize = FALSE;
// The surface is a YUV format surface
if (DDSurf_HasPixelFormat(psurf->dwFlags))
{
if (psurf_gbl->ddpfSurface.dwFlags & DDPF_FOURCC)
{
bResize = TRUE;
switch( psurf_gbl->ddpfSurface.dwFourCC )
{
case FOURCC_YUV422:
DISPDBG((DBGLVL,"Surface is YUV422"));
psurf_gbl->ddpfSurface.dwYUVBitCount = 16;
BitDepth = 16;
break;
case FOURCC_YUV411:
DISPDBG((DBGLVL,"Surface is YUV411"));
psurf_gbl->ddpfSurface.dwYUVBitCount = 32;
BitDepth = 32;
break;
default:
// We should never get here, as CanCreateSurface will
// validate the YUV format for us.
DISPDBG((ERRLVL,"Trying to create an invalid YUV surface!"));
break;
}
}
}
DISPDBG((DBGLVL,"Surface Pitch is: 0x%x", psurf_gbl->lPitch));
// This flag is set if the surface needs resizing.
if (bResize)
{
DWORD dwNewWidth = psurf_gbl->wWidth;
DWORD dwNewHeight = psurf_gbl->wHeight;
DWORD dwHeightAlignment = 1;
DWORD dwWidthAlignment = 1;
DISPDBG((DBGLVL, "Resizing surface"));
while ((dwNewWidth % dwWidthAlignment) != 0) dwNewWidth++;
while ((dwNewHeight % dwHeightAlignment) != 0) dwNewHeight++;
DISPDBG((DBGLVL,"Surface original = %d x %d, Surface new = %d x %d",
psurf_gbl->wWidth, psurf_gbl->wHeight,
dwNewWidth, dwNewHeight));
psurf_gbl->fpVidMem = (FLATPTR) DDHAL_PLEASEALLOC_BLOCKSIZE;
psurf_gbl->lPitch = (DWORD)(dwNewWidth * (BitDepth / 8));
// Ddraw surfaces in IA64 have to be DWORD aligned in their
// pitch in order for emulation code to work correctly
// And on X86 we declared surfaces will be DWORD aligned in
// DrvGetDirectDrawInfo (vmiData.dwXXXXXAlign = 4)
psurf_gbl->lPitch = MAKE_DWORD_ALIGNED(psurf_gbl->lPitch);
psurf_gbl->dwBlockSizeX = (DWORD)((DWORD)dwNewHeight *
(DWORD)psurf_gbl->lPitch );
psurf_gbl->dwBlockSizeY = 1;
}
else
{
psurf_gbl->lPitch = (DWORD)(psurf_gbl->wWidth * (BitDepth / 8));
// Ddraw surfaces in IA64 have to be DWORD aligned in their
// pitch in order for emulation code to work correctly
// And on X86 we declared surfaces will be DWORD aligned in
// DrvGetDirectDrawInfo (vmiData.dwXXXXXAlign = 4)
psurf_gbl->lPitch = MAKE_DWORD_ALIGNED(psurf_gbl->lPitch);
#if DX8_3DTEXTURES
if (psurf_more->ddsCapsEx.dwCaps2 & DDSCAPS2_VOLUME)
{
// Put slice pitch into dwBlockSizeY.
psurf_gbl->dwBlockSizeY = psurf_gbl->lPitch *
psurf_gbl->wHeight;
}
#endif // DX8_3DTEXTURES
}
#if DX7_TEXMANAGEMENT
// If this is going to be a driver managed texture we'll request DX to
// allocate it in a private area in system user memory for us.
if (psurf_more->ddsCapsEx.dwCaps2 & DDSCAPS2_TEXTUREMANAGE)
{
pcsd->lpDDSurfaceDesc->lPitch = psurf_gbl->lPitch;
pcsd->lpDDSurfaceDesc->dwFlags |= DDSD_PITCH;
if (pcsd->lpDDSurfaceDesc->dwFlags & DDSD_PIXELFORMAT)
{
pcsd->lpDDSurfaceDesc->lPitch =
psurf_gbl->lPitch =
((pcsd->lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount*
psurf_gbl->wWidth+31)/32)*4; //make it DWORD aligned
// Ddraw surfaces in IA64 have to be DWORD aligned in their
// pitch in order for emulation code to work correctly
// And on X86 we declared surfaces will be DWORD aligned in
// DrvGetDirectDrawInfo (vmiData.dwXXXXXAlign = 4)
pcsd->lpDDSurfaceDesc->lPitch =
psurf_gbl->lPitch = MAKE_DWORD_ALIGNED(psurf_gbl->lPitch);
}
#if WNT_DDRAW
psurf_gbl->dwUserMemSize = psurf_gbl->lPitch *
(DWORD)(psurf_gbl->wHeight);
psurf_gbl->fpVidMem = DDHAL_PLEASEALLOC_USERMEM;
pcsd->ddRVal = DD_OK;
DBG_CB_EXIT(DdCreateSurface, pcsd->ddRVal);
return DDHAL_DRIVER_NOTHANDLED;
#else
// Assume all the memory allocation will succeed
if (i == 0)
{
bHandled = TRUE;
}
psurf_gbl->fpVidMem = (FLATPTR)HEAP_ALLOC(FL_ZERO_MEMORY,
psurf_gbl->lPitch*psurf_gbl->wHeight,
ALLOC_TAG_DX(M));
if (psurf_gbl->fpVidMem)
{
// Move on to the next MIP level, skip calling VRAM allocator
continue;
}
else
{
pcsd->ddRVal = DDERR_OUTOFMEMORY;
DBG_CB_EXIT(DdCreateSurface, pcsd->ddRVal);
return DDHAL_DRIVER_HANDLED;
}
#endif
}
#endif // DX7_TEXMANAGEMENT
// If its not to be created in AGP memory and its not the primary
// then we allocate the memory using our videomemory allocator
if ((!(psurf->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)) &&
(!(psurf->ddsCaps.dwCaps & DDSCAPS_NONLOCALVIDMEM)))
{
P3_MEMREQUEST mmrq;
DWORD dwResult;
memset(&mmrq, 0, sizeof(P3_MEMREQUEST));
mmrq.dwSize = sizeof(P3_MEMREQUEST);
// Compute what size should be requested for the surface allocation
#if DX8_3DTEXTURES
if (psurf_more->ddsCapsEx.dwCaps2 & DDSCAPS2_VOLUME)
{
if (bResize)
{
DISPDBG((ERRLVL,"No volume with block size alloc"));
}
else
{
// the depth of volume texture is given in
// ddsCapsEx.dwCaps4.
mmrq.dwBytes = (DWORD)psurf_gbl->lPitch *
(DWORD)psurf_gbl->wHeight *
(DWORD)psurf_more->ddsCapsEx.dwCaps4;
}
}
else
#endif // DX8_3DTEXTURES
{
if (bResize)
{
mmrq.dwBytes = psurf_gbl->dwBlockSizeX *
psurf_gbl->dwBlockSizeY;
}
else
{
mmrq.dwBytes = (DWORD)psurf_gbl->lPitch *
(DWORD)psurf_gbl->wHeight;
}
}
// 16 Byte alignment will work for everything
mmrq.dwAlign = 16;
// Figure out where in the video mem to place it
mmrq.dwFlags = MEM3DL_FIRST_FIT;
if(__SUR_bSurfPlacement(psurf,
pcsd->lpDDSurfaceDesc) == MEM3DL_FRONT)
{
mmrq.dwFlags |= MEM3DL_FRONT;
}
else
{
mmrq.dwFlags |= MEM3DL_BACK;
}
DISPDBG((DBGLVL,"DdCreateSurface allocating vidmem for handle #%d",
psurf->lpSurfMore->dwSurfaceHandle));
// Try allocating it in our video memory
dwResult = _DX_LIN_AllocateLinearMemory(
&pThisDisplay->LocalVideoHeap0Info,
&mmrq);
// Did we got the memory we asked for?
if (dwResult != GLDD_SUCCESS)
{
// If we have an AGP heap and it is a texture request,
// don't give up - ask DDRAW to allocate it for us.
if ((pThisDisplay->bCanAGP) &&
((psurf->ddsCaps.dwCaps & DDSCAPS_TEXTURE ) ||
(psurf->ddsCaps.dwCaps & DDSCAPS_OFFSCREENPLAIN) ))
{
DISPDBG((WRNLVL,"No texture VideoMemory left, "
"going for AGP"));
psurf->ddsCaps.dwCaps &= ~DDSCAPS_LOCALVIDMEM;
psurf->ddsCaps.dwCaps |= DDSCAPS_NONLOCALVIDMEM;
}
else
{
psurf_gbl->fpVidMem = 0;
DISPDBG((ERRLVL, "DdCreateSurface: failed, "
"returning NULL"));
pcsd->ddRVal = DDERR_OUTOFVIDEOMEMORY;
START_SOFTWARE_CURSOR(pThisDisplay);
DBG_CB_EXIT(DdCreateSurface, pcsd->ddRVal);
return DDHAL_DRIVER_HANDLED;
}
}
else
{
// We succeeded. Now update the fpVidMem of the surface
psurf_gbl->fpVidMem = mmrq.pMem;
}
}
#if WNT_DDRAW
// NT requires us to set some things up differently
pcsd->lpDDSurfaceDesc->lPitch = psurf_gbl->lPitch;
pcsd->lpDDSurfaceDesc->dwFlags |= DDSD_PITCH;
#endif
// Mark the surface with the correct video memory type
if (psurf->ddsCaps.dwCaps & DDSCAPS_NONLOCALVIDMEM)
{
DISPDBG((DBGLVL,"Surface is in AGP memory"));
ASSERTDD(pThisDisplay->bCanAGP,
"** DdCreateSurface: Somehow managed to create an AGP "
"texture when AGP disabled" );
psurf->ddsCaps.dwCaps &= ~DDSCAPS_LOCALVIDMEM;
psurf->ddsCaps.dwCaps |= DDSCAPS_NONLOCALVIDMEM;
// let DDraw manage AGP memory (return DDHAL_DRIVER_NOTHANDLED)
// THIS IS ABSOLUTELY NECESSARY IF WE WANT DDRAW TO ALLOCTE THIS!
bHandled = FALSE;
}
else
{
DISPDBG((DBGLVL,"Surface in Local Video Memory"));
psurf->ddsCaps.dwCaps &= ~DDSCAPS_NONLOCALVIDMEM;
psurf->ddsCaps.dwCaps |= DDSCAPS_LOCALVIDMEM;
}
DISPDBG((DBGLVL, "DdCreateSurface: Surface=0x%08x, vidMem=0x%08x",
psurf, psurf_gbl->fpVidMem));
} // for i
START_SOFTWARE_CURSOR(pThisDisplay);
//
// If we allocated the memory successfully then we return OK and
// say that we handled it. Otherwise we should return DDHAL_DRIVER_NOTHANDLED
//
if(bHandled)
{
pcsd->ddRVal = DD_OK;
DBG_CB_EXIT(DdCreateSurface, pcsd->ddRVal);
return DDHAL_DRIVER_HANDLED;
}
else
{
// if we return handled, then it is assumed that we did SOMETHING
// with the surface structures to indicate either what size of block
// or a new pitch or some modification; or we are returning an error.
DBG_CB_EXIT(DdCreateSurface, pcsd->ddRVal);
return DDHAL_DRIVER_NOTHANDLED;
}
} // DdCreateSurface
//-----------------------------Public Routine----------------------------------
//
// DdDestroySurface
//
// Destroys a DirectDraw surface.
//
// If DirectDraw did the memory allocation at surface creation time,
// DdDestroySurface should return DDHAL_DRIVER_NOTHANDLED.
//
// If the driver is performing the surface memory management itself,
// DdDestroySurface should free the surface memory and perform any other
// cleanup, such as freeing private data stored in the dwReserved1 members
// of the DD_SURFACE_GLOBAL and DD_SURFACE_LOCAL structures.
//
// Parameters
//
// psdd
// Points to a DD_DESTROYSURFACEDATA structure that contains the
// information needed to destroy a surface.
//
// .lpDD
// Points to the DD_DIRECTDRAW_GLOBAL structure that describes
// the driver.
// .lpDDSurface
// Points to the DD_SURFACE_LOCAL structure representing the
// surface object to be destroyed.
// .ddRVal
// Specifies the location in which the driver writes the return
// value of the DdDestroySurface callback. A return code of
// DD_OK indicates success.
// .DestroySurface
// This is unused on Windows 2000.
//
//-----------------------------------------------------------------------------
DWORD CALLBACK
DdDestroySurface(
LPDDHAL_DESTROYSURFACEDATA psdd )
{
P3_THUNKEDDATA* pThisDisplay;
DBG_CB_ENTRY(DdDestroySurface);
GET_THUNKEDDATA(pThisDisplay, psdd->lpDD);
// make sure the DMA buffer is flushed and
// complete before we destroy any surface
STOP_SOFTWARE_CURSOR(pThisDisplay);
{
P3_DMA_DEFS();
DDRAW_OPERATION(pContext, pThisDisplay);
P3_DMA_GET_BUFFER();
P3_DMA_FLUSH_BUFFER();
WAIT_DMA_COMPLETE;
}
START_SOFTWARE_CURSOR(pThisDisplay);
DISPDBG((DBGLVL,"DdDestroySurface handle # %d",
psdd->lpDDSurface->lpSurfMore->dwSurfaceHandle));
// If we are destroying a videomemory surface which isn't the primary,
// we'll need to free ourselves the memory as the driver is managing
// its own local video memory (though non-local/AGP memory is being
// managed by DirectDraw)
if ((!(psdd->lpDDSurface->ddsCaps.dwCaps & DDSCAPS_NONLOCALVIDMEM)) &&
(!(psdd->lpDDSurface->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)))
{
#if DX7_TEXMANAGEMENT
// If this is a driver managed texture surface, we need to make sure
// it is deallocated from video memory before proceeding.
if (psdd->lpDDSurface->lpSurfMore->ddsCapsEx.dwCaps2 &
DDSCAPS2_TEXTUREMANAGE)
{
if (psdd->lpDDSurface->dwFlags & DDRAWISURF_INVALID)
{
// This is not a surface destruction,
// but a managed surface eviction
#if W95_DDRAW
// On Win2k, managed textures are evicted from video memory by
// _DD_TM_EvictAllManagedTextures() when mode change happens.
_D3D_TM_RemoveDDSurface(pThisDisplay, psdd->lpDDSurface);
#endif
psdd->ddRVal= DD_OK;
DBG_CB_EXIT(DdDestroySurface, psdd->ddRVal);
return DDHAL_DRIVER_HANDLED;
}
else
{
// Normal destruction of managed surface
_D3D_TM_RemoveDDSurface(pThisDisplay, psdd->lpDDSurface);
#if W95_DDRAW
// On Win2k, runtime will free the system memory for drivers.
if (psdd->lpDDSurface->lpGbl->fpVidMem)
{
HEAP_FREE((LPVOID)psdd->lpDDSurface->lpGbl->fpVidMem);
}
#endif
}
}
else
#endif
{
// Have no memory to free in error recovery case
if (psdd->lpDDSurface->lpGbl->fpVidMem)
{
_DX_LIN_FreeLinearMemory(&pThisDisplay->LocalVideoHeap0Info,
(DWORD)(psdd->lpDDSurface->lpGbl->fpVidMem));
}
}
// Must reset the surface pointer to NULL
DISPDBG((DBGLVL, "DdDestroySurface: setting ptr to NULL"));
psdd->lpDDSurface->lpGbl->fpVidMem = 0;
psdd->lpDDSurface->lpGbl->dwReserved1 = 0;
psdd->ddRVal = DD_OK;
DBG_CB_EXIT(DdDestroySurface, psdd->ddRVal);
return DDHAL_DRIVER_HANDLED;
}
else
{
DISPDBG((WRNLVL, "DdDestroySurface: **NOT** setting ptr to NULL"));
psdd->lpDDSurface->lpGbl->dwReserved1 = 0;
psdd->ddRVal = DD_OK;
DBG_CB_EXIT(DdDestroySurface, psdd->ddRVal);
return DDHAL_DRIVER_NOTHANDLED;
}
} // DdDestroySurface
//-----------------------------Public Routine----------------------------------
//
// DdSetColorKey
//
// Sets the color key value for the specified surface.
//
// DdSetColorKey sets the source or destination color key for the specified
// surface. Typically, this callback is implemented only for drivers that
// support overlays with color key capabilities.
//
// Parameters
//
// psckd
// Points to a DD_SETCOLORKEYDATA structure that contains the
// information required to set the color key for the specified surface.
//
// .lpDD
// Points to the DD_DIRECTDRAW_GLOBAL structure that describes
// the driver.
// .lpDDSurface
// Points to the DD_SURFACE_LOCAL structure that describes the
// surface with which the color key is to be associated.
// .dwFlags
// Specifies which color key is being requested. This member is
// a bit-wise OR of any of the following values:
//
// DDCKEY_COLORSPACE
// The DDCOLORKEY structure contains a color space. If
// this bit is not set, the structure contains a single
// color key.
// DDCKEY_DESTBLT
// The DDCOLORKEY structure specifies a color key or color
// space to be used as a destination color key for blit
// operations.
// DDCKEY_DESTOVERLAY
// The DDCOLORKEY structure specifies a color key or color
// space to be used as a destination color key for overlay
// operations.
// DDCKEY_SRCBLT
// The DDCOLORKEY structure specifies a color key or color
// space to be used as a source color key for blit
// operations.
// DDCKEY_SRCOVERLAY
// The DDCOLORKEY structure specifies a color key or color
// space to be used as a source color key for overlay
// operations.
// .ckNew
// Specifies a DDCOLORKEY structure that specifies the new color
// key values for the DirectDrawSurface object.
// .ddRVal
// Specifies the location in which the driver writes the return
// value of the DdSetColorKey callback. A return code of DD_OK
// indicates success.
// .SetColorKey
// This is not used on Windows 2000.
//
//-----------------------------------------------------------------------------
DWORD CALLBACK
DdSetColorKey(
LPDDHAL_SETCOLORKEYDATA psckd)
{
P3_THUNKEDDATA* pThisDisplay;
DBG_CB_ENTRY(DdSetColorKey);
GET_THUNKEDDATA(pThisDisplay, psckd->lpDD);
//@@BEGIN_DDKSPLIT
#if 0
// Also, see if this colour key is the one used by the overlay.
// Yes, we should check that various surfaces agree and so on,
// but can we assume apps are not going to set these flags if there is
// no overlay active/appropriate?
if ( psckd->dwFlags & DDCKEY_DESTOVERLAY )
{
pThisDisplay->OverlayDstColourKey = psckd->ckNew.dwColorSpaceLowValue;
}
#endif
//@@END_DDKSPLIT
// We have to keep track of colorkey changes for D3D videomemory textures
// associated with (some) D3D context. We don't know however from this call
// which D3D context this is so we have to do a search through them (if
// there are any at all)
if ((DDSCAPS_TEXTURE & psckd->lpDDSurface->ddsCaps.dwCaps) &&
(DDSCAPS_VIDEOMEMORY & psckd->lpDDSurface->ddsCaps.dwCaps) &&
(pThisDisplay->pDirectDrawLocalsHashTable != NULL))
{
DWORD dwSurfaceHandle = psckd->lpDDSurface->lpSurfMore->dwSurfaceHandle;
PointerArray* pSurfaceArray;
// For now we'll assume failure unless proven otherwise
psckd->ddRVal = DDERR_INVALIDPARAMS;
// Get a pointer to an array of surface pointers associated to this lpDD
// The PDD_DIRECTDRAW_LOCAL was stored at D3DCreateSurfaceEx call time
// in PDD_SURFACE_LOCAL->dwReserved1
pSurfaceArray = (PointerArray*)
HT_GetEntry(pThisDisplay->pDirectDrawLocalsHashTable,
psckd->lpDDSurface->dwReserved1);
if (pSurfaceArray)
{
// Found a surface array associated to this lpDD !
P3_SURF_INTERNAL* pSurfInternal;
// Check the surface in this array associated to this surface handle
pSurfInternal = PA_GetEntry(pSurfaceArray, dwSurfaceHandle);
if (pSurfInternal)
{
// Got it! Now update the color key setting(s)
pSurfInternal->dwFlagsInt |= DDRAWISURF_HASCKEYSRCBLT;
pSurfInternal->dwCKLow = psckd->ckNew.dwColorSpaceLowValue;
pSurfInternal->dwCKHigh = psckd->ckNew.dwColorSpaceHighValue;
// Report success!
psckd->ddRVal = DD_OK;
}
}
}
else
{
// No D3D colorkey tracking necessary
psckd->ddRVal = DD_OK;
}
DBG_CB_EXIT(DdSetColorKey, psckd->ddRVal);
return DDHAL_DRIVER_HANDLED;
} // DdSetColorKey
//-----------------------------Public Routine----------------------------------
//
// DdGetAvailDriverMemory
//
// DdGetAvailDriverMemory queries the amount of free memory in the driver
// managed memory heap. This function does not need to be implemented if the
// memory will be managed by DirectDraw.
//
// DdGetAvailDriverMemory determines how much free memory is in the driver's
// private heaps for the specified surface type. The driver should check the
// surface capabilities specified in DDSCaps against the heaps that it is
// maintaining internally to determine which heap size to query. For example,
// if DDSCAPS_NONLOCALVIDMEM is set, the driver should return only
// contributions from the AGP heaps.
//
// The driver indicates its support of DdGetAvailDriverMemory by implementing a
// response to GUID_MiscellaneousCallbacks in DdGetDriverInfo.
//
// Parameters
//
// pgadmd
// Points to a DD_GETAVAILDRIVERMEMORYDATA structure that contains the
// information required to perform the query.
//
// lpDD
// Points to the DD_DIRECTDRAW_GLOBAL structure that describes
// the driver.
// DDSCaps
// Points to a DDSCAPS structure that describes the type of
// surface for which memory availability is being queried.
// The DDSCAPS structure is defined in ddraw.h.
// dwTotal
// Specifies the location in which the driver returns the
// number of bytes of driver-managed memory that can be used
// for surfaces of the type described by DDSCaps.
// dwFree
// Specifies the location in which the driver returns the
// amount of free memory, in bytes, for the surface type
// described by DDSCaps.
// ddRVal
// Specifies the location in which the driver writes the
// return value of the DdGetAvailDriverMemory callback. A
// return code of DD_OK indicates success.
// GetAvailDriverMemory
// This is unused on Windows 2000.
//
// Return Value
// DdGetAvailDriverMemory returns one of the following callback codes:
//
// DDHAL_DRIVER_HANDLED
// DDHAL_DRIVER_NOTHANDLED
//
// Comments
//
// DdGetAvailDriverMemory determines how much free memory is in the
// driver's private heaps for the specified surface type. The driver
// should check the surface capabilities specified in DDSCaps against
// the heaps that it is maintaining internally to determine which heap
// size to query. For example, if DDSCAPS_NONLOCALVIDMEM is set, the
// driver should return only contributions from the AGP heaps.
//
//-----------------------------------------------------------------------------
DWORD CALLBACK
DdGetAvailDriverMemory(
LPDDHAL_GETAVAILDRIVERMEMORYDATA pgadmd)
{
P3_THUNKEDDATA* pThisDisplay;
DBG_CB_ENTRY(DdGetAvailDriverMemory);
GET_THUNKEDDATA(pThisDisplay, pgadmd->lpDD);
VALIDATE_MODE_AND_STATE(pThisDisplay);
DISPDBG((DBGLVL, "Heap0: dwMemStart:0x%x, dwMemEnd:0x%x",
pThisDisplay->LocalVideoHeap0Info.dwMemStart,
pThisDisplay->LocalVideoHeap0Info.dwMemEnd));
pgadmd->ddRVal = DD_OK;
if (pgadmd->DDSCaps.dwCaps & DDSCAPS_NONLOCALVIDMEM)
{
DISPDBG((DBGLVL," Not returning AGP heap free memory "
"(we don't manage it)"));
DBG_CB_EXIT(DdGetAvailDriverMemory, pgadmd->ddRVal);
return DDHAL_DRIVER_NOTHANDLED;
}
else
{
pgadmd->dwTotal = pThisDisplay->LocalVideoHeap0Info.dwMaxChunks *
pThisDisplay->LocalVideoHeap0Info.dwMemPerChunk;
pgadmd->dwFree =
_DX_LIN_GetFreeMemInHeap(&pThisDisplay->LocalVideoHeap0Info);
}
DISPDBG((DBGLVL," Returning %d TotalMem, of which %d free",
pgadmd->dwTotal, pgadmd->dwFree));
DBG_CB_EXIT(DdGetAvailDriverMemory, pgadmd->ddRVal);
return DDHAL_DRIVER_HANDLED;
} // DdGetAvailDriverMemory
#if W95_DDRAW
//-----------------------------------------------------------------------------
//
// __FindAGPHeap
//
//-----------------------------------------------------------------------------
static void
__FindAGPHeap(
P3_THUNKEDDATA* pThisDisplay,
LPDDRAWI_DIRECTDRAW_GBL lpDD )
{
VIDMEMINFO MemInfo = lpDD->vmiData;
LPVIDMEM pStartHeap;
LPVIDMEM pCurrentHeap = NULL;
BOOL bFoundAGPHeap = FALSE;
if ((pThisDisplay->bCanAGP) &&
(pThisDisplay->dwGARTDev != 0) &&
(MemInfo.dwNumHeaps) &&
(MemInfo.pvmList))
{
int i;
// Look around for a good AGP heap
pStartHeap = MemInfo.pvmList;
for (i = 0; i < (int)MemInfo.dwNumHeaps; i++)
{
pCurrentHeap = pStartHeap + i;
if (pCurrentHeap->dwFlags & VIDMEM_ISNONLOCAL)
{
bFoundAGPHeap = TRUE;
break;
}
}
} else {
DISPDBG((ERRLVL,"Unable to allocate AGP memory (AllocatePrivAGPMem)"));
}
if(!bFoundAGPHeap)
{
DISPDBG((ERRLVL,"Unable to locate AGP heap (AllocatePrivAGPMem)"));
}
pThisDisplay->pAGPHeap = pCurrentHeap;
} // __FindAGPHeap
//-----------------------------Public Routine----------------------------------
// DdUpdateNonLocalHeap
//
// Received the address of the AGP Heap and updates the chip.
//
//
//-----------------------------------------------------------------------------
DWORD CALLBACK
DdUpdateNonLocalHeap(
LPDDHAL_UPDATENONLOCALHEAPDATA plhd)
{
P3_THUNKEDDATA* pThisDisplay;
GET_THUNKEDDATA(pThisDisplay, plhd->lpDD);
DISPDBG((DBGLVL,"** In DdUpdateNonLocalHeap - for Heap 0x%x",
plhd->dwHeap));
// Fill in the base pointers
pThisDisplay->dwGARTDevBase = (DWORD)plhd->fpGARTDev;
pThisDisplay->dwGARTLinBase = (DWORD)plhd->fpGARTLin;
// Fill in the changeable base pointers.
pThisDisplay->dwGARTDev = pThisDisplay->dwGARTDevBase;
pThisDisplay->dwGARTLin = pThisDisplay->dwGARTLinBase;
__FindAGPHeap( pThisDisplay, plhd->lpDD );
DISPDBG((DBGLVL,"GartLin: 0x%x, GartDev: 0x%x",
plhd->fpGARTLin, plhd->fpGARTDev));
plhd->ddRVal = DD_OK;
return DDHAL_DRIVER_HANDLED;
} // DdUpdateNonLocalHeap()
//-----------------------------Public Routine----------------------------------
//
// DdGetHeapAlignment
//
//-----------------------------------------------------------------------------
DWORD CALLBACK
DdGetHeapAlignment(
LPDDHAL_GETHEAPALIGNMENTDATA lpGhaData)
{
P3_THUNKEDDATA* pThisDisplay;
DISPDBG(( DBGLVL,"DdGetHeapAlignment: Heap %d", lpGhaData->dwHeap ));
if (lpGhaData->dwInstance)
pThisDisplay = (P3_THUNKEDDATA*)lpGhaData->dwInstance;
else
pThisDisplay = (P3_THUNKEDDATA*)g_pDriverData;
if( lpGhaData->dwHeap <= 2 )
{
lpGhaData->Alignment.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
lpGhaData->Alignment.Texture.Linear.dwStartAlignment = 16;
lpGhaData->ddRVal = DD_OK;
return DDHAL_DRIVER_HANDLED;
}
else
{
lpGhaData->ddRVal = DDERR_INVALIDPARAMS;
return DDHAL_DRIVER_NOTHANDLED;
}
} // DdGetHeapAlignment
#endif // W95_DDRAW