This commit is contained in:
IoIxD 2026-09-17 21:44:55 -07:00 committed by Nishi
commit 47c9f8df4e
12 changed files with 354 additions and 65 deletions

View file

@ -32,8 +32,10 @@ else()
option(MW_TRY_OPENGL "Try to compile OpenGL widget or not" ON)
option(MW_TRY_VULKAN "Try to compile Vulkan widget or not" ON)
endif()
if(${CMAKE_SYSTEM_NAME} MATCHES Windows)
option(MW_TRY_DIRECTX "Try to compile DirectX widget or not" ON)
option(MW_TRY_D3D8 "Try to compile D3D8 widget or not" ON)
option(MW_TRY_D3D9 "Try to compile D3D9 widget or not" ON)
endif()
@ -94,13 +96,19 @@ if(MW_TRY_VULKAN)
endif()
endif()
if(MW_TRY_DIRECTX)
if(MW_TRY_D3D8 OR MW_TRY_D3D9)
include(${CMAKE_CURRENT_SOURCE_DIR}/resource/FindDirectX.cmake)
if(DIRECTX_FOUND)
set(MW_BUILD_DIRECTX ON)
message(STATUS "DirectX widget has been enabled")
if(MW_TRY_D3D8)
set(MW_BUILD_D3D8 ON)
message(STATUS "D3D8 widget has been enabled")
endif()
if(MW_TRY_D3D9)
set(MW_BUILD_D3D9 ON)
message(STATUS "D3D9 widget has been enabled")
endif()
else()
message(STATUS "DirectX widget has been disabled")
message(STATUS "DirectX widgets have been disabled (DirectX not found)")
endif()
endif()
@ -491,12 +499,19 @@ if(MW_BUILD_VULKAN)
endif()
endif()
if(MW_BUILD_DIRECTX)
list(APPEND LIBRARIES ${DIRECTX_D3DX9_LIBRARIES})
if(MW_BUILD_D3D8)
target_compile_definitions(
Mw
PRIVATE
MW_DIRECTX
PUBLIC
MW_DIRECTX8
)
endif()
if(MW_BUILD_D3D9)
target_compile_definitions(
Mw
PUBLIC
MW_DIRECTX9
)
endif()

4
NTMakefile generated
View file

@ -2,7 +2,7 @@ CC = cl /TC /c /nologo
LD = link /nologo
!if [where d3d9.h >nul 2>nul]
!if [for /f "delims=" %P in ('where d3d9.h 2^>nul') do @echo DX9_FLAGS = /DMW_DIRECTX /I"%~dpP">dx9flags.mk]
!if [for /f "delims=" %P in ('where d3d9.h 2^>nul') do @echo DX9_FLAGS = /DMW_DIRECTX9 /I"%~dpP">dx9flags.mk]
!endif
!else
!if [echo DX9_FLAGS =>dx9flags.mk]
@ -14,7 +14,7 @@ LD = link /nologo
DX9_FLAGS =
!endif
MW_CFLAGS = /Iinclude /Iexternal\libz\include /D_MILSKO /D_MILSKO_BUILD /DUSE_GDI /DUSE_STB_IMAGE /DSTBI_NO_SIMD /DUSE_GDI_TEXT /DMW_OPENGL $(DX9_FLAGS)
MW_CFLAGS = /Iinclude /Iexternal\libz\include /D_MILSKO /D_MILSKO_BUILD /DUSE_GDI /DUSE_STB_IMAGE /DSTBI_NO_SIMD /DUSE_GDI_TEXT /DMW_OPENGL $(DX8_FLAGS) $(DX9_FLAGS)
MW_LDFLAGS = /DLL
EXE_CFLAGS = /Iinclude
EXE_LDFLAGS =

2
WatMakefile generated
View file

