render_pipeline.cc (4677B)
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 "lib/jxl/base/status.h" 9 #include "lib/jxl/render_pipeline/low_memory_render_pipeline.h" 10 #include "lib/jxl/render_pipeline/simple_render_pipeline.h" 11 #include "lib/jxl/sanitizers.h" 12 13 namespace jxl { 14 15 void RenderPipeline::Builder::AddStage( 16 std::unique_ptr<RenderPipelineStage> stage) { 17 stages_.push_back(std::move(stage)); 18 } 19 20 StatusOr<std::unique_ptr<RenderPipeline>> RenderPipeline::Builder::Finalize( 21 FrameDimensions frame_dimensions) && { 22 #if JXL_ENABLE_ASSERT 23 // Check that the last stage is not an kInOut stage for any channel, and that 24 // there is at least one stage. 25 JXL_ASSERT(!stages_.empty()); 26 for (size_t c = 0; c < num_c_; c++) { 27 JXL_ASSERT(stages_.back()->GetChannelMode(c) != 28 RenderPipelineChannelMode::kInOut); 29 } 30 #endif 31 32 std::unique_ptr<RenderPipeline> res; 33 if (use_simple_implementation_) { 34 res = jxl::make_unique<SimpleRenderPipeline>(); 35 } else { 36 res = jxl::make_unique<LowMemoryRenderPipeline>(); 37 } 38 39 res->padding_.resize(stages_.size()); 40 for (size_t i = stages_.size(); i-- > 0;) { 41 const auto& stage = stages_[i]; 42 res->padding_[i].resize(num_c_); 43 if (i + 1 == stages_.size()) { 44 continue; 45 } 46 for (size_t c = 0; c < num_c_; c++) { 47 if (stage->GetChannelMode(c) == RenderPipelineChannelMode::kInOut) { 48 res->padding_[i][c].first = DivCeil(res->padding_[i + 1][c].first, 49 1 << stage->settings_.shift_x) + 50 stage->settings_.border_x; 51 res->padding_[i][c].second = DivCeil(res->padding_[i + 1][c].second, 52 1 << stage->settings_.shift_y) + 53 stage->settings_.border_y; 54 } else { 55 res->padding_[i][c] = res->padding_[i + 1][c]; 56 } 57 } 58 } 59 60 res->frame_dimensions_ = frame_dimensions; 61 res->group_completed_passes_.resize(frame_dimensions.num_groups); 62 res->channel_shifts_.resize(stages_.size()); 63 res->channel_shifts_[0].resize(num_c_); 64 for (size_t i = 1; i < stages_.size(); i++) { 65 auto& stage = stages_[i - 1]; 66 for (size_t c = 0; c < num_c_; c++) { 67 if (stage->GetChannelMode(c) == RenderPipelineChannelMode::kInOut) { 68 res->channel_shifts_[0][c].first += stage->settings_.shift_x; 69 res->channel_shifts_[0][c].second += stage->settings_.shift_y; 70 } 71 } 72 } 73 for (size_t i = 1; i < stages_.size(); i++) { 74 auto& stage = stages_[i - 1]; 75 res->channel_shifts_[i].resize(num_c_); 76 for (size_t c = 0; c < num_c_; c++) { 77 if (stage->GetChannelMode(c) == RenderPipelineChannelMode::kInOut) { 78 res->channel_shifts_[i][c].first = 79 res->channel_shifts_[i - 1][c].first - stage->settings_.shift_x; 80 res->channel_shifts_[i][c].second = 81 res->channel_shifts_[i - 1][c].second - stage->settings_.shift_y; 82 } else { 83 res->channel_shifts_[i][c].first = res->channel_shifts_[i - 1][c].first; 84 res->channel_shifts_[i][c].second = 85 res->channel_shifts_[i - 1][c].second; 86 } 87 } 88 } 89 res->stages_ = std::move(stages_); 90 JXL_RETURN_IF_ERROR(res->Init()); 91 return res; 92 } 93 94 RenderPipelineInput RenderPipeline::GetInputBuffers(size_t group_id, 95 size_t thread_id) { 96 RenderPipelineInput ret; 97 JXL_DASSERT(group_id < group_completed_passes_.size()); 98 ret.group_id_ = group_id; 99 ret.thread_id_ = thread_id; 100 ret.pipeline_ = this; 101 ret.buffers_ = PrepareBuffers(group_id, thread_id); 102 return ret; 103 } 104 105 Status RenderPipeline::InputReady( 106 size_t group_id, size_t thread_id, 107 const std::vector<std::pair<ImageF*, Rect>>& buffers) { 108 JXL_DASSERT(group_id < group_completed_passes_.size()); 109 group_completed_passes_[group_id]++; 110 for (size_t i = 0; i < buffers.size(); ++i) { 111 (void)i; 112 JXL_CHECK_PLANE_INITIALIZED(*buffers[i].first, buffers[i].second, i); 113 } 114 115 JXL_RETURN_IF_ERROR(ProcessBuffers(group_id, thread_id)); 116 return true; 117 } 118 119 Status RenderPipeline::PrepareForThreads(size_t num, bool use_group_ids) { 120 for (const auto& stage : stages_) { 121 JXL_RETURN_IF_ERROR(stage->PrepareForThreads(num)); 122 } 123 JXL_RETURN_IF_ERROR(PrepareForThreadsInternal(num, use_group_ids)); 124 return true; 125 } 126 127 Status RenderPipelineInput::Done() { 128 JXL_ASSERT(pipeline_); 129 JXL_RETURN_IF_ERROR(pipeline_->InputReady(group_id_, thread_id_, buffers_)); 130 return true; 131 } 132 133 } // namespace jxl