| // |
| // Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| // |
| |
| // WindowSurfaceWGL.cpp: WGL implementation of egl::Surface for windows |
| |
| #include "libANGLE/renderer/gl/wgl/WindowSurfaceWGL.h" |
| |
| #include "common/debug.h" |
| #include "libANGLE/renderer/gl/RendererGL.h" |
| #include "libANGLE/renderer/gl/wgl/FunctionsWGL.h" |
| #include "libANGLE/renderer/gl/wgl/wgl_utils.h" |
| |
| namespace rx |
| { |
| |
| WindowSurfaceWGL::WindowSurfaceWGL(const egl::SurfaceState &state, |
| RendererGL *renderer, |
| EGLNativeWindowType window, |
| int pixelFormat, |
| HGLRC wglContext, |
| const FunctionsWGL *functions, |
| EGLint orientation) |
| : SurfaceGL(state, renderer), |
| mPixelFormat(pixelFormat), |
| mWGLContext(wglContext), |
| mWindow(window), |
| mDeviceContext(nullptr), |
| mFunctionsWGL(functions), |
| mSwapBehavior(0) |
| { |
| // EGL_ANGLE_surface_orientation is not supported for regular WGL window surfaces |
| ASSERT(orientation == 0); |
| } |
| |
| WindowSurfaceWGL::~WindowSurfaceWGL() |
| { |
| ReleaseDC(mWindow, mDeviceContext); |
| mDeviceContext = nullptr; |
| } |
| |
| egl::Error WindowSurfaceWGL::initialize(const DisplayImpl *displayImpl) |
| { |
| mDeviceContext = GetDC(mWindow); |
| if (!mDeviceContext) |
| { |
| return egl::Error(EGL_BAD_NATIVE_WINDOW, "Failed to get the device context from the native window, " |
| "error: 0x%X.", GetLastError()); |
| } |
| |
| // Require that the pixel format for this window has not been set yet or is equal to the Display's pixel format. |
| int windowPixelFormat = GetPixelFormat(mDeviceContext); |
| if (windowPixelFormat == 0) |
| { |
| PIXELFORMATDESCRIPTOR pixelFormatDescriptor = { 0 }; |
| if (!DescribePixelFormat(mDeviceContext, mPixelFormat, sizeof(pixelFormatDescriptor), &pixelFormatDescriptor)) |
| { |
| return egl::Error(EGL_BAD_NATIVE_WINDOW, "Failed to DescribePixelFormat, error: 0x%X.", GetLastError()); |
| } |
| |
| if (!SetPixelFormat(mDeviceContext, mPixelFormat, &pixelFormatDescriptor)) |
| { |
| return egl::Error(EGL_NOT_INITIALIZED, "Failed to set the pixel format on the device context, " |
| "error: 0x%X.", GetLastError()); |
| } |
| } |
| else if (windowPixelFormat != mPixelFormat) |
| { |
| return egl::Error(EGL_NOT_INITIALIZED, "Pixel format of the NativeWindow and NativeDisplayType must match."); |
| } |
| |
| // Check for the swap behavior of this pixel format |
| switch ( |
| wgl::QueryWGLFormatAttrib(mDeviceContext, mPixelFormat, WGL_SWAP_METHOD_ARB, mFunctionsWGL)) |
| { |
| case WGL_SWAP_COPY_ARB: |
| mSwapBehavior = EGL_BUFFER_PRESERVED; |
| break; |
| |
| case WGL_SWAP_EXCHANGE_ARB: |
| case WGL_SWAP_UNDEFINED_ARB: |
| default: |
| mSwapBehavior = EGL_BUFFER_DESTROYED; |
| break; |
| } |
| |
| return egl::Error(EGL_SUCCESS); |
| } |
| |
| egl::Error WindowSurfaceWGL::makeCurrent() |
| { |
| if (!mFunctionsWGL->makeCurrent(mDeviceContext, mWGLContext)) |
| { |
| // TODO: What error type here? |
| return egl::Error(EGL_CONTEXT_LOST, "Failed to make the WGL context current."); |
| } |
| |
| return egl::Error(EGL_SUCCESS); |
| } |
| |
| egl::Error WindowSurfaceWGL::swap(const DisplayImpl *displayImpl) |
| { |
| if (!mFunctionsWGL->swapBuffers(mDeviceContext)) |
| { |
| // TODO: What error type here? |
| return egl::Error(EGL_CONTEXT_LOST, "Failed to swap buffers on the child window."); |
| } |
| |
| return egl::Error(EGL_SUCCESS); |
| } |
| |
| egl::Error WindowSurfaceWGL::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) |
| { |
| UNIMPLEMENTED(); |
| return egl::Error(EGL_SUCCESS); |
| } |
| |
| egl::Error WindowSurfaceWGL::querySurfacePointerANGLE(EGLint attribute, void **value) |
| { |
| *value = nullptr; |
| return egl::Error(EGL_SUCCESS); |
| } |
| |
| egl::Error WindowSurfaceWGL::bindTexImage(gl::Texture *texture, EGLint buffer) |
| { |
| UNIMPLEMENTED(); |
| return egl::Error(EGL_SUCCESS); |
| } |
| |
| egl::Error WindowSurfaceWGL::releaseTexImage(EGLint buffer) |
| { |
| UNIMPLEMENTED(); |
| return egl::Error(EGL_SUCCESS); |
| } |
| |
| void WindowSurfaceWGL::setSwapInterval(EGLint interval) |
| { |
| if (mFunctionsWGL->swapIntervalEXT) |
| { |
| mFunctionsWGL->swapIntervalEXT(interval); |
| } |
| } |
| |
| EGLint WindowSurfaceWGL::getWidth() const |
| { |
| RECT rect; |
| if (!GetClientRect(mWindow, &rect)) |
| { |
| return 0; |
| } |
| return rect.right - rect.left; |
| } |
| |
| EGLint WindowSurfaceWGL::getHeight() const |
| { |
| RECT rect; |
| if (!GetClientRect(mWindow, &rect)) |
| { |
| return 0; |
| } |
| return rect.bottom - rect.top; |
| } |
| |
| EGLint WindowSurfaceWGL::isPostSubBufferSupported() const |
| { |
| // PostSubBuffer extension not exposed on WGL. |
| UNIMPLEMENTED(); |
| return EGL_FALSE; |
| } |
| |
| EGLint WindowSurfaceWGL::getSwapBehavior() const |
| { |
| return mSwapBehavior; |
| } |
| |
| } |