redistributing directx

DSP, Plugin and Host development discussion.
RELATED
PRODUCTS

Post

Hi all

Does anybody use directx for GUI's? I have recently used directx 9 for an application, considering that it was the oldest relevant version and probably compatible with even ancient versions of windows, but no version of windows seems to have it preinstalled. It would be nice to know if any specific version is already preinstalled, say dx 10 on windows 8 and dx 11 on windows 10 and so on:)

Found some info, but not a complete list yet

DirectX 11.1 is preinstalled on windows 8
DirectX 10.? is probably preinstalled on windows vista

p.s. Google is fast, I have posted this half an hour ago but now it's among the web search results when I still look for information about the subject:) It isn't much fun to find only your own post in a thread, though:)
~stratum~

Post

~stratum~

Post

If you want to use Direct3D9 that works from XP up to Windows 10.
Don't use the DirectX wrapper but only the d3d9.lib (d3d9.dll is available on all XP up to Windows 10 computers.)
I use the d3d9.lib from 2003 and never had any problems.

But, you have to write your own image/texture loader. ( just use GDIplus for this )
And make your own Math library for the needed trig functions etc.

This way it doesn't matter which version of DirectX9 is installed on the users PC, it will always work and your .exe will be very small.

If you make use of the DirectX wrapper d3dx9.lib then the user need to have installed the same version of your wrapper and that it rarely the case. ( it will report a missing d3dx9_XX.dll )

Post

Ignoring the question of redistributable, I've found in the past that Direct3D windows (and this applies to both Direct3D9 and the later versions; I know the problem exists on Win7 at least, no idea if later versions of Windows share the issue) don't really play well with GDI windows in certain hosts, namely if the host wants to embed your plugin editor into a window containing other stuff that is drawn using GDI, you will most likely experience all kinds of synchronisation problems with repaints, learning to artifacts in the GDI drawing. YMMV, but you might want to use OpenGL instead which works perfectly fine everywhere and can even support modern goodies on WinXP as long as the user has hardware to deal with it.

Post

Hi,

Thanks for the responses so far. It's nice to know that if I had used directx for a plugin I wouldn't need to include a directx setup.
This question isn't about plugins, though, I've just thought that this community is probably familiar with directx because I seen a few plugins with nice multisampled/antialiased gui's. I have no chance of using OpenGL because this is about hardware accelerated video decoding and the related sdk uses DirectX9/11.

The problem with GDI is interesting. I have seen similar drawing conflicts with QT too, but I haven't really investigated the issue and had to leave that to work on something more urgent, and meanwhile people started asking, do we really need to install directx, what the hell is it for, we have no business with game development :-)
~stratum~

Post

stratum wrote: The problem with GDI is interesting. I have seen similar drawing conflicts with QT too, but I haven't really investigated the issue and had to leave that to work on something more urgent, and meanwhile people started asking, do we really need to install directx, what the hell is it for, we have no business with game development :-)
I believe QT is internally using GDI or OpenGL, so it's most likely the very same issue. It's also worth noting that it has something to do with GDI redirection under DWM that uses some kind of implicit synchronization (while Direct3D back-buffers are available to DWM directly; the problem also affects Direct2D that uses the same interfaces I guess). I've never seen the issue happen with DWM disable, but that's not really realistic these days. :)

