Trouble porting OpenGL app to Windows - c++

I am trying to move an OpenGL app to Windows.
It was my understanding that Windows had a decent OpenGL implementation. But I'm starting to think that it doesn't...
Specifically, I use array buffers and glDrawArrays.
When I tried to compile my code in Visual Studio 2008 Pro, I received the following errors:
vertexbuffers.cpp(31) : error C3861: 'glGenBuffers': identifier not found
vertexbuffers.cpp(32) : error C2065: 'GL_ARRAY_BUFFER' : undeclared identifier
vertexbuffers.cpp(32) : error C3861: 'glBindBuffer': identifier not found
vertexbuffers.cpp(33) : error C2065: 'GL_ARRAY_BUFFER' : undeclared identifier
vertexbuffers.cpp(33) : error C2065: 'GL_STATIC_DRAW' : undeclared identifier
vertexbuffers.cpp(33) : error C3861: 'glBufferData': identifier not found
When I examined <GL\gl.h> (contained in C:\Program Files\Microsoft SDKs\Windows\v6.0A\Include\gl), I saw:
/* ClientArrayType */
/* GL_VERTEX_ARRAY */
/* GL_NORMAL_ARRAY */
/* GL_COLOR_ARRAY */
Update but it would seem that those contants get defined elsewhere.
How am I supposed to generate buffers if I don't have access to those functions?
The documentation doesn't say that those array types are disabled. How do I get access to the real implementation on OpenGL on Windows?

You might give GLEW a shot:
http://glew.sourceforge.net/
I'm pretty sure I used it at some time in the past, and makes this sort of thing a little easier and more portable.

The #defines are commented out in the header file whenever they would otherwise be repeated. Look at line 1054 of gl.h:
/* vertex_array */
#define GL_VERTEX_ARRAY 0x8074
If this #define is actually missing then you should probably replace the file with a fresh copy.
If you look at the documentation for glGenBuffers you will see that it is only available in OpenGL 1.5 and higher. The header file for Windows only comes with OpenGL 1.2 and you should use the extension mechanism to access the newer functionality. If you call wglGetProcAddress with the function name, e.g.
void (__stdcall *glGenBuffers)(GLsizei,GLuint*) =
wglGetProcAddress("glGenBuffers");
then you have a pointer to the function.

It would seem that the buffer functions are only available on Windows as extension methods.
OpenGL provides glext.h that declares pointers to all of these functions. It is then up to my app to use wglGetProcAddress to get pointers to the functions.
For example:
PFNGLGENBUFFERSPROC myglBindBuffers =
(PFNGLGENBUFFERSPROC)wglGetProcAddress("glGenBuffersARB");
Thankfully, I only have to do it for about 4 functions. Unfortunately, I now have to add platform-dependent code to my app.

Microsoft's support for OpenGL stretches only as far as OpenGL-1.1 up to Windows XP, and OpenGL-1.4 starting with Vista. Any OpenGL functionality beyond those must be delivered and supported by the installable client driver (ICD), i.e. the GPU driver's OpenGL implmenentation. To access the advanced functionality, OpenGL provides the so called Extension System, formed by wglGetProcAddress, which is kind of like GetProcAddress for DLLs, but gives access to functions of the OpenGL implementation (=driver).
To make things easier, nice wrapper libraries like GLEW have been developed, which do all the grunt work initializing all the available OpenGL extensions, providing them to the end user.

Related

glbinding, Qt and error "glbinding is not compatible with gl.h"

