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
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
|
|
|
|
|