Fix T56657: Crash when creating a collection instance containing probes
[blender.git] / source / blender / draw / modes / paint_texture_mode.c
1 /*
2  * Copyright 2016, Blender Foundation.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * Contributor(s): Blender Institute
19  *
20  */
21
22 /** \file blender/draw/modes/paint_texture_mode.c
23  *  \ingroup draw
24  */
25
26 #include "DRW_engine.h"
27 #include "DRW_render.h"
28
29 #include "BIF_gl.h"
30
31 /* If builtin shaders are needed */
32 #include "GPU_shader.h"
33 #include "GPU_texture.h"
34
35 #include "draw_common.h"
36
37 #include "draw_mode_engines.h"
38
39 #include "DNA_mesh_types.h"
40
41 extern char datatoc_common_globals_lib_glsl[];
42 extern char datatoc_paint_texture_vert_glsl[];
43 extern char datatoc_paint_texture_frag_glsl[];
44 extern char datatoc_paint_wire_vert_glsl[];
45 extern char datatoc_paint_wire_frag_glsl[];
46
47 /* If needed, contains all global/Theme colors
48  * Add needed theme colors / values to DRW_globals_update() and update UBO
49  * Not needed for constant color. */
50 extern struct GPUUniformBuffer *globals_ubo; /* draw_common.c */
51 extern struct GlobalsUboStorage ts; /* draw_common.c */
52
53 /* *********** LISTS *********** */
54 /* All lists are per viewport specific datas.
55  * They are all free when viewport changes engines
56  * or is free itself. Use PAINT_TEXTURE_engine_init() to
57  * initialize most of them and PAINT_TEXTURE_cache_init()
58  * for PAINT_TEXTURE_PassList */
59
60 typedef struct PAINT_TEXTURE_PassList {
61         /* Declare all passes here and init them in
62          * PAINT_TEXTURE_cache_init().
63          * Only contains (DRWPass *) */
64         struct DRWPass *image_faces;
65
66         struct DRWPass *wire_overlay;
67         struct DRWPass *face_overlay;
68 } PAINT_TEXTURE_PassList;
69
70 typedef struct PAINT_TEXTURE_FramebufferList {
71         /* Contains all framebuffer objects needed by this engine.
72          * Only contains (GPUFrameBuffer *) */
73         struct GPUFrameBuffer *fb;
74 } PAINT_TEXTURE_FramebufferList;
75
76 typedef struct PAINT_TEXTURE_TextureList {
77         /* Contains all framebuffer textures / utility textures
78          * needed by this engine. Only viewport specific textures
79          * (not per object). Only contains (GPUTexture *) */
80         struct GPUTexture *texture;
81 } PAINT_TEXTURE_TextureList;
82
83 typedef struct PAINT_TEXTURE_StorageList {
84         /* Contains any other memory block that the engine needs.
85          * Only directly MEM_(m/c)allocN'ed blocks because they are
86          * free with MEM_freeN() when viewport is freed.
87          * (not per object) */
88         struct CustomStruct *block;
89         struct PAINT_TEXTURE_PrivateData *g_data;
90 } PAINT_TEXTURE_StorageList;
91
92 typedef struct PAINT_TEXTURE_Data {
93         /* Struct returned by DRW_viewport_engine_data_ensure.
94          * If you don't use one of these, just make it a (void *) */
95         // void *fbl;
96         void *engine_type; /* Required */
97         PAINT_TEXTURE_FramebufferList *fbl;
98         PAINT_TEXTURE_TextureList *txl;
99         PAINT_TEXTURE_PassList *psl;
100         PAINT_TEXTURE_StorageList *stl;
101 } PAINT_TEXTURE_Data;
102
103 /* *********** STATIC *********** */
104
105 static struct {
106         /* Custom shaders :
107          * Add sources to source/blender/draw/modes/shaders
108          * init in PAINT_TEXTURE_engine_init();
109          * free in PAINT_TEXTURE_engine_free(); */
110         struct GPUShader *fallback_sh;
111         struct GPUShader *image_sh;
112
113         struct GPUShader *wire_overlay_shader;
114         struct GPUShader *face_overlay_shader;
115 } e_data = {NULL}; /* Engine data */
116
117 typedef struct PAINT_TEXTURE_PrivateData {
118         /* This keeps the references of the shading groups for
119          * easy access in PAINT_TEXTURE_cache_populate() */
120         DRWShadingGroup *shgroup_fallback;
121         DRWShadingGroup **shgroup_image_array;
122
123         /* face-mask  */
124         DRWShadingGroup *lwire_shgrp;
125         DRWShadingGroup *face_shgrp;
126 } PAINT_TEXTURE_PrivateData; /* Transient data */
127
128 /* *********** FUNCTIONS *********** */
129
130 /* Init Textures, Framebuffers, Storage and Shaders.
131  * It is called for every frames.
132  * (Optional) */
133 static void PAINT_TEXTURE_engine_init(void *vedata)
134 {
135         PAINT_TEXTURE_TextureList *txl = ((PAINT_TEXTURE_Data *)vedata)->txl;
136         PAINT_TEXTURE_FramebufferList *fbl = ((PAINT_TEXTURE_Data *)vedata)->fbl;
137         PAINT_TEXTURE_StorageList *stl = ((PAINT_TEXTURE_Data *)vedata)->stl;
138
139         UNUSED_VARS(txl, fbl, stl);
140
141         /* Init Framebuffers like this: order is attachment order (for color texs) */
142         /*
143          * DRWFboTexture tex[2] = {{&txl->depth, GPU_DEPTH_COMPONENT24, 0},
144          *                         {&txl->color, GPU_RGBA8, DRW_TEX_FILTER}};
145          */
146
147         /* DRW_framebuffer_init takes care of checking if
148          * the framebuffer is valid and has the right size*/
149         /*
150          * float *viewport_size = DRW_viewport_size_get();
151          * DRW_framebuffer_init(&fbl->occlude_wire_fb,
152          *                     (int)viewport_size[0], (int)viewport_size[1],
153          *                     tex, 2);
154          */
155
156         if (!e_data.fallback_sh) {
157                 e_data.fallback_sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
158         }
159         if (!e_data.image_sh) {
160                 e_data.image_sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
161
162                 e_data.image_sh = DRW_shader_create_with_lib(
163                         datatoc_paint_texture_vert_glsl, NULL,
164                         datatoc_paint_texture_frag_glsl,
165                         datatoc_common_globals_lib_glsl, NULL);
166
167         }
168
169         if (!e_data.wire_overlay_shader) {
170                 e_data.wire_overlay_shader = DRW_shader_create_with_lib(
171                         datatoc_paint_wire_vert_glsl, NULL,
172                         datatoc_paint_wire_frag_glsl,
173                         datatoc_common_globals_lib_glsl,
174                         "#define VERTEX_MODE\n");
175         }
176
177         if (!e_data.face_overlay_shader) {
178                 e_data.face_overlay_shader = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
179         }
180 }
181
182 /* Here init all passes and shading groups
183  * Assume that all Passes are NULL */
184 static void PAINT_TEXTURE_cache_init(void *vedata)
185 {
186         PAINT_TEXTURE_PassList *psl = ((PAINT_TEXTURE_Data *)vedata)->psl;
187         PAINT_TEXTURE_StorageList *stl = ((PAINT_TEXTURE_Data *)vedata)->stl;
188
189         if (!stl->g_data) {
190                 /* Alloc transient pointers */
191                 stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__);
192                 stl->g_data->shgroup_image_array = NULL;
193         }
194
195         {
196                 /* Create a pass */
197                 DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_BLEND;
198                 psl->image_faces = DRW_pass_create("Image Color Pass", state);
199
200                 stl->g_data->shgroup_fallback = DRW_shgroup_create(e_data.fallback_sh, psl->image_faces);
201
202                 /* Uniforms need a pointer to it's value so be sure it's accessible at
203                  * any given time (i.e. use static vars) */
204                 static float color[4] = {1.0f, 0.0f, 1.0f, 1.0};
205                 DRW_shgroup_uniform_vec4(stl->g_data->shgroup_fallback, "color", color, 1);
206
207                 MEM_SAFE_FREE(stl->g_data->shgroup_image_array);
208
209                 const DRWContextState *draw_ctx = DRW_context_state_get();
210                 Object *ob = draw_ctx->obact;
211                 if (ob && ob->type == OB_MESH) {
212                         Scene *scene = draw_ctx->scene;
213                         const bool use_material_slots = (scene->toolsettings->imapaint.mode == IMAGEPAINT_MODE_MATERIAL);
214                         const Mesh *me = ob->data;
215
216                         stl->g_data->shgroup_image_array = MEM_mallocN(
217                                 sizeof(*stl->g_data->shgroup_image_array) * (use_material_slots ? me->totcol : 1), __func__);
218
219                         if (use_material_slots) {
220                                 for (int i = 0; i < me->totcol; i++) {
221                                         Material *ma = give_current_material(ob, i + 1);
222                                         Image *ima = (ma && ma->texpaintslot) ? ma->texpaintslot[ma->paint_active_slot].ima : NULL;
223                                         GPUTexture *tex = ima ?
224                                                 GPU_texture_from_blender(ima, NULL, GL_TEXTURE_2D, false, 0.0f) : NULL;
225
226                                         if (tex) {
227                                                 DRWShadingGroup *grp = DRW_shgroup_create(e_data.image_sh, psl->image_faces);
228                                                 DRW_shgroup_uniform_texture(grp, "image", tex);
229                                                 DRW_shgroup_uniform_float(grp, "alpha", &draw_ctx->v3d->overlay.texture_paint_mode_opacity, 1);
230                                                 DRW_shgroup_uniform_block(grp, "globalsBlock", globals_ubo);
231                                                 stl->g_data->shgroup_image_array[i] = grp;
232                                         }
233                                         else {
234                                                 stl->g_data->shgroup_image_array[i] = NULL;
235                                         }
236                                 }
237                         }
238                         else {
239                                 Image *ima = scene->toolsettings->imapaint.canvas;
240                                 GPUTexture *tex = ima ?
241                                         GPU_texture_from_blender(ima, NULL, GL_TEXTURE_2D, false, 0.0f) : NULL;
242
243                                 if (tex) {
244                                         DRWShadingGroup *grp = DRW_shgroup_create(e_data.image_sh, psl->image_faces);
245                                         DRW_shgroup_uniform_texture(grp, "image", tex);
246                                         DRW_shgroup_uniform_float(grp, "alpha", &draw_ctx->v3d->overlay.texture_paint_mode_opacity, 1);
247                                         stl->g_data->shgroup_image_array[0] = grp;
248                                 }
249                                 else {
250                                         stl->g_data->shgroup_image_array[0] = NULL;
251                                 }
252                         }
253                 }
254         }
255
256         /* Face Mask */
257         {
258                 psl->wire_overlay = DRW_pass_create(
259                         "Wire Pass",
260                         DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL);
261
262                 stl->g_data->lwire_shgrp = DRW_shgroup_create(e_data.wire_overlay_shader, psl->wire_overlay);
263                 DRW_shgroup_uniform_block(stl->g_data->lwire_shgrp, "globalsBlock", globals_ubo);
264         }
265
266         {
267                 psl->face_overlay = DRW_pass_create(
268                         "Face Mask Pass",
269                         DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND);
270
271                 stl->g_data->face_shgrp = DRW_shgroup_create(e_data.face_overlay_shader, psl->face_overlay);
272
273                 static float col[4] = {1.0f, 1.0f, 1.0f, 0.2f};
274                 DRW_shgroup_uniform_vec4(stl->g_data->face_shgrp, "color", col, 1);
275         }
276 }
277
278 /* Add geometry to shadingGroups. Execute for each objects */
279 static void PAINT_TEXTURE_cache_populate(void *vedata, Object *ob)
280 {
281         PAINT_TEXTURE_PassList *psl = ((PAINT_TEXTURE_Data *)vedata)->psl;
282         PAINT_TEXTURE_StorageList *stl = ((PAINT_TEXTURE_Data *)vedata)->stl;
283         const DRWContextState *draw_ctx = DRW_context_state_get();
284
285         UNUSED_VARS(psl, stl);
286
287         if ((ob->type == OB_MESH) && (draw_ctx->obact == ob)) {
288                 /* Get geometry cache */
289                 const Mesh *me = ob->data;
290                 Scene *scene = draw_ctx->scene;
291                 const bool use_surface = draw_ctx->v3d->overlay.texture_paint_mode_opacity != 0.0; //DRW_object_is_mode_shade(ob) == true;
292                 const bool use_material_slots = (scene->toolsettings->imapaint.mode == IMAGEPAINT_MODE_MATERIAL);
293                 bool ok = false;
294
295                 if (use_surface) {
296                         if (me->mloopuv != NULL) {
297                                 if (use_material_slots) {
298                                         struct GPUBatch **geom_array = me->totcol ? DRW_cache_mesh_surface_texpaint_get(ob) : NULL;
299                                         if ((me->totcol == 0) || (geom_array == NULL)) {
300                                                 struct GPUBatch *geom = DRW_cache_mesh_surface_get(ob);
301                                                 DRW_shgroup_call_add(stl->g_data->shgroup_fallback, geom, ob->obmat);
302                                                 ok = true;
303                                         }
304                                         else {
305                                                 for (int i = 0; i < me->totcol; i++) {
306                                                         if (stl->g_data->shgroup_image_array[i]) {
307                                                                 DRW_shgroup_call_add(stl->g_data->shgroup_image_array[i], geom_array[i], ob->obmat);
308                                                         }
309                                                         else {
310                                                                 DRW_shgroup_call_add(stl->g_data->shgroup_fallback, geom_array[i], ob->obmat);
311                                                         }
312                                                         ok = true;
313                                                 }
314                                         }
315                                 }
316                                 else {
317                                         struct GPUBatch *geom = DRW_cache_mesh_surface_texpaint_single_get(ob);
318                                         if (geom && stl->g_data->shgroup_image_array[0]) {
319                                                 DRW_shgroup_call_add(stl->g_data->shgroup_image_array[0], geom, ob->obmat);
320                                                 ok = true;
321                                         }
322                                 }
323                         }
324
325                         if (!ok) {
326                                 struct GPUBatch *geom = DRW_cache_mesh_surface_get(ob);
327                                 DRW_shgroup_call_add(stl->g_data->shgroup_fallback, geom, ob->obmat);
328                         }
329                 }
330
331                 /* Face Mask */
332                 const bool use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
333                 if (use_face_sel) {
334                         struct GPUBatch *geom;
335                         /* Note: ideally selected faces wouldn't show interior wire. */
336                         const bool use_wire = true;
337                         geom = DRW_cache_mesh_edges_paint_overlay_get(ob, use_wire, use_face_sel);
338                         DRW_shgroup_call_add(stl->g_data->lwire_shgrp, geom, ob->obmat);
339
340                         geom = DRW_cache_mesh_faces_weight_overlay_get(ob);
341                         DRW_shgroup_call_add(stl->g_data->face_shgrp, geom, ob->obmat);
342                 }
343         }
344 }
345
346 /* Optional: Post-cache_populate callback */
347 static void PAINT_TEXTURE_cache_finish(void *vedata)
348 {
349         PAINT_TEXTURE_PassList *psl = ((PAINT_TEXTURE_Data *)vedata)->psl;
350         PAINT_TEXTURE_StorageList *stl = ((PAINT_TEXTURE_Data *)vedata)->stl;
351
352         /* Do something here! dependant on the objects gathered */
353         UNUSED_VARS(psl);
354
355         MEM_SAFE_FREE(stl->g_data->shgroup_image_array);
356 }
357
358 /* Draw time ! Control rendering pipeline from here */
359 static void PAINT_TEXTURE_draw_scene(void *vedata)
360 {
361         PAINT_TEXTURE_PassList *psl = ((PAINT_TEXTURE_Data *)vedata)->psl;
362         PAINT_TEXTURE_FramebufferList *fbl = ((PAINT_TEXTURE_Data *)vedata)->fbl;
363
364         /* Default framebuffer and texture */
365         DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
366         DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
367
368         UNUSED_VARS(fbl, dfbl, dtxl);
369
370         DRW_draw_pass(psl->image_faces);
371
372         DRW_draw_pass(psl->face_overlay);
373         DRW_draw_pass(psl->wire_overlay);
374 }
375
376 /* Cleanup when destroying the engine.
377  * This is not per viewport ! only when quitting blender.
378  * Mostly used for freeing shaders */
379 static void PAINT_TEXTURE_engine_free(void)
380 {
381         DRW_SHADER_FREE_SAFE(e_data.image_sh);
382         DRW_SHADER_FREE_SAFE(e_data.wire_overlay_shader);
383 }
384
385 static const DrawEngineDataSize PAINT_TEXTURE_data_size = DRW_VIEWPORT_DATA_SIZE(PAINT_TEXTURE_Data);
386
387 DrawEngineType draw_engine_paint_texture_type = {
388         NULL, NULL,
389         N_("PaintTextureMode"),
390         &PAINT_TEXTURE_data_size,
391         &PAINT_TEXTURE_engine_init,
392         &PAINT_TEXTURE_engine_free,
393         &PAINT_TEXTURE_cache_init,
394         &PAINT_TEXTURE_cache_populate,
395         &PAINT_TEXTURE_cache_finish,
396         NULL, /* draw_background but not needed by mode engines */
397         &PAINT_TEXTURE_draw_scene,
398         NULL,
399         NULL,
400 };