|
@@ -0,0 +1,76 @@
|
|
|
|
+/*
|
|
|
|
+ * Copyright (c) 2022, kleines Filmröllchen <filmroellchen@serenityos.org>.
|
|
|
|
+ *
|
|
|
|
+ * SPDX-License-Identifier: BSD-2-Clause
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+#pragma once
|
|
|
|
+
|
|
|
|
+#include "Filters/Filter.h"
|
|
|
|
+#include <AK/Function.h>
|
|
|
|
+#include <AK/NonnullRefPtr.h>
|
|
|
|
+#include <AK/RefCounted.h>
|
|
|
|
+#include <AK/Singleton.h>
|
|
|
|
+#include <LibCore/SharedCircularQueue.h>
|
|
|
|
+#include <LibThreading/ConditionVariable.h>
|
|
|
|
+#include <LibThreading/Thread.h>
|
|
|
|
+
|
|
|
|
+namespace PixelPaint {
|
|
|
|
+
|
|
|
|
+class ImageProcessingCommand : public RefCounted<ImageProcessingCommand> {
|
|
|
|
+public:
|
|
|
|
+ virtual void execute() = 0;
|
|
|
|
+ virtual ~ImageProcessingCommand() = default;
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+// A command applying a filter from a source to a target bitmap.
|
|
|
|
+class FilterApplicationCommand : public ImageProcessingCommand {
|
|
|
|
+public:
|
|
|
|
+ FilterApplicationCommand(NonnullRefPtr<Filter>, NonnullRefPtr<Layer>);
|
|
|
|
+
|
|
|
|
+ virtual void execute() override;
|
|
|
|
+ virtual ~FilterApplicationCommand() = default;
|
|
|
|
+
|
|
|
|
+private:
|
|
|
|
+ NonnullRefPtr<Filter> m_filter;
|
|
|
|
+ NonnullRefPtr<Layer> m_target_layer;
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+// A command based on a custom user function.
|
|
|
|
+class FunctionCommand : public ImageProcessingCommand {
|
|
|
|
+public:
|
|
|
|
+ FunctionCommand(Function<void()> function)
|
|
|
|
+ : m_function(move(function))
|
|
|
|
+ {
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ virtual void execute() override { m_function(); }
|
|
|
|
+
|
|
|
|
+private:
|
|
|
|
+ Function<void()> m_function;
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+// A utility class that allows various PixelPaint systems to execute image processing commands asynchronously on another thread.
|
|
|
|
+class ImageProcessor final {
|
|
|
|
+ friend struct AK::SingletonInstanceCreator<ImageProcessor>;
|
|
|
|
+
|
|
|
|
+public:
|
|
|
|
+ static ImageProcessor* the();
|
|
|
|
+
|
|
|
|
+ ErrorOr<void> enqueue_command(NonnullRefPtr<ImageProcessingCommand> command);
|
|
|
|
+
|
|
|
|
+private:
|
|
|
|
+ ImageProcessor();
|
|
|
|
+ void processor_main();
|
|
|
|
+
|
|
|
|
+ // Only the memory in the queue is in shared memory, i.e. the smart pointers themselves.
|
|
|
|
+ // The actual data will remain in normal memory, but for this application we're not using multiple processes so it's fine.
|
|
|
|
+ using Queue = Core::SharedSingleProducerCircularQueue<RefPtr<ImageProcessingCommand>>;
|
|
|
|
+ Queue m_command_queue;
|
|
|
|
+
|
|
|
|
+ NonnullRefPtr<Threading::Thread> m_processor_thread;
|
|
|
|
+ Threading::Mutex m_wakeup_mutex {};
|
|
|
|
+ Threading::ConditionVariable m_wakeup_variable;
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+}
|