//----------------------------------------------------------------------------- bool Win32Context::initWin32GLContext(HGLRC share_context, const vl::String& title, const vl::OpenGLContextFormat& fmt, int x, int y, int width, int height) { class InOutContract { Win32Context* mContext; public: bool mOK; InOutContract(Win32Context* context): mContext(context), mOK(true) { cleanup(); } ~InOutContract() { if (!mOK) cleanup(); } void cleanup() { // delete HDC if (mContext->mHDC) { DeleteDC(mContext->mHDC); mContext->mHDC = NULL; } // delete HGLRC if (mContext->mHGLRC) { if ( wglDeleteContext(mContext->mHGLRC) == FALSE ) { MessageBox(NULL, L"OpenGL context cleanup failed.\n" L"The handle either doesn't specify a valid context or the context is being used by another thread.", L"Win32Context::init() error!", MB_OK); mOK = false; } mContext->mHGLRC = NULL; } } } contract(this); if (!contract.mOK) return false; framebuffer()->setWidth(width); framebuffer()->setHeight(height); if (!hwnd()) { MessageBox(NULL, L"Cannot create OpenGL context: null HWND.", L"Win32Context::init() error!", MB_OK); return contract.mOK = false; } setWindowTitle(title); VL_CHECK(mHDC == NULL); mHDC = ::GetDC(hwnd()); if (!mHDC) { MessageBox(NULL, L"Device context acquisition failed.", L"Win32Context::init() error!", MB_OK); return contract.mOK = false; } int pixel_format_index = vlWin32::choosePixelFormat(fmt); if (pixel_format_index == -1) { MessageBox(NULL, L"No suitable pixel fmt found.", L"Win32Context::init() error!", MB_OK); return contract.mOK = false; } if (SetPixelFormat(mHDC, pixel_format_index, NULL) == FALSE) { MessageBox(NULL, L"Pixel fmt setup failed.", L"Win32Context::init() error!", MB_OK); return contract.mOK = false; } // OpenGL rendering context creation if (wglCreateContextAttribsARB && mContextAttribs.size() > 1) { // must be 0-terminated list VL_CHECK(mContextAttribs.back() == 0); // Creates an OpenGL 3.x / 4.x context with the specified attributes. mHGLRC = wglCreateContextAttribsARB(mHDC, 0, &mContextAttribs[0]); } else { // Creates default OpenGL context mHGLRC = wglCreateContext(mHDC); } if (!mHGLRC) { MessageBox(NULL, L"OpenGL rendering context creation failed.", L"Win32Context::init() error!", MB_OK); return contract.mOK = false; } // init GL context and makes it current // mic fixme: check this also on all the other GUI bindings. if( !initGLContext() ) return contract.mOK = false; if (fmt.multisample() && !Has_GL_ARB_multisample) vl::Log::error("WGL_ARB_multisample not supported.\n"); dispatchInitEvent(); setPosition(x, y); setSize(width, height); if (Has_GL_EXT_swap_control) wglSwapIntervalEXT( fmt.vSync() ? 1 : 0 ); if (share_context) shareOpenGLResources(share_context); if (fmt.fullscreen()) setFullscreen(true); return contract.mOK = true; }
//----------------------------------------------------------------------------- int vlWin32::choosePixelFormat(const vl::OpenGLContextFormat& fmt, bool verbose) { if (!registerClass()) return false; // this is true only under Win32 // VL_CHECK( sizeof(wchar_t) == sizeof(short int) ) HWND hWnd = CreateWindowEx( WS_EX_APPWINDOW | WS_EX_ACCEPTFILES, gWin32WindowClassName, L"Temp GL Window", WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, GetModuleHandle(NULL), NULL); if (!hWnd) { if (verbose) MessageBox(NULL, L"choosePixelFormat() critical failure: could not create window.", L"Visualization Library error", MB_OK); return -1; } HDC hDC = GetDC(hWnd); if (!hDC) { if (verbose) MessageBox(NULL, L"choosePixelFormat() critical failure: could not create HDC.", L"Visualization Library error", MB_OK); DestroyWindow(hWnd); return -1; } PIXELFORMATDESCRIPTOR pfd; memset(&pfd, 0, sizeof(pfd)); pfd.nSize = sizeof(pfd); pfd.nVersion = 1; pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL; pfd.dwFlags |= fmt.doubleBuffer() ? PFD_DOUBLEBUFFER : 0; pfd.dwFlags |= fmt.stereo() ? PFD_STEREO : 0; pfd.iPixelType = PFD_TYPE_RGBA; pfd.cColorBits = 0; pfd.cRedBits = (BYTE)fmt.rgbaBits().r(); pfd.cGreenBits = (BYTE)fmt.rgbaBits().g(); pfd.cBlueBits = (BYTE)fmt.rgbaBits().b(); pfd.cAlphaBits = (BYTE)fmt.rgbaBits().a(); pfd.cAccumRedBits = (BYTE)fmt.accumRGBABits().r(); pfd.cAccumGreenBits = (BYTE)fmt.accumRGBABits().g(); pfd.cAccumBlueBits = (BYTE)fmt.accumRGBABits().b(); pfd.cAccumAlphaBits = (BYTE)fmt.accumRGBABits().a(); pfd.cDepthBits = (BYTE)fmt.depthBufferBits(); pfd.cStencilBits = (BYTE)fmt.stencilBufferBits(); pfd.iLayerType = PFD_MAIN_PLANE; int pixel_format_index = ChoosePixelFormat(hDC, &pfd); if (pixel_format_index == 0) { if (verbose) MessageBox(NULL, L"choosePixelFormat() critical failure: could not choose temporary format.", L"Visualization Library error", MB_OK); DeleteDC(hDC); DestroyWindow(hWnd); return -1; } if (SetPixelFormat(hDC, pixel_format_index, &pfd) == FALSE) { if (verbose) MessageBox(NULL, L"choosePixelFormat() critical failure: could not set temporary format.", L"Visualization Library error", MB_OK); DeleteDC(hDC); DestroyWindow(hWnd); return -1; } // OpenGL Rendering Context HGLRC hGLRC = wglCreateContext(hDC); if (!hGLRC) { if (verbose) MessageBox(NULL, L"choosePixelFormat() critical failure: could not create temporary OpenGL context.", L"Visualization Library error", MB_OK); DeleteDC(hDC); DestroyWindow(hWnd); return -1; } wglMakeCurrent(hDC, hGLRC); if (!initializeOpenGL()) { fprintf(stderr, "Error initializing OpenGL!\n"); DeleteDC(hDC); DestroyWindow(hWnd); return -1; } // if this is not supported we use the current 'pixel_format_index' returned by ChoosePixelFormat above. int samples = 0; if(Has_WGL_ARB_pixel_format && fmt.multisample()) { float fAttributes[] = { 0, 0 }; int iAttributes[] = { // multi sampling WGL_SAMPLE_BUFFERS_ARB, GL_TRUE, WGL_SAMPLES_ARB, -1, // this is set below // generic WGL_DRAW_TO_WINDOW_ARB, GL_TRUE, WGL_SUPPORT_OPENGL_ARB, GL_TRUE, WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB, // color buffer WGL_RED_BITS_ARB, pfd.cRedBits, WGL_GREEN_BITS_ARB, pfd.cGreenBits, WGL_BLUE_BITS_ARB, pfd.cBlueBits, WGL_ALPHA_BITS_ARB, pfd.cAlphaBits, // accumulation buffer WGL_ACCUM_RED_BITS_ARB, pfd.cAccumRedBits, WGL_ACCUM_GREEN_BITS_ARB, pfd.cAccumGreenBits, WGL_ACCUM_BLUE_BITS_ARB, pfd.cAccumBlueBits, WGL_ACCUM_ALPHA_BITS_ARB, pfd.cAccumAlphaBits, // depth buffer WGL_DEPTH_BITS_ARB, pfd.cDepthBits, WGL_DOUBLE_BUFFER_ARB, fmt.doubleBuffer() ? GL_TRUE : GL_FALSE, // stencil buffer WGL_STENCIL_BITS_ARB, pfd.cStencilBits, // stereo WGL_STEREO_ARB, fmt.stereo() ? GL_TRUE : GL_FALSE, 0,0 }; for(samples = fmt.multisampleSamples(); samples > 1; samples/=2) { // sets WGL_SAMPLES_ARB value iAttributes[3] = samples; pixel_format_index = -1; UINT num_formats = 0; if ( wglChoosePixelFormatARB(hDC,iAttributes,fAttributes,1,&pixel_format_index,&num_formats) && num_formats >= 1 ) break; else pixel_format_index = -1; } } // destroy temporary HWND, HDC, HGLRC if ( wglDeleteContext(hGLRC) == FALSE ) if (verbose) MessageBox(NULL, L"Error deleting temporary OpenGL context, wglDeleteContext(hGLRC) failed.", L"Visualization Library error", MB_OK); DeleteDC(hDC); DestroyWindow(hWnd); if (verbose) { if(pixel_format_index == -1) vl::Log::error("No suitable pixel format found.\n"); else { // check the returned pixel format #if defined(DEBUG) || !defined(NDEBUG) DescribePixelFormat(hDC, pixel_format_index, sizeof(PIXELFORMATDESCRIPTOR), &pfd); vl::Log::debug(" --- vlWin32::choosePixelFormat() ---\n"); // This one returns "not supported" even when its supported... // vl::Log::print( vl::Say(" OpenGL = %s\n") << (pfd.dwFlags & PFD_SUPPORT_OPENGL ? "Supported" : "Not supported") ); vl::Log::debug( vl::Say("RGBA Bits = %n %n %n %n\n") << pfd.cRedBits << pfd.cGreenBits << pfd.cBlueBits << pfd.cAlphaBits); vl::Log::debug( vl::Say("Depth Bits = %n\n") << pfd.cDepthBits ); vl::Log::debug( vl::Say("Stencil Bits = %n \n") << pfd.cStencilBits); vl::Log::debug( vl::Say("Double Buffer = %s\n") << (pfd.dwFlags & PFD_DOUBLEBUFFER ? "Yes" : "No") ); vl::Log::debug( vl::Say("Stereo = %s\n") << (pfd.dwFlags & PFD_STEREO ? "Yes" : "No") ); vl::Log::debug( vl::Say("Samples = %n\n") << samples ); vl::Log::debug("\n"); #endif } } return pixel_format_index; }
//----------------------------------------------------------------------------- bool SDLWindow::initSDLWindow(const vl::String& title, const vl::OpenGLContextFormat& info, int x, int y, int width, int height) { if (mScreen || mSDLWindow) { vl::Log::error("SDL supports only one window at a time.\n"); VL_TRAP(); return false; } framebuffer()->setWidth(width); framebuffer()->setHeight(height); mSDLWindow = this; // init key translation map for(int i=0; key_translation_vec[i]; i+=2) key_translation_map[ key_translation_vec[i] ] = (vl::EKey)key_translation_vec[i+1]; // SDL_VIDEO_WINDOW_POS char win_pos[32] = {0}; sprintf ( win_pos, "SDL_VIDEO_WINDOW_POS=%d,%d", x, y ); SDL_putenv(win_pos); // setenv("SDL_VIDEO_CENTERED", "YES", 0); // init SDL if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) { printf("Unable to init SDL: %s\n", SDL_GetError()); return false; } SDL_GL_SetAttribute(SDL_GL_RED_SIZE, info.rgbaBits().r()); SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, info.rgbaBits().g()); SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, info.rgbaBits().b()); SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, info.rgbaBits().a()); SDL_GL_SetAttribute(SDL_GL_ACCUM_RED_SIZE, info.accumRGBABits().r()); SDL_GL_SetAttribute(SDL_GL_ACCUM_GREEN_SIZE, info.accumRGBABits().g()); SDL_GL_SetAttribute(SDL_GL_ACCUM_BLUE_SIZE, info.accumRGBABits().b()); SDL_GL_SetAttribute(SDL_GL_ACCUM_ALPHA_SIZE, info.accumRGBABits().a()); SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, info.depthBufferBits()); SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, info.stencilBufferBits()); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, info.doubleBuffer()?1:0); SDL_GL_SetAttribute(SDL_GL_STEREO, info.stereo()); SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, info.multisample()?1:0); if (info.multisample()) SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, info.multisampleSamples()); SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, info.vSync()); int bpp = SDL_GetVideoInfo()->vfmt->BitsPerPixel; Uint32 flags = SDL_OPENGL | (info.fullscreen() ? SDL_FULLSCREEN : 0); width = width !=0 ? width : SDL_GetVideoInfo()->current_w; height = height !=0 ? height : SDL_GetVideoInfo()->current_h; mScreen = SDL_SetVideoMode( width, height, bpp, flags ); if (mScreen == 0) { vl::Log::print( vl::Say("\n error: SDL_SetVideoMode(%n, %n, %n, %hn) failed: %s\n") << width << height << bpp << flags << SDL_GetError() ); exit(1); } // window size problem int viewport[4]; glGetIntegerv(GL_VIEWPORT, viewport); VL_CHECK(viewport[0] == 0); VL_CHECK(viewport[1] == 0); if (viewport[2] != mScreen->w || viewport[3] != mScreen->h) { vl::Log::print( vl::Say("\n warning: OpenGL reported %nx%n as video size but SDL says %nx%n\n") << viewport[2] << viewport[3] << mScreen->w << mScreen->h ); VL_TRAP() }