使用 cygwin 编译器的定制 win32 窗口上的 OpenGL 不起作用
Posted
技术标签:
【中文标题】使用 cygwin 编译器的定制 win32 窗口上的 OpenGL 不起作用【英文标题】:OpenGL on a custom made win32 window, using cygwin compiler, doesn't work 【发布时间】:2014-07-09 09:49:17 【问题描述】:我根据 NeHe 的第一个教程编写了一些代码,它创建了一个窗口并初始化了 gl 上下文。这与在 vc++ 中的工作方式完全相同。然后我尝试使用cygwin编译器在eclipse c++环境中复制相同的代码,问题就开始了。
窗口编译没有任何错误(许多警告但没有错误),exe打开一个win32窗口,我在窗口中编码的所有功能也可以工作(例如全屏模式,更改分辨率)唯一的问题是,我没有像应该那样用红色刷新窗口的背景,而是得到一个黑色方块,仅此而已。
对我来说,这看起来像是一个 opengl 初始化问题。这两天一直在尝试解决这个问题,但我找不到任何解决方案我希望有人能看到我做错了什么。
以下是代码摘录。
初始方法
#include <iostream>
#include <windows.h>
#include <gl/glew.h>
#include <string>
#define GLEW_STATIC
using namespace std;
#include <glWindow.h>
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
MSG msg;
GLboolean Exit = FALSE;
glWindow screen("Dark Light", 640, 480, 16);
while(!Exit)
if (screen.LastError() == errNone && screen.WndState() != glExit)
// Is There A Message Waiting?
if (PeekMessage(&msg, screen.Handles().Window(), 0, 0, PM_REMOVE))
// Have We Received A Quit Message?
if (msg.message == WM_QUIT)
screen.WndState() = glExit;
// If Not, Deal With Window Messages
else
TranslateMessage(&msg); // Translate The Message
DispatchMessage(&msg); // Dispatch The Message
// If There Are No Messages
else
if (screen.WndState() == glActive)
if (screen.KeysState(VK_ESCAPE))
screen.WndState() = glExit;
else
// Draw The Scene
screen.Draw();
if (screen.KeysState(VK_F1))
screen.KeysState(VK_F1) = FALSE;
screen.ToggleFullscreen();
if (screen.KeysState(VK_SPACE))
screen.KeysState(VK_SPACE) = FALSE;
screen.SetResolution(800, 600);
else
Exit = true;
// Shutdown
return 0;
glWindow.h
#ifndef GLWINDOW_H
#define GLWINDOW_H
#include <string>
using namespace std;
enum glWndState
glActive = 0, glPaused = 1, glExit = 2
;
enum glWndErrors
errNone = 0, errCreateWC = 1, errCreateWnd = 2, errCreateDC = 3, errMatchPixelFormat = 4,
errSetPixelFormat = 5, errCreateRC = 6, errActivateRC = 7, errInitGL = 8, errChangeRC = 9,
errReleaseRC = 10, errReleaseDC = 11, errDestroyWnd = 12, errDestroyWC = 13, errGoToFullscreen = 14,
errGoToWindowed = 15, errGetInstance = 16
;
class glWndSettings
private:
GLsizei _width;
GLsizei _height;
GLboolean _fullscreen;
GLint _bits;
PIXELFORMATDESCRIPTOR _pfd;
DEVMODE _screenSettings;
public:
glWndSettings(GLsizei width, GLsizei height, GLint bits);
glWndErrors glSetStyle(HWND hWnd);
glWndErrors glSetStyle(HWND hWnd, GLboolean fullscreen, GLboolean save = TRUE);
glWndErrors glSetResolution(HWND hWnd, GLsizei width, GLsizei height);
GLsizei& Width();
GLsizei& Height();
GLboolean& Fullscreen();
GLint& Bits();
PIXELFORMATDESCRIPTOR& PixelFormatDescription();
;
class glWndHandles
private:
string _className;
HINSTANCE _hInstance;
WNDCLASS _wc;
HWND _hWnd;
HDC _hDC;
HGLRC _hRC;
GLuint _pixelFormat;
public:
glWndHandles(HICON icon, string title, WNDPROC wndProc);
~glWndHandles();
glWndErrors glDefWindow(PIXELFORMATDESCRIPTOR pfd);
HINSTANCE& Instance();
WNDCLASS& WinClass();
HWND& Window();
HDC& DeviceContext();
HGLRC& RenderContext();
;
class glWndFPS
GLint _framesCounter;
GLint _fps;
public:
glWndFPS();
GLvoid NewFrame();
GLvoid ResetFrames();
GLint FPS();
;
class glWindow
glWndHandles _handles;
glWndSettings _settings;
glWndFPS _fps;
glWndErrors _error;
glWndState _state;
bool _keys[256];
string _title;
static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
public:
glWindow(string title, int width, int height, int bits);
~glWindow();
int InitGL();
GLvoid Draw();
GLvoid DisplayFPS();
GLvoid SetTitle(string title);
GLvoid SetResolution(GLsizei width, GLsizei height);
GLvoid SetFullscreen(GLboolean fullscreen);
GLvoid ToggleFullscreen();
glWndHandles& Handles();
glWndSettings& Settings();
glWndFPS& fpsInfo();
glWndErrors& LastError();
glWndState& WndState();
bool& KeysState(int key);
GLvoid ReSizeGLScene(GLsizei width, GLsizei height);
;
#endif /* GLWINDOW_H_ */
glWindow.cpp
#include <stdio.h>
#include <windows.h>
#include <GL/glew.h>
#include <glm/gtc/matrix_transform.hpp>
using namespace std;
#include "glWindow.h"
glWndSettings::glWndSettings(GLsizei width, GLsizei height, GLint bits)
_fullscreen = FALSE;
_width = width;
_height = height;
_bits = bits;
_pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR); // Size Of This Pixel Format Descriptor
_pfd.nVersion = 1; // Version Number
_pfd.dwFlags = PFD_DRAW_TO_WINDOW | // Format Must Support Window
PFD_SUPPORT_OPENGL | // Format Must Support OpenGL
PFD_DOUBLEBUFFER; // Must Support Double Buffering
_pfd.iPixelType = PFD_TYPE_RGBA; // Request An RGBA Format
_pfd.cColorBits = bits; // Select Our Color Depth
_pfd.cRedBits = 0; _pfd.cRedShift = 0;
_pfd.cGreenBits = 0; _pfd.cGreenShift = 0;
_pfd.cBlueBits = 0; _pfd.cBlueShift = 0; // Color Bits Ignored
_pfd.cAlphaBits = 0; _pfd.cAlphaShift = 0; // No Alpha Buffer
_pfd.cAccumBits = 0;
_pfd.cAccumRedBits = 0;
_pfd.cAccumGreenBits = 0;
_pfd.cAccumBlueBits = 0;
_pfd.cAccumAlphaBits = 0;
_pfd.cDepthBits = 16; // 16Bit Z-Buffer (Depth Buffer)
_pfd.cStencilBits = 0; // No Stencil Buffer
_pfd.cAuxBuffers = 0; // No Auxiliary Buffer
_pfd.iLayerType = PFD_MAIN_PLANE; // Main Drawing Layer
_pfd.bReserved = 0; // Reserved
_pfd.dwLayerMask = 0;
_pfd.dwVisibleMask = 0;
_pfd.dwDamageMask = 0; // Layer Masks Ignored
glWndErrors glWndSettings::glSetStyle(HWND hWnd)
GLboolean fullscreen = !_fullscreen;
return glSetStyle(hWnd, fullscreen);
glWndErrors glWndSettings::glSetStyle(HWND hWnd, GLboolean fullscreen, GLboolean save)
DWORD dwExStyle = 0;
DWORD dwStyle = 0;
if (save)
_fullscreen = fullscreen;
if (fullscreen)
dwExStyle = WS_EX_APPWINDOW;
dwStyle = WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
memset(&_screenSettings, 0, sizeof(_screenSettings)); // Makes Sure Memory's Cleared
_screenSettings.dmSize = sizeof(_screenSettings); // Size Of The Devmode Structure
_screenSettings.dmPelsWidth = _width; // Selected Screen Width
_screenSettings.dmPelsHeight = _height; // Selected Screen Height
_screenSettings.dmBitsPerPel = _bits; // Selected Bits Per Pixel
_screenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
// Try To Set Selected Mode And Get Results. NOTE: CDS_FULLSCREEN Gets Rid Of Start Bar.
if (ChangeDisplaySettings(&_screenSettings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
return errGoToFullscreen;
while(ShowCursor(FALSE) >= 0);
else
dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
dwStyle = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX;
if (ChangeDisplaySettings(NULL, 0) != DISP_CHANGE_SUCCESSFUL)
return errGoToWindowed;
while(ShowCursor(TRUE) < 0);
RECT windowRect;
windowRect.left=(long)0; // Set Left Value To 0
windowRect.right=(long)_width; // Set Right Value To Requested Width
windowRect.top=(long)0; // Set Top Value To 0
windowRect.bottom=(long)_height; // Set Bottom Value To Requested Height
AdjustWindowRectEx(&windowRect, dwStyle, FALSE, dwExStyle); // Adjust Window To True Requested Size
ShowWindow(hWnd, SW_HIDE);
DWORD oldExStyle = SetWindowLongPtr(hWnd, GWL_EXSTYLE, dwExStyle);
DWORD oldStyle = SetWindowLongPtr(hWnd, GWL_STYLE, dwStyle);
SetWindowPos(hWnd, HWND_TOP, 0, 0, windowRect.right, windowRect.bottom, SWP_NOZORDER);
ShowWindow(hWnd, SW_SHOW);
return errNone;
glWndErrors glWndSettings::glSetResolution(HWND hWnd, GLsizei width, GLsizei height)
_width = width; _height = height;
glSetStyle(hWnd, _fullscreen);
return errNone;
GLsizei& glWndSettings::Width()
return _width;
GLsizei& glWndSettings::Height()
return _height;
GLboolean& glWndSettings::Fullscreen()
return _fullscreen;
GLint& glWndSettings::Bits()
return _bits;
PIXELFORMATDESCRIPTOR& glWndSettings::PixelFormatDescription()
return _pfd;
glWndHandles::glWndHandles(HICON icon, string title, WNDPROC wndProc)
_hInstance = NULL;
_hWnd = NULL;
_hDC = NULL;
_hRC = NULL;
_pixelFormat = NULL;
_className = title;
_wc.style = CS_HREDRAW | CS_VREDRAW | // Redraw On Size
CS_OWNDC; // Own DC For Window.
_wc.lpfnWndProc = wndProc; // WndProc Handles Messages
_wc.cbClsExtra = NULL; // No Extra Window Data
_wc.cbWndExtra = NULL; // No Extra Window Data
_wc.hInstance = NULL; // Set The Instance
_wc.hIcon = icon; // Load The Default Icon
_wc.hCursor = LoadCursor(NULL, IDC_ARROW); // Load The Arrow Pointer
_wc.hbrBackground = NULL; // No Background Required For GL
_wc.lpszMenuName = NULL; // We Don't Want A Menu
_wc.lpszClassName = _className.c_str(); // Set The Class Name
glWndHandles::~glWndHandles()
// Are We Able To Release The DC And RC Contexts?
if (_hRC)
if (!wglMakeCurrent(NULL, NULL))
MessageBox(NULL, "Release Of DC And RC Failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);
// Are We Able To Delete The RC?
if (!wglDeleteContext(_hRC))
MessageBox(NULL, "Release Rendering Context Failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);
// Are We Able To Release The DC
if (_hDC && !ReleaseDC(_hWnd, _hDC))
MessageBox(NULL, "Release Device Context Failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);
// Are We Able To Destroy The Window?
if (_hWnd && !DestroyWindow(_hWnd))
MessageBox(NULL, "Could Not Release hWnd.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);
// Are We Able To Unregister Class
if (!UnregisterClass(_className.c_str(), _hInstance))
MessageBox(NULL, "Could Not Unregister Class.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);
glWndErrors glWndHandles::glDefWindow(PIXELFORMATDESCRIPTOR pfd)
if ((_hInstance = GetModuleHandle(NULL)))
_wc.hInstance = _hInstance;
else
MessageBox(NULL, "Failed To Get Window's Instance.", "ERROR", MB_OK|MB_ICONEXCLAMATION);
return errGetInstance;
if (!RegisterClass(&_wc))
MessageBox(NULL, "Failed To Register The Window Class.", "ERROR", MB_OK|MB_ICONEXCLAMATION);
return errCreateWC;
if (!(_hWnd=CreateWindowEx( NULL, // Extended Style For The Window
_wc.lpszClassName, // Class Name
_className.c_str(), // Window Title
NULL, // Style For The Window
0, 0, 300, 300, // Window's Position and Size
NULL, // No Parent Window
NULL, // No Menu
_hInstance, // Instance
NULL)))
MessageBox(NULL, "Window Creation Error.", "ERROR",MB_OK|MB_ICONEXCLAMATION);
return errCreateWnd;
//Get Window's Device Context
if (!(_hDC = GetDC(_hWnd)))
MessageBox(NULL, "Can't Create A GL Device Context.", "ERROR",MB_OK|MB_ICONEXCLAMATION);
return errCreateDC;
// Did Windows Find A Matching Pixel Format?
if (!(_pixelFormat = ChoosePixelFormat(_hDC, &pfd)))
MessageBox(NULL, "Can't Find A Suitable PixelFormat.", "ERROR",MB_OK|MB_ICONEXCLAMATION);
return errMatchPixelFormat;
// Are We Able To Set The Pixel Format?
if(!SetPixelFormat(_hDC, _pixelFormat, &pfd))
MessageBox(NULL, "Can't Set The PixelFormat.", "ERROR",MB_OK|MB_ICONEXCLAMATION);
return errSetPixelFormat;
if (!(_hRC=wglCreateContext(_hDC)))
MessageBox(NULL, "Can't Create A GL Rendering Context.", "ERROR",MB_OK|MB_ICONEXCLAMATION);
return errCreateRC;
if(!wglMakeCurrent(_hDC,_hRC))
MessageBox(NULL, "Can't Activate The GL Rendering Context.", "ERROR",MB_OK|MB_ICONEXCLAMATION);
return errActivateRC;
// GLenum err = glewInit();
//
// if (err != GLEW_OK)
// MessageBox(NULL, (char*)glewGetErrorString(err), "ERROR", MB_OK|MB_ICONEXCLAMATION);
// return errInitGL;
//
return errNone;
HINSTANCE& glWndHandles::Instance()
return _hInstance;
WNDCLASS& glWndHandles::WinClass()
return _wc;
HDC& glWndHandles::DeviceContext()
return _hDC;
HGLRC& glWndHandles::RenderContext()
return _hRC;
HWND& glWndHandles::Window()
return _hWnd;
glWndFPS::glWndFPS()
_framesCounter = 0; _fps = 0;
GLvoid glWndFPS::NewFrame()
_framesCounter++;
GLvoid glWndFPS::ResetFrames()
_fps = _framesCounter; _framesCounter = 0;
GLint glWndFPS::FPS()
return _fps;
glWindow* owner;
LRESULT CALLBACK glWindow::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
// Check For Windows Messages
switch (uMsg)
// Watch For Window Activate Message
case WM_ACTIVATE:
// Check Minimization State
if (!HIWORD(wParam))
// Program Is Active
owner->_state = glActive;
else
// Program Is No Longer Active
owner->_state = glPaused;
// Return To The Message Loop
return 0;
// Intercept System Commands
case WM_SYSCOMMAND:
// Check System Calls
switch (wParam)
// Screensaver Trying To Start?
case SC_SCREENSAVE:
// Monitor Trying To Enter Powersave?
case SC_MONITORPOWER:
// Prevent From Happening
return 0;
break;
// Did We Receive A Close Message?
case WM_CLOSE:
// Send A Quit Message
PostQuitMessage(0);
return 0;
// Is A Key Being Held Down?
case WM_KEYDOWN:
// If So, Mark It As TRUE
owner->_keys[wParam] = TRUE;
return 0;
// Has A Key Been Released?
case WM_KEYUP:
// If So, Mark It As FALSE
owner->_keys[wParam] = FALSE;
return 0;
// Resize The OpenGL Window
case WM_SIZE:
if (owner->Settings().Fullscreen() && IsWindowVisible(hWnd))
if (wParam == SIZE_MINIMIZED)
owner->Settings().glSetStyle(hWnd, FALSE, FALSE);
else if (wParam == SIZE_RESTORED)
owner->Settings().glSetStyle(hWnd, TRUE, FALSE);
// LoWord=Width, HiWord=Height
owner->ReSizeGLScene(LOWORD(lParam), HIWORD(lParam));
return 0;
case WM_KILLFOCUS:
if (IsWindowVisible(hWnd) && owner->Settings().Fullscreen())
ShowWindow(hWnd, SW_MINIMIZE);
return 0;
case WM_TIMER:
if (wParam == 1)
owner->DisplayFPS();
return 0;
// Pass All Unhandled Messages To DefWindowProc
return DefWindowProc(hWnd,uMsg,wParam,lParam);
glWindow::glWindow(string title, int width, int height, int bits)
:_settings(width, height, bits), _handles(LoadIcon(NULL, IDI_WINLOGO), title, (WNDPROC)WndProc)
for (int i = 0; i < 256; i++)
_keys[i] = false;
_error = errNone; _state = glActive; owner = this;
_title = title;
if ((_error = _handles.glDefWindow(_settings.PixelFormatDescription())) != errNone)
return;
_settings.glSetStyle(_handles.Window(), false);
SetForegroundWindow(_handles.Window()); // Slightly Higher Priority
SetFocus(_handles.Window()); // Sets Keyboard Focus To The Window
// Initialize Our Newly Created GL Window
if (!InitGL())
MessageBox(NULL, "Initialization Failed.", "ERROR", MB_OK|MB_ICONEXCLAMATION);
_error = errInitGL;
return;
SetTimer(_handles.Window(), 1, 1000, NULL);
glWindow::~glWindow(void)
if (_settings.Fullscreen())
ChangeDisplaySettings(NULL,0); // If So Switch Back To The Desktop
ShowCursor(TRUE); // Show Mouse Pointer
int glWindow::InitGL()
glShadeModel(GL_SMOOTH);
glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
glClearDepth(1.0f); // Depth Buffer Setup
glEnable(GL_DEPTH_TEST); // Enables Depth Testing
glDepthFunc(GL_LEQUAL); // The Type Of Depth Test To Do
// Really Nice Perspective Calculations
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
return TRUE; // Initialization Went OK
GLvoid glWindow::Draw()
//Clear The Screen And The Depth Buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity(); // Reset The Current Modelview Matrix
SwapBuffers(_handles.DeviceContext());
fpsInfo().NewFrame();
glWndErrors& glWindow::LastError()
return _error;
glWndState& glWindow::WndState()
return _state;
glWndHandles& glWindow::Handles()
return _handles;
glWndSettings& glWindow::Settings()
return _settings;
glWndFPS& glWindow::fpsInfo()
return _fps;
bool& glWindow::KeysState(int key)
return _keys[key];
GLvoid glWindow::DisplayFPS()
fpsInfo().ResetFrames();
char fps[100];
sprintf(fps, "%d", fpsInfo().FPS());
SetTitle(_title + " : ");
SetTimer(_handles.Window(), 1, 1000, NULL);
GLvoid glWindow::SetTitle(string title)
SetWindowText(_handles.Window(), title.c_str());
GLvoid glWindow::SetResolution(GLsizei width, GLsizei height)
_settings.glSetResolution(_handles.Window(), width, height);
GLvoid glWindow::SetFullscreen(GLboolean fullscreen)
_settings.glSetStyle(_handles.Window(), fullscreen);
GLvoid glWindow::ToggleFullscreen()
_settings.glSetStyle(_handles.Window());
GLvoid glWindow::ReSizeGLScene(GLsizei width, GLsizei height)
if (height == 0 && width == 0)
return;
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
glLoadIdentity(); // Reset The Projection Matrix
// Calculate The Aspect Ratio Of The Window
glm::perspective(45.0f, (GLfloat)width/(GLfloat)height, 0.1f, 100.0f);
glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
glLoadIdentity(); // Reset The Modelview Matrix
编译器输出
g++ -ID:/DarkLight/hello/header -ID:/DarkLight/externals/include -O0 -g3 -Wall -c -fmessage-length=0 -o "src\\glWindow.o" "..\\src\\glWindow.cpp"
g++ -ID:/DarkLight/hello/header -ID:/DarkLight/externals/include -O0 -g3 -Wall -c -fmessage-length=0 -o "src\\hello.o" "..\\src\\hello.cpp"
g++ -mwindows -o hello.exe "src\\hello.o" "src\\glWindow.o" -lgl -lglew32 -lglu32 -lopengl32 -lgdi32
【问题讨论】:
【参考方案1】:您是如何编译 Cygwin 版本的?您具体链接了哪些库?
Cygwin 可以编译为本地 GUI 系统 (Win32) 或使用 X11。但是 OpenGL 在这两种情况之间经历了两个非常不同的堆栈。在 Win32 的情况下,它通过 WGL,在 X11 的情况下,它通过 GLX。现在,如果您不小心链接了基于 GLX 的 OpenGL API (-lGL
),那么所有的 OpenGL 符号都在那里,所以事情似乎在表面上工作,但没有输出。您必须链接到 opengl32.lib
,即 -lopengl32
,以便使用基于 WGL 的绑定。
【讨论】:
我认为您可能正在做某事,因为我必须同时包含 GL 和 opengl32,否则链接器无法识别 GL 方法。检查我添加到原始帖子中的编译器输出。 @DarkPhoton:链接器参数的顺序很重要。我想知道:glew32
是使用 Cygwin 编译的还是由 Cygwin 安装程序安装的?因为如果是这种情况,它很可能与 OpenGL API 的 GLX 变体有关(-lGL
)。无论如何,-lGL
的存在绝对是您的问题的原因。另请记住,对于 binutils ld 链接器参数的顺序确实很重要(似乎对于 gold 链接器无关),因此您可能必须将-lopengl32
在其他库之前。
@DarkPhoton:当然,编译针对 Win32 的应用程序的最佳方法根本不是使用 Cygwin,而是使用 MinGW。请注意,在 Linux 或 Cygwin 主机上交叉编译到 Windows 工作得非常好。我在安装了 MinGW 交叉编译器的 Linux 机器上执行所有不使用 VC++ 的 Windows 目标构建,这样我就可以将我信任的 Unix 工具用于构建系统。我不知道它是否在 Cygwin 包中现成可用,但构建托管在 Cygwin 环境中的 MinGW 交叉编译器是完全可行的。以上是关于使用 cygwin 编译器的定制 win32 窗口上的 OpenGL 不起作用的主要内容,如果未能解决你的问题,请参考以下文章
MTK功能机编译错误ToolsMSYSinmake.exe: *** Couldn’t reserve spac e for cygwin’s heap, Win32 error
insh.exe:*** Couldn't reserve space for cygwin's heap,Win32 error 0