GithubHelp home page GithubHelp logo

egui-d3d9's Introduction

Hi, I'm unknowntrojan

I go by he/him, am 20 years old and currently live in Germany.

I love reverse engineering, gamehacking, organic chemistry, pharmacology, the Rust programming language, owls, cats and evergreens.

I have a blog at unknowntrojan.win, I intend to make use of it more in the future. Right now, you can find a post about me holding my first talk there.

If you're looking for slides or information about my talks, see here.

You can find me here:

Platform Username
Discord unknowntrojan
Matrix @unknowntrojan:unknowntrojan.win

egui-d3d9's People

Contributors

bogadana avatar cestef avatar pvolok avatar tobii-dev avatar unknowntrojan avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

egui-d3d9's Issues

How to handle IDirect3DDevice9::Reset(...)? (for switching between Fullscreen and Windowed)

When switching between full-screen and windowed mode inside my d3d9 app (pressing AltโŽ), it crashes if I'm drawing egui stuff. This makes sense, as per the docs: https://learn.microsoft.com/en-us/windows/win32/api/d3d9/nf-d3d9-idirect3ddevice9-reset

Calling IDirect3DDevice9::Reset causes all texture memory surfaces to be lost, managed textures to be flushed from video memory, and all state information to be lost. Before calling the IDirect3DDevice9::Reset method for a device, an application should release any explicit render targets, depth stencil surfaces, additional swap chains, state blocks, and D3DPOOL_DEFAULT resources associated with the device.

Pixel shaders and vertex shaders survive IDirect3DDevice9::Reset calls for Direct3D 9. They do not need to be re-created explicitly by the application.

It would be nice if there was a way to handle this on the egui side. I tried looking for examples on how other egui-backend crates handle this, but I didn't find anything simple. I found this: https://github.com/derivator/egui_vulkano/blob/41362f02897ca63fa6f26fb3a9b093b9973d839a/examples/example.rs#L278 on the egui_vulkano back-end, and this https://github.com/MatchaChoco010/egui-winit-ash-integration/blob/540a0bb2375991139312d79d691c308b166bf110/examples/example/main.rs#L1827 on egui-winit-ash-integration, but they're not really the same.

Here is an example on how the directx9 imgui back-end handles this:
https://github.com/ocornut/imgui/blob/956a1a17fb8f8d72726cad92f203cdd57470eae7/examples/example_win32_directx9/main.cpp#L165

They invalidate the textures, call device.Reset(...), and create it again.

It would be useful if this crate had something similar, like

impl<T> EguiDx9<T> {
    /// Call me before my IDirect3DDevice9 gets Reset(...)!
    pub fn invalidate(&mut self, dev: &IDirect3DDevice9, ppresentationparameters: &D3DPRESENT_PARAMETERS) {
        self.drop_stuff_that_will_be_flushed_by_the_reset();
        self.try_to_use_new_window(&ppresentationparameters);
    }
}

Is this possible, or should I handle the full-screen switching a different way?

Name of detour crate changed

Hi, I'm the maintainer of the detour fork!

I just renamed the repo/crate, so it's going to break your project, I'm really sorry about that.
But it's now on crates.io now here, so you can add it to your Cargo.toml!

retour = "0.1.0"

Figured I send out issues to the repos using it to avoid any confusion/frustration. Again, sorry about that, but this makes things a lot easier going forward.

Happy hacking! ๐Ÿ˜„

Panicked at "unable to create temporary texture"

Hi, when I try to call

egui_d3d9::app::EguiDx9::present(&mut self, dev: &IDirect3DDevice9)

I get this error:

thread '<unnamed>' panicked at 'unable to create temporary texture: Error { code: HRESULT(0x8876086C), message: "" }'
Full stacktrace:

