Blender  V3.3
draw_manager_shader.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2016 Blender Foundation. */
3 
8 #include "DNA_material_types.h"
9 #include "DNA_object_types.h"
10 #include "DNA_world_types.h"
11 
12 #include "PIL_time.h"
13 
14 #include "BLI_dynstr.h"
15 #include "BLI_listbase.h"
16 #include "BLI_string_utils.h"
17 #include "BLI_threads.h"
18 
19 #include "BKE_context.h"
20 #include "BKE_global.h"
21 #include "BKE_main.h"
22 
23 #include "DEG_depsgraph_query.h"
24 
25 #include "GPU_capabilities.h"
26 #include "GPU_material.h"
27 #include "GPU_shader.h"
28 
29 #include "WM_api.h"
30 #include "WM_types.h"
31 
32 #include "wm_window.h"
33 
34 #include "draw_manager.h"
35 
36 #include "CLG_log.h"
37 
38 static CLG_LogRef LOG = {"draw.manager.shader"};
39 
42 
43 #define USE_DEFERRED_COMPILATION 1
44 
45 /* -------------------------------------------------------------------- */
53 typedef struct DRWShaderCompiler {
54  ListBase queue; /* GPUMaterial */
56 
57  void *gl_context;
61 
63  void *custom_data,
64  /* Cannot be const, this function implements wm_jobs_start_callback.
65  * NOLINTNEXTLINE: readability-non-const-parameter. */
66  short *stop,
67  short *UNUSED(do_update),
68  float *UNUSED(progress))
69 {
71  DRWShaderCompiler *comp = (DRWShaderCompiler *)custom_data;
72  void *gl_context = comp->gl_context;
73  GPUContext *gpu_context = comp->gpu_context;
74 
75  BLI_assert(gl_context != NULL);
76  BLI_assert(gpu_context != NULL);
77 
78  const bool use_main_context_workaround = GPU_use_main_context_workaround();
79  if (use_main_context_workaround) {
80  BLI_assert(gl_context == DST.gl_context);
82  }
83 
84  WM_opengl_context_activate(gl_context);
85  GPU_context_active_set(gpu_context);
86 
87  while (true) {
88  if (*stop != 0) {
89  /* We don't want user to be able to cancel the compilation
90  * but wm can kill the task if we are closing blender. */
91  break;
92  }
93 
94  BLI_spin_lock(&comp->list_lock);
95  /* Pop tail because it will be less likely to lock the main thread
96  * if all GPUMaterials are to be freed (see DRW_deferred_shader_remove()). */
97  LinkData *link = (LinkData *)BLI_poptail(&comp->queue);
98  GPUMaterial *mat = link ? (GPUMaterial *)link->data : NULL;
99  if (mat) {
100  /* Avoid another thread freeing the material mid compilation. */
102  }
103  BLI_spin_unlock(&comp->list_lock);
104 
105  if (mat) {
106  /* Do the compilation. */
109  MEM_freeN(link);
110  }
111  else {
112  break;
113  }
114 
116  GPU_flush();
117  }
118  }
119 
121  WM_opengl_context_release(gl_context);
122  if (use_main_context_workaround) {
124  }
125  GPU_render_end();
126 }
127 
128 static void drw_deferred_shader_compilation_free(void *custom_data)
129 {
130  DRWShaderCompiler *comp = (DRWShaderCompiler *)custom_data;
131 
132  BLI_spin_lock(&comp->list_lock);
133  BLI_freelistN(&comp->queue);
134  BLI_spin_unlock(&comp->list_lock);
135 
136  if (comp->own_context) {
137  /* Only destroy if the job owns the context. */
142 
144  }
145 
146  MEM_freeN(comp);
147 }
148 
149 static void drw_deferred_shader_add(GPUMaterial *mat, bool deferred)
150 {
152  return;
153  }
154  /* Do not defer the compilation if we are rendering for image.
155  * deferred rendering is only possible when `evil_C` is available */
157  deferred = false;
158  }
159 
160  if (!deferred) {
162  /* Shaders could already be compiling. Have to wait for compilation to finish. */
163  while (GPU_material_status(mat) == GPU_MAT_QUEUED) {
164  PIL_sleep_ms(20);
165  }
166  if (GPU_material_status(mat) == GPU_MAT_CREATED) {
168  }
169  return;
170  }
171 
172  /* Don't add material to the queue twice. */
173  if (GPU_material_status(mat) == GPU_MAT_QUEUED) {
174  return;
175  }
176 
177  const bool use_main_context = GPU_use_main_context_workaround();
178  const bool job_own_context = !use_main_context;
179 
183 
184  /* Get the running job or a new one if none is running. Can only have one job per type & owner.
185  */
186  wmJob *wm_job = WM_jobs_get(
187  wm, win, wm, "Shaders Compilation", 0, WM_JOB_TYPE_SHADER_COMPILATION);
188 
190 
191  DRWShaderCompiler *comp = MEM_callocN(sizeof(DRWShaderCompiler), "DRWShaderCompiler");
192  BLI_spin_init(&comp->list_lock);
193 
194  if (old_comp) {
195  BLI_spin_lock(&old_comp->list_lock);
196  BLI_movelisttolist(&comp->queue, &old_comp->queue);
197  BLI_spin_unlock(&old_comp->list_lock);
198  /* Do not recreate context, just pass ownership. */
199  if (old_comp->gl_context) {
200  comp->gl_context = old_comp->gl_context;
201  comp->gpu_context = old_comp->gpu_context;
202  old_comp->own_context = false;
203  comp->own_context = job_own_context;
204  }
205  }
206 
209  BLI_addtail(&comp->queue, node);
210 
211  /* Create only one context. */
212  if (comp->gl_context == NULL) {
213  if (use_main_context) {
214  comp->gl_context = DST.gl_context;
215  comp->gpu_context = DST.gpu_context;
216  }
217  else {
221 
224  }
225  comp->own_context = job_own_context;
226  }
227 
229  WM_jobs_timer(wm_job, 0.1, NC_MATERIAL | ND_SHADING_DRAW, 0);
230  WM_jobs_delay_start(wm_job, 0.1);
232 
233  G.is_break = false;
234 
235  WM_jobs_start(wm, wm_job);
236 }
237 
239 {
240  LISTBASE_FOREACH (wmWindowManager *, wm, &G_MAIN->wm) {
241  LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
244  if (comp != NULL) {
245  BLI_spin_lock(&comp->list_lock);
246  LinkData *link = (LinkData *)BLI_findptr(&comp->queue, mat, offsetof(LinkData, data));
247  if (link) {
248  BLI_remlink(&comp->queue, link);
250  }
251  BLI_spin_unlock(&comp->list_lock);
252 
253  MEM_SAFE_FREE(link);
254  }
255  }
256  }
257 }
258 
261 /* -------------------------------------------------------------------- */
262 
266  const char *vert, const char *geom, const char *frag, const char *defines, const char *name)
267 {
268  return GPU_shader_create(vert, frag, geom, NULL, defines, name);
269 }
270 
272  const char *geom,
273  const char *frag,
274  const char *lib,
275  const char *defines,
276  const char *name)
277 {
278  GPUShader *sh;
279  char *vert_with_lib = NULL;
280  char *frag_with_lib = NULL;
281  char *geom_with_lib = NULL;
282 
283  vert_with_lib = BLI_string_joinN(lib, vert);
284  frag_with_lib = BLI_string_joinN(lib, frag);
285  if (geom) {
286  geom_with_lib = BLI_string_joinN(lib, geom);
287  }
288 
289  sh = GPU_shader_create(vert_with_lib, frag_with_lib, geom_with_lib, NULL, defines, name);
290 
291  MEM_freeN(vert_with_lib);
292  MEM_freeN(frag_with_lib);
293  if (geom) {
294  MEM_freeN(geom_with_lib);
295  }
296 
297  return sh;
298 }
299 
301  const char *geom,
302  const char *frag,
303  const DRWShaderLibrary *lib,
304  const char *defines,
305  const char *name)
306 {
307  GPUShader *sh;
308  char *vert_with_lib = DRW_shader_library_create_shader_string(lib, vert);
309  char *frag_with_lib = DRW_shader_library_create_shader_string(lib, frag);
310  char *geom_with_lib = (geom) ? DRW_shader_library_create_shader_string(lib, geom) : NULL;
311 
312  sh = GPU_shader_create(vert_with_lib, frag_with_lib, geom_with_lib, NULL, defines, name);
313 
314  MEM_SAFE_FREE(vert_with_lib);
315  MEM_SAFE_FREE(frag_with_lib);
316  MEM_SAFE_FREE(geom_with_lib);
317 
318  return sh;
319 }
320 
322  const char *geom,
323  const char *defines,
324  const eGPUShaderTFBType prim_type,
325  const char **varying_names,
326  const int varying_count)
327 {
328  return GPU_shader_create_ex(vert,
330  geom,
331  NULL,
332  NULL,
333  defines,
334  prim_type,
335  varying_names,
336  varying_count,
337  __func__);
338 }
339 
340 GPUShader *DRW_shader_create_fullscreen_ex(const char *frag, const char *defines, const char *name)
341 {
342  return GPU_shader_create(datatoc_common_fullscreen_vert_glsl, frag, NULL, NULL, defines, name);
343 }
344 
346  const DRWShaderLibrary *lib,
347  const char *defines,
348  const char *name)
349 {
350 
351  GPUShader *sh;
353  char *frag_with_lib = DRW_shader_library_create_shader_string(lib, frag);
354 
355  sh = GPU_shader_create(vert, frag_with_lib, NULL, NULL, defines, name);
356 
357  MEM_SAFE_FREE(frag_with_lib);
358 
359  return sh;
360 }
361 
363  struct bNodeTree *ntree,
364  const uint64_t shader_id,
365  const bool is_volume_shader,
366  bool deferred,
368  void *thunk)
369 {
372  NULL,
373  ntree,
374  &wo->gpumaterial,
375  wo->id.name,
376  shader_id,
377  is_volume_shader,
378  false,
379  callback,
380  thunk);
382  /* Do not deferred if doing render. */
383  deferred = false;
384  }
385 
386  drw_deferred_shader_add(mat, deferred);
387  return mat;
388 }
389 
391  struct bNodeTree *ntree,
392  const uint64_t shader_id,
393  const bool is_volume_shader,
394  bool deferred,
396  void *thunk)
397 {
400  ma,
401  ntree,
402  &ma->gpumaterial,
403  ma->id.name,
404  shader_id,
405  is_volume_shader,
406  false,
407  callback,
408  thunk);
409 
411  /* Do not deferred if doing render. */
412  deferred = false;
413  }
414 
415  drw_deferred_shader_add(mat, deferred);
416  return mat;
417 }
418 
420 {
421  GPU_shader_free(shader);
422 }
423 
426 /* -------------------------------------------------------------------- */
438 /* 64 because we use a 64bit bitmap. */
439 #define MAX_LIB 64
440 #define MAX_LIB_NAME 64
441 #define MAX_LIB_DEPS 8
442 
444  const char *libs[MAX_LIB];
447 };
448 
450 {
451  return MEM_callocN(sizeof(DRWShaderLibrary), "DRWShaderLibrary");
452 }
453 
455 {
457 }
458 
459 static int drw_shader_library_search(const DRWShaderLibrary *lib, const char *name)
460 {
461  for (int i = 0; i < MAX_LIB; i++) {
462  if (lib->libs[i]) {
463  if (!strncmp(lib->libs_name[i], name, strlen(lib->libs_name[i]))) {
464  return i;
465  }
466  }
467  else {
468  break;
469  }
470  }
471  return -1;
472 }
473 
474 /* Return bitmap of dependencies. */
476  const char *pragma_str,
477  const char *lib_code,
478  const char *UNUSED(lib_name))
479 {
480  /* Search dependencies. */
481  uint pragma_len = strlen(pragma_str);
482  uint64_t deps = 0;
483  const char *haystack = lib_code;
484  while ((haystack = strstr(haystack, pragma_str))) {
485  haystack += pragma_len;
486  int dep = drw_shader_library_search(lib, haystack);
487  if (dep == -1) {
488  char dbg_name[MAX_NAME];
489  int i = 0;
490  while ((*haystack != ')') && (i < (sizeof(dbg_name) - 2))) {
491  dbg_name[i] = *haystack;
492  haystack++;
493  i++;
494  }
495  dbg_name[i] = '\0';
496 
497  CLOG_INFO(&LOG,
498  0,
499  "Dependency '%s' not found\n"
500  "This might be due to bad lib ordering or overriding a builtin shader.\n",
501  dbg_name);
502  }
503  else {
504  deps |= 1llu << ((uint64_t)dep);
505  }
506  }
507  return deps;
508 }
509 
510 void DRW_shader_library_add_file(DRWShaderLibrary *lib, const char *lib_code, const char *lib_name)
511 {
512  int index = -1;
513  for (int i = 0; i < MAX_LIB; i++) {
514  if (lib->libs[i] == NULL) {
515  index = i;
516  break;
517  }
518  }
519 
520  if (index > -1) {
521  lib->libs[index] = lib_code;
522  BLI_strncpy(lib->libs_name[index], lib_name, MAX_LIB_NAME);
524  lib, "BLENDER_REQUIRE(", lib_code, lib_name);
525  }
526  else {
527  printf("Error: Too many libraries. Cannot add %s.\n", lib_name);
528  BLI_assert(0);
529  }
530 }
531 
532 char *DRW_shader_library_create_shader_string(const DRWShaderLibrary *lib, const char *shader_code)
533 {
534  uint64_t deps = drw_shader_dependencies_get(lib, "BLENDER_REQUIRE(", shader_code, "shader code");
535 
536  DynStr *ds = BLI_dynstr_new();
537  /* Add all dependencies recursively. */
538  for (int i = MAX_LIB - 1; i > -1; i--) {
539  if (lib->libs[i] && (deps & (1llu << (uint64_t)i))) {
540  deps |= lib->libs_deps[i];
541  }
542  }
543  /* Concatenate all needed libs into one string. */
544  for (int i = 0; i < MAX_LIB && deps != 0llu; i++, deps >>= 1llu) {
545  if (deps & 1llu) {
546  BLI_dynstr_append(ds, lib->libs[i]);
547  }
548  }
549 
550  BLI_dynstr_append(ds, shader_code);
551 
552  char *str = BLI_dynstr_get_cstring(ds);
553  BLI_dynstr_free(ds);
554 
555  return str;
556 }
557 
struct wmWindowManager * CTX_wm_manager(const bContext *C)
Definition: context.c:713
struct wmWindow * CTX_wm_window(const bContext *C)
Definition: context.c:723
#define G_MAIN
Definition: BKE_global.h:267
#define BLI_assert(a)
Definition: BLI_assert.h:46
A dynamically sized string ADT.
DynStr * BLI_dynstr_new(void) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
Definition: BLI_dynstr.c:50
char * BLI_dynstr_get_cstring(const DynStr *ds) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: BLI_dynstr.c:256
void BLI_dynstr_free(DynStr *ds) ATTR_NONNULL()
Definition: BLI_dynstr.c:281
void BLI_dynstr_append(DynStr *__restrict ds, const char *cstr) ATTR_NONNULL()
Definition: BLI_dynstr.c:75
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
struct LinkData * BLI_genericNodeN(void *data)
Definition: listbase.c:842
void void void BLI_movelisttolist(struct ListBase *dst, struct ListBase *src) ATTR_NONNULL(1
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
Definition: listbase.c:466
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:80
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:100
void * BLI_poptail(ListBase *listbase) ATTR_NONNULL(1)
Definition: listbase.c:230
void * BLI_findptr(const struct ListBase *listbase, const void *ptr, int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t maxncpy) ATTR_NONNULL()
Definition: string.c:64
#define BLI_string_joinN(...)
unsigned int uint
Definition: BLI_sys_types.h:67
pthread_spinlock_t SpinLock
Definition: BLI_threads.h:110
void BLI_spin_init(SpinLock *spin)
Definition: threads.cc:419
void BLI_spin_unlock(SpinLock *spin)
Definition: threads.cc:452
void BLI_spin_lock(SpinLock *spin)
Definition: threads.cc:433
#define UNUSED(x)
#define ELEM(...)
#define CLOG_INFO(clg_ref, level,...)
Definition: CLG_log.h:187
struct ID * DEG_get_original_id(struct ID *id)
#define MAX_NAME
Definition: DNA_defs.h:48
Object is a sort of wrapper for general info.
bool GPU_use_main_context_workaround(void)
struct GPUContext GPUContext
Definition: GPU_context.h:27
void GPU_context_main_lock(void)
Definition: gpu_context.cc:171
void GPU_render_begin(void)
Definition: gpu_context.cc:190
void GPU_context_discard(GPUContext *)
Definition: gpu_context.cc:110
GPUContext * GPU_context_create(void *ghost_window)
Definition: gpu_context.cc:93
void GPU_context_active_set(GPUContext *)
Definition: gpu_context.cc:127
void GPU_context_main_unlock(void)
Definition: gpu_context.cc:176
void GPU_render_end(void)
Definition: gpu_context.cc:196
GPUMaterial * GPU_material_from_nodetree(struct Scene *scene, struct Material *ma, struct bNodeTree *ntree, struct ListBase *gpumaterials, const char *name, uint64_t shader_uuid, bool is_volume_shader, bool is_lookdev, GPUCodegenCallbackFn callback, void *thunk)
Definition: gpu_material.c:624
void GPU_material_acquire(GPUMaterial *mat)
Definition: gpu_material.c:702
void GPU_material_compile(GPUMaterial *mat)
Definition: gpu_material.c:712
void GPU_material_status_set(GPUMaterial *mat, eGPUMaterialStatus status)
Definition: gpu_material.c:579
void(* GPUCodegenCallbackFn)(void *thunk, GPUMaterial *mat, GPUCodegenOutput *codegen)
Definition: GPU_material.h:137
void GPU_material_release(GPUMaterial *mat)
Definition: gpu_material.c:707
eGPUMaterialStatus GPU_material_status(GPUMaterial *mat)
Definition: gpu_material.c:574
@ GPU_MAT_QUEUED
Definition: GPU_material.h:116
@ GPU_MAT_FAILED
Definition: GPU_material.h:114
@ GPU_MAT_SUCCESS
Definition: GPU_material.h:117
@ GPU_MAT_CREATED
Definition: GPU_material.h:115
@ GPU_BACKEND_OPENGL
Definition: GPU_platform.h:17
@ GPU_DRIVER_ANY
Definition: GPU_platform.h:47
bool GPU_type_matches_ex(eGPUDeviceType device, eGPUOSType os, eGPUDriverType driver, eGPUBackendType backend)
@ GPU_OS_ANY
Definition: GPU_platform.h:40
@ GPU_DEVICE_ANY
Definition: GPU_platform.h:31
GPUShader * GPU_shader_create(const char *vertcode, const char *fragcode, const char *geomcode, const char *libcode, const char *defines, const char *shname)
Definition: gpu_shader.cc:211
struct GPUShader GPUShader
Definition: GPU_shader.h:20
GPUShader * GPU_shader_create_ex(const char *vertcode, const char *fragcode, const char *geomcode, const char *computecode, const char *libcode, const char *defines, eGPUShaderTFBType tf_type, const char **tf_names, int tf_count, const char *shname)
Definition: gpu_shader.cc:107
eGPUShaderTFBType
Definition: GPU_shader.h:22
void GPU_shader_free(GPUShader *shader)
Definition: gpu_shader.cc:200
void GPU_flush(void)
Definition: gpu_state.cc:291
#define MEM_SAFE_FREE(v)
Platform independent time functions.
@ WM_JOB_TYPE_SHADER_COMPILATION
Definition: WM_api.h:1367
#define NC_MATERIAL
Definition: WM_types.h:330
#define ND_SHADING_DRAW
Definition: WM_types.h:426
OperationNode * node
Scene scene
DEGForeachIDComponentCallback callback
DRWManager DST
Definition: draw_manager.c:104
bool DRW_state_is_image_render(void)
GPUMaterial * DRW_shader_from_world(World *wo, struct bNodeTree *ntree, const uint64_t shader_id, const bool is_volume_shader, bool deferred, GPUCodegenCallbackFn callback, void *thunk)
GPUMaterial * DRW_shader_from_material(Material *ma, struct bNodeTree *ntree, const uint64_t shader_id, const bool is_volume_shader, bool deferred, GPUCodegenCallbackFn callback, void *thunk)
GPUShader * DRW_shader_create_with_lib_ex(const char *vert, const char *geom, const char *frag, const char *lib, const char *defines, const char *name)
GPUShader * DRW_shader_create_with_transform_feedback(const char *vert, const char *geom, const char *defines, const eGPUShaderTFBType prim_type, const char **varying_names, const int varying_count)
char datatoc_gpu_shader_depth_only_frag_glsl[]
GPUShader * DRW_shader_create_ex(const char *vert, const char *geom, const char *frag, const char *defines, const char *name)
static void drw_deferred_shader_compilation_exec(void *custom_data, short *stop, short *UNUSED(do_update), float *UNUSED(progress))
void DRW_shader_free(GPUShader *shader)
struct DRWShaderCompiler DRWShaderCompiler
void DRW_shader_library_add_file(DRWShaderLibrary *lib, const char *lib_code, const char *lib_name)
char datatoc_common_fullscreen_vert_glsl[]
static int drw_shader_library_search(const DRWShaderLibrary *lib, const char *name)
void DRW_shader_library_free(DRWShaderLibrary *lib)
static uint64_t drw_shader_dependencies_get(const DRWShaderLibrary *lib, const char *pragma_str, const char *lib_code, const char *UNUSED(lib_name))
GPUShader * DRW_shader_create_fullscreen_ex(const char *frag, const char *defines, const char *name)
static CLG_LogRef LOG
GPUShader * DRW_shader_create_with_shaderlib_ex(const char *vert, const char *geom, const char *frag, const DRWShaderLibrary *lib, const char *defines, const char *name)
DRWShaderLibrary * DRW_shader_library_create(void)
GPUShader * DRW_shader_create_fullscreen_with_shaderlib_ex(const char *frag, const DRWShaderLibrary *lib, const char *defines, const char *name)
#define USE_DEFERRED_COMPILATION
char * DRW_shader_library_create_shader_string(const DRWShaderLibrary *lib, const char *shader_code)
#define MAX_LIB
static void drw_deferred_shader_add(GPUMaterial *mat, bool deferred)
void DRW_deferred_shader_remove(GPUMaterial *mat)
static void drw_deferred_shader_compilation_free(void *custom_data)
#define MAX_LIB_NAME
bNodeTree * ntree
DRWShaderLibrary * lib
#define str(s)
ccl_gpu_kernel_postfix ccl_global float int int int int sh
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
#define G(x, y, z)
unsigned __int64 uint64_t
Definition: stdint.h:90
struct Scene * scene
Definition: DRW_render.h:979
const struct bContext * evil_C
Definition: DRW_render.h:997
DRWContextState draw_ctx
Definition: draw_manager.h:616
GPUContext * gpu_context
Definition: draw_manager.h:645
void * gl_context
Definition: draw_manager.h:644
GPUContext * gpu_context
uint64_t libs_deps[MAX_LIB]
const char * libs[MAX_LIB]
char libs_name[MAX_LIB][MAX_LIB_NAME]
char name[66]
Definition: DNA_ID.h:378
void * data
Definition: DNA_listBase.h:26
ListBase gpumaterial
ListBase gpumaterial
Definition: wm_jobs.c:57
void PIL_sleep_ms(int ms)
Definition: time.c:84
void WM_jobs_start(wmWindowManager *wm, wmJob *wm_job)
Definition: wm_jobs.c:437
void * WM_jobs_customdata_from_type(wmWindowManager *wm, const void *owner, int job_type)
Definition: wm_jobs.c:293
void WM_jobs_delay_start(wmJob *wm_job, double delay_time)
Definition: wm_jobs.c:346
void WM_jobs_callbacks(wmJob *wm_job, wm_jobs_start_callback startjob, void(*initjob)(void *), void(*update)(void *), void(*endjob)(void *))
Definition: wm_jobs.c:351
void * WM_jobs_customdata_get(wmJob *wm_job)
Definition: wm_jobs.c:315
void WM_jobs_customdata_set(wmJob *wm_job, void *customdata, void(*free)(void *))
Definition: wm_jobs.c:323
void WM_jobs_timer(wmJob *wm_job, double timestep, unsigned int note, unsigned int endnote)
Definition: wm_jobs.c:339
wmJob * WM_jobs_get(wmWindowManager *wm, wmWindow *win, const void *owner, const char *name, int flag, int job_type)
Definition: wm_jobs.c:184
void * WM_opengl_context_create(void)
Definition: wm_window.c:2353
void wm_window_reset_drawable(void)
Definition: wm_window.c:1049
void WM_opengl_context_activate(void *context)
Definition: wm_window.c:2380
void WM_opengl_context_release(void *context)
Definition: wm_window.c:2386
void WM_opengl_context_dispose(void *context)
Definition: wm_window.c:2374