Path: blob/main_old/src/tests/deqp_support/tcuANGLENativeDisplayFactory.cpp
1693 views
/*-------------------------------------------------------------------------1* drawElements Quality Program Tester Core2* ----------------------------------------3*4* Copyright 2014 The Android Open Source Project5*6* Licensed under the Apache License, Version 2.0 (the "License");7* you may not use this file except in compliance with the License.8* You may obtain a copy of the License at9*10* http://www.apache.org/licenses/LICENSE-2.011*12* Unless required by applicable law or agreed to in writing, software13* distributed under the License is distributed on an "AS IS" BASIS,14* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.15* See the License for the specific language governing permissions and16* limitations under the License.17*18*/1920#include "egluNativeDisplay.hpp"2122#include "tcuANGLENativeDisplayFactory.h"2324#include <EGL/egl.h>25#include <EGL/eglext.h>2627#include "deClock.h"28#include "deMemory.h"29#include "egluDefs.hpp"30#include "eglwLibrary.hpp"31#include "tcuTexture.hpp"32#include "util/OSPixmap.h"33#include "util/OSWindow.h"3435// clang-format off36#if (DE_OS == DE_OS_WIN32)37#define ANGLE_EGL_LIBRARY_FULL_NAME ANGLE_EGL_LIBRARY_NAME ".dll"38#elif (DE_OS == DE_OS_UNIX) || (DE_OS == DE_OS_ANDROID)39#define ANGLE_EGL_LIBRARY_FULL_NAME ANGLE_EGL_LIBRARY_NAME ".so"40#elif (DE_OS == DE_OS_OSX)41#define ANGLE_EGL_LIBRARY_FULL_NAME ANGLE_EGL_LIBRARY_NAME ".dylib"42#else43#error "Unsupported platform"44#endif45// clang-format on4647#if defined(ANGLE_USE_X11)48# include <X11/Xlib.h>49#endif5051namespace tcu52{53namespace54{5556template <typename destType, typename sourceType>57destType bitCast(sourceType source)58{59constexpr size_t copySize =60sizeof(destType) < sizeof(sourceType) ? sizeof(destType) : sizeof(sourceType);61destType output(0);62memcpy(&output, &source, copySize);63return output;64}6566enum67{68DEFAULT_SURFACE_WIDTH = 400,69DEFAULT_SURFACE_HEIGHT = 300,70};7172constexpr eglu::NativeDisplay::Capability kDisplayCapabilities =73static_cast<eglu::NativeDisplay::Capability>(74eglu::NativeDisplay::CAPABILITY_GET_DISPLAY_PLATFORM |75eglu::NativeDisplay::CAPABILITY_GET_DISPLAY_PLATFORM_EXT);76constexpr eglu::NativePixmap::Capability kBitmapCapabilities =77eglu::NativePixmap::CAPABILITY_CREATE_SURFACE_LEGACY;78constexpr eglu::NativeWindow::Capability kWindowCapabilities =79static_cast<eglu::NativeWindow::Capability>(80eglu::NativeWindow::CAPABILITY_CREATE_SURFACE_LEGACY |81eglu::NativeWindow::CAPABILITY_GET_SURFACE_SIZE |82eglu::NativeWindow::CAPABILITY_GET_SCREEN_SIZE |83eglu::NativeWindow::CAPABILITY_READ_SCREEN_PIXELS |84eglu::NativeWindow::CAPABILITY_SET_SURFACE_SIZE |85eglu::NativeWindow::CAPABILITY_CHANGE_VISIBILITY);8687class ANGLENativeDisplay : public eglu::NativeDisplay88{89public:90explicit ANGLENativeDisplay(EGLNativeDisplayType display, std::vector<eglw::EGLAttrib> attribs);91~ANGLENativeDisplay() override = default;9293void *getPlatformNative() override94{95// On OSX 64bits mDeviceContext is a 32 bit integer, so we can't simply96// use reinterpret_cast<void*>.97return bitCast<void *>(mDeviceContext);98}99const eglw::EGLAttrib *getPlatformAttributes() const override100{101return &mPlatformAttributes[0];102}103const eglw::Library &getLibrary() const override { return mLibrary; }104105EGLNativeDisplayType getDeviceContext() const { return mDeviceContext; }106107private:108EGLNativeDisplayType mDeviceContext;109eglw::DefaultLibrary mLibrary;110std::vector<eglw::EGLAttrib> mPlatformAttributes;111};112113class NativePixmapFactory : public eglu::NativePixmapFactory114{115public:116NativePixmapFactory();117~NativePixmapFactory() override = default;118119eglu::NativePixmap *createPixmap(eglu::NativeDisplay *nativeDisplay,120int width,121int height) const override;122eglu::NativePixmap *createPixmap(eglu::NativeDisplay *nativeDisplay,123eglw::EGLDisplay display,124eglw::EGLConfig config,125const eglw::EGLAttrib *attribList,126int width,127int height) const override;128};129130class NativePixmap : public eglu::NativePixmap131{132public:133NativePixmap(EGLNativeDisplayType display, int width, int height, int bitDepth);134virtual ~NativePixmap();135136eglw::EGLNativePixmapType getLegacyNative() override;137138private:139OSPixmap *mPixmap;140};141142class NativeWindowFactory : public eglu::NativeWindowFactory143{144public:145explicit NativeWindowFactory(EventState *eventState, uint32_t preRotation);146~NativeWindowFactory() override = default;147148eglu::NativeWindow *createWindow(eglu::NativeDisplay *nativeDisplay,149const eglu::WindowParams ¶ms) const override;150eglu::NativeWindow *createWindow(eglu::NativeDisplay *nativeDisplay,151eglw::EGLDisplay display,152eglw::EGLConfig config,153const eglw::EGLAttrib *attribList,154const eglu::WindowParams ¶ms) const override;155156private:157EventState *mEvents;158uint32_t mPreRotation;159};160161class NativeWindow : public eglu::NativeWindow162{163public:164NativeWindow(ANGLENativeDisplay *nativeDisplay,165const eglu::WindowParams ¶ms,166EventState *eventState,167uint32_t preRotation);168~NativeWindow() override;169170eglw::EGLNativeWindowType getLegacyNative() override;171IVec2 getSurfaceSize() const override;172IVec2 getScreenSize() const override { return getSurfaceSize(); }173void processEvents() override;174void setSurfaceSize(IVec2 size) override;175void setVisibility(eglu::WindowParams::Visibility visibility) override;176void readScreenPixels(tcu::TextureLevel *dst) const override;177178private:179OSWindow *mWindow;180EventState *mEvents;181uint32_t mPreRotation;182};183184// ANGLE NativeDisplay185186ANGLENativeDisplay::ANGLENativeDisplay(EGLNativeDisplayType display, std::vector<EGLAttrib> attribs)187: eglu::NativeDisplay(kDisplayCapabilities, EGL_PLATFORM_ANGLE_ANGLE, "EGL_EXT_platform_base"),188mDeviceContext(display),189mLibrary(ANGLE_EGL_LIBRARY_FULL_NAME),190mPlatformAttributes(std::move(attribs))191{}192193// NativePixmap194195NativePixmap::NativePixmap(EGLNativeDisplayType display, int width, int height, int bitDepth)196: eglu::NativePixmap(kBitmapCapabilities), mPixmap(CreateOSPixmap())197{198#if (DE_OS != DE_OS_UNIX)199throw tcu::NotSupportedError("Pixmap not supported");200#else201if (!mPixmap)202{203throw ResourceError("Failed to create pixmap", DE_NULL, __FILE__, __LINE__);204}205206if (!mPixmap->initialize(display, width, height, bitDepth))207{208throw ResourceError("Failed to initialize pixmap", DE_NULL, __FILE__, __LINE__);209}210#endif211}212213NativePixmap::~NativePixmap()214{215delete mPixmap;216}217218eglw::EGLNativePixmapType NativePixmap::getLegacyNative()219{220return reinterpret_cast<eglw::EGLNativePixmapType>(mPixmap->getNativePixmap());221}222223// NativePixmapFactory224225NativePixmapFactory::NativePixmapFactory()226: eglu::NativePixmapFactory("bitmap", "ANGLE Bitmap", kBitmapCapabilities)227{}228229eglu::NativePixmap *NativePixmapFactory::createPixmap(eglu::NativeDisplay *nativeDisplay,230eglw::EGLDisplay display,231eglw::EGLConfig config,232const eglw::EGLAttrib *attribList,233int width,234int height) const235{236const eglw::Library &egl = nativeDisplay->getLibrary();237int nativeVisual = 0;238239DE_ASSERT(display != EGL_NO_DISPLAY);240241egl.getConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &nativeVisual);242EGLU_CHECK_MSG(egl, "eglGetConfigAttrib()");243244return new NativePixmap(dynamic_cast<ANGLENativeDisplay *>(nativeDisplay)->getDeviceContext(),245width, height, nativeVisual);246}247248eglu::NativePixmap *NativePixmapFactory::createPixmap(eglu::NativeDisplay *nativeDisplay,249int width,250int height) const251{252const int defaultDepth = 32;253return new NativePixmap(dynamic_cast<ANGLENativeDisplay *>(nativeDisplay)->getDeviceContext(),254width, height, defaultDepth);255}256257// NativeWindowFactory258259NativeWindowFactory::NativeWindowFactory(EventState *eventState, uint32_t preRotation)260: eglu::NativeWindowFactory("window", "ANGLE Window", kWindowCapabilities),261mEvents(eventState),262mPreRotation(preRotation)263{}264265eglu::NativeWindow *NativeWindowFactory::createWindow(eglu::NativeDisplay *nativeDisplay,266const eglu::WindowParams ¶ms) const267{268DE_ASSERT(DE_FALSE);269return nullptr;270}271272eglu::NativeWindow *NativeWindowFactory::createWindow(eglu::NativeDisplay *nativeDisplay,273eglw::EGLDisplay display,274eglw::EGLConfig config,275const eglw::EGLAttrib *attribList,276const eglu::WindowParams ¶ms) const277{278return new NativeWindow(dynamic_cast<ANGLENativeDisplay *>(nativeDisplay), params, mEvents,279mPreRotation);280}281282// NativeWindow283284NativeWindow::NativeWindow(ANGLENativeDisplay *nativeDisplay,285const eglu::WindowParams ¶ms,286EventState *eventState,287uint32_t preRotation)288: eglu::NativeWindow(kWindowCapabilities),289mWindow(OSWindow::New()),290mEvents(eventState),291mPreRotation(preRotation)292{293int osWindowWidth =294params.width == eglu::WindowParams::SIZE_DONT_CARE ? DEFAULT_SURFACE_WIDTH : params.width;295int osWindowHeight = params.height == eglu::WindowParams::SIZE_DONT_CARE296? DEFAULT_SURFACE_HEIGHT297: params.height;298299if (mPreRotation == 90 || mPreRotation == 270)300{301std::swap(osWindowWidth, osWindowHeight);302}303304bool initialized = mWindow->initialize("dEQP ANGLE Tests", osWindowWidth, osWindowHeight);305TCU_CHECK(initialized);306307if (params.visibility != eglu::WindowParams::VISIBILITY_DONT_CARE)308NativeWindow::setVisibility(params.visibility);309}310311void NativeWindow::setVisibility(eglu::WindowParams::Visibility visibility)312{313switch (visibility)314{315case eglu::WindowParams::VISIBILITY_HIDDEN:316mWindow->setVisible(false);317break;318319case eglu::WindowParams::VISIBILITY_VISIBLE:320case eglu::WindowParams::VISIBILITY_FULLSCREEN:321mWindow->setVisible(true);322break;323324default:325DE_ASSERT(DE_FALSE);326}327}328329NativeWindow::~NativeWindow()330{331OSWindow::Delete(&mWindow);332}333334eglw::EGLNativeWindowType NativeWindow::getLegacyNative()335{336return reinterpret_cast<eglw::EGLNativeWindowType>(mWindow->getNativeWindow());337}338339IVec2 NativeWindow::getSurfaceSize() const340{341int width = mWindow->getWidth();342int height = mWindow->getHeight();343344if (mPreRotation == 90 || mPreRotation == 270)345{346// Return the original dimensions dEQP asked for. This ensures that the dEQP code is never347// aware of the window actually being rotated.348std::swap(width, height);349}350351return IVec2(width, height);352}353354void NativeWindow::processEvents()355{356mWindow->messageLoop();357358// Look for a quit event to forward to the EventState359Event event = {};360while (mWindow->popEvent(&event))361{362if (event.Type == Event::EVENT_CLOSED)363{364mEvents->signalQuitEvent();365}366}367}368369void NativeWindow::setSurfaceSize(IVec2 size)370{371int osWindowWidth = size.x();372int osWindowHeight = size.y();373374if (mPreRotation == 90 || mPreRotation == 270)375{376std::swap(osWindowWidth, osWindowHeight);377}378379mWindow->resize(osWindowWidth, osWindowHeight);380}381382void NativeWindow::readScreenPixels(tcu::TextureLevel *dst) const383{384dst->setStorage(TextureFormat(TextureFormat::BGRA, TextureFormat::UNORM_INT8),385mWindow->getWidth(), mWindow->getHeight());386if (!mWindow->takeScreenshot(reinterpret_cast<uint8_t *>(dst->getAccess().getDataPtr())))387{388throw InternalError("Failed to read screen pixels", DE_NULL, __FILE__, __LINE__);389}390391if (mPreRotation != 0)392{393throw InternalError("Read screen pixels with prerotation is not supported", DE_NULL,394__FILE__, __LINE__);395}396}397398} // namespace399400ANGLENativeDisplayFactory::ANGLENativeDisplayFactory(401const std::string &name,402const std::string &description,403std::vector<eglw::EGLAttrib> platformAttributes,404EventState *eventState)405: eglu::NativeDisplayFactory(name,406description,407kDisplayCapabilities,408EGL_PLATFORM_ANGLE_ANGLE,409"EGL_EXT_platform_base"),410mNativeDisplay(bitCast<eglw::EGLNativeDisplayType>(EGL_DEFAULT_DISPLAY)),411mPlatformAttributes(std::move(platformAttributes))412{413#if (DE_OS == DE_OS_UNIX) && defined(ANGLE_USE_X11)414// Make sure to only open the X display once so that it can be used by the EGL display as well415// as pixmaps416mNativeDisplay = bitCast<eglw::EGLNativeDisplayType>(XOpenDisplay(nullptr));417#endif // (DE_OS == DE_OS_UNIX)418419// If pre-rotating, let NativeWindowFactory know.420uint32_t preRotation = 0;421for (size_t attrIndex = 0;422attrIndex < mPlatformAttributes.size() && mPlatformAttributes[attrIndex] != EGL_NONE;423attrIndex += 2)424{425if (mPlatformAttributes[attrIndex] != EGL_FEATURE_OVERRIDES_ENABLED_ANGLE)426{427continue;428}429430const char **enabledFeatures =431reinterpret_cast<const char **>(mPlatformAttributes[attrIndex + 1]);432DE_ASSERT(enabledFeatures != nullptr && *enabledFeatures != nullptr);433434for (; *enabledFeatures; ++enabledFeatures)435{436if (strcmp(enabledFeatures[0], "emulatedPrerotation90") == 0)437{438preRotation = 90;439}440else if (strcmp(enabledFeatures[0], "emulatedPrerotation180") == 0)441{442preRotation = 180;443}444else if (strcmp(enabledFeatures[0], "emulatedPrerotation270") == 0)445{446preRotation = 270;447}448}449break;450}451452m_nativeWindowRegistry.registerFactory(new NativeWindowFactory(eventState, preRotation));453m_nativePixmapRegistry.registerFactory(new NativePixmapFactory());454}455456ANGLENativeDisplayFactory::~ANGLENativeDisplayFactory() = default;457458eglu::NativeDisplay *ANGLENativeDisplayFactory::createDisplay(459const eglw::EGLAttrib *attribList) const460{461DE_UNREF(attribList);462return new ANGLENativeDisplay(bitCast<EGLNativeDisplayType>(mNativeDisplay),463mPlatformAttributes);464}465466} // namespace tcu467468469