17:51:53 [ERROR] thread '<unnamed>' panicked at 'unable to create temporary texture: Error { code: HRESULT(0x8876086C), message: "" }': C:\Users\tobii\.cargo\git\checkouts\egui-d3d9-6163636d01cb9325\2fa7541\egui-d3d9\src\texman.rs:240
   0: backtrace::backtrace::trace<backtrace::capture::impl$1::create::closure_env$0>
             at C:\Users\tobii\.cargo\registry\src\index.crates.io-6f17d22bba15001f\backtrace-0.3.67\src\backtrace\mod.rs:53
   1: backtrace::capture::Backtrace::create
             at C:\Users\tobii\.cargo\registry\src\index.crates.io-6f17d22bba15001f\backtrace-0.3.67\src\capture.rs:176
   2: backtrace::capture::Backtrace::new
             at C:\Users\tobii\.cargo\registry\src\index.crates.io-6f17d22bba15001f\backtrace-0.3.67\src\capture.rs:140
   3: backtrace::capture::impl$8::default
             at C:\Users\tobii\.cargo\registry\src\index.crates.io-6f17d22bba15001f\backtrace-0.3.67\src\capture.rs:410
   4: alloc::vec::Vec::append_elements
             at /rustc/87b1f891ea76713462cfc5a15137a8fe2b24ecc2/library\alloc\src\vec\mod.rs:1942
   5: alloc::vec::spec_extend::impl$4::spec_extend
             at /rustc/87b1f891ea76713462cfc5a15137a8fe2b24ecc2/library\alloc\src\vec\spec_extend.rs:55
   6: alloc::vec::Vec::extend_from_slice
             at /rustc/87b1f891ea76713462cfc5a15137a8fe2b24ecc2/library\alloc\src\vec\mod.rs:2386
   7: alloc::string::String::push_str
             at /rustc/87b1f891ea76713462cfc5a15137a8fe2b24ecc2/library\alloc\src\string.rs:926
   8: alloc::string::impl$65::write_str
             at /rustc/87b1f891ea76713462cfc5a15137a8fe2b24ecc2/library\alloc\src\string.rs:2861
   9: core::fmt::impl$0::write_str<alloc::string::String>
             at /rustc/87b1f891ea76713462cfc5a15137a8fe2b24ecc2/library\core\src\fmt\mod.rs:199
  10: core::fmt::write
             at /rustc/87b1f891ea76713462cfc5a15137a8fe2b24ecc2/library\core\src\fmt\mod.rs:1118
  11: core::fmt::Formatter::write_fmt
             at /rustc/87b1f891ea76713462cfc5a15137a8fe2b24ecc2/library\core\src\fmt\mod.rs:1548
  12: windows::core::strings::hstring::impl$9::fmt
             at C:\Users\tobii\.cargo\registry\src\index.crates.io-6f17d22bba15001f\windows-0.48.0\src\core\strings\hstring.rs:149
  13: windows::core::strings::hstring::HSTRING::is_empty
             at C:\Users\tobii\.cargo\registry\src\index.crates.io-6f17d22bba15001f\windows-0.48.0\src\core\strings\hstring.rs:19
  14: core::fmt::builders::impl$3::finish::closure$0
             at /rustc/87b1f891ea76713462cfc5a15137a8fe2b24ecc2/library\core\src\fmt\builders.rs:226
  15: core::result::Result::and_then
             at /rustc/87b1f891ea76713462cfc5a15137a8fe2b24ecc2/library\core\src\result.rs:1319
  16: core::fmt::builders::DebugStruct::finish
             at /rustc/87b1f891ea76713462cfc5a15137a8fe2b24ecc2/library\core\src\fmt\builders.rs:225
  17: core::ptr::drop_in_place<windows::core::strings::hstring::HSTRING>
             at /rustc/87b1f891ea76713462cfc5a15137a8fe2b24ecc2\library\core\src\ptr\mod.rs:491
  18: core::fmt::impl$53::fmt<dyn$<core::fmt::Debug> >
             at /rustc/87b1f891ea76713462cfc5a15137a8fe2b24ecc2/library\core\src\fmt\mod.rs:2258
  19: core::fmt::rt::Argument::fmt
             at /rustc/87b1f891ea76713462cfc5a15137a8fe2b24ecc2/library\core\src\fmt\rt.rs:138
  20: core::fmt::write
             at /rustc/87b1f891ea76713462cfc5a15137a8fe2b24ecc2/library\core\src\fmt\mod.rs:1094
  21: core::fmt::Write::write_fmt
             at /rustc/87b1f891ea76713462cfc5a15137a8fe2b24ecc2/library\core\src\fmt\mod.rs:192
  22: std::panicking::begin_panic_handler::impl$0::fill::closure$0
             at /rustc/87b1f891ea76713462cfc5a15137a8fe2b24ecc2/library\std\src\panicking.rs:544
  23: core::option::Option::get_or_insert_with
             at /rustc/87b1f891ea76713462cfc5a15137a8fe2b24ecc2/library\core\src\option.rs:1651
  24: std::panicking::begin_panic_handler::PanicPayload::fill
             at /rustc/87b1f891ea76713462cfc5a15137a8fe2b24ecc2/library\std\src\panicking.rs:542
  25: std::panicking::begin_panic_handler::impl$1::get
             at /rustc/87b1f891ea76713462cfc5a15137a8fe2b24ecc2/library\std\src\panicking.rs:560
  26: <unknown>
  27: windows::core::error::GetErrorInfo
             at C:\Users\tobii\.cargo\registry\src\index.crates.io-6f17d22bba15001f\windows-0.48.0\src\core\error.rs:154
  28: std::panicking::begin_panic_handler::closure$0
             at /rustc/87b1f891ea76713462cfc5a15137a8fe2b24ecc2/library\std\src\panicking.rs:582
  29: <unknown>
  30: enum2$<core::result::Result<tuple$<>,windows::core::error::Error> >::expect<tuple$<>,windows::core::error::Error>
             at /rustc/87b1f891ea76713462cfc5a15137a8fe2b24ecc2\library\core\src\result.rs:1033
  31: egui_d3d9::texman::create_temporary_texture
             at C:\Users\tobii\.cargo\git\checkouts\egui-d3d9-6163636d01cb9325\2fa7541\egui-d3d9\src\texman.rs:240
  32: egui_d3d9::texman::new_texture_from_buffer
             at C:\Users\tobii\.cargo\git\checkouts\egui-d3d9-6163636d01cb9325\2fa7541\egui-d3d9\src\texman.rs:263
  33: egui_d3d9::texman::TextureManager::create_new_texture
             at C:\Users\tobii\.cargo\git\checkouts\egui-d3d9-6163636d01cb9325\2fa7541\egui-d3d9\src\texman.rs:88
  34: egui_d3d9::texman::impl$1::process_set_deltas::closure$0
             at C:\Users\tobii\.cargo\git\checkouts\egui-d3d9-6163636d01cb9325\2fa7541\egui-d3d9\src\texman.rs:58
  35: egui_d3d9::texman::TextureManager::process_set_deltas
             at C:\Users\tobii\.cargo\git\checkouts\egui-d3d9-6163636d01cb9325\2fa7541\egui-d3d9\src\texman.rs:41
  36: SE_GetProcAddressForCaller
  37: MsgWaitForMultipleObjectsEx
  38: NtUserSetWindowLong
  39: <unknown>