@ -1,7 +1,7 @@
CC = wcc386 -bt=nt -q
LD = wlink option quiet
MW_CFLAGS = -bd -i=include -i=external/libz/include -d_MILSKO -d_MILSKO_BUILD -dUSE_GDI -dUSE_STB_IMAGE -dSTBI_NO_SIMD -dUSE_GDI_TEXT -dMW_OPENGL -dMW_DIRECTX
MW_CFLAGS = -bd -i=include -i=external/libz/include -d_MILSKO -d_MILSKO_BUILD -dUSE_GDI -dUSE_STB_IMAGE -dSTBI_NO_SIMD -dUSE_GDI_TEXT -dMW_OPENGL -dMW_DIRECTX8 -dMW_DIRECTX9
MW_LDFLAGS = system nt_dll
EXE_CFLAGS = -i=include
EXE_LDFLAGS = system nt

View file

@ -5,8 +5,9 @@ endif()
if(${MW_TRY_VULKAN})
add_subdirectory(vkdemos)
endif()
if(WIN32)
if(${MW_TRY_DIRECTX})
if(${MW_TRY_D3D8} OR ${MW_BUILD_D3D8})
add_subdirectory(dxdemos)
endif()
endif()

View file

@ -8,17 +8,16 @@ include(${CMAKE_CURRENT_SOURCE_DIR}/../../resource/FindDirectX.cmake)
if(${DIRECTX_FOUND})
foreach(PATH IN LISTS EXAMPLES_DIRECTX_SOURCES)
get_filename_component(TARGET ${PATH} NAME_WE)
add_executable(${TARGET} MACOSX_BUNDLE ${PATH})
add_executable(${TARGET} ${PATH})
target_include_directories(
${TARGET}
PRIVATE
${DIRECTX_INCLUDE_DIRS}
)
target_link_libraries(
${TARGET}
PRIVATE
Mw
${DIRECTX_D3DX9_LIBRARIES}
)
${TARGET}
PRIVATE
Mw
)
endforeach()
endif()

91
examples/dxdemos/d3d8.c Normal file
View file

@ -0,0 +1,91 @@
/*
* Adapted from:
* https://web.archive.org/web/20211126225651/https://www.codeguru.com/multimedia/using-direct3d8-the-basics/
*/
#include <Mw/Milsko.h>
#include <Mw/Widget/D3D8.h>
MwWidget window, d3d8;
LPDIRECT3D8 d3d;
LPDIRECT3DDEVICE8 d3ddev;
LPDIRECT3DVERTEXBUFFER8 v_buffer;
struct CUSTOMVERTEX {
FLOAT x, y, z, rhw; // from the D3DFVF_XYZRHW flag
DWORD color; // from the D3DFVF_DIFFUSE flag
};
#define CUSTOMFVF (D3DFVF_XYZRHW | D3DFVF_DIFFUSE)
static void MWAPI draw(MwWidget handle, void* user, void* client) {
// clear the window to a deep blue
d3ddev->lpVtbl->Clear(d3ddev, 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 40, 100), 1.0f, 0);
d3ddev->lpVtbl->BeginScene(d3ddev); // begins the 3D scene
// select which vertex format we are using
d3ddev->lpVtbl->SetVertexShader(d3ddev, CUSTOMFVF);
// select the vertex buffer to display
d3ddev->lpVtbl->SetStreamSource(d3ddev, 0, v_buffer, sizeof(struct CUSTOMVERTEX));
// // copy the vertex buffer to the back buffer
d3ddev->lpVtbl->DrawPrimitive(d3ddev, D3DPT_TRIANGLELIST, 0, 1);
d3ddev->lpVtbl->EndScene(d3ddev); // ends the 3D scene
d3ddev->lpVtbl->Present(d3ddev, NULL, NULL, NULL, NULL); // displays the created frame
}
int main() {
BYTE* pVoid;
MwLibraryInit();
window = MwCreateWidget(MwWindowClass, NULL, NULL, MwDEFAULT, MwDEFAULT, 1024, 768);
d3d8 = MwCreateWidget(MwD3D8Class, NULL, window, (1024 - 800) / 2, (768 - 600) / 2, 800, 600);
d3d = MwDirectXGetD3D8(d3d8);
d3ddev = MwDirectXGetD3Dev8(d3d8);
// create three vertices using the CUSTOMVERTEX struct built earlier
struct CUSTOMVERTEX vertices[] =
{
{
400.0f,
0.0f,
0.5f,
1.0f,
D3DCOLOR_XRGB(0, 0, 255),
},
{
800.0f,
600.0f,
0.5f,
1.0f,
D3DCOLOR_XRGB(0, 255, 0),
},
{
0.0f,
600.0f,
0.5f,
1.0f,
D3DCOLOR_XRGB(255, 0, 0),
},
};
d3ddev->lpVtbl->CreateVertexBuffer(d3ddev,
3 * sizeof(struct CUSTOMVERTEX),
0,
CUSTOMFVF,
D3DPOOL_MANAGED,
&v_buffer);
v_buffer->lpVtbl->Lock(v_buffer, 0, 0, (BYTE**)&pVoid, 0); // lock the vertex buffer
memcpy(pVoid, vertices, sizeof(vertices)); // copy the vertices to the locked buffer
v_buffer->lpVtbl->Unlock(v_buffer); // unlock the vertex buffer
MwAddUserHandler(window, MwNtickHandler, draw, NULL);
MwLoop(window);
}

