|
|
//-------------------------------------------------------------------------------
//
// 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; }
|