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.
1365 lines
39 KiB
1365 lines
39 KiB
/*==========================================================================;
|
|
*
|
|
* Copyright (C) 1995 Microsoft Corporation. All Rights Reserved.
|
|
*
|
|
* File: vwport.c
|
|
* Content: Direct3D viewport functions
|
|
*@@BEGIN_MSINTERNAL
|
|
*
|
|
* $Id: vwport.c,v 1.25 1995/12/04 11:29:49 sjl Exp $
|
|
*
|
|
* History:
|
|
* Date By Reason
|
|
* ==== == ======
|
|
* 05/11/95 stevela Initial rev with this header.
|
|
*@@END_MSINTERNAL
|
|
*
|
|
***************************************************************************/
|
|
|
|
#include "pch.cpp"
|
|
#pragma hdrstop
|
|
|
|
/*
|
|
* Create an api for the Direct3DViewport object
|
|
*/
|
|
|
|
#include "d3dfei.h"
|
|
#include "drawprim.hpp"
|
|
|
|
extern void UpdateViewportCache(LPDIRECT3DDEVICEI device, D3DVIEWPORT2 *data);
|
|
|
|
//---------------------------------------------------------------------
|
|
//
|
|
// Compute inverse Mclip matrix
|
|
//
|
|
void updateInverseMclip(LPDIRECT3DDEVICEI lpDevI)
|
|
{
|
|
D3DFE_VIEWPORTCACHE& VPORT = lpDevI->vcache;
|
|
VPORT.imclip11 = D3DVAL(1)/VPORT.mclip11;
|
|
VPORT.imclip41 = - VPORT.imclip11 * VPORT.mclip41;
|
|
VPORT.imclip22 = D3DVAL(1)/VPORT.mclip22;
|
|
VPORT.imclip42 = - VPORT.imclip22 * VPORT.mclip42;
|
|
VPORT.imclip33 = D3DVAL(1)/VPORT.mclip33;
|
|
VPORT.imclip43 = VPORT.imclip33 * VPORT.mclip43;
|
|
}
|
|
//---------------------------------------------------------------------
|
|
HRESULT downloadView(LPDIRECT3DVIEWPORTI lpViewI)
|
|
{
|
|
HRESULT err;
|
|
|
|
if (!lpViewI->v_data_is_set)
|
|
{
|
|
D3D_ERR("SetViewport not called for viewport yet");
|
|
return D3DERR_VIEWPORTDATANOTSET;
|
|
}
|
|
|
|
LPDIRECT3DDEVICEI lpDevI = lpViewI->lpDevI;
|
|
|
|
// Update front-end data
|
|
UpdateViewportCache(lpDevI, &lpViewI->v_data);
|
|
|
|
// Download viewport data
|
|
if ((err = lpDevI->UpdateDrvViewInfo(&lpViewI->v_data)) != DD_OK)
|
|
{
|
|
return err;
|
|
}
|
|
|
|
lpViewI->bLightsChanged = TRUE; // Force setLights call
|
|
lpDevI->v_id = lpViewI->v_id;
|
|
|
|
return (D3D_OK);
|
|
}
|
|
//---------------------------------------------------------------------
|
|
// Viewport ID could be different from Device->v_id, because during Execute call
|
|
// Device->v_id is changed to whatever viewport is used as a parameter.
|
|
// So we have to make sure that we use the right viewport.
|
|
//
|
|
inline HRESULT ValidateViewport(LPDIRECT3DDEVICEI lpDevI,
|
|
LPDIRECT3DVIEWPORTI lpView)
|
|
{
|
|
#if DBG
|
|
if (!VALID_DIRECT3DDEVICE3_PTR(lpDevI)) {
|
|
D3D_ERR( "Viewport not attached to Device" );
|
|
return D3DERR_VIEWPORTHASNODEVICE;
|
|
}
|
|
#endif
|
|
|
|
if (lpDevI->v_id != lpView->v_id)
|
|
{
|
|
return downloadView(lpView);
|
|
}
|
|
else
|
|
return D3D_OK;
|
|
}
|
|
|
|
HRESULT hookViewportToD3D(LPDIRECT3DI lpDirect3DI,
|
|
LPDIRECT3DVIEWPORTI lpD3DView)
|
|
{
|
|
|
|
LIST_INSERT_ROOT(&lpDirect3DI->viewports, lpD3DView, list);
|
|
lpD3DView->lpDirect3DI = lpDirect3DI;
|
|
|
|
lpDirect3DI->numViewports++;
|
|
|
|
return (D3D_OK);
|
|
}
|
|
|
|
HRESULT D3DAPI DIRECT3DVIEWPORTI::Initialize(LPDIRECT3D lpD3D)
|
|
{
|
|
return DDERR_ALREADYINITIALIZED;
|
|
}
|
|
|
|
/*
|
|
* Light Management
|
|
*/
|
|
HRESULT hookLightToViewport(LPDIRECT3DVIEWPORTI lpD3DViewI,
|
|
LPDIRECT3DLIGHTI lpD3DLight)
|
|
{
|
|
|
|
CIRCLE_QUEUE_INSERT_END(&lpD3DViewI->lights, DIRECT3DLIGHTI, lpD3DLight,
|
|
light_list);
|
|
lpD3DLight->lpD3DViewportI = lpD3DViewI;
|
|
|
|
lpD3DViewI->numLights++;
|
|
|
|
return (D3D_OK);
|
|
}
|
|
|
|
HRESULT setLights(LPDIRECT3DVIEWPORTI lpView)
|
|
{
|
|
LPDIRECT3DDEVICEI lpDevI;
|
|
LPDIRECT3DLIGHTI lpD3DLightI;
|
|
int i;
|
|
|
|
lpDevI = lpView->lpDevI;
|
|
|
|
lpD3DLightI = (LPDIRECT3DLIGHTI)CIRCLE_QUEUE_FIRST(&lpView->lights);
|
|
|
|
D3DFE_LIGHTING& LIGHTING = lpDevI->lighting;
|
|
LIGHTING.activeLights = NULL;
|
|
|
|
// Set lights in the device
|
|
for (i = 0; i < lpView->numLights; i++)
|
|
{
|
|
if (lpD3DLightI->diLightData.valid &&
|
|
lpD3DLightI->diLightData.flags & D3DLIGHT_ACTIVE)
|
|
{
|
|
lpD3DLightI->diLightData.next = LIGHTING.activeLights;
|
|
LIGHTING.activeLights = &lpD3DLightI->diLightData;
|
|
}
|
|
lpD3DLightI = CIRCLE_QUEUE_NEXT(&lpView->lights,lpD3DLightI,light_list);
|
|
}
|
|
lpDevI->dwFEFlags |= (D3DFE_NEED_TRANSFORM_LIGHTS | D3DFE_LIGHTS_DIRTY);
|
|
|
|
return (D3D_OK);
|
|
}
|
|
|
|
/*
|
|
* Create the Viewport
|
|
*/
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "Direct3D::CreateViewport"
|
|
|
|
HRESULT D3DAPI DIRECT3DI::CreateViewport(LPDIRECT3DVIEWPORT* lplpD3DView,
|
|
IUnknown *pUnkOuter)
|
|
{
|
|
return CreateViewport((LPDIRECT3DVIEWPORT3*)lplpD3DView, NULL);
|
|
}
|
|
|
|
HRESULT D3DAPI DIRECT3DI::CreateViewport(LPDIRECT3DVIEWPORT2* lplpD3DView2,
|
|
IUnknown *pUnkOuter)
|
|
{
|
|
return CreateViewport((LPDIRECT3DVIEWPORT3*)lplpD3DView2, NULL);
|
|
}
|
|
|
|
HRESULT D3DAPI DIRECT3DI::CreateViewport(LPDIRECT3DVIEWPORT3* lplpD3DView,
|
|
IUnknown *pUnkOuter)
|
|
{
|
|
LPDIRECT3DVIEWPORTI lpView;
|
|
HRESULT ret = D3D_OK;
|
|
|
|
if(pUnkOuter != NULL) {
|
|
return CLASS_E_NOAGGREGATION;
|
|
}
|
|
|
|
CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
|
|
|
|
/*
|
|
* validate parms
|
|
*/
|
|
if (!VALID_DIRECT3D3_PTR(this)) {
|
|
D3D_ERR( "Invalid Direct3D pointer" );
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
if (!VALID_OUTPTR(lplpD3DView)) {
|
|
D3D_ERR( "Invalid pointer to pointer pointer" );
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
*lplpD3DView = NULL;
|
|
|
|
lpView = new DIRECT3DVIEWPORTI(this);
|
|
|
|
if (!lpView) {
|
|
D3D_ERR("failed to allocate space for object");
|
|
return (DDERR_OUTOFMEMORY);
|
|
}
|
|
|
|
/*
|
|
* Put this device in the list of those owned by the
|
|
* Direct3D object
|
|
*/
|
|
ret = hookViewportToD3D(this, lpView);
|
|
if (ret != D3D_OK) {
|
|
D3D_ERR("failed to associate viewport to Direct3D");
|
|
delete lpView;
|
|
return (ret);
|
|
}
|
|
*lplpD3DView = (LPDIRECT3DVIEWPORT3)lpView;
|
|
|
|
return (D3D_OK);
|
|
}
|
|
|
|
DIRECT3DVIEWPORTI::DIRECT3DVIEWPORTI(LPDIRECT3DI lpD3DI)
|
|
{
|
|
/*
|
|
* setup the object
|
|
*/
|
|
/*** Object Data ***/
|
|
memset(&v_data, 0, sizeof(D3DVIEWPORT2));
|
|
v_data_is_set = FALSE;
|
|
bHaveBackgndMat=FALSE;
|
|
hBackgndMat=NULL;
|
|
lpDDSBackgndDepth=NULL;
|
|
clrCount=0;
|
|
clrRects=NULL;
|
|
|
|
refCnt = 1;
|
|
lpDevI=NULL;
|
|
v_id = lpD3DI->v_next++;
|
|
|
|
/*
|
|
* Initialise lights
|
|
*/
|
|
numLights = 0;
|
|
CIRCLE_QUEUE_INITIALIZE(&lights, DIRECT3DLIGHTI);
|
|
|
|
/*
|
|
* Make sure that lights are always downloaded the first time
|
|
*/
|
|
bLightsChanged = TRUE;
|
|
|
|
}
|
|
|
|
/*
|
|
* IDirect3DViewport members
|
|
*/
|
|
|
|
/*
|
|
* Transform
|
|
*/
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "Direct3DViewport::SetViewport"
|
|
|
|
HRESULT D3DAPI DIRECT3DVIEWPORTI::SetViewport(LPD3DVIEWPORT lpData)
|
|
{
|
|
HRESULT ret;
|
|
|
|
CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
|
|
/*
|
|
* validate parms
|
|
*/
|
|
TRY
|
|
{
|
|
if (!VALID_DIRECT3DVIEWPORT3_PTR(this)) {
|
|
D3D_ERR( "Invalid Direct3DViewport pointer" );
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
if (!VALID_D3DVIEWPORT_PTR(lpData)) {
|
|
D3D_ERR( "Invalid D3DVIEWPORT pointer" );
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
}
|
|
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
D3D_ERR( "Exception encountered validating parameters" );
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
D3DVIEWPORT2 v;
|
|
if (lpData->dvScaleX == 0.0f || lpData->dvScaleY == 0.0f)
|
|
{
|
|
D3D_ERR( "Invalid viewport data" );
|
|
v.dvClipWidth = 0.0f;
|
|
v.dvClipHeight = 0.0f;
|
|
}
|
|
else
|
|
{
|
|
v.dvClipWidth = lpData->dwWidth / lpData->dvScaleX;
|
|
v.dvClipHeight = lpData->dwHeight / lpData->dvScaleY;
|
|
}
|
|
/* Convert D3DVIEWPORT to D3DVIEWPORT2 */
|
|
v.dwSize = sizeof(D3DVIEWPORT2);
|
|
v.dwX = lpData->dwX;
|
|
v.dwY = lpData->dwY;
|
|
v.dwWidth = lpData->dwWidth;
|
|
v.dwHeight = lpData->dwHeight;
|
|
v.dvClipX = -v.dvClipWidth/2.0f;
|
|
v.dvClipY = v.dvClipHeight/2.0f;
|
|
v.dvMinZ = 0.0f;
|
|
v.dvMaxZ = 1.0f;
|
|
ret = SetViewport2(&v);
|
|
return ret;
|
|
}
|
|
|
|
HRESULT D3DAPI DIRECT3DVIEWPORTI::SetViewport2(LPD3DVIEWPORT2 lpData)
|
|
{
|
|
HRESULT err;
|
|
DWORD uSurfWidth,uSurfHeight;
|
|
LPDIRECTDRAWSURFACE lpDDS;
|
|
|
|
CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
|
|
|
|
/*
|
|
* validate parms
|
|
*/
|
|
TRY
|
|
{
|
|
if (!VALID_DIRECT3DVIEWPORT3_PTR(this)) {
|
|
D3D_ERR( "Invalid Direct3DViewport2 pointer" );
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
if (!VALID_D3DVIEWPORT2_PTR(lpData)) {
|
|
D3D_ERR( "Invalid D3DVIEWPORT2 pointer" );
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
}
|
|
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
D3D_ERR( "Exception encountered validating parameters" );
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
if (!VALID_DIRECT3DDEVICE3_PTR(this->lpDevI)) {
|
|
D3D_ERR( "Viewport not attached to Device" );
|
|
return D3DERR_VIEWPORTHASNODEVICE;
|
|
}
|
|
|
|
if (IS_DX5_COMPATIBLE_DEVICE(this->lpDevI))
|
|
{ /* we're called directly by dx5 app, so validate params */
|
|
if (lpData->dvClipWidth == 0.0f || lpData->dvClipHeight == 0.0f ||
|
|
lpData->dvMinZ == lpData->dvMaxZ)
|
|
{
|
|
D3D_ERR( "Invalid viewport data" );
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
lpDDS = this->lpDevI->lpDDSTarget;
|
|
|
|
uSurfWidth= ((LPDDRAWI_DDRAWSURFACE_INT) lpDDS)->lpLcl->lpGbl->wWidth;
|
|
uSurfHeight= ((LPDDRAWI_DDRAWSURFACE_INT) lpDDS)->lpLcl->lpGbl->wHeight;
|
|
|
|
if (lpData->dwX > uSurfWidth ||
|
|
lpData->dwY > uSurfHeight ||
|
|
lpData->dwX + lpData->dwWidth > uSurfWidth ||
|
|
lpData->dwY + lpData->dwHeight > uSurfHeight)
|
|
{
|
|
D3D_ERR("Viewport outside the render target surface");
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
}
|
|
|
|
this->v_data = *lpData;
|
|
this->v_data_is_set = TRUE;
|
|
// If this is the last rendered viewport, update its device
|
|
if (this->v_id == this->lpDevI->v_id)
|
|
{
|
|
err = downloadView(this);
|
|
if (err != D3D_OK)
|
|
{
|
|
return err;
|
|
}
|
|
}
|
|
|
|
return (D3D_OK);
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "Direct3DViewport::GetViewport"
|
|
|
|
HRESULT D3DAPI DIRECT3DVIEWPORTI::GetViewport(LPD3DVIEWPORT lpData)
|
|
{
|
|
HRESULT ret;
|
|
D3DVIEWPORT2 v;
|
|
|
|
CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
|
|
/*
|
|
* validate parms
|
|
*/
|
|
TRY
|
|
{
|
|
if (!VALID_DIRECT3DVIEWPORT3_PTR(this)) {
|
|
D3D_ERR( "Invalid Direct3DViewport pointer" );
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
if (!VALID_D3DVIEWPORT_PTR(lpData)) {
|
|
D3D_ERR( "Invalid D3DVIEWPORT pointer" );
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
}
|
|
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
D3D_ERR( "Exception encountered validating parameters" );
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
v.dwSize = sizeof(D3DVIEWPORT2);
|
|
ret = GetViewport2(&v);
|
|
/* Convert D3DVIEWPORT2 to D3DVIEWPORT */
|
|
lpData->dwSize = sizeof(D3DVIEWPORT);
|
|
lpData->dwX = v.dwX;
|
|
lpData->dwY = v.dwY;
|
|
lpData->dwWidth = v.dwWidth;
|
|
lpData->dwHeight = v.dwHeight;
|
|
lpData->dvMinZ = 0.0f;
|
|
lpData->dvMaxZ = 1.0f;
|
|
lpData->dvScaleX = v.dwWidth / v.dvClipWidth;
|
|
lpData->dvScaleY = v.dwHeight / v.dvClipHeight;
|
|
lpData->dvMaxX = v.dvClipX + v.dvClipWidth;
|
|
lpData->dvMaxY = v.dvClipY;
|
|
return ret;
|
|
}
|
|
|
|
|
|
HRESULT D3DAPI DIRECT3DVIEWPORTI::GetViewport2(LPD3DVIEWPORT2 lpData)
|
|
{
|
|
CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
|
|
|
|
/*
|
|
* validate parms
|
|
*/
|
|
TRY
|
|
{
|
|
if (!VALID_DIRECT3DVIEWPORT3_PTR(this)) {
|
|
D3D_ERR( "Invalid Direct3DViewport pointer" );
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
if (!VALID_D3DVIEWPORT2_PTR(lpData)) {
|
|
D3D_ERR( "Invalid D3DVIEWPORT2 pointer" );
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
}
|
|
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
D3D_ERR( "Exception encountered validating parameters" );
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
if (!this->v_data_is_set)
|
|
{
|
|
D3D_ERR("SetViewport not called for viewport yet");
|
|
return D3DERR_VIEWPORTDATANOTSET;
|
|
}
|
|
|
|
*lpData = this->v_data;
|
|
|
|
return (D3D_OK);
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "Direct3DViewport::TransformVertices"
|
|
|
|
HRESULT D3DAPI DIRECT3DVIEWPORTI::TransformVertices(DWORD dwVertexCount,
|
|
LPD3DTRANSFORMDATA lpData,
|
|
DWORD dwFlags,
|
|
LPDWORD lpOffScreen)
|
|
{
|
|
HRESULT err;
|
|
D3DTRANSFORMDATAI data;
|
|
LPDIRECT3DVIEWPORTI lpViewOld;
|
|
|
|
CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
|
|
CD3DFPstate D3DFPstate; // Sets optimal FPU state for D3D.
|
|
|
|
/*
|
|
* validate parms
|
|
*/
|
|
TRY
|
|
{
|
|
if (!VALID_DIRECT3DVIEWPORT3_PTR(this)) {
|
|
D3D_ERR( "Invalid Direct3DViewport pointer" );
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
if (!VALID_D3DTRANSFORMDATA_PTR(lpData)) {
|
|
D3D_ERR( "Invalid D3DTRANSFORMDATA pointer" );
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
if (!VALID_DWORD_PTR(lpOffScreen)) {
|
|
D3D_ERR( "Invalid DWORD pointer" );
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
}
|
|
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
D3D_ERR( "Exception encountered validating parameters" );
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
dwFlags &= (D3DTRANSFORM_CLIPPED | D3DTRANSFORM_UNCLIPPED);
|
|
if (!dwFlags)
|
|
{
|
|
D3D_ERR("invalid flags");
|
|
return (DDERR_INVALIDPARAMS);
|
|
}
|
|
/*
|
|
* Make sure the correct viewport is set up in the driver.
|
|
*/
|
|
err = ValidateViewport(this->lpDevI, this);
|
|
if (err != D3D_OK)
|
|
{
|
|
D3D_ERR("failed to set viewport");
|
|
return err;
|
|
}
|
|
|
|
lpViewOld = this->lpDevI->lpCurrentViewport;
|
|
lpDevI->lpCurrentViewport = this;
|
|
|
|
data = *(LPD3DTRANSFORMDATAI)lpData;
|
|
data.drExtent.x1 = D3DVAL(lpData->drExtent.x1);
|
|
data.drExtent.y1 = D3DVAL(lpData->drExtent.y1);
|
|
data.drExtent.x2 = D3DVAL(lpData->drExtent.x2);
|
|
data.drExtent.y2 = D3DVAL(lpData->drExtent.y2);
|
|
|
|
if (lpDevI->dwFEFlags & D3DFE_TRANSFORM_DIRTY)
|
|
updateTransform(lpDevI);
|
|
|
|
if (dwFlags == D3DTRANSFORM_CLIPPED)
|
|
{
|
|
if (lpDevI->dwFEFlags & D3DFE_INVERSEMCLIP_DIRTY)
|
|
{
|
|
updateInverseMclip(lpDevI);
|
|
lpDevI->dwFEFlags &= ~D3DFE_INVERSEMCLIP_DIRTY;
|
|
}
|
|
lpDevI->dwFlags &= ~D3DDP_DONOTCLIP;
|
|
}
|
|
else
|
|
lpDevI->dwFlags |= D3DDP_DONOTCLIP;
|
|
|
|
*lpOffScreen = lpDevI->pGeometryFuncs->TransformVertices(lpDevI, dwVertexCount, &data);
|
|
|
|
*lpData = *(D3DTRANSFORMDATA*)&data;
|
|
D3DFE_ConvertExtent(this->lpDevI, &data.drExtent, &lpData->drExtent);
|
|
|
|
this->lpDevI->lpCurrentViewport = lpViewOld;
|
|
|
|
return (D3D_OK);
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "Direct3DViewport::LightElements"
|
|
|
|
HRESULT D3DAPI DIRECT3DVIEWPORTI::LightElements(DWORD dwElementCount,
|
|
LPD3DLIGHTDATA lpData)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "Direct3DViewport::SetBackground"
|
|
|
|
HRESULT D3DAPI DIRECT3DVIEWPORTI::SetBackground(D3DMATERIALHANDLE hMat)
|
|
{
|
|
|
|
CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
|
|
|
|
/*
|
|
* validate parms
|
|
*/
|
|
TRY
|
|
{
|
|
if (!VALID_DIRECT3DVIEWPORT3_PTR(this)) {
|
|
D3D_ERR( "Invalid Direct3DViewport pointer" );
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
}
|
|
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
D3D_ERR( "Exception encountered validating parameters" );
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
if (!hMat) {
|
|
D3D_ERR("invalid material handle");
|
|
return (DDERR_INVALIDPARAMS);
|
|
}
|
|
|
|
this->bHaveBackgndMat = (hMat!=0);
|
|
this->hBackgndMat = hMat;
|
|
|
|
return (D3D_OK);
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "Direct3DViewport::GetBackground"
|
|
|
|
HRESULT D3DAPI DIRECT3DVIEWPORTI::GetBackground(LPD3DMATERIALHANDLE lphMat,
|
|
LPBOOL lpValid)
|
|
{
|
|
HRESULT err;
|
|
|
|
err = D3D_OK;
|
|
|
|
CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
|
|
|
|
/*
|
|
* validate parms
|
|
*/
|
|
TRY
|
|
{
|
|
if (!VALID_DIRECT3DVIEWPORT3_PTR(this)) {
|
|
D3D_ERR( "Invalid Direct3DViewport pointer" );
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
if (!VALID_D3DMATERIALHANDLE_PTR(lphMat)) {
|
|
D3D_ERR( "Invalid D3DMATERIALHANDLE pointer" );
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
if (!VALID_BOOL_PTR(lpValid)) {
|
|
D3D_ERR( "Invalid BOOL pointer" );
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
}
|
|
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
D3D_ERR( "Exception encountered validating parameters" );
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
if (this->bHaveBackgndMat) {
|
|
*lpValid = TRUE;
|
|
*lphMat = this->hBackgndMat;
|
|
} else {
|
|
*lphMat = 0;
|
|
*lpValid = FALSE;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "Direct3DViewport::SetBackgroundDepth"
|
|
|
|
HRESULT D3DAPI DIRECT3DVIEWPORTI::SetBackgroundDepth(LPDIRECTDRAWSURFACE lpDDS) {
|
|
|
|
CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
|
|
|
|
/*
|
|
* validate parms
|
|
*/
|
|
TRY
|
|
{
|
|
if (!VALID_DIRECT3DVIEWPORT2_PTR(this)) {
|
|
D3D_ERR( "Invalid Direct3DViewport pointer" );
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
// passing NULL is OK
|
|
if ((lpDDS!=NULL) && !VALID_D3D_DIRECTDRAWSURFACE_PTR((LPDDRAWI_DDRAWSURFACE_INT)lpDDS)) {
|
|
D3D_ERR( "Invalid DirectDrawSurface pointer" );
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
}
|
|
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
D3D_ERR( "Exception encountered validating parameters" );
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
if(this->lpDDSBackgndDepth!=NULL) {
|
|
this->lpDDSBackgndDepth->Release();
|
|
}
|
|
|
|
this->lpDDSBackgndDepth=lpDDS;
|
|
|
|
return (D3D_OK);
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "Direct3DViewport::SetBackgroundDepth2"
|
|
|
|
HRESULT D3DAPI DIRECT3DVIEWPORTI::SetBackgroundDepth2(LPDIRECTDRAWSURFACE4 lpDDS4)
|
|
{
|
|
LPDIRECTDRAWSURFACE lpDDS;
|
|
HRESULT ret;
|
|
|
|
CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
|
|
|
|
/*
|
|
* validate parms
|
|
*/
|
|
TRY
|
|
{
|
|
if (!VALID_DIRECT3DVIEWPORT3_PTR(this)) {
|
|
D3D_ERR( "Invalid Direct3DViewport pointer" );
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
|
|
// passing NULL is OK
|
|
if ((lpDDS4!=NULL) && !VALID_D3D_DIRECTDRAWSURFACE4_PTR((LPDDRAWI_DDRAWSURFACE_INT)lpDDS4)) {
|
|
D3D_ERR( "Invalid DirectDrawSurface4 pointer" );
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
}
|
|
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
D3D_ERR( "Exception encountered validating parameters" );
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
lpDDS=NULL;
|
|
if(lpDDS4!=NULL) {
|
|
// QI for DDS interface. This constitutes an AddRef, which is different from previous DX5 behavior
|
|
ret = lpDDS4->QueryInterface(IID_IDirectDrawSurface, (LPVOID*)&lpDDS);
|
|
if(FAILED(ret))
|
|
return ret;
|
|
}
|
|
|
|
if(this->lpDDSBackgndDepth)
|
|
this->lpDDSBackgndDepth->Release();
|
|
|
|
this->lpDDSBackgndDepth = lpDDS;
|
|
|
|
return (D3D_OK);
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "Direct3DViewport::GetBackgroundDepth2"
|
|
|
|
HRESULT D3DAPI DIRECT3DVIEWPORTI::GetBackgroundDepth2(LPDIRECTDRAWSURFACE4* lplpDDS,
|
|
LPBOOL lpValid)
|
|
{
|
|
LPDIRECTDRAWSURFACE lpDDS;
|
|
HRESULT ret = D3D_OK;
|
|
|
|
CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
|
|
|
|
/*
|
|
* validate parms
|
|
*/
|
|
TRY
|
|
{
|
|
if (!VALID_DIRECT3DVIEWPORT3_PTR(this)) {
|
|
D3D_ERR( "Invalid Direct3DViewport pointer" );
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
if (!VALID_OUTPTR(lplpDDS)) {
|
|
D3D_ERR( "Invalid ptr to LPDIRECTDRAWSURFACE4" );
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
if (!VALID_BOOL_PTR(lpValid)) {
|
|
D3D_ERR( "Invalid BOOL pointer" );
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
}
|
|
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
D3D_ERR( "Exception encountered validating parameters" );
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
*lplpDDS=NULL;
|
|
|
|
if(this->lpDDSBackgndDepth!=NULL) {
|
|
// QI for DDS interface. This constitutes an AddRef, which is different from previous DX5 behavior
|
|
ret = this->lpDDSBackgndDepth->QueryInterface(IID_IDirectDrawSurface4, (LPVOID*)lplpDDS);
|
|
}
|
|
|
|
*lpValid = (*lplpDDS!=NULL);
|
|
return ret;
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "Direct3DViewport::GetBackgroundDepth"
|
|
|
|
HRESULT D3DAPI DIRECT3DVIEWPORTI::GetBackgroundDepth(LPDIRECTDRAWSURFACE* lplpDDS,
|
|
LPBOOL lpValid)
|
|
{
|
|
CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
|
|
|
|
/*
|
|
* validate parms
|
|
*/
|
|
TRY
|
|
{
|
|
if (!VALID_DIRECT3DVIEWPORT3_PTR(this)) {
|
|
D3D_ERR( "Invalid Direct3DViewport pointer" );
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
if (!VALID_OUTPTR(lplpDDS)) {
|
|
D3D_ERR( "Invalid ptr to LPDIRECTDRAWSURFACE" );
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
if (!VALID_BOOL_PTR(lpValid)) {
|
|
D3D_ERR( "Invalid BOOL pointer" );
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
}
|
|
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
D3D_ERR( "Exception encountered validating parameters" );
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
// no AddRef taken (this was a DX3 bug)
|
|
*lplpDDS = this->lpDDSBackgndDepth;
|
|
*lpValid = (this->lpDDSBackgndDepth!=NULL);
|
|
|
|
return D3D_OK;
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "Direct3DViewport::Clear (ProcessRects)"
|
|
|
|
HRESULT ProcessRects(DIRECT3DVIEWPORTI *pViewport, DWORD dwCount, LPD3DRECT rects) {
|
|
RECT vwport;
|
|
DWORD i,j;
|
|
|
|
/*
|
|
* Rip through the rects and validate that they
|
|
* are within the viewport.
|
|
*/
|
|
|
|
#if DBG
|
|
if(dwCount == 0)
|
|
{
|
|
return D3D_OK;
|
|
}
|
|
if(rects == NULL)
|
|
{
|
|
D3D_ERR("invalid clear rectangle parameter rects == NULL");
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
#endif
|
|
|
|
if (dwCount > pViewport->clrCount) {
|
|
if (D3DRealloc((void**)&pViewport->clrRects, dwCount * sizeof(D3DRECT)) != DD_OK) {
|
|
pViewport->clrCount = 0;
|
|
pViewport->clrRects = NULL;
|
|
D3D_ERR("failed to allocate space for rects");
|
|
return DDERR_OUTOFMEMORY;
|
|
}
|
|
}
|
|
if (IS_DX5_COMPATIBLE_DEVICE(pViewport->lpDevI))
|
|
{
|
|
vwport.left = pViewport->v_data.dwX;
|
|
vwport.top = pViewport->v_data.dwY;
|
|
vwport.right = pViewport->v_data.dwX + pViewport->v_data.dwWidth;
|
|
vwport.bottom = pViewport->v_data.dwY + pViewport->v_data.dwHeight;
|
|
}
|
|
else
|
|
{
|
|
LPDIRECTDRAWSURFACE lpDDS;
|
|
|
|
lpDDS = pViewport->lpDevI->lpDDSTarget;
|
|
|
|
vwport.right = ((LPDDRAWI_DDRAWSURFACE_INT) lpDDS)->lpLcl->lpGbl->wWidth;
|
|
vwport.bottom = ((LPDDRAWI_DDRAWSURFACE_INT) lpDDS)->lpLcl->lpGbl->wHeight;
|
|
|
|
vwport.left = 0;
|
|
vwport.top = 0;
|
|
|
|
}
|
|
j=0;
|
|
for (i = 0; i < dwCount; i++) {
|
|
if (IntersectRect((LPRECT)(pViewport->clrRects + j), &vwport, (LPRECT)(rects + i)))
|
|
j++;
|
|
}
|
|
pViewport->clrCount = j;
|
|
|
|
return D3D_OK;
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "Direct3DViewport::Clear2"
|
|
|
|
HRESULT D3DAPI DIRECT3DVIEWPORTI::Clear2(DWORD dwCount, LPD3DRECT rects, DWORD dwFlags,
|
|
D3DCOLOR dwColor, D3DVALUE dvZ, DWORD dwStencil)
|
|
{
|
|
LPDIRECT3DVIEWPORTI lpTempVwport;
|
|
HRESULT err;
|
|
BOOL bDoRGBClear,bDoZClear,bDoStencilClear;
|
|
LPDDPIXELFORMAT pZPixFmt=NULL;
|
|
|
|
CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
|
|
|
|
/*
|
|
* validate parms
|
|
*/
|
|
TRY
|
|
{
|
|
if (!VALID_DIRECT3DVIEWPORT3_PTR(this)) {
|
|
D3D_ERR( "Invalid Direct3DViewport pointer" );
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
|
|
if (!VALID_DIRECT3DDEVICE3_PTR(this->lpDevI)) {
|
|
D3D_ERR( "Viewport not attached to Device" );
|
|
return D3DERR_VIEWPORTHASNODEVICE;
|
|
}
|
|
#if DBG
|
|
if (IsBadWritePtr(rects, dwCount * sizeof(D3DRECT))) {
|
|
D3D_ERR( "Invalid rects pointer" );
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
#endif
|
|
}
|
|
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
D3D_ERR( "Exception encountered validating parameters" );
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
bDoRGBClear=((dwFlags & D3DCLEAR_TARGET)!=0);
|
|
bDoZClear=((dwFlags & D3DCLEAR_ZBUFFER)!=0);
|
|
bDoStencilClear=((dwFlags & D3DCLEAR_STENCIL)!=0);
|
|
|
|
if (lpDevI->lpD3DHALGlobalDriverData->hwCaps.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_ZBUFFERLESSHSR)
|
|
{
|
|
if (!(lpDevI->lpD3DHALCallbacks3->Clear2) &&
|
|
!(IS_DX7HAL_DEVICE(lpDevI)))
|
|
{
|
|
if (bDoStencilClear)
|
|
{
|
|
D3D_ERR("Invalid flag D3DCLEAR_STENCIL: this ZBUFFERLESSHSR device doesn't support Clear2()");
|
|
return D3DERR_ZBUFFER_NOTPRESENT;
|
|
}
|
|
if (bDoZClear)
|
|
{
|
|
if (!(lpDevI->lpD3DHALCallbacks2->Clear) || (dvZ!=1.0))
|
|
{
|
|
D3D_WARN(3,"Ignoring D3DCLEAR_ZBUFFER since this ZBUFFERLESSHSR device doesn't even support Clear() or Z!=1");
|
|
dwFlags &= ~(D3DCLEAR_ZBUFFER);
|
|
bDoZClear = FALSE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if((this->lpDevI->lpDDSZBuffer==NULL)&&(bDoStencilClear||bDoZClear)) {
|
|
// unlike Clear(), specifying a Zbuffer-clearing flag without a zbuffer will
|
|
// be considered an error
|
|
|
|
if(bDoZClear) {
|
|
D3D_ERR("Invalid flag D3DCLEAR_ZBUFFER: no zbuffer is associated with device");
|
|
}
|
|
if(bDoStencilClear) {
|
|
D3D_ERR("Invalid flag D3DCLEAR_STENCIL: no zbuffer is associated with device");
|
|
}
|
|
return D3DERR_ZBUFFER_NOTPRESENT;
|
|
}
|
|
|
|
if(bDoStencilClear) {
|
|
pZPixFmt=&((LPDDRAWI_DDRAWSURFACE_INT) lpDevI->lpDDSZBuffer)->lpLcl->lpGbl->ddpfSurface;
|
|
if(!(pZPixFmt->dwFlags & DDPF_STENCILBUFFER)) {
|
|
D3D_ERR("Invalid flag D3DCLEAR_STENCIL; current zbuffer's pixel format doesnt support stencil bits");
|
|
return D3DERR_STENCILBUFFER_NOTPRESENT;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!(dwFlags & (D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL))) {
|
|
D3D_ERR("no valid flags passed to Clear2");
|
|
err=DDERR_INVALIDPARAMS;
|
|
goto early_out;
|
|
}
|
|
|
|
#if DBG
|
|
// bad clear values just cause wacky results but no crashes, so OK to allow in retail bld
|
|
|
|
if(bDoZClear && ((dvZ<0.0) || (dvZ>1.0))) {
|
|
D3D_ERR("clear2 Z value outside legal range (0.0-1.0)");
|
|
err=DDERR_INVALIDPARAMS;
|
|
goto early_out;
|
|
}
|
|
|
|
if(bDoStencilClear && pZPixFmt && (dwStencil > (DWORD)((1<<pZPixFmt->dwStencilBitDepth)-1))) {
|
|
D3D_ERR("clear2 stencil value larger than max allowed stencil value for zbuf pixelfmt");
|
|
err=DDERR_INVALIDPARAMS;
|
|
goto early_out;
|
|
}
|
|
#endif
|
|
|
|
// leave this check in retail build since DDFE_Clear keys off lpDDSBackgndDepth to do textured backg. clrs
|
|
|
|
if(bDoZClear && (this->lpDDSBackgndDepth!=NULL)) {
|
|
D3D_ERR("Background Depth Buffer not allowed to be used with Clear2");
|
|
err=DDERR_INVALIDPARAMS;
|
|
goto early_out;
|
|
}
|
|
|
|
#if DBG
|
|
// dont bother with this check for retail, since we can easily ignore existing background material
|
|
if(this->bHaveBackgndMat && bDoRGBClear) {
|
|
D3DMATERIAL dmMat;
|
|
err = D3DHAL_MaterialGetData(this->lpDevI, this->hBackgndMat, &dmMat);
|
|
if (err != D3D_OK) {
|
|
D3D_ERR("Failed to find material from current viewport background material handle");
|
|
goto early_out;
|
|
}
|
|
if(dmMat.hTexture!=0) {
|
|
D3D_ERR("Textured background materials not allowed to be used with Clear2");
|
|
err=DDERR_INVALIDPARAMS;
|
|
goto early_out;
|
|
}
|
|
D3D_WARN(3,"Ignoring current Background Material Color, Clear2 dwColor arg overrides it");
|
|
}
|
|
#endif
|
|
|
|
// Make sure the correct viewport is set up in the driver.
|
|
err = ValidateViewport(this->lpDevI, this);
|
|
if (err != D3D_OK)
|
|
{
|
|
D3D_ERR("failed to set viewport");
|
|
goto early_out;
|
|
}
|
|
|
|
if((err=ProcessRects(this,dwCount,rects))!=D3D_OK)
|
|
goto early_out;
|
|
|
|
/* Make sure this viewport is the current viewport for the duration of this call */
|
|
lpTempVwport = this->lpDevI->lpCurrentViewport;
|
|
this->lpDevI->lpCurrentViewport = this;
|
|
if (IS_DX7HAL_DEVICE(lpDevI))
|
|
{
|
|
static_cast<CDirect3DDeviceIDP2*>(lpDevI)->ClearI(dwFlags, clrCount, clrRects, dwColor, dvZ, dwStencil);
|
|
}
|
|
else
|
|
{
|
|
err = D3DFE_Clear2(this->lpDevI, dwFlags, this->clrCount, this->clrRects,
|
|
dwColor, dvZ, dwStencil);
|
|
}
|
|
/* Restore the original current viewport of the device */
|
|
this->lpDevI->lpCurrentViewport = lpTempVwport;
|
|
|
|
early_out:
|
|
return err;
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "Direct3DViewport::Clear"
|
|
extern void TriFillRectsTex(LPDIRECT3DDEVICEI lpDevI, DWORD count, LPD3DRECT rect,D3DTEXTUREHANDLE hTex);
|
|
|
|
HRESULT D3DAPI DIRECT3DVIEWPORTI::Clear(DWORD dwCount,
|
|
LPD3DRECT rects,
|
|
DWORD dwFlags)
|
|
{
|
|
LPDIRECT3DVIEWPORTI lpTempVwport;
|
|
HRESULT err;
|
|
|
|
CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
|
|
|
|
/*
|
|
* validate parms
|
|
*/
|
|
TRY
|
|
{
|
|
if (!VALID_DIRECT3DVIEWPORT3_PTR(this)) {
|
|
D3D_ERR( "Invalid Direct3DViewport pointer" );
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
|
|
if (!VALID_DIRECT3DDEVICE3_PTR(this->lpDevI)) {
|
|
D3D_ERR( "Viewport not attached to Device" );
|
|
return D3DERR_VIEWPORTHASNODEVICE;
|
|
}
|
|
#if DBG
|
|
if (IsBadWritePtr(rects, dwCount * sizeof(D3DRECT))) {
|
|
D3D_ERR( "Invalid rects pointer" );
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
#endif
|
|
}
|
|
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
D3D_ERR( "Exception encountered validating parameters" );
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
if((dwFlags & D3DCLEAR_ZBUFFER) && (this->lpDevI->lpDDSZBuffer==NULL)) {
|
|
// this is not an error for legacy app compatibility--DX5 allowed this flag
|
|
// to be set even if no ZBuffer exists
|
|
if (!(this->lpDevI->lpD3DHALGlobalDriverData->hwCaps.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_ZBUFFERLESSHSR)
|
|
|| !(this->lpDevI->lpD3DHALCallbacks2->Clear || this->lpDevI->lpD3DHALCallbacks3->Clear2
|
|
|| (IS_DX7HAL_DEVICE(lpDevI)))
|
|
)
|
|
{
|
|
D3D_WARN(3,"Ignoring D3DCLEAR_ZBUFFER since no zbuffer associated with device");
|
|
dwFlags &= ~(D3DCLEAR_ZBUFFER);
|
|
if (! dwFlags)
|
|
{
|
|
D3D_WARN(3, "Viewport::Clear: Nothing to do");
|
|
err = D3D_OK;
|
|
goto early_out;
|
|
}
|
|
}
|
|
}
|
|
|
|
#if DBG
|
|
if (dwFlags & D3DCLEAR_ZBUFFER)
|
|
{
|
|
LPDDPIXELFORMAT pZPixFmt =
|
|
&((LPDDRAWI_DDRAWSURFACE_INT) lpDevI->lpDDSZBuffer)->lpLcl->lpGbl->ddpfSurface;
|
|
if (pZPixFmt->dwFlags & DDPF_STENCILBUFFER) {
|
|
D3D_ERR("Can't use Clear() on Z buffer with stencil planes. Use Clear2()");
|
|
// No change to execution path.
|
|
}
|
|
}
|
|
#endif
|
|
|
|
// leave this check until after checks that turn off flags
|
|
if (!(dwFlags & (D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER))) {
|
|
D3D_ERR("no valid flags were passed to Clear");
|
|
err=DDERR_INVALIDPARAMS;
|
|
goto early_out;
|
|
}
|
|
|
|
// Make sure the correct viewport is set up in the driver.
|
|
err = ValidateViewport(this->lpDevI, this);
|
|
if (err != D3D_OK)
|
|
{
|
|
D3D_ERR("failed to set viewport");
|
|
goto early_out;
|
|
}
|
|
|
|
if((err=ProcessRects(this,dwCount,rects))!=D3D_OK)
|
|
goto early_out;
|
|
|
|
D3DMATERIAL dmMat;
|
|
|
|
if(this->bHaveBackgndMat) {
|
|
err = D3DHAL_MaterialGetData(lpDevI, this->hBackgndMat, &dmMat);
|
|
if(err != D3D_OK) {
|
|
D3D_ERR("Failed to find material from current background material handle");
|
|
goto early_out;
|
|
}
|
|
} else {
|
|
// DX5 legacy apps expect to Clear to Black if Background not initialized
|
|
dmMat.diffuse.r=dmMat.diffuse.g=dmMat.diffuse.b=dmMat.diffuse.a=0;
|
|
dmMat.hTexture=0;
|
|
D3D_WARN(3,"Background Material is NULL!! Setting color to black, but please set a valid background");
|
|
}
|
|
|
|
/* Make sure this viewport is the current viewport for the duration of this call */
|
|
lpTempVwport = this->lpDevI->lpCurrentViewport;
|
|
this->lpDevI->lpCurrentViewport = this;
|
|
|
|
if (IS_DX7HAL_DEVICE(lpDevI))
|
|
{
|
|
if (0 != dmMat.hTexture && (D3DCLEAR_TARGET & dwFlags))
|
|
{
|
|
err = lpDevI->FlushStates();
|
|
if (err != D3D_OK)
|
|
{
|
|
D3D_ERR("Error trying to render batched commands in Clear");
|
|
goto early_out;
|
|
}
|
|
TriFillRectsTex(lpDevI, clrCount, clrRects, dmMat.hTexture);
|
|
dwFlags &= ~D3DCLEAR_TARGET;
|
|
}
|
|
if ((D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER) & dwFlags)
|
|
{
|
|
static_cast<CDirect3DDeviceIDP2*>(lpDevI)->ClearI(dwFlags, clrCount, clrRects, CVAL_TO_RGBA(dmMat.diffuse), 1.0, 0);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
err = D3DFE_Clear(this->lpDevI, dwFlags, this->clrCount, this->clrRects,
|
|
&dmMat.diffuse, dmMat.hTexture);
|
|
}
|
|
/* Restore the original current viewport of the device */
|
|
this->lpDevI->lpCurrentViewport = lpTempVwport;
|
|
|
|
early_out:
|
|
return err;
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "Direct3DViewport::AddLight"
|
|
|
|
HRESULT D3DAPI DIRECT3DVIEWPORTI::AddLight(LPDIRECT3DLIGHT lpD3DLight)
|
|
{
|
|
LPDIRECT3DLIGHTI lpLightI;
|
|
HRESULT err = D3D_OK;
|
|
|
|
CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
|
|
|
|
/*
|
|
* validate parms
|
|
*/
|
|
TRY
|
|
{
|
|
lpLightI = (LPDIRECT3DLIGHTI)lpD3DLight;
|
|
|
|
if (!VALID_DIRECT3DVIEWPORT3_PTR(this)) {
|
|
D3D_ERR( "Invalid Direct3DViewport pointer" );
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
if (!VALID_DIRECT3DLIGHT_PTR(lpLightI)) {
|
|
D3D_ERR( "Invalid DIRECT3DLIGHT pointer" );
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
}
|
|
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
D3D_ERR( "Exception encountered validating parameters" );
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
if (lpLightI->lpD3DViewportI) {
|
|
D3D_ERR("light already associated with a viewport");
|
|
return (D3DERR_LIGHTHASVIEWPORT);
|
|
}
|
|
|
|
err = hookLightToViewport(this, lpLightI);
|
|
if (err != D3D_OK) {
|
|
D3D_ERR("failed to add light to viewport");
|
|
return (err);
|
|
}
|
|
|
|
this->bLightsChanged = TRUE;
|
|
|
|
/*
|
|
* AddRef the light
|
|
*/
|
|
lpD3DLight->AddRef();
|
|
|
|
return (err);
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "Direct3DViewport::DeleteLight"
|
|
|
|
HRESULT D3DAPI DIRECT3DVIEWPORTI::DeleteLight(LPDIRECT3DLIGHT lpD3DLight)
|
|
{
|
|
LPDIRECT3DLIGHTI lpLightI;
|
|
HRESULT err = D3D_OK;
|
|
|
|
CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
|
|
|
|
/*
|
|
* validate parms
|
|
*/
|
|
TRY
|
|
{
|
|
lpLightI = (LPDIRECT3DLIGHTI)lpD3DLight;
|
|
if (!VALID_DIRECT3DVIEWPORT3_PTR(this)) {
|
|
D3D_ERR( "Invalid Direct3DViewport pointer" );
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
if (!VALID_DIRECT3DLIGHT_PTR(lpLightI)) {
|
|
D3D_ERR( "Invalid DIRECT3DLIGHT pointer" );
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
}
|
|
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
D3D_ERR( "Exception encountered validating parameters" );
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
if (lpLightI->lpD3DViewportI != this) {
|
|
D3D_ERR("Light is not associated with this viewport");
|
|
return (D3DERR_LIGHTNOTINTHISVIEWPORT);
|
|
}
|
|
|
|
/*
|
|
* Remove this light from the viewport.
|
|
*/
|
|
CIRCLE_QUEUE_DELETE(&this->lights, lpLightI, light_list);
|
|
this->numLights--;
|
|
|
|
lpLightI->lpD3DViewportI = NULL;
|
|
|
|
this->bLightsChanged = TRUE;
|
|
|
|
/*
|
|
* Release the light
|
|
*/
|
|
lpD3DLight->Release();
|
|
|
|
return (err);
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "Direct3DViewport::NextLight"
|
|
|
|
HRESULT D3DAPI DIRECT3DVIEWPORTI::NextLight(LPDIRECT3DLIGHT lpD3DLight,
|
|
LPDIRECT3DLIGHT* lplpLight,
|
|
DWORD dwFlags)
|
|
{
|
|
LPDIRECT3DLIGHTI lpLightI;
|
|
|
|
CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
|
|
|
|
/*
|
|
* validate parms
|
|
*/
|
|
TRY
|
|
{
|
|
if (!VALID_OUTPTR(lplpLight)) {
|
|
D3D_ERR( "Invalid output pointer to LPDIRECT3DLIGHT" );
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
*lplpLight = NULL;
|
|
|
|
lpLightI = (LPDIRECT3DLIGHTI)lpD3DLight;
|
|
if (!VALID_DIRECT3DVIEWPORT3_PTR(this)) {
|
|
D3D_ERR( "Invalid Direct3DViewport pointer" );
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
if (dwFlags & D3DNEXT_NEXT) {
|
|
if (!VALID_DIRECT3DLIGHT_PTR(lpLightI)) {
|
|
D3D_ERR( "Invalid Direct3DLight pointer" );
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
if (lpLightI && lpLightI->lpD3DViewportI != this) {
|
|
D3D_ERR("light not associated with this viewport");
|
|
return (D3DERR_LIGHTNOTINTHISVIEWPORT);
|
|
}
|
|
}
|
|
|
|
}
|
|
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
D3D_ERR( "Exception encountered validating parameters" );
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
switch (dwFlags) {
|
|
case D3DNEXT_NEXT:
|
|
*lplpLight = (LPDIRECT3DLIGHT)CIRCLE_QUEUE_NEXT(this,lpLightI,light_list);
|
|
break;
|
|
case D3DNEXT_HEAD:
|
|
*lplpLight = (LPDIRECT3DLIGHT)CIRCLE_QUEUE_FIRST(&this->lights);
|
|
break;
|
|
case D3DNEXT_TAIL:
|
|
*lplpLight = (LPDIRECT3DLIGHT)CIRCLE_QUEUE_LAST(&this->lights);
|
|
break;
|
|
default:
|
|
D3D_ERR("invalid flags");
|
|
return (DDERR_INVALIDPARAMS);
|
|
}
|
|
if (*lplpLight == (LPDIRECT3DLIGHT)&this->lights) {
|
|
*lplpLight = NULL;
|
|
}
|
|
|
|
/*
|
|
* Must AddRef the returned object
|
|
*/
|
|
if (*lplpLight)
|
|
(*lplpLight)->AddRef();
|
|
|
|
return (D3D_OK);
|
|
}
|