/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 | 198k | std::unique_ptr<RenderPipelineStage> stage) { |
27 | 198k | if (!stage) return JXL_FAILURE("internal: no stage to add"); |
28 | 198k | stages_.push_back(std::move(stage)); |
29 | 198k | return true; |
30 | 198k | } |
31 | | |
32 | | StatusOr<std::unique_ptr<RenderPipeline>> RenderPipeline::Builder::Finalize( |
33 | 35.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 | 35.3k | JXL_ENSURE(!stages_.empty()); |
37 | 147k | for (size_t c = 0; c < num_c_; c++) { |
38 | 111k | JXL_ENSURE(stages_.back()->GetChannelMode(c) != |
39 | 111k | RenderPipelineChannelMode::kInOut); |
40 | 111k | } |
41 | | |
42 | 35.3k | std::unique_ptr<RenderPipeline> res; |
43 | 35.3k | if (use_simple_implementation_) { |
44 | 0 | res = jxl::make_unique<SimpleRenderPipeline>(memory_manager_); |
45 | 35.3k | } else { |
46 | 35.3k | res = jxl::make_unique<LowMemoryRenderPipeline>(memory_manager_); |
47 | 35.3k | } |
48 | | |
49 | 35.3k | res->padding_.resize(stages_.size()); |
50 | 233k | for (size_t i = stages_.size(); i-- > 0;) { |
51 | 198k | const auto& stage = stages_[i]; |
52 | 198k | res->padding_[i].resize(num_c_); |
53 | 198k | if (i + 1 == stages_.size()) { |
54 | 35.3k | continue; |
55 | 35.3k | } |
56 | 698k | for (size_t c = 0; c < num_c_; c++) { |
57 | 535k | if (stage->GetChannelMode(c) == RenderPipelineChannelMode::kInOut) { |
58 | 190k | res->padding_[i][c].first = DivCeil(res->padding_[i + 1][c].first, |
59 | 190k | 1 << stage->settings_.shift_x) + |
60 | 190k | stage->settings_.border_x; |
61 | 190k | res->padding_[i][c].second = DivCeil(res->padding_[i + 1][c].second, |
62 | 190k | 1 << stage->settings_.shift_y) + |
63 | 190k | stage->settings_.border_y; |
64 | 344k | } else { |
65 | 344k | res->padding_[i][c] = res->padding_[i + 1][c]; |
66 | 344k | } |
67 | 535k | } |
68 | 162k | } |
69 | | |
70 | 35.3k | res->frame_dimensions_ = frame_dimensions; |
71 | 35.3k | res->group_completed_passes_.resize(frame_dimensions.num_groups); |
72 | 35.3k | res->channel_shifts_.resize(stages_.size()); |
73 | 35.3k | res->channel_shifts_[0].resize(num_c_); |
74 | 198k | for (size_t i = 1; i < stages_.size(); i++) { |
75 | 162k | auto& stage = stages_[i - 1]; |
76 | 698k | for (size_t c = 0; c < num_c_; c++) { |
77 | 535k | if (stage->GetChannelMode(c) == RenderPipelineChannelMode::kInOut) { |
78 | 190k | res->channel_shifts_[0][c].first += stage->settings_.shift_x; |
79 | 190k | res->channel_shifts_[0][c].second += stage->settings_.shift_y; |
80 | 190k | } |
81 | 535k | } |
82 | 162k | } |
83 | 198k | 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 | 698k | for (size_t c = 0; c < num_c_; c++) { |
87 | 535k | if (stage->GetChannelMode(c) == RenderPipelineChannelMode::kInOut) { |
88 | 190k | res->channel_shifts_[i][c].first = |
89 | 190k | res->channel_shifts_[i - 1][c].first - stage->settings_.shift_x; |
90 | 190k | res->channel_shifts_[i][c].second = |
91 | 190k | res->channel_shifts_[i - 1][c].second - stage->settings_.shift_y; |
92 | 344k | } else { |
93 | 344k | res->channel_shifts_[i][c].first = res->channel_shifts_[i - 1][c].first; |
94 | 344k | res->channel_shifts_[i][c].second = |
95 | 344k | res->channel_shifts_[i - 1][c].second; |
96 | 344k | } |
97 | 535k | } |
98 | 162k | } |
99 | 35.3k | res->stages_ = std::move(stages_); |
100 | 35.3k | JXL_RETURN_IF_ERROR(res->Init()); |
101 | 35.3k | return res; |
102 | 35.3k | } |
103 | | |
104 | | RenderPipelineInput RenderPipeline::GetInputBuffers(size_t group_id, |
105 | 74.1k | size_t thread_id) { |
106 | 74.1k | RenderPipelineInput ret; |
107 | 74.1k | JXL_DASSERT(group_id < group_completed_passes_.size()); |
108 | 74.1k | ret.group_id_ = group_id; |
109 | 74.1k | ret.thread_id_ = thread_id; |
110 | 74.1k | ret.pipeline_ = this; |
111 | 74.1k | ret.buffers_ = PrepareBuffers(group_id, thread_id); |
112 | 74.1k | return ret; |
113 | 74.1k | } |
114 | | |
115 | | Status RenderPipeline::InputReady( |
116 | | size_t group_id, size_t thread_id, |
117 | 44.6k | const std::vector<std::pair<ImageF*, Rect>>& buffers) { |
118 | 44.6k | JXL_ENSURE(group_id < group_completed_passes_.size()); |
119 | 44.6k | group_completed_passes_[group_id]++; |
120 | 184k | for (size_t i = 0; i < buffers.size(); ++i) { |
121 | 140k | (void)i; |
122 | 140k | JXL_CHECK_PLANE_INITIALIZED(*buffers[i].first, buffers[i].second, i); |
123 | 140k | } |
124 | | |
125 | 44.6k | JXL_RETURN_IF_ERROR(ProcessBuffers(group_id, thread_id)); |
126 | 44.6k | return true; |
127 | 44.6k | } |
128 | | |
129 | 62.0k | Status RenderPipeline::PrepareForThreads(size_t num, bool use_group_ids) { |
130 | 354k | for (const auto& stage : stages_) { |
131 | 354k | JXL_RETURN_IF_ERROR(stage->PrepareForThreads(num)); |
132 | 354k | } |
133 | 62.0k | JXL_RETURN_IF_ERROR(PrepareForThreadsInternal(num, use_group_ids)); |
134 | 62.0k | return true; |
135 | 62.0k | } |
136 | | |
137 | 44.6k | Status RenderPipelineInput::Done() { |
138 | 44.6k | JXL_ENSURE(pipeline_); |
139 | 44.6k | JXL_RETURN_IF_ERROR(pipeline_->InputReady(group_id_, thread_id_, buffers_)); |
140 | 44.6k | return true; |
141 | 44.6k | } |
142 | | |
143 | | } // namespace jxl |