blob: b6865477bce4962ec5bd239235f056a0649f9e36 [file] [log] [blame]
//
// 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;
}
}