summaryrefslogtreecommitdiff
path: root/Userland/Applications/PixelPaint/ImageProcessor.h
blob: a455677574f24d6af0500b82e09e22cccc110f0d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
/*
 * 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();

    // 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;
};

}