The error seems to come from here: https://github.com/unknowntrojan/egui-d3d9/blob/b28a661163db170ebd996be59b9b87e267406e89/egui-d3d9/src/texman.rs#LL241C21-L241C21

But I have no idea why that would fail, or how to debug it.

According to the docs, at https://learn.microsoft.com/en-us/windows/win32/api/d3d9/nf-d3d9-idirect3ddevice9-createtexture

In Windows Vista CreateTexture can create a texture from a system memory pointer allowing the application >more flexibility over the use, allocation and deletion of the system memory. For example, an application >could pass a GDI system memory bitmap pointer and get a Direct3D texture interface around it. Using a system >memory pointer with CreateTexture has the following restrictions:

  • The pitch of the texture must be equal to the width multiplied by the number of bytes per pixel.
  • Only textures with a single mipmap level are supported. The Levels argument must be 1.
  • The Pool argument must be D3DPOOL_SYSTEMMEM.
  • The pSharedHandle argument must be a valid pointer to a buffer that can hold the system memory point; >*pSharedHandle must be a valid pointer to system memory with a size in bytes of texture width * texture >height * bytes per pixel of the texture format.

But I think that is all correct in this case.

Here is the rest of the code:

use egui::Context;
use egui_d3d9::EguiDx9;
use std::sync::Once;
use windows::Win32::{
	Foundation::{HWND, LPARAM, LRESULT, WPARAM},
	Graphics::Direct3D9::IDirect3DDevice9,
	UI::WindowsAndMessaging::{CallWindowProcW, SetWindowLongPtrA, GWLP_WNDPROC, WNDPROC},
};

static mut APP: Option<EguiDx9<i32>> = None;

/// Original WNDPROC, so we can do CallWindowProcW(...) with it
static mut FN_ORG_WNDPROC: WNDPROC = None;

fn hello_ui(ctx: &Context, _frame: &mut i32) {
	log::trace!("I made it to hello_ui(..., _frame={_frame})"); // it reaches this line...
	egui::containers::Window::new("Main").show(ctx, |ui| {
		ctx.settings_ui(ui);
		ui.label("Hello world!");
		//ui.label(egui::RichText::new("Hello world").color(egui::Color32::WHITE));
	});
	log::trace!("I made past egui::containers::Window::new(...)!"); // and this one... But after that it crashes?
}

/// draw() gets called right before the original IDirect3DDevice9::Present() is called.
pub fn draw(dev: &IDirect3DDevice9, hwnd: HWND) {
	log::trace!("I made it to draw({hwnd:?})");
	static INIT: Once = Once::new();
	INIT.call_once(move || {
		unsafe {
			APP = Some(EguiDx9::init(dev, hwnd, hello_ui, 0, true));
			FN_ORG_WNDPROC = std::mem::transmute(SetWindowLongPtrA(
				hwnd,
				GWLP_WNDPROC,
				hk_wnd_proc as usize as _,
			));
		};
	});
	let app = unsafe { APP.as_mut().unwrap() };
	app.present(dev); //Crashes
	log::trace!("I made it past app.present(dev))"); // doesnt reach this line I think
}

