EGLSurface Display::createWindowSurface(HWND window, EGLConfig config, const EGLint *attribList) { const Config *configuration = mConfigSet.get(config); EGLint postSubBufferSupported = EGL_FALSE; if (attribList) { while (*attribList != EGL_NONE) { switch (attribList[0]) { case EGL_RENDER_BUFFER: switch (attribList[1]) { case EGL_BACK_BUFFER: break; case EGL_SINGLE_BUFFER: return error(EGL_BAD_MATCH, EGL_NO_SURFACE); // Rendering directly to front buffer not supported default: return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE); } break; case EGL_POST_SUB_BUFFER_SUPPORTED_NV: postSubBufferSupported = attribList[1]; break; case EGL_VG_COLORSPACE: return error(EGL_BAD_MATCH, EGL_NO_SURFACE); case EGL_VG_ALPHA_FORMAT: return error(EGL_BAD_MATCH, EGL_NO_SURFACE); default: return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE); } attribList += 2; } } if (hasExistingWindowSurface(window)) { return error(EGL_BAD_ALLOC, EGL_NO_SURFACE); } if (testDeviceLost()) { if (!restoreLostDevice()) return EGL_NO_SURFACE; } Surface *surface = new Surface(this, configuration, window, postSubBufferSupported); if (!surface->initialize()) { delete surface; return EGL_NO_SURFACE; } mSurfaceSet.insert(surface); return success(surface); }
bool Display::resetDevice() { D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters(); HRESULT result = D3D_OK; bool lost = testDeviceLost(); int attempts = 3; while (lost && attempts > 0) { if (mDeviceEx) { Sleep(500); // Give the graphics driver some CPU time result = mDeviceEx->ResetEx(&presentParameters, NULL); } else { result = mDevice->TestCooperativeLevel(); while (result == D3DERR_DEVICELOST) { Sleep(100); // Give the graphics driver some CPU time result = mDevice->TestCooperativeLevel(); } if (result == D3DERR_DEVICENOTRESET) { result = mDevice->Reset(&presentParameters); } } lost = testDeviceLost(); attempts --; } if (FAILED(result)) { ERR("Reset/ResetEx failed multiple times: 0x%08X", result); return error(EGL_BAD_ALLOC, false); } // reset device defaults initializeDevice(); return true; }
gl::GraphicsResetStatus RendererD3D::getResetStatus() { if (!mDeviceLost) { if (testDeviceLost()) { mDeviceLost = true; notifyDeviceLost(); return gl::GraphicsResetStatus::UnknownContextReset; } return gl::GraphicsResetStatus::NoError; } if (testDeviceResettable()) { return gl::GraphicsResetStatus::NoError; } return gl::GraphicsResetStatus::UnknownContextReset; }
GLenum RendererD3D::getResetStatus() { if (!mDeviceLost) { if (testDeviceLost()) { mDeviceLost = true; notifyDeviceLost(); return GL_UNKNOWN_CONTEXT_RESET_EXT; } return GL_NO_ERROR; } if (testDeviceResettable()) { return GL_NO_ERROR; } return GL_UNKNOWN_CONTEXT_RESET_EXT; }
void Display::sync(bool block) { HRESULT result; IDirect3DQuery9* query = allocateEventQuery(); if (!query) { return; } result = query->Issue(D3DISSUE_END); ASSERT(SUCCEEDED(result)); do { result = query->GetData(NULL, 0, D3DGETDATA_FLUSH); if(block && result == S_FALSE) { // Keep polling, but allow other threads to do something useful first Sleep(0); // explicitly check for device loss // some drivers seem to return S_FALSE even if the device is lost // instead of D3DERR_DEVICELOST like they should if (testDeviceLost()) { result = D3DERR_DEVICELOST; } } } while(block && result == S_FALSE); freeEventQuery(query); if (isDeviceLostError(result)) { notifyDeviceLost(); } }
EGLContext Display::createContext(EGLConfig configHandle, const gl::Context *shareContext, bool notifyResets, bool robustAccess) { if (!mDevice) { if (!createDevice()) { return NULL; } } else if (testDeviceLost()) // Lost device { if (!restoreLostDevice()) return NULL; } const egl::Config *config = mConfigSet.get(configHandle); gl::Context *context = glCreateContext(config, shareContext, notifyResets, robustAccess); mContextSet.insert(context); mDeviceLost = false; return context; }
EGLSurface Display::createOffscreenSurface(EGLConfig config, HANDLE shareHandle, const EGLint *attribList) { EGLint width = 0, height = 0; EGLenum textureFormat = EGL_NO_TEXTURE; EGLenum textureTarget = EGL_NO_TEXTURE; const Config *configuration = mConfigSet.get(config); if (attribList) { while (*attribList != EGL_NONE) { switch (attribList[0]) { case EGL_WIDTH: width = attribList[1]; break; case EGL_HEIGHT: height = attribList[1]; break; case EGL_LARGEST_PBUFFER: if (attribList[1] != EGL_FALSE) UNIMPLEMENTED(); // FIXME break; case EGL_TEXTURE_FORMAT: switch (attribList[1]) { case EGL_NO_TEXTURE: case EGL_TEXTURE_RGB: case EGL_TEXTURE_RGBA: textureFormat = attribList[1]; break; default: return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE); } break; case EGL_TEXTURE_TARGET: switch (attribList[1]) { case EGL_NO_TEXTURE: case EGL_TEXTURE_2D: textureTarget = attribList[1]; break; default: return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE); } break; case EGL_MIPMAP_TEXTURE: if (attribList[1] != EGL_FALSE) return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE); break; case EGL_VG_COLORSPACE: return error(EGL_BAD_MATCH, EGL_NO_SURFACE); case EGL_VG_ALPHA_FORMAT: return error(EGL_BAD_MATCH, EGL_NO_SURFACE); default: return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE); } attribList += 2; } } if (width < 0 || height < 0) { return error(EGL_BAD_PARAMETER, EGL_NO_SURFACE); } if (width == 0 || height == 0) { return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE); } if (textureFormat != EGL_NO_TEXTURE && !getNonPower2TextureSupport() && (!gl::isPow2(width) || !gl::isPow2(height))) { return error(EGL_BAD_MATCH, EGL_NO_SURFACE); } if ((textureFormat != EGL_NO_TEXTURE && textureTarget == EGL_NO_TEXTURE) || (textureFormat == EGL_NO_TEXTURE && textureTarget != EGL_NO_TEXTURE)) { return error(EGL_BAD_MATCH, EGL_NO_SURFACE); } if (!(configuration->mSurfaceType & EGL_PBUFFER_BIT)) { return error(EGL_BAD_MATCH, EGL_NO_SURFACE); } if ((textureFormat == EGL_TEXTURE_RGB && configuration->mBindToTextureRGB != EGL_TRUE) || (textureFormat == EGL_TEXTURE_RGBA && configuration->mBindToTextureRGBA != EGL_TRUE)) { return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE); } if (testDeviceLost()) { if (!restoreLostDevice()) return EGL_NO_SURFACE; } Surface *surface = new Surface(this, configuration, shareHandle, width, height, textureFormat, textureTarget); if (!surface->initialize()) { delete surface; return EGL_NO_SURFACE; } mSurfaceSet.insert(surface); return success(surface); }
void Display::terminate() { while (!mSurfaceSet.empty()) { destroySurface(*mSurfaceSet.begin()); } while (!mContextSet.empty()) { destroyContext(*mContextSet.begin()); } while (!mEventQueryPool.empty()) { mEventQueryPool.back()->Release(); mEventQueryPool.pop_back(); } mVertexShaderCache.clear(); mPixelShaderCache.clear(); if (mDevice) { // If the device is lost, reset it first to prevent leaving the driver in an unstable state if (testDeviceLost()) { resetDevice(); } mDevice->Release(); mDevice = NULL; } if (mDeviceEx) { mDeviceEx->Release(); mDeviceEx = NULL; } if (mD3d9) { mD3d9->Release(); mD3d9 = NULL; } if (mDeviceWindow) { DestroyWindow(mDeviceWindow); mDeviceWindow = NULL; } if (mD3d9Ex) { mD3d9Ex->Release(); mD3d9Ex = NULL; } if (mD3d9Module) { mD3d9Module = NULL; } if (mD3dCompilerModule) { FreeLibrary(mD3dCompilerModule); mD3dCompilerModule = NULL; } }