2018-09-13 22:44:08 +08:00
// dear imgui: Renderer for DirectX9
2018-02-22 06:05:17 +08:00
// This needs to be used along with a Platform Binding (e.g. Win32)
2018-02-06 03:34:11 +08:00
// Implemented features:
2019-10-16 17:23:15 +08:00
// [X] Renderer: User texture binding. Use 'LPDIRECT3DTEXTURE9' as ImTextureID. Read the FAQ about ImTextureID!
2019-03-07 04:34:37 +08:00
// [X] Renderer: Multi-viewport support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
2019-11-20 18:58:25 +08:00
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
2016-03-24 18:00:47 +08:00
2015-11-29 19:19:30 +08:00
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
2018-07-05 01:06:28 +08:00
// If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp.
2015-03-09 21:03:46 +08:00
// https://github.com/ocornut/imgui
2019-01-21 00:56:17 +08:00
// CHANGELOG
2018-02-17 02:18:16 +08:00
// (minor and older changes stripped away, please see git history for details)
2020-01-10 21:38:09 +08:00
// 2020-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
2019-05-29 22:29:17 +08:00
// 2019-05-29: DirectX9: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag.
2019-05-01 04:28:29 +08:00
// 2019-04-30: DirectX9: Added support for special ImDrawCallback_ResetRenderState callback to reset render state.
2019-03-30 01:29:15 +08:00
// 2019-03-29: Misc: Fixed erroneous assert in ImGui_ImplDX9_InvalidateDeviceObjects().
2019-01-17 13:07:15 +08:00
// 2019-01-16: Misc: Disabled fog before drawing UI's. Fixes issue #2288.
2018-12-01 01:18:15 +08:00
// 2018-11-30: Misc: Setting up io.BackendRendererName so it can be displayed in the About Window.
2018-06-09 01:37:33 +08:00
// 2018-06-08: Misc: Extracted imgui_impl_dx9.cpp/.h away from the old combined DX9+Win32 example.
// 2018-06-08: DirectX9: Use draw_data->DisplayPos and draw_data->DisplaySize to setup projection matrix and clipping rectangle.
2018-05-07 17:52:11 +08:00
// 2018-05-07: Render: Saving/restoring Transform because they don't seem to be included in the StateBlock. Setting shading mode to Gouraud.
2018-02-17 02:18:16 +08:00
// 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplDX9_RenderDrawData() in the .h file so you can call it yourself.
// 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves.
2018-01-29 21:38:46 +08:00
# include "imgui.h"
2015-03-09 21:03:46 +08:00
# include "imgui_impl_dx9.h"
// DirectX
2016-05-03 16:47:42 +08:00
# include <d3d9.h>
2015-03-09 21:03:46 +08:00
# define DIRECTINPUT_VERSION 0x0800
# include <dinput.h>
2018-02-20 20:55:09 +08:00
// DirectX data
2015-03-09 21:03:46 +08:00
static LPDIRECT3DDEVICE9 g_pd3dDevice = NULL ;
static LPDIRECT3DVERTEXBUFFER9 g_pVB = NULL ;
2015-04-10 04:05:35 +08:00
static LPDIRECT3DINDEXBUFFER9 g_pIB = NULL ;
2015-08-14 13:06:11 +08:00
static LPDIRECT3DTEXTURE9 g_FontTexture = NULL ;
static int g_VertexBufferSize = 5000 , g_IndexBufferSize = 10000 ;
2015-03-09 21:03:46 +08:00
struct CUSTOMVERTEX
{
2016-05-03 16:47:42 +08:00
float pos [ 3 ] ;
D3DCOLOR col ;
float uv [ 2 ] ;
2015-03-09 21:03:46 +08:00
} ;
# define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1)
2019-03-07 04:34:37 +08:00
// Forward Declarations
static void ImGui_ImplDX9_InitPlatformInterface ( ) ;
static void ImGui_ImplDX9_ShutdownPlatformInterface ( ) ;
2019-05-06 18:07:29 +08:00
static void ImGui_ImplDX9_CreateDeviceObjectsForPlatformWindows ( ) ;
static void ImGui_ImplDX9_InvalidateDeviceObjectsForPlatformWindows ( ) ;
2019-03-07 04:34:37 +08:00
2019-05-01 04:15:59 +08:00
static void ImGui_ImplDX9_SetupRenderState ( ImDrawData * draw_data )
{
// Setup viewport
D3DVIEWPORT9 vp ;
vp . X = vp . Y = 0 ;
vp . Width = ( DWORD ) draw_data - > DisplaySize . x ;
vp . Height = ( DWORD ) draw_data - > DisplaySize . y ;
vp . MinZ = 0.0f ;
vp . MaxZ = 1.0f ;
g_pd3dDevice - > SetViewport ( & vp ) ;
// Setup render state: fixed-pipeline, alpha-blending, no face culling, no depth testing, shade mode (for gradient)
g_pd3dDevice - > SetPixelShader ( NULL ) ;
g_pd3dDevice - > SetVertexShader ( NULL ) ;
g_pd3dDevice - > SetRenderState ( D3DRS_CULLMODE , D3DCULL_NONE ) ;
2020-02-17 23:07:46 +08:00
g_pd3dDevice - > SetRenderState ( D3DRS_LIGHTING , FALSE ) ;
g_pd3dDevice - > SetRenderState ( D3DRS_ZENABLE , FALSE ) ;
g_pd3dDevice - > SetRenderState ( D3DRS_ALPHABLENDENABLE , TRUE ) ;
g_pd3dDevice - > SetRenderState ( D3DRS_ALPHATESTENABLE , FALSE ) ;
2019-05-01 04:15:59 +08:00
g_pd3dDevice - > SetRenderState ( D3DRS_BLENDOP , D3DBLENDOP_ADD ) ;
g_pd3dDevice - > SetRenderState ( D3DRS_SRCBLEND , D3DBLEND_SRCALPHA ) ;
g_pd3dDevice - > SetRenderState ( D3DRS_DESTBLEND , D3DBLEND_INVSRCALPHA ) ;
2020-02-17 23:07:46 +08:00
g_pd3dDevice - > SetRenderState ( D3DRS_SCISSORTESTENABLE , TRUE ) ;
2019-05-01 04:15:59 +08:00
g_pd3dDevice - > SetRenderState ( D3DRS_SHADEMODE , D3DSHADE_GOURAUD ) ;
2020-02-17 23:07:46 +08:00
g_pd3dDevice - > SetRenderState ( D3DRS_FOGENABLE , FALSE ) ;
2019-05-01 04:15:59 +08:00
g_pd3dDevice - > SetTextureStageState ( 0 , D3DTSS_COLOROP , D3DTOP_MODULATE ) ;
g_pd3dDevice - > SetTextureStageState ( 0 , D3DTSS_COLORARG1 , D3DTA_TEXTURE ) ;
g_pd3dDevice - > SetTextureStageState ( 0 , D3DTSS_COLORARG2 , D3DTA_DIFFUSE ) ;
g_pd3dDevice - > SetTextureStageState ( 0 , D3DTSS_ALPHAOP , D3DTOP_MODULATE ) ;
g_pd3dDevice - > SetTextureStageState ( 0 , D3DTSS_ALPHAARG1 , D3DTA_TEXTURE ) ;
g_pd3dDevice - > SetTextureStageState ( 0 , D3DTSS_ALPHAARG2 , D3DTA_DIFFUSE ) ;
g_pd3dDevice - > SetSamplerState ( 0 , D3DSAMP_MINFILTER , D3DTEXF_LINEAR ) ;
g_pd3dDevice - > SetSamplerState ( 0 , D3DSAMP_MAGFILTER , D3DTEXF_LINEAR ) ;
// Setup orthographic projection matrix
2019-06-06 22:16:18 +08:00
// Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps.
2019-05-01 04:15:59 +08:00
// Being agnostic of whether <d3dx9.h> or <DirectXMath.h> can be used, we aren't relying on D3DXMatrixIdentity()/D3DXMatrixOrthoOffCenterLH() or DirectX::XMMatrixIdentity()/DirectX::XMMatrixOrthographicOffCenterLH()
{
float L = draw_data - > DisplayPos . x + 0.5f ;
float R = draw_data - > DisplayPos . x + draw_data - > DisplaySize . x + 0.5f ;
float T = draw_data - > DisplayPos . y + 0.5f ;
float B = draw_data - > DisplayPos . y + draw_data - > DisplaySize . y + 0.5f ;
D3DMATRIX mat_identity = { { { 1.0f , 0.0f , 0.0f , 0.0f , 0.0f , 1.0f , 0.0f , 0.0f , 0.0f , 0.0f , 1.0f , 0.0f , 0.0f , 0.0f , 0.0f , 1.0f } } } ;
D3DMATRIX mat_projection =
{ { {
2.0f / ( R - L ) , 0.0f , 0.0f , 0.0f ,
0.0f , 2.0f / ( T - B ) , 0.0f , 0.0f ,
0.0f , 0.0f , 0.5f , 0.0f ,
( L + R ) / ( L - R ) , ( T + B ) / ( B - T ) , 0.5f , 1.0f
} } } ;
g_pd3dDevice - > SetTransform ( D3DTS_WORLD , & mat_identity ) ;
g_pd3dDevice - > SetTransform ( D3DTS_VIEW , & mat_identity ) ;
g_pd3dDevice - > SetTransform ( D3DTS_PROJECTION , & mat_projection ) ;
}
}
2018-02-17 02:18:16 +08:00
// Render function.
// (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop)
void ImGui_ImplDX9_RenderDrawData ( ImDrawData * draw_data )
2015-03-09 21:03:46 +08:00
{
2016-05-03 16:47:42 +08:00
// Avoid rendering when minimized
2018-03-14 04:45:09 +08:00
if ( draw_data - > DisplaySize . x < = 0.0f | | draw_data - > DisplaySize . y < = 0.0f )
2016-05-03 16:47:42 +08:00
return ;
2015-08-14 13:13:20 +08:00
// Create and grow buffers if needed
2015-08-14 13:06:11 +08:00
if ( ! g_pVB | | g_VertexBufferSize < draw_data - > TotalVtxCount )
{
2015-08-14 13:13:20 +08:00
if ( g_pVB ) { g_pVB - > Release ( ) ; g_pVB = NULL ; }
2015-08-14 13:06:11 +08:00
g_VertexBufferSize = draw_data - > TotalVtxCount + 5000 ;
if ( g_pd3dDevice - > CreateVertexBuffer ( g_VertexBufferSize * sizeof ( CUSTOMVERTEX ) , D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY , D3DFVF_CUSTOMVERTEX , D3DPOOL_DEFAULT , & g_pVB , NULL ) < 0 )
return ;
}
if ( ! g_pIB | | g_IndexBufferSize < draw_data - > TotalIdxCount )
{
2015-08-14 13:13:20 +08:00
if ( g_pIB ) { g_pIB - > Release ( ) ; g_pIB = NULL ; }
2015-08-14 13:06:11 +08:00
g_IndexBufferSize = draw_data - > TotalIdxCount + 10000 ;
2015-11-08 19:00:31 +08:00
if ( g_pd3dDevice - > CreateIndexBuffer ( g_IndexBufferSize * sizeof ( ImDrawIdx ) , D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY , sizeof ( ImDrawIdx ) = = 2 ? D3DFMT_INDEX16 : D3DFMT_INDEX32 , D3DPOOL_DEFAULT , & g_pIB , NULL ) < 0 )
2015-08-14 13:06:11 +08:00
return ;
}
2016-05-16 08:02:09 +08:00
// Backup the DX9 state
IDirect3DStateBlock9 * d3d9_state_block = NULL ;
2016-05-16 16:54:52 +08:00
if ( g_pd3dDevice - > CreateStateBlock ( D3DSBT_ALL , & d3d9_state_block ) < 0 )
2016-05-16 08:02:09 +08:00
return ;
2016-04-12 00:33:16 +08:00
2018-05-07 17:52:11 +08:00
// Backup the DX9 transform (DX9 documentation suggests that it is included in the StateBlock but it doesn't appear to)
2018-05-03 17:01:41 +08:00
D3DMATRIX last_world , last_view , last_projection ;
g_pd3dDevice - > GetTransform ( D3DTS_WORLD , & last_world ) ;
g_pd3dDevice - > GetTransform ( D3DTS_VIEW , & last_view ) ;
g_pd3dDevice - > GetTransform ( D3DTS_PROJECTION , & last_projection ) ;
2018-05-07 17:52:11 +08:00
// Copy and convert all vertices into a single contiguous buffer, convert colors to DX9 default format.
// FIXME-OPT: This is a waste of resource, the ideal is to use imconfig.h and
// 1) to avoid repacking colors: #define IMGUI_USE_BGRA_PACKED_COLOR
// 2) to avoid repacking vertices: #define IMGUI_OVERRIDE_DRAWVERT_STRUCT_LAYOUT struct ImDrawVert { ImVec2 pos; float z; ImU32 col; ImVec2 uv; }
2015-03-09 21:03:46 +08:00
CUSTOMVERTEX * vtx_dst ;
2015-04-10 04:05:35 +08:00
ImDrawIdx * idx_dst ;
2015-07-08 10:17:07 +08:00
if ( g_pVB - > Lock ( 0 , ( UINT ) ( draw_data - > TotalVtxCount * sizeof ( CUSTOMVERTEX ) ) , ( void * * ) & vtx_dst , D3DLOCK_DISCARD ) < 0 )
2015-03-09 21:03:46 +08:00
return ;
2015-07-08 10:17:07 +08:00
if ( g_pIB - > Lock ( 0 , ( UINT ) ( draw_data - > TotalIdxCount * sizeof ( ImDrawIdx ) ) , ( void * * ) & idx_dst , D3DLOCK_DISCARD ) < 0 )
2015-04-10 04:05:35 +08:00
return ;
2015-07-08 10:17:07 +08:00
for ( int n = 0 ; n < draw_data - > CmdListsCount ; n + + )
2015-03-09 21:03:46 +08:00
{
2015-07-08 10:17:07 +08:00
const ImDrawList * cmd_list = draw_data - > CmdLists [ n ] ;
2016-09-04 01:24:57 +08:00
const ImDrawVert * vtx_src = cmd_list - > VtxBuffer . Data ;
for ( int i = 0 ; i < cmd_list - > VtxBuffer . Size ; i + + )
2015-03-09 21:03:46 +08:00
{
2016-05-03 16:47:42 +08:00
vtx_dst - > pos [ 0 ] = vtx_src - > pos . x ;
vtx_dst - > pos [ 1 ] = vtx_src - > pos . y ;
vtx_dst - > pos [ 2 ] = 0.0f ;
2018-05-07 17:52:11 +08:00
vtx_dst - > col = ( vtx_src - > col & 0xFF00FF00 ) | ( ( vtx_src - > col & 0xFF0000 ) > > 16 ) | ( ( vtx_src - > col & 0xFF ) < < 16 ) ; // RGBA --> ARGB for DirectX9
2016-05-03 16:47:42 +08:00
vtx_dst - > uv [ 0 ] = vtx_src - > uv . x ;
vtx_dst - > uv [ 1 ] = vtx_src - > uv . y ;
2015-03-09 21:03:46 +08:00
vtx_dst + + ;
vtx_src + + ;
}
2016-09-04 01:24:57 +08:00
memcpy ( idx_dst , cmd_list - > IdxBuffer . Data , cmd_list - > IdxBuffer . Size * sizeof ( ImDrawIdx ) ) ;
idx_dst + = cmd_list - > IdxBuffer . Size ;
2015-03-09 21:03:46 +08:00
}
g_pVB - > Unlock ( ) ;
2015-04-10 04:05:35 +08:00
g_pIB - > Unlock ( ) ;
2016-05-16 16:54:52 +08:00
g_pd3dDevice - > SetStreamSource ( 0 , g_pVB , 0 , sizeof ( CUSTOMVERTEX ) ) ;
g_pd3dDevice - > SetIndices ( g_pIB ) ;
g_pd3dDevice - > SetFVF ( D3DFVF_CUSTOMVERTEX ) ;
2015-03-09 21:03:46 +08:00
2019-05-01 04:15:59 +08:00
// Setup desired DX state
ImGui_ImplDX9_SetupRenderState ( draw_data ) ;
2015-03-09 21:03:46 +08:00
// Render command lists
2019-05-29 21:53:36 +08:00
// (Because we merged all buffers into a single one, we maintain our own offset into them)
int global_vtx_offset = 0 ;
int global_idx_offset = 0 ;
2019-02-12 01:38:07 +08:00
ImVec2 clip_off = draw_data - > DisplayPos ;
2015-07-08 10:17:07 +08:00
for ( int n = 0 ; n < draw_data - > CmdListsCount ; n + + )
2015-03-09 21:03:46 +08:00
{
2015-07-08 10:17:07 +08:00
const ImDrawList * cmd_list = draw_data - > CmdLists [ n ] ;
2016-09-04 01:24:57 +08:00
for ( int cmd_i = 0 ; cmd_i < cmd_list - > CmdBuffer . Size ; cmd_i + + )
2015-03-09 21:03:46 +08:00
{
2015-07-08 10:17:07 +08:00
const ImDrawCmd * pcmd = & cmd_list - > CmdBuffer [ cmd_i ] ;
2019-05-01 04:15:59 +08:00
if ( pcmd - > UserCallback ! = NULL )
2015-03-09 23:26:58 +08:00
{
2019-05-01 04:15:59 +08:00
// User callback, registered via ImDrawList::AddCallback()
// (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
if ( pcmd - > UserCallback = = ImDrawCallback_ResetRenderState )
ImGui_ImplDX9_SetupRenderState ( draw_data ) ;
else
pcmd - > UserCallback ( cmd_list , pcmd ) ;
2015-03-09 23:26:58 +08:00
}
else
{
2019-02-12 01:38:07 +08:00
const RECT r = { ( LONG ) ( pcmd - > ClipRect . x - clip_off . x ) , ( LONG ) ( pcmd - > ClipRect . y - clip_off . y ) , ( LONG ) ( pcmd - > ClipRect . z - clip_off . x ) , ( LONG ) ( pcmd - > ClipRect . w - clip_off . y ) } ;
2018-08-09 23:49:48 +08:00
const LPDIRECT3DTEXTURE9 texture = ( LPDIRECT3DTEXTURE9 ) pcmd - > TextureId ;
g_pd3dDevice - > SetTexture ( 0 , texture ) ;
2016-05-16 16:54:52 +08:00
g_pd3dDevice - > SetScissorRect ( & r ) ;
2020-06-30 21:31:54 +08:00
g_pd3dDevice - > DrawIndexedPrimitive ( D3DPT_TRIANGLELIST , pcmd - > VtxOffset + global_vtx_offset , 0 , ( UINT ) cmd_list - > VtxBuffer . Size , pcmd - > IdxOffset + global_idx_offset , pcmd - > ElemCount / 3 ) ;
2015-03-09 23:26:58 +08:00
}
2015-03-09 21:03:46 +08:00
}
2019-05-29 21:53:36 +08:00
global_idx_offset + = cmd_list - > IdxBuffer . Size ;
global_vtx_offset + = cmd_list - > VtxBuffer . Size ;
2015-03-09 21:03:46 +08:00
}
2016-04-12 00:33:16 +08:00
2019-09-18 00:32:26 +08:00
// When using multi-viewports, it appears that there's an odd logic in DirectX9 which prevent subsequent windows
// from rendering until the first window submits at least one draw call, even once. That's our workaround. (see #2560)
if ( global_vtx_offset = = 0 )
g_pd3dDevice - > DrawIndexedPrimitive ( D3DPT_TRIANGLELIST , 0 , 0 , 0 , 0 , 0 ) ;
2018-05-03 17:01:41 +08:00
// Restore the DX9 transform
g_pd3dDevice - > SetTransform ( D3DTS_WORLD , & last_world ) ;
g_pd3dDevice - > SetTransform ( D3DTS_VIEW , & last_view ) ;
g_pd3dDevice - > SetTransform ( D3DTS_PROJECTION , & last_projection ) ;
2016-05-16 08:02:09 +08:00
// Restore the DX9 state
d3d9_state_block - > Apply ( ) ;
d3d9_state_block - > Release ( ) ;
2015-03-09 21:03:46 +08:00
}
2018-02-20 23:18:02 +08:00
bool ImGui_ImplDX9_Init ( IDirect3DDevice9 * device )
2015-03-09 21:03:46 +08:00
{
2019-06-06 22:16:18 +08:00
// Setup back-end capabilities flags
2018-12-01 01:18:15 +08:00
ImGuiIO & io = ImGui : : GetIO ( ) ;
io . BackendRendererName = " imgui_impl_dx9 " ;
2019-05-29 22:29:17 +08:00
io . BackendFlags | = ImGuiBackendFlags_RendererHasVtxOffset ; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
2019-06-06 22:16:18 +08:00
io . BackendFlags | = ImGuiBackendFlags_RendererHasViewports ; // We can create multi-viewports on the Renderer side (optional)
2018-12-01 01:18:15 +08:00
2015-03-09 21:03:46 +08:00
g_pd3dDevice = device ;
2019-05-06 16:11:02 +08:00
g_pd3dDevice - > AddRef ( ) ;
2019-03-07 04:34:37 +08:00
if ( io . ConfigFlags & ImGuiConfigFlags_ViewportsEnable )
ImGui_ImplDX9_InitPlatformInterface ( ) ;
2015-03-09 21:03:46 +08:00
return true ;
}
2015-03-09 22:55:46 +08:00
void ImGui_ImplDX9_Shutdown ( )
{
2019-03-07 04:34:37 +08:00
ImGui_ImplDX9_ShutdownPlatformInterface ( ) ;
2015-03-09 22:55:46 +08:00
ImGui_ImplDX9_InvalidateDeviceObjects ( ) ;
2019-03-07 04:34:37 +08:00
if ( g_pd3dDevice ) { g_pd3dDevice - > Release ( ) ; g_pd3dDevice = NULL ; }
2015-03-09 22:55:46 +08:00
}
2015-08-14 13:07:53 +08:00
static bool ImGui_ImplDX9_CreateFontsTexture ( )
2015-03-09 22:55:46 +08:00
{
2015-11-29 22:54:05 +08:00
// Build texture atlas
2015-03-09 22:55:46 +08:00
ImGuiIO & io = ImGui : : GetIO ( ) ;
unsigned char * pixels ;
int width , height , bytes_per_pixel ;
2016-02-08 16:03:43 +08:00
io . Fonts - > GetTexDataAsRGBA32 ( & pixels , & width , & height , & bytes_per_pixel ) ;
2015-03-09 22:55:46 +08:00
2015-11-29 22:54:05 +08:00
// Upload texture to graphics system
2015-08-14 13:06:11 +08:00
g_FontTexture = NULL ;
2016-05-03 16:47:42 +08:00
if ( g_pd3dDevice - > CreateTexture ( width , height , 1 , D3DUSAGE_DYNAMIC , D3DFMT_A8R8G8B8 , D3DPOOL_DEFAULT , & g_FontTexture , NULL ) < 0 )
2015-08-14 13:07:53 +08:00
return false ;
2015-03-09 22:55:46 +08:00
D3DLOCKED_RECT tex_locked_rect ;
2016-03-26 22:43:45 +08:00
if ( g_FontTexture - > LockRect ( 0 , & tex_locked_rect , NULL , 0 ) ! = D3D_OK )
2015-08-14 13:07:53 +08:00
return false ;
2015-03-09 22:55:46 +08:00
for ( int y = 0 ; y < height ; y + + )
2020-06-30 21:31:54 +08:00
memcpy ( ( unsigned char * ) tex_locked_rect . pBits + tex_locked_rect . Pitch * y , pixels + ( width * bytes_per_pixel ) * y , ( width * bytes_per_pixel ) ) ;
2015-08-14 13:06:11 +08:00
g_FontTexture - > UnlockRect ( 0 ) ;
2015-03-09 22:55:46 +08:00
// Store our identifier
2018-08-09 23:49:48 +08:00
io . Fonts - > TexID = ( ImTextureID ) g_FontTexture ;
2015-05-12 22:16:12 +08:00
2015-08-14 13:07:53 +08:00
return true ;
2015-03-09 22:55:46 +08:00
}
bool ImGui_ImplDX9_CreateDeviceObjects ( )
{
if ( ! g_pd3dDevice )
return false ;
2015-08-14 13:07:53 +08:00
if ( ! ImGui_ImplDX9_CreateFontsTexture ( ) )
return false ;
2019-05-06 18:07:29 +08:00
ImGui_ImplDX9_CreateDeviceObjectsForPlatformWindows ( ) ;
2015-03-09 22:55:46 +08:00
return true ;
}
2015-03-09 22:13:29 +08:00
void ImGui_ImplDX9_InvalidateDeviceObjects ( )
2015-03-09 21:03:46 +08:00
{
2015-03-09 22:13:29 +08:00
if ( ! g_pd3dDevice )
return ;
2019-03-30 01:29:15 +08:00
if ( g_pVB ) { g_pVB - > Release ( ) ; g_pVB = NULL ; }
if ( g_pIB ) { g_pIB - > Release ( ) ; g_pIB = NULL ; }
if ( g_FontTexture ) { g_FontTexture - > Release ( ) ; g_FontTexture = NULL ; ImGui : : GetIO ( ) . Fonts - > TexID = NULL ; } // We copied g_pFontTextureView to io.Fonts->TexID so let's clear that as well.
2019-05-06 18:07:29 +08:00
ImGui_ImplDX9_InvalidateDeviceObjectsForPlatformWindows ( ) ;
2015-03-09 22:13:29 +08:00
}
2015-03-09 21:03:46 +08:00
void ImGui_ImplDX9_NewFrame ( )
{
2015-08-14 13:06:11 +08:00
if ( ! g_FontTexture )
2015-03-09 22:55:46 +08:00
ImGui_ImplDX9_CreateDeviceObjects ( ) ;
2015-03-09 21:03:46 +08:00
}
2019-03-07 04:34:37 +08:00
//--------------------------------------------------------------------------------------------------------
// MULTI-VIEWPORT / PLATFORM INTERFACE SUPPORT
// This is an _advanced_ and _optional_ feature, allowing the back-end to create and handle multiple viewports simultaneously.
// If you are new to dear imgui or creating a new binding for dear imgui, it is recommended that you completely ignore this section first..
//--------------------------------------------------------------------------------------------------------
2020-01-21 02:33:46 +08:00
// Helper structure we store in the void* RenderUserData field of each ImGuiViewport to easily retrieve our backend data.
2019-03-07 04:34:37 +08:00
struct ImGuiViewportDataDx9
{
IDirect3DSwapChain9 * SwapChain ;
D3DPRESENT_PARAMETERS d3dpp ;
ImGuiViewportDataDx9 ( ) { SwapChain = NULL ; ZeroMemory ( & d3dpp , sizeof ( D3DPRESENT_PARAMETERS ) ) ; }
~ ImGuiViewportDataDx9 ( ) { IM_ASSERT ( SwapChain = = NULL ) ; }
} ;
static void ImGui_ImplDX9_CreateWindow ( ImGuiViewport * viewport )
{
ImGuiViewportDataDx9 * data = IM_NEW ( ImGuiViewportDataDx9 ) ( ) ;
viewport - > RendererUserData = data ;
2019-06-19 05:35:48 +08:00
// PlatformHandleRaw should always be a HWND, whereas PlatformHandle might be a higher-level handle (e.g. GLFWWindow*, SDL_Window*).
// Some back-ends will leave PlatformHandleRaw NULL, in which case we assume PlatformHandle will contain the HWND.
HWND hwnd = viewport - > PlatformHandleRaw ? ( HWND ) viewport - > PlatformHandleRaw : ( HWND ) viewport - > PlatformHandle ;
IM_ASSERT ( hwnd ! = 0 ) ;
2019-03-07 04:34:37 +08:00
ZeroMemory ( & data - > d3dpp , sizeof ( D3DPRESENT_PARAMETERS ) ) ;
data - > d3dpp . Windowed = TRUE ;
data - > d3dpp . SwapEffect = D3DSWAPEFFECT_DISCARD ;
2019-05-06 18:07:29 +08:00
data - > d3dpp . BackBufferWidth = ( UINT ) viewport - > Size . x ;
data - > d3dpp . BackBufferHeight = ( UINT ) viewport - > Size . y ;
2019-03-07 04:34:37 +08:00
data - > d3dpp . BackBufferFormat = D3DFMT_UNKNOWN ;
2019-06-19 05:35:48 +08:00
data - > d3dpp . hDeviceWindow = hwnd ;
2019-05-06 18:12:32 +08:00
data - > d3dpp . EnableAutoDepthStencil = FALSE ;
2019-03-07 04:34:37 +08:00
data - > d3dpp . AutoDepthStencilFormat = D3DFMT_D16 ;
data - > d3dpp . PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE ; // Present without vsync
2019-05-06 18:07:29 +08:00
HRESULT hr = g_pd3dDevice - > CreateAdditionalSwapChain ( & data - > d3dpp , & data - > SwapChain ) ; IM_UNUSED ( hr ) ;
IM_ASSERT ( hr = = D3D_OK ) ;
2019-03-07 04:34:37 +08:00
IM_ASSERT ( data - > SwapChain ! = NULL ) ;
}
static void ImGui_ImplDX9_DestroyWindow ( ImGuiViewport * viewport )
{
// The main viewport (owned by the application) will always have RendererUserData == NULL since we didn't create the data for it.
if ( ImGuiViewportDataDx9 * data = ( ImGuiViewportDataDx9 * ) viewport - > RendererUserData )
{
if ( data - > SwapChain )
data - > SwapChain - > Release ( ) ;
data - > SwapChain = NULL ;
ZeroMemory ( & data - > d3dpp , sizeof ( D3DPRESENT_PARAMETERS ) ) ;
IM_DELETE ( data ) ;
}
viewport - > RendererUserData = NULL ;
}
static void ImGui_ImplDX9_SetWindowSize ( ImGuiViewport * viewport , ImVec2 size )
{
ImGuiViewportDataDx9 * data = ( ImGuiViewportDataDx9 * ) viewport - > RendererUserData ;
if ( data - > SwapChain )
{
data - > SwapChain - > Release ( ) ;
data - > SwapChain = NULL ;
data - > d3dpp . BackBufferWidth = ( UINT ) size . x ;
data - > d3dpp . BackBufferHeight = ( UINT ) size . y ;
2019-05-06 18:07:29 +08:00
HRESULT hr = g_pd3dDevice - > CreateAdditionalSwapChain ( & data - > d3dpp , & data - > SwapChain ) ; IM_UNUSED ( hr ) ;
IM_ASSERT ( hr = = D3D_OK ) ;
2019-03-07 04:34:37 +08:00
}
}
static void ImGui_ImplDX9_RenderWindow ( ImGuiViewport * viewport , void * )
{
ImGuiViewportDataDx9 * data = ( ImGuiViewportDataDx9 * ) viewport - > RendererUserData ;
ImVec4 clear_color = ImVec4 ( 0.0f , 0.0f , 0.0f , 1.0f ) ;
LPDIRECT3DSURFACE9 render_target = NULL ;
LPDIRECT3DSURFACE9 last_render_target = NULL ;
2019-05-06 18:12:32 +08:00
LPDIRECT3DSURFACE9 last_depth_stencil = NULL ;
2019-03-07 04:34:37 +08:00
data - > SwapChain - > GetBackBuffer ( 0 , D3DBACKBUFFER_TYPE_MONO , & render_target ) ;
g_pd3dDevice - > GetRenderTarget ( 0 , & last_render_target ) ;
2019-05-06 18:12:32 +08:00
g_pd3dDevice - > GetDepthStencilSurface ( & last_depth_stencil ) ;
2019-03-07 04:34:37 +08:00
g_pd3dDevice - > SetRenderTarget ( 0 , render_target ) ;
2019-05-06 18:12:32 +08:00
g_pd3dDevice - > SetDepthStencilSurface ( NULL ) ;
2019-03-07 04:34:37 +08:00
if ( ! ( viewport - > Flags & ImGuiViewportFlags_NoRendererClear ) )
{
D3DCOLOR clear_col_dx = D3DCOLOR_RGBA ( ( int ) ( clear_color . x * 255.0f ) , ( int ) ( clear_color . y * 255.0f ) , ( int ) ( clear_color . z * 255.0f ) , ( int ) ( clear_color . w * 255.0f ) ) ;
2019-05-06 18:12:32 +08:00
g_pd3dDevice - > Clear ( 0 , NULL , D3DCLEAR_TARGET , clear_col_dx , 1.0f , 0 ) ;
2019-03-07 04:34:37 +08:00
}
ImGui_ImplDX9_RenderDrawData ( viewport - > DrawData ) ;
// Restore render target
g_pd3dDevice - > SetRenderTarget ( 0 , last_render_target ) ;
2019-05-06 18:12:32 +08:00
g_pd3dDevice - > SetDepthStencilSurface ( last_depth_stencil ) ;
2019-03-07 04:34:37 +08:00
render_target - > Release ( ) ;
last_render_target - > Release ( ) ;
2019-05-06 18:12:32 +08:00
if ( last_depth_stencil ) last_depth_stencil - > Release ( ) ;
2019-03-07 04:34:37 +08:00
}
static void ImGui_ImplDX9_SwapBuffers ( ImGuiViewport * viewport , void * )
{
ImGuiViewportDataDx9 * data = ( ImGuiViewportDataDx9 * ) viewport - > RendererUserData ;
2019-05-06 18:07:29 +08:00
HRESULT hr = data - > SwapChain - > Present ( NULL , NULL , data - > d3dpp . hDeviceWindow , NULL , NULL ) ;
IM_ASSERT ( hr = = D3D_OK ) ;
2019-03-07 04:34:37 +08:00
}
static void ImGui_ImplDX9_InitPlatformInterface ( )
{
ImGuiPlatformIO & platform_io = ImGui : : GetPlatformIO ( ) ;
platform_io . Renderer_CreateWindow = ImGui_ImplDX9_CreateWindow ;
platform_io . Renderer_DestroyWindow = ImGui_ImplDX9_DestroyWindow ;
platform_io . Renderer_SetWindowSize = ImGui_ImplDX9_SetWindowSize ;
platform_io . Renderer_RenderWindow = ImGui_ImplDX9_RenderWindow ;
platform_io . Renderer_SwapBuffers = ImGui_ImplDX9_SwapBuffers ;
}
static void ImGui_ImplDX9_ShutdownPlatformInterface ( )
{
2020-03-07 00:53:09 +08:00
ImGui : : DestroyPlatformWindows ( ) ;
2019-03-07 04:34:37 +08:00
}
2019-05-06 18:07:29 +08:00
static void ImGui_ImplDX9_CreateDeviceObjectsForPlatformWindows ( )
{
ImGuiPlatformIO & platform_io = ImGui : : GetPlatformIO ( ) ;
for ( int i = 1 ; i < platform_io . Viewports . Size ; i + + )
if ( ! platform_io . Viewports [ i ] - > RendererUserData )
ImGui_ImplDX9_CreateWindow ( platform_io . Viewports [ i ] ) ;
}
static void ImGui_ImplDX9_InvalidateDeviceObjectsForPlatformWindows ( )
{
ImGuiPlatformIO & platform_io = ImGui : : GetPlatformIO ( ) ;
for ( int i = 1 ; i < platform_io . Viewports . Size ; i + + )
if ( platform_io . Viewports [ i ] - > RendererUserData )
ImGui_ImplDX9_DestroyWindow ( platform_io . Viewports [ i ] ) ;
}