Edit

kc3-lang/angle/src/libGL/entry_points_wgl.cpp

Branch :

  • Show log

    Commit

  • Author : Courtney Goeltzenleuchter
    Date : 2020-08-04 09:06:01
    Hash : 3a3d419d
    Message : Reference count context to fix ASAN issues Running with ASAN there are several use after free issues because a eglDestroyContext destroys the context right away even though it's in use in other thread(s). Adding reference count to context so that it's not destroyed until all users are done using it. Bug: b/162609728 Change-Id: I00b24b53d760e38ff61dd9ce652a49b1f32f0cd2 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2336447 Commit-Queue: Courtney Goeltzenleuchter <courtneygo@google.com> Reviewed-by: Tobin Ehlis <tobine@google.com> Reviewed-by: Geoff Lang <geofflang@chromium.org> Reviewed-by: Jamie Madill <jmadill@chromium.org>

  • src/libGL/entry_points_wgl.cpp
  • //
    // Copyright 2019 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.
    //
    // entry_points_wgl.cpp: Implements the exported WGL functions.
    
    #include "entry_points_wgl.h"
    
    #include "common/debug.h"
    #include "common/event_tracer.h"
    #include "common/utilities.h"
    #include "common/version.h"
    #include "libANGLE/Context.h"
    #include "libANGLE/Display.h"
    #include "libANGLE/EGLSync.h"
    #include "libANGLE/Surface.h"
    #include "libANGLE/Texture.h"
    #include "libANGLE/Thread.h"
    #include "libANGLE/entry_points_utils.h"
    #include "libANGLE/queryutils.h"
    #include "libANGLE/validationEGL.h"
    #include "libGL/proc_table_wgl.h"
    #include "libGLESv2/global_state.h"
    
    using namespace wgl;
    using namespace egl;
    
    namespace
    {
    
    bool CompareProc(const ProcEntry &a, const char *b)
    {
        return strcmp(a.first, b) < 0;
    }
    
    void ClipConfigs(const std::vector<const Config *> &filteredConfigs,
                     EGLConfig *output_configs,
                     EGLint config_size,
                     EGLint *num_config)
    {
        EGLint result_size = static_cast<EGLint>(filteredConfigs.size());
        if (output_configs)
        {
            result_size = std::max(std::min(result_size, config_size), 0);
            for (EGLint i = 0; i < result_size; i++)
            {
                output_configs[i] = const_cast<Config *>(filteredConfigs[i]);
            }
        }
        *num_config = result_size;
    }
    }  // anonymous namespace
    
    extern "C" {
    
    // WGL 1.0
    int GL_APIENTRY wglChoosePixelFormat(HDC hDc, const PIXELFORMATDESCRIPTOR *pPfd)
    {
        UNIMPLEMENTED();
        return 1;
    }
    
    int GL_APIENTRY wglDescribePixelFormat(HDC hdc, int ipfd, UINT cjpfd, PIXELFORMATDESCRIPTOR *ppfd)
    {
        UNIMPLEMENTED();
        if (ppfd)
        {
            ppfd->dwFlags      = ppfd->dwFlags | PFD_DRAW_TO_WINDOW;
            ppfd->dwFlags      = ppfd->dwFlags | PFD_SUPPORT_OPENGL;
            ppfd->dwFlags      = ppfd->dwFlags | PFD_GENERIC_ACCELERATED;
            ppfd->dwFlags      = ppfd->dwFlags | PFD_DOUBLEBUFFER;
            ppfd->iPixelType   = PFD_TYPE_RGBA;
            ppfd->cColorBits   = 24;
            ppfd->cRedBits     = 8;
            ppfd->cGreenBits   = 8;
            ppfd->cBlueBits    = 8;
            ppfd->cAlphaBits   = 8;
            ppfd->cDepthBits   = 24;
            ppfd->cStencilBits = 8;
            ppfd->nVersion     = 1;
        }
        return 1;
    }
    
    UINT GL_APIENTRY wglGetEnhMetaFilePixelFormat(HENHMETAFILE hemf,
                                                  UINT cbBuffer,
                                                  PIXELFORMATDESCRIPTOR *ppfd)
    {
        UNIMPLEMENTED();
        return 1u;
    }
    
    int GL_APIENTRY wglGetPixelFormat(HDC hdc)
    {
        UNIMPLEMENTED();
        return 1;
    }
    
    BOOL GL_APIENTRY wglSetPixelFormat(HDC hdc, int ipfd, const PIXELFORMATDESCRIPTOR *ppfd)
    {
        UNIMPLEMENTED();
        return TRUE;
    }
    
    BOOL GL_APIENTRY wglSwapBuffers(HDC hdc)
    {
        Thread *thread        = egl::GetCurrentThread();
        egl::Display *display = egl::Display::GetExistingDisplayFromNativeDisplay(hdc);
    
        ANGLE_EGL_TRY_RETURN(thread, display->getWGLSurface()->swap(thread->getContext()),
                             "wglSwapBuffers", display->getWGLSurface(), FALSE);
        return TRUE;
    }
    
    BOOL GL_APIENTRY wglCopyContext(HGLRC hglrcSrc, HGLRC hglrcDst, UINT mask)
    {
        UNIMPLEMENTED();
        return TRUE;
    }
    
    HGLRC GL_APIENTRY wglCreateContext(HDC hDc)
    {
        Thread *thread = egl::GetCurrentThread();
    
        std::vector<EGLAttrib> displayAttributes;
        displayAttributes.push_back(EGL_PLATFORM_ANGLE_TYPE_ANGLE);
        GLenum platformType = EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE;
        displayAttributes.push_back(platformType);
        displayAttributes.push_back(EGL_NONE);
    
        const auto &attribMapDisplay = AttributeMap::CreateFromAttribArray(displayAttributes.data());
    
        egl::Display *display = egl::Display::GetDisplayFromNativeDisplay(hDc, attribMapDisplay);
    
        ANGLE_EGL_TRY_RETURN(thread, display->initialize(), "wglCreateContext", display, nullptr);
    
        thread->setAPI(EGL_OPENGL_API);
    
        // Default config
        const EGLint configAttributes[] = {EGL_NONE};
    
        // Choose config
        EGLint configCount;
        EGLConfig config;
        AttributeMap attribMapConfig = AttributeMap::CreateFromIntArray(configAttributes);
        ClipConfigs(display->chooseConfig(attribMapConfig), &config, 1, &configCount);
    
        Config *configuration = static_cast<Config *>(config);
    
        // Initialize surface
        std::vector<EGLint> surfaceAttributes;
        surfaceAttributes.push_back(EGL_NONE);
        surfaceAttributes.push_back(EGL_NONE);
        AttributeMap surfAttributes = AttributeMap::CreateFromIntArray(&surfaceAttributes[0]);
    
        // Create first window surface
        egl::Surface *surface = nullptr;
        ANGLE_EGL_TRY_RETURN(
            thread,
            display->createWindowSurface(configuration, WindowFromDC(hDc), surfAttributes, &surface),
            "wglCreateContext", display, nullptr);
    
        // Initialize context
        EGLint contextAttibutes[] = {EGL_CONTEXT_CLIENT_VERSION, 4, EGL_CONTEXT_MINOR_VERSION, 6,
                                     EGL_NONE};
    
        gl::Context *sharedGLContext = static_cast<gl::Context *>(nullptr);
        AttributeMap ctxAttributes   = AttributeMap::CreateFromIntArray(contextAttibutes);
    
        gl::Context *context = nullptr;
    
        ANGLE_EGL_TRY_RETURN(thread,
                             display->createContext(configuration, sharedGLContext, EGL_OPENGL_API,
                                                    ctxAttributes, &context),
                             "wglCreateContext", display, nullptr);
    
        return reinterpret_cast<HGLRC>(context);
    }
    
    HGLRC GL_APIENTRY wglCreateLayerContext(HDC hDc, int level)
    {
        UNIMPLEMENTED();
        return nullptr;
    }
    
    BOOL GL_APIENTRY wglDeleteContext(HGLRC oldContext)
    {
        UNIMPLEMENTED();
        return FALSE;
    }
    
    BOOL GL_APIENTRY wglDescribeLayerPlane(HDC hDc,
                                           int pixelFormat,
                                           int layerPlane,
                                           UINT nBytes,
                                           LAYERPLANEDESCRIPTOR *plpd)
    {
        UNIMPLEMENTED();
        return FALSE;
    }
    
    HGLRC GL_APIENTRY wglGetCurrentContext()
    {
        UNIMPLEMENTED();
        return nullptr;
    }
    
    HDC GL_APIENTRY wglGetCurrentDC()
    {
        UNIMPLEMENTED();
        return nullptr;
    }
    
    int GL_APIENTRY
    wglGetLayerPaletteEntries(HDC hdc, int iLayerPlane, int iStart, int cEntries, COLORREF *pcr)
    {
        UNIMPLEMENTED();
        return 0;
    }
    
    PROC GL_APIENTRY wglGetProcAddress(LPCSTR lpszProc)
    {
        ANGLE_SCOPED_GLOBAL_LOCK();
        FUNC_EVENT("const char *procname = \"%s\"", lpszProc);
        egl::Thread *thread = egl::GetCurrentThread();
    
        const ProcEntry *entry =
            std::lower_bound(&g_procTable[0], &g_procTable[g_numProcs], lpszProc, CompareProc);
    
        thread->setSuccess();
    
        if (entry == &g_procTable[g_numProcs] || strcmp(entry->first, lpszProc) != 0)
        {
            return nullptr;
        }
    
        return entry->second;
    }
    
    BOOL GL_APIENTRY wglMakeCurrent(HDC hDc, HGLRC newContext)
    {
        Thread *thread        = egl::GetCurrentThread();
        egl::Display *display = egl::Display::GetExistingDisplayFromNativeDisplay(hDc);
        const gl::Context *context =
            GetContextIfValid(display, reinterpret_cast<gl::Context *>(newContext));
    
        // If display or context are invalid, make thread's current rendering context not current
        if (!context)
        {
            gl::Context *oldContext = thread->getContext();
            if (oldContext)
            {
                ANGLE_EGL_TRY_RETURN(thread, oldContext->unMakeCurrent(display), "wglMakeCurrent",
                                     GetContextIfValid(display, oldContext), EGL_FALSE);
            }
            SetContextCurrent(thread, nullptr);
            return TRUE;
        }
    
        egl::Surface *surface        = display->getWGLSurface();
        Surface *previousDraw        = thread->getCurrentDrawSurface();
        Surface *previousRead        = thread->getCurrentReadSurface();
        gl::Context *previousContext = thread->getContext();
    
        if (previousDraw != surface || previousRead != surface || previousContext != context)
        {
            ANGLE_EGL_TRY_RETURN(thread,
                                 display->makeCurrent(previousContext, surface, surface,
                                                      const_cast<gl::Context *>(context)),
                                 "wglMakeCurrent", GetContextIfValid(display, context), EGL_FALSE);
    
            SetContextCurrent(thread, const_cast<gl::Context *>(context));
        }
    
        return TRUE;
    }
    
    BOOL GL_APIENTRY wglRealizeLayerPalette(HDC hdc, int iLayerPlane, BOOL bRealize)
    {
        UNIMPLEMENTED();
        return FALSE;
    }
    
    int GL_APIENTRY
    wglSetLayerPaletteEntries(HDC hdc, int iLayerPlane, int iStart, int cEntries, const COLORREF *pcr)
    {
        UNIMPLEMENTED();
        return 0;
    }
    
    BOOL GL_APIENTRY wglShareLists(HGLRC hrcSrvShare, HGLRC hrcSrvSource)
    {
        UNIMPLEMENTED();
        return FALSE;
    }
    
    BOOL GL_APIENTRY wglSwapLayerBuffers(HDC hdc, UINT fuFlags)
    {
        UNIMPLEMENTED();
        return FALSE;
    }
    
    BOOL GL_APIENTRY wglUseFontBitmapsA(HDC hDC, DWORD first, DWORD count, DWORD listBase)
    {
        UNIMPLEMENTED();
        return FALSE;
    }
    
    BOOL GL_APIENTRY wglUseFontBitmapsW(HDC hDC, DWORD first, DWORD count, DWORD listBase)
    {
        UNIMPLEMENTED();
        return FALSE;
    }
    
    BOOL GL_APIENTRY wglUseFontOutlinesA(HDC hDC,
                                         DWORD first,
                                         DWORD count,
                                         DWORD listBase,
                                         FLOAT deviation,
                                         FLOAT extrusion,
                                         int format,
                                         LPGLYPHMETRICSFLOAT lpgmf)
    {
        UNIMPLEMENTED();
        return FALSE;
    }
    
    BOOL GL_APIENTRY wglUseFontOutlinesW(HDC hDC,
                                         DWORD first,
                                         DWORD count,
                                         DWORD listBase,
                                         FLOAT deviation,
                                         FLOAT extrusion,
                                         int format,
                                         LPGLYPHMETRICSFLOAT lpgmf)
    {
        UNIMPLEMENTED();
        return FALSE;
    }
    
    }  // extern "C"