I'm writing a new project and want to replace GLEW with glbinding.
My setup is like this:
VS 2015, Qt 5.6, glbinding 2.0
I tried to compile quite simple code - only window (QWindow) with OpenGL context (QOpenGLContext) but got an error: glbinding is not compatible with gl.h
When I was tracking this bug I found out that file (which is imported by the glbinding/gl/gl.h) nogl.h is causing this message with the code below:
#ifdef __gl_h_
#error "glbinding is not compatible with gl.h"
#else
#define __gl_h_
#endif
Then I noticed that this is caused by the QtGui/qopenglcontext.h header (which I need for creating OpenGL context...). So when I don't include qopenglcontext.h my program compiles without error. I also noticed that this error message appears only when I include glbinding/gl/gl.h after QtGui/qopenglcontext.h. If I reverse the include order I get a bunch of errors like this:
1>C:\Qt\Qt5.6.0\5.6\msvc2015_64\include\QtGui/qopenglext.h(117): error C2065: 'GLenum': undeclared identifier
1>C:\Qt\Qt5.6.0\5.6\msvc2015_64\include\QtGui/qopenglext.h(117): error C2146: syntax error: missing ')' before identifier 'mode'
1>C:\Qt\Qt5.6.0\5.6\msvc2015_64\include\QtGui/qopenglext.h(118): error C2065: 'GLenum': undeclared identifier
1>C:\Qt\Qt5.6.0\5.6\msvc2015_64\include\QtGui/qopenglext.h(118): error C2146: syntax error: missing ')' before identifier 'target'
After all I still don't know how to solve this and what exactly is causing this error...
glbinding – like practically every other OpenGL loader – has to fiddle with the OpenGL symbol tokens to avoid namespace clashing. To this end it must interact with the OpenGL definitions in a specific way, which means you must not have included any OpenGL header, or something that includes such in turn at the moment you include the glbinding header. The preprocessor fiddling glbinding performs will prevent gl.h getting included in a way that causes trouble.
So what you must do is: Include the glbinding headers in your C++ compilation unit files before everything else (Qt headers, OpenGL helper libraries and so on).

How to shrink the size of a WTL application?

