libjxl

FORK: libjxl patches used on blog
git clone https://git.neptards.moe/blog/libjxl.git
Log | Files | Refs | Submodules | README | LICENSE

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