Go to bottom

getting processes with 3d contexts

category: general [glöplog]
hello, i would like to get all the process that hold a 3d context on win32.

basically the way, that fraps does it when it overlays the framerate on the 3d canvas of any application.

so, how can i get a list of all the processes, that do either OpenGL or DirectX rendering? thanks!
added on the 2007-10-22 20:08:43 by zatom zatom
I'm guessing it involves hooking a few functions in each of the two APIs. No idea how to do that in Windows. Alternatively you could probably read a list of allocated resources for every process (like what the SysInternals tools do), but that wouldn't notify you when surfaces are refreshed, or let you manipulate the output.

Also, I'm the last person you should ask.
added on the 2007-10-22 20:18:39 by doomdoom doomdoom
emzic: for OpenGL, you intercept wglSwapBuffers and SwapBuffers, and inject some gl-commands before those. For D3D, you hook into IDirect3DDeviceX::Present (where X is the API version). Hooking into COM-objects might be a bit nasty, though. By the way, Microsoft already made an API to simplify these things called Detours.
added on the 2007-10-22 20:23:37 by kusma kusma
download the kkapture sources. might help.
added on the 2007-10-22 22:18:30 by raer raer
nope, it probably won't, at least not directly. kkapture explicitly only patches the 3d api functions inside the target application's address space, and i've got no nice idea of how to do it globally right now, because i never wanted to :) (you can patch the dlls on disk, but that's not exactly a nice solution).

if you're into tedium, you can first walk the process list using the toolhelp api, then walk the per-process module lists to find processes importing d3d/opengl dlls (look up "Taking a Snapshot and Viewing Processes" in MSDN). that at least gives you a list of candidates, and you could try to go on from there. or you might be able to use EnumWindows (or just GetForegroundWindow) together with GetWindowThreadProcessId. you might be able to detect fullscreen gl apps via GetForegroundWindow/GetWindowDC/GetPixelFormat. in any case, if d3d/ogl dlls are used, you can certainly use detours or something similar to hook api calls. ogl is easier to get working since it just uses imported functions (which is why the first version of kkapture only did ogl). for d3d com interfaces, you need to know where the vtables are to be able to redirect functions. kkapture elegantly works around the problem by hooking the creation functions so that whenever a ddraw/d3d object is created, it knows where it is (and thus where the vtable is). if you want to intercept an already running process, it isn't that easy, because the relevant objects have already been created; the vtable is constant data though, so its offset (relative to the base address of the d3d dll containing it) will be constant, so you can create a d3d object in the intercepting process to find out where the vtable is, then patch the functions in the target process (using the debugger/toolhelp api). be sure to not just use the function addresses as seen in the intercepting process, because the d3d dlls might be relocated in the address space of the target app.

finally, kkapture can easily create a bunch of persistent surfaces because it knows the object lifetimes (since it tracks them from creation on); it isn't as easy for an app that intercepts a running process, mainly because you have no way of knowing which objects there are, so you might want to create all textures you use per frame and release them afterwards. certainly pretty awkward.

there's probably a simpler way to do this, but this is the best i can do off the top of my head. you could try finding out what fraps does though (either by asking the authors or by asking a disassembler ;).
added on the 2007-10-23 03:59:57 by ryg ryg


Go to top