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.
1960 lines
58 KiB
1960 lines
58 KiB
//-------------------------------------------------------------------------------
|
|
//
|
|
// Copyright (C) 1994-1997 Microsoft Corporation. All Rights Reserved.
|
|
//
|
|
// File: ddoptsur.c
|
|
// Content: DirectDraw Optimized Surface support
|
|
// History:
|
|
// Date By Reason
|
|
// ==== == ======
|
|
// 2-nov-97 anankan Original implementation
|
|
//
|
|
//-------------------------------------------------------------------------------
|
|
|
|
#include "ddrawpr.h"
|
|
|
|
//-------------------------------------------------------------------------------
|
|
//
|
|
// IsRecognizedOptSurfaceGUID
|
|
//
|
|
// Checks to see if the GUID passed is recognized by the driver.
|
|
// This is done by looking at the list maintained in LPDDRAWI_DIRECTDRAW_GBL
|
|
//
|
|
//-------------------------------------------------------------------------------
|
|
BOOL
|
|
IsRecognizedOptSurfaceGUID(
|
|
LPDDRAWI_DIRECTDRAW_GBL this,
|
|
LPGUID pGuid)
|
|
{
|
|
int i;
|
|
|
|
LPDDOPTSURFACEINFO pOptSurfInfo;
|
|
pOptSurfInfo = this->lpDDOptSurfaceInfo;
|
|
|
|
for (i = 0; i < (int)pOptSurfInfo->dwNumGuids; i++)
|
|
{
|
|
if (IsEqualIID(pGuid, &(pOptSurfInfo->lpGuidArray[i])))
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------------
|
|
//
|
|
// ValidateSurfDesc
|
|
//
|
|
// Fill in correct surf desc to be passed to the driver
|
|
//
|
|
//-------------------------------------------------------------------------------
|
|
HRESULT
|
|
ValidateSurfDesc(
|
|
LPDDSURFACEDESC2 pOrigSurfDesc
|
|
)
|
|
{
|
|
DWORD caps = pOrigSurfDesc->ddsCaps.dwCaps;
|
|
|
|
//
|
|
// check for no caps at all!
|
|
//
|
|
if( caps == 0 )
|
|
{
|
|
DPF_ERR( "no caps specified" );
|
|
return DDERR_INVALIDCAPS;
|
|
}
|
|
|
|
//
|
|
// check for bogus caps.
|
|
//
|
|
if( caps & ~DDSCAPS_VALID )
|
|
{
|
|
DPF_ERR( "Create surface: invalid caps specified" );
|
|
return DDERR_INVALIDCAPS;
|
|
}
|
|
|
|
//
|
|
// Anything other than a texture is not allowed
|
|
// ATTENTION: some more flags need to be checked
|
|
//
|
|
if(caps & (DDSCAPS_EXECUTEBUFFER |
|
|
DDSCAPS_BACKBUFFER |
|
|
DDSCAPS_FRONTBUFFER |
|
|
DDSCAPS_OFFSCREENPLAIN |
|
|
DDSCAPS_PRIMARYSURFACE |
|
|
DDSCAPS_PRIMARYSURFACELEFT |
|
|
DDSCAPS_VIDEOPORT |
|
|
DDSCAPS_ZBUFFER |
|
|
DDSCAPS_OWNDC |
|
|
DDSCAPS_OVERLAY |
|
|
DDSCAPS_3DDEVICE |
|
|
DDSCAPS_ALLOCONLOAD)
|
|
)
|
|
{
|
|
DPF_ERR( "currently only textures can be optimized" );
|
|
return DDERR_INVALIDCAPS;
|
|
}
|
|
|
|
if( !(caps & DDSCAPS_TEXTURE) )
|
|
{
|
|
DPF_ERR( "DDSCAPS_TEXTURE needs to be set" );
|
|
return DDERR_INVALIDCAPS;
|
|
}
|
|
|
|
// Pixelformat not specified ?
|
|
if (!(pOrigSurfDesc->dwFlags & DDSD_PIXELFORMAT))
|
|
{
|
|
DPF_ERR( "Pixel format needs to be set" );
|
|
return DDERR_INVALIDCAPS;
|
|
}
|
|
|
|
return DD_OK;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------------
|
|
//
|
|
// DD_CanOptimizeSurface
|
|
//
|
|
// Check to see if a surface given the description be optimized.
|
|
//
|
|
//-------------------------------------------------------------------------------
|
|
HRESULT
|
|
EXTERN_DDAPI
|
|
DD_CanOptimizeSurface(
|
|
LPDIRECTDRAW pDD,
|
|
LPDDSURFACEDESC2 pDDSurfDesc,
|
|
LPDDOPTSURFACEDESC pDDOptSurfDesc,
|
|
BOOL *bTrue
|
|
)
|
|
{
|
|
LPDDRAWI_DIRECTDRAW_INT this_int;
|
|
LPDDRAWI_DIRECTDRAW_LCL this_lcl;
|
|
LPDDRAWI_DIRECTDRAW_GBL this;
|
|
DDHAL_CANOPTIMIZESURFACEDATA ddhal_cosd;
|
|
LPDDOPTSURFACEINFO pDDOptSurfInfo = NULL;
|
|
HRESULT ddrval = DD_OK;
|
|
|
|
ENTER_DDRAW();
|
|
|
|
DPF(2,A,"ENTERAPI: DD_CanOptimizeSurface");
|
|
|
|
//
|
|
// Setup DPF stuff
|
|
//
|
|
DPF_ENTERAPI(pDD);
|
|
|
|
//
|
|
// Parameter validation
|
|
//
|
|
TRY
|
|
{
|
|
this_int = (LPDDRAWI_DIRECTDRAW_INT) pDD;
|
|
if( !VALID_DIRECTDRAW_PTR( this_int ) )
|
|
{
|
|
DPF_ERR( "Invalid driver object passed" );
|
|
DPF_APIRETURNS(DDERR_INVALIDOBJECT);
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
this_lcl = this_int->lpLcl;
|
|
this = this_lcl->lpGbl;
|
|
|
|
if( this->dwModeIndex == DDUNSUPPORTEDMODE )
|
|
{
|
|
DPF_ERR( "Driver is in an unsupported mode" );
|
|
LEAVE_DDRAW();
|
|
DPF_APIRETURNS(DDERR_UNSUPPORTEDMODE);
|
|
return DDERR_UNSUPPORTEDMODE;
|
|
}
|
|
|
|
if( !VALID_DDSURFACEDESC2_PTR( pDDSurfDesc ) )
|
|
{
|
|
DPF_ERR( "Invalid surface description. Did you set the dwSize member?" );
|
|
LEAVE_DDRAW();
|
|
DPF_APIRETURNS(DDERR_INVALIDPARAMS);
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
if( !VALID_DDOPTSURFACEDESC_PTR( pDDOptSurfDesc ) )
|
|
{
|
|
DPF_ERR( "Invalid optimized surface description. Did you set the dwSize member?" );
|
|
LEAVE_DDRAW();
|
|
DPF_APIRETURNS(DDERR_INVALIDPARAMS);
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
if( !VALID_PTR( bTrue, sizeof (*bTrue)) )
|
|
{
|
|
DPF_ERR( "Invalid Boolean pointer" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
*bTrue = TRUE;
|
|
}
|
|
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
DPF_ERR( "Exception encountered validating parameters" );
|
|
LEAVE_DDRAW();
|
|
DPF_APIRETURNS(DDERR_INVALIDPARAMS);
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
//
|
|
// Quit with error if:
|
|
// 1) No hardware
|
|
// 2) Hardware doesnt support optimized surfaces
|
|
// 3) pSurfDesc does not provide useful information
|
|
// 4) Is the guid one of the recognized ones
|
|
// 5) The driver fails for some reason
|
|
//
|
|
|
|
// 1)
|
|
if( this->dwFlags & DDRAWI_NOHARDWARE )
|
|
{
|
|
DPF_ERR ("No hardware present");
|
|
LEAVE_DDRAW();
|
|
return DDERR_NODIRECTDRAWHW;
|
|
}
|
|
|
|
// 2)
|
|
if ((0 == this->lpDDOptSurfaceInfo) ||
|
|
!(this->ddCaps.dwCaps2 & DDCAPS2_OPTIMIZEDSURFACES))
|
|
{
|
|
DPF_ERR ("Optimized surfaces not supported");
|
|
LEAVE_DDRAW();
|
|
return DDERR_NOOPTSURFACESUPPORT;
|
|
}
|
|
|
|
// 3)
|
|
ddrval = ValidateSurfDesc (pDDSurfDesc);
|
|
if (ddrval != DD_OK)
|
|
{
|
|
DPF_ERR ("Invalid surface description");
|
|
LEAVE_DDRAW();
|
|
return ddrval;
|
|
}
|
|
|
|
// 4)
|
|
if (!IsRecognizedOptSurfaceGUID (this, &(pDDOptSurfDesc->guid)))
|
|
{
|
|
DPF_ERR( "Not a recognized GUID" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_UNRECOGNIZEDGUID;
|
|
}
|
|
|
|
// Call the driver
|
|
ZeroMemory (&ddhal_cosd, sizeof (ddhal_cosd));
|
|
ddhal_cosd.lpDD = this_lcl;
|
|
ddhal_cosd.ddOptSurfDesc = *pDDOptSurfDesc;
|
|
ddhal_cosd.ddSurfaceDesc = *pDDSurfDesc;
|
|
|
|
// Make the HAL call
|
|
pDDOptSurfInfo = this->lpDDOptSurfaceInfo;
|
|
DOHALCALL(CanOptimizeSurface, pDDOptSurfInfo->CanOptimizeSurface, ddhal_cosd, ddrval, FALSE );
|
|
|
|
if (ddrval != DD_OK)
|
|
{
|
|
DPF_ERR ("LoadUnOptSurface failed in the driver");
|
|
LEAVE_DDRAW();
|
|
return ddrval;
|
|
}
|
|
|
|
if (ddhal_cosd.bCanOptimize != 0)
|
|
{
|
|
*bTrue = TRUE;
|
|
}
|
|
else
|
|
{
|
|
*bTrue = FALSE;
|
|
}
|
|
|
|
LEAVE_DDRAW();
|
|
return DD_OK;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------------
|
|
//
|
|
// CreateAndLinkUninitializedSurface
|
|
//
|
|
// Create a surface, and link it into the chain.
|
|
// We create a single surface place-holder here, real work is done at the
|
|
// Load/Copy time.
|
|
//
|
|
//-------------------------------------------------------------------------------
|
|
HRESULT
|
|
CreateAndLinkUnintializedSurface(
|
|
LPDDRAWI_DIRECTDRAW_LCL this_lcl,
|
|
LPDDRAWI_DIRECTDRAW_INT this_int,
|
|
LPDIRECTDRAWSURFACE FAR *ppDDSurface
|
|
)
|
|
{
|
|
LPDDRAWI_DIRECTDRAW_GBL this;
|
|
LPDDRAWI_DDRAWSURFACE_INT pSurf_int;
|
|
LPDDRAWI_DDRAWSURFACE_LCL pSurf_lcl;
|
|
LPDDRAWI_DDRAWSURFACE_GBL pSurf;
|
|
LPVOID *ppSurf_gbl_more;
|
|
DDSCAPS caps;
|
|
DDPIXELFORMAT ddpf;
|
|
int surf_size;
|
|
int surf_size_lcl;
|
|
int surf_size_lcl_more;
|
|
#ifdef WIN95
|
|
DWORD ptr16;
|
|
#endif
|
|
HRESULT ddrval = DD_OK;
|
|
|
|
// DDraw-global
|
|
this = this_lcl->lpGbl;
|
|
#ifdef WINNT
|
|
// Update DDraw handle in driver GBL object.
|
|
this->hDD = this_lcl->hDD;
|
|
#endif //WINNT
|
|
|
|
//
|
|
// Zero the caps
|
|
//
|
|
ZeroMemory (&caps, sizeof (DDCAPS));
|
|
|
|
//
|
|
// PixelFormat: Mark it as an empty surface
|
|
//
|
|
ZeroMemory (&ddpf, sizeof (ddpf));
|
|
ddpf.dwSize = sizeof (ddpf);
|
|
ddpf.dwFlags = DDPF_EMPTYSURFACE;
|
|
|
|
|
|
//
|
|
// Allocate the internal Surface structure and initialize the fields
|
|
//
|
|
//
|
|
// fail requests for non-local video memory allocations if the driver does
|
|
// not support non-local video memory.
|
|
//
|
|
// NOTE: Should we really do this or just let the allocation fail from
|
|
// naturalcauses?
|
|
//
|
|
// ALSO NOTE: Don't have to worry about emulation as no emulated surface
|
|
// should
|
|
// ever get this far with DDSCAPS_NONLOCALVIDMEM set.
|
|
//
|
|
// ALSO ALSO NOTE: Should we also fail DDSCAPS_LOCALVIDMEM if the driver does
|
|
// not support DDSCAPS_NONLOCALVIDMEM. My feeling is that we should allow.
|
|
// DDSCAPS_LOCALVIDMEM is legal with a non AGP driver - redundant but legal.
|
|
//
|
|
|
|
//
|
|
// allocate the surface struct, allowing for overlay and pixel
|
|
// format data
|
|
//
|
|
// NOTE: This single allocation can allocate space for local surface
|
|
// structure (DDRAWI_DDRAWSURFACE_LCL), the additional local surface
|
|
// structure (DDRAWI_DDRAWSURFACE_MORE) and the global surface structure
|
|
// (DDRAWI_DDRAWSURFACE_GBL). And now the global surface more
|
|
// structure too (DDRAWI_DDRAWSURFACE_GBL_MORE). As both the local and
|
|
// global objects can be variable sized this can get pretty complex.
|
|
// Additionally, we have 4 bytes just before the surface_gbl that points to
|
|
// the surface_gbl_more.
|
|
//
|
|
// CAVEAT: All future surfaces that share this global all point to this
|
|
// allocation. The last surface's release has to free it. During
|
|
// InternalSurfaceRelease (in ddsiunk.c) a calculation is made to determine
|
|
// the start of this memory allocation. If the surface being released is
|
|
// the first one, then freeing "this_lcl" will free the whole thing. If
|
|
// not, then "this_lcl->lpGbl - (Surface_lcl + surface_more + more_ptr)"
|
|
// is computed. Keep this layout in synch with code in ddsiunk.c.
|
|
//
|
|
// The layout of the various objects in the allocation is as follows:
|
|
//
|
|
// +-----------------+---------------+----+------------+-----------------+
|
|
// | SURFACE_LCL | SURFACE_MORE |More| SURFACE_GBL| SURFACE_GBL_MORE|
|
|
// | (variable) | |Ptr | (variable) | |
|
|
// +-----------------+---------------+----+------------+-----------------+
|
|
// <- surf_size_lcl -> | |
|
|
// <- surf_size_lcl_more ------------> |
|
|
// <- surf_size --------------------------------------------------------->
|
|
//
|
|
//
|
|
|
|
// ATTENTION: Currently ignores to account for the overlays
|
|
#if 0
|
|
surf_size_lcl = sizeof( DDRAWI_DDRAWSURFACE_LCL );
|
|
#endif
|
|
surf_size_lcl = offsetof( DDRAWI_DDRAWSURFACE_LCL, ddckCKSrcOverlay );
|
|
surf_size_lcl_more = surf_size_lcl + sizeof( DDRAWI_DDRAWSURFACE_MORE );
|
|
|
|
// Assume that the pixelformat is present for allocating the GBL
|
|
surf_size = surf_size_lcl_more + sizeof( DDRAWI_DDRAWSURFACE_GBL );
|
|
#if 0
|
|
surf_size = surf_size_lcl_more + offsetof( DDRAWI_DDRAWSURFACE_GBL,
|
|
ddpfSurface );
|
|
#endif
|
|
|
|
// Need to allocate a pointer just before the SURFACE_GBL to
|
|
// point to the beginning of the GBL_MORE.
|
|
surf_size += sizeof( LPDDRAWI_DDRAWSURFACE_GBL_MORE );
|
|
|
|
// Need to allocate a SURFACE_GBL_MORE too
|
|
surf_size += sizeof( DDRAWI_DDRAWSURFACE_GBL_MORE );
|
|
|
|
DPF( 8, "Allocating struct (%ld)", surf_size );
|
|
|
|
#ifdef WIN95
|
|
pSurf_lcl = (LPDDRAWI_DDRAWSURFACE_LCL) MemAlloc16 (surf_size, &ptr16);
|
|
#else
|
|
pSurf_lcl = (LPDDRAWI_DDRAWSURFACE_LCL) MemAlloc (surf_size);
|
|
#endif
|
|
|
|
if (pSurf_lcl == NULL)
|
|
{
|
|
DPF_ERR ("Failed to allocate internal surface structure");
|
|
ddrval = DDERR_OUTOFMEMORY;
|
|
goto error_exit_create_link;
|
|
}
|
|
|
|
// Initialize SURFACE_GBL pointer
|
|
// skipping 4 bytes for a pointer to the GBL_MORE
|
|
ZeroMemory (pSurf_lcl, surf_size);
|
|
pSurf_lcl->lpGbl = (LPVOID) (((LPSTR) pSurf_lcl) + surf_size_lcl_more +
|
|
sizeof (LPVOID));
|
|
|
|
// Initialize GBL_MORE pointer
|
|
ppSurf_gbl_more = (LPVOID *)((LPBYTE)pSurf_lcl->lpGbl - sizeof (LPVOID));
|
|
*ppSurf_gbl_more = (LPVOID) ((LPBYTE)pSurf_lcl + surf_size
|
|
- sizeof (DDRAWI_DDRAWSURFACE_GBL_MORE));
|
|
|
|
// Sanity Check
|
|
DDASSERT( *ppSurf_gbl_more ==
|
|
(LPVOID) GET_LPDDRAWSURFACE_GBL_MORE(pSurf_lcl->lpGbl));
|
|
|
|
//
|
|
// 1) Initialize GBL_MORE structure
|
|
//
|
|
GET_LPDDRAWSURFACE_GBL_MORE(pSurf_lcl->lpGbl)->dwSize =
|
|
sizeof( DDRAWI_DDRAWSURFACE_GBL_MORE );
|
|
|
|
// Init the contents stamp to 0 means the surface's contents can
|
|
// change at any time.
|
|
GET_LPDDRAWSURFACE_GBL_MORE( pSurf_lcl->lpGbl )->dwContentsStamp = 0;
|
|
|
|
//
|
|
// 2) Initialize DDRAWI_DDRAWSURFACE_GBL structure
|
|
//
|
|
pSurf = pSurf_lcl->lpGbl;
|
|
pSurf->ddpfSurface = ddpf;
|
|
pSurf->lpDD = this;
|
|
|
|
//
|
|
// 3) Allocate and initialize DDRAWI_DDRAWSURFACE_INT structure
|
|
//
|
|
pSurf_int = (LPDDRAWI_DDRAWSURFACE_INT)
|
|
MemAlloc( sizeof(DDRAWI_DDRAWSURFACE_INT));
|
|
if( NULL == pSurf_int )
|
|
{
|
|
DPF_ERR ("Failed allocation of DDRAWI_DDRAWSURFACE_INT");
|
|
ddrval = DDERR_OUTOFMEMORY;
|
|
goto error_exit_create_link;
|
|
}
|
|
|
|
// fill surface specific stuff
|
|
ZeroMemory (pSurf_int, sizeof(DDRAWI_DDRAWSURFACE_INT));
|
|
pSurf_int->lpLcl = pSurf_lcl;
|
|
pSurf_int->lpVtbl = NULL;
|
|
|
|
//
|
|
// 4) Initialize DDRAWI_DDRAWSURFACE_LCL structure
|
|
//
|
|
pSurf_lcl->dwLocalRefCnt = OBJECT_ISROOT;
|
|
pSurf_lcl->dwProcessId = GetCurrentProcessId();
|
|
#ifdef WIN95
|
|
pSurf_lcl->dwModeCreatedIn = this->dwModeIndex;
|
|
#else
|
|
pSurf_lcl->dmiCreated = this->dmiCurrent;
|
|
#endif
|
|
pSurf_lcl->dwBackBufferCount = 0;
|
|
|
|
// Flag it as an:
|
|
// 1) empty surface
|
|
// 2) Front surface
|
|
// 3) Has a pixelformat
|
|
pSurf_lcl->dwFlags = (DDRAWISURF_EMPTYSURFACE |
|
|
DDRAWISURF_FRONTBUFFER |
|
|
DDRAWISURF_HASPIXELFORMAT);
|
|
//
|
|
// 5) Initialize DDRAWI_DDRAWSURFACE_MORE structure
|
|
//
|
|
pSurf_lcl->lpSurfMore = (LPDDRAWI_DDRAWSURFACE_MORE) (((LPSTR) pSurf_lcl) +
|
|
surf_size_lcl );
|
|
pSurf_lcl->lpSurfMore->dwSize = sizeof( DDRAWI_DDRAWSURFACE_MORE );
|
|
pSurf_lcl->lpSurfMore->lpIUnknowns = NULL;
|
|
pSurf_lcl->lpSurfMore->lpDD_lcl = this_lcl;
|
|
pSurf_lcl->lpSurfMore->lpDD_int = this_int;
|
|
pSurf_lcl->lpSurfMore->dwMipMapCount = 0UL;
|
|
pSurf_lcl->lpSurfMore->lpddOverlayFX = NULL;
|
|
pSurf_lcl->lpSurfMore->lpD3DDevIList = NULL;
|
|
pSurf_lcl->lpSurfMore->dwPFIndex = PFINDEX_UNINITIALIZED;
|
|
|
|
// fill in the current caps
|
|
pSurf_lcl->ddsCaps = caps;
|
|
|
|
#ifdef WINNT
|
|
//
|
|
// NT kernel needs to know about surface
|
|
//
|
|
|
|
//don't let NT kernel know about exec buffers
|
|
DPF(8,"Attempting to create NT kernel mode surface object");
|
|
|
|
if (!DdCreateSurfaceObject(pSurf_lcl, FALSE))
|
|
{
|
|
DPF_ERR("NT kernel mode stuff won't create its surface object!");
|
|
ddrval = DDERR_GENERIC;
|
|
goto error_exit_create_link;
|
|
}
|
|
DPF(9,"Kernel mode handle is %08x", pSurf_lcl->hDDSurface);
|
|
#endif
|
|
|
|
//
|
|
// Link the newly created surface to the DDraw surface chain
|
|
//
|
|
pSurf_int->lpLink = this->dsList;
|
|
this->dsList = pSurf_int;
|
|
|
|
//
|
|
// AddRef the newly created surface
|
|
//
|
|
DD_Surface_AddRef( (LPDIRECTDRAWSURFACE) pSurf_int );
|
|
|
|
//
|
|
// Now assign it to the ptr-to-ptr passed in
|
|
//
|
|
*ppDDSurface = (LPDIRECTDRAWSURFACE) pSurf_int;
|
|
return DD_OK;
|
|
|
|
error_exit_create_link:
|
|
//
|
|
// Free any allocated memory
|
|
//
|
|
|
|
// 1) The allocated SURFACE_LCL
|
|
if (pSurf_lcl)
|
|
{
|
|
MemFree (pSurf_lcl);
|
|
}
|
|
|
|
// 2) The Surface_int
|
|
if (pSurf_int)
|
|
{
|
|
MemFree (pSurf_int);
|
|
}
|
|
|
|
return ddrval;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------------
|
|
//
|
|
// createAndLinkOptSurface
|
|
//
|
|
// Create a surface, and link it into the chain.
|
|
// We create a single surface place-holder here, real work is done at the
|
|
// Load/Copy time.
|
|
//
|
|
//-------------------------------------------------------------------------------
|
|
HRESULT
|
|
createAndLinkOptSurface(
|
|
LPDDRAWI_DIRECTDRAW_LCL this_lcl,
|
|
LPDDRAWI_DIRECTDRAW_INT this_int,
|
|
LPDDOPTSURFACEDESC pDDOptSurfaceDesc,
|
|
LPDIRECTDRAWSURFACE FAR *ppDDSurface
|
|
)
|
|
{
|
|
LPDDRAWI_DIRECTDRAW_GBL this;
|
|
LPDDRAWI_DDRAWSURFACE_INT new_surf_int;
|
|
LPDDRAWI_DDRAWSURFACE_LCL new_surf_lcl;
|
|
LPDDRAWI_DDRAWSURFACE_GBL new_surf;
|
|
LPDDRAWI_DDRAWSURFACE_GBL_MORE new_surf_gbl_more;
|
|
DDSCAPS2 caps2;
|
|
LPDDOPTSURFACEDESC pOptSurfDesc;
|
|
DDPIXELFORMAT ddpf;
|
|
HRESULT ddrval = DD_OK;
|
|
|
|
// DDraw-global
|
|
this = this_lcl->lpGbl;
|
|
|
|
//
|
|
// Fix the caps
|
|
//
|
|
ZeroMemory (&caps2, sizeof (DDSCAPS));
|
|
caps2.dwCaps = DDSCAPS_OPTIMIZED;
|
|
if (pDDOptSurfaceDesc->ddSCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
|
|
caps2.dwCaps |= DDSCAPS_SYSTEMMEMORY;
|
|
if (pDDOptSurfaceDesc->ddSCaps.dwCaps & DDSCAPS_VIDEOMEMORY)
|
|
caps2.dwCaps |= DDSCAPS_VIDEOMEMORY;
|
|
if (pDDOptSurfaceDesc->ddSCaps.dwCaps & DDSCAPS_LOCALVIDMEM)
|
|
caps2.dwCaps |= DDSCAPS_LOCALVIDMEM;
|
|
if (pDDOptSurfaceDesc->ddSCaps.dwCaps & DDSCAPS_NONLOCALVIDMEM)
|
|
caps2.dwCaps |= DDSCAPS_NONLOCALVIDMEM;
|
|
|
|
// Quit is the memory type is not supported
|
|
if (caps2.dwCaps & DDSCAPS_NONLOCALVIDMEM)
|
|
{
|
|
if (!(this->ddCaps.dwCaps2 & DDCAPS2_NONLOCALVIDMEM))
|
|
{
|
|
DPF_ERR( "Driver does not support non-local video memory" );
|
|
ddrval = DDERR_NONONLOCALVIDMEM;
|
|
goto error_exit_create_opt;
|
|
}
|
|
}
|
|
|
|
#if 0
|
|
// Quit if textures are not supported
|
|
if (!(this->ddCaps.dwCaps & DDSCAPS_TEXTURE))
|
|
{
|
|
DPF_ERR( "Driver does not support textures" );
|
|
return DDERR_NOTEXTUREHW;
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// PixelFormat: Mark it as an empty surface
|
|
//
|
|
ZeroMemory (&ddpf, sizeof (ddpf));
|
|
ddpf.dwSize = sizeof (ddpf);
|
|
ddpf.dwFlags = DDPF_EMPTYSURFACE;
|
|
|
|
//
|
|
// OptSurfaceDesc
|
|
//
|
|
pOptSurfDesc = MemAlloc (sizeof (DDOPTSURFACEDESC));
|
|
if (NULL == pOptSurfDesc)
|
|
{
|
|
DPF_ERR ("Memory allocation failed for opt surface descriptor");
|
|
ddrval = DDERR_OUTOFMEMORY;
|
|
goto error_exit_create_opt;
|
|
}
|
|
ZeroMemory (pOptSurfDesc, sizeof (*pOptSurfDesc));
|
|
CopyMemory (pOptSurfDesc, pDDOptSurfaceDesc, sizeof (DDOPTSURFACEDESC));
|
|
|
|
// Create and link an uninitialized surface
|
|
ddrval = CreateAndLinkUnintializedSurface (this_lcl,
|
|
this_int,
|
|
ppDDSurface);
|
|
if (ddrval != DD_OK)
|
|
{
|
|
DPF_ERR ("createAndLinkUninitializedSurface failed");
|
|
goto error_exit_create_opt;
|
|
}
|
|
|
|
|
|
//
|
|
// 1) Update GBL_MORE structure
|
|
//
|
|
new_surf_int = (LPDDRAWI_DDRAWSURFACE_INT)*ppDDSurface;
|
|
new_surf_lcl = new_surf_int->lpLcl;
|
|
new_surf = new_surf_lcl->lpGbl;
|
|
new_surf_gbl_more = GET_LPDDRAWSURFACE_GBL_MORE(new_surf);
|
|
new_surf_gbl_more->lpDDOptSurfaceDesc = pOptSurfDesc;
|
|
// Init the contents stamp to 0 means the surface's contents can
|
|
// change at any time.
|
|
new_surf_gbl_more->dwContentsStamp = 0;
|
|
|
|
//
|
|
// 2) Update DDRAWI_DDRAWSURFACE_GBL structure
|
|
//
|
|
new_surf->ddpfSurface = ddpf;
|
|
|
|
//
|
|
// 3) Update DDRAWI_DDRAWSURFACE_INT structure
|
|
//
|
|
new_surf_int->lpVtbl = &ddOptSurfaceCallbacks;
|
|
|
|
//
|
|
// 4) Update DDRAWI_DDRAWSURFACE_LCL structure
|
|
//
|
|
|
|
// Flag it as an:
|
|
// 1) empty surface
|
|
// 2) Front surface
|
|
// 3) Has a pixelformat
|
|
new_surf_lcl->dwFlags = (DDRAWISURF_EMPTYSURFACE |
|
|
DDRAWISURF_FRONTBUFFER |
|
|
DDRAWISURF_HASPIXELFORMAT);
|
|
// fill in the current caps
|
|
CopyMemory (&new_surf_lcl->ddsCaps, &caps2, sizeof(new_surf_lcl->ddsCaps));
|
|
|
|
|
|
return DD_OK;
|
|
|
|
error_exit_create_opt:
|
|
//
|
|
// Free any allocated memory
|
|
//
|
|
|
|
// 1) The allocated OPTSURFDESC
|
|
if (pOptSurfDesc)
|
|
{
|
|
MemFree (pOptSurfDesc);
|
|
}
|
|
|
|
return ddrval;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------------
|
|
//
|
|
// InternalCreateOptSurface
|
|
//
|
|
// Create the surface.
|
|
// This is the internal way of doing this; used by EnumSurfaces.
|
|
// Assumes the directdraw lock has been taken.
|
|
//
|
|
//-------------------------------------------------------------------------------
|
|
|
|
HRESULT
|
|
InternalCreateOptSurface(
|
|
LPDDRAWI_DIRECTDRAW_LCL this_lcl,
|
|
LPDDOPTSURFACEDESC pDDOptSurfaceDesc,
|
|
LPDIRECTDRAWSURFACE FAR *ppDDSurface,
|
|
LPDDRAWI_DIRECTDRAW_INT this_int )
|
|
{
|
|
DDSCAPS2 caps2;
|
|
DDOSCAPS ocaps;
|
|
HRESULT ddrval;
|
|
LPDDRAWI_DIRECTDRAW_GBL this;
|
|
|
|
this = this_lcl->lpGbl;
|
|
|
|
// Validate Caps
|
|
caps2 = pDDOptSurfaceDesc->ddSCaps;
|
|
if (caps2.dwCaps & ~DDOSDCAPS_VALIDSCAPS)
|
|
{
|
|
DPF_ERR( "Unrecognized optimized surface caps" );
|
|
return DDERR_INVALIDCAPS;
|
|
}
|
|
|
|
ocaps = pDDOptSurfaceDesc->ddOSCaps;
|
|
if (ocaps.dwCaps & ~DDOSDCAPS_VALIDOSCAPS)
|
|
{
|
|
DPF_ERR( "Unrecognized optimized surface caps" );
|
|
return DDERR_INVALIDCAPS;
|
|
}
|
|
|
|
//
|
|
// valid memory caps?
|
|
//
|
|
if ((caps2.dwCaps & DDSCAPS_SYSTEMMEMORY)
|
|
&& (caps2.dwCaps & DDSCAPS_VIDEOMEMORY))
|
|
{
|
|
DPF_ERR( "Can't specify SYSTEMMEMORY and VIDEOMEMORY" );
|
|
return DDERR_INVALIDCAPS;
|
|
}
|
|
|
|
//
|
|
// If DDSCAPS_LOCALVIDMEM or DDSCAPS_NONLOCALVIDMEM are specified
|
|
// then DDSCAPS_VIDOEMEMORY must be explicity specified. Note, we
|
|
// can't dely this check until checkCaps() as by that time the heap
|
|
// scanning software may well have turned on DDSCAPS_VIDOEMEMORY.
|
|
//
|
|
if ((caps2.dwCaps & (DDSCAPS_LOCALVIDMEM | DDSCAPS_NONLOCALVIDMEM)) &&
|
|
!(caps2.dwCaps & DDSCAPS_VIDEOMEMORY))
|
|
{
|
|
DPF_ERR( "DDOSDCAPS_VIDEOMEMORY must be specified with DDSCAPS_LOCALVIDMEM or DDSCAPS_NONLOCALVIDMEM" );
|
|
return DDERR_INVALIDCAPS;
|
|
}
|
|
|
|
//
|
|
// have to specify if it is sys-mem or vid-mem
|
|
//
|
|
if ((caps2.dwCaps & (DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY)) == 0)
|
|
{
|
|
DPF_ERR( "Need to specify the memory type" );
|
|
return DDERR_INVALIDCAPS;
|
|
}
|
|
|
|
//
|
|
// Validate optimization type caps
|
|
//
|
|
if ((ocaps.dwCaps & (DDOSDCAPS_OPTCOMPRESSED | DDOSDCAPS_OPTREORDERED)) == 0)
|
|
{
|
|
DPF_ERR ("Not specified whether compressed or reordered, let the driver choose");
|
|
}
|
|
|
|
// Cannot be both compresses and reordered
|
|
if ((ocaps.dwCaps & DDOSDCAPS_OPTCOMPRESSED)
|
|
&& (ocaps.dwCaps & DDOSDCAPS_OPTREORDERED))
|
|
{
|
|
DPF_ERR ("Cannot be both compresses and reordered");
|
|
return DDERR_INVALIDCAPS;
|
|
}
|
|
|
|
ddrval = createAndLinkOptSurface (this_lcl, this_int, pDDOptSurfaceDesc,
|
|
ppDDSurface);
|
|
return ddrval;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------------
|
|
//
|
|
// CreateOptSurface method of IDirectDrawSurface4
|
|
//
|
|
// Create an optimized surface given the Optimized surface descriptor
|
|
//
|
|
//-------------------------------------------------------------------------------
|
|
HRESULT
|
|
EXTERN_DDAPI
|
|
DD_CreateOptSurface(
|
|
LPDIRECTDRAW pDD,
|
|
LPDDOPTSURFACEDESC pDDOptSurfaceDesc,
|
|
LPDIRECTDRAWSURFACE FAR *ppDDS,
|
|
IUnknown FAR *pUnkOuter )
|
|
{
|
|
LPDDRAWI_DIRECTDRAW_INT this_int;
|
|
LPDDRAWI_DIRECTDRAW_LCL this_lcl;
|
|
LPDDRAWI_DIRECTDRAW_GBL this;
|
|
DDOPTSURFACEDESC ddosd;
|
|
HRESULT ddrval;
|
|
|
|
ZeroMemory(&ddosd,sizeof(ddosd));
|
|
ddosd.dwSize = sizeof (ddosd);
|
|
|
|
//
|
|
// Return error if aggregation expected
|
|
//
|
|
if( pUnkOuter != NULL )
|
|
{
|
|
return CLASS_E_NOAGGREGATION;
|
|
}
|
|
|
|
ENTER_DDRAW();
|
|
|
|
DPF(2,A,"ENTERAPI: DD_CreateOptSurface");
|
|
|
|
//
|
|
// Setup DPF stuff
|
|
//
|
|
DPF_ENTERAPI(pDD);
|
|
|
|
//
|
|
// Parameter validation
|
|
//
|
|
TRY
|
|
{
|
|
this_int = (LPDDRAWI_DIRECTDRAW_INT) pDD;
|
|
if( !VALID_DIRECTDRAW_PTR( this_int ) )
|
|
{
|
|
DPF_ERR( "Invalid driver object passed" );
|
|
DPF_APIRETURNS(DDERR_INVALIDOBJECT);
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
this_lcl = this_int->lpLcl;
|
|
this = this_lcl->lpGbl;
|
|
|
|
// verify that cooperative level is set
|
|
if( !(this_lcl->dwLocalFlags & DDRAWILCL_SETCOOPCALLED) )
|
|
{
|
|
DPF_ERR( "Must call SetCooperativeLevel before calling Create functions" );
|
|
LEAVE_DDRAW();
|
|
DPF_APIRETURNS(DDERR_NOCOOPERATIVELEVELSET);
|
|
return DDERR_NOCOOPERATIVELEVELSET;
|
|
}
|
|
|
|
if( this->dwModeIndex == DDUNSUPPORTEDMODE )
|
|
{
|
|
DPF_ERR( "Driver is in an unsupported mode" );
|
|
LEAVE_DDRAW();
|
|
DPF_APIRETURNS(DDERR_UNSUPPORTEDMODE);
|
|
return DDERR_UNSUPPORTEDMODE;
|
|
}
|
|
|
|
if( !VALID_DDOPTSURFACEDESC_PTR( pDDOptSurfaceDesc ) )
|
|
{
|
|
DPF_ERR( "Invalid optimized surface description. Did you set the dwSize member?" );
|
|
LEAVE_DDRAW();
|
|
DPF_APIRETURNS(DDERR_INVALIDPARAMS);
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
memcpy(&ddosd, pDDOptSurfaceDesc, sizeof(*pDDOptSurfaceDesc));
|
|
*ppDDS = NULL;
|
|
}
|
|
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
DPF_ERR( "Exception encountered validating parameters" );
|
|
LEAVE_DDRAW();
|
|
DPF_APIRETURNS(DDERR_INVALIDPARAMS);
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
// Quit if there is no hardware present
|
|
if( this->dwFlags & DDRAWI_NOHARDWARE )
|
|
{
|
|
ddrval = DDERR_NODIRECTDRAWHW;
|
|
goto exit_create;
|
|
}
|
|
|
|
// Assert that: (0 == this->lpDDOptSurfaceInfo) <==> (if and only if)
|
|
// (this->ddCaps.dwCaps2 & DDCAPS2_OPTIMIZEDSURFACES)
|
|
|
|
//Check to see if the driver supports OptSurface
|
|
if ((0 == this->lpDDOptSurfaceInfo) // GetDriverInfo failed for some reason
|
|
|| !(this->ddCaps.dwCaps2 & DDCAPS2_OPTIMIZEDSURFACES))
|
|
{
|
|
ddrval = DDERR_NOOPTSURFACESUPPORT;
|
|
goto exit_create;
|
|
}
|
|
|
|
//
|
|
// Check if the GUID passed is a recognized optimized surface GUID
|
|
// The compression ratio is more a hint.
|
|
//
|
|
if (!IsRecognizedOptSurfaceGUID (this, &(pDDOptSurfaceDesc->guid)))
|
|
{
|
|
DPF_ERR( "Not a recognized GUID" );
|
|
ddrval = DDERR_UNRECOGNIZEDGUID;
|
|
goto exit_create;
|
|
}
|
|
|
|
//
|
|
// Now create the Optimized surface
|
|
//
|
|
ddrval = InternalCreateOptSurface(this_lcl, &ddosd, ppDDS, this_int);
|
|
|
|
exit_create:
|
|
DPF_APIRETURNS(ddrval);
|
|
LEAVE_DDRAW();
|
|
return ddrval;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------------
|
|
//
|
|
// CreateOptSurface method of IDirectDrawSurface4
|
|
//
|
|
// Create an optimized surface given the Optimized surface descriptor
|
|
//
|
|
//-------------------------------------------------------------------------------
|
|
HRESULT
|
|
EXTERN_DDAPI
|
|
DD_ListOptSurfaceGUIDS(
|
|
LPDIRECTDRAW pDD,
|
|
DWORD *pNumGuids,
|
|
LPGUID pGuidArray )
|
|
{
|
|
LPDDRAWI_DIRECTDRAW_INT this_int;
|
|
LPDDRAWI_DIRECTDRAW_LCL this_lcl;
|
|
LPDDRAWI_DIRECTDRAW_GBL this;
|
|
HRESULT ddrval = DD_OK;
|
|
LPGUID pRetGuids = NULL;
|
|
LPDDOPTSURFACEINFO pOptSurfInfo;
|
|
|
|
ENTER_DDRAW();
|
|
|
|
DPF(2,A,"ENTERAPI: DD_ListOptSurfaceGUIDS");
|
|
|
|
//
|
|
// Parameter validation
|
|
//
|
|
TRY
|
|
{
|
|
this_int = (LPDDRAWI_DIRECTDRAW_INT) pDD;
|
|
if( !VALID_DIRECTDRAW_PTR( this_int ) )
|
|
{
|
|
DPF_ERR( "Invalid driver object passed" );
|
|
DPF_APIRETURNS(DDERR_INVALIDOBJECT);
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
this_lcl = this_int->lpLcl;
|
|
this = this_lcl->lpGbl;
|
|
|
|
if( !VALID_PTR( pGuidArray, sizeof (GUID) ))
|
|
{
|
|
DPF_ERR( "Invalid GuidArray pointer" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
pGuidArray = NULL;
|
|
|
|
if( !VALID_PTR( pNumGuids, sizeof (*pNumGuids)) )
|
|
{
|
|
DPF_ERR( "Invalid GuidArray pointer" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
*pNumGuids = 0;
|
|
}
|
|
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
DPF_ERR( "Exception encountered validating parameters" );
|
|
LEAVE_DDRAW();
|
|
DPF_APIRETURNS(DDERR_INVALIDPARAMS);
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
pOptSurfInfo = this->lpDDOptSurfaceInfo;
|
|
|
|
// Assert that: (0 == this->lpDDOptSurfaceInfo) <==> (if and only if)
|
|
// (this->ddCaps.dwCaps2 & DDCAPS2_OPTIMIZEDSURFACES)
|
|
|
|
//Check to see if the driver supports OptSurface
|
|
if ((0 == pOptSurfInfo) // GetDriverInfo failed for some reason
|
|
|| !(this->ddCaps.dwCaps2 & DDCAPS2_OPTIMIZEDSURFACES))
|
|
{
|
|
ddrval = DDERR_NOOPTSURFACESUPPORT;
|
|
goto list_exit;
|
|
}
|
|
|
|
// If there are no GUIDS reported by the driver,
|
|
// return the nulled out out-params.
|
|
if (pOptSurfInfo->dwNumGuids == 0)
|
|
{
|
|
ddrval = DD_OK;
|
|
goto list_exit;
|
|
}
|
|
|
|
// Allocate the array of GUIDS
|
|
// ATTENTION: Incomplete allocation?
|
|
pRetGuids = MemAlloc(pOptSurfInfo->dwNumGuids * sizeof(GUID));
|
|
if( NULL == pRetGuids )
|
|
{
|
|
ddrval = DDERR_OUTOFMEMORY;
|
|
goto list_exit;
|
|
}
|
|
|
|
// Copy the GUID array to be returned
|
|
CopyMemory ((PVOID)pRetGuids, (PVOID)pOptSurfInfo->lpGuidArray,
|
|
pOptSurfInfo->dwNumGuids * sizeof(GUID));
|
|
pGuidArray = pRetGuids;
|
|
*pNumGuids = pOptSurfInfo->dwNumGuids;
|
|
|
|
list_exit:
|
|
LEAVE_DDRAW();
|
|
return ddrval;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------------
|
|
//
|
|
// GetOptSurfaceDesc method of IDirectDrawOptSurface
|
|
//
|
|
// Get the Optimized surface description
|
|
//
|
|
//-------------------------------------------------------------------------------
|
|
HRESULT
|
|
EXTERN_DDAPI
|
|
DD_OptSurface_GetOptSurfaceDesc(
|
|
LPDIRECTDRAWSURFACE pDDS,
|
|
LPDDOPTSURFACEDESC pDDOptSurfDesc)
|
|
{
|
|
LPDDRAWI_DDRAWSURFACE_INT this_int;
|
|
LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
|
|
LPDDRAWI_DDRAWSURFACE_GBL this;
|
|
LPDDRAWI_DDRAWSURFACE_GBL_MORE this_gbl_more;
|
|
LPDDOPTSURFACEDESC pDDRetOptSurfDesc = NULL;
|
|
LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
|
|
LPDDRAWI_DIRECTDRAW_GBL pdrv;
|
|
|
|
ENTER_DDRAW();
|
|
|
|
DPF(2,A,"ENTERAPI: DD_OptSurface_GetOptSurfaceDesc");
|
|
|
|
TRY
|
|
{
|
|
this_int = (LPDDRAWI_DDRAWSURFACE_INT) pDDS;
|
|
if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
|
|
{
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
this_lcl = this_int->lpLcl;
|
|
this = this_lcl->lpGbl;
|
|
this_gbl_more = GET_LPDDRAWSURFACE_GBL_MORE(this);
|
|
|
|
if( SURFACE_LOST( this_lcl ) )
|
|
{
|
|
LEAVE_DDRAW();
|
|
return DDERR_SURFACELOST;
|
|
}
|
|
|
|
if( !VALID_DDOPTSURFACEDESC_PTR( pDDOptSurfDesc ) )
|
|
{
|
|
DPF_ERR( "Invalid optimized surface description. Did you set the dwSize member?" );
|
|
LEAVE_DDRAW();
|
|
DPF_APIRETURNS(DDERR_INVALIDPARAMS);
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
pDDOptSurfDesc = NULL;
|
|
}
|
|
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
DPF_ERR( "Exception encountered validating parameters" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
//
|
|
// Quit with error if:
|
|
// 1) No hardware
|
|
// 2) Hardware doesnt support optimized surfaces
|
|
// 3) Surface is an unoptimized surface
|
|
//
|
|
|
|
// DDraw Gbl pointer
|
|
pdrv_lcl = this_lcl->lpSurfMore->lpDD_lcl;
|
|
pdrv = pdrv_lcl->lpGbl;
|
|
|
|
// Assert that: (0 == this->lpDDOptSurfaceInfo) <==> (if and only if)
|
|
// (this->ddCaps.dwCaps2 & DDCAPS2_OPTIMIZEDSURFACES)
|
|
|
|
// 1)
|
|
if( pdrv->dwFlags & DDRAWI_NOHARDWARE )
|
|
{
|
|
DPF_ERR ("No hardware present");
|
|
LEAVE_DDRAW();
|
|
return DDERR_NODIRECTDRAWHW;
|
|
}
|
|
|
|
// 2)
|
|
if ((0 == pdrv->lpDDOptSurfaceInfo) ||
|
|
!(pdrv->ddCaps.dwCaps2 & DDCAPS2_OPTIMIZEDSURFACES))
|
|
{
|
|
DPF_ERR ("Optimized surfaces not supported");
|
|
LEAVE_DDRAW();
|
|
return DDERR_NOOPTSURFACESUPPORT;
|
|
}
|
|
|
|
// 3)
|
|
if (!(this_lcl->ddsCaps.dwCaps & DDSCAPS_OPTIMIZED))
|
|
{
|
|
DPF_ERR ("Current surface is not an optimized surface");
|
|
LEAVE_DDRAW();
|
|
return DDERR_NOTANOPTIMIZEDSURFACE;
|
|
}
|
|
|
|
pDDRetOptSurfDesc = MemAlloc (sizeof (*pDDRetOptSurfDesc));
|
|
if (!pDDRetOptSurfDesc)
|
|
{
|
|
DPF_ERR ("Memory allocation failed");
|
|
LEAVE_DDRAW();
|
|
return DDERR_OUTOFMEMORY;
|
|
}
|
|
ZeroMemory (pDDRetOptSurfDesc, sizeof (*pDDRetOptSurfDesc));
|
|
CopyMemory (pDDRetOptSurfDesc, this_gbl_more->lpDDOptSurfaceDesc,
|
|
sizeof (*pDDRetOptSurfDesc));
|
|
pDDOptSurfDesc = pDDRetOptSurfDesc;
|
|
|
|
LEAVE_DDRAW();
|
|
return DD_OK;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------------
|
|
//
|
|
// DoLoadUnOptSurf
|
|
//
|
|
// Actually make the HAL call and update data-structures if the call
|
|
// succeeds.
|
|
//
|
|
//-------------------------------------------------------------------------------
|
|
HRESULT
|
|
DoLoadUnOptSurf(
|
|
LPDDRAWI_DDRAWSURFACE_LCL this_lcl,
|
|
LPDDRAWI_DDRAWSURFACE_GBL this,
|
|
LPDDRAWI_DDRAWSURFACE_LCL src_lcl,
|
|
LPDDRAWI_DDRAWSURFACE_GBL src
|
|
)
|
|
{
|
|
LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
|
|
LPDDRAWI_DIRECTDRAW_GBL pdrv;
|
|
DDHAL_OPTIMIZESURFACEDATA ddhal_osd;
|
|
LPDDOPTSURFACEINFO pDDOptSurfInfo = NULL;
|
|
LPDDRAWI_DDRAWSURFACE_GBL_MORE this_gbl_more, src_gbl_more;
|
|
HRESULT ddrval = DD_OK;
|
|
|
|
// Get the ddraw pointers
|
|
pdrv_lcl = this_lcl->lpSurfMore->lpDD_lcl;
|
|
pdrv = pdrv_lcl->lpGbl;
|
|
pDDOptSurfInfo = pdrv->lpDDOptSurfaceInfo;
|
|
this_gbl_more = GET_LPDDRAWSURFACE_GBL_MORE (this);
|
|
|
|
// Setup data to pass to the driver
|
|
ZeroMemory (&ddhal_osd, sizeof (DDHAL_COPYOPTSURFACEDATA));
|
|
ddhal_osd.lpDD = pdrv_lcl;
|
|
ddhal_osd.ddOptSurfDesc = *(this_gbl_more->lpDDOptSurfaceDesc);
|
|
ddhal_osd.lpDDSSrc = src_lcl;
|
|
ddhal_osd.lpDDSDest = this_lcl;
|
|
|
|
// Make the HAL call
|
|
DOHALCALL(OptimizeSurface, pDDOptSurfInfo->OptimizeSurface, ddhal_osd, ddrval, FALSE );
|
|
|
|
if (ddrval != DD_OK)
|
|
{
|
|
DPF_ERR ("LoadUnOptSurface failed in the driver");
|
|
return ddrval;
|
|
}
|
|
|
|
// ATTENTION: Should the driver do these updates ?
|
|
|
|
// 1) Update the DDRAWI_DDRAWSURFACE_LCL structure
|
|
// Color key stuff is ignored for now
|
|
this_lcl->dwFlags = src_lcl->dwFlags;
|
|
this_lcl->dwFlags &= ~DDRAWISURF_EMPTYSURFACE;
|
|
this_lcl->ddsCaps = src_lcl->ddsCaps;
|
|
this_lcl->ddsCaps.dwCaps |= DDSCAPS_OPTIMIZED;
|
|
#ifdef WIN95
|
|
this_lcl->dwModeCreatedIn = src_lcl->dwModeCreatedIn;
|
|
#else
|
|
this_lcl->dmiCreated = src_lcl->dmiCreated;
|
|
#endif
|
|
this_lcl->dwBackBufferCount = src_lcl->dwBackBufferCount;
|
|
|
|
// 2) Update the DDRAWI_DDRAWSURFACE_MORE structure
|
|
this_lcl->lpSurfMore->dwMipMapCount = src_lcl->lpSurfMore->dwMipMapCount;
|
|
this_lcl->lpSurfMore->ddsCapsEx = src_lcl->lpSurfMore->ddsCapsEx;
|
|
|
|
// 3) Update the DDRAWI_DDRAWSURFACE_GBL structure
|
|
this->dwGlobalFlags = src->dwGlobalFlags;
|
|
this->wHeight = src->wHeight;
|
|
this->wWidth = src->wWidth;
|
|
this->ddpfSurface = src->ddpfSurface;
|
|
|
|
// 4) Update the DDRAWI_DDRAWSURFACE_GBL_MORE structure
|
|
this_gbl_more = GET_LPDDRAWSURFACE_GBL_MORE (this);
|
|
src_gbl_more = GET_LPDDRAWSURFACE_GBL_MORE (src);
|
|
|
|
this_gbl_more->dwContentsStamp = src_gbl_more->dwContentsStamp;
|
|
CopyMemory (this_gbl_more->lpDDOptSurfaceDesc,
|
|
src_gbl_more->lpDDOptSurfaceDesc,
|
|
sizeof (DDOPTSURFACEDESC));
|
|
|
|
return ddrval;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------------
|
|
//
|
|
// FilterSurfCaps
|
|
//
|
|
// Check to see if the surface is can be optimized
|
|
//
|
|
//-------------------------------------------------------------------------------
|
|
HRESULT
|
|
FilterSurfCaps(
|
|
LPDDRAWI_DDRAWSURFACE_LCL surf_lcl,
|
|
LPDDRAWI_DDRAWSURFACE_GBL surf)
|
|
{
|
|
DWORD caps = surf_lcl->ddsCaps.dwCaps;
|
|
|
|
//
|
|
// check for no caps at all!
|
|
//
|
|
if( caps == 0 )
|
|
{
|
|
DPF_ERR( "no caps specified" );
|
|
return DDERR_INVALIDCAPS;
|
|
}
|
|
|
|
//
|
|
// check for bogus caps.
|
|
//
|
|
if( caps & ~DDSCAPS_VALID )
|
|
{
|
|
DPF_ERR( "Create surface: invalid caps specified" );
|
|
return DDERR_INVALIDCAPS;
|
|
}
|
|
|
|
//
|
|
// Anything other than a texture is not allowed
|
|
// ATTENTION: some more flags need to be checked
|
|
//
|
|
if(caps & (DDSCAPS_EXECUTEBUFFER |
|
|
DDSCAPS_BACKBUFFER |
|
|
DDSCAPS_FRONTBUFFER |
|
|
DDSCAPS_OFFSCREENPLAIN |
|
|
DDSCAPS_PRIMARYSURFACE |
|
|
DDSCAPS_PRIMARYSURFACELEFT |
|
|
DDSCAPS_VIDEOPORT |
|
|
DDSCAPS_ZBUFFER |
|
|
DDSCAPS_OWNDC |
|
|
DDSCAPS_OVERLAY |
|
|
DDSCAPS_3DDEVICE |
|
|
DDSCAPS_ALLOCONLOAD)
|
|
)
|
|
{
|
|
DPF_ERR( "currently only textures can be optimized" );
|
|
return DDERR_INVALIDCAPS;
|
|
}
|
|
|
|
if( !(caps & DDSCAPS_TEXTURE) )
|
|
{
|
|
DPF_ERR( "DDSCAPS_TEXTURE needs to be set" );
|
|
return DDERR_INVALIDCAPS;
|
|
}
|
|
|
|
return DD_OK;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------------
|
|
//
|
|
// LoadUnoptimizedSurf method of IDirectDrawOptSurface
|
|
//
|
|
// Load an unoptimized surface. This is a way to optimize a surface.
|
|
//
|
|
// The Surface's PIXELFORMAT will be that of the pDDSSrc in case the call
|
|
// succeeds.
|
|
//
|
|
//-------------------------------------------------------------------------------
|
|
HRESULT
|
|
EXTERN_DDAPI
|
|
DD_OptSurface_LoadUnoptimizedSurf(
|
|
LPDIRECTDRAWSURFACE pDDS,
|
|
LPDIRECTDRAWSURFACE pDDSSrc)
|
|
{
|
|
LPDDRAWI_DDRAWSURFACE_INT this_int;
|
|
LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
|
|
LPDDRAWI_DDRAWSURFACE_GBL this;
|
|
LPDDRAWI_DDRAWSURFACE_INT src_int;
|
|
LPDDRAWI_DDRAWSURFACE_LCL src_lcl;
|
|
LPDDRAWI_DDRAWSURFACE_GBL src;
|
|
LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
|
|
LPDDRAWI_DIRECTDRAW_GBL pdrv;
|
|
HRESULT ddrval = DD_OK;
|
|
|
|
ENTER_DDRAW();
|
|
|
|
DPF(2,A,"ENTERAPI: DD_OptSurface_LoadUnoptimizedSurf");
|
|
|
|
TRY
|
|
{
|
|
this_int = (LPDDRAWI_DDRAWSURFACE_INT) pDDS;
|
|
if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
|
|
{
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
this_lcl = this_int->lpLcl;
|
|
this = this_lcl->lpGbl;
|
|
|
|
if( SURFACE_LOST( this_lcl ) )
|
|
{
|
|
LEAVE_DDRAW();
|
|
return DDERR_SURFACELOST;
|
|
}
|
|
|
|
src_int = (LPDDRAWI_DDRAWSURFACE_INT) pDDSSrc;
|
|
if( !VALID_DIRECTDRAWSURFACE_PTR( src_int ) )
|
|
{
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
|
|
src_lcl = src_int->lpLcl;
|
|
if( SURFACE_LOST( src_lcl ) )
|
|
{
|
|
LEAVE_DDRAW();
|
|
return DDERR_SURFACELOST;
|
|
}
|
|
src = src_lcl->lpGbl;
|
|
}
|
|
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
DPF_ERR( "Exception encountered validating parameters" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
//ATTENTION: Should src be AddRef'd ?
|
|
|
|
//
|
|
// Quit with error if:
|
|
// 1) No hardware
|
|
// 2) Hardware doesnt support optimized surfaces
|
|
// 3) Surface is an unoptimized surface
|
|
// 4) Src is an optimized surface
|
|
// 5) Current surface is not empty (should we enforce it, or let the driver
|
|
// deal with it ?)
|
|
// 6) The surface is not the "right" type
|
|
// 7) The driver fails for some reason
|
|
//
|
|
|
|
// DDraw Gbl pointer
|
|
pdrv_lcl = this_lcl->lpSurfMore->lpDD_lcl;
|
|
pdrv = pdrv_lcl->lpGbl;
|
|
|
|
// 1)
|
|
if( pdrv->dwFlags & DDRAWI_NOHARDWARE )
|
|
{
|
|
DPF_ERR ("No hardware present");
|
|
LEAVE_DDRAW();
|
|
return DDERR_NODIRECTDRAWHW;
|
|
}
|
|
|
|
// 2)
|
|
if ((0 == pdrv->lpDDOptSurfaceInfo) ||
|
|
!(pdrv->ddCaps.dwCaps2 & DDCAPS2_OPTIMIZEDSURFACES))
|
|
{
|
|
DPF_ERR ("Optimized surfaces not supported");
|
|
LEAVE_DDRAW();
|
|
return DDERR_NOOPTSURFACESUPPORT;
|
|
}
|
|
|
|
// 3)
|
|
if (!(this_lcl->ddsCaps.dwCaps & DDSCAPS_OPTIMIZED))
|
|
{
|
|
DPF_ERR ("Current surface is not an optimized surface");
|
|
LEAVE_DDRAW();
|
|
return DDERR_NOTANOPTIMIZEDSURFACE;
|
|
}
|
|
|
|
// 4)
|
|
if (src_lcl->ddsCaps.dwCaps & DDSCAPS_OPTIMIZED)
|
|
{
|
|
DPF_ERR ("Source surface is an optimized surface");
|
|
LEAVE_DDRAW();
|
|
return DDERR_ISOPTIMIZEDSURFACE;
|
|
}
|
|
|
|
// 5)
|
|
if (!(this_lcl->dwFlags & DDRAWISURF_EMPTYSURFACE))
|
|
{
|
|
DPF_ERR ("Current surface is not an empty optimized surface");
|
|
LEAVE_DDRAW();
|
|
return DDERR_NOTANEMPTYOPTIMIZEDSURFACE;
|
|
}
|
|
|
|
// 6)
|
|
ddrval = FilterSurfCaps (src_lcl, src);
|
|
if (ddrval != DD_OK)
|
|
{
|
|
DPF_ERR ("Source surface cannot be optimized");
|
|
LEAVE_DDRAW();
|
|
return DDERR_NOTANEMPTYOPTIMIZEDSURFACE;
|
|
}
|
|
|
|
// Now attempt the actual load
|
|
ddrval = DoLoadUnOptSurf (this_lcl, this, src_lcl, src);
|
|
|
|
LEAVE_DDRAW();
|
|
return ddrval;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------------
|
|
//
|
|
// DoCopyOptSurf
|
|
//
|
|
// Actually make the HAL call and update data-structures if the call
|
|
// succeeds.
|
|
//
|
|
//-------------------------------------------------------------------------------
|
|
HRESULT
|
|
DoCopyOptSurf(
|
|
LPDDRAWI_DDRAWSURFACE_LCL this_lcl,
|
|
LPDDRAWI_DDRAWSURFACE_GBL this,
|
|
LPDDRAWI_DDRAWSURFACE_LCL src_lcl,
|
|
LPDDRAWI_DDRAWSURFACE_GBL src
|
|
)
|
|
{
|
|
LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
|
|
LPDDRAWI_DIRECTDRAW_GBL pdrv;
|
|
DDHAL_COPYOPTSURFACEDATA ddhal_cosd;
|
|
LPDDOPTSURFACEINFO pDDOptSurfInfo = NULL;
|
|
LPDDRAWI_DDRAWSURFACE_GBL_MORE this_gbl_more, src_gbl_more;
|
|
HRESULT ddrval = DD_OK;
|
|
|
|
// Get the ddraw pointers
|
|
pdrv_lcl = this_lcl->lpSurfMore->lpDD_lcl;
|
|
pdrv = pdrv_lcl->lpGbl;
|
|
pDDOptSurfInfo = pdrv->lpDDOptSurfaceInfo;
|
|
|
|
// Setup data to pass to the driver
|
|
ZeroMemory (&ddhal_cosd, sizeof (DDHAL_COPYOPTSURFACEDATA));
|
|
ddhal_cosd.lpDD = pdrv_lcl;
|
|
ddhal_cosd.lpDDSSrc = src_lcl;
|
|
ddhal_cosd.lpDDSDest = this_lcl;
|
|
|
|
DOHALCALL(CopyOptSurface, pDDOptSurfInfo->CopyOptSurface, ddhal_cosd, ddrval, FALSE );
|
|
|
|
// If the driver call succeeds, then copy the surface description and
|
|
// pixel format etc.
|
|
if (ddrval != DD_OK)
|
|
{
|
|
DPF_ERR ("CopyOptSurface failed in the driver");
|
|
return ddrval;
|
|
}
|
|
|
|
// ATTENTION: Should the driver do these updates ?
|
|
|
|
// 1) Update the DDRAWI_DDRAWSURFACE_LCL structure
|
|
// Color key stuff is ignored for now
|
|
this_lcl->dwFlags = src_lcl->dwFlags;
|
|
this_lcl->ddsCaps = src_lcl->ddsCaps;
|
|
#ifdef WIN95
|
|
this_lcl->dwModeCreatedIn = src_lcl->dwModeCreatedIn;
|
|
#else
|
|
this_lcl->dmiCreated = src_lcl->dmiCreated;
|
|
#endif
|
|
this_lcl->dwBackBufferCount = src_lcl->dwBackBufferCount;
|
|
|
|
// 2) Update the DDRAWI_DDRAWSURFACE_MORE structure
|
|
this_lcl->lpSurfMore->dwMipMapCount = src_lcl->lpSurfMore->dwMipMapCount;
|
|
this_lcl->lpSurfMore->ddsCapsEx = src_lcl->lpSurfMore->ddsCapsEx;
|
|
|
|
// 3) Update the DDRAWI_DDRAWSURFACE_GBL structure
|
|
this->dwGlobalFlags = src->dwGlobalFlags;
|
|
this->wHeight = src->wHeight;
|
|
this->wWidth = src->wWidth;
|
|
this->ddpfSurface = src->ddpfSurface;
|
|
|
|
// 4) Update the DDRAWI_DDRAWSURFACE_GBL_MORE structure
|
|
this_gbl_more = GET_LPDDRAWSURFACE_GBL_MORE (this);
|
|
src_gbl_more = GET_LPDDRAWSURFACE_GBL_MORE (src);
|
|
|
|
this_gbl_more->dwContentsStamp = src_gbl_more->dwContentsStamp;
|
|
CopyMemory (this_gbl_more->lpDDOptSurfaceDesc,
|
|
src_gbl_more->lpDDOptSurfaceDesc,
|
|
sizeof (DDOPTSURFACEDESC));
|
|
|
|
return ddrval;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------------
|
|
//
|
|
// CopyOptimizedSurf method of IDirectDrawOptSurface
|
|
//
|
|
// Copy an optimized surface.
|
|
//
|
|
// The Surface's PIXELFORMAT will be that of the pDDSSrc in case the call
|
|
// succeeds.
|
|
//
|
|
//-------------------------------------------------------------------------------
|
|
HRESULT
|
|
EXTERN_DDAPI
|
|
DD_OptSurface_CopyOptimizedSurf(
|
|
LPDIRECTDRAWSURFACE pDDS,
|
|
LPDIRECTDRAWSURFACE pDDSSrc)
|
|
{
|
|
LPDDRAWI_DDRAWSURFACE_INT this_int;
|
|
LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
|
|
LPDDRAWI_DDRAWSURFACE_GBL this;
|
|
LPDDRAWI_DDRAWSURFACE_INT src_int;
|
|
LPDDRAWI_DDRAWSURFACE_LCL src_lcl;
|
|
LPDDRAWI_DDRAWSURFACE_GBL src;
|
|
LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
|
|
LPDDRAWI_DIRECTDRAW_GBL pdrv;
|
|
HRESULT ddrval = DD_OK;
|
|
|
|
ENTER_DDRAW();
|
|
|
|
DPF(2,A,"ENTERAPI: DD_OptSurface_CopyOptimizedSurf");
|
|
|
|
TRY
|
|
{
|
|
this_int = (LPDDRAWI_DDRAWSURFACE_INT) pDDS;
|
|
if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
|
|
{
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
this_lcl = this_int->lpLcl;
|
|
this = this_lcl->lpGbl;
|
|
|
|
if( SURFACE_LOST( this_lcl ) )
|
|
{
|
|
LEAVE_DDRAW();
|
|
return DDERR_SURFACELOST;
|
|
}
|
|
|
|
src_int = (LPDDRAWI_DDRAWSURFACE_INT) pDDSSrc;
|
|
if( !VALID_DIRECTDRAWSURFACE_PTR( src_int ) )
|
|
{
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
src_lcl = src_int->lpLcl;
|
|
src = src_lcl->lpGbl;
|
|
}
|
|
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
DPF_ERR( "Exception encountered validating parameters" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
//ATTENTION: Should src be AddRef'd ?
|
|
|
|
//
|
|
// Quit with error if:
|
|
// 1) No hardware
|
|
// 2) Hardware doesnt support optimized surfaces
|
|
// 3) Surface is an unoptimized surface
|
|
// 4) Src is an unoptimized surface
|
|
// 5) Src is an empty optimized surface
|
|
// 6) Current surface is not empty (should we enforce it, or let the driver
|
|
// deal with it ?)
|
|
// 7) The driver fails for some reason
|
|
//
|
|
|
|
// DDraw Gbl pointer
|
|
pdrv_lcl = this_lcl->lpSurfMore->lpDD_lcl;
|
|
pdrv = pdrv_lcl->lpGbl;
|
|
|
|
// 1)
|
|
if( pdrv->dwFlags & DDRAWI_NOHARDWARE )
|
|
{
|
|
DPF_ERR ("No hardware present");
|
|
LEAVE_DDRAW();
|
|
return DDERR_NODIRECTDRAWHW;
|
|
}
|
|
|
|
// 2)
|
|
if ((0 == pdrv->lpDDOptSurfaceInfo) ||
|
|
!(pdrv->ddCaps.dwCaps2 & DDCAPS2_OPTIMIZEDSURFACES))
|
|
{
|
|
DPF_ERR ("Optimized surfaces not supported");
|
|
LEAVE_DDRAW();
|
|
return DDERR_NOOPTSURFACESUPPORT;
|
|
}
|
|
|
|
// 3)
|
|
if (!(this_lcl->ddsCaps.dwCaps & DDSCAPS_OPTIMIZED))
|
|
{
|
|
DPF_ERR ("Current surface is not an optimized surface");
|
|
LEAVE_DDRAW();
|
|
return DDERR_NOTANOPTIMIZEDSURFACE;
|
|
}
|
|
|
|
// 4)
|
|
if (!(src_lcl->ddsCaps.dwCaps & DDSCAPS_OPTIMIZED))
|
|
{
|
|
DPF_ERR ("Source surface is not an optimized surface");
|
|
LEAVE_DDRAW();
|
|
return DDERR_NOTANOPTIMIZEDSURFACE;
|
|
}
|
|
|
|
// 5)
|
|
if (src_lcl->dwFlags & DDRAWISURF_EMPTYSURFACE)
|
|
{
|
|
DPF_ERR ("Source surface is an empty optimized surface");
|
|
LEAVE_DDRAW();
|
|
return DDERR_ISANEMPTYOPTIMIZEDSURFACE;
|
|
}
|
|
|
|
// 6)
|
|
if (!(this_lcl->dwFlags & DDRAWISURF_EMPTYSURFACE))
|
|
{
|
|
DPF_ERR ("Current surface is not an empty optimized surface");
|
|
LEAVE_DDRAW();
|
|
return DDERR_NOTANEMPTYOPTIMIZEDSURFACE;
|
|
}
|
|
|
|
// Now attempt the actual copy
|
|
ddrval = DoCopyOptSurf (this_lcl, this, src_lcl, src);
|
|
|
|
LEAVE_DDRAW();
|
|
return ddrval;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------------
|
|
//
|
|
// DoUnOptimize
|
|
//
|
|
// Actually make the HAL call and update data-structures if the call
|
|
// succeeds.
|
|
//
|
|
//-------------------------------------------------------------------------------
|
|
HRESULT
|
|
DoUnOptimize(
|
|
LPDDSURFACEDESC2 pSurfDesc,
|
|
LPDDRAWI_DDRAWSURFACE_LCL this_lcl,
|
|
LPDDRAWI_DDRAWSURFACE_GBL this,
|
|
LPDIRECTDRAWSURFACE FAR *ppDDSDest
|
|
)
|
|
{
|
|
LPDDRAWI_DIRECTDRAW_INT pdrv_int;
|
|
LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
|
|
LPDDRAWI_DIRECTDRAW_GBL pdrv;
|
|
LPDDRAWI_DDRAWSURFACE_LCL new_surf_lcl;
|
|
LPDDRAWI_DDRAWSURFACE_INT new_surf_int;
|
|
LPDDRAWI_DDRAWSURFACE_GBL new_surf;
|
|
LPDDRAWI_DDRAWSURFACE_GBL_MORE new_surf_gbl_more;
|
|
DDPIXELFORMAT ddpf;
|
|
DDSCAPS caps;
|
|
DDHAL_UNOPTIMIZESURFACEDATA ddhal_uosd;
|
|
LPDDOPTSURFACEINFO pDDOptSurfInfo = NULL;
|
|
LPDDRAWI_DDRAWSURFACE_INT pSurf_int, prev_int;
|
|
HRESULT ddrval = DD_OK;
|
|
|
|
// Get the ddraw pointers
|
|
pdrv_int = this_lcl->lpSurfMore->lpDD_int;
|
|
pdrv_lcl = this_lcl->lpSurfMore->lpDD_lcl;
|
|
pdrv = pdrv_lcl->lpGbl;
|
|
|
|
//
|
|
// Fix the caps
|
|
//
|
|
ZeroMemory (&caps, sizeof (DDSCAPS));
|
|
if (pSurfDesc->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
|
|
caps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
|
|
if (pSurfDesc->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)
|
|
caps.dwCaps |= DDSCAPS_VIDEOMEMORY;
|
|
if (pSurfDesc->ddsCaps.dwCaps & DDSCAPS_LOCALVIDMEM)
|
|
caps.dwCaps |= DDSCAPS_LOCALVIDMEM;
|
|
if (pSurfDesc->ddsCaps.dwCaps & DDSCAPS_NONLOCALVIDMEM)
|
|
caps.dwCaps |= DDSCAPS_NONLOCALVIDMEM;
|
|
|
|
// Quit if the memory type is not supported
|
|
if (caps.dwCaps & DDSCAPS_NONLOCALVIDMEM)
|
|
{
|
|
if (!(pdrv->ddCaps.dwCaps2 & DDCAPS2_NONLOCALVIDMEM))
|
|
{
|
|
DPF_ERR( "Driver does not support non-local video memory" );
|
|
return DDERR_NONONLOCALVIDMEM;
|
|
}
|
|
}
|
|
|
|
#if 0
|
|
// Quit if textures are not supported
|
|
if (!(pdrv->ddCaps.dwCaps & DDCAPS_TEXTURE))
|
|
{
|
|
DPF_ERR( "Driver does not support textures" );
|
|
return DDERR_NOTEXTUREHW;
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// PixelFormat: Mark it as an empty surface
|
|
//
|
|
ZeroMemory (&ddpf, sizeof (ddpf));
|
|
ddpf.dwSize = sizeof (ddpf);
|
|
ddpf.dwFlags = DDPF_EMPTYSURFACE;
|
|
|
|
// Make a new uninitialized surface
|
|
ddrval = CreateAndLinkUnintializedSurface (pdrv_lcl, pdrv_int, ppDDSDest);
|
|
if (ddrval != DD_OK)
|
|
{
|
|
DPF_ERR ("createAndLinkUnintializedSurface failed");
|
|
return ddrval;
|
|
}
|
|
|
|
//
|
|
// 1) Update GBL_MORE structure
|
|
//
|
|
new_surf_int = (LPDDRAWI_DDRAWSURFACE_INT)*ppDDSDest;
|
|
new_surf_lcl = new_surf_int->lpLcl;
|
|
new_surf = new_surf_lcl->lpGbl;
|
|
new_surf_gbl_more = GET_LPDDRAWSURFACE_GBL_MORE (new_surf);
|
|
// Init the contents stamp to 0 means the surface's contents can
|
|
// change at any time.
|
|
new_surf_gbl_more->dwContentsStamp = 0;
|
|
|
|
//
|
|
// 2) Update DDRAWI_DDRAWSURFACE_GBL structure
|
|
//
|
|
new_surf->ddpfSurface = this->ddpfSurface;
|
|
|
|
//
|
|
// 3) Update DDRAWI_DDRAWSURFACE_INT structure
|
|
//
|
|
new_surf_int->lpVtbl = &ddSurface4Callbacks;
|
|
|
|
//
|
|
// 4) Update DDRAWI_DDRAWSURFACE_LCL structure
|
|
//
|
|
|
|
// Flag it as an:
|
|
// 1) empty surface
|
|
// 2) Front surface
|
|
// 3) Has a pixelformat
|
|
new_surf_lcl->dwFlags = (DDRAWISURF_EMPTYSURFACE |
|
|
DDRAWISURF_FRONTBUFFER |
|
|
DDRAWISURF_HASPIXELFORMAT);
|
|
// fill in the current caps
|
|
new_surf_lcl->ddsCaps = caps;
|
|
|
|
|
|
// Try the unoptimize
|
|
pDDOptSurfInfo = pdrv->lpDDOptSurfaceInfo;
|
|
|
|
// Setup data to pass to the driver
|
|
ZeroMemory (&ddhal_uosd, sizeof (DDHAL_UNOPTIMIZESURFACEDATA));
|
|
ddhal_uosd.lpDD = pdrv_lcl;
|
|
ddhal_uosd.lpDDSSrc = this_lcl;
|
|
ddhal_uosd.lpDDSDest = new_surf_lcl;
|
|
|
|
DOHALCALL(UnOptimizeSurface, pDDOptSurfInfo->UnOptimizeSurface, ddhal_uosd, ddrval, FALSE );
|
|
|
|
if (ddrval == DD_OK)
|
|
{
|
|
return DD_OK;
|
|
}
|
|
|
|
// If there was an error, then destroy the surface
|
|
// Since it is an empty surface, all we need to do is:
|
|
// i) unlink the surface from the ddraw-chain
|
|
// ii) on NT, inform the kernel
|
|
// iii) free all the allocated memory
|
|
|
|
// i)
|
|
prev_int = NULL;
|
|
pSurf_int = pdrv->dsList;
|
|
while ((pSurf_int != NULL) && (pSurf_int != new_surf_int))
|
|
{
|
|
prev_int = pSurf_int;
|
|
pSurf_int = pSurf_int->lpLink;
|
|
}
|
|
if (pSurf_int == new_surf_int)
|
|
{
|
|
prev_int->lpLink = new_surf_int->lpLink;
|
|
}
|
|
|
|
// ii)
|
|
#ifdef WINNT
|
|
DPF(8,"Attempting to destroy NT kernel mode surface object");
|
|
|
|
if (!DdDeleteSurfaceObject (new_surf_lcl))
|
|
{
|
|
DPF_ERR("NT kernel mode stuff won't delete its surface object!");
|
|
ddrval = DDERR_GENERIC;
|
|
}
|
|
#endif
|
|
|
|
// iii)
|
|
MemFree (new_surf_lcl);
|
|
|
|
return ddrval;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------------
|
|
//
|
|
// Unoptimize method of IDirectDrawOptSurface
|
|
//
|
|
// Unoptimize an optimized surface. In doing so, it creates a new surface.
|
|
//
|
|
// The pDDSDest surface's PIXELFORMAT will be that of the pDDS in case the call
|
|
// succeeds. This means that the pixelformat of the original surface that was
|
|
// loaded is restored.
|
|
//
|
|
//-------------------------------------------------------------------------------
|
|
HRESULT
|
|
EXTERN_DDAPI
|
|
DD_OptSurface_Unoptimize(
|
|
LPDIRECTDRAWSURFACE pDDS,
|
|
LPDDSURFACEDESC2 pSurfDesc,
|
|
LPDIRECTDRAWSURFACE FAR *ppDDSDest,
|
|
IUnknown FAR *pUnkOuter)
|
|
{
|
|
LPDDRAWI_DDRAWSURFACE_INT this_int;
|
|
LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
|
|
LPDDRAWI_DDRAWSURFACE_GBL this;
|
|
LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
|
|
LPDDRAWI_DIRECTDRAW_GBL pdrv;
|
|
HRESULT ddrval = DD_OK;
|
|
|
|
if( pUnkOuter != NULL )
|
|
{
|
|
return CLASS_E_NOAGGREGATION;
|
|
}
|
|
|
|
ENTER_DDRAW();
|
|
|
|
DPF(2,A,"ENTERAPI: DD_OptSurface_Unoptimize");
|
|
|
|
TRY
|
|
{
|
|
if( !VALID_DDSURFACEDESC2_PTR( pSurfDesc ) )
|
|
{
|
|
DPF_ERR( "Invalid surface description. Did you set the dwSize member?" );
|
|
LEAVE_DDRAW();
|
|
DPF_APIRETURNS(DDERR_INVALIDPARAMS);
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
this_int = (LPDDRAWI_DDRAWSURFACE_INT) pDDS;
|
|
if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
|
|
{
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
this_lcl = this_int->lpLcl;
|
|
this = this_lcl->lpGbl;
|
|
|
|
if( SURFACE_LOST( this_lcl ) )
|
|
{
|
|
LEAVE_DDRAW();
|
|
return DDERR_SURFACELOST;
|
|
}
|
|
|
|
if( !VALID_PTR_PTR( ppDDSDest ) )
|
|
{
|
|
DPF_ERR( "Invalid dest. surface pointer" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
*ppDDSDest = NULL;
|
|
|
|
}
|
|
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
DPF_ERR( "Exception encountered validating parameters" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
//
|
|
// Quit with error if:
|
|
// 0) pSurfaceDesc not understood
|
|
// 1) No hardware
|
|
// 2) Hardware doesnt support optimized surfaces
|
|
// 3) Surface is an unoptimized surface
|
|
// 4) Surface is an empty optimized surface
|
|
// 5) The driver fails for some reason
|
|
//
|
|
|
|
// DDraw Gbl pointer
|
|
pdrv_lcl = this_lcl->lpSurfMore->lpDD_lcl;
|
|
pdrv = pdrv_lcl->lpGbl;
|
|
|
|
// 0)
|
|
if (pSurfDesc->ddsCaps.dwCaps & ~(DDSCAPS_SYSTEMMEMORY |
|
|
DDSCAPS_VIDEOMEMORY |
|
|
DDSCAPS_NONLOCALVIDMEM |
|
|
DDSCAPS_LOCALVIDMEM))
|
|
{
|
|
DPF_ERR ("Invalid flags");
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDCAPS;
|
|
}
|
|
|
|
// 1)
|
|
if( pdrv->dwFlags & DDRAWI_NOHARDWARE )
|
|
{
|
|
DPF_ERR ("No hardware present");
|
|
LEAVE_DDRAW();
|
|
return DDERR_NODIRECTDRAWHW;
|
|
}
|
|
|
|
// 2)
|
|
if ((0 == pdrv->lpDDOptSurfaceInfo) ||
|
|
!(pdrv->ddCaps.dwCaps2 & DDCAPS2_OPTIMIZEDSURFACES))
|
|
{
|
|
DPF_ERR ("Optimized surfaces not supported");
|
|
LEAVE_DDRAW();
|
|
return DDERR_NOOPTSURFACESUPPORT;
|
|
}
|
|
|
|
// 3)
|
|
if (!(this_lcl->ddsCaps.dwCaps & DDSCAPS_OPTIMIZED))
|
|
{
|
|
DPF_ERR ("Current surface is not an optimized surface");
|
|
LEAVE_DDRAW();
|
|
return DDERR_NOTANOPTIMIZEDSURFACE;
|
|
}
|
|
|
|
// 4)
|
|
if (this_lcl->dwFlags & DDRAWISURF_EMPTYSURFACE)
|
|
{
|
|
DPF_ERR ("Current surface is an empty optimized surface");
|
|
LEAVE_DDRAW();
|
|
return DDERR_ISANEMPTYOPTIMIZEDSURFACE;
|
|
}
|
|
|
|
// Do the actual unoptimize
|
|
ddrval = DoUnOptimize (pSurfDesc, this_lcl, this, ppDDSDest);
|
|
|
|
LEAVE_DDRAW();
|
|
return ddrval;
|
|
}
|
|
|
|
|