Edit

kc3-lang/angle/src/tests/deqp_support/tcuANGLENativeDisplayFactory.cpp

Branch :

  • Show log

    Commit

  • Author : Shahbaz Youssefi
    Date : 2020-11-20 16:27:48
    Hash : 9041ca0c
    Message : Limit testing of in-progress work to ANGLE's build of dEQP A new feature is added, exposeNonConformantExtensionsAndVersions, which is set by ANGLE's build of dEQP to allow exposing ES3.2 or extensions that are not yet entirely conformant. This would allow ANGLE to expose WIP extensions for regression testing without affecting partners that test ANGLE with dEQP's standalone build. Bug: angleproject:3647 Change-Id: Id1e6219f26b41d3f8cdc9763131b8052227761c5 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2552926 Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: Sunny Sun <sunny.sun@arm.com> Reviewed-by: Jamie Madill <jmadill@chromium.org>

  • src/tests/deqp_support/tcuANGLENativeDisplayFactory.cpp
  • /*-------------------------------------------------------------------------
     * drawElements Quality Program Tester Core
     * ----------------------------------------
     *
     * Copyright 2014 The Android Open Source Project
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     *      http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     *
     */
    
    #include "egluNativeDisplay.hpp"
    
    #include "tcuANGLENativeDisplayFactory.h"
    
    #include <EGL/egl.h>
    #include <EGL/eglext.h>
    
    #include "deClock.h"
    #include "deMemory.h"
    #include "egluDefs.hpp"
    #include "eglwLibrary.hpp"
    #include "tcuTexture.hpp"
    #include "util/OSPixmap.h"
    #include "util/OSWindow.h"
    
    // clang-format off
    #if (DE_OS == DE_OS_WIN32)
        #define ANGLE_EGL_LIBRARY_FULL_NAME ANGLE_EGL_LIBRARY_NAME ".dll"
    #elif (DE_OS == DE_OS_UNIX) || (DE_OS == DE_OS_ANDROID)
        #define ANGLE_EGL_LIBRARY_FULL_NAME ANGLE_EGL_LIBRARY_NAME ".so"
    #elif (DE_OS == DE_OS_OSX)
        #define ANGLE_EGL_LIBRARY_FULL_NAME ANGLE_EGL_LIBRARY_NAME ".dylib"
    #else
        #error "Unsupported platform"
    #endif
    // clang-format on
    
    #if defined(ANGLE_USE_X11)
    #    include <X11/Xlib.h>
    #endif
    
    namespace tcu
    {
    namespace
    {
    
    template <typename destType, typename sourceType>
    destType bitCast(sourceType source)
    {
        constexpr size_t copySize =
            sizeof(destType) < sizeof(sourceType) ? sizeof(destType) : sizeof(sourceType);
        destType output(0);
        memcpy(&output, &source, copySize);
        return output;
    }
    
    enum
    {
        DEFAULT_SURFACE_WIDTH  = 400,
        DEFAULT_SURFACE_HEIGHT = 300,
    };
    
    constexpr eglu::NativeDisplay::Capability kDisplayCapabilities =
        static_cast<eglu::NativeDisplay::Capability>(
            eglu::NativeDisplay::CAPABILITY_GET_DISPLAY_PLATFORM |
            eglu::NativeDisplay::CAPABILITY_GET_DISPLAY_PLATFORM_EXT);
    constexpr eglu::NativePixmap::Capability kBitmapCapabilities =
        eglu::NativePixmap::CAPABILITY_CREATE_SURFACE_LEGACY;
    constexpr eglu::NativeWindow::Capability kWindowCapabilities =
        static_cast<eglu::NativeWindow::Capability>(
            eglu::NativeWindow::CAPABILITY_CREATE_SURFACE_LEGACY |
            eglu::NativeWindow::CAPABILITY_GET_SURFACE_SIZE |
            eglu::NativeWindow::CAPABILITY_GET_SCREEN_SIZE |
            eglu::NativeWindow::CAPABILITY_READ_SCREEN_PIXELS |
            eglu::NativeWindow::CAPABILITY_SET_SURFACE_SIZE |
            eglu::NativeWindow::CAPABILITY_CHANGE_VISIBILITY);
    
    class ANGLENativeDisplay : public eglu::NativeDisplay
    {
      public:
        explicit ANGLENativeDisplay(EGLNativeDisplayType display, std::vector<eglw::EGLAttrib> attribs);
        ~ANGLENativeDisplay() override = default;
    
        void *getPlatformNative() override
        {
            // On OSX 64bits mDeviceContext is a 32 bit integer, so we can't simply
            // use reinterpret_cast<void*>.
            return bitCast<void *>(mDeviceContext);
        }
        const eglw::EGLAttrib *getPlatformAttributes() const override
        {
            return &mPlatformAttributes[0];
        }
        const eglw::Library &getLibrary() const override { return mLibrary; }
    
        EGLNativeDisplayType getDeviceContext() const { return mDeviceContext; }
    
      private:
        EGLNativeDisplayType mDeviceContext;
        eglw::DefaultLibrary mLibrary;
        std::vector<eglw::EGLAttrib> mPlatformAttributes;
    };
    
    class NativePixmapFactory : public eglu::NativePixmapFactory
    {
      public:
        NativePixmapFactory();
        ~NativePixmapFactory() override = default;
    
        eglu::NativePixmap *createPixmap(eglu::NativeDisplay *nativeDisplay,
                                         int width,
                                         int height) const override;
        eglu::NativePixmap *createPixmap(eglu::NativeDisplay *nativeDisplay,
                                         eglw::EGLDisplay display,
                                         eglw::EGLConfig config,
                                         const eglw::EGLAttrib *attribList,
                                         int width,
                                         int height) const override;
    };
    
    class NativePixmap : public eglu::NativePixmap
    {
      public:
        NativePixmap(EGLNativeDisplayType display, int width, int height, int bitDepth);
        virtual ~NativePixmap();
    
        eglw::EGLNativePixmapType getLegacyNative() override;
    
      private:
        OSPixmap *mPixmap;
    };
    
    class NativeWindowFactory : public eglu::NativeWindowFactory
    {
      public:
        explicit NativeWindowFactory(EventState *eventState, uint32_t preRotation);
        ~NativeWindowFactory() override = default;
    
        eglu::NativeWindow *createWindow(eglu::NativeDisplay *nativeDisplay,
                                         const eglu::WindowParams &params) const override;
        eglu::NativeWindow *createWindow(eglu::NativeDisplay *nativeDisplay,
                                         eglw::EGLDisplay display,
                                         eglw::EGLConfig config,
                                         const eglw::EGLAttrib *attribList,
                                         const eglu::WindowParams &params) const override;
    
      private:
        EventState *mEvents;
        uint32_t mPreRotation;
    };
    
    class NativeWindow : public eglu::NativeWindow
    {
      public:
        NativeWindow(ANGLENativeDisplay *nativeDisplay,
                     const eglu::WindowParams &params,
                     EventState *eventState,
                     uint32_t preRotation);
        ~NativeWindow() override;
    
        eglw::EGLNativeWindowType getLegacyNative() override;
        IVec2 getSurfaceSize() const override;
        IVec2 getScreenSize() const override { return getSurfaceSize(); }
        void processEvents() override;
        void setSurfaceSize(IVec2 size) override;
        void setVisibility(eglu::WindowParams::Visibility visibility) override;
        void readScreenPixels(tcu::TextureLevel *dst) const override;
    
      private:
        OSWindow *mWindow;
        EventState *mEvents;
        uint32_t mPreRotation;
    };
    
    // ANGLE NativeDisplay
    
    ANGLENativeDisplay::ANGLENativeDisplay(EGLNativeDisplayType display, std::vector<EGLAttrib> attribs)
        : eglu::NativeDisplay(kDisplayCapabilities, EGL_PLATFORM_ANGLE_ANGLE, "EGL_EXT_platform_base"),
          mDeviceContext(display),
          mLibrary(ANGLE_EGL_LIBRARY_FULL_NAME),
          mPlatformAttributes(std::move(attribs))
    {}
    
    // NativePixmap
    
    NativePixmap::NativePixmap(EGLNativeDisplayType display, int width, int height, int bitDepth)
        : eglu::NativePixmap(kBitmapCapabilities), mPixmap(CreateOSPixmap())
    {
    #if (DE_OS != DE_OS_UNIX)
        throw tcu::NotSupportedError("Pixmap not supported");
    #else
        if (!mPixmap)
        {
            throw ResourceError("Failed to create pixmap", DE_NULL, __FILE__, __LINE__);
        }
    
        if (!mPixmap->initialize(display, width, height, bitDepth))
        {
            throw ResourceError("Failed to initialize pixmap", DE_NULL, __FILE__, __LINE__);
        }
    #endif
    }
    
    NativePixmap::~NativePixmap()
    {
        delete mPixmap;
    }
    
    eglw::EGLNativePixmapType NativePixmap::getLegacyNative()
    {
        return reinterpret_cast<eglw::EGLNativePixmapType>(mPixmap->getNativePixmap());
    }
    
    // NativePixmapFactory
    
    NativePixmapFactory::NativePixmapFactory()
        : eglu::NativePixmapFactory("bitmap", "ANGLE Bitmap", kBitmapCapabilities)
    {}
    
    eglu::NativePixmap *NativePixmapFactory::createPixmap(eglu::NativeDisplay *nativeDisplay,
                                                          eglw::EGLDisplay display,
                                                          eglw::EGLConfig config,
                                                          const eglw::EGLAttrib *attribList,
                                                          int width,
                                                          int height) const
    {
        const eglw::Library &egl = nativeDisplay->getLibrary();
        int nativeVisual         = 0;
    
        DE_ASSERT(display != EGL_NO_DISPLAY);
    
        egl.getConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &nativeVisual);
        EGLU_CHECK_MSG(egl, "eglGetConfigAttrib()");
    
        return new NativePixmap(dynamic_cast<ANGLENativeDisplay *>(nativeDisplay)->getDeviceContext(),
                                width, height, nativeVisual);
    }
    
    eglu::NativePixmap *NativePixmapFactory::createPixmap(eglu::NativeDisplay *nativeDisplay,
                                                          int width,
                                                          int height) const
    {
        const int defaultDepth = 32;
        return new NativePixmap(dynamic_cast<ANGLENativeDisplay *>(nativeDisplay)->getDeviceContext(),
                                width, height, defaultDepth);
    }
    
    // NativeWindowFactory
    
    NativeWindowFactory::NativeWindowFactory(EventState *eventState, uint32_t preRotation)
        : eglu::NativeWindowFactory("window", "ANGLE Window", kWindowCapabilities),
          mEvents(eventState),
          mPreRotation(preRotation)
    {}
    
    eglu::NativeWindow *NativeWindowFactory::createWindow(eglu::NativeDisplay *nativeDisplay,
                                                          const eglu::WindowParams &params) const
    {
        DE_ASSERT(DE_FALSE);
        return nullptr;
    }
    
    eglu::NativeWindow *NativeWindowFactory::createWindow(eglu::NativeDisplay *nativeDisplay,
                                                          eglw::EGLDisplay display,
                                                          eglw::EGLConfig config,
                                                          const eglw::EGLAttrib *attribList,
                                                          const eglu::WindowParams &params) const
    {
        return new NativeWindow(dynamic_cast<ANGLENativeDisplay *>(nativeDisplay), params, mEvents,
                                mPreRotation);
    }
    
    // NativeWindow
    
    NativeWindow::NativeWindow(ANGLENativeDisplay *nativeDisplay,
                               const eglu::WindowParams &params,
                               EventState *eventState,
                               uint32_t preRotation)
        : eglu::NativeWindow(kWindowCapabilities),
          mWindow(OSWindow::New()),
          mEvents(eventState),
          mPreRotation(preRotation)
    {
        int osWindowWidth =
            params.width == eglu::WindowParams::SIZE_DONT_CARE ? DEFAULT_SURFACE_WIDTH : params.width;
        int osWindowHeight = params.height == eglu::WindowParams::SIZE_DONT_CARE
                                 ? DEFAULT_SURFACE_HEIGHT
                                 : params.height;
    
        if (mPreRotation == 90 || mPreRotation == 270)
        {
            std::swap(osWindowWidth, osWindowHeight);
        }
    
        bool initialized = mWindow->initialize("dEQP ANGLE Tests", osWindowWidth, osWindowHeight);
        TCU_CHECK(initialized);
    
        if (params.visibility != eglu::WindowParams::VISIBILITY_DONT_CARE)
            NativeWindow::setVisibility(params.visibility);
    }
    
    void NativeWindow::setVisibility(eglu::WindowParams::Visibility visibility)
    {
        switch (visibility)
        {
            case eglu::WindowParams::VISIBILITY_HIDDEN:
                mWindow->setVisible(false);
                break;
    
            case eglu::WindowParams::VISIBILITY_VISIBLE:
            case eglu::WindowParams::VISIBILITY_FULLSCREEN:
                mWindow->setVisible(true);
                break;
    
            default:
                DE_ASSERT(DE_FALSE);
        }
    }
    
    NativeWindow::~NativeWindow()
    {
        OSWindow::Delete(&mWindow);
    }
    
    eglw::EGLNativeWindowType NativeWindow::getLegacyNative()
    {
        return reinterpret_cast<eglw::EGLNativeWindowType>(mWindow->getNativeWindow());
    }
    
    IVec2 NativeWindow::getSurfaceSize() const
    {
        int width  = mWindow->getWidth();
        int height = mWindow->getHeight();
    
        if (mPreRotation == 90 || mPreRotation == 270)
        {
            // Return the original dimensions dEQP asked for.  This ensures that the dEQP code is never
            // aware of the window actually being rotated.
            std::swap(width, height);
        }
    
        return IVec2(width, height);
    }
    
    void NativeWindow::processEvents()
    {
        mWindow->messageLoop();
    
        // Look for a quit event to forward to the EventState
        Event event = {};
        while (mWindow->popEvent(&event))
        {
            if (event.Type == Event::EVENT_CLOSED)
            {
                mEvents->signalQuitEvent();
            }
        }
    }
    
    void NativeWindow::setSurfaceSize(IVec2 size)
    {
        int osWindowWidth  = size.x();
        int osWindowHeight = size.y();
    
        if (mPreRotation == 90 || mPreRotation == 270)
        {
            std::swap(osWindowWidth, osWindowHeight);
        }
    
        mWindow->resize(osWindowWidth, osWindowHeight);
    }
    
    void NativeWindow::readScreenPixels(tcu::TextureLevel *dst) const
    {
        dst->setStorage(TextureFormat(TextureFormat::BGRA, TextureFormat::UNORM_INT8),
                        mWindow->getWidth(), mWindow->getHeight());
        if (!mWindow->takeScreenshot(reinterpret_cast<uint8_t *>(dst->getAccess().getDataPtr())))
        {
            throw InternalError("Failed to read screen pixels", DE_NULL, __FILE__, __LINE__);
        }
    
        if (mPreRotation != 0)
        {
            throw InternalError("Read screen pixels with prerotation is not supported", DE_NULL,
                                __FILE__, __LINE__);
        }
    }
    
    }  // namespace
    
    ANGLENativeDisplayFactory::ANGLENativeDisplayFactory(
        const std::string &name,
        const std::string &description,
        std::vector<eglw::EGLAttrib> platformAttributes,
        EventState *eventState)
        : eglu::NativeDisplayFactory(name,
                                     description,
                                     kDisplayCapabilities,
                                     EGL_PLATFORM_ANGLE_ANGLE,
                                     "EGL_EXT_platform_base"),
          mNativeDisplay(bitCast<eglw::EGLNativeDisplayType>(EGL_DEFAULT_DISPLAY)),
          mPlatformAttributes(std::move(platformAttributes))
    {
    #if (DE_OS == DE_OS_UNIX) && defined(ANGLE_USE_X11)
        // Make sure to only open the X display once so that it can be used by the EGL display as well
        // as pixmaps
        mNativeDisplay = bitCast<eglw::EGLNativeDisplayType>(XOpenDisplay(nullptr));
    #endif  // (DE_OS == DE_OS_UNIX)
    
        // If pre-rotating, let NativeWindowFactory know.
        uint32_t preRotation = 0;
        for (size_t attrIndex = 0;
             attrIndex < mPlatformAttributes.size() && mPlatformAttributes[attrIndex] != EGL_NONE;
             attrIndex += 2)
        {
            if (mPlatformAttributes[attrIndex] != EGL_FEATURE_OVERRIDES_ENABLED_ANGLE)
            {
                continue;
            }
    
            const char **enabledFeatures =
                reinterpret_cast<const char **>(mPlatformAttributes[attrIndex + 1]);
            DE_ASSERT(enabledFeatures != nullptr && *enabledFeatures != nullptr);
    
            for (; *enabledFeatures; ++enabledFeatures)
            {
                if (strcmp(enabledFeatures[0], "emulatedPrerotation90") == 0)
                {
                    preRotation = 90;
                }
                else if (strcmp(enabledFeatures[0], "emulatedPrerotation180") == 0)
                {
                    preRotation = 180;
                }
                else if (strcmp(enabledFeatures[0], "emulatedPrerotation270") == 0)
                {
                    preRotation = 270;
                }
            }
            break;
        }
    
        m_nativeWindowRegistry.registerFactory(new NativeWindowFactory(eventState, preRotation));
        m_nativePixmapRegistry.registerFactory(new NativePixmapFactory());
    }
    
    ANGLENativeDisplayFactory::~ANGLENativeDisplayFactory() = default;
    
    eglu::NativeDisplay *ANGLENativeDisplayFactory::createDisplay(
        const eglw::EGLAttrib *attribList) const
    {
        DE_UNREF(attribList);
        return new ANGLENativeDisplay(bitCast<EGLNativeDisplayType>(mNativeDisplay),
                                      mPlatformAttributes);
    }
    
    }  // namespace tcu