View file

@ -4,9 +4,9 @@
* http://www.directxtutorial.com/Lesson.aspx?lessonid=9-4-4
*/
#include <Mw/Milsko.h>
#include <Mw/Widget/DirectX.h>
#include <Mw/Widget/D3D9.h>
MwWidget window, d3d9;
MwWidget window, d3d8;
LPDIRECT3D9 d3d;
LPDIRECT3DDEVICE9 d3ddev;
LPDIRECT3DVERTEXBUFFER9 v_buffer;
@ -38,14 +38,16 @@ static void MWAPI draw(MwWidget handle, void* user, void* client) {
}
int main() {
VOID* pVoid;
MwLibraryInit();
window = MwCreateWidget(MwWindowClass, NULL, NULL, MwDEFAULT, MwDEFAULT, 1024, 768);
d3d9 = MwCreateWidget(MwD3D9Class, NULL, window, (1024 - 800) / 2, (768 - 600) / 2, 800, 600);
d3d8 = MwCreateWidget(MwD3D9Class, NULL, window, (1024 - 800) / 2, (768 - 600) / 2, 800, 600);
d3d = MwDirectXGetD3D9(d3d9);
d3ddev = MwDirectXGetD3Dev9(d3d9);
d3d = MwDirectXGetD3D9(d3d8);
d3ddev = MwDirectXGetD3Dev9(d3d8);
// create three vertices using the CUSTOMVERTEX struct built earlier
struct CUSTOMVERTEX vertices[] =
@ -81,8 +83,6 @@ int main() {
&v_buffer,
NULL);
VOID* pVoid; // the void pointer
v_buffer->lpVtbl->Lock(v_buffer, 0, 0, (void**)&pVoid, 0); // lock the vertex buffer
memcpy(pVoid, vertices, sizeof(vertices)); // copy the vertices to the locked buffer
v_buffer->lpVtbl->Unlock(v_buffer); // unlock the vertex buffer

55
include/Mw/Widget/D3D8.h Normal file
View file

@ -0,0 +1,55 @@
/*!
* @file Mw/Widget/D3D8.h
* @brief D3D8 widget.
* @warning Only avaliable on Windows.
*/
#ifndef __MW_WIDGET_D3D8_H__
#define __MW_WIDGET_D3D8_H__
#include <Mw/Core.h>
#include <Mw/MachDep.h>
#include <Mw/TypeDefs.h>
#if !defined(MW_D3D8_NO_INCLUDE)
/* https://github.com/microsoft/Windows-classic-samples/issues/317 */
#if defined(__MINGW32__) || defined(__MINGW64__)
#define NTDDI_VERSION 0x07000000
#define _WIN32_WINNT 0x0A00
#endif
#endif
#ifndef _WIN32
#error D3D8 widget only avaliable for Win32 backends
#else
#ifdef MW_DIRECTX8
#include <d3d8.h>
#endif
#endif
/*!
* @brief D3D8 widget class
*/
MWDECL MwClass MwD3D8Class;
#ifdef __cplusplus
extern "C" {
#endif
MwInline LPDIRECT3D8 MwDirectXGetD3D8(MwWidget handle) {
LPDIRECT3D8 out = NULL;
MwVaWidgetExecute(handle, "mwDirectXGetD3D8", &out, NULL);
return out;
};
MwInline LPDIRECT3DDEVICE8 MwDirectXGetD3Dev8(MwWidget handle) {
LPDIRECT3DDEVICE8 out = NULL;
MwVaWidgetExecute(handle, "mwDirectXGetD3Dev8", &out);
return out;
};
#ifdef __cplusplus
}
#endif
#endif

View file

@ -3,27 +3,28 @@
* @brief DirectX widget.
* @warning Only avaliable on Windows.
*/
#ifndef __MW_WIDGET_DIRECTX_H__
#define __MW_WIDGET_DIRECTX_H__
#ifndef __MW_WIDGET_D3D9_H__
#define __MW_WIDGET_D3D9_H__
#include <Mw/Core.h>
#include <Mw/MachDep.h>
#include <Mw/TypeDefs.h>
#if !defined(MW_DIRECTX_NO_INCLUDE)
#if !defined(MW_D3D9_NO_INCLUDE)
/* https://github.com/microsoft/Windows-classic-samples/issues/317 */
#if defined(__MINGW32__) || defined(__MINGW64__)
#define NTDDI_VERSION 0x07000000
#define _WIN32_WINNT 0x0A00
#endif
#include <d3d9.h>
#endif
#ifndef _WIN32
#error DirectX widget only avaliable for Win32 backends
#error D3D9 widget only avaliable for Win32 backends
#else
#ifdef MW_DIRECTX9
#include <d3d9.h>
#endif
#endif
#endif
/*!

107
src/widget/d3d8.c Normal file
View file

@ -0,0 +1,107 @@
#include <Mw/Milsko.h>
#ifndef MW_DIRECTX8
#define MW_DIRECTX8_NO_INCLUDE
MWDECL MwClass MwDX8Class;
MwClass MwDX8Class = NULL;
#else
#include <Mw/Widget/D3D8.h>
typedef struct gdid3d8 {
void* d3d8dll;
IDirect3D8* (*Direct3DCreate8)(UINT sdk_version);
LPDIRECT3D8 d3d; // the pointer to our Direct3D interface
LPDIRECT3DDEVICE8 d3ddev; // the pointer to the device class\
} gdid3d8_t;
static int wcreate_d3d8(MwWidget handle) {
void* r = NULL;
MwWidget w = handle;
gdid3d8_t* o = malloc(sizeof(gdid3d8_t));
D3DPRESENT_PARAMETERS d3dpp;
D3DDISPLAYMODE dispMode;
o->d3d8dll = LoadLibrary("d3d8.dll");
if(!o->d3d8dll) {
MessageBox(NULL, "d3d8.dll not found! Is DirectX8 installed?", "Error", MB_OK);
ExitProcess(-1);
}
o->Direct3DCreate8 = (void*)GetProcAddress(o->d3d8dll, "Direct3DCreate8");
if(!o->Direct3DCreate8) {
MessageBox(NULL, "Direct3DCreate8 not found! Is DirectX8 installed properly?", "Error", MB_OK);
ExitProcess(-1);
}
o->d3d = o->Direct3DCreate8(D3D_SDK_VERSION);
o->d3d->lpVtbl->GetAdapterDisplayMode(o->d3d, D3DADAPTER_DEFAULT, &dispMode);
ZeroMemory(&d3dpp, sizeof(d3dpp));
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.hDeviceWindow = handle->lowlevel->gdi.hWnd;
d3dpp.BackBufferFormat = dispMode.Format;
d3dpp.EnableAutoDepthStencil = TRUE;
d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
// create a device class using this information and information from the d3dpp stuct
o->d3d->lpVtbl->CreateDevice(o->d3d,
D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
handle->lowlevel->gdi.hWnd,
D3DCREATE_MIXED_VERTEXPROCESSING,
&d3dpp,
&o->d3ddev);
o->d3ddev->lpVtbl->SetRenderState(o->d3ddev, D3DRS_LIGHTING, FALSE);
handle->internal = o;
return 0;
}
static void destroy_d3d8(MwWidget handle) {
MwWidget w = handle;
gdid3d8_t* o = handle->internal;
o->d3ddev->lpVtbl->Release(o->d3ddev); // close and release the 3D device
o->d3d->lpVtbl->Release(o->d3d); // close and release Direct3D
free(handle->internal);
}
static void func_handler_d3d8(MwWidget handle, const char* name, void* out,
va_list va) {
gdid3d8_t* o = handle->internal;
if(strcmp(name, "mwDirectXGetD3D8") == 0) {
*(LPDIRECT3D8*)out = o->d3d;
}
if(strcmp(name, "mwDirectXGetD3Dev8") == 0) {
*(LPDIRECT3DDEVICE8*)out = o->d3ddev;
}
}
MwClassRec MwDX8ClassRec = {wcreate_d3d8, /* create */
destroy_d3d8, /* destroy */
NULL, /* draw */
NULL, /* click */
NULL, /* parent_resize */
NULL, /* prop_change */
NULL, /* mouse_move */
NULL, /* mouse_up */
NULL, /* mouse_down */
NULL, /* key */
func_handler_d3d8, /* execute */
NULL, /* tick */
NULL, /* resize */
NULL, /* children_update */
NULL, /* children_prop_change */
NULL, /* clipboard */
NULL, /* props_change */
NULL, NULL, NULL};
MwClass MwD3D8Class = &MwDX8ClassRec;
#endif

