#include "ASW_Graphics_D3D.h" Direct3D::Exception:: Exception(const char * p_ptrFile, const unsigned int p_uintLine, const char * p_ptrFunction, const char * p_ptrDetail, const HRESULT p_hndError) : ASW::Exception(p_ptrFile, p_uintLine, p_ptrFunction, p_ptrDetail), m_hndError(p_hndError) {} void Direct3D::Exception:: Print(UTIL::Output & p_clsOutput) { char * ptrBuffer; FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, m_hndError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)(&ptrBuffer), 0, NULL); p_clsOutput.Printf("An error has occurred with Direct3D.\n\nFile: [%s]\nLine: [%i]\nFunction: [%s]\nDetail: [%s]\nError: [%s]", ( m_ptrFile != NULL ) ? m_ptrFile : "unknown", m_uintLine, ( m_ptrFunction != NULL ) ? m_ptrFunction : "unknown", ( m_ptrDetail != NULL ) ? m_ptrDetail : "none", ptrBuffer); LocalFree(ptrBuffer); } const char * Direct3D::Exception:: Type() { return "Direct3D"; } const D3DPRIMITIVETYPE Direct3D::m_enmPrimitiveTypes[ASW::Type::PRIMITIVE_COUNT] = { D3DPT_LINELIST, D3DPT_LINESTRIP, D3DPT_TRIANGLELIST, }; const D3DTRANSFORMSTATETYPE Direct3D::m_enmMatrixTypes[ASW::Type::MATRIX_COUNT] = { D3DTS_PROJECTION, D3DTS_TEXTURE0, D3DTS_VIEW, }; const D3DSTENCILOP Direct3D::m_enmStencilOps[ASW::GraphicsApi::STENCILOP_COUNT] = { D3DSTENCILOP_KEEP, D3DSTENCILOP_ZERO, D3DSTENCILOP_REPLACE, D3DSTENCILOP_INVERT, D3DSTENCILOP_INCR, D3DSTENCILOP_DECR, D3DSTENCILOP_INCRSAT, D3DSTENCILOP_DECRSAT, }; const D3DCMPFUNC Direct3D::m_enmTests[ASW::GraphicsApi::TEST_COUNT] = { D3DCMP_NEVER, D3DCMP_ALWAYS, D3DCMP_EQUAL, D3DCMP_NOTEQUAL, D3DCMP_LESS, D3DCMP_GREATER, D3DCMP_LESSEQUAL, D3DCMP_GREATEREQUAL, }; Direct3D:: Direct3D(WindowW32 & p_clsWindow, const ASW::GraphicsApi::Settings & p_stuSettings) : m_fltClearDepth(1.0f), m_dwdClearColor(D3DCOLOR_RGBA(0, 0, 0, 0)), m_ptrDirect3D(NULL), m_ptrDevice(NULL), m_ptrActiveTexture(NULL) { try { m_ptrDirect3D = Direct3DCreate9(D3D_SDK_VERSION); if ( m_ptrDirect3D == NULL ) throw ASW::Exception(__FILE__, __LINE__, __FUNCTION__, "Could not create Direct3D object"); ASW::Window::Settings stuSettings = p_clsWindow.GetSettings(); HWND hndWindow = p_clsWindow.GetWindow(); D3DPRESENT_PARAMETERS stuParameters; memset(&stuParameters, 0, sizeof(D3DPRESENT_PARAMETERS)); stuParameters.SwapEffect = D3DSWAPEFFECT_DISCARD; stuParameters.hDeviceWindow = hndWindow; stuParameters.EnableAutoDepthStencil = TRUE; stuParameters.AutoDepthStencilFormat = D3DFMT_D16; stuParameters.Flags = D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL; stuParameters.PresentationInterval = ( p_stuSettings.m_blnVsync ) ? D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE; HRESULT hndResult; if ( stuSettings.m_blnFullScreen ) { stuParameters.Windowed = FALSE; stuParameters.BackBufferWidth = stuSettings.m_uintWidth; stuParameters.BackBufferHeight = stuSettings.m_uintHeight; stuParameters.BackBufferFormat = FindFormat(stuSettings); hndResult = m_ptrDirect3D->CreateDevice(D3DADAPTER_DEFAULT, ( p_stuSettings.m_blnHardwareRasterizer ) ? D3DDEVTYPE_HAL : D3DDEVTYPE_REF, hndWindow, ( p_stuSettings.m_blnHardwareVertexProcessing ) ? D3DCREATE_HARDWARE_VERTEXPROCESSING : D3DCREATE_SOFTWARE_VERTEXPROCESSING, &stuParameters, &m_ptrDevice); } else { stuParameters.Windowed = TRUE; stuParameters.BackBufferFormat = D3DFMT_UNKNOWN; hndResult = m_ptrDirect3D->CreateDevice(D3DADAPTER_DEFAULT, ( p_stuSettings.m_blnHardwareRasterizer ) ? D3DDEVTYPE_HAL : D3DDEVTYPE_REF, hndWindow, ( p_stuSettings.m_blnHardwareVertexProcessing ) ? D3DCREATE_HARDWARE_VERTEXPROCESSING : D3DCREATE_SOFTWARE_VERTEXPROCESSING, &stuParameters, &m_ptrDevice); } D3D_CHECK(hndResult); D3D_CALL(GetDeviceCaps(&m_stuCaps)); D3D_CALL(GetRenderState(D3DRS_SRCBLEND, (DWORD *)(&(m_enmBlend[0])))); D3D_CALL(GetRenderState(D3DRS_DESTBLEND, (DWORD *)(&(m_enmBlend[1])))); CG_CALL(cgD3D9SetDevice(m_ptrDevice)); CG_CALL(m_stuCgContext = cgCreateContext()); CG_CALL(m_enmCgProfileVertex = cgD3D9GetLatestVertexProfile()); CG_CALL(m_enmCgProfilePixel = cgD3D9GetLatestPixelProfile()); CG_CALL(cgSetAutoCompile(m_stuCgContext, CG_COMPILE_LAZY)); m_uintMaxTextures = 8; m_uintMaxIndexValue = m_stuCaps.MaxVertexIndex; m_uintMaxLights = m_stuCaps.MaxActiveLights; m_uchrMaxBlendingMatrices = ( m_stuCaps.MaxVertexBlendMatrixIndex > 255 ) ? 255 : (unsigned char)(m_stuCaps.MaxVertexBlendMatrixIndex); } catch ( ... ) { cgD3D9SetDevice(NULL); if ( m_ptrDevice ) { m_ptrDevice->Release(); m_ptrDevice = NULL; } if ( m_ptrDirect3D ) { m_ptrDirect3D->Release(); m_ptrDirect3D = NULL; } throw; } } void Direct3D:: Bind(const ASW::Material & p_stuMaterial) { D3DMATERIAL9 stuMaterial; stuMaterial.Diffuse = *((D3DCOLORVALUE *)(&(p_stuMaterial.m_stuDiffuse))); stuMaterial.Ambient = *((D3DCOLORVALUE *)(&(p_stuMaterial.m_stuAmbient))); stuMaterial.Specular = *((D3DCOLORVALUE *)(&(p_stuMaterial.m_stuSpecular))); stuMaterial.Emissive = *((D3DCOLORVALUE *)(&(p_stuMaterial.m_stuEmissive))); stuMaterial.Power = p_stuMaterial.m_fltSpecularDecay; D3D_RUN(SetMaterial(&stuMaterial)); } void Direct3D:: Bind(const ASW::Texture * p_ptrTexture, const unsigned int p_uintStage) { ASW_ASSERT(p_ptrTexture == NULL || p_ptrTexture->m_blnLoaded, "Cannot bind an unloaded texture"); ASW_ASSERT(p_uintStage < m_uintMaxTextures, "Stage exceeds maximum number of textures"); if ( p_ptrTexture != NULL ) { if ( m_blnProperties[ASW::GraphicsApi::PROPERTY_TEXTURING - 1] == false || (p_ptrTexture->m_uchrDimensions == 1 && m_blnProperties[ASW::GraphicsApi::PROPERTY_TEXTURE_1D - 1] == false) || (p_ptrTexture->m_uchrDimensions == 2 && m_blnProperties[ASW::GraphicsApi::PROPERTY_TEXTURE_2D - 1] == false) ) { return; } } m_ptrActiveTexture = p_ptrTexture; if ( m_ptrActiveTexture != NULL ) { DWORD dwdDimensions[] = {D3DTTFF_COUNT1, D3DTTFF_COUNT2, D3DTTFF_COUNT3}; DWORD dwdAddressModes[] = {D3DTADDRESS_WRAP, D3DTADDRESS_CLAMP}; DWORD dwdFilterModes[] = {D3DTEXF_POINT, D3DTEXF_LINEAR}; D3D_RUN(SetSamplerState(p_uintStage, D3DSAMP_ADDRESSU, dwdAddressModes[p_ptrTexture->m_enmAddressMode[0]])); D3D_RUN(SetSamplerState(p_uintStage, D3DSAMP_ADDRESSV, dwdAddressModes[p_ptrTexture->m_enmAddressMode[1]])); D3D_RUN(SetSamplerState(p_uintStage, D3DSAMP_MINFILTER, dwdFilterModes[p_ptrTexture->m_enmFilterMode[0]])); D3D_RUN(SetSamplerState(p_uintStage, D3DSAMP_MAGFILTER, dwdFilterModes[p_ptrTexture->m_enmFilterMode[1]])); D3D_RUN(SetTextureStageState(p_uintStage, D3DTSS_TEXTURETRANSFORMFLAGS, dwdDimensions[p_ptrTexture->m_uchrDimensions - 1])); D3D_RUN(SetTransform((D3DTRANSFORMSTATETYPE)(D3DTS_TEXTURE0 + p_uintStage), (const D3DMATRIX *)(&(p_ptrTexture->m_stuMatrix)))); D3D_RUN(SetTexture(p_uintStage, (IDirect3DBaseTexture9 *)(p_ptrTexture->m_ptrObject))); } else D3D_RUN(SetTexture(p_uintStage, NULL)); } void Direct3D:: Bind(const ASW::BufferIndex * p_ptrBuffer) { ASW_ASSERT(p_ptrBuffer == NULL || &(p_ptrBuffer->m_clsApi) == this, "Buffer is not loaded to this API object"); if ( m_ptrActiveBufferIndex != p_ptrBuffer ) { m_ptrActiveBufferIndex = p_ptrBuffer; if ( p_ptrBuffer != NULL ) D3D_RUN(SetIndices((IDirect3DIndexBuffer9 *)(p_ptrBuffer->m_ptrApiObject))); else D3D_RUN(SetIndices(NULL)); } } void Direct3D:: Bind(const ASW::BufferVertex * p_ptrBuffer) { ASW_ASSERT(p_ptrBuffer == NULL || &(p_ptrBuffer->m_clsApi) == this, "Buffer is not loaded to this API object"); m_ptrActiveBufferVertex = p_ptrBuffer; if ( m_ptrActiveBufferVertex == NULL ) return; else if ( m_ptrActiveBufferVertex->m_ptrApiData == NULL ) BufferInfo(*m_ptrActiveBufferVertex); D3D_RUN(SetVertexDeclaration((IDirect3DVertexDeclaration9 *)(m_ptrActiveBufferVertex->m_ptrApiData))); D3D_RUN(SetStreamSource(0, (IDirect3DVertexBuffer9 *)(m_ptrActiveBufferVertex->m_ptrApiObject), 0, m_ptrActiveBufferVertex->m_uchrElementSize)); } void Direct3D:: Bind(const ASW::Shader * p_ptrShader, const ASW::Type::Shader p_enmType) { ASW_ASSERT(p_ptrShader == NULL || p_ptrShader->m_blnLoaded, "Cannot bind an unloaded shader"); ASW_ASSERT(p_ptrShader != NULL || p_enmType == ASW::Type::SHADER_VERTEX || p_enmType == ASW::Type::SHADER_PIXEL, "Invalid parameter"); if ( p_ptrShader != NULL ) { HRESULT hndResult = cgD3D9BindProgram(p_ptrShader->m_clsProgram); D3D_RUN_CHECK(hndResult); } //else if ( p_enmType == ASW::Type::SHADER_VERTEX ) // HOW TO TURN OFF SHADER??? //else if ( p_enmType == ASW::Type::SHADER_PIXEL ) // HOW TO TURN OFF SHADER??? } void Direct3D:: Blend(const ASW::GraphicsApi::BlendType p_enmSourceType, const ASW::GraphicsApi::BlendType p_enmDestinationType) { ASW_ASSERT((int)(p_enmSourceType) > (int)(ASW::GraphicsApi::BLEND_UNKNOWN) && (int)(p_enmSourceType) <= (int)(ASW::GraphicsApi::BLEND_COUNT), "Invalid parameter"); ASW_ASSERT((int)(p_enmDestinationType) > (int)(ASW::GraphicsApi::BLEND_UNKNOWN) && (int)(p_enmDestinationType) <= (int)(ASW::GraphicsApi::BLEND_COUNT), "Invalid parameter"); D3DBLEND enmTypes[ASW::GraphicsApi::BLEND_COUNT] = { D3DBLEND_ZERO, D3DBLEND_ONE, D3DBLEND_SRCCOLOR, D3DBLEND_INVSRCCOLOR, D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA, D3DBLEND_DESTCOLOR, D3DBLEND_INVDESTCOLOR, D3DBLEND_DESTALPHA, D3DBLEND_INVDESTALPHA, D3DBLEND_SRCALPHASAT, }; m_enmBlend[0] = enmTypes[p_enmSourceType - 1]; m_enmBlend[1] = enmTypes[p_enmDestinationType - 1]; if ( m_blnProperties[ASW::GraphicsApi::PROPERTY_BLENDING - 1] ) { D3D_RUN(SetRenderState(D3DRS_SRCBLEND, m_enmBlend[0])); D3D_RUN(SetRenderState(D3DRS_DESTBLEND, m_enmBlend[1])); } } void Direct3D:: BufferClear(const unsigned int p_uintMask) { unsigned int uintMask = 0; if ( p_uintMask & ASW::GraphicsApi::BUFFER_COLOR ) uintMask |= D3DCLEAR_TARGET; if ( p_uintMask & ASW::GraphicsApi::BUFFER_DEPTH ) uintMask |= D3DCLEAR_ZBUFFER; if ( p_uintMask & ASW::GraphicsApi::BUFFER_STENCIL ) uintMask |= D3DCLEAR_STENCIL; D3D_RUN(Clear(0, NULL, uintMask, m_dwdClearColor, m_fltClearDepth, 0)); } void Direct3D:: BufferEnable(const unsigned int p_uintMask, const bool p_blnEnable) { if ( (p_uintMask & ASW::GraphicsApi::BUFFER_COLOR) != 0 ) D3D_RUN(SetRenderState(D3DRS_COLORWRITEENABLE , ( p_blnEnable ) ? 0xf : 0)); if ( (p_uintMask & ASW::GraphicsApi::BUFFER_DEPTH) != 0 ) D3D_RUN(SetRenderState(D3DRS_ZWRITEENABLE , ( p_blnEnable ) ? TRUE : FALSE)); if ( (p_uintMask & ASW::GraphicsApi::BUFFER_STENCIL) != 0 ) D3D_RUN(SetRenderState(D3DRS_STENCILWRITEMASK , ( p_blnEnable ) ? ~0 : 0)); } void Direct3D:: BufferInfo(const ASW::BufferVertex & p_clsBuffer) { ASW_ASSERT(&(p_clsBuffer.m_clsApi) == this, "Buffer is not loaded to this API object"); ASW::BufferVertex * ptrBuffer = (ASW::BufferVertex *)(&p_clsBuffer); if ( ptrBuffer->m_ptrApiData ) { ((IDirect3DVertexDeclaration9 *)(ptrBuffer->m_ptrApiData))->Release(); ptrBuffer->m_ptrApiData = NULL; } BYTE uchrUsage[] = { D3DDECLUSAGE_POSITION, D3DDECLUSAGE_NORMAL, D3DDECLUSAGE_TEXCOORD, D3DDECLUSAGE_BLENDWEIGHT, D3DDECLUSAGE_BLENDINDICES, }; unsigned char uchrIndex = 0; D3DVERTEXELEMENT9 stuInfo[sizeof(unsigned long) * 8]; for (unsigned int i=0; i 0 && p_clsBuffer.m_clsElements[i].m_uchrElements <= 4, "Invalid number of vertex elements"); stuInfo[uchrIndex].Type = (D3DDECLTYPE)(D3DDECLTYPE_FLOAT1 + (p_clsBuffer.m_clsElements[i].m_uchrElements - 1)); } else if ( p_clsBuffer.m_clsElements[i].m_enmTypeData == UTIL::UNSIGNED_BYTE ) { ASW_ASSERT(p_clsBuffer.m_clsElements[i].m_uchrElements == 4, "Invalid number of vertex elements"); stuInfo[uchrIndex].Type = D3DDECLTYPE_UBYTE4; } else if ( p_clsBuffer.m_clsElements[i].m_enmTypeData == UTIL::SIGNED_SHORT ) { ASW_ASSERT(p_clsBuffer.m_clsElements[i].m_uchrElements == 2 || p_clsBuffer.m_clsElements[i].m_uchrElements == 4, "Invalid number of vertex elements"); stuInfo[uchrIndex].Type = ( p_clsBuffer.m_clsElements[i].m_uchrElements == 2 ) ? D3DDECLTYPE_SHORT2 : D3DDECLTYPE_SHORT4; } else ASW_ASSERT(false, "Invalid data type"); uchrIndex++; } } D3DVERTEXELEMENT9 stuTemp = D3DDECL_END(); stuInfo[uchrIndex] = stuTemp; D3D_RUN(CreateVertexDeclaration(stuInfo, (IDirect3DVertexDeclaration9 **)(&(ptrBuffer->m_ptrApiData)))); } bool Direct3D:: CheckEnable(const ASW::GraphicsApi::PropertyType p_enmProperty) { switch ( p_enmProperty ) { case ASW::GraphicsApi::PROPERTY_TWO_SIDED_STENCIL: return ( (m_stuCaps.StencilCaps & D3DSTENCILCAPS_TWOSIDED) != 0 ); default: return true; } } void Direct3D:: ClearColor(const unsigned char p_uchrRed, const unsigned char p_uchrGreen, const unsigned char p_uchrBlue, const unsigned char p_uchrAlpha) { m_dwdClearColor = D3DCOLOR_RGBA(p_uchrRed, p_uchrGreen, p_uchrBlue, p_uchrAlpha); } void Direct3D:: ClearDepth(const float p_fltDepth) { m_fltClearDepth = p_fltDepth; } void Direct3D:: CullMode(const ASW::GraphicsApi::CullType p_enmType) { ASW_ASSERT((int)(p_enmType) > (int)(ASW::GraphicsApi::CULL_UNKNOWN) && (int)(p_enmType) <= (int)(ASW::GraphicsApi::CULL_COUNT), "Invalid parameter"); D3DCULL enmTypes[ASW::GraphicsApi::CULL_COUNT] = { D3DCULL_NONE, D3DCULL_CW, D3DCULL_CCW, }; D3D_RUN(SetRenderState(D3DRS_CULLMODE, enmTypes[p_enmType - 1])); } void Direct3D:: Draw(const ASW::Type::Primitive p_enmType, const ASW::BufferVertex::Index & p_clsIndex) { ASW_ASSERT(m_ptrActiveBufferVertex != NULL, "No vertex buffer bound"); ASW_ASSERT((int)(p_enmType) > (int)(ASW::Type::PRIMITIVE_UNKNOWN) && (int)(p_enmType) <= (int)(ASW::Type::PRIMITIVE_COUNT), "Invalid primitive type"); unsigned int uintPrimitives; switch ( p_enmType ) { case ASW::Type::PRIMITIVE_TRIANGLES: ASW_ASSERT(((p_clsIndex.m_stuIndices[1] - p_clsIndex.m_stuIndices[0]) % 3) == 0, "Incorrect number of vertices for PRIMITIVE_TRIANGLES"); uintPrimitives = (p_clsIndex.m_stuIndices[1] - p_clsIndex.m_stuIndices[0]) / 3; break; case ASW::Type::PRIMITIVE_LINES: ASW_ASSERT(((p_clsIndex.m_stuIndices[1] - p_clsIndex.m_stuIndices[0]) % 2) == 0, "Incorrect number of vertices for PRIMITIVE_LINES"); uintPrimitives = (p_clsIndex.m_stuIndices[1] - p_clsIndex.m_stuIndices[0]) / 2; break; default: uintPrimitives = (p_clsIndex.m_stuIndices[1] - p_clsIndex.m_stuIndices[0]) - 1; break; } D3D_RUN(DrawPrimitive(Direct3D::m_enmPrimitiveTypes[p_enmType - 1], p_clsIndex.m_stuIndices[0], uintPrimitives)); } void Direct3D:: Draw(const ASW::Type::Primitive p_enmType, const ASW::BufferIndex::Index & p_clsIndex) { ASW_ASSERT(m_ptrActiveBufferVertex != NULL && m_ptrActiveBufferIndex != NULL, "No vertex and/or index buffer bound"); ASW_ASSERT((int)(p_enmType) > (int)(ASW::Type::PRIMITIVE_UNKNOWN) && (int)(p_enmType) <= (int)(ASW::Type::PRIMITIVE_COUNT), "Invalid primitive type"); unsigned int uintPrimitives; unsigned int uintVertices = p_clsIndex.m_stuIndices[1] - p_clsIndex.m_stuIndices[0]; switch ( p_enmType ) { case ASW::Type::PRIMITIVE_TRIANGLES: ASW_ASSERT((uintVertices % 3) == 0, "Incorrect number of vertices for PRIMITIVE_TRIANGLES"); uintPrimitives = uintVertices / (3 * m_ptrActiveBufferVertex->m_uchrElementSize); break; case ASW::Type::PRIMITIVE_LINES: ASW_ASSERT((uintVertices % 2) == 0, "Incorrect number of vertices for PRIMITIVE_TRIANGLES"); uintPrimitives = uintVertices / (2 * m_ptrActiveBufferVertex->m_uchrElementSize); break; default: uintPrimitives = (uintVertices / m_ptrActiveBufferVertex->m_uchrElementSize) - 1; break; } D3D_RUN(DrawIndexedPrimitive(Direct3D::m_enmPrimitiveTypes[p_enmType - 1], 0, p_clsIndex.m_stuIndicesRange[0], uintVertices, p_clsIndex.m_stuIndices[0], uintPrimitives)); } void Direct3D:: DrawIndices(const ASW::Type::Primitive p_enmType, const ASW::CompositeIndex ** p_ptrIndices, const unsigned int p_uintAmount) { for (unsigned int i=0; i (int)(ASW::GraphicsApi::PROPERTY_UNKNOWN) && (int)(p_enmProperty) <= (int)(ASW::GraphicsApi::PROPERTY_COUNT), "Invalid parameter"); m_blnProperties[p_enmProperty - 1] = p_blnEnable; switch ( p_enmProperty ) { case ASW::GraphicsApi::PROPERTY_TEXTURE_1D: if ( p_blnEnable == false && m_ptrActiveTexture != NULL && m_ptrActiveTexture->m_uchrDimensions == 1 ) Bind((ASW::Texture *)(NULL), 0); break; case ASW::GraphicsApi::PROPERTY_TEXTURE_2D: if ( p_blnEnable == false && m_ptrActiveTexture != NULL && m_ptrActiveTexture->m_uchrDimensions == 2 ) Bind((ASW::Texture *)(NULL), 0); break; case ASW::GraphicsApi::PROPERTY_TEXTURING: D3D_RUN(SetTextureStageState(0, D3DTSS_COLOROP, ( p_blnEnable ) ? D3DTOP_MODULATE : D3DTOP_DISABLE)); break; case ASW::GraphicsApi::PROPERTY_LIGHTING: D3D_RUN(SetRenderState(D3DRS_LIGHTING, ( p_blnEnable ) ? TRUE : FALSE)); break; case ASW::GraphicsApi::PROPERTY_BLENDING: D3D_RUN(SetRenderState(D3DRS_ALPHABLENDENABLE, ( p_blnEnable ) ? TRUE : FALSE)); break; case ASW::GraphicsApi::PROPERTY_TEST_DEPTH: D3D_RUN(SetRenderState(D3DRS_ZENABLE, ( p_blnEnable ) ? D3DZB_TRUE : D3DZB_FALSE)); break; case ASW::GraphicsApi::PROPERTY_TEST_STENCIL: D3D_RUN(SetRenderState(D3DRS_STENCILENABLE, ( p_blnEnable ) ? TRUE : FALSE)); break; case ASW::GraphicsApi::PROPERTY_TWO_SIDED_STENCIL: D3D_RUN(SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, ( p_blnEnable ) ? TRUE : FALSE)); break; default: break; } } void Direct3D:: EnableLight(const unsigned int p_uintIndex, const bool p_blnEnable) { ASW_ASSERT(p_uintIndex < m_uintMaxLights, "Index exceeds maximum number of lights"); D3D_RUN(LightEnable(p_uintIndex, ( p_blnEnable ) ? TRUE : FALSE)); } void Direct3D:: FillMode(const ASW::GraphicsApi::FillType p_enmType) { ASW_ASSERT((int)(p_enmType) > (int)(ASW::GraphicsApi::FILL_UNKNOWN) && (int)(p_enmType) <= (int)(ASW::GraphicsApi::FILL_COUNT), "Invalid parameter"); D3DFILLMODE enmTypes[] = { D3DFILL_POINT, D3DFILL_WIREFRAME, D3DFILL_SOLID }; D3D_RUN(SetRenderState(D3DRS_FILLMODE, enmTypes[p_enmType - 1])); } void Direct3D:: GetDeviceInfo(std::string & p_clsDevice, std::string & p_clsApi) { D3DADAPTER_IDENTIFIER9 stuData; D3D_CHECK(m_ptrDirect3D->GetAdapterIdentifier(D3DADAPTER_DEFAULT, 0, &stuData)); p_clsDevice = stuData.Description; p_clsApi = "Direct3D9"; } D3DFORMAT Direct3D:: FindFormat(const ASW::Window::Settings & p_stuSettings) { D3DDISPLAYMODE stuMode; D3DFORMAT enmFormats[] = { D3DFMT_X8R8G8B8, D3DFMT_A8R8G8B8, D3DFMT_A2R10G10B10, D3DFMT_A1R5G5B5, D3DFMT_X1R5G5B5, D3DFMT_R5G6B5, }; for (unsigned int i=0; i<6; i++) { unsigned int uintDisplayModes = m_ptrDirect3D->GetAdapterModeCount(D3DADAPTER_DEFAULT, enmFormats[i]); for (unsigned int j=0; jEnumAdapterModes(D3DADAPTER_DEFAULT, enmFormats[i], j, &stuMode) == D3D_OK ) { if ( stuMode.Width == p_stuSettings.m_uintWidth && stuMode.Height == p_stuSettings.m_uintHeight && stuMode.RefreshRate == p_stuSettings.m_uintFrequency ) { HRESULT enmResult = m_ptrDirect3D->CheckDeviceType(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, enmFormats[i], enmFormats[i], ( p_stuSettings.m_blnFullScreen ) ? FALSE : TRUE); if ( SUCCEEDED(enmResult) ) return stuMode.Format; else if ( enmResult != D3DERR_NOTAVAILABLE ) return D3DFMT_UNKNOWN; } } } } return D3DFMT_UNKNOWN; } ASW::Colorf Direct3D:: GetAmbience() { DWORD dwdTemp; ASW::Colorf stuReturn; D3D_RUN(GetRenderState(D3DRS_AMBIENT, &dwdTemp)); stuReturn[0] = (float)((dwdTemp >> 16) & 0xff) / 255.0f; stuReturn[1] = (float)((dwdTemp >> 8) & 0xff) / 255.0f; stuReturn[2] = (float)(dwdTemp & 0xff) / 255.0f; stuReturn[3] = (float)((dwdTemp >> 24) & 0xff) / 255.0f; return stuReturn; } ASW::Point4i Direct3D:: GetViewport(ASW::Point2f * p_ptrDepthRange) { ASW::Point4i stuReturn; D3DVIEWPORT9 stuViewport; D3D_RUN(GetViewport(&stuViewport)); stuReturn[0] = (int)(stuViewport.X); stuReturn[1] = (int)(stuViewport.Y); stuReturn[2] = (int)(stuViewport.Width); stuReturn[3] = (int)(stuViewport.Height); if ( p_ptrDepthRange ) { p_ptrDepthRange->m_fltX = stuViewport.MinZ; p_ptrDepthRange->m_fltY = stuViewport.MaxZ; } return stuReturn; } bool Direct3D:: Load(ASW::Font & p_stuFont) { ASW_ASSERT(p_stuFont.m_blnLoaded == false, "Font is already loaded"); int intWeight[] = { FW_DONTCARE, FW_THIN, FW_EXTRALIGHT, FW_LIGHT, FW_NORMAL, FW_MEDIUM, FW_SEMIBOLD, FW_BOLD, FW_EXTRABOLD, FW_HEAVY, }; DWORD dwdQuality[] = { DEFAULT_QUALITY, DRAFT_QUALITY, ANTIALIASED_QUALITY, }; p_stuFont.m_blnLoaded = SUCCEEDED(D3DXCreateFont(m_ptrDevice, p_stuFont.m_intSize, // Height 0, // Width intWeight[p_stuFont.m_uchrWeight], // Weight 0, // MipLevels ( p_stuFont.m_blnItalic ) ? TRUE : FALSE, // Italic ANSI_CHARSET, // CharSet OUT_TT_PRECIS, // OutputPrecision dwdQuality[p_stuFont.m_uchrQuality], // Quality FF_DONTCARE | DEFAULT_PITCH, // PitchAndFamily p_stuFont.m_ptrFace, // pFacename (LPD3DXFONT *)(&(p_stuFont.m_ptrData[0])))); return p_stuFont.m_blnLoaded; } void Direct3D:: Load(ASW::Buffer & p_clsBuffer) { void * ptrData; if ( p_clsBuffer.m_blnIsIndexBuffer ) { IDirect3DIndexBuffer9 * ptrBuffer; ASW_ASSERT(p_clsBuffer.m_uchrElementSize == sizeof(unsigned short) || p_clsBuffer.m_uchrElementSize == sizeof(unsigned long), "Direct3D only supports indices of 16 or 32 bits"); D3D_RUN(CreateIndexBuffer(p_clsBuffer.m_uintElements * p_clsBuffer.m_uchrElementSize, ( p_clsBuffer.m_enmWriteHint == ASW::Type::WRITE_DYNAMIC ) ? D3DUSAGE_DYNAMIC : D3DUSAGE_WRITEONLY, ( p_clsBuffer.m_uchrElementSize == sizeof(unsigned short) ) ? D3DFMT_INDEX16 : D3DFMT_INDEX32, ( p_clsBuffer.m_enmWriteHint == ASW::Type::WRITE_STATIC ) ? D3DPOOL_DEFAULT : D3DPOOL_SYSTEMMEM, &ptrBuffer, NULL)); p_clsBuffer.m_ptrApiObject = ptrBuffer; HRESULT hndResult = ptrBuffer->Lock(0, 0, &ptrData, ( p_clsBuffer.m_enmWriteHint == ASW::Type::WRITE_DYNAMIC ) ? D3DLOCK_DISCARD : 0); D3D_RUN_CHECK(hndResult); memcpy(ptrData, p_clsBuffer.m_ptrData, p_clsBuffer.m_uintElements * p_clsBuffer.m_uchrElementSize); hndResult = ptrBuffer->Unlock(); D3D_RUN_CHECK(hndResult); } else { IDirect3DVertexBuffer9 * ptrBuffer; D3D_RUN(CreateVertexBuffer(p_clsBuffer.m_uintElements * p_clsBuffer.m_uchrElementSize, ( p_clsBuffer.m_enmWriteHint == ASW::Type::WRITE_DYNAMIC ) ? D3DUSAGE_DYNAMIC : D3DUSAGE_WRITEONLY, 0,//D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1 | D3DFVF_DIFFUSE, ( p_clsBuffer.m_enmWriteHint == ASW::Type::WRITE_STATIC ) ? D3DPOOL_DEFAULT : D3DPOOL_SYSTEMMEM, &ptrBuffer, NULL)); p_clsBuffer.m_ptrApiObject = ptrBuffer; HRESULT hndResult = ptrBuffer->Lock(0, 0, &ptrData, ( p_clsBuffer.m_enmWriteHint == ASW::Type::WRITE_DYNAMIC ) ? D3DLOCK_DISCARD : 0); D3D_RUN_CHECK(hndResult); memcpy(ptrData, p_clsBuffer.m_ptrData, p_clsBuffer.m_uintElements * p_clsBuffer.m_uchrElementSize); hndResult = ptrBuffer->Unlock(); D3D_RUN_CHECK(hndResult); } free(p_clsBuffer.m_ptrData); p_clsBuffer.m_ptrData = NULL; } bool Direct3D:: Load(ASW::Shader & p_clsShader, const char * p_ptrFileName, const char * p_ptrEntryPoint) { if ( ASW::GraphicsApi::Load(p_clsShader, p_ptrFileName, p_ptrEntryPoint) == false ) { return false; } CG_RUN(cgD3D9LoadProgram(p_clsShader.m_clsProgram, CG_FALSE, 0)); return true; } bool Direct3D:: Load(ASW::Texture & p_clsTexture) { ASW_ASSERT(p_clsTexture.m_blnLoaded == false, "Texture has already been loaded"); if ( FAILED(D3DXCreateTextureFromFile(m_ptrDevice, p_clsTexture.m_ptrFileName, (LPDIRECT3DTEXTURE9 *)(&(p_clsTexture.m_ptrObject)))) ) { return false; } D3DSURFACE_DESC stuDesc; if ( FAILED(((LPDIRECT3DTEXTURE9)(p_clsTexture.m_ptrObject))->GetLevelDesc(0, &stuDesc)) ) { ((LPDIRECT3DTEXTURE9)(p_clsTexture.m_ptrObject))->Release(); p_clsTexture.m_ptrObject = NULL; return false; } p_clsTexture.m_uchrDimensions = ( stuDesc.Width == 1 || stuDesc.Height == 1 ) ? 1 : 2; p_clsTexture.SetMatrix(ASW::Type::DIRECTION_RIGHT, ASW::Type::DIRECTION_DOWN); p_clsTexture.m_blnLoaded = true; return true; } void * Direct3D:: Lock(ASW::Buffer & p_clsBuffer, const unsigned int p_uintOffset, const unsigned int p_uintSize, const ASW::Type::HintAccess p_enmHint) { ASW_ASSERT(&(p_clsBuffer.m_clsApi) == this, "Buffer is not loaded to this API object"); ASW_ASSERT((int)(p_enmHint) > (int)(ASW::Type::ACCESS_UNKNOWN) && (int)(p_enmHint) <= (int)(ASW::Type::ACCESS_COUNT), "Invalid parameter"); unsigned int uintLockOptions[] = { D3DLOCK_READONLY | D3DLOCK_NOOVERWRITE, 0, D3DLOCK_DISCARD, 0 }; void * ptrReturn = NULL; if ( p_clsBuffer.m_blnIsIndexBuffer ) { IDirect3DIndexBuffer9 * ptrBuffer = (IDirect3DIndexBuffer9 *)(p_clsBuffer.m_ptrApiObject); HRESULT hndResult = ptrBuffer->Lock(p_uintOffset, p_uintSize, &ptrReturn, uintLockOptions[p_enmHint - 1]); D3D_RUN_CHECK(hndResult); } else { IDirect3DVertexBuffer9 * ptrBuffer = (IDirect3DVertexBuffer9 *)(p_clsBuffer.m_ptrApiObject); HRESULT hndResult = ptrBuffer->Lock(p_uintOffset, p_uintSize, &ptrReturn, uintLockOptions[p_enmHint - 1]); D3D_RUN_CHECK(hndResult); } return ptrReturn; } UTIL::D3::Matrix Direct3D:: MatrixBuild(const unsigned int p_uintWidth, const unsigned int p_uintHeight, const float p_fltPlaneNear, const float p_fltPlaneFar, const float p_fltFov) { UTIL::D3::Matrix stuResult; if ( p_fltFov > 0.0f ) { D3DXMatrixPerspectiveFovRH((D3DXMATRIX *)(&stuResult), p_fltFov, (float)(p_uintWidth) / (float)(( p_uintHeight ) ? (p_uintHeight) : 1), p_fltPlaneNear, p_fltPlaneFar); } else { D3DXMatrixOrthoRH((D3DXMATRIX *)(&stuResult), (float)(p_uintWidth), (float)(( p_uintHeight ) ? (p_uintHeight) : 1), p_fltPlaneNear, p_fltPlaneFar); } return stuResult; } UTIL::D3::Matrix Direct3D:: MatrixGet(const ASW::Type::Matrix p_enmType) { ASW_ASSERT((int)(p_enmType) > (int)(ASW::Type::MATRIX_UNKNOWN) && (int)(p_enmType) <= (int)(ASW::Type::MATRIX_COUNT), "Invalid parameter"); UTIL::D3::Matrix stuMatrix; D3D_RUN(GetTransform(m_enmMatrixTypes[p_enmType - 1], (D3DMATRIX *)(&stuMatrix))); return stuMatrix; } void Direct3D:: MatrixSet(const ASW::Type::Matrix p_enmType, const UTIL::D3::Matrix & p_stuMatrix) { ASW_ASSERT((int)(p_enmType) > (int)(ASW::Type::MATRIX_UNKNOWN) && (int)(p_enmType) <= (int)(ASW::Type::MATRIX_COUNT), "Invalid parameter"); UTIL::D3::Matrix stuMatrix; D3D_RUN(SetTransform(m_enmMatrixTypes[p_enmType - 1], (D3DMATRIX *)(&p_stuMatrix))); } /* void Direct3D:: MatrixSet(const unsigned int p_uintWidth, const unsigned int p_uintHeight) { D3DXMATRIX stuMatrix; D3D_RUN(SetTransform(D3DTS_PROJECTION, D3DXMatrixOrthoRH(&stuMatrix, (float)(p_uintWidth), (float)(p_uintHeight), -1.0f, 1.0f))); } void Direct3D:: MatrixSet(const unsigned int p_uintWidth, const unsigned int p_uintHeight, const float p_fltPlaneNear, const float p_fltPlaneFar) { D3DXMATRIX stuMatrix; D3D_RUN(SetTransform(D3DTS_PROJECTION, D3DXMatrixPerspectiveFovRH(&stuMatrix, 45.0f, (float)(p_uintWidth) / (float)(( p_uintHeight ) ? (p_uintHeight) : 1), p_fltPlaneNear, p_fltPlaneFar))); } */ void Direct3D:: PrivateDestroy() { CG_RUN(cgD3D9SetDevice(NULL)); if ( m_ptrDevice ) { m_ptrDevice->Release(); m_ptrDevice = NULL; } if ( m_ptrDirect3D ) { m_ptrDirect3D->Release(); m_ptrDirect3D = NULL; } } void Direct3D:: Print(const ASW::GraphicsApi::DrawTextInfo & p_stuInfo) { ASW_ASSERT(p_stuInfo.m_enmHorizontal == ASW::Type::ALIGN_LEFT || p_stuInfo.m_enmHorizontal == ASW::Type::ALIGN_MIDDLE || p_stuInfo.m_enmHorizontal == ASW::Type::ALIGN_RIGHT, "Invalid horizontal alignment"); ASW_ASSERT(p_stuInfo.m_enmVertical == ASW::Type::ALIGN_TOP || p_stuInfo.m_enmVertical == ASW::Type::ALIGN_MIDDLE || p_stuInfo.m_enmVertical == ASW::Type::ALIGN_BOTTOM, "Invalid vertical alignment"); // // Horizontal alignment // DWORD dwdFormat = 0; if ( p_stuInfo.m_enmHorizontal == ASW::Type::ALIGN_LEFT ) dwdFormat |= DT_LEFT; else if ( p_stuInfo.m_enmHorizontal == ASW::Type::ALIGN_RIGHT ) dwdFormat |= DT_RIGHT; else dwdFormat |= DT_CENTER; // // Vertical alignment // if ( p_stuInfo.m_enmVertical == ASW::Type::ALIGN_TOP ) dwdFormat |= DT_TOP; else if ( p_stuInfo.m_enmVertical == ASW::Type::ALIGN_BOTTOM ) dwdFormat |= DT_BOTTOM; else dwdFormat |= DT_VCENTER; RECT stuRect; stuRect.left = p_stuInfo.m_stuBox[0]; stuRect.right = p_stuInfo.m_stuBox[1]; stuRect.top = p_stuInfo.m_stuBox[2]; stuRect.bottom = p_stuInfo.m_stuBox[3]; LPD3DXFONT ptrFont = (LPD3DXFONT)(p_stuInfo.m_ptrFont->m_ptrData[0]); INT intResult = ptrFont->DrawText(NULL, p_stuInfo.m_ptrText, -1, &stuRect, dwdFormat, COLORF(p_stuInfo.m_stuColor[0], p_stuInfo.m_stuColor[1], p_stuInfo.m_stuColor[2], p_stuInfo.m_stuColor[3])); ASW_ASSERT(intResult != 0, "DrawText failed"); } void Direct3D:: Resize(const unsigned int p_uintWidth, const unsigned int p_uintHeight) { D3DVIEWPORT9 stuViewport; stuViewport.X = 0; stuViewport.Y = 0; stuViewport.Width = p_uintWidth; stuViewport.Height = p_uintHeight; stuViewport.MinZ = 0.0f; stuViewport.MaxZ = 1.0f; D3D_RUN(SetViewport(&stuViewport)); } void Direct3D:: SetAmbience(const ASW::Colorf & p_stuAmbience) { DWORD dwdAmbient = D3DCOLOR_RGBA((unsigned char)(UTIL::Round(p_stuAmbience[0] * 255.0f)), (unsigned char)(UTIL::Round(p_stuAmbience[1] * 255.0f)), (unsigned char)(UTIL::Round(p_stuAmbience[2] * 255.0f)), (unsigned char)(UTIL::Round(p_stuAmbience[3] * 255.0f))); D3D_RUN(SetRenderState(D3DRS_AMBIENT, dwdAmbient)); } void Direct3D:: SetDepthTest(const ASW::GraphicsApi::Test p_enmTest) { ASW_ASSERT((int)(p_enmTest) > (int)(ASW::GraphicsApi::TEST_UNKNOWN) && (int)(p_enmTest) <= (int)(ASW::GraphicsApi::TEST_COUNT), "Invalid parameter"); D3D_RUN(SetRenderState(D3DRS_ZFUNC, Direct3D::m_enmTests[p_enmTest - 1])); } void Direct3D:: SetLight(const unsigned int p_uintIndex, const ASW::Instance::Light & p_clsLight) { ASW_ASSERT(p_uintIndex < m_uintMaxLights, "Index exceeds maximum number of lights"); D3DLIGHTTYPE enmTypes[] = { D3DLIGHT_DIRECTIONAL, D3DLIGHT_POINT, D3DLIGHT_SPOT }; ASW::Point3f stuRotation; ASW::Point3f stuTranslation; p_clsLight.GetTransform(stuRotation, stuTranslation, false); ASW::Parameters::Light stuParams = p_clsLight.GetParams(); ASW_ASSERT(stuParams.m_enmType == ASW::Type::LIGHT_DIRECTIONAL || stuParams.m_enmType == ASW::Type::LIGHT_POINT || stuParams.m_enmType == ASW::Type::LIGHT_SPOT, "Invalid light type"); D3DLIGHT9 stuLight; stuLight.Type = enmTypes[stuParams.m_enmType - 1]; memcpy(&(stuLight.Ambient), &(stuParams.m_stuAmbient), 4 * sizeof(float)); memcpy(&(stuLight.Diffuse), &(stuParams.m_stuDiffuse), 4 * sizeof(float)); memcpy(&(stuLight.Specular), &(stuParams.m_stuSpecular), 4 * sizeof(float)); memcpy(&(stuLight.Position), &stuTranslation, 3 * sizeof(float)); memcpy(&(stuLight.Direction), &stuRotation, 3 * sizeof(float)); stuLight.Range = stuParams.m_fltRange; stuLight.Phi = stuParams.m_fltAngle * 2.0f; stuLight.Falloff = 0.0f; stuLight.Theta = 0.0f; stuLight.Attenuation0 = stuParams.m_stuAttenuation[0]; stuLight.Attenuation1 = stuParams.m_stuAttenuation[1]; stuLight.Attenuation2 = stuParams.m_stuAttenuation[2]; D3D_RUN(SetLight(p_uintIndex, &stuLight)); } void Direct3D:: SetScissorRectangle(const int p_intLeft, const int p_intBottom, const unsigned int p_uintWidth, const unsigned int p_uintHeight) { RECT stuRect; stuRect.left = (LONG)(p_intLeft); stuRect.bottom = (LONG)(p_intBottom); stuRect.right = (LONG)(stuRect.left + p_uintWidth); stuRect.top = (LONG)(stuRect.bottom + p_uintHeight); D3D_RUN(SetScissorRect(&stuRect)); } void Direct3D:: SetStencilTest(const ASW::GraphicsApi::Test p_enmTest, const int p_intReference, const unsigned int p_uintMask, const bool p_blnFront) { ASW_ASSERT((int)(p_enmTest) > (int)(ASW::GraphicsApi::TEST_UNKNOWN) && (int)(p_enmTest) <= (int)(ASW::GraphicsApi::TEST_COUNT), "Invalid parameter"); if ( p_blnFront ) { D3D_RUN(SetRenderState(D3DRS_STENCILFUNC, Direct3D::m_enmTests[p_enmTest - 1])); D3D_RUN(SetRenderState(D3DRS_STENCILREF, (DWORD)(p_intReference))); D3D_RUN(SetRenderState(D3DRS_STENCILMASK, p_uintMask)); } else D3D_RUN(SetRenderState(D3DRS_CCW_STENCILFUNC, Direct3D::m_enmTests[p_enmTest - 1])); } void Direct3D:: SetStencilWriteMask(const unsigned int p_uintMask, const bool p_blnFront) { ASW_ASSERT(p_blnFront, "Direct3D does not support a stencil write mask for back-facing triangles"); D3D_RUN(SetRenderState(D3DRS_STENCILWRITEMASK, p_uintMask)); } void Direct3D:: SetStencilOp(const ASW::GraphicsApi::StencilOp p_enmTestFail, const ASW::GraphicsApi::StencilOp p_enmTestPassDepthFail, const ASW::GraphicsApi::StencilOp p_enmTestPassDepthPass, const bool p_blnFront) { ASW_ASSERT((int)(p_enmTestFail) > (int)(ASW::GraphicsApi::STENCILOP_UNKNOWN) && (int)(p_enmTestFail) <= (int)(ASW::GraphicsApi::STENCILOP_COUNT), "Invalid parameter"); ASW_ASSERT((int)(p_enmTestPassDepthFail) > (int)(ASW::GraphicsApi::STENCILOP_UNKNOWN) && (int)(p_enmTestPassDepthFail) <= (int)(ASW::GraphicsApi::STENCILOP_COUNT), "Invalid parameter"); ASW_ASSERT((int)(p_enmTestPassDepthPass) > (int)(ASW::GraphicsApi::STENCILOP_UNKNOWN) && (int)(p_enmTestPassDepthPass) <= (int)(ASW::GraphicsApi::STENCILOP_COUNT), "Invalid parameter"); if ( p_blnFront ) { D3D_RUN(SetRenderState(D3DRS_STENCILFAIL, Direct3D::m_enmStencilOps[p_enmTestFail - 1])); D3D_RUN(SetRenderState(D3DRS_STENCILZFAIL, Direct3D::m_enmStencilOps[p_enmTestPassDepthFail - 1])); D3D_RUN(SetRenderState(D3DRS_STENCILPASS, Direct3D::m_enmStencilOps[p_enmTestPassDepthPass - 1])); } else { D3D_RUN(SetRenderState(D3DRS_CCW_STENCILFAIL, Direct3D::m_enmStencilOps[p_enmTestFail - 1])); D3D_RUN(SetRenderState(D3DRS_CCW_STENCILZFAIL, Direct3D::m_enmStencilOps[p_enmTestPassDepthFail - 1])); D3D_RUN(SetRenderState(D3DRS_CCW_STENCILPASS, Direct3D::m_enmStencilOps[p_enmTestPassDepthPass - 1])); } } void Direct3D:: SetStencilParams(const unsigned int p_uintWriteMask, const ASW::GraphicsApi::Test p_enmTest, const ASW::GraphicsApi::StencilOp p_enmTestFail, const ASW::GraphicsApi::StencilOp p_enmTestPassDepthFail, const ASW::GraphicsApi::StencilOp p_enmTestPassDepthPass, const int p_intReference, const unsigned int p_uintMask, const bool p_blnFront) { ASW_ASSERT((int)(p_enmTest) > (int)(ASW::GraphicsApi::TEST_UNKNOWN) && (int)(p_enmTest) <= (int)(ASW::GraphicsApi::TEST_COUNT), "Invalid parameter"); ASW_ASSERT((int)(p_enmTestFail) > (int)(ASW::GraphicsApi::STENCILOP_UNKNOWN) && (int)(p_enmTestFail) <= (int)(ASW::GraphicsApi::STENCILOP_COUNT), "Invalid parameter"); ASW_ASSERT((int)(p_enmTestPassDepthFail) > (int)(ASW::GraphicsApi::STENCILOP_UNKNOWN) && (int)(p_enmTestPassDepthFail) <= (int)(ASW::GraphicsApi::STENCILOP_COUNT), "Invalid parameter"); ASW_ASSERT((int)(p_enmTestPassDepthPass) > (int)(ASW::GraphicsApi::STENCILOP_UNKNOWN) && (int)(p_enmTestPassDepthPass) <= (int)(ASW::GraphicsApi::STENCILOP_COUNT), "Invalid parameter"); if ( p_blnFront ) { D3D_RUN(SetRenderState(D3DRS_STENCILFUNC, Direct3D::m_enmTests[p_enmTest - 1])); D3D_RUN(SetRenderState(D3DRS_STENCILFAIL, Direct3D::m_enmStencilOps[p_enmTestFail - 1])); D3D_RUN(SetRenderState(D3DRS_STENCILZFAIL, Direct3D::m_enmStencilOps[p_enmTestPassDepthFail - 1])); D3D_RUN(SetRenderState(D3DRS_STENCILPASS, Direct3D::m_enmStencilOps[p_enmTestPassDepthPass - 1])); D3D_RUN(SetRenderState(D3DRS_STENCILREF, (DWORD)(p_intReference))); D3D_RUN(SetRenderState(D3DRS_STENCILMASK, p_uintWriteMask)); D3D_RUN(SetRenderState(D3DRS_STENCILWRITEMASK, p_uintMask)); } else { D3D_RUN(SetRenderState(D3DRS_CCW_STENCILFUNC, Direct3D::m_enmTests[p_enmTest - 1])); D3D_RUN(SetRenderState(D3DRS_CCW_STENCILFAIL, Direct3D::m_enmStencilOps[p_enmTestFail - 1])); D3D_RUN(SetRenderState(D3DRS_CCW_STENCILZFAIL, Direct3D::m_enmStencilOps[p_enmTestPassDepthFail - 1])); D3D_RUN(SetRenderState(D3DRS_CCW_STENCILPASS, Direct3D::m_enmStencilOps[p_enmTestPassDepthPass - 1])); } } ASW::Point2f Direct3D:: Size(const ASW::Font & p_stuFont, const char * p_ptrString) { ASW_ASSERT(p_stuFont.m_blnLoaded, "Font is not loaded"); RECT stuRect = {0, 0, 0, 0}; LPD3DXFONT ptrFont = (LPD3DXFONT)(p_stuFont.m_ptrData[0]); int intReturn = ptrFont->DrawText(NULL, p_ptrString, -1, &stuRect, DT_CALCRECT, 0); ASW_ASSERT(intReturn != 0, "DrawText failed"); return ASW::Point2f((float)(stuRect.right - stuRect.left), (float)(intReturn)); } void Direct3D:: Unload(ASW::Font & p_stuFont) { ASW_ASSERT(p_stuFont.m_blnLoaded && p_stuFont.m_ptrData[0] != NULL, "Font is not loaded"); ((LPD3DXFONT)(p_stuFont.m_ptrData[0]))->Release(); p_stuFont.m_ptrData[0] = NULL; p_stuFont.m_blnLoaded = false; } void Direct3D:: Unload(ASW::Buffer & p_clsBuffer, const bool p_blnRetainData) { ASW_ASSERT(&(p_clsBuffer.m_clsApi) == this, "Buffer is not loaded to this API object"); if ( p_blnRetainData ) { if ( p_clsBuffer.m_blnIsIndexBuffer ) { // // If the buffer is locked, unlock it first (unless the lock is over the whole buffer) // void * ptrData; IDirect3DIndexBuffer9 * ptrIb = (IDirect3DIndexBuffer9 *)(p_clsBuffer.m_ptrApiObject); if ( p_clsBuffer.m_stuLockPosition[0] != ~0 || p_clsBuffer.m_stuLockPosition[1] != ~0 ) { if ( p_clsBuffer.m_stuLockPosition[0] > 0 || p_clsBuffer.m_stuLockPosition[1] < p_clsBuffer.m_uintElements ) { HRESULT hndResult = ptrIb->Unlock(); D3D_RUN_CHECK(hndResult); hndResult = ptrIb->Lock(0, p_clsBuffer.m_uintElements * p_clsBuffer.m_uchrElementSize, &ptrData, 0); D3D_RUN_CHECK(hndResult); } else ptrData = p_clsBuffer.m_ptrData; } else { HRESULT hndResult = ptrIb->Lock(0, p_clsBuffer.m_uintElements * p_clsBuffer.m_uchrElementSize, &ptrData, 0); D3D_RUN_CHECK(hndResult); } // // Allocate system memory and copy the data into it // p_clsBuffer.m_ptrData = malloc(p_clsBuffer.m_uintElements * p_clsBuffer.m_uchrElementSize); memcpy(p_clsBuffer.m_ptrData, ptrData, p_clsBuffer.m_uintElements * p_clsBuffer.m_uchrElementSize); HRESULT hndResult = ptrIb->Unlock(); D3D_RUN_CHECK(hndResult); // // Release the video memory buffer // ptrIb->Release(); p_clsBuffer.m_ptrApiObject = NULL; } else { // // If the buffer is locked, unlock it first (unless the lock is over the whole buffer // void * ptrData; IDirect3DVertexBuffer9 * ptrVb = (IDirect3DVertexBuffer9 *)(p_clsBuffer.m_ptrApiObject); if ( p_clsBuffer.m_stuLockPosition[0] != ~0 || p_clsBuffer.m_stuLockPosition[1] != ~0 ) { if ( p_clsBuffer.m_stuLockPosition[0] > 0 || p_clsBuffer.m_stuLockPosition[1] < p_clsBuffer.m_uintElements ) { HRESULT hndResult = ptrVb->Unlock(); D3D_RUN_CHECK(hndResult); hndResult = ptrVb->Lock(0, p_clsBuffer.m_uintElements * p_clsBuffer.m_uchrElementSize, &ptrData, 0); D3D_RUN_CHECK(hndResult); } else ptrData = p_clsBuffer.m_ptrData; } else { HRESULT hndResult = ptrVb->Lock(0, p_clsBuffer.m_uintElements * p_clsBuffer.m_uchrElementSize, &ptrData, 0); D3D_RUN_CHECK(hndResult); } // // Allocate system memory and copy the data into it // p_clsBuffer.m_ptrData = malloc(p_clsBuffer.m_uintElements * p_clsBuffer.m_uchrElementSize); memcpy(p_clsBuffer.m_ptrData, ptrData, p_clsBuffer.m_uintElements * p_clsBuffer.m_uchrElementSize); HRESULT hndResult = ptrVb->Unlock(); D3D_RUN_CHECK(hndResult); // // Release the buffer descriptor // if ( ((ASW::BufferVertex *)(&p_clsBuffer))->m_ptrApiData ) { ((IDirect3DVertexDeclaration9 *)(((ASW::BufferVertex *)(&p_clsBuffer))->m_ptrApiData))->Release(); ((ASW::BufferVertex *)(&p_clsBuffer))->m_ptrApiData = NULL; } // // Release the video memory buffer // ptrVb->Release(); p_clsBuffer.m_ptrApiObject = NULL; } } else { if ( p_clsBuffer.m_blnIsIndexBuffer ) { if ( m_ptrActiveBufferIndex == (ASW::BufferIndex *)(&p_clsBuffer) ) { m_ptrActiveBufferIndex = NULL; m_ptrDevice->SetIndices(NULL); } ((IDirect3DIndexBuffer9 *)(p_clsBuffer.m_ptrApiObject))->Release(); } else { if ( m_ptrActiveBufferVertex == (ASW::BufferVertex *)(&p_clsBuffer) ) { m_ptrActiveBufferVertex = NULL; m_ptrDevice->SetStreamSource(0, NULL, 0, 0); } // // Release the buffer descriptor // if ( ((ASW::BufferVertex *)(&p_clsBuffer))->m_ptrApiData ) { ((IDirect3DVertexDeclaration9 *)(((ASW::BufferVertex *)(&p_clsBuffer))->m_ptrApiData))->Release(); ((ASW::BufferVertex *)(&p_clsBuffer))->m_ptrApiData = NULL; } ((IDirect3DVertexBuffer9 *)(p_clsBuffer.m_ptrApiObject))->Release(); } p_clsBuffer.m_ptrApiObject = NULL; p_clsBuffer.m_ptrData = NULL; } } void Direct3D:: Unload(ASW::Texture & p_clsTexture) { ASW_ASSERT(p_clsTexture.m_blnLoaded, "Texture is not loaded"); ((LPDIRECT3DTEXTURE9)(p_clsTexture.m_ptrObject))->Release(); p_clsTexture.m_ptrObject = NULL; p_clsTexture.m_blnLoaded = false; } void Direct3D:: Set(ASW::Buffer & p_clsBuffer, const void * p_ptrData, const unsigned int p_uintOffset, const unsigned int p_uintSize) { ASW_ASSERT(&(p_clsBuffer.m_clsApi) == this, "Buffer is not loaded to this API object"); ASW_ASSERT((p_uintOffset + p_uintSize) <= (p_clsBuffer.m_uintElements * p_clsBuffer.m_uchrElementSize), "Size/offset exceeds buffer size"); // The D3DLOCK_DISCARD and D3DLOCK_NOOVERWRITE flags are valid only on buffers created with D3DUSAGE_DYNAMIC if ( p_clsBuffer.m_blnIsIndexBuffer ) { void * ptrData; IDirect3DIndexBuffer9 * ptrIb = (IDirect3DIndexBuffer9 *)(p_clsBuffer.m_ptrApiObject); HRESULT hndResult = ptrIb->Lock(p_uintOffset, p_uintSize, &ptrData, ( p_clsBuffer.m_enmWriteHint == ASW::Type::WRITE_DYNAMIC && p_uintOffset == 0 && p_uintSize == (p_clsBuffer.m_uintElements * p_clsBuffer.m_uchrElementSize) ) ? D3DLOCK_DISCARD : 0); D3D_RUN_CHECK(hndResult); memcpy(ptrData, p_ptrData, p_uintSize); hndResult = ptrIb->Unlock(); D3D_RUN_CHECK(hndResult); } else { void * ptrData; IDirect3DVertexBuffer9 * ptrVb = (IDirect3DVertexBuffer9 *)(p_clsBuffer.m_ptrApiObject); HRESULT hndResult = ptrVb->Lock(p_uintOffset, p_uintSize, &ptrData, ( p_clsBuffer.m_enmWriteHint == ASW::Type::WRITE_DYNAMIC && p_uintOffset == 0 && p_uintSize == (p_clsBuffer.m_uintElements * p_clsBuffer.m_uchrElementSize) ) ? D3DLOCK_DISCARD : 0); D3D_RUN_CHECK(hndResult); memcpy(ptrData, p_ptrData, p_uintSize); hndResult = ptrVb->Unlock(); D3D_RUN_CHECK(hndResult); } } void Direct3D:: SetViewport(const ASW::Point4i & p_stuDimensions, const ASW::Point2f & p_stuDepthRange) { D3DVIEWPORT9 stuViewport; stuViewport.X = (DWORD)(p_stuDimensions[0]); stuViewport.Y = (DWORD)(p_stuDimensions[1]); stuViewport.Width = (DWORD)(p_stuDimensions[2]); stuViewport.Height = (DWORD)(p_stuDimensions[3]); stuViewport.MinZ = p_stuDepthRange[0]; stuViewport.MaxZ = p_stuDepthRange[1]; D3D_RUN(SetViewport(&stuViewport)); } void Direct3D:: Unlock(ASW::Buffer & p_clsBuffer) { ASW_ASSERT(&(p_clsBuffer.m_clsApi) == this, "Buffer is not loaded to this API object"); HRESULT hndResult = ( p_clsBuffer.m_blnIsIndexBuffer ) ? ((IDirect3DIndexBuffer9 *)(p_clsBuffer.m_ptrApiObject))->Unlock() : ((IDirect3DVertexBuffer9 *)(p_clsBuffer.m_ptrApiObject))->Unlock(); D3D_RUN_CHECK(hndResult); }