WTL applications are quite small already. However, using VS 2005 a statically linked application with WTL 9.10 weighs in at 136 kB (139,264 Bytes) for the Win32 configuration.
Looking at the executable I noticed a static import of oleaut32.dll. A cursory look with dumpbin shows one import via ordinal.
OLEAUT32.dll
4181C0 Import Address Table
41C9B8 Import Name Table
0 time date stamp
0 Index of first forwarder reference
Ordinal 277
Inspecting oleaut32.dll one finds that the export is named VarUI4FromStr.
Digging a little with IDA, I found that VarUI4FromStr was used by ATL::CRegParser::AddValue. Following the dependents from there, showed two calls in ATL::CRegParser::RegisterSubkeys.
Cross-referencing the ATL code of my Visual Studio installation with the findings, I found that the culprit was ATL::CAtlComModule. It does a lot of TypeLib registration stuff that is simply not needed for my use case.
However, the linker seems to leave all of that in, because it cannot reasonably decide to throw it out.
How can I get rid of this seemingly superfluous import?
Alas, since WTL::CAppModule derives directly from ATL::CComModule, including the atlbase.h header while having _ATL_NO_COMMODULE defined leads to an error:
Error 1 fatal error C1189: #error : WTL requires that _ATL_NO_COMMODULE is not defined $(ProjectDir)\wtl\Include\atlapp.h 33
The actual culprit that ultimately pulls in ATL::CComModule is, however, ATL::CAtlComModule. So our goal is to get rid of both of them.
We'll try to trick atlbase.h into excluding all the TypeLib registration code by defining _ATL_NO_COMMODULE anyway, but undefining it right after we're done including it. This way atlapp.h and other WTL headers won't "notice".
#define _ATL_NO_COMMODULE
#include <atlbase.h>
#undef _ATL_NO_COMMODULE
#include <atlapp.h>
Obviously that gets us into some trouble:
1>atlapp.h(1515) : error C2039: 'CComModule' : is not a member of 'ATL'
1>atlapp.h(1515) : error C2504: 'CComModule' : base class undefined
1>atlapp.h(1524) : error C2653: 'CComModule' : is not a class or namespace name
1>atlapp.h(1543) : error C2653: 'CComModule' : is not a class or namespace name
1>atlapp.h(1625) : error C3861: 'GetModuleInstance': identifier not found
1>atlapp.h(1784) : error C2653: 'CComModule' : is not a class or namespace name
1>atlapp.h(1806) : error C2065: 'm_nLockCnt' : undeclared identifier
However, it looks like we should be able to fix this handful of errors quickly.
First of all let's check where ATL::CComModule comes from: it's declared and defined in atlbase.h. We can surely declare our own class and squeeze it in between #include <atlbase.h> and #include <atlapp.h> (see above).
Let's start with the basics, based on what can be found in atlbase.h:
namespace ATL
{
class CComModule : public CAtlModuleT<CComModule>
{
public:
CComModule() {}
};
};
Now we get a different set of errors:
1>atlapp.h(1524) : error C2039: 'Init' : is not a member of 'ATL::CComModule'
1> stdafx.h(31) : see declaration of 'ATL::CComModule'
1>atlapp.h(1625) : error C3861: 'GetModuleInstance': identifier not found
Excellent, so we're in fact only missing two more class functions: GetModuleInstance and Init. Let's pull those in as well. For good measure we'll also add GetResourceInstance:
namespace ATL
{
class CComModule : public CAtlModuleT<CComModule>
{
public:
CComModule() {}
HINSTANCE GetModuleInstance() throw() { return _AtlBaseModule.m_hInst; }
HINSTANCE GetResourceInstance() throw() { return _AtlBaseModule.m_hInstResource; }
HRESULT Init(_ATL_OBJMAP_ENTRY*, HINSTANCE, const GUID*) throw() { return S_OK; }
};
};
A short test proves that this is working fine. And the oleaut32.dll import is gone along with three more imports from ole32.dll. Great success!
And as a result we have saved 12 kB on the executable size.
Do you know other cool tricks to shrink WTL application size?
IMPORTANT
Note that depending on the features of ATL::CComModule which your code uses, you may have to fall back to using the original. The only other alternative is to extend the above mock version of ATL::CComModule to fix any compilation errors you may run into.
CAUTIONARY NOTE
I have not tested this extensively yet and I'll report back (by editing this answer) if I run into any trouble. However, from looking at it in both the ATL and WTL code as well as in the IDA database prior to my changes, I think this is a safe change.
Bonus trick
You may also use the 6001.18002 standalone WDK (for Vista SP1), which supports to target Windows 2000 (SP4) and newer. It includes ATL 7.0 and is therefore suited to build ATL+WTL applications.
To do that you just need to add the following two lines to your sources file:
USE_STATIC_ATL=1
ATL_VER=70
Thanks to the WDK, which uses msvcrt.dll, a system DLL, as its default (multithreaded dynamically linked) C runtime, you can then shrink the executable size further by linking dynamically to the C runtime. And in this case, since that particular C runtime is a system DLL (starting with Windows 2000), you can rest assured that it will work.
All of that taken into account you can build standard Windows applications (GUI or console) and DLLs that are really small.
Here is an example sources file which you can use as a template:
# Name of the program
TARGETNAME=progname
# Prefix used for the intermediate/output paths (e.g. objfre_w2k_x86)
TARGETPATH=obj
# A program, not a driver or DLL or static lib
TARGETTYPE=PROGRAM
# windows == GUI, console == Console, native == no subsystem ...
UMTYPE=windows
# Use Unicode ("wide char") instead of ANSI
UNICODE=1
# By default the WDK build treats warnings as errors - this turns it off
BUILD_ALLOW_ALL_WARNINGS=1
# Link dynamically to msvcrt.dll
USE_MSVCRT=1
# Don't link against any of the ATL DLLs
USE_STATIC_ATL=1
# In the 7600.16385.1 WDK you can use 70 as well, which translates to 71
ATL_VER=70
USE_NATIVE_EH=1
# RTTI is required for some ATL/WTL features
USE_RTTI=1
# GUI programs require these entry points
!IF defined(UNICODE) && $(UNICODE)
UMENTRY=wwinmain
C_DEFINES=$(C_DEFINES) /DUNICODE /D_UNICODE
!ELSE
UMENTRY=winmain
C_DEFINES=$(C_DEFINES) /DMBCS /D_MBCS
!ENDIF
# Include folders
INCLUDES=$(DDK_INC_PATH);$(CRT_INC_PATH);$(SDK_INC_PATH);wtl\Include
# Libraries to link to, not just import libraries
TARGETLIBS=\
$(SDK_LIB_PATH)\kernel32.lib \
$(SDK_LIB_PATH)\user32.lib \
$(SDK_LIB_PATH)\Comctl32.lib \
# Give source files (also resources and .mc) in the current or parent directory
SOURCES=...
The 7600.16385.1 standalone WDK also works for this. The WDKs starting from the Windows 8 WDK now require a Visual C++ into which they can be integrated. This also leads to the binaries requiring the respective C runtime version instead of the msvcrt.dll from prior WDK versions.

ISampleGrabber undeclared identifier

