views:

528

answers:

3

I'm trying to write a C++ windows service that can render to a texture. I've got the code working as a regular console app, but when run as a service wglGetProcAddress() returns NULL.

Can anyone tell me if this is possible, and if so, what do I need to do to make OpenGL work inside a service process?


Edit:

I still haven't got this to work under Vista, but it does work under XP.

A: 

OpenGL needs desktop access to create a render context and a service by default don't have desktop access.

You need to run the service in interactive mode. To do that go in the service properties in Administrative Tools. Where you set the service's log on user, you will have an option to run the service in interactive mode, or something similar as "Allow service to interact with desktop". You can try logging the service as another user too.

If you are working through a .Net IIS application, you will also have to force the managed part of the server to log as another user.

EDIT:

I forgot to say, a user must currently be logged on the accelerated hardware desktop and the machine must not be locked. That sucks but that's the only way I made it work before. We had dirty script that logged a user on as soon as the machine started.

As a side note, we were using DirectX, so it might not apply to OpenGL.

Coincoin
I have tried that, checking the box "Allow service to interact with the Desktop", but it still doesn't work. Interestingly CreateWindowEx() works, I can create the window handle and get messages, but wglGetProcAddress() doesn't work.
kevin42
Have you tried other permutations, such as changing the "Log on as" to a user account and not "Local System account"?
JMD
This will not work, interactive desktop runs in some basic non-accelerated, non-driver GDI mode.
Andrew Grant
What JMD said. I know this will work with DirectX, but OpenGL I don't know. We made a realtime 3D rendering service and stumbled upon the same problem. We had to change the Log on options and also had to force IIS in our case to Log on a different user.
Coincoin
+1  A: 

Services run in non-interactive desktops. These desktops do not connect to the physical display device of the computer but rather to logical display devices. The logical display devices are very basic generic VGA devices set to 1024 X 768 with no bells and whistles.

Services can use most GDI functions but no advanced graphics functions such as DirectX or OpenGL. So you can create windows, create or retrieve device contexts and do some fairly complex drawing and rendering but you can't use anything but straightforward GDI (and some GDI+).

If you check GetLastError after wglGetProcAddress returns NULL you should get the reason for the failure.

Stephen Martin
+1  A: 

You can get a fully capable software renderer by using Mesa3D. Simply build Mesa3D and put the opengl32.dll built there alongside your application. This should enable you to use OpenGL 2.1 and extensions. We use this for testing Opengl applications in a Windows service.

Shane Blackett