Source code of Windows XP (NT5)
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.
|
|
/*==========================================================================;
* * Copyright (C) 1997 Microsoft Corporation. All Rights Reserved. * * File: dphal.c * Content: DrawPrimitive implementation for DrawPrimitive HALs * ***************************************************************************/
#include "pch.cpp"
#pragma hdrstop
#include "drawprim.hpp"
#include "clipfunc.h"
//-----------------------------------------------------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "CD3DHal::ProcessVertices"
HRESULT D3DAPI CD3DHal::ProcessVertices(UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IDirect3DVertexBuffer8 *DestBuffer, DWORD dwFlags) { API_ENTER(this); // Takes D3D Lock if necessary
HRESULT hr = D3D_OK; CVertexBuffer* pVB = static_cast<CVertexBuffer*>(DestBuffer); const D3DBUFFER_DESC* pDesc = pVB->GetBufferDesc(); UINT vbVertexSize = pVB->GetVertexSize(); UINT vbNumVertices = pVB->GetNumVertices(); #if DBG
if (pVB->Device() != this) { D3D_ERR("VertexBuffer not created with this device. ProcessVertices failed."); return D3DERR_INVALIDCALL; } if (m_dwCurrentShaderHandle == 0) { D3D_ERR("Current vertex shader is not set. ProcessVertices failed."); return D3DERR_INVALIDCALL; } if (D3DVSD_ISLEGACY(m_dwCurrentShaderHandle) && FVF_TRANSFORMED(m_dwCurrentShaderHandle)) { D3D_ERR("Invalid vertex shader for ProcessVertices. ProcessVertices failed."); return D3DERR_INVALIDCALL; } if (!(m_dwRuntimeFlags & D3DRT_RSSOFTWAREPROCESSING)) { D3D_ERR("D3D Device should be in software mode for ProcessVertices. ProcessVertices failed."); return D3DERR_INVALIDCALL; } if (dwFlags & ~D3DPV_DONOTCOPYDATA) { D3D_ERR( "Invalid dwFlags set. ProcessVertices failed." ); return D3DERR_INVALIDCALL; }
if (pDesc->Usage & D3DUSAGE_DONOTCLIP && !(m_pv->dwDeviceFlags & D3DDEV_DONOTCLIP)) { D3D_ERR("Vertex buffer has D3D_DONOTCLIP usage, but clipping is enabled. ProcessVertices failed."); return D3DERR_INVALIDCALL; } if (pVB->GetFVF() == 0) { D3D_ERR("Destination buffer has no FVF associated with it. ProcessVertices failed."); return D3DERR_INVALIDCALL; } if ((pVB->GetFVF() & D3DFVF_POSITION_MASK) != D3DFVF_XYZRHW) { D3D_ERR("Destination vertex buffer should have D3DFVF_XYZRHW position. ProcessVertices failed."); return D3DERR_INVALIDCALL; } if (VertexCount + DestIndex > vbNumVertices) { D3D_ERR("Destination vertex buffer has not enough space. ProcessVertices failed."); return D3DERR_INVALIDCALL; } #endif
try { DWORD vbFVF = pVB->GetFVF(); m_pv->dwNumVertices = VertexCount; m_pv->dwFlags = D3DPV_VBCALL; #if DBG
ValidateDraw2(D3DPT_TRIANGLELIST, SrcStartIndex, 1, VertexCount, FALSE); #endif
// Internal flags and output vertex offsets could be different for
// ProcessVertices
ForceFVFRecompute();
(this->*m_pfnPrepareToDraw)(SrcStartIndex);
if (!(m_pv->dwDeviceFlags & D3DDEV_DONOTCLIP)) { if (pVB->GetClipCodes() == NULL) { pVB->AllocateClipCodes(); } m_pv->lpClipFlags = pVB->GetClipCodes(); #if DBG
if (m_pv->lpClipFlags == NULL) { D3D_THROW_FAIL("Failed to allocate clip code for the dest VB"); } #endif
m_pv->lpClipFlags += DestIndex; }
// Check number of texture coordinates and texture formats in the
// destination VB are the same as in the computed FVF
DWORD dwComputedTexFormats = m_pv->dwVIDOut & 0xFFFF0000; DWORD dwNumTexCoordVB = FVF_TEXCOORD_NUMBER(vbFVF); if (m_pv->nOutTexCoord > dwNumTexCoordVB || ((vbFVF & dwComputedTexFormats) != dwComputedTexFormats)) { D3D_ERR("Number of output texture coordinates and their format should be"); D3D_ERR("the same in the destination vertex buffer and as computed for current D3D settings."); D3D_ERR("Computed output FVF is 0x%08X", m_pv->dwVIDOut); D3D_THROW_FAIL(""); } // Check if the computed output FVF is a subset of the VB's FVF.
// Number of texture coordinates should be cleared.
DWORD dwComputedFVF = m_pv->dwVIDOut & 0x000000FF; // Specularand diffuse colors could be omitted, as well as psize
dwComputedFVF &= ~(D3DFVF_PSIZE | D3DFVF_DIFFUSE | D3DFVF_SPECULAR | D3DFVF_FOG); if((dwComputedFVF & vbFVF) != dwComputedFVF) { D3D_ERR("Dest vertex buffer's FVF should be a superset of the FVF, computed for"); D3D_ERR("the current D3D settings"); D3D_ERR("Computed output FVF is 0x%08X", m_pv->dwVIDOut); D3D_THROW_FAIL(""); }
BYTE* p; hr = pVB->Lock(0, pDesc->Size, &p, D3DLOCK_NOSYSLOCK); if (FAILED(hr)) { D3D_THROW_FAIL("Cannot lock destination buffer"); }
if (this->dwFEFlags & D3DFE_FRONTEND_DIRTY) DoUpdateState(this);
// Replace output FVF and vertex size
m_pv->dwOutputSize = vbVertexSize; m_pv->dwVIDOut = vbFVF; m_pv->lpvOut = p + DestIndex * vbVertexSize;
// Vertex shaders don't write to the output unless shader writes to it
// explicitely. So we do not bother setting any flags
if (dwFlags & D3DPV_DONOTCOPYDATA) { if (m_pv->dwDeviceFlags & D3DDEV_VERTEXSHADERS) { m_pv->dwFlags |= D3DPV_DONOTCOPYDIFFUSE | D3DPV_DONOTCOPYSPECULAR | D3DPV_DONOTCOPYTEXTURE; } else { m_pv->dwFlags |= D3DPV_DONOTCOPYDIFFUSE | D3DPV_DONOTCOPYSPECULAR | D3DPV_DONOTCOPYTEXTURE; // If D3DIM generates colors or texture, we should clear
// DONOTCOPY bits
if (m_pv->dwFlags & D3DPV_LIGHTING) { m_pv->dwFlags &= ~D3DPV_DONOTCOPYDIFFUSE; if (m_pv->dwDeviceFlags & D3DDEV_SPECULARENABLE) m_pv->dwFlags &= ~D3DPV_DONOTCOPYSPECULAR; } if (m_pv->dwFlags & D3DPV_FOG) m_pv->dwFlags &= ~D3DPV_DONOTCOPYSPECULAR; // If front-end is asked to do something with texture
// coordinates we disable DONOTCOPYTEXTURE
if (__TEXTURETRANSFORMENABLED(m_pv) || m_pv->dwFlags2 & __FLAGS2_TEXGEN) { m_pv->dwFlags &= ~D3DPV_DONOTCOPYTEXTURE; } } }
// Compute flags based on the vertex buffer FVF
UpdateFlagsForOutputFVF(m_pv);
// Update output vertex offsets for the new FVF
ComputeOutputVertexOffsets(m_pv);
m_pv->pGeometryFuncs->ProcessVertices(m_pv);
if (!(m_pv->dwDeviceFlags & D3DDEV_DONOTCLIP)) UpdateClipStatus(this);
// When ProcessVertices is used, user must re-program texture
// stage indices and wrap modes himself
m_pv->dwDeviceFlags &= ~D3DDEV_REMAPTEXTUREINDICES; } catch(HRESULT ret) { D3D_ERR("ProcessVertices failed."); hr = ret; } ForceFVFRecompute(); pVB->Unlock(); return hr; }
|