/src/libjxl/lib/jxl/render_pipeline/render_pipeline.cc
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright (c) the JPEG XL Project Authors. All rights reserved. |
2 | | // |
3 | | // Use of this source code is governed by a BSD-style |
4 | | // license that can be found in the LICENSE file. |
5 | | |
6 | | #include "lib/jxl/render_pipeline/render_pipeline.h" |
7 | | |
8 | | #include <cstddef> |
9 | | #include <memory> |
10 | | #include <utility> |
11 | | #include <vector> |
12 | | |
13 | | #include "lib/jxl/base/common.h" |
14 | | #include "lib/jxl/base/rect.h" |
15 | | #include "lib/jxl/base/sanitizers.h" |
16 | | #include "lib/jxl/base/status.h" |
17 | | #include "lib/jxl/frame_dimensions.h" |
18 | | #include "lib/jxl/image.h" |
19 | | #include "lib/jxl/render_pipeline/low_memory_render_pipeline.h" |
20 | | #include "lib/jxl/render_pipeline/render_pipeline_stage.h" |
21 | | #include "lib/jxl/render_pipeline/simple_render_pipeline.h" |
22 | | |
23 | | namespace jxl { |
24 | | |
25 | | Status RenderPipeline::Builder::AddStage( |
26 | 184k | std::unique_ptr<RenderPipelineStage> stage) { |
27 | 184k | if (!stage) return JXL_FAILURE("internal: no stage to add"); |
28 | 184k | stages_.push_back(std::move(stage)); |
29 | 184k | return true; |
30 | 184k | } |
31 | | |
32 | | StatusOr<std::unique_ptr<RenderPipeline>> RenderPipeline::Builder::Finalize( |
33 | 22.3k | FrameDimensions frame_dimensions) && { |
34 | | // Check that the last stage is not a kInOut stage for any channel, and that |
35 | | // there is at least one stage. |
36 | 22.3k | JXL_ENSURE(!stages_.empty()); |
37 | 101k | for (size_t c = 0; c < num_c_; c++) { |
38 | 78.8k | JXL_ENSURE(stages_.back()->GetChannelMode(c) != |
39 | 78.8k | RenderPipelineChannelMode::kInOut); |
40 | 78.8k | } |
41 | | |
42 | 22.3k | std::unique_ptr<RenderPipeline> res; |
43 | 22.3k | if (use_simple_implementation_) { |
44 | 0 | res = jxl::make_unique<SimpleRenderPipeline>(memory_manager_); |
45 | 22.3k | } else { |
46 | 22.3k | res = jxl::make_unique<LowMemoryRenderPipeline>(memory_manager_); |
47 | 22.3k | } |
48 | | |
49 | 22.3k | res->padding_.resize(stages_.size()); |
50 | 206k | for (size_t i = stages_.size(); i-- > 0;) { |
51 | 184k | const auto& stage = stages_[i]; |
52 | 184k | res->padding_[i].resize(num_c_); |
53 | 184k | if (i + 1 == stages_.size()) { |
54 | 22.3k | continue; |
55 | 22.3k | } |
56 | 746k | for (size_t c = 0; c < num_c_; c++) { |
57 | 584k | if (stage->GetChannelMode(c) == RenderPipelineChannelMode::kInOut) { |
58 | 173k | res->padding_[i][c].first = DivCeil(res->padding_[i + 1][c].first, |
59 | 173k | 1 << stage->settings_.shift_x) + |
60 | 173k | stage->settings_.border_x; |
61 | 173k | res->padding_[i][c].second = DivCeil(res->padding_[i + 1][c].second, |
62 | 173k | 1 << stage->settings_.shift_y) + |
63 | 173k | stage->settings_.border_y; |
64 | 410k | } else { |
65 | 410k | res->padding_[i][c] = res->padding_[i + 1][c]; |
66 | 410k | } |
67 | 584k | } |
68 | 162k | } |
69 | | |
70 | 22.3k | res->frame_dimensions_ = frame_dimensions; |
71 | 22.3k | res->group_completed_passes_.resize(frame_dimensions.num_groups); |
72 | 22.3k | res->channel_shifts_.resize(stages_.size()); |
73 | 22.3k | res->channel_shifts_[0].resize(num_c_); |
74 | 184k | for (size_t i = 1; i < stages_.size(); i++) { |
75 | 162k | auto& stage = stages_[i - 1]; |
76 | 746k | for (size_t c = 0; c < num_c_; c++) { |
77 | 584k | if (stage->GetChannelMode(c) == RenderPipelineChannelMode::kInOut) { |
78 | 173k | res->channel_shifts_[0][c].first += stage->settings_.shift_x; |
79 | 173k | res->channel_shifts_[0][c].second += stage->settings_.shift_y; |
80 | 173k | } |
81 | 584k | } |
82 | 162k | } |
83 | 184k | for (size_t i = 1; i < stages_.size(); i++) { |
84 | 162k | auto& stage = stages_[i - 1]; |
85 | 162k | res->channel_shifts_[i].resize(num_c_); |
86 | 746k | for (size_t c = 0; c < num_c_; c++) { |
87 | 584k | if (stage->GetChannelMode(c) == RenderPipelineChannelMode::kInOut) { |
88 | 173k | res->channel_shifts_[i][c].first = |
89 | 173k | res->channel_shifts_[i - 1][c].first - stage->settings_.shift_x; |
90 | 173k | res->channel_shifts_[i][c].second = |
91 | 173k | res->channel_shifts_[i - 1][c].second - stage->settings_.shift_y; |
92 | 410k | } else { |
93 | 410k | res->channel_shifts_[i][c].first = res->channel_shifts_[i - 1][c].first; |
94 | 410k | res->channel_shifts_[i][c].second = |
95 | 410k | res->channel_shifts_[i - 1][c].second; |
96 | 410k | } |
97 | 584k | } |
98 | 162k | } |
99 | 22.3k | res->stages_ = std::move(stages_); |
100 | 22.3k | JXL_RETURN_IF_ERROR(res->Init()); |
101 | 22.3k | return res; |
102 | 22.3k | } |
103 | | |
104 | | RenderPipelineInput RenderPipeline::GetInputBuffers(size_t group_id, |
105 | 48.3k | size_t thread_id) { |
106 | 48.3k | RenderPipelineInput ret; |
107 | 48.3k | JXL_DASSERT(group_id < group_completed_passes_.size()); |
108 | 48.3k | ret.group_id_ = group_id; |
109 | 48.3k | ret.thread_id_ = thread_id; |
110 | 48.3k | ret.pipeline_ = this; |
111 | 48.3k | ret.buffers_ = PrepareBuffers(group_id, thread_id); |
112 | 48.3k | return ret; |
113 | 48.3k | } |
114 | | |
115 | | Status RenderPipeline::InputReady( |
116 | | size_t group_id, size_t thread_id, |
117 | 23.7k | const std::vector<std::pair<ImageF*, Rect>>& buffers) { |
118 | 23.7k | JXL_ENSURE(group_id < group_completed_passes_.size()); |
119 | 23.7k | group_completed_passes_[group_id]++; |
120 | 109k | for (size_t i = 0; i < buffers.size(); ++i) { |
121 | 85.5k | (void)i; |
122 | 85.5k | JXL_CHECK_PLANE_INITIALIZED(*buffers[i].first, buffers[i].second, i); |
123 | 85.5k | } |
124 | | |
125 | 23.7k | JXL_RETURN_IF_ERROR(ProcessBuffers(group_id, thread_id)); |
126 | 23.7k | return true; |
127 | 23.7k | } |
128 | | |
129 | 41.3k | Status RenderPipeline::PrepareForThreads(size_t num, bool use_group_ids) { |
130 | 348k | for (const auto& stage : stages_) { |
131 | 348k | JXL_RETURN_IF_ERROR(stage->PrepareForThreads(num)); |
132 | 348k | } |
133 | 41.3k | JXL_RETURN_IF_ERROR(PrepareForThreadsInternal(num, use_group_ids)); |
134 | 41.3k | return true; |
135 | 41.3k | } |
136 | | |
137 | 23.7k | Status RenderPipelineInput::Done() { |
138 | 23.7k | JXL_ENSURE(pipeline_); |
139 | 23.7k | JXL_RETURN_IF_ERROR(pipeline_->InputReady(group_id_, thread_id_, buffers_)); |
140 | 23.7k | return true; |
141 | 23.7k | } |
142 | | |
143 | | } // namespace jxl |