Coverage Report

Created: 2026-11-12 07:35

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