Edit

kc3-lang/angle/util/windows/WGLWindow.cpp

Branch :

  • Show log

    Commit

  • Author : Jamie Madill
    Date : 2020-07-24 11:02:21
    Hash : 308078b0
    Message : Tests: Add getProcAddress method to GLWindowBase. This will allow the Trace tests to load a custom GL after the GL window has already loaded the default entry points. Bug: angleproject:4845 Change-Id: Ic1b65b6cf1a582ea7c2f58a9f76077760e5cf0d8 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2315626 Reviewed-by: Manh Nguyen <nguyenmh@google.com> Reviewed-by: Cody Northrop <cnorthrop@google.com> Commit-Queue: Jamie Madill <jmadill@chromium.org>

  • util/windows/WGLWindow.cpp
  • //
    // Copyright 2018 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.
    //
    // WGLWindow:
    //   Implements initializing a WGL rendering context.
    //
    
    #include "util/windows/WGLWindow.h"
    
    #include "common/string_utils.h"
    #include "common/system_utils.h"
    #include "util/OSWindow.h"
    
    #include <iostream>
    
    namespace
    {
    PIXELFORMATDESCRIPTOR GetDefaultPixelFormatDescriptor()
    {
        PIXELFORMATDESCRIPTOR pixelFormatDescriptor = {};
        pixelFormatDescriptor.nSize                 = sizeof(pixelFormatDescriptor);
        pixelFormatDescriptor.nVersion              = 1;
        pixelFormatDescriptor.dwFlags =
            PFD_DRAW_TO_WINDOW | PFD_GENERIC_ACCELERATED | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
        pixelFormatDescriptor.iPixelType   = PFD_TYPE_RGBA;
        pixelFormatDescriptor.cColorBits   = 24;
        pixelFormatDescriptor.cAlphaBits   = 8;
        pixelFormatDescriptor.cDepthBits   = 24;
        pixelFormatDescriptor.cStencilBits = 8;
        pixelFormatDescriptor.iLayerType   = PFD_MAIN_PLANE;
    
        return pixelFormatDescriptor;
    }
    
    PFNWGLGETPROCADDRESSPROC gCurrentWGLGetProcAddress = nullptr;
    HMODULE gCurrentModule                             = nullptr;
    
    angle::GenericProc WINAPI GetProcAddressWithFallback(const char *name)
    {
        angle::GenericProc proc = reinterpret_cast<angle::GenericProc>(gCurrentWGLGetProcAddress(name));
        if (proc)
        {
            return proc;
        }
    
        return reinterpret_cast<angle::GenericProc>(GetProcAddress(gCurrentModule, name));
    }
    
    bool HasExtension(const std::vector<std::string> &extensions, const char *ext)
    {
        return std::find(extensions.begin(), extensions.end(), ext) != extensions.end();
    }
    
    void DumpLastWindowsError()
    {
        std::cerr << "Last Windows error code: 0x" << std::hex << GetLastError() << std::endl;
    }
    }  // namespace
    
    WGLWindow::WGLWindow(int glesMajorVersion, int glesMinorVersion)
        : GLWindowBase(glesMajorVersion, glesMinorVersion),
          mDeviceContext(nullptr),
          mWGLContext(nullptr),
          mWindow(nullptr)
    {}
    
    WGLWindow::~WGLWindow() {}
    
    // Internally initializes GL resources.
    bool WGLWindow::initializeGL(OSWindow *osWindow,
                                 angle::Library *glWindowingLibrary,
                                 angle::GLESDriverType driverType,
                                 const EGLPlatformParameters &platformParams,
                                 const ConfigParameters &configParams)
    {
        if (driverType != angle::GLESDriverType::SystemWGL)
        {
            std::cerr << "WGLWindow requires angle::GLESDriverType::SystemWGL.\n";
            return false;
        }
    
        glWindowingLibrary->getAs("wglGetProcAddress", &gCurrentWGLGetProcAddress);
    
        if (!gCurrentWGLGetProcAddress)
        {
            std::cerr << "Error loading wglGetProcAddress." << std::endl;
            return false;
        }
    
        gCurrentModule = reinterpret_cast<HMODULE>(glWindowingLibrary->getNative());
        angle::LoadWGL(GetProcAddressWithFallback);
    
        mWindow                                           = osWindow->getNativeWindow();
        mDeviceContext                                    = GetDC(mWindow);
        const PIXELFORMATDESCRIPTOR pixelFormatDescriptor = GetDefaultPixelFormatDescriptor();
    
        int pixelFormat = ChoosePixelFormat(mDeviceContext, &pixelFormatDescriptor);
        if (pixelFormat == 0)
        {
            std::cerr << "Could not find a compatible pixel format." << std::endl;
            DumpLastWindowsError();
            return false;
        }
    
        // According to the Windows docs, it is an error to set a pixel format twice.
        int currentPixelFormat = GetPixelFormat(mDeviceContext);
        if (currentPixelFormat != pixelFormat)
        {
            if (SetPixelFormat(mDeviceContext, pixelFormat, &pixelFormatDescriptor) != TRUE)
            {
                std::cerr << "Failed to set the pixel format." << std::endl;
                DumpLastWindowsError();
                return false;
            }
        }
    
        mWGLContext = _wglCreateContext(mDeviceContext);
        if (!mWGLContext)
        {
            std::cerr << "Failed to create a WGL context." << std::endl;
            return false;
        }
    
        if (!makeCurrent())
        {
            return false;
        }
    
        // Reload entry points to capture extensions.
        angle::LoadWGL(GetProcAddressWithFallback);
    
        if (!_wglGetExtensionsStringARB)
        {
            std::cerr << "Driver does not expose wglGetExtensionsStringARB." << std::endl;
            return false;
        }
    
        const char *extensionsString = _wglGetExtensionsStringARB(mDeviceContext);
    
        std::vector<std::string> extensions;
        angle::SplitStringAlongWhitespace(extensionsString, &extensions);
    
        if (!HasExtension(extensions, "WGL_EXT_create_context_es2_profile"))
        {
            std::cerr << "Driver does not expose WGL_EXT_create_context_es2_profile." << std::endl;
            return false;
        }
    
        if (configParams.webGLCompatibility.valid() || configParams.robustResourceInit.valid())
        {
            std::cerr << "WGLWindow does not support the requested feature set." << std::endl;
            return false;
        }
    
        // Tear down the context and create another with ES2 compatibility.
        _wglDeleteContext(mWGLContext);
    
        // This could be extended to cover ES1 compatiblity.
        int kCreateAttribs[] = {WGL_CONTEXT_MAJOR_VERSION_ARB,
                                mClientMajorVersion,
                                WGL_CONTEXT_MINOR_VERSION_ARB,
                                mClientMinorVersion,
                                WGL_CONTEXT_PROFILE_MASK_ARB,
                                WGL_CONTEXT_ES2_PROFILE_BIT_EXT,
                                0,
                                0};
    
        mWGLContext = _wglCreateContextAttribsARB(mDeviceContext, nullptr, kCreateAttribs);
        if (!mWGLContext)
        {
            std::cerr << "Failed to create an ES2 compatible WGL context." << std::endl;
            return false;
        }
    
        if (!makeCurrent())
        {
            return false;
        }
    
        mPlatform     = platformParams;
        mConfigParams = configParams;
    
        angle::LoadGLES(GetProcAddressWithFallback);
        return true;
    }
    
    void WGLWindow::destroyGL()
    {
        if (mWGLContext)
        {
            _wglDeleteContext(mWGLContext);
            mWGLContext = nullptr;
        }
    
        if (mDeviceContext)
        {
            ReleaseDC(mWindow, mDeviceContext);
            mDeviceContext = nullptr;
        }
    }
    
    bool WGLWindow::isGLInitialized() const
    {
        return mWGLContext != nullptr;
    }
    
    bool WGLWindow::makeCurrent()
    {
        if (_wglMakeCurrent(mDeviceContext, mWGLContext) == FALSE)
        {
            std::cerr << "Error during wglMakeCurrent.\n";
            return false;
        }
    
        return true;
    }
    
    bool WGLWindow::setSwapInterval(EGLint swapInterval)
    {
        if (!_wglSwapIntervalEXT || _wglSwapIntervalEXT(swapInterval) == FALSE)
        {
            std::cerr << "Error during wglSwapIntervalEXT.\n";
            return false;
        }
        return true;
    }
    
    void WGLWindow::swap()
    {
        if (SwapBuffers(mDeviceContext) == FALSE)
        {
            std::cerr << "Error during SwapBuffers.\n";
        }
    }
    
    bool WGLWindow::hasError() const
    {
        return GetLastError() != S_OK;
    }
    
    angle::GenericProc WGLWindow::getProcAddress(const char *name)
    {
        return GetProcAddressWithFallback(name);
    }
    
    // static
    WGLWindow *WGLWindow::New(int glesMajorVersion, int glesMinorVersion)
    {
        return new WGLWindow(glesMajorVersion, glesMinorVersion);
    }
    
    // static
    void WGLWindow::Delete(WGLWindow **window)
    {
        delete *window;
        *window = nullptr;
    }