One thing to keep in mind is that (if I'm not mistaken) the Direct3D9 shader compiler is not installed by default either, so if you need to compile shaders on the fly (rather than distribute precompiled shader bytecode) then you'll also need to install the redistributable. I personally don't see why adding the redistributables "just in case" to an installer would be a problem, but if you don't have an installer otherwise then that might obviously be a problem. :P

Post

I believe QT is internally using GDI or OpenGL,
QT has many options, but the default on windows is probably trying to use OpenGL first, and if that fails, there is an OpenGL emulation called ANGLE which forwards OpenGL calls to DirectX, and if that fails too, I don't know what it does. Which means, it could actually be using anything, or, it is necessary to compile it from the sources and specify exactly what you want. Given the issue about DWM, perhaps configuring it to always use ANGLE would solve the problem.
but if you don't have an installer otherwise then that might obviously be a problem. :P
I've seen more amusing problems which prevent people to remember making an installer :-)
~stratum~

Post

Why compile shader-files on the fly when precompiled shader-files are often much smaller ?
And you need no shader-compiler on the users computer ?

If it's not for games but only for GUI's, do you realy need a shader ?
Without a shader you can do most of the effects with just plain coding.

Why does someone want to mix different types of graphics renderers ?
You can do everything with only the d3d9.lib, even shaders. (d3d9.dll is available on all windows computers with XP and up)

The only reason I use GDIplus is to make use of the picture/image encoder/decoders and not for drawing.
I copy the raw picture/image data to Direct9 texture buffers and shut down GDIplus.

Just keep it simple and don't mix things that will bite each other.

Timing issues can easily be solved if programmed smart and simple if you know what you are doing.
Synchronise it all to 1 timer and everything will run in pace.

So, no need for any kind of an installer to create a Directx 9 GUI program.

Post

Hi Siekmanski,

This stuff is a mess for a number of different reasons. Using QT in a scenario in which fastest possible graphics performance is needed is one. That fact that Microsoft created directx at a time when opengl had already existed is another.

No a shader is not needed and yes we could distribute this app without a setup program if I had rendered the textures the way you had described. Thanks for that info.
Last edited by stratum on Tue Mar 07, 2017 2:48 pm, edited 1 time in total.
~stratum~

Post

Siekmanski wrote:Why compile shader-files on the fly when precompiled shader-files are often much smaller ?
The most common reason to compile shaders on the fly is when you want to choose some of the shader details at run-time and/or adapt it depending on hardware. If you only have a couple of shaders without many variations then obviously precompiling is not an issue.

Post

Hi mystran,
I just send different parameters to the shader code to make those changes.

Hi stratum,
You can include for example the .jpg .png files etc. in the resource section of your exe and decode them on the fly in the startup of your program using the GDIplus api and copy them to the texture buffers.

I just started coding a GUI for a picture crucher program written with Directx9 as I described here, it's still in its first stage ( only the textures and the alpha blending ) and uses only the d3d9.dll and GDIplus for the decoding of the textures/pictures.

The GUI graphics ( font, background and window borders ) are included in the resource section of the executable and the alpha handpointer.png is loaded from the Media folder. The rest is not finished yet, but just to show you it can be done without the need of the DirectX9 redistributables installed.

http://members.home.nl/siekmanski/GUI_directx9.zip "Hit F1 for full screen"

Post

Hi,

What I do is this:

Code: Select all

//to create:
						D3DFORMAT fmt = D3DFMT_A8B8G8R8
						HRESULT hr = D3DXCreateTexture(m_Target,
							m_TxWidth,
							m_TxHeight,
							0,
							D3DUSAGE_DYNAMIC,
							fmt,
							D3DPOOL_DEFAULT,
							&m_Texture);
						if (FAILED(hr))
							return hr;
						return S_OK;

//// when data needs to be refreshed:
				HRESULT Update()
				{
					if (!m_Texture)
						return E_FAIL;

					D3DLOCKED_RECT r;
					HRESULT hr = m_Texture->LockRect(0, &r, NULL, D3DLOCK_DISCARD);
					if (FAILED(hr))
						return hr;
					unsigned char* target = (unsigned char*)r.pBits;
					unsigned char* src = (unsigned char*)m_Data;// m_Data holds the image (logo, etc)
					for (int i = 0; i < m_TxHeight; i++)
					{
						memcpy(target, src, 4 * m_TxWidth);
						target += r.Pitch;
						src += m_Pitch; // source row size in bytes
					}
					hr = m_Texture->UnlockRect(0);
					if (FAILED(hr))
						return hr;
					return hr;
				}

According to the info you had given, probably missing dll's are due to calls like D3DXCreateTexture/D3DXCreateTextureFromFile (there is also a D3DXCreateTextureFromFile call somewhere else)
~stratum~

Post

D3DXCreateTextureFromFile function is from a d3dx9_XX.dll which is part of the DirectX9 redistributables you don't want to use.
So, you have to write your own D3DXCreateTextureFromFile function.

This is my DirectX9 texture loader routine.
It's written in Masm assembler ( my mother language :) )
You could try to translate it to C++

Code: Select all

LoadTexture proc uses ebx esi edi PictureName:DWORD,ColorKey:DWORD,pTexture:DWORD
LOCAL GdiplusToken:dword
LOCAL PictureBuffer:dword
LOCAL RsrcSize:dword
LOCAL hRsrc:dword
LOCAL pStream:dword
LOCAL pImage:dword
LOCAL pLockedRect:D3DLOCKED_RECT
LOCAL ReturnMessage:dword


	mov		ReturnMessage,E_FAIL
	mov		esi,pTexture
	SAFE_RELEASE dword ptr [esi]

	
	invoke	GdiplusStartup,addr GdiplusToken,addr GdiplusSInput,NULL
	test	        eax,eax 
	jnz		Exit_LoadTexture 

	mov		PictureBuffer,NULL
	mov		pStream,NULL
	
	invoke	FindResource,NULL,PictureName,TEXT_("PICTURE")
	test	        eax,eax
	jnz		Picture_In_Resource ; Picture found in the resource ?
	
	; Try to load Picture from file.

	invoke	MultiByteToWideChar,CP_ACP,0,PictureName,-1,addr FilenameW,MAX_PATH-1
	invoke	GdipCreateBitmapFromFile,addr FilenameW,addr pImage
	test	        eax,eax
	jnz		ShutdownGDIplus
	jmp		LockBitmap	

Picture_In_Resource:
	mov		hRsrc,eax
	invoke	SizeofResource,NULL,eax
	mov		RsrcSize,eax

	invoke	GlobalAlloc,GMEM_FIXED or GMEM_ZEROINIT,eax
	test      eax,eax
	jz		ShutdownGDIplus
	mov		PictureBuffer,eax
	invoke	LoadResource,NULL,hRsrc
	invoke	LockResource,eax
	invoke	RtlMoveMemory,PictureBuffer,eax,RsrcSize
	invoke	CreateStreamOnHGlobal,PictureBuffer,TRUE,addr pStream
	test	        eax,eax
	jnz		Close_Gdiplus

	invoke	GdipCreateBitmapFromStream,pStream,addr pImage
	test	        eax,eax
	jnz		Close_Gdiplus

LockBitmap:
	invoke	GdipBitmapLockBits,pImage,NULL,ImageLockModeRead,PixelFormat32bppARGB,addr GDIplusBitmapData
	test	        eax,eax
	jnz		Close_Image

	coinvoke g_pD3DDevice,IDirect3DDevice9,CreateTexture,GDIplusBitmapData.dwWidth,GDIplusBitmapData.dwHeight,\
								1,D3DUSAGE_DYNAMIC,D3DFMT_A8R8G8B8,D3DPOOL_DEFAULT,pTexture,NULL
	cmp		eax,D3D_OK
	jne		UnlockBitmap

	coinvoke g_pPictureTexture,IDirect3DTexture9,LockRect,0,addr pLockedRect,NULL,D3DLOCK_DISCARD
	cmp		eax,D3D_OK
	jne		UnlockBitmap
	
	mov		esi,GDIplusBitmapData.Scan0		; pointer to the bitmap data
	mov		edi,pLockedRect.pBits			; pointer to the texture data
	
	mov		ecx,GDIplusBitmapData.dwHeight
Height_lp:
	mov		edx,GDIplusBitmapData.dwWidth
	xor		ebx,ebx
Width_lp:
	mov		eax,dword ptr [esi+ebx]
	
	cmp		ColorKey,NULL
	jz		NoColorKey
	or		eax,D3DCOLOR_ARGB(255,0,0,0)
	cmp		ColorKey,eax
	jne		NoColorKey
	xor		eax,eax
NoColorKey:
	
	mov		dword ptr [edi+ebx],eax
	add		ebx,4
	dec		edx
	jnz		Width_lp
	add		esi,GDIplusBitmapData.Stride	
	add		edi,pLockedRect.Pitch
	dec		ecx
	jnz		Height_lp	

	coinvoke g_pPictureTexture,IDirect3DTexture9,UnlockRect,0

	mov		ReturnMessage,D3D_OK

UnlockBitmap:
	invoke	GdipBitmapUnlockBits,pImage,addr GDIplusBitmapData
Close_Image:
	invoke	GdipDisposeImage,pImage
Close_Gdiplus:
	SAFE_RELEASE  pStream
	cmp		PictureBuffer,NULL
	jz		ShutdownGDIplus
	invoke	GlobalFree,PictureBuffer
ShutdownGDIplus:
	invoke	GdiplusShutdown,GdiplusToken
Exit_LoadTexture:
	mov		eax,ReturnMessage
	ret

LoadTexture endp

Post

It's written in Masm assembler ( my mother language :) )
I always knew that the probability of finding someone sane among software engineers wasn't high, but the place where you find people who claim the ability to save the world, or code an whole app in masm, is probably the best of the best and I guess these people smoke something more interesting than the zillion cups of turkish coffee I daily consume

https://www.youtube.com/watch?v=vBzY7F2lMNo
~stratum~

Post

Right, so essentially what you want to do is call IDirect3dDevice9::CreateTexture to create the texture, then call texture->GetSurfaceLevel to get the level 0 (highest resolution mip) surface and then surface->LockRect to get a pointer where you can upload the image data (which you can load using whatever image loader floats your boat). Then UnlockRect and release the surface.

The complication is that you need the texture surface to be lockable to upload data which doesn't work for default pool (which you'd probably want to use), so what I normally do is first CreatePlainOffscreenSurface in D3DPOOL_SYSTEMMEM (or you can also create another texture, if you need a pixel format that doesn't work with plain offscreen.. not a problem with normal ARGB though), then do LockRect on that and write the data, then create the actual final texture into D3DPOOL_DEFAULT, use GetSurfaceLevel() to get the top MIP and copy the data over using IDirect3DSurface9::UpdateSurface or StretchRect or some such, then throw away the system memory surface afterwards.

Post Reply

Return to “DSP and Plugin Development”