I'm trying to execute a code generated by graphEditPlus (using VS2010) but having a trouble with the following line:
CComQIPtr<ISampleGrabber, &IID_ISampleGrabber> pSampleGrabber_isg(pSampleGrabber);
where the errors are:
error C2065: 'ISampleGrabber' : undeclared identifier
error C2065: 'IID_ISampleGrabber' : undeclared identifier
error C2514: 'ATL::CComQIPtr' : class has no constructors
I tried downloading different versions of Windows SDK (V7.1, V6.0A, V5) and set the include / lib paths but still having the same problem!
Is the SampleGrabber still being supported? Mainly, the SampleGrabber is used in my code to grab frames from a video capturing source...
Thanks for your assistance...
Microsoft deprecated Sample Grabber and the entire DES API, however you if you import the type library, or just copy the declarations into your project - the component is still usable except some very latest OS releases (Windows Server 2008?) where it is completely gone and you might need another solution such as building your own from earlier SDK samples.
See ISampleGrabber deprecated: where can I find alternatives? for more information.
See also RenderWmvVideo.cpp with code fragment to copy/paste and re-add the declarations to your project (#pragma section at the top of the file):
#pragma region Windows SDK Tribute, qedit.h
struct __declspec(uuid("0579154a-2b53-4994-b0d0-e773148eff85"))
ISampleGrabberCB : IUnknown
{
...
#pragma endregion

error C2146 trying to compile a basic HLSL shader in C++

i've just started to learn the basics of HLSL using C++, im following the tutorials on a book, the first basic shader is:
float4 VS_Main( float4 pos:POSITION):SV_POSITION
{
return pos;
}
but i get a lot of errors at compile time:
error C2146: syntax error: ';' missing before the identifier 'VS_Main'
error C4430: missing type specifier, int assumed. Note: default-int is no longer supported
error C2146: syntax error : ')' missing before the identifier 'pos'
error C2059: syntax errorlooks like a function definition, but there is no formal parameter list.
error C2059: syntax error: '{'
it really looks like the compiler cant handle HLSL at all...maybe VS2012 express doesnt support HLSL?
thanks in advance
HLSL is not C++. You should compile shaders with shader compiler, and C++ with C++ compiler — do not mix. There are two options for compiling HLSL.
Use command-line utility fxc.exe that is included in DirectX SDK (docs and usage here at MSDN). It generates a file that you should load in runtime by some of the ways described here.
Compile your shader at runtime by using D3DCompileFromFile function.
There are pros and cons about each of the variants. In short, pre-compiling at build time gives you some time gain at runtime, while compiling at runtime is more flexible and comfortable at development stage (no need to remember to recompile it or to use post-build scripts) but is more error-prone. Choose by yourself.
The code looks fine for HLSL. If you want to compile it from within VS2012 set the ".fx" file to build using the HLSL shader compiler. Right click the file select properties. Then select General and Item Type should be set to HLSL compiler.
If you really want to make shaders using C++ you could look into C++AMP to see if it may suit your needs.
it really looks like the compiler cant handle HLSL at all...maybe VS2012 express doesnt support HLSL?
No C++ compiler does. It is not supposed to be handled by the compiler.
You need to turn it into a resource and copy it into the bin directory using post-build scripts, and load the HLSL at runtime.
See also: http://www.directxtutorial.com/Lesson.aspx?lessonid=11-4-5

Not a member of global namespace?

I have the error:
error C2039: 'read' : is not a member of '`global namespace''
and
error C2661: 'Calc::SymString::read' : no overloaded function takes 3 arguments
from the line:
if (::read(fd_sock, &size, 4) != 4)
This error and similar ones appear quite a lot in my code. Does anyone know what the problem could be?
I am using Windows Visual Studio 2010 and I am migrating code from Unix.
Thanks in advance!
read() is a UNIX function defined (in LINUX) in unistd.h - all the documentation I have read indicates it is not a standard C function. That may be why it is compiling in UNIX but not in Windows.
In UNIX read() takes a file descriptor, but the equivalent construct in Windows is a "handle".
Do you really need low level file descriptor I/O in your program? Can you use fread, which is a standard C function?
This Microsoft support article describes the types of file handles available in Windows:
There are multiple types of file handles that can be opened using
the Win32 API and the C Run-time:
Returned Type File Creation API API Set
---------------------------------------------
HANDLE CreateFile() Win32
HFILE OpenFile()/_lcreat() Win32
int _creat()/_open() C Run-time
FILE * fopen() C Run-time
Microsoft declares the Unix-style I/O functions in io.h.
Try including that header - you may get a bunch of warnings about using deprecated names (MS would prefer you use the name _read()). If so, you may want to define the macro _POSIX_ which should quiet those warnings.