Edit

kc3-lang/angle/util/test_utils.cpp

Branch :

  • Show log

    Commit

  • Author : Geoff Lang
    Date : 2024-05-08 12:31:37
    Hash : 85e2e6a9
    Message : WebGPU: Add Window and Pbuffer surfaces. Bug: angleproject:342213844 Change-Id: I58465bdf895b4bab63ec3c74e326c6be4827bf60 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/5525974 Reviewed-by: Matthew Denton <mpdenton@chromium.org> Commit-Queue: Geoff Lang <geofflang@chromium.org>

  • util/test_utils.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.
    //
    
    // system_utils: Defines common utility functions
    
    #include "util/test_utils.h"
    
    #include <EGL/egl.h>
    #include <EGL/eglext.h>
    
    #include <cstring>
    #include <fstream>
    #include <iostream>
    
    namespace angle
    {
    
    namespace
    {
    void DeleteArg(int *argc, char **argv, int argIndex)
    {
        // Shift the remainder of the argv list left by one.  Note that argv has (*argc + 1) elements,
        // the last one always being NULL.  The following loop moves the trailing NULL element as well.
        for (int index = argIndex; index < *argc; ++index)
        {
            argv[index] = argv[index + 1];
        }
        (*argc)--;
    }
    
    const char *GetSingleArg(const char *flag,
                             int *argc,
                             char **argv,
                             int argIndex,
                             ArgHandling handling)
    {
        if (strstr(argv[argIndex], flag) == argv[argIndex])
        {
            const char *ptr = argv[argIndex] + strlen(flag);
    
            if (*ptr == '=')
            {
                if (handling == ArgHandling::Delete)
                {
                    DeleteArg(argc, argv, argIndex);
                }
                return ptr + 1;
            }
    
            if (*ptr == '\0' && argIndex < *argc - 1)
            {
                ptr = argv[argIndex + 1];
                if (handling == ArgHandling::Delete)
                {
                    DeleteArg(argc, argv, argIndex);
                    DeleteArg(argc, argv, argIndex);
                }
                return ptr;
            }
        }
    
        return nullptr;
    }
    
    using DisplayTypeInfo = std::pair<const char *, EGLint>;
    
    const DisplayTypeInfo kDisplayTypes[] = {
        {"d3d9", EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE},
        {"d3d11", EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE},
        {"gl", EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE},
        {"gles", EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE},
        {"metal", EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE},
        {"null", EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE},
        {"swiftshader", EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE},
        {"vulkan", EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE},
        {"vulkan-null", EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE},
        {"webgpu", EGL_PLATFORM_ANGLE_TYPE_WEBGPU_ANGLE},
    };
    }  // anonymous namespace
    
    bool GetFileSize(const char *filePath, uint32_t *sizeOut)
    {
        std::ifstream stream(filePath);
        if (!stream)
        {
            return false;
        }
    
        stream.seekg(0, std::ios::end);
        *sizeOut = static_cast<uint32_t>(stream.tellg());
        return true;
    }
    
    bool ReadEntireFileToString(const char *filePath, std::string *contentsOut)
    {
        std::ifstream stream(filePath);
        if (!stream)
        {
            return false;
        }
    
        stream.seekg(0, std::ios::end);
        contentsOut->reserve(static_cast<unsigned int>(stream.tellg()));
        stream.seekg(0, std::ios::beg);
    
        contentsOut->assign((std::istreambuf_iterator<char>(stream)), std::istreambuf_iterator<char>());
    
        return true;
    }
    
    // static
    Process::~Process() = default;
    
    ProcessHandle::ProcessHandle() : mProcess(nullptr) {}
    
    ProcessHandle::ProcessHandle(Process *process) : mProcess(process) {}
    
    ProcessHandle::ProcessHandle(const std::vector<const char *> &args,
                                 ProcessOutputCapture captureOutput)
        : mProcess(LaunchProcess(args, captureOutput))
    {}
    
    ProcessHandle::~ProcessHandle()
    {
        reset();
    }
    
    ProcessHandle::ProcessHandle(ProcessHandle &&other) : mProcess(other.mProcess)
    {
        other.mProcess = nullptr;
    }
    
    ProcessHandle &ProcessHandle::operator=(ProcessHandle &&rhs)
    {
        std::swap(mProcess, rhs.mProcess);
        return *this;
    }
    
    void ProcessHandle::reset()
    {
        if (mProcess)
        {
            delete mProcess;
            mProcess = nullptr;
        }
    }
    
    bool ParseIntArgWithHandling(const char *flag,
                                 int *argc,
                                 char **argv,
                                 int argIndex,
                                 int *valueOut,
                                 ArgHandling handling)
    {
        const char *value = GetSingleArg(flag, argc, argv, argIndex, handling);
        if (!value)
        {
            return false;
        }
    
        char *end            = nullptr;
        const long longValue = strtol(value, &end, 10);
    
        if (*end != '\0')
        {
            printf("Error parsing integer flag value.\n");
            exit(EXIT_FAILURE);
        }
    
        if (longValue == LONG_MAX || longValue == LONG_MIN || static_cast<int>(longValue) != longValue)
        {
            printf("Overflow when parsing integer flag value.\n");
            exit(EXIT_FAILURE);
        }
    
        *valueOut = static_cast<int>(longValue);
        // Note: return value is always false with ArgHandling::Preserve handling
        return handling == ArgHandling::Delete;
    }
    
    bool ParseIntArg(const char *flag, int *argc, char **argv, int argIndex, int *valueOut)
    {
        return ParseIntArgWithHandling(flag, argc, argv, argIndex, valueOut, ArgHandling::Delete);
    }
    
    bool ParseFlag(const char *flag, int *argc, char **argv, int argIndex, bool *flagOut)
    {
        if (strcmp(flag, argv[argIndex]) == 0)
        {
            *flagOut = true;
            DeleteArg(argc, argv, argIndex);
            return true;
        }
        return false;
    }
    
    bool ParseStringArg(const char *flag, int *argc, char **argv, int argIndex, std::string *valueOut)
    {
        const char *value = GetSingleArg(flag, argc, argv, argIndex, ArgHandling::Delete);
        if (!value)
        {
            return false;
        }
    
        *valueOut = value;
        return true;
    }
    
    bool ParseCStringArgWithHandling(const char *flag,
                                     int *argc,
                                     char **argv,
                                     int argIndex,
                                     const char **valueOut,
                                     ArgHandling handling)
    {
        const char *value = GetSingleArg(flag, argc, argv, argIndex, handling);
        if (!value)
        {
            return false;
        }
    
        *valueOut = value;
        // Note: return value is always false with ArgHandling::Preserve handling
        return handling == ArgHandling::Delete;
    }
    
    bool ParseCStringArg(const char *flag, int *argc, char **argv, int argIndex, const char **valueOut)
    {
        return ParseCStringArgWithHandling(flag, argc, argv, argIndex, valueOut, ArgHandling::Delete);
    }
    
    void AddArg(int *argc, char **argv, const char *arg)
    {
        // This unsafe const_cast is necessary to work around gtest limitations.
        argv[*argc]     = const_cast<char *>(arg);
        argv[*argc + 1] = nullptr;
        (*argc)++;
    }
    
    uint32_t GetPlatformANGLETypeFromArg(const char *useANGLEArg, uint32_t defaultPlatformType)
    {
        if (!useANGLEArg)
        {
            return defaultPlatformType;
        }
    
        for (const DisplayTypeInfo &displayTypeInfo : kDisplayTypes)
        {
            if (strcmp(displayTypeInfo.first, useANGLEArg) == 0)
            {
                std::cout << "Using ANGLE back-end API: " << displayTypeInfo.first << std::endl;
                return displayTypeInfo.second;
            }
        }
    
        std::cout << "Unknown ANGLE back-end API: " << useANGLEArg << std::endl;
        exit(EXIT_FAILURE);
    }
    
    uint32_t GetANGLEDeviceTypeFromArg(const char *useANGLEArg, uint32_t defaultDeviceType)
    {
        if (useANGLEArg)
        {
            if (strcmp(useANGLEArg, "swiftshader") == 0)
            {
                return EGL_PLATFORM_ANGLE_DEVICE_TYPE_SWIFTSHADER_ANGLE;
            }
            if (strstr(useANGLEArg, "null") != 0)
            {
                return EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE;
            }
        }
        return defaultDeviceType;
    }
    }  // namespace angle