summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibGPU
diff options
context:
space:
mode:
authorStephan Unverwerth <s.unverwerth@serenityos.org>2022-03-27 18:54:31 +0200
committerAndreas Kling <kling@serenityos.org>2022-04-06 11:32:24 +0200
commit5bb76e9b6326c5b36e2e9e3d1d41d90012fafa11 (patch)
treeba6821e95bc05181bcca510e177a4912bd8cd317 /Userland/Libraries/LibGPU
parent211d24a218459035959abfb46dc1937f669fc45d (diff)
downloadserenity-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.txt8
-rw-r--r--Userland/Libraries/LibGPU/Device.h6
-rw-r--r--Userland/Libraries/LibGPU/Driver.cpp76
-rw-r--r--Userland/Libraries/LibGPU/Driver.h42
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 };
+};
+
+}