Serenity Operating System
1/*
2 * Copyright (c) 2022, kleines Filmröllchen <filmroellchen@serenityos.org>.
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7#include "ImageProcessor.h"
8
9namespace PixelPaint {
10
11FilterApplicationCommand::FilterApplicationCommand(NonnullRefPtr<Filter> filter, NonnullRefPtr<Layer> target_layer)
12 : m_filter(move(filter))
13 , m_target_layer(move(target_layer))
14{
15}
16
17void FilterApplicationCommand::execute()
18{
19 m_filter->apply(m_target_layer->get_scratch_edited_bitmap(), m_target_layer->get_scratch_edited_bitmap());
20 m_filter->m_editor->gui_event_loop().deferred_invoke([strong_this = NonnullRefPtr(*this)]() {
21 // HACK: we can't tell strong_this to not be const
22 (*const_cast<NonnullRefPtr<Layer>*>(&strong_this->m_target_layer))->did_modify_bitmap(strong_this->m_target_layer->rect());
23 strong_this->m_filter->m_editor->did_complete_action(DeprecatedString::formatted("Filter {}", strong_this->m_filter->filter_name()));
24 });
25}
26
27static Singleton<ImageProcessor> s_image_processor;
28
29ImageProcessor::ImageProcessor()
30 : m_command_queue(MUST(Queue::create()))
31 , m_processor_thread(Threading::Thread::construct([this]() {
32 while (true) {
33 if (auto next_command = m_command_queue.dequeue(); !next_command.is_error()) {
34 next_command.value()->execute();
35 } else {
36 Threading::MutexLocker locker { m_wakeup_mutex };
37 m_wakeup_variable.wait_while([this]() { return m_command_queue.weak_used() == 0; });
38 }
39 }
40 return 0;
41 },
42 "Image Processor"sv))
43 , m_wakeup_variable(m_wakeup_mutex)
44{
45}
46
47ImageProcessor* ImageProcessor::the()
48{
49 return s_image_processor;
50}
51
52ErrorOr<void> ImageProcessor::enqueue_command(NonnullRefPtr<ImageProcessingCommand> command)
53{
54 if (auto queue_status = m_command_queue.enqueue(move(command)); queue_status.is_error())
55 return ENOSPC;
56
57 if (!m_processor_thread->is_started()) {
58 m_processor_thread->start();
59 m_processor_thread->detach();
60 }
61
62 Threading::MutexLocker const locker(m_wakeup_mutex);
63 m_wakeup_variable.signal();
64 return {};
65}
66
67}