View file

@ -1,12 +1,12 @@
#include <Mw/Milsko.h>
#ifndef MW_DIRECTX
#define MW_DIRECTX_NO_INCLUDE
#ifndef MW_DIRECTX9
#define MW_DIRECTX9_NO_INCLUDE
MWDECL MwClass MwDX9Class;
MwClass MwDX9Class = NULL;
#else
#include <Mw/Widget/DirectX.h>
#include <Mw/Widget/D3D9.h>
typedef struct gdid3d9 {
void* d3d9dll;
@ -17,7 +17,7 @@ typedef struct gdid3d9 {
} gdid3d9_t;
static int wcreate(MwWidget handle) {
static int wcreate_d3d9(MwWidget handle) {
void* r = NULL;
MwWidget w = handle;
gdid3d9_t* o = malloc(sizeof(gdid3d9_t));
@ -52,7 +52,7 @@ static int wcreate(MwWidget handle) {
return 0;
}
static void destroy(MwWidget handle) {
static void destroy_d3d9(MwWidget handle) {
MwWidget w = handle;
gdid3d9_t* o = handle->internal;
@ -62,7 +62,7 @@ static void destroy(MwWidget handle) {
free(handle->internal);
}
static void func_handler(MwWidget handle, const char* name, void* out,
static void func_handler_d3d9(MwWidget handle, const char* name, void* out,
va_list va) {
gdid3d9_t* o = handle->internal;
@ -74,8 +74,8 @@ static void func_handler(MwWidget handle, const char* name, void* out,
}
}
MwClassRec MwDX9ClassRec = {wcreate, /* create */
destroy, /* destroy */
MwClassRec MwDX9ClassRec = {wcreate_d3d9, /* create */
destroy_d3d9, /* destroy */
NULL, /* draw */
NULL, /* click */
NULL, /* parent_resize */
@ -84,7 +84,7 @@ MwClassRec MwDX9ClassRec = {wcreate, /* create */
NULL, /* mouse_up */
NULL, /* mouse_down */
NULL, /* key */
func_handler, /* execute */
func_handler_d3d9, /* execute */
NULL, /* tick */
NULL, /* resize */
NULL, /* children_update */

View file

@ -42,10 +42,28 @@ sub cobjs {
return $r;
}
sub dx8_detect_block {
return <<'EOF';
!if [where d3d8.h >nul 2>nul]
!if [for /f "delims=" %P in ('where d3d8.h 2^>nul') do @echo DX8_FLAGS = /DMW_DIRECTX8 /I"%~dpP">dx8flags.mk]
!endif
!else
!if [echo DX8_FLAGS =>dx9flags.mk]
!endif
!endif
!if exist("dx8flags.mk")
!include "dx8flags.mk"
!else
DX8_FLAGS =
!endif
EOF
}
sub dx9_detect_block {
return <<'EOF';
!if [where d3d9.h >nul 2>nul]
!if [for /f "delims=" %P in ('where d3d9.h 2^>nul') do @echo DX9_FLAGS = /DMW_DIRECTX /I"%~dpP">dx9flags.mk]
!if [for /f "delims=" %P in ('where d3d9.h 2^>nul') do @echo DX9_FLAGS = /DMW_DIRECTX9 /I"%~dpP">dx9flags.mk]
!endif
!else
!if [echo DX9_FLAGS =>dx9flags.mk]
@ -82,6 +100,8 @@ sub generate {
my $lib = "";
my $c_dllout = "";
my $c_dllafter = "";
my $dx8_flags = "";
my $dx8_block = "";
my $dx9_flags = "";
my $dx9_block = "";
@ -108,9 +128,8 @@ sub generate {
$inc = "/I";
$dll = "/DLL";
# DX9 headers aren't part of every MSVC/Windows SDK install, so probe
# PATH for a d3d9.h at build time (on the machine actually running
# nmake) rather than baking in a yes/no here.
$dx8_flags = "\$(DX8_FLAGS)";
$dx8_block = dx8_detect_block();
$dx9_flags = "\$(DX9_FLAGS)";
$dx9_block = dx9_detect_block();
}
@ -135,7 +154,8 @@ sub generate {
$needlibs = "${lib}clib3r.lib";
$c_dllout = "option implib=src${dir}Mw.lib";
$dx9_flags = "${def}MW_DIRECTX";
$dx8_flags = "${def}MW_DIRECTX8";
$dx9_flags = "${def}MW_DIRECTX9";
}
open(OUT, ">", $output);
@ -147,7 +167,7 @@ sub generate {
print(OUT "\n");
}
print(OUT
"MW_CFLAGS = ${cdll} ${inc}include ${inc}external${dir}libz${dir}include ${def}_MILSKO ${def}_MILSKO_BUILD ${def}USE_GDI ${def}USE_STB_IMAGE ${def}STBI_NO_SIMD ${def}USE_GDI_TEXT ${def}MW_OPENGL ${dx9_flags}\n"
"MW_CFLAGS = ${cdll} ${inc}include ${inc}external${dir}libz${dir}include ${def}_MILSKO ${def}_MILSKO_BUILD ${def}USE_GDI ${def}USE_STB_IMAGE ${def}STBI_NO_SIMD ${def}USE_GDI_TEXT ${def}MW_OPENGL ${dx8_flags} ${dx9_flags}\n"
);
print(OUT "MW_LDFLAGS = $dll\n");
print(OUT "EXE_CFLAGS = ${inc}include\n");