i have encountered an issue trying to debug my 64 bit application under Visual Studio 2015. When i switch it to debug mode, it crashes during window creation. Which did not happen in 32 bit mode;
Here's redacted window initialization code:
int indexPF;
WNDCLASS WinClass;
WinClass.style = CS_OWNDC | CS_PARENTDC;
WinClass.lpfnWndProc = WndProc;
WinClass.cbClsExtra = 0;
WinClass.cbWndExtra = 0;
WinClass.hInstance = hInstance;
WinClass.hIcon = LoadIcon(NULL, IDC_ICON);
WinClass.hCursor = LoadCursor(NULL, IDC_ARROW);
WinClass.hbrBackground = (HBRUSH)GetStockObject(5);
WinClass.lpszMenuName = NULL;
WinClass.lpszClassName = "N2";
if (!RegisterClass(&WinClass))
{
...report error and terminate...
}
Logger::Inst() << " ~RegisterClass;" << endl;
//CREATE WINDOW
if (fullScreen)
{
if ((hwnd = CreateWindowEx(WS_EX_LEFT, "N2", "N2",
WS_POPUP,
0, 0, width, height,
NULL, NULL, hInstance, NULL)) == 0)
{
...report error and terminate...
}
}
else
{
if ((hwnd = CreateWindowEx(WS_EX_LEFT, "N2", "N2",
WS_OVERLAPPEDWINDOW,
0, 0, width, height,
NULL, NULL, hInstance, NULL)) == 0)
{
...report error and terminate...
}
}
Logger::Inst() << " ~CreateWindow;" << endl;
//PFD SETUP
PIXELFORMATDESCRIPTOR pfd =
{
sizeof(PIXELFORMATDESCRIPTOR),
1,
PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
PFD_TYPE_RGBA,
32,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
24,
8, 0, PFD_MAIN_PLANE, 0, 0, 0x00FF00FF, 0
};
//HDC
if ((hdc = GetDC(hwnd)) == NULL)
{
...report error and terminate...
}
Logger::Inst() << " ~GotHDC;" << endl;
//SET PIXEL FORMAT
indexPF = ChoosePixelFormat(hdc, &pfd);
if (!indexPF)
{
...report error and terminate...
}
if (!SetPixelFormat(hdc, indexPF, &pfd))
{
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_SWAP_EXCHANGE;
indexPF = ChoosePixelFormat(hdc, &pfd);
if (!SetPixelFormat(hdc, indexPF, &pfd))
{
...report error and terminate...
}
}
Logger::Inst() << " ~SetPFD;" << endl;
//TEMP CONTEXT TO ACQUIRE POINTER
HGLRC tempContext = wglCreateContext(hdc);
if (!tempContext) {
...report error and terminate...
}
if (!wglMakeCurrent(hdc, tempContext)) {
...report error and terminate...
}
int major, minor; glGetIntegerv(GL_MAJOR_VERSION, &major); glGetIntegerv(GL_MINOR_VERSION, &minor);
if (major < 4 || minor < 1) {
...report error and terminate...
}
const int attribs[] =
{
WGL_CONTEXT_MAJOR_VERSION_ARB, major,
WGL_CONTEXT_MINOR_VERSION_ARB, minor,
WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
0, 0
};
PFNWGLCREATEBUFFERREGIONARBPROC wglCreateContextAttribsARB = (PFNWGLCREATEBUFFERREGIONARBPROC)wglGetProcAddress("wglCreateContextAttribsARB");
if (!wglCreateContextAttribsARB) {
...report error and terminate...
}
**!!! CRASH HERE !!!**
if (!(hglrc = (HGLRC)wglCreateContextAttribsARB(hdc, 0, (UINT)attribs))) {
...report error and terminate...
}
Debugger shows it happens exactly at wglCreateContextAttribsARB(nvoglv64.dll!0000000074ccbdfa). That is a complete mystery to me. My only clue is that after switching to x64 it requires attributes passed as "UINT" instead of "const int*", i don't get that part, not even sure how conversion between each other supposed to work, seems fishy. Ideas?
You've got a typo: the type for wglCreateContextAttribsARB is wrong. It should be PFNWGLCREATECONTEXTATTRIBSARBPROC.
The reason it worked when you were targeting 32-bit is because the signature of the two is essentially the same in 32-bit:
wglCreateContextAttribsARB:
typedef HGLRC (WINAPI * PFNWGLCREATECONTEXTATTRIBSARBPROC) (HDC hDC, HGLRC hShareContext, const int *attribList);
wglCreateBufferRegionARB:
typedef HANDLE (WINAPI * PFNWGLCREATEBUFFERREGIONARBPROC) (HDC hDC, int iLayerPlane, UINT uType);
The second and third parameters to wglCreateContextAttribsARB are pointers (an HGLRC is a handle, which is just a pointer) and the second and third parameters to wglCreateBufferRegionARB are integers. In 32-bit, pointers are 32-bit in size, so the signatures are essentially the same.
In 64-bit, pointers are 64-bit in size, but integers are still 32-bit (assuming you're using MSVC) so those two pointers you were passing in were being truncated.
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
I tried to follow the example found:
Capturing an image from a minimized window
My code:
#include <iostream>
#include <string>
#include <windows.h>
#include <gdiplus.h>
#pragma comment(lib, "gdiplus.lib")
#pragma warning(disable : 4996)
using namespace std;
using namespace Gdiplus;
int GetEncoderClsid(LPCWSTR format, CLSID* pClsid)
{
unsigned int num = 0, size = 0;
GetImageEncodersSize(&num, &size);
if (size == 0) return -1;
ImageCodecInfo* pImageCodecInfo = (ImageCodecInfo*)(malloc(size));
if (pImageCodecInfo == NULL) return -1;
GetImageEncoders(num, size, pImageCodecInfo);
for (unsigned int j = 0; j < num; ++j) {
if (wcscmp(pImageCodecInfo[j].MimeType, format) == 0) {
*pClsid = pImageCodecInfo[j].Clsid;
free(pImageCodecInfo);
return j;
}
}
free(pImageCodecInfo);
return -1;
}
int SaveScreenshot(string filename, ULONG uQuality, HWND hwnd) // by Napalm
{
ULONG_PTR gdiplusToken;
GdiplusStartupInput gdiplusStartupInput;
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
HWND hMyWnd = hwnd;
//HWND hMyWnd = GetDesktopWindow();
RECT r;
int w, h;
HDC dc, hdcCapture;
int nBPP, nCapture, iRes;
LPBYTE lpCapture;
CLSID imageCLSID;
Bitmap* pScreenShot;
// get the area of my application's window
GetWindowRect(hMyWnd, &r);
dc = GetWindowDC(hMyWnd); // GetDC(hMyWnd) ;
w = r.right - r.left;
h = r.bottom - r.top;
nBPP = GetDeviceCaps(dc, BITSPIXEL);
hdcCapture = CreateCompatibleDC(dc);
// create the buffer for the screenshot
BITMAPINFO bmiCapture = { sizeof(BITMAPINFOHEADER), w, -h, 1, nBPP, BI_RGB, 0, 0, 0, 0, 0, };
// create a container and take the screenshot
HBITMAP hbmCapture = CreateDIBSection(dc, &bmiCapture, DIB_PAL_COLORS, (LPVOID*)&lpCapture, NULL, 0);
// failed to take it
if (!hbmCapture) {
DeleteDC(hdcCapture);
DeleteDC(dc);
GdiplusShutdown(gdiplusToken);
printf("failed to take the screenshot. err: %d\n", GetLastError());
return 0;
}
// copy the screenshot buffer
nCapture = SaveDC(hdcCapture);
SelectObject(hdcCapture, hbmCapture);
BitBlt(hdcCapture, 0, 0, w, h, dc, 0, 0, SRCCOPY);
RestoreDC(hdcCapture, nCapture);
DeleteDC(hdcCapture);
DeleteDC(dc);
// save the buffer to a file
pScreenShot = new Bitmap(hbmCapture, (HPALETTE)NULL);
EncoderParameters encoderParams;
encoderParams.Count = 1;
encoderParams.Parameter[0].NumberOfValues = 1;
encoderParams.Parameter[0].Guid = EncoderQuality;
encoderParams.Parameter[0].Type = EncoderParameterValueTypeLong;
encoderParams.Parameter[0].Value = &uQuality;
GetEncoderClsid(L"image/jpeg", &imageCLSID);
wchar_t* lpszFilename = new wchar_t[filename.length() + 1];
mbstowcs(lpszFilename, filename.c_str(), filename.length() + 1);
iRes = (pScreenShot->Save(lpszFilename, &imageCLSID, &encoderParams) == Ok);
delete pScreenShot;
DeleteObject(hbmCapture);
GdiplusShutdown(gdiplusToken);
return iRes;
}
int main() {
HWND hWnd;
hWnd = FindWindowA(NULL, "txt.txt - Bloco de Notas");
WINDOWPLACEMENT wp = { 0 };
wp.length = sizeof(WINDOWPLACEMENT);
GetWindowPlacement(hWnd, &wp);
ANIMATIONINFO ai = { 0 };
bool restoreAnimated = false;
if (wp.showCmd == SW_SHOWMINIMIZED)
{
ai.cbSize = sizeof(ANIMATIONINFO);
SystemParametersInfo(SPI_GETANIMATION, sizeof(ANIMATIONINFO), &ai, 0);
if (ai.iMinAnimate != 0)
{
ai.iMinAnimate = 0;
SystemParametersInfo(SPI_SETANIMATION, sizeof(ANIMATIONINFO), &ai, 0);
restoreAnimated = true;
}
// optionally move the window off-screen, or
// apply alpha using SetLayeredWindowAttributes()...
ShowWindow(hWnd, SW_SHOWNOACTIVATE);
}
// capture as needed ...
string path = "C:\\Users\\CAIO\\Desktop\\screenshot.jpg";
ULONG quality = 100;
SaveScreenshot(path, quality, hWnd);
if (wp.showCmd == SW_SHOWMINIMIZED)
{
SetWindowPlacement(hWnd, &wp);
// optionally remove alpha using SetLayeredWindowAttributes()...
if (restoreAnimated)
{
ai.iMinAnimate = 1;
SystemParametersInfo(SPI_SETANIMATION, sizeof(ANIMATIONINFO), &ai, 0);
}
}
return 0;
}
In her code there's restoreAnimation = true; and if (restoreAnimation) did he mean restoreAnimated?
With the code above it still shown the window for a sec, also the captured image is all black (maybe captured while minimized) or is not captured properly.
https://youtu.be/8b1wXxtaXsY?t=9
Sec 8 and 9 from the video you can see the window is being shown on the screen.
Suggestions?
did he mean restoreAnimated?
I think yes.
This code from #Remy only disables the animation effects when minimizing and restoring, the window will still be displayed for a short time when restoring. As the answer pointed out, you can use SetLayeredWindowAttributes to make the window nearly completely transparent(It should be noted that using SetLayeredWindowAttributes needs to ensure that hwnd has WS_EX_LAYERED style.) and then you will not see the window, but the operating system will.
In addition, the problem of incomplete window capture is because the window is not drawn completely, call UpdateWindow after ShowWindow works for me, it will send a WM_PAINT message to the window.
bool restoreAnimated = false;
BYTE Alph = 0;
LONG_PTR exstyle = 0;
if (wp.showCmd == SW_SHOWMINIMIZED)
{
ai.cbSize = sizeof(ANIMATIONINFO);
SystemParametersInfo(SPI_GETANIMATION, sizeof(ANIMATIONINFO), &ai, 0);
if (ai.iMinAnimate != 0)
{
ai.iMinAnimate = 0;
SystemParametersInfo(SPI_SETANIMATION, sizeof(ANIMATIONINFO), &ai, 0);
restoreAnimated = true;
}
// optionally move the window off-screen, or
// apply alpha using SetLayeredWindowAttributes()...
exstyle = GetWindowLongPtr(hWnd, GWL_EXSTYLE);
SetWindowLongPtr(hWnd, GWL_EXSTYLE, exstyle | WS_EX_LAYERED);
DWORD flag;
BOOL ret = GetLayeredWindowAttributes(hWnd, 0, &Alph, 0);
SetLayeredWindowAttributes(hWnd, 0, 1, LWA_ALPHA);
ShowWindow(hWnd, SW_SHOWNOACTIVATE);
UpdateWindow(hWnd);
}
// capture as needed ...
string path = "C:\\Users\\name\\Desktop\\screenshot.jpg";
ULONG quality = 100;
SaveScreenshot(path, quality, hWnd);
if (wp.showCmd == SW_SHOWMINIMIZED)
{
SetWindowPlacement(hWnd, &wp);
// optionally remove alpha using SetLayeredWindowAttributes()...
SetLayeredWindowAttributes(hWnd, 0, Alph, LWA_ALPHA);
SetWindowLongPtr(hWnd, GWL_EXSTYLE, exstyle);
if (restoreAnimated)
{
ai.iMinAnimate = 1;
SystemParametersInfo(SPI_SETANIMATION, sizeof(ANIMATIONINFO), &ai, 0);
}
}
I am trying to make a kind of popup notification window that slides out of the task bar.
At the moment I am only trying to get it to work if the taskbar is on bottom of screen, I have it working like it should.
But the problem im having is when the window is starting to appear/slide the bottom part of it flickers (depending on how big i have set my m_nIncrement value, it flashes the bottom area the same size as the m_nIncrement value)
The window disappears fine with no flicker.
//MyWindow
WNDCLASS wc =
{
CS_HREDRAW | CS_VREDRAW, __sWndProcDlg, 0, 0, g_hInst, nullptr,
LoadCursor(nullptr, IDC_ARROW), (HBRUSH)::GetStockObject(BLACK_BRUSH),
nullptr, m_lpszClassName
};
if (!RegisterClass(&wc))
return;
m_hWnd = CreateWindowEx(WS_EX_NOACTIVATE, m_lpszClassName, NULL, WS_POPUP | WS_VISIBLE, 0, 0, 0, 0, m_hWndParent, NULL, g_hInst, NULL);
//ShowWindow
void _ShowWindow(int _show)
{
unsigned int nDesktopWidth = m_rcDesktop.right - m_rcDesktop.left;
unsigned int nDesktopHeight = m_rcDesktop.bottom - m_rcDesktop.top;
unsigned int nScreenWidth = ::GetSystemMetrics(SM_CXSCREEN);
unsigned int nScreenHeight = ::GetSystemMetrics(SM_CYSCREEN);
BOOL bTaskbarOnRight = nDesktopWidth<nScreenWidth && m_rcDesktop.left == 0;
BOOL bTaskbarOnLeft = nDesktopWidth<nScreenWidth && m_rcDesktop.left != 0;
BOOL bTaskBarOnTop = nDesktopHeight<nScreenHeight && m_rcDesktop.top != 0;
BOOL bTaskbarOnBottom = nDesktopHeight<nScreenHeight && m_rcDesktop.top == 0;
if (_show)
{
ShowWindow(m_hWnd, SW_SHOW);
if (bTaskbarOnBottom)
{
m_nCurrentPos.cx = m_rcDesktop.right - m_sMaxSize.cx;
m_nCurrentPos.cy = m_rcDesktop.bottom - m_nCurrentSize.cy;
m_nTaskbarPlacement = TASKBAR_ON_BOTTOM;
}
KillTimer(m_hWnd, IDT_DISAPPEARING);
SetTimer(m_hWnd, IDT_APPEARING, 1, nullptr);
}
else
{
KillTimer(m_hWnd, IDT_APPEARING);
if (bTaskbarOnRight)
m_nCurrentPos.cx = m_rcDesktop.right - m_sMaxSize.cx;
else if (bTaskbarOnLeft)
m_nCurrentPos.cx = m_rcDesktop.left;
else if (bTaskBarOnTop)
m_nCurrentPos.cy = m_rcDesktop.top;
else //if (bTaskbarOnBottom)
m_nCurrentPos.cy = m_rcDesktop.bottom - m_nCurrentSize.cy;
SetTimer(m_hWnd, IDT_DISAPPEARING, 1, NULL);
}
}
//__OnTimer
LRESULT __OnTimer(HWND hWnd, UINT nIDEvent)
{
int m_nIncrement = 20;
if (nIDEvent == IDT_APPEARING)
{
switch (m_nTaskbarPlacement)
{
case TASKBAR_ON_BOTTOM:
if (m_nCurrentPos.cy > (m_rcDesktop.bottom - m_sMaxSize.cy))
{
m_nCurrentPos.cy -= m_nIncrement;
m_nCurrentSize.cy = m_rcDesktop.bottom - m_nCurrentPos.cy;
}
else
KillTimer(hWnd, IDT_APPEARING);
break;
}
SetFocus(hWnd);
SetWindowPos(hWnd, HWND_TOPMOST, m_nCurrentPos.cx, m_nCurrentPos.cy, m_sMaxSize.cx, m_nCurrentSize.cy, SWP_NOOWNERZORDER | SWP_NOZORDER | SWP_NOACTIVATE);
}
else if (nIDEvent == IDT_DISAPPEARING)
{
switch (m_nTaskbarPlacement)
{
case TASKBAR_ON_BOTTOM:
if (m_nCurrentPos.cy < m_rcDesktop.bottom)
{
m_nCurrentPos.cy += m_nIncrement;
m_nCurrentSize.cy = m_rcDesktop.bottom - m_nCurrentPos.cy;
}
else
{
KillTimer(hWnd, IDT_DISAPPEARING);
MoveWindow(m_hWnd, 0, 0, 0, 0, FALSE);
ShowWindow(m_hWnd, SW_HIDE);
}
break;
}
SetWindowPos(hWnd, HWND_TOPMOST, m_nCurrentPos.cx, m_nCurrentPos.cy, m_sMaxSize.cx, m_nCurrentSize.cy, SWP_NOOWNERZORDER | SWP_NOZORDER | SWP_NOACTIVATE);
}
return true;
}
use AnimateWindow instead. it is easy to use. you may need to handle WM_PRINT, and this also is quit straightforward.
if ever you want to keep working on your code then:
1) remove from popup class the flags CS_HREDRAW & CS_VREDRAW
2) handle WM_ERASEBACKGROUND
finally. if it is a popup window, do not call SetFocus(); maybe you have to set zorder to TOP_MOST
good luck
I had made a program using opengl in Ubuntu. Now, I want to produce .exe file from it. Would it be possible if I use g++ compiler in Windows and compile it ?
Depends on your code. Usually the device context is created on each platform in a different way
Windows:
hRC_ = wglCreateContextAttribsARB(hDC_, 0, attributes); // Create and OpenGL 3.x context based on the given attributes
if(hRC_ == 0)
{
GLenum error = glGetError();
// ... handle error
}
wglMakeCurrent(nullptr, nullptr); // Remove the temporary context from being active
wglDeleteContext(tempContext); // Delete the temporary OpenGL 2.1 context
wglMakeCurrent(hDC_, hRC_); // Make our OpenGL 3.0 context current
X11/GLX:
const char *glxExts = glXQueryExtensionsString( display_, DefaultScreen( display_ ) );
if(isExtensionSupported( glxExts, "GLX_ARB_create_context" )) // If the OpenGL 3.x context creation extension is available
{
glXCreateContextAttribsARB = (GLXContext(*)(Display* dpy, GLXFBConfig config, GLXContext share_context, Bool direct, const int *attrib_list))glXGetProcAddressARB((GLubyte*)"glXCreateContextAttribsARB");
hRC_ = glXCreateContextAttribsARB(display_, fbConfigs_[0], 0, true, attributes); // Create and OpenGL 3.x context based on the given attributes
if(!glXMakeCurrent(display_, window_, hRC_))
{
throw BlueFramework::BlueCore::Exception("Making context current failed.");
}; // Make our OpenGL 3.0 context current
GLenum err = glewInit(); // Enable GLEW
if (GLEW_OK != err) // If GLEW fails
{
std::cerr << err << std::endl;
std::cerr << "Error: " << glewGetString(err) << std::endl;
throw BlueFramework::BlueCore::Exception("GLEW is not initialized!");
}
}
There are also differences in the attributes handed over to XXXCreateContextAttribs:
Windows:
WGL_CONTEXT_MAJOR_VERSION_ARB, majorVersion_, // Set the MAJOR version of OpenGL
WGL_CONTEXT_MINOR_VERSION_ARB, miniorVersion_, // Set the MINOR version of OpenGL
WGL_CONTEXT_FLAGS_ARB,
WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB // Set our OpenGL context to be forward com
WGL_CONTEXT_PROFILE_MASK_ARB,
WGL_CONTEXT_CORE_PROFILE_BIT_ARB
...
X11/GLX:
GLX_CONTEXT_MAJOR_VERSION_ARB, majorVersion_, // Set the MAJOR version of OpenGL
GLX_CONTEXT_MINOR_VERSION_ARB, miniorVersion_, // Set the MINOR version of OpenGL
GLX_CONTEXT_FLAGS_ARB,
GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB // Set our OpenGL context to be forward compatible
//#ifdef _DEBUG
| GLX_CONTEXT_DEBUG_BIT_ARB
//#endif
,
GLX_CONTEXT_PROFILE_MASK_ARB,
GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
0
...
After device creation the OpenGL dependent code is almost the same. To create a render context in Win you need to create a Window handle.
Can look something like this:
// Register class
WNDCLASSEX wcex;
wcex.cbSize = sizeof( WNDCLASSEX );
wcex.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wcex.lpfnWndProc = (WNDPROC)RenderWindow::controlEventsProcessor;//WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = nullptr;//LoadIcon( hInstance, ( LPCTSTR )IDI_TUTORIAL1 );
wcex.hCursor = LoadCursor( NULL, IDC_ARROW );
if(fullscreen_)
{
wcex.hbrBackground = ( HBRUSH )( COLOR_WINDOW + 1 );
}
else
{
wcex.hbrBackground = ( HBRUSH )( COLOR_WINDOW + 1 );
}
wcex.lpszMenuName = NULL;
wcex.lpszClassName = wstrWindowClassName_.c_str(); //ss.str().c_str();
wcex.hIconSm = nullptr;//LoadIcon( wcex.hInstance, ( LPCTSTR )IDI_TUTORIAL1 );
if( !RegisterClassEx( &wcex ) )
{
BLUE_LOG_STREAM_EX(
"BlueFramework::BlueGraphicsEngine::RenderWindow::initWindow",
buw::eLogSeverityLevel::Error)
<< "RegisterClassEx failed";
return E_FAIL;
}
// Create window
hInstance = hInstance;
RECT rc = { 0, 0, width, height };
if(!AdjustWindowRect( &rc, WS_OVERLAPPEDWINDOW, FALSE ))
{
BLUE_LOG_STREAM_EX(
"BlueFramework::BlueGraphicsEngine::RenderWindow::initWindow",
buw::eLogSeverityLevel::Error)
<< "AdjustWindowRect failed";
}
if(fullscreen_)
{
hWnd_ = CreateWindowEx(0,
wstrWindowClassName_.c_str(),//L"BlueRenderWindow",//ss.str().c_str(),
L"Render Window",
WS_EX_TOPMOST | WS_POPUP, // fullscreen values
0, 0, // the starting x and y positions should be 0
rc.right - rc.left,
rc.bottom - rc.top,
nullptr,
nullptr,
hInstance,
nullptr);
}
else
{
hWnd_ = CreateWindowEx(0,
wstrWindowClassName_.c_str(),//L"BlueRenderWindow",//ss.str().c_str(),
L"Render Window",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
rc.right - rc.left,
rc.bottom - rc.top,
nullptr,
nullptr,
hInstance,
nullptr);
}
The counter part in X11/GLX can look something like this:
int attribs[] = {
GLX_RENDER_TYPE, GLX_RGBA_BIT,
GLX_X_RENDERABLE, True,
GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR,
GLX_DOUBLEBUFFER, True,
GLX_RED_SIZE, 8,
GLX_BLUE_SIZE, 8,
GLX_GREEN_SIZE, 8,
GLX_ALPHA_SIZE, 8,
GLX_DEPTH_SIZE, 24,
GLX_STENCIL_SIZE, 8,
0L //= None
};
display_ = XOpenDisplay(nullptr);
if(display_ == nullptr)
{
BLUE_LOG_STREAM_EX(
"BlueFramework::BlueGraphicsEngine::RenderWindow::initWindow",
buw::eLogSeverityLevel::Error)
<< "Cannot connect to X-Server";
return false;
}
int screenNr = XDefaultScreen (display_);
int numConfigs = 0;
// glXCreateContextAttribsARB = (GLXContext(*)(Display* dpy, GLXFBConfig config, GLXContext share_context, Bool direct, const int *attrib_list))glXGetProcAddressARB((GLubyte*)"glXCreateContextAttribsARB");
glXChooseFBConfig = (GLXFBConfig*(*)(Display *dpy, int screen, const int *attrib_list, int *nelements))glXGetProcAddressARB((GLubyte*)"glXChooseFBConfig");
glXGetVisualFromFBConfig = (XVisualInfo*(*)(Display *dpy, GLXFBConfig config))glXGetProcAddressARB((GLubyte*)"glXGetVisualFromFBConfig");
fbConfigs_ = glXChooseFBConfig(display_, XDefaultScreen(display_), attribs, &numConfigs);
if(fbConfigs_ == nullptr)
{
BLUE_LOG_STREAM_EX(
"BlueFramework::BlueGraphicsEngine::RenderWindow::initWindow",
buw::eLogSeverityLevel::Error)
<< "Failed to get framebuffer config";
return false;
}
XVisualInfo* vi = glXGetVisualFromFBConfig(display_, fbConfigs_[0]);
if(vi == nullptr)
{
BLUE_LOG_STREAM_EX(
"BlueFramework::BlueGraphicsEngine::RenderWindow::initWindow",
buw::eLogSeverityLevel::Error)
<< "No appropriate visual found (X-Server)";
return false;
}
bool doubleBuffered = true;
Colormap cmap = XCreateColormap (display_, RootWindow (display_, vi->screen),
vi->visual, AllocNone);
XSetWindowAttributes attributes;
attributes.background_pixmap = 0L;
attributes.colormap = cmap;
attributes.border_pixel = 0;
The easy way would be with cygwin and freeglut, as well as, perhaps, glew.
I'm writing some OpenGL 3 program on C++, and now i have an issue on my laptop Lenovo Thinkpad e320 (Intel HD Graphics 3000). It works fine on my PC (ATI Radeon HD 5870).
Code near the error is following:
bool GLWindowCreate(const char *title, int width, int height, bool fullScreen){
...
g_hRC = wglCreateContextAttribsARB(g_hDC, 0, attribs);
if (!g_hRC || !wglMakeCurrent(g_hDC, g_hRC))
{
LOG_ERROR("Creating render context fail (%d)\n", GetLastError());
return false;
}
...
}
All compiles fine and i saw this error in log file.
I'm using Windows 8 (both on PC and laptop). Graphic card on laptop supports OpenGL 3. I have found some answer about same problem that i need to turn off hardware acceleration, but it seems there is no way to do this in Win 8.
Added:
Whole window create function:
bool GLWindowCreate(const char *title, int width, int height, bool fullScreen)
{
ASSERT(title);
ASSERT(width > 0);
ASSERT(height > 0);
WNDCLASSEX wcx;
PIXELFORMATDESCRIPTOR pfd;
RECT rect;
HGLRC hRCTemp;
DWORD style, exStyle;
int x, y, format;
memset(&g_window, 0, sizeof(g_window));
memset(&g_input, 0, sizeof(g_input));
PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = NULL;
// attributes for OpenGL context
int attribs[] =
{
WGL_CONTEXT_MAJOR_VERSION_ARB, 3,
WGL_CONTEXT_MINOR_VERSION_ARB, 3,
WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
0
};
// timer init
QueryPerformanceFrequency(&g_qpc);
ASSERT(g_qpc.QuadPart > 0);
g_timerFrequency = 1.0 / g_qpc.QuadPart;
g_hInstance = (HINSTANCE)GetModuleHandle(NULL);
memset(&wcx, 0, sizeof(wcx));
wcx.cbSize = sizeof(wcx);
wcx.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wcx.lpfnWndProc = (WNDPROC)GLWindowProc;
wcx.hInstance = g_hInstance;
wcx.lpszClassName = GLWINDOW_CLASS_NAME;
wcx.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wcx.hCursor = LoadCursor(NULL, IDC_ARROW);
if (!RegisterClassEx(&wcx))
{
LOG_ERROR("RegisterClassEx fail (%d)\n", GetLastError());
return false;
}
style = WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX;
exStyle = WS_EX_APPWINDOW;
x = (GetSystemMetrics(SM_CXSCREEN) - width) / 2;
y = (GetSystemMetrics(SM_CYSCREEN) - height) / 2;
rect.left = x;
rect.right = x + width;
rect.top = y;
rect.bottom = y + height;
AdjustWindowRectEx (&rect, style, FALSE, exStyle);
// creating window
g_hWnd = CreateWindowEx(exStyle, GLWINDOW_CLASS_NAME, title, style, rect.left, rect.top,
rect.right - rect.left, rect.bottom - rect.top, NULL, NULL, g_hInstance, NULL);
if (!g_hWnd)
{
LOG_ERROR("CreateWindowEx fail (%d)\n", GetLastError());
return false;
}
// get window descriptor
g_hDC = GetDC(g_hWnd);
if (!g_hDC)
{
LOG_ERROR("GetDC fail (%d)\n", GetLastError());
return false;
}
memset(&pfd, 0, sizeof(pfd));
pfd.nSize = sizeof(pfd);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 32;
pfd.cDepthBits = 24;
// get pixel format
format = ChoosePixelFormat(g_hDC, &pfd);
if (!format || !SetPixelFormat(g_hDC, format, &pfd))
{
LOG_ERROR("Setting pixel format fail (%d)\n", GetLastError());
return false;
}
// creating temp context
// to get wglCreateContextAttribsARB function
hRCTemp = wglCreateContext(g_hDC);
if (!hRCTemp || !wglMakeCurrent(g_hDC, hRCTemp))
{
LOG_ERROR("Сreating temp render context fail (%d)\n", GetLastError());
return false;
}
OPENGL_GET_PROC(PFNWGLCREATECONTEXTATTRIBSARBPROC, wglCreateContextAttribsARB);
// delete temp context
wglMakeCurrent(NULL, NULL);
wglDeleteContext(hRCTemp);
// creating OpenGL 3 context
g_hRC = wglCreateContextAttribsARB(g_hDC, 0, attribs);
if (!g_hRC || !wglMakeCurrent(g_hDC, g_hRC))
{
LOG_ERROR("Creating render context fail (%d)\n", GetLastError());
return false;
}
int major, minor;
glGetIntegerv(GL_MAJOR_VERSION, &major);
glGetIntegerv(GL_MINOR_VERSION, &minor);
LOG_DEBUG("OpenGL render context information:\n"
" Renderer : %s\n"
" Vendor : %s\n"
" Version : %s\n"
" GLSL version : %s\n"
" OpenGL version : %d.%d\n",
(const char*)glGetString(GL_RENDERER),
(const char*)glGetString(GL_VENDOR),
(const char*)glGetString(GL_VERSION),
(const char*)glGetString(GL_SHADING_LANGUAGE_VERSION),
major, minor
);
if (!OpenGLInitExtensions())
return false;
GLWindowSetSize(width, height, fullScreen);
return true;
}
I have accidentally found a decision. Problem was there:
int attribs[] =
{
WGL_CONTEXT_MAJOR_VERSION_ARB, 3,
WGL_CONTEXT_MINOR_VERSION_ARB, 3,
WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
0
};
Intel HD Graphics 3000 supports only OpenGL 3.1, not 3.3, so i have had to change
WGL_CONTEXT_MINOR_VERSION_ARB, 3,
to
WGL_CONTEXT_MINOR_VERSION_ARB, 1,
Thanks everyone and sorry for worry, hope my problem solution will help someone
I decided to add MSAA support into my application and therefor I checked what's up to do. The examples I found always refer to WGL_SAMPLE_BUFFERS_ARB / WGL_SAMPLES_ARB in the pixelformatdescriptor to do that. I am using glew right now:
int DesiredColorBits = 32;
int DesiredStencilBits = 0;
int DesiredDepthBits = 24;
int MajorVersion=3;
int MinorVersion=3;
PIXELFORMATDESCRIPTOR temppfd =
{
sizeof(PIXELFORMATDESCRIPTOR),
1,
PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
PFD_TYPE_RGBA,
DesiredColorBits,
0, 0, 0, 0, 0, 0,
0, 0,
0, 0, 0, 0, 0,
DesiredDepthBits,
0,//DesiredStencilBits,
0,
PFD_MAIN_PLANE,
0,
0, 0, 0
};
HDC TemphDC;
TemphDC = GetDC( hWnd );
int nPixelFormat = ChoosePixelFormat( TemphDC, &temppfd );
check(nPixelFormat);
verify(SetPixelFormat( TemphDC, nPixelFormat, &temppfd ));
// oldstyle context to init glew.
HGLRC tempContext = wglCreateContext(TemphDC);
wglMakeCurrent(TemphDC, tempContext);
//init glew
glewExperimental = GL_TRUE;
GLenum err = glewInit();
if (GLEW_OK != err)
errorprintf(TEXT("Error: Init glew failed: %s"), glewGetErrorString(err)));
else debugprintf( TEXT("Glew successfully initialized."));
ReleaseDC(hWnd, TemphDC);
//Now init pure OpenGL >= 3.3 context.
if (WGLEW_ARB_create_context && WGLEW_ARB_pixel_format)
{
wglMakeCurrent(NULL, NULL);
wglDeleteContext(tempContext);
PIXELFORMATDESCRIPTOR pfd;
memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DOUBLEBUFFER | PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = DesiredColorBits;
pfd.cDepthBits = DesiredDepthBits;
pfd.iLayerType = PFD_MAIN_PLANE;
int iPixelFormatAttribList[30];
iPixelFormatAttribList[0] = WGL_DRAW_TO_WINDOW_ARB;
iPixelFormatAttribList[1] = GL_TRUE;
iPixelFormatAttribList[2] = WGL_SUPPORT_OPENGL_ARB;
iPixelFormatAttribList[3] = GL_TRUE;
iPixelFormatAttribList[4] = WGL_DOUBLE_BUFFER_ARB;
iPixelFormatAttribList[5] = GL_TRUE;
iPixelFormatAttribList[6] = WGL_PIXEL_TYPE_ARB;
iPixelFormatAttribList[7] = WGL_TYPE_RGBA_ARB;
iPixelFormatAttribList[8] = WGL_COLOR_BITS_ARB;
iPixelFormatAttribList[9] = DesiredColorBits;
iPixelFormatAttribList[10] = WGL_DEPTH_BITS_ARB;
iPixelFormatAttribList[11] = DesiredDepthBits;
iPixelFormatAttribList[12] = WGL_STENCIL_BITS_ARB;
iPixelFormatAttribList[13] = 0;
iPixelFormatAttribList[14] = WGL_SAMPLE_BUFFERS_ARB;
iPixelFormatAttribList[15] = GL_TRUE;
iPixelFormatAttribList[16] = WGL_SAMPLES_ARB;
iPixelFormatAttribList[17] = NumAASamples;
iPixelFormatAttribList[18] = 0;
int iPixelFormat, iNumFormats;
wglChoosePixelFormatARB(hDC, iPixelFormatAttribList, NULL, 1, &iPixelFormat, (GLuint*)&iNumFormats);
if( iNumFormats == 0 )
{
debugprintf(TEXT("Couldn't support multisampling"));
}
else debugprintf(TEXT("Available formats: %i %i"),iNumFormats,iPixelFormat);
int iContextAttribs[] =
{
WGL_CONTEXT_MAJOR_VERSION_ARB, MajorVersion,
WGL_CONTEXT_MINOR_VERSION_ARB, MinorVersion,
WGL_CONTEXT_FLAGS_ARB, ContextFlags,
0 // End of attributes list
};
// pfd oldstyle crap...
debugprintf(TEXT("DesiredColorBits: %i"), DesiredColorBits);
debugprintf(TEXT("DesiredDepthBits: %i"), DesiredDepthBits);
if (!SetPixelFormat(hDC, iPixelFormat, &pfd))
{
debugprintf(TEXT("Setting PixelFormat %i failed!"), iPixelFormat);
iPixelFormat = ChoosePixelFormat(hDC, &pfd);
if (!SetPixelFormat(hDC, iPixelFormat, &pfd))
errorprintf(TEXT("Error: SetPixelFormat %i failed."),iPixelFormat);
}
hRC = wglCreateContextAttribsARB(hDC, 0, iContextAttribs);
}
else errorprintf(TEXT("Error: Init glew failed: %s"), glewGetErrorString(err)));
if(hRC)
{
MakeCurrent();
debugprintf( TEXT("GL_VENDOR : %s"), glGetString(GL_VENDOR));
debugprintf( TEXT("GL_RENDERER : %s"), glGetString(GL_RENDERER));
debugprintf( TEXT("GL_VERSION : %s"), glGetString(GL_VERSION));
debugprintf( TEXT("GLEW Version : %s"), glewGetString(GLEW_VERSION));
int NumberOfAASamples=0, NumberOfSampleBufers;
glGetintegerv(GL_SAMPLE_BUFFERS,&NumberOfSampleBufers);
glGetintegerv(GL_SAMPLES,&NumberOfAASamples);
debugprintf(TEXT("SampleBuffers: %i, NumAASamples: (%i/%i)"),NumberOfSampleBufers, NumberOfAASamples,NumAASamples);
int NumberOfExtensions=0;
glGetintegerv(GL_NUM_EXTENSIONS, &NumberOfExtensions);
for (int i = 0; i<NumberOfExtensions; i++)
{
FString ExtensionString = glGetStringi(GL_EXTENSIONS, i));
debugprintf(NAME_DevLoad, TEXT("GL_EXTENSIONS(%i) : %s"), i, ExtensionString);
}
debugprintf( TEXT("OpenGL %i.%i context initialized!"), MajorVersion,MinorVersion);
}
So far, so good, I am getting my tempcontext to init glew, it initializes correctly and is ready to use, also no problems with SetPixelFormat- without sample buffers at least.
Now if I am adding WGL_SAMPLE_BUFFERS_ARB and WGL_SAMPLES_ARB I still get a pixelformat back from wglChoosePixelFormatARB (indeed iNumFormats returns 32), but SetPixelFormat always fails with the pixelformat returned from it.
I tried various color and depth bits, but no matter what I do, I can't seem to find a way to make this work. I also tried this on my NVidia and an Intel card, no AA preset is forced either.
Now- is there a different way to get this result? I take it that SetPixelformat is "deprecated", partially even obsolete from what I read, yet I seem to need it here to enable MSAA, which is a kinda annoying dependency.
Did I miss something?
I solved it by changing one thing, I created a completely standalone window for glew init like this:
LRESULT CALLBACK WndProc(HWND hWnd, UINT uiMsg, WPARAM wParam, LPARAM lParam)
{
switch(uiMsg)
{
case WM_CLOSE:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, uiMsg, wParam, lParam);
}
return 0;
}
PIXELFORMATDESCRIPTOR temppfd =
{
sizeof(PIXELFORMATDESCRIPTOR),
1,
PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
PFD_TYPE_RGBA,
DesiredColorBits,
0, 0, 0, 0, 0, 0,
0, 0,
0, 0, 0, 0, 0,
DesiredDepthBits,
0,//DesiredStencilBits,
0,
PFD_MAIN_PLANE,
0,
0, 0, 0
};
DWORD Style = WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
WNDCLASSEX WndClassEx;
memset(&WndClassEx, 0, sizeof(WNDCLASSEX));
WndClassEx.cbSize = sizeof(WNDCLASSEX);
WndClassEx.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
WndClassEx.lpfnWndProc = WndProc;
WndClassEx.hInstance = hInstance;
WndClassEx.hIcon = LoadIcon(NULL, IDI_APPLICATION);
WndClassEx.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
WndClassEx.hCursor = LoadCursor(NULL, IDC_ARROW);
WndClassEx.lpszClassName = L"Win32OpenGLWindow";
if(RegisterClassEx(&WndClassEx) == 0)
{
debugprintf(TEXT("RegisterClassEx failed!"));
}
HWND TemphWnd = CreateWindowEx(WS_EX_APPWINDOW, WndClassEx.lpszClassName, L"InitWIndow", Style, 0, 0, SizeX, SizeY, NULL, NULL, hInstance, NULL);
HDC TemphDC = GetDC( TemphWnd );
INT nPixelFormat = ChoosePixelFormat( TemphDC, &temppfd );
check(nPixelFormat);
verify(SetPixelFormat( TemphDC, nPixelFormat, &temppfd ));
// oldstyle context to init glew.
HGLRC tempContext = wglCreateContext(TemphDC);
wglMakeCurrent(TemphDC, tempContext);
//init glew
glewExperimental = GL_TRUE;
GLenum err = glewInit();
if (GLEW_OK != err)
errorprintf(TEXT("Error: Init glew failed: %s"),glewGetErrorString(err));
else debugprintf(TEXT("Glew successfully initialized."));
//Now init pure OpenGL >= 3.3 context.
if (WGLEW_ARB_create_context && WGLEW_ARB_pixel_format)
{
wglMakeCurrent(NULL, NULL);
wglDeleteContext(tempContext);
ReleaseDC(TemphWnd, TemphDC);
DestroyWindow(TemphWnd);
...
After destroying this temp window and then using the actual one for the game like shown above it was possible to use SetPixelFormat with the new options. Why it didn't cause any trouble like this when not adding WGL_SAMPLE_BUFFERS_ARB / WGL_SAMPLES_ARB I don't know, I assume that it is not possible to really change the pixelformat for a window afterwards, unrelated to any hWnd, hDC or context and if those are destroyed or renewed in between. Many examples and tutorials in the web are not clear about that and are showing this indeed the wrong way too.
In short, create a tempwindow, temphWnd and temphDC, then init glew, destroy all temporary stuff, then go on creating the context you really want with the real window, hWnd and hDC, otherwise you'll buy some trouble.
Yes, I think it is a real mess to get clean context in windows.
Either way, I hope this will help others.