| // |
| // 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. |
| // |
| |
| // SurfaceWGL.cpp: WGL implementation of egl::Surface |
| |
| #include "libANGLE/renderer/gl/wgl/PbufferSurfaceWGL.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 |
| { |
| |
| PbufferSurfaceWGL::PbufferSurfaceWGL(const egl::SurfaceState &state, |
| RendererGL *renderer, |
| EGLint width, |
| EGLint height, |
| EGLenum textureFormat, |
| EGLenum textureTarget, |
| bool largest, |
| int pixelFormat, |
| HDC deviceContext, |
| HGLRC wglContext, |
| const FunctionsWGL *functions) |
| : SurfaceGL(state, renderer), |
| mWidth(width), |
| mHeight(height), |
| mLargest(largest), |
| mTextureFormat(textureFormat), |
| mTextureTarget(textureTarget), |
| mPixelFormat(pixelFormat), |
| mShareWGLContext(wglContext), |
| mParentDeviceContext(deviceContext), |
| mPbuffer(nullptr), |
| mPbufferDeviceContext(nullptr), |
| mFunctionsWGL(functions) |
| { |
| } |
| |
| PbufferSurfaceWGL::~PbufferSurfaceWGL() |
| { |
| mFunctionsWGL->releasePbufferDCARB(mPbuffer, mPbufferDeviceContext); |
| mPbufferDeviceContext = nullptr; |
| |
| mFunctionsWGL->destroyPbufferARB(mPbuffer); |
| mPbuffer = nullptr; |
| } |
| |
| static int GetWGLTextureType(EGLenum eglTextureType) |
| { |
| switch (eglTextureType) |
| { |
| case EGL_NO_TEXTURE: return WGL_NO_TEXTURE_ARB; |
| case EGL_TEXTURE_RGB: return WGL_TEXTURE_RGB_ARB; |
| case EGL_TEXTURE_RGBA: return WGL_TEXTURE_RGBA_ARB; |
| default: UNREACHABLE(); return 0; |
| } |
| } |
| |
| static int GetWGLTextureTarget(EGLenum eglTextureTarget) |
| { |
| switch (eglTextureTarget) |
| { |
| case EGL_NO_TEXTURE: return WGL_NO_TEXTURE_ARB; |
| case EGL_TEXTURE_2D: return WGL_TEXTURE_2D_ARB; |
| default: UNREACHABLE(); return 0; |
| } |
| } |
| |
| egl::Error PbufferSurfaceWGL::initialize(const DisplayImpl *displayImpl) |
| { |
| const int pbufferCreationAttributes[] = |
| { |
| WGL_PBUFFER_LARGEST_ARB, mLargest ? 1 : 0, |
| WGL_TEXTURE_FORMAT_ARB, GetWGLTextureType(mTextureFormat), |
| WGL_TEXTURE_TARGET_ARB, GetWGLTextureTarget(mTextureTarget), |
| 0, 0, |
| }; |
| |
| mPbuffer = mFunctionsWGL->createPbufferARB(mParentDeviceContext, mPixelFormat, mWidth, mHeight, |
| pbufferCreationAttributes); |
| if (mPbuffer == nullptr) |
| { |
| DWORD error = GetLastError(); |
| return egl::Error(EGL_BAD_ALLOC, "Failed to create a native WGL pbuffer, error: 0x%08x.", HRESULT_CODE(error)); |
| } |
| |
| // The returned pbuffer may not be as large as requested, update the size members. |
| if (mFunctionsWGL->queryPbufferARB(mPbuffer, WGL_PBUFFER_WIDTH_ARB, &mWidth) != TRUE || |
| mFunctionsWGL->queryPbufferARB(mPbuffer, WGL_PBUFFER_HEIGHT_ARB, &mHeight) != TRUE) |
| { |
| DWORD error = GetLastError(); |
| return egl::Error(EGL_BAD_ALLOC, "Failed to query the WGL pbuffer's dimensions, error: 0x%08x.", HRESULT_CODE(error)); |
| } |
| |
| mPbufferDeviceContext = mFunctionsWGL->getPbufferDCARB(mPbuffer); |
| if (mPbufferDeviceContext == nullptr) |
| { |
| mFunctionsWGL->destroyPbufferARB(mPbuffer); |
| mPbuffer = nullptr; |
| |
| DWORD error = GetLastError(); |
| return egl::Error(EGL_BAD_ALLOC, "Failed to get the WGL pbuffer handle, error: 0x%08x.", HRESULT_CODE(error)); |
| } |
| |
| return egl::Error(EGL_SUCCESS); |
| } |
| |
| egl::Error PbufferSurfaceWGL::makeCurrent() |
| { |
| if (!mFunctionsWGL->makeCurrent(mPbufferDeviceContext, mShareWGLContext)) |
| { |
| // 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 PbufferSurfaceWGL::swap(const DisplayImpl *displayImpl) |
| { |
| return egl::Error(EGL_SUCCESS); |
| } |
| |
| egl::Error PbufferSurfaceWGL::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) |
| { |
| return egl::Error(EGL_SUCCESS); |
| } |
| |
| egl::Error PbufferSurfaceWGL::querySurfacePointerANGLE(EGLint attribute, void **value) |
| { |
| *value = nullptr; |
| return egl::Error(EGL_SUCCESS); |
| } |
| |
| static int GetWGLBufferBindTarget(EGLint buffer) |
| { |
| switch (buffer) |
| { |
| case EGL_BACK_BUFFER: return WGL_BACK_LEFT_ARB; |
| default: UNREACHABLE(); return 0; |
| } |
| } |
| |
| egl::Error PbufferSurfaceWGL::bindTexImage(gl::Texture *texture, EGLint buffer) |
| { |
| if (!mFunctionsWGL->bindTexImageARB(mPbuffer, GetWGLBufferBindTarget(buffer))) |
| { |
| DWORD error = GetLastError(); |
| return egl::Error(EGL_BAD_SURFACE, "Failed to bind native wgl pbuffer, error: 0x%08x.", HRESULT_CODE(error)); |
| } |
| |
| return egl::Error(EGL_SUCCESS); |
| } |
| |
| egl::Error PbufferSurfaceWGL::releaseTexImage(EGLint buffer) |
| { |
| if (!mFunctionsWGL->releaseTexImageARB(mPbuffer, GetWGLBufferBindTarget(buffer))) |
| { |
| DWORD error = GetLastError(); |
| return egl::Error(EGL_BAD_SURFACE, "Failed to unbind native wgl pbuffer, error: 0x%08x.", HRESULT_CODE(error)); |
| } |
| |
| return egl::Error(EGL_SUCCESS); |
| } |
| |
| void PbufferSurfaceWGL::setSwapInterval(EGLint interval) |
| { |
| } |
| |
| EGLint PbufferSurfaceWGL::getWidth() const |
| { |
| return mWidth; |
| } |
| |
| EGLint PbufferSurfaceWGL::getHeight() const |
| { |
| return mHeight; |
| } |
| |
| EGLint PbufferSurfaceWGL::isPostSubBufferSupported() const |
| { |
| return EGL_FALSE; |
| } |
| |
| EGLint PbufferSurfaceWGL::getSwapBehavior() const |
| { |
| return EGL_BUFFER_PRESERVED; |
| } |
| |
| } |