D3D9 CreateDevice() fails on Windows 10 when creating a multihead device - windows-10

When calling IDirect3D9::CreateDevice with the BehaviorFlags D3DCREATE_ADAPTERGROUP_DEVICE in order to create a fullscreen multihead device (with 2 or more monitors attached) the function returns D3DERR_INVALIDCALL, when running the application on Windows 10 (build 1511, or build 10240).
The same code works fine on Windows 7 (on a multitude of different machines), and also on Windows 8.1 (with the latest updates). Also creating individual D3D9 devices (fullscreen) for each attached monitor to the graphics adapter works fine on Windows 10.
D3D9Ex by the way shows exactly the same behavior. Can anyone point me to a working D3D9 multihead example that works on Windows 10? Thanks!

I observed the exact same behaviour with "CreateDevice".
But when you use "CreateDeviceEx" it works ... well ... almost :-(.
You may now create the device and use it, but under some circumstances (especially if you use the same resolutions as the desktop already had) you wont see anything and "Present" will continuously return "S_PRESENT_MODE_CHANGED". But if you now switch the second monitor to some other resolution via ResetEx end then switch back to desktop resolution - voila it works. I put that on on a key I can press after initialization:
const int idx = 1;
int OldWidth = D3DPresPar[idx].BackBufferWidth;
int OldHeight = D3DPresPar[idx].BackBufferHeight;
D3DPresPar[idx].BackBufferWidth = 1280;
D3DPresPar[idx].BackBufferHeight = 720;
D3DDispMode[idx].Width = 1280;
D3DDispMode[idx].Height = 720;
FailCheck(pD3DDevice->ResetEx(D3DPresPar, D3DDispMode), "ResetEX");
D3DPresPar[idx].BackBufferWidth = OldWidth;
D3DPresPar[idx].BackBufferHeight = OldHeight;
D3DDispMode[idx].Width = OldWidth;
D3DDispMode[idx].Height = OldHeight;
FailCheck(pD3DDevice->ResetEx(D3DPresPar, D3DDispMode), "ResetEX");
And after pressing the key it suddenly works. Weird, eh?
I confirmed this behaviour on multiple computers with nvidia, amd and intel grafics adapters. So the bug seems to be on microsoft side.
Conclusion: Theoretically it should work but there is some annyoing bug in windows 10 multihead initialization.
With some weird tricks you can achieve what you want, but these tricks are just too weird to use in production.

Related

How do you detect whether your Mixed Reality app is running on HoloLens 1, HoloLens 2 or an immersive headset?

Mixed Reality apps can soon run on three kinds of devices: HoloLens 1, Hololens 2 and Immersive (VR) headsets. Some behavior will likely be different depending on the type of device you run the app on. How can I ask the SDK what kind of device my app is running currently on?
If you are using MRTK (I noticed you might based on your tag), then the best way to do this is by using platform capabilities utility, since that will work as new devices come out, and across platforms. For example, instead of checking "am on on HoloLens 2" you can check "does my device support articulated hands?". That will then work on other platforms that support articulated hands. For an example, chekc out MixedRealityToolkit.Examples/Demos/Utilities/Scenes/MixedRealityCapabilityDemo.unity in MRTK examples.
If you need a temporary solution for now to differentiate WMR from HL1 from HL2, you can use the following code. Note it's windows-only:
using Windows.Security.ExchangeActiveSyncProvisioning;
EasClientDeviceInformation CurrentInfo = new EasClientDeviceInformation();
string sku = CurrentInfo.SystemSku;
HoloLens 1, HoloLens 2, and Immersive headsets should all return different strings.
Edit 6/5/2020:
It's also possible to check the runtime platform as follows:
if (Application.platform == RuntimePlatform.WSAPlayerARM)
{
// Running HoloLens 2, most likely.
}
HolographicDisplay.GetDefault().IsOpaque is true for Immersive VR headsets and false for AR devices like HoloLens.
For HoloLens you don't need to detect a precise device family. Instead you should check the feature support via Universal Contract Version like
bool checkUniversalApiContract(int contractNumber)
{
return winrt::Windows::Foundation::Metadata::ApiInformation::IsApiContractPresent(L"Windows.Foundation.UniversalApiContract", contractNumber);
}
bool supportsHandTracking = checkUniversalApiContract(8);
To check whether it is opaque (VR) or not (AR):
#if UNITY_2017_2_OR_NEWER
bool isOpaque = UnityEngine.XR.WSA.HolographicSettings.IsDisplayOpaque;
#else
bool isOpaque = UnityEngine.VR.VRDevice.isPresent;
#endif
To check whether it is HL1 or HL2, this is a simple solution, not requiring other dlls:
#if UNITY_WSA || UNITY_WSA_10_0
// Get vertical field of view in degrees
// HL1 == 17.5, HL2 == 29
bool isHL1 = (Camera.main.fieldOfView < 23f);
#endif

Cannot get QWindow::fromWinId to work properly

My Qt 5.9 program (on X11 Linux) launches other applications, using QProcess.
I would like to have control over windows these applications spawn, so I obtain their winId value and use QWindow::fromWinId to get a QWindow instance.
The problem is these instances are invalid and do not represent the window they are supposed to.
If I check the winId values using xwininfo, the correct information is returned, so I know they are good.
What am I doing wrong?
Edit: An example won't help much, but here goes:
QProcess *process=new QProcess(this);
...
process.open()
... // wait until window appears
WId winId=PidToWid(process->processId()); // this function returns the Window ID in decimal format. I test this with xwininfo, it's always correct
...
QWindow *appWindow=QWindow::fromWinId(winId);
... And that's basically it. appWindow is a valid QWindow instance, but it does not relate to the actual window in any way. For example, if I close() it, it returns true but the window does not close.
Even if I provide a wrong WId on purpose, the end result is the same.
This is not proper solution with explanation why it should work, however it may be helpful for somebody...
I had the same issue with my application when I switched from Qt4 QX11EmebeddedContainer to Qt5 implementation using QWindow. What I did to resolve / fix this issue was following:
Client application:
widget->show(); //Widget had to be shown
widget->createWinId();
sendWinId(widget->winId()); //Post window handle to master app where is constructed container
Master application:
QWindow* window = QWindow::fromWinId(clientWinId);
window->show(); //This show/hide toggle did trick in combination with show in client app
window->hide();
QWidget* container = QWidget::createWindowContainer(window, parentWindowWidget);
After this I was able to control window properly through QWidget container.

where to put a while loop in a system tray application so that loop starts with the app

I have created a System Tray Application using Windows Forms Template (Visual C++) in Visual Studio 2008. I have used ContextMenuStrip and NotifyIcon. It's a managed code as I have used the form and Drag/Drop.
I want as soon as this System Tray Application starts, it starts polling for any new USB devices (from a specific vendor) connected.
The logic is ready except I don't know "Where to put this while(1) loop?"
It works fine in a console app that I made but now we want it to be integrated to the system tray app.
Here is the code snippet:
int numDevices, n = 0;
while(1)
{
Sleep(5000);
numDevices = usb_find_devices();
if(connectedDevices > numDevices)
{
enumDevices();
connectedDevices++;
}
}
It would really be appreciable if anyone could suggest me some pointers on how to proceed.
Thank you Hans! I added a new "Component Class" with WM_DEVICECHANGE and it is working fine.
Just in case anyone needs this info:
If a function needs to be called as soon as the Windows Forms App starts (Systray app in my case), the respective function can be called after the call to "InitializeComponent()" function. Though it is clearly mentioned "TODO: Add the constructor code here", still a beginner (like me) has inhibitions regarding "Where to put this Function Call??" Hope this helps somebody..

Is Xinerama causing issues with my code?

After trying to get a basic "Hello World"-like XServer application up and running, I've found that, no matter what I try, I keep running into the same error, which is:
X Error of Failed request: BadMAtch( invalid parameter attributes )
Major opcode of failed request: 78 ( X_CreateColormap )
At first, I thought it was my drivers, so I updated them to 290.10 (nVidia).
My (relevant) setup consists of the following:
nVidia GTX 550 Ti
Sabayon Linux
Kernel 3.2
But, after some surfing, it seems like it could be either the fact that I have dual monitors (one connected to an hdmi-mini port, the other vga/dvi), or the fact that I have Xinerama enabled, or both.
I tried to compensate for both monitors by creating two GLXContext objects in my code, which, as expected, didn't do anything (be nice: I just started learning this API). I did this because it seemed like a GLXContext had something to do with monitor input/output.
After that didn't work, I tried glXGetConfig, and that didn't work either. So, I started looking around more and found a post on a forum (written a couple years ago) about someone having issues with disabling Xinerama, and that that was causing the issue. The weird thing was that this was posted back in 2009, so one would think that nVidia had fixed this by now.
I'm at a loss as to what to do, and I believe that I'm kind of screwed some how unless I can fix this.
Anyone can view my code here (pastebin), along with my post on SuperUser here.
I could really use some help on this one.
tl;dr
setWindowAtt.colormap = colorMap;
setWindowAtt.event_mask = ExposureMask | KeyPressMask;
win = XCreateWindow( dp, root, 0, 0, 600, 600, 0, visualInfo->depth, InputOutput, visualInfo->visual, CWColormap | CWEventMask, &setWindowAtt );
XMapWindow( dp, win );
XStoreName( dp, win, VI_UN_DEF_WIN_NAME );
glxContext = glXCreateContext( dp, visualInfo, NULL, GL_TRUE ); //error
glXMakeCurrent( dp, win, glxContext );
The clue is right in front of you:
Major opcode of failed request: 78 ( X_CreateColormap )
That means XCreateColormap failed. If it wanted to tell you a GLX command had failed, it would have said something about GLX instead.
After reading the rest of your code: the visual you're getting from glXChooseVisual is probably a TrueColor-class visual, and - as the manual for XCreateColormap says - TrueColor visuals must be allocated with AllocNone, and will throw BadMatch if you don't.

Flash trace output in firefox, linux

I'm developing an applications which I've got running on a server on my linux desktop. Due to the shortcomings of Flash on Linux (read: too hard) I'm developing the (small) flash portion of the app in Windows, which means there's a lot of frustrating back and forth. Now I'm trying to capture the output of the flash portion using flash tracer and that is proving very difficult also. Is there any other way I could monitor the output of trace on linux? Thanks...
Hope this helps too (for the sake of google search i came from):
In order to do trace, you need the debugger version of Flash Player from
http://www.adobe.com/support/flashplayer/downloads.html (look for "debugger" version specifically - they are hard to spot on first look)
Then an mm.cfg file in your home containing
ErrorReportingEnable=1 TraceOutputFileEnable=1 MaxWarnings=50
And then you are good to go - restart the browser. When traces start to fill in, you will find the log file in
~/.macromedia/Flash_Player/Logs/flashlog.txt
Something like
tail ~/.macromedia/Flash_Player/Logs/flashlog.txt -f
Should suffice to follow the trace.
A different and mind-bogglingly simple workaround that I've used for years is to simply create an output module directly within the swf. All this means is a keyboard shortcut that attaches a MovieClip with a textfield. All my traces go to this textfield instead of (or in addition to) the output window. Over the years I've refined it of course, making the window draggable, resizable, etc. But I've never needed any other approach for simple logging, and it's 100% reliable and reusable across all platforms.
[EDIT - response to comment]
There's no alert quite like javascript's alert() function. But using an internal textfield is just this simple:
ACTIONSCRIPT 1 VERSION
(See notes at bottom)
/* import ExternalInterface package */
import flash.external.*;
/* Create a movieclip for the alert. Set an arbitrary (but very high) number for the depth
* since we want the alert in front of everything else.
*/
var alert = this.createEmptyMovieClip("alert", 32000);
/* Create the alert textfield */
var output_txt = alert.createTextField("output_txt", 1, 0, 0, 300, 200);
output_txt.background = true;
output_txt.backgroundColor = 0xEFEFEF;
output_txt.selectable = false;
/* Set up drag behaviour */
alert.onPress = function()
{
this.startDrag();
}
alert.onMouseUp = function()
{
stopDrag();
}
/* I was using a button to text EI. You don't need to. */
testEI_btn.onPress = function()
{
output_txt.text = (ExternalInterface.available);
}
Notes: This works fine for AS1, and will translate well into AS2 (best to use strong data-typing if doing so, but not strictly required). It should work in Flash Players 8-10. ExternalInterface was added in Flash 8, so it won't work in previous player versions.
ACTIONSCRIPT 3 VERSION
var output_txt:TextField = new TextField();
addChild(output_txt);
output_txt.text = (String(ExternalInterface.available));
If you want to beef it out a bit:
var alert:Sprite = new Sprite();
var output_txt:TextField = new TextField();
output_txt.background = true;
output_txt.backgroundColor = 0xEFEFEF;
output_txt.selectable = false;
output_txt.width = 300;
output_txt.height = 300;
alert.addChild(output_txt);
addChild(alert);
alert.addEventListener(MouseEvent.MOUSE_DOWN, drag);
alert.addEventListener(MouseEvent.MOUSE_UP, stopdrag);
output_txt.text = (String(ExternalInterface.available));
function drag(e:MouseEvent):void
{
var alert:Sprite = e.currentTarget as Sprite;
alert.startDrag();
}
function stopdrag(e:MouseEvent):void
{
var alert:Sprite = e.currentTarget as Sprite;
alert.stopDrag();
}
[/EDIT]
If you only need the trace output at runtime, you can use Firebug in Firefox and then use Flash.external.ExternalInterface to call the console.log() Javascript method provided by Firebug.
I've used that strategy multiple times to a large degree of success.
Thunderbolt is a great logging framework with built-in firebug support.
I use the flex compiler on linux to build actionscript files, [embed(source="file")] for all my assets including images and fonts, I find actionscript development on linux very developer friendly.
Then again, I'm most interested in that flash has become Unix Friendly as aposed to the other way around :)
To implement FlashTracer, head to the following address and be sure you have the latest file. http://www.sephiroth.it/firefox/flashtracer/ . Install it and restart the browser.
Head over to adobe and get the latest flash debugger. Download and install the firefox version as FlashTracer is a firefox addition.
Now that firefox has the latest flash debugger and flash tracer we need to locate mm.cfg
Location on PC: C:\Documents and Settings\username
Inside of mm.cfg should be:
ErrorReportingEnable=1
TraceOutputFileEnable=1
MaxWarnings=100 //Change to your own liking.
Once that is saved, open firefox, head to the flash tracer window by heading to tools > flash tracer. In the panel that pops up there is two icons in the bottom right corner, click the wrench and make sure the path is set to where your log file is being saved. Also check to see that flash tracer is turned on, there is a play/pause button at the bottom.
I currently use this implementation and hope that it works for you. Flash Tracer is a little old, but works with the newest versions of FireFox. I am using it with FireFox 3.0.10.

Resources