unsafe extern "stdcall" fn hk_wnd_proc(
	hwnd: HWND,
	msg: u32,
	wparam: WPARAM,
	lparam: LPARAM,
) -> LRESULT {
	//This is okay because APP gets set before hooking this WNDPROC
	APP.as_mut().unwrap().wnd_proc(msg, wparam, lparam);
	CallWindowProcW(FN_ORG_WNDPROC, hwnd, msg, wparam, lparam)
}

[EDIT] Full code here: https://github.com/tobii-dev/blur-hooks-rs/blob/2f96fcb9d54a2dbfae2aca9258f4ccf5e62aefbb/src/gui/console.rs#L40

In the trace log file, I can see all the traces hit, except "I made it past app.present(dev))".
Any help testing or debugging this would be ๐Ÿ’ฏ

Exposing ui_state?

Hello! I can add this change myself - but I'd rather remain upstream. What do you think about implementing an EguiDx9 ui_state getter? Is this antithetical to the design, or something?

Incorrect rendering of text and checkbox

Thank you for this library. I am trying to use it to render overlay in Lineage 2.

There seem to be issues with rendering. I rendered the same app using egui-glow (winit window) and egui-d3d9.

Left: egui-glow
Right: egui-d3d9
Untitled

Do you have any idea what might cause this problem?

Can I Init with c++ d3d9 device pointer and HWND

I already got the d3d9 device pointer and game's window HWND, and event hooked by c++, now I called c++ library to get d3d9 device and hwnd by ffi, c++ api returned void*, and received by rust via *mut c_void.

I get the debug log like this:

IDirect3DDevice9(IUnknown(0x56610d8)), wnd: HWND(2823448)

but game display c++ runtime error.

can I call the EguiDx9's pre_preset and present in my hooked functions ?

broken build

cargo build
warning: associated function from_raw is never used
--> egui-opengl-internal\src\painter.rs:61:12
|
61 | pub fn from_raw(id: u32) -> Self {
| ^^^^^^^^
|
= note: #[warn(dead_code)] on by default

warning: associated function new_opengl_texture is never used
--> egui-opengl-internal\src\painter.rs:212:12
|
212 | pub fn new_opengl_texture(&mut self, openl_id: u32) -> egui::TextureId {
| ^^^^^^^^^^^^^^^^^^

warning: associated function new_user_texture is never used
--> egui-opengl-internal\src\painter.rs:220:12
|
220 | pub fn new_user_texture(
| ^^^^^^^^^^^^^^^^

warning: associated function update_user_texture_data is never used
--> egui-opengl-internal\src\painter.rs:245:12
|
245 | pub fn update_user_texture_data(&mut self, texture_id: &egui::TextureId, pixels: &[Color32]) {
| ^^^^^^^^^^^^^^^^^^^^^^^^

warning: egui-opengl-internal (lib) generated 4 warnings
Compiling retour v0.1.0
error[E0554]: #![feature] may not be used on the stable release channel
--> C:\Users\icetrix.cargo\registry\src\github.com-1ecc6299db9ec823\retour-0.1.0\src\lib.rs:4:3
|
4 | feature(unboxed_closures, abi_thiscall, tuple_trait)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0554]: #![feature] may not be used on the stable release channel
--> C:\Users\icetrix.cargo\registry\src\github.com-1ecc6299db9ec823\retour-0.1.0\src\lib.rs:4:43
|
4 | feature(unboxed_closures, abi_thiscall, tuple_trait)
| ^^^^^^^^^^^

For more information about this error, try rustc --explain E0554.
error: could not compile retour due to 2 previous errors
PS C:\Users\icetrix\egui-opengl-internal>

what do?

Input state seems broken

When getting

ui.input(|input| input.keys_down.clone());

The keys returned do not match with the ones pressed. I am using a QWERTZ keyboard (Swiss French layout). The "mapping" that is returned is the following:

Q => O
W => U
E => C
R => P
T => R
Z => X

Any similar known issues ? I can also provide more information on the problem if needed !

Feathering is broken

Feathering seems to be broken in this implementation. It makes everything appear jagged like here:


My guess is something with texture sampling or some antialiasing we're doing? or the 0.5 pixel offset we apply to everything afaik?

I need to investigate this further, but if you know what the problem is, just comment on the issue.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.