diff options
author | Stephan Unverwerth <s.unverwerth@serenityos.org> | 2022-03-27 18:54:31 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2022-04-06 11:32:24 +0200 |
commit | 5bb76e9b6326c5b36e2e9e3d1d41d90012fafa11 (patch) | |
tree | ba6821e95bc05181bcca510e177a4912bd8cd317 /Userland/Libraries/LibGPU | |
parent | 211d24a218459035959abfb46dc1937f669fc45d (diff) | |
download | serenity-5bb76e9b6326c5b36e2e9e3d1d41d90012fafa11.zip |
LibGL+LibGPU+LibSoftGPU: Load SoftGPU driver dynamically
This loads libsoftgpu.so during GLContext creation and instantiates the
device class which is then passed into the GLContext constructor.
Diffstat (limited to 'Userland/Libraries/LibGPU')
-rw-r--r-- | Userland/Libraries/LibGPU/CMakeLists.txt | 8 | ||||
-rw-r--r-- | Userland/Libraries/LibGPU/Device.h | 6 | ||||
-rw-r--r-- | Userland/Libraries/LibGPU/Driver.cpp | 76 | ||||
-rw-r--r-- | Userland/Libraries/LibGPU/Driver.h | 42 |
4 files changed, 132 insertions, 0 deletions
diff --git a/Userland/Libraries/LibGPU/CMakeLists.txt b/Userland/Libraries/LibGPU/CMakeLists.txt new file mode 100644 index 0000000000..05a77dfb95 --- /dev/null +++ b/Userland/Libraries/LibGPU/CMakeLists.txt @@ -0,0 +1,8 @@ +set(SOURCES + Driver.cpp +) + +serenity_lib(LibGPU gpu) +target_link_libraries(LibGPU LibCore LibDl) + +add_dependencies(LibGPU LibSoftGPU) diff --git a/Userland/Libraries/LibGPU/Device.h b/Userland/Libraries/LibGPU/Device.h index a87a7cc641..39ae7262c4 100644 --- a/Userland/Libraries/LibGPU/Device.h +++ b/Userland/Libraries/LibGPU/Device.h @@ -7,6 +7,7 @@ #pragma once #include <AK/Array.h> +#include <AK/Error.h> #include <AK/NonnullRefPtr.h> #include <AK/RefCounted.h> #include <AK/RefPtr.h> @@ -28,6 +29,7 @@ #include <LibGfx/Matrix3x3.h> #include <LibGfx/Matrix4x4.h> #include <LibGfx/Rect.h> +#include <LibGfx/Size.h> #include <LibGfx/Vector4.h> namespace GPU { @@ -66,3 +68,7 @@ public: }; } + +typedef GPU::Device* (*serenity_gpu_create_device_t)(Gfx::IntSize const& size); + +extern "C" GPU::Device* serenity_gpu_create_device(Gfx::IntSize const& size); diff --git a/Userland/Libraries/LibGPU/Driver.cpp b/Userland/Libraries/LibGPU/Driver.cpp new file mode 100644 index 0000000000..0b529e7661 --- /dev/null +++ b/Userland/Libraries/LibGPU/Driver.cpp @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2022, Stephan Unverwerth <s.unverwerth@serenityos.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <AK/HashMap.h> +#include <AK/String.h> +#include <AK/WeakPtr.h> +#ifdef __serenity__ +# include <LibDl/dlfcn.h> +#else +# include <dlfcn.h> +#endif +#include <LibGPU/Driver.h> + +namespace GPU { + +// FIXME: Think of a better way to configure these paths. Maybe use ConfigServer? +static HashMap<String, String> const s_driver_path_map +{ +#if defined(__serenity__) + { "softgpu", "/usr/lib/libsoftgpu.so" }, +#elif defined(__APPLE__) + { "softgpu", "./liblagom-softgpu.dylib" }, +#else + { "softgpu", "./liblagom-softgpu.so" }, +#endif +}; + +static HashMap<String, WeakPtr<Driver>> s_loaded_drivers; + +ErrorOr<NonnullRefPtr<Driver>> Driver::try_create(StringView driver_name) +{ + // Check if the library for this driver is already loaded + auto already_loaded_driver = s_loaded_drivers.find(driver_name); + if (already_loaded_driver != s_loaded_drivers.end() && !already_loaded_driver->value.is_null()) + return *already_loaded_driver->value; + + // Nope, we need to load the library + auto it = s_driver_path_map.find(driver_name); + if (it == s_driver_path_map.end()) + return Error::from_string_literal("The requested GPU driver was not found in the list of allowed driver libraries"); + + auto lib = dlopen(it->value.characters(), RTLD_NOW); + if (!lib) + return Error::from_string_literal("The library for the requested GPU driver could not be opened"); + + auto serenity_gpu_create_device = reinterpret_cast<serenity_gpu_create_device_t>(dlsym(lib, "serenity_gpu_create_device")); + if (!serenity_gpu_create_device) { + dlclose(lib); + return Error::from_string_literal("The library for the requested GPU driver does not contain serenity_gpu_create_device()"); + } + + auto driver = adopt_ref(*new Driver(lib, serenity_gpu_create_device)); + + s_loaded_drivers.set(driver_name, driver->make_weak_ptr()); + + return driver; +} + +Driver::~Driver() +{ + dlclose(m_dlopen_result); +} + +ErrorOr<NonnullOwnPtr<Device>> Driver::try_create_device(Gfx::IntSize size) +{ + auto device_or_null = m_serenity_gpu_create_device(size); + if (!device_or_null) + return Error::from_string_literal("Could not create GPU device"); + + return adopt_own(*device_or_null); +} + +} diff --git a/Userland/Libraries/LibGPU/Driver.h b/Userland/Libraries/LibGPU/Driver.h new file mode 100644 index 0000000000..c2197e167a --- /dev/null +++ b/Userland/Libraries/LibGPU/Driver.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2022, Stephan Unverwerth <s.unverwerth@serenityos.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include <AK/Error.h> +#include <AK/NonnullOwnPtr.h> +#include <AK/NonnullRefPtr.h> +#include <AK/RefCounted.h> +#include <AK/StringView.h> +#include <AK/Weakable.h> +#include <LibGPU/Device.h> +#include <LibGfx/Size.h> + +namespace GPU { + +class Driver final + : public RefCounted<Driver> + , public Weakable<Driver> { +public: + static ErrorOr<NonnullRefPtr<Driver>> try_create(StringView driver_name); + ~Driver(); + + ErrorOr<NonnullOwnPtr<Device>> try_create_device(Gfx::IntSize size); + +private: + Driver(void* dlopen_result, serenity_gpu_create_device_t device_creation_function) + : m_dlopen_result { dlopen_result } + , m_serenity_gpu_create_device { device_creation_function } + { + VERIFY(dlopen_result); + VERIFY(device_creation_function); + } + + void* const m_dlopen_result { nullptr }; + serenity_gpu_create_device_t m_serenity_gpu_create_device { nullptr }; +}; + +} |