// Records an error code void error(GLenum errorCode) { gl::Context *context = glGetCurrentContext(); if (context) { switch (errorCode) { case GL_INVALID_ENUM: context->recordInvalidEnum(); TRACE("\t! Error generated: invalid enum\n"); break; case GL_INVALID_VALUE: context->recordInvalidValue(); TRACE("\t! Error generated: invalid value\n"); break; case GL_INVALID_OPERATION: context->recordInvalidOperation(); TRACE("\t! Error generated: invalid operation\n"); break; case GL_OUT_OF_MEMORY: context->recordOutOfMemory(); TRACE("\t! Error generated: out of memory\n"); break; case GL_INVALID_FRAMEBUFFER_OPERATION: context->recordInvalidFramebufferOperation(); TRACE("\t! Error generated: invalid framebuffer operation\n"); break; default: UNREACHABLE(); } } }
bool Surface::checkForOutOfDateSwapChain() { RECT client; if (!GetClientRect(getWindowHandle(), &client)) { ASSERT(false); return false; } // Grow the buffer now, if the window has grown. We need to grow now to avoid losing information. int clientWidth = client.right - client.left; int clientHeight = client.bottom - client.top; bool sizeDirty = clientWidth != getWidth() || clientHeight != getHeight(); if (sizeDirty || mPresentIntervalDirty) { resetSwapChain(clientWidth, clientHeight); if (static_cast<egl::Surface*>(getCurrentDrawSurface()) == this) { glMakeCurrent(glGetCurrentContext(), static_cast<egl::Display*>(getCurrentDisplay()), this); } return true; } return false; }
EGLContext __stdcall eglGetCurrentContext(void) { EVENT("()"); EGLContext context = glGetCurrentContext(); return egl::success(context); }
bool Surface::checkForOutOfDateSwapChain() { RECT client; int clientWidth = getWidth(); int clientHeight = getHeight(); bool sizeDirty = false; if (!mFixedSize && !mNativeWindow.isIconic()) { // The window is automatically resized to 150x22 when it's minimized, but the swapchain shouldn't be resized // because that's not a useful size to render to. if (!mNativeWindow.getClientRect(&client)) { ASSERT(false); return false; } // Grow the buffer now, if the window has grown. We need to grow now to avoid losing information. clientWidth = client.right - client.left; clientHeight = client.bottom - client.top; sizeDirty = clientWidth != getWidth() || clientHeight != getHeight(); } if (mFixedSize && (mWidth != mFixedWidth || mHeight != mFixedHeight)) { clientWidth = mFixedWidth; clientHeight = mFixedHeight; sizeDirty = true; } bool wasDirty = (mSwapIntervalDirty || sizeDirty); if (mSwapIntervalDirty) { resetSwapChain(clientWidth, clientHeight); } else if (sizeDirty) { resizeSwapChain(clientWidth, clientHeight); } if (wasDirty) { if (static_cast<egl::Surface*>(getCurrentDrawSurface()) == this) { glMakeCurrent(glGetCurrentContext(), static_cast<egl::Display*>(getCurrentDisplay()), this); } return true; } return false; }
EGLContext __stdcall eglGetCurrentContext(void) { EVENT("()"); ANGLE_TRY { EGLContext context = glGetCurrentContext(); return egl::success(context); } ANGLE_CATCH_ALL { return egl::error(EGL_BAD_ALLOC, EGL_NO_CONTEXT); } }
EGLContext __stdcall eglGetCurrentContext(void) { EVENT("()"); try { EGLContext context = glGetCurrentContext(); return success(context); } catch(std::bad_alloc&) { return error(EGL_BAD_ALLOC, EGL_NO_CONTEXT); } }
bool Surface::checkForOutOfDateSwapChain() { #if defined(ANGLE_PLATFORM_WINRT) int clientWidth = 0; int clientHeight = 0; winrt::getCurrentWindowDimensions(clientWidth,clientHeight); #else RECT client; if (!GetClientRect(getWindowHandle(), &client)) { ASSERT(false); return false; } // Grow the buffer now, if the window has grown. We need to grow now to avoid losing information. int clientWidth = client.right - client.left; int clientHeight = client.bottom - client.top; #endif // #if defined(ANGLE_PLATFORM_WINRT) bool sizeDirty = clientWidth != getWidth() || clientHeight != getHeight(); if (mSwapIntervalDirty) { resetSwapChain(clientWidth, clientHeight); } else if (sizeDirty) { resizeSwapChain(clientWidth, clientHeight); } if (mSwapIntervalDirty || sizeDirty) { if (static_cast<egl::Surface*>(getCurrentDrawSurface()) == this) { glMakeCurrent(glGetCurrentContext(), static_cast<egl::Display*>(getCurrentDisplay()), this); } return true; } return false; }
bool Surface::checkForWindowResize() { RECT client; if (!GetClientRect(getWindowHandle(), &client)) { ASSERT(false); return false; } if (getWidth() != client.right - client.left || getHeight() != client.bottom - client.top) { resetSwapChain(); if (static_cast<egl::Surface*>(getCurrentDrawSurface()) == this) { glMakeCurrent(glGetCurrentContext(), static_cast<egl::Display*>(getCurrentDisplay()), this); } return true; } return false; }
bool Surface::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) { if (!mSwapChain) { return true; } if (x + width > mWidth) { width = mWidth - x; } if (y + height > mHeight) { height = mHeight - y; } if (width == 0 || height == 0) { return true; } IDirect3DDevice9 *device = mDisplay->getDevice(); // Disable all pipeline operations device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE); device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); device->SetRenderState(D3DRS_STENCILENABLE, FALSE); device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0); device->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA | D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_RED); device->SetRenderState(D3DRS_SRGBWRITEENABLE, FALSE); device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE); device->SetPixelShader(NULL); device->SetVertexShader(NULL); device->SetRenderTarget(0, mBackBuffer); device->SetDepthStencilSurface(NULL); device->SetTexture(0, mOffscreenTexture); device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); device->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT); device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT); device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); device->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1); D3DVIEWPORT9 viewport = {0, 0, mWidth, mHeight, 0.0f, 1.0f}; device->SetViewport(&viewport); float x1 = x - 0.5f; float y1 = (mHeight - y - height) - 0.5f; float x2 = (x + width) - 0.5f; float y2 = (mHeight - y) - 0.5f; float u1 = x / float(mWidth); float v1 = y / float(mHeight); float u2 = (x + width) / float(mWidth); float v2 = (y + height) / float(mHeight); float quad[4][6] = {{x1, y1, 0.0f, 1.0f, u1, v2}, {x2, y1, 0.0f, 1.0f, u2, v2}, {x2, y2, 0.0f, 1.0f, u2, v1}, {x1, y2, 0.0f, 1.0f, u1, v1}}; // x, y, z, rhw, u, v mDisplay->startScene(); device->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, quad, 6 * sizeof(float)); mDisplay->endScene(); device->SetTexture(0, NULL); RECT rect = { x, mHeight - y - height, x + width, mHeight - y }; HRESULT result = mSwapChain->Present(&rect, &rect, NULL, NULL, 0); gl::Context *context = static_cast<gl::Context*>(glGetCurrentContext()); if (context) { context->markAllStateDirty(); } if (isDeviceLostError(result)) { mDisplay->notifyDeviceLost(); return false; } if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DRIVERINTERNALERROR) { return error(EGL_BAD_ALLOC, false); } ASSERT(SUCCEEDED(result)); checkForOutOfDateSwapChain(); return true; }
SDLWindow::SDLWindow(const GWindow::Settings& settings) { #if defined(G3D_OSX) NSApplicationWrapper wrapper; // Hack to get our window/process to the front... ProcessSerialNumber psn = { 0, kCurrentProcess}; TransformProcessType (&psn, kProcessTransformToForegroundApplication); SetFrontProcess (&psn); _pool = new NSAutoreleasePoolWrapper(); #endif if (SDL_Init(SDL_INIT_NOPARACHUTE | SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) < 0 ) { fprintf(stderr, "Unable to initialize SDL: %s\n", SDL_GetError()); debugPrintf("Unable to initialize SDL: %s\n", SDL_GetError()); Log::common()->printf("Unable to initialize SDL: %s\n", SDL_GetError()); exit(1); } // Set default icon if available if (settings.defaultIconFilename != "nodefault") { try { GImage defaultIcon; defaultIcon.load(settings.defaultIconFilename); setIcon(defaultIcon); } catch (const GImage::Error& e) { // Throw away default icon fprintf(stderr, "GWindow's default icon failed to load: %s (%s)", e.filename.c_str(), e.reason.c_str()); debugPrintf("GWindow's default icon failed to load: %s (%s)", e.filename.c_str(), e.reason.c_str()); Log::common()->printf("GWindow's default icon failed to load: %s (%s)", e.filename.c_str(), e.reason.c_str()); } } if (! settings.fullScreen) { // This doesn't really work very well due to SDL bugs so we fix up // the position after the window is created. if (settings.center) { System::setEnv("SDL_VIDEO_CENTERED", ""); } else { System::setEnv("SDL_VIDEO_WINDOW_POS", format("%d,%d", settings.x, settings.y)); } } _mouseVisible = true; _inputCapture = false; // Request various OpenGL parameters SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, settings.depthBits); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, settings.stencilBits); SDL_GL_SetAttribute(SDL_GL_RED_SIZE, settings.rgbBits); SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, settings.rgbBits); SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, settings.rgbBits); SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, settings.alphaBits); SDL_GL_SetAttribute(SDL_GL_STEREO, settings.stereo); #if SDL_FSAA if (settings.fsaaSamples > 1) { SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1); SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, settings.fsaaSamples); } #endif // Create a width x height OpenGL screen int flags = SDL_HWSURFACE | SDL_OPENGL | (settings.fullScreen ? SDL_FULLSCREEN : 0) | (settings.resizable ? SDL_RESIZABLE : 0) | (settings.framed ? 0 : SDL_NOFRAME); if (SDL_SetVideoMode(settings.width, settings.height, 0, flags) == NULL) { debugAssert(false); Log::common()->printf("Unable to create OpenGL screen: %s\n", SDL_GetError()); error("Critical Error", format("Unable to create OpenGL screen: %s\n", SDL_GetError()).c_str(), true); SDL_Quit(); exit(2); } // See what video mode we really got _settings = settings; int depthBits, stencilBits, redBits, greenBits, blueBits, alphaBits; glGetIntegerv(GL_DEPTH_BITS, &depthBits); glGetIntegerv(GL_STENCIL_BITS, &stencilBits); glGetIntegerv(GL_RED_BITS, &redBits); glGetIntegerv(GL_GREEN_BITS, &greenBits); glGetIntegerv(GL_BLUE_BITS, &blueBits); glGetIntegerv(GL_ALPHA_BITS, &alphaBits); int actualFSAABuffers = 0, actualFSAASamples = 0; #if SDL_FSAA SDL_GL_GetAttribute(SDL_GL_MULTISAMPLEBUFFERS, &actualFSAABuffers); SDL_GL_GetAttribute(SDL_GL_MULTISAMPLESAMPLES, &actualFSAASamples); #else (void)actualFSAABuffers; (void)actualFSAASamples; #endif _settings.rgbBits = iMin(iMin(redBits, greenBits), blueBits); _settings.alphaBits = alphaBits; _settings.stencilBits = stencilBits; _settings.depthBits = depthBits; _settings.fsaaSamples = actualFSAASamples; SDL_version ver; SDL_VERSION(&ver); _version = format("%d,%0d.%0d", ver.major, ver.minor, ver.patch); SDL_EnableUNICODE(1); setCaption("G3D"); SDL_SysWMinfo info; SDL_VERSION(&info.version); SDL_GetWMInfo(&info); _glContext = glGetCurrentContext(); #if defined(G3D_WIN32) // Extract SDL HDC/HWND on Win32 _Win32HWND = info.window; _Win32HDC = wglGetCurrentDC(); #elif defined(G3D_LINUX) // Extract SDL's internal Display pointer on Linux _X11Display = info.info.x11.display; _X11Window = info.info.x11.window; _X11WMWindow = info.info.x11.wmwindow; if (glXGetCurrentDisplay != NULL) { G3D::_internal::x11Display = glXGetCurrentDisplay(); } else { G3D::_internal::x11Display = info.info.x11.display; } if (glXGetCurrentDrawable != NULL) { // A Drawable appears to be either a Window or a Pixmap G3D::_internal::x11Window = glXGetCurrentDrawable(); } else { G3D::_internal::x11Window = info.info.x11.window; } #endif // Adjust window position #ifdef G3D_WIN32 if (! settings.fullScreen) { int W = screenWidth(); int H = screenHeight(); int x = iClamp(settings.x, 0, W); int y = iClamp(settings.y, 0, H); if (settings.center) { x = (W - settings.width) / 2; y = (H - settings.height) / 2; } SetWindowPos(_Win32HWND, NULL, x, y, 0, 0, SWP_NOZORDER | SWP_NOSIZE); } #endif #ifdef G3D_LINUX if (! settings.fullScreen) { int W = screenWidth(_X11Display); int H = screenHeight(_X11Display); int x = iClamp(settings.x, 0, W); int y = iClamp(settings.y, 0, H); if (settings.center) { x = (W - settings.width) / 2; y = (H - settings.height) / 2; } XMoveWindow(_X11Display, _X11WMWindow, x, y); } #endif // Check for joysticks int j = SDL_NumJoysticks(); if ((j < 0) || (j > 10)) { // If there is no joystick adapter on Win32, // SDL returns ridiculous numbers. j = 0; } if (j > 0) { SDL_JoystickEventState(SDL_ENABLE); // Turn on the joysticks joy.resize(j); for (int i = 0; i < j; ++i) { joy[i] = SDL_JoystickOpen(i); debugAssert(joy[i]); } } GLCaps::init(); // Register this window as the current window makeCurrent(); # if defined(G3D_LINUX) // If G3D is using the default assertion hooks, replace them with our own that use // SDL functions to release the mouse, since we've been unable to implement // a non-SDL way of releasing the mouse using the X11 handle directly. if (assertionHook() == _internal::_handleDebugAssert_) { setFailureHook(SDL_handleDebugAssert_); } if (failureHook() == _internal::_handleErrorCheck_) { setFailureHook(SDL_handleErrorCheck_); } # endif }