00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include <vlWin32/Win32Context.hpp>
00033 #include <vlCore/Log.hpp>
00034
00035 using namespace vl;
00036 using namespace vlWin32;
00037
00038
00039 Win32Context::~Win32Context()
00040 {
00041 }
00042
00043 void Win32Context::shareOpenGLResources(HGLRC hGLRC)
00044 {
00045 if (hwnd() && mHDC && mHGLRC)
00046 wglShareLists(hglrc(), hGLRC);
00047 }
00048
00049 void Win32Context::makeCurrent()
00050 {
00051 if (mHDC && mHGLRC)
00052 wglMakeCurrent(mHDC, mHGLRC);
00053 }
00054
00055 void Win32Context::update()
00056 {
00057 if (hwnd())
00058 PostMessage(hwnd(), WM_PAINT, 0, 0);
00059 }
00060
00061 void Win32Context::quitApplication()
00062 {
00063 PostQuitMessage(0);
00064 }
00065
00066 void Win32Context::setMouseVisible(bool visible)
00067 {
00068 mMouseVisible = visible;
00069 if (visible)
00070 while(ShowCursor(TRUE ) < 0) {}
00071 else
00072 while(ShowCursor(FALSE) >= 0) {}
00073 }
00074
00075 void Win32Context::setPosition(int x, int y)
00076 {
00077 if (hwnd())
00078 SetWindowPos(hwnd(), 0, x, y, 0, 0, SWP_NOSIZE );
00079 }
00080
00081 void Win32Context::setSize(int w, int h)
00082 {
00083 if (hwnd())
00084 {
00085 RECT windowRect = { 0, 0, w, h };
00086 AdjustWindowRectEx(&windowRect, (DWORD)GetWindowLongPtr(hwnd(), GWL_STYLE), 0, (DWORD)GetWindowLongPtr(hwnd(), GWL_EXSTYLE) );
00087
00088 int cx = windowRect.right - windowRect.left;
00089 int cy = windowRect.bottom - windowRect.top;
00090 SetWindowPos(hwnd(), 0, 0, 0, cx, cy, SWP_NOMOVE );
00091 }
00092 }
00093
00094 void Win32Context::setWindowSize(int w, int h)
00095 {
00096
00097
00098
00099 SetWindowPos(hwnd(), 0, 0, 0, w, h, SWP_NOMOVE);
00100 }
00101
00102 vl::ivec2 Win32Context::position() const
00103 {
00104 RECT r = {0,0,0,0};
00105 if (hwnd())
00106 GetWindowRect(hwnd(), &r);
00107 return vl::ivec2(r.left,r.top);
00108 }
00109
00110 vl::ivec2 Win32Context::windowSize() const
00111 {
00112 RECT r = {0,0,0,0};
00113 if (hwnd())
00114 GetWindowRect(hwnd(), &r);
00115 return vl::ivec2(r.right - r.left, r.bottom - r.top);
00116 }
00117
00118 vl::ivec2 Win32Context::size() const
00119 {
00120 RECT r = {0,0,0,0};
00121 if (hwnd())
00122 GetClientRect(hwnd(), &r);
00123 return vl::ivec2(r.right - r.left, r.bottom - r.top);
00124
00125 }
00126
00127 void Win32Context::setWindowTitle(const String& title)
00128 {
00129 if (hwnd())
00130 SetWindowText(hwnd(), (wchar_t*)title.ptr());
00131 }
00132
00133 void Win32Context::show()
00134 {
00135 if (hwnd())
00136 ShowWindow(hwnd(), SW_SHOW);
00137 }
00138
00139 void Win32Context::hide()
00140 {
00141 if (hwnd())
00142 ShowWindow(hwnd(), SW_HIDE);
00143 }
00144
00145 void Win32Context::getFocus()
00146 {
00147 if (hwnd())
00148 SetFocus(hwnd());
00149 }
00150
00151 void Win32Context::setMousePosition(int x, int y)
00152 {
00153 if (hwnd())
00154 {
00155 POINT pt = {x, y};
00156 ClientToScreen( hwnd(), &pt );
00157 SetCursorPos(pt.x, pt.y);
00158 }
00159 }
00160
00161 void Win32Context::swapBuffers()
00162 {
00163 if(hwnd() && hdc())
00164 SwapBuffers(hdc());
00165 }
00166
00167 bool Win32Context::setFullscreen(bool fullscreen_on)
00168 {
00169 if (!hwnd())
00170 return false;
00171
00172 if (fullscreen_on == fullscreen())
00173 return true;
00174
00175 if (!fullscreen_on)
00176 {
00177 SetWindowLongPtr(hwnd(), GWL_STYLE, mNormFlags);
00178
00179 if (!((mNormFlags & WS_MAXIMIZE) || (mNormFlags & WS_MINIMIZE)))
00180 {
00181 setPosition(mNormPosit.x(),mNormPosit.y());
00182 setSize(mNormSize.x(), mNormSize.y());
00183 }
00184
00185 SetWindowPos(hwnd(), 0, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOSIZE | SWP_NOMOVE);
00186
00187
00188 ChangeDisplaySettings(NULL, 0);
00189 }
00190 else
00191 {
00192 DEVMODE devmode;
00193 EnumDisplaySettings(NULL,ENUM_CURRENT_SETTINGS,&devmode);
00194
00195
00196
00197
00198 devmode.dmBitsPerPel = openglContextInfo().bitsPerPixel();
00199 devmode.dmFields |= DM_BITSPERPEL;
00200
00201 mNormFlags = (unsigned int)GetWindowLongPtr(hwnd(), GWL_STYLE);
00202 mNormPosit = position();
00203 mNormSize = size();
00204
00205 switch( ChangeDisplaySettings(&devmode, CDS_FULLSCREEN) )
00206 {
00207 case DISP_CHANGE_SUCCESSFUL:
00208 {
00209 RECT windowRect = { 0, 0, devmode.dmPelsWidth, devmode.dmPelsHeight };
00210 SetWindowLongPtr(hwnd(), GWL_STYLE, WS_POPUP | WS_VISIBLE );
00211 AdjustWindowRectEx(&windowRect, (DWORD)GetWindowLongPtr(hwnd(), GWL_STYLE), 0, (DWORD)GetWindowLongPtr(hwnd(), GWL_EXSTYLE) );
00212 SetWindowPos(hwnd(), HWND_TOP, windowRect.left, windowRect.top, windowRect.right - windowRect.left, windowRect.bottom - windowRect.top, SWP_FRAMECHANGED );
00213 break;
00214 }
00215 #if(_WIN32_WINNT >= 0x0501)
00216 case DISP_CHANGE_BADDUALVIEW:
00217 MessageBox(NULL, L"Full-screen mode switch failed: DISP_CHANGE_BADDUALVIEW", L"Win32Context::setFullscreen() error!", MB_OK | MB_ICONEXCLAMATION);
00218 return false;
00219 #endif
00220 case DISP_CHANGE_BADFLAGS:
00221 MessageBox(NULL, L"Full-screen mode switch failed: DISP_CHANGE_BADFLAGS", L"Win32Context::setFullscreen() error!", MB_OK | MB_ICONEXCLAMATION);
00222 return false;
00223 case DISP_CHANGE_BADMODE:
00224 MessageBox(NULL, L"Full-screen mode switch failed: DISP_CHANGE_BADMODE", L"Win32Context::setFullscreen() error!", MB_OK | MB_ICONEXCLAMATION);
00225 return false;
00226 case DISP_CHANGE_BADPARAM:
00227 MessageBox(NULL, L"Full-screen mode switch failed: DISP_CHANGE_BADPARAM", L"Win32Context::setFullscreen() error!", MB_OK | MB_ICONEXCLAMATION);
00228 return false;
00229 case DISP_CHANGE_FAILED:
00230 MessageBox(NULL, L"Full-screen mode switch failed: DISP_CHANGE_FAILED", L"Win32Context::setFullscreen() error!", MB_OK | MB_ICONEXCLAMATION);
00231 return false;
00232 case DISP_CHANGE_NOTUPDATED:
00233 MessageBox(NULL, L"Full-screen mode switch failed: DISP_CHANGE_NOTUPDATED", L"Win32Context::setFullscreen() error!", MB_OK | MB_ICONEXCLAMATION);
00234 return false;
00235 case DISP_CHANGE_RESTART:
00236 MessageBox(NULL, L"Full-screen mode switch failed: DISP_CHANGE_RESTART", L"Win32Context::setFullscreen() error!", MB_OK | MB_ICONEXCLAMATION);
00237 return false;
00238 default:
00239 return false;
00240 }
00241 }
00242
00243 mFullscreen = fullscreen_on;
00244 update();
00245 return true;
00246 }
00247
00248 bool Win32Context::initWin32GLContext(HGLRC share_context, const vl::String& title, const vl::OpenGLContextFormat& fmt, int x, int y, int width, int height)
00249 {
00250 class InOutContract
00251 {
00252 Win32Context* mContext;
00253
00254 public:
00255 bool mOK;
00256
00257 InOutContract(Win32Context* context): mContext(context), mOK(true)
00258 {
00259 cleanup();
00260 }
00261
00262 ~InOutContract()
00263 {
00264 if (!mOK)
00265 cleanup();
00266 }
00267
00268 void cleanup()
00269 {
00270
00271 if (mContext->mHDC)
00272 {
00273 DeleteDC(mContext->mHDC);
00274 mContext->mHDC = NULL;
00275 }
00276
00277
00278 if (mContext->mHGLRC)
00279 {
00280 if ( wglDeleteContext(mContext->mHGLRC) == FALSE )
00281 {
00282 MessageBox(NULL, L"OpenGL context cleanup failed.\n"
00283 L"The handle either doesn't specify a valid context or the context is being used by another thread.",
00284 L"Win32Context::init() error!", MB_OK);
00285 mOK = false;
00286 }
00287 mContext->mHGLRC = NULL;
00288 }
00289 }
00290 } contract(this);
00291
00292 if (!contract.mOK)
00293 return false;
00294
00295 renderTarget()->setWidth(width);
00296 renderTarget()->setHeight(height);
00297
00298 if (!hwnd())
00299 {
00300 MessageBox(NULL, L"Cannot create OpenGL context: null HWND.", L"Win32Context::init() error!", MB_OK);
00301 return contract.mOK = false;
00302 }
00303
00304 setWindowTitle(title);
00305
00306 VL_CHECK(mHDC == NULL);
00307 mHDC = ::GetDC(hwnd());
00308 if (!mHDC)
00309 {
00310 MessageBox(NULL, L"Device context acquisition failed.", L"Win32Context::init() error!", MB_OK);
00311 return contract.mOK = false;
00312 }
00313
00314 int pixel_format_index = vlWin32::choosePixelFormat(fmt);
00315 if (pixel_format_index == -1)
00316 {
00317 MessageBox(NULL, L"No suitable pixel fmt found.", L"Win32Context::init() error!", MB_OK);
00318 return contract.mOK = false;
00319 }
00320
00321 if (SetPixelFormat(mHDC, pixel_format_index, NULL) == FALSE)
00322 {
00323 MessageBox(NULL, L"Pixel fmt setup failed.", L"Win32Context::init() error!", MB_OK);
00324 return contract.mOK = false;
00325 }
00326
00327
00328
00329 if (wglCreateContextAttribsARB && mContextAttribs.size() > 1)
00330 {
00331
00332 VL_CHECK(mContextAttribs.back() == 0);
00333
00334 mHGLRC = wglCreateContextAttribsARB(mHDC, 0, &mContextAttribs[0]);
00335 }
00336 else
00337 {
00338
00339 mHGLRC = wglCreateContext(mHDC);
00340 }
00341
00342 if (!mHGLRC)
00343 {
00344 MessageBox(NULL, L"OpenGL rendering context creation failed.", L"Win32Context::init() error!", MB_OK);
00345 return contract.mOK = false;
00346 }
00347
00348
00349 initGLContext();
00350
00351 if (fmt.multisample() && !WGLEW_ARB_multisample)
00352 vl::Log::error("WGL_ARB_multisample not supported.\n");
00353
00354 dispatchInitEvent();
00355
00356 setPosition(x, y);
00357
00358 setSize(width, height);
00359
00360 if (WGLEW_EXT_swap_control)
00361 wglSwapIntervalEXT( fmt.vSync() ? 1 : 0 );
00362
00363 if (share_context)
00364 shareOpenGLResources(share_context);
00365
00366 if (fmt.fullscreen())
00367 setFullscreen(true);
00368
00369 return contract.mOK = true;
00370 }
00371
00372 void Win32Context::setContextAttribs(const int* attribs, int size)
00373 {
00374 mContextAttribs.resize(size);
00375 for(int i = 0; i < size; ++i)
00376 mContextAttribs[ i ] = attribs[ i ];
00377 }
00378