Welcome to mirror list, hosted at ThFree Co, Russian Federation.

compositor_engine.cc « compositor « engines « draw « blender « source - git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 2c9e5182b01812e4564e27db8b381ded48d5f919 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
/* SPDX-License-Identifier: GPL-2.0-or-later */

#include "BLI_listbase.h"
#include "BLI_math_vec_types.hh"
#include "BLI_string_ref.hh"
#include "BLI_utildefines.h"

#include "BLT_translation.h"

#include "DNA_ID_enums.h"
#include "DNA_scene_types.h"

#include "DEG_depsgraph_query.h"

#include "DRW_render.h"

#include "IMB_colormanagement.h"

#include "COM_context.hh"
#include "COM_evaluator.hh"
#include "COM_texture_pool.hh"

#include "GPU_texture.h"

namespace blender::draw::compositor {

class TexturePool : public realtime_compositor::TexturePool {
 public:
  GPUTexture *allocate_texture(int2 size, eGPUTextureFormat format) override
  {
    DrawEngineType *owner = (DrawEngineType *)this;
    return DRW_texture_pool_query_2d(size.x, size.y, format, owner);
  }
};

class Context : public realtime_compositor::Context {
 private:
  /* A pointer to the info message of the compositor engine. This is a char array of size
   * GPU_INFO_SIZE. The message is cleared prior to updating or evaluating the compositor. */
  char *info_message_;

 public:
  Context(realtime_compositor::TexturePool &texture_pool, char *info_message)
      : realtime_compositor::Context(texture_pool), info_message_(info_message)
  {
  }

  const Scene *get_scene() const override
  {
    return DRW_context_state_get()->scene;
  }

  int2 get_output_size() override
  {
    return int2(float2(DRW_viewport_size_get()));
  }

  GPUTexture *get_output_texture() override
  {
    return DRW_viewport_texture_list_get()->color;
  }

  GPUTexture *get_input_texture(int /*view_layer*/, eScenePassType /*pass_type*/) override
  {
    return get_output_texture();
  }

  StringRef get_view_name() override
  {
    const SceneRenderView *view = static_cast<SceneRenderView *>(
        BLI_findlink(&get_scene()->r.views, DRW_context_state_get()->v3d->multiview_eye));
    return view->name;
  }

  void set_info_message(StringRef message) const override
  {
    message.copy(info_message_, GPU_INFO_SIZE);
  }
};

class Engine {
 private:
  TexturePool texture_pool_;
  Context context_;
  realtime_compositor::Evaluator evaluator_;
  /* Stores the viewport size at the time the last compositor evaluation happened. See the
   * update_viewport_size method for more information. */
  int2 last_viewport_size_;

 public:
  Engine(char *info_message)
      : context_(texture_pool_, info_message),
        evaluator_(context_, node_tree()),
        last_viewport_size_(context_.get_output_size())
  {
  }

  /* Update the viewport size and evaluate the compositor. */
  void draw()
  {
    update_viewport_size();
    evaluator_.evaluate();
  }

  /* If the size of the viewport changed from the last time the compositor was evaluated, update
   * the viewport size and reset the evaluator. That's because the evaluator compiles the node tree
   * in a manner that is specifically optimized for the size of the viewport. This should be called
   * before evaluating the compositor. */
  void update_viewport_size()
  {
    if (last_viewport_size_ == context_.get_output_size()) {
      return;
    }

    last_viewport_size_ = context_.get_output_size();

    evaluator_.reset();
  }

  /* If the compositor node tree changed, reset the evaluator. */
  void update(const Depsgraph *depsgraph)
  {
    if (DEG_id_type_updated(depsgraph, ID_NT)) {
      evaluator_.reset();
    }
  }

  /* Get a reference to the compositor node tree. */
  static bNodeTree &node_tree()
  {
    return *DRW_context_state_get()->scene->nodetree;
  }
};

}  // namespace blender::draw::compositor

using namespace blender::draw::compositor;

struct COMPOSITOR_Data {
  DrawEngineType *engine_type;
  DRWViewportEmptyList *fbl;
  DRWViewportEmptyList *txl;
  DRWViewportEmptyList *psl;
  DRWViewportEmptyList *stl;
  Engine *instance_data;
  char info[GPU_INFO_SIZE];
};

static void compositor_engine_init(void *data)
{
  COMPOSITOR_Data *compositor_data = static_cast<COMPOSITOR_Data *>(data);

  if (!compositor_data->instance_data) {
    compositor_data->instance_data = new Engine(compositor_data->info);
  }
}

static void compositor_engine_free(void *instance_data)
{
  Engine *engine = static_cast<Engine *>(instance_data);
  delete engine;
}

static void compositor_engine_draw(void *data)
{
  const COMPOSITOR_Data *compositor_data = static_cast<COMPOSITOR_Data *>(data);
  compositor_data->instance_data->draw();
}

static void compositor_engine_update(void *data)
{
  COMPOSITOR_Data *compositor_data = static_cast<COMPOSITOR_Data *>(data);

  /* Clear any info message that was set in a previous update. */
  compositor_data->info[0] = '\0';

  if (compositor_data->instance_data) {
    compositor_data->instance_data->update(DRW_context_state_get()->depsgraph);
  }
}

extern "C" {

static const DrawEngineDataSize compositor_data_size = DRW_VIEWPORT_DATA_SIZE(COMPOSITOR_Data);

DrawEngineType draw_engine_compositor_type = {
    nullptr,                   /* next */
    nullptr,                   /* prev */
    N_("Compositor"),          /* idname */
    &compositor_data_size,     /* vedata_size */
    &compositor_engine_init,   /* engine_init */
    nullptr,                   /* engine_free */
    &compositor_engine_free,   /* instance_free */
    nullptr,                   /* cache_init */
    nullptr,                   /* cache_populate */
    nullptr,                   /* cache_finish */
    &compositor_engine_draw,   /* draw_scene */
    &compositor_engine_update, /* view_update */
    nullptr,                   /* id_update */
    nullptr,                   /* render_to_image */
    nullptr,                   /* store_metadata */
};
}