// // Copyright 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, EGLint width, EGLint height, EGLenum textureFormat, EGLenum textureTarget, bool largest, int pixelFormat, HDC deviceContext, const FunctionsWGL *functions) : SurfaceWGL(state), mWidth(width), mHeight(height), mLargest(largest), mTextureFormat(textureFormat), mTextureTarget(textureTarget), mPixelFormat(pixelFormat), 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 egl::Display *display) { 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::EglBadAlloc() << "Failed to create a native WGL pbuffer, " << gl::FmtErr(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::EglBadAlloc() << "Failed to query the WGL pbuffer's dimensions, " << gl::FmtErr(HRESULT_CODE(error)); } mPbufferDeviceContext = mFunctionsWGL->getPbufferDCARB(mPbuffer); if (mPbufferDeviceContext == nullptr) { mFunctionsWGL->destroyPbufferARB(mPbuffer); mPbuffer = nullptr; DWORD error = GetLastError(); return egl::EglBadAlloc() << "Failed to get the WGL pbuffer handle, " << gl::FmtErr(HRESULT_CODE(error)); } return egl::NoError(); } egl::Error PbufferSurfaceWGL::makeCurrent(const gl::Context *context) { return egl::NoError(); } egl::Error PbufferSurfaceWGL::swap(const gl::Context *context) { return egl::NoError(); } egl::Error PbufferSurfaceWGL::postSubBuffer(const gl::Context *context, EGLint x, EGLint y, EGLint width, EGLint height) { return egl::NoError(); } egl::Error PbufferSurfaceWGL::querySurfacePointerANGLE(EGLint attribute, void **value) { *value = nullptr; return egl::NoError(); } static int GetWGLBufferBindTarget(EGLint buffer) { switch (buffer) { case EGL_BACK_BUFFER: return WGL_BACK_LEFT_ARB; default: UNREACHABLE(); return 0; } } egl::Error PbufferSurfaceWGL::bindTexImage(const gl::Context *context, gl::Texture *texture, EGLint buffer) { if (!mFunctionsWGL->bindTexImageARB(mPbuffer, GetWGLBufferBindTarget(buffer))) { DWORD error = GetLastError(); return egl::EglBadSurface() << "Failed to bind native wgl pbuffer, " << gl::FmtErr(HRESULT_CODE(error)); } return egl::NoError(); } egl::Error PbufferSurfaceWGL::releaseTexImage(const gl::Context *context, EGLint buffer) { if (!mFunctionsWGL->releaseTexImageARB(mPbuffer, GetWGLBufferBindTarget(buffer))) { DWORD error = GetLastError(); return egl::EglBadSurface() << "Failed to unbind native wgl pbuffer, " << gl::FmtErr(HRESULT_CODE(error)); } return egl::NoError(); } 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; } HDC PbufferSurfaceWGL::getDC() const { return mPbufferDeviceContext; } } // namespace rx