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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/draw/intern')
-rw-r--r--source/blender/draw/intern/DRW_render.h43
-rw-r--r--source/blender/draw/intern/draw_manager.c257
-rw-r--r--source/blender/draw/intern/draw_manager.h2
-rw-r--r--source/blender/draw/intern/draw_manager_shader.c20
4 files changed, 257 insertions, 65 deletions
diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h
index f732082018d..4d1b8269494 100644
--- a/source/blender/draw/intern/DRW_render.h
+++ b/source/blender/draw/intern/DRW_render.h
@@ -44,6 +44,7 @@
#include "DNA_lamp_types.h"
#include "DNA_material_types.h"
#include "DNA_scene_types.h"
+#include "DNA_world_types.h"
#include "GPU_framebuffer.h"
#include "GPU_texture.h"
@@ -239,14 +240,14 @@ struct GPUShader *DRW_shader_create_2D(const char *frag, const char *defines);
struct GPUShader *DRW_shader_create_3D(const char *frag, const char *defines);
struct GPUShader *DRW_shader_create_fullscreen(const char *frag, const char *defines);
struct GPUShader *DRW_shader_create_3D_depth_only(void);
-struct GPUMaterial *DRW_shader_find_from_world(struct World *wo, const void *engine_type, int options);
-struct GPUMaterial *DRW_shader_find_from_material(struct Material *ma, const void *engine_type, int options);
+struct GPUMaterial *DRW_shader_find_from_world(struct World *wo, const void *engine_type, int options, bool no_deferred);
+struct GPUMaterial *DRW_shader_find_from_material(struct Material *ma, const void *engine_type, int options, bool no_deferred);
struct GPUMaterial *DRW_shader_create_from_world(
struct Scene *scene, struct World *wo, const void *engine_type, int options,
- const char *vert, const char *geom, const char *frag_lib, const char *defines);
+ const char *vert, const char *geom, const char *frag_lib, const char *defines, bool no_deferred);
struct GPUMaterial *DRW_shader_create_from_material(
struct Scene *scene, struct Material *ma, const void *engine_type, int options,
- const char *vert, const char *geom, const char *frag_lib, const char *defines);
+ const char *vert, const char *geom, const char *frag_lib, const char *defines, bool no_deferred);
void DRW_shader_free(struct GPUShader *shader);
#define DRW_SHADER_FREE_SAFE(shader) do { \
if (shader != NULL) { \
@@ -409,6 +410,7 @@ void DRW_pass_sort_shgroup_z(DRWPass *pass);
/* Viewport */
typedef enum {
+ /* keep in sync with the union struct DRWMatrixState. */
DRW_MAT_PERS = 0,
DRW_MAT_PERSINV,
DRW_MAT_VIEW,
@@ -420,7 +422,18 @@ typedef enum {
} DRWViewportMatrixType;
typedef struct DRWMatrixState {
- float mat[DRW_MAT_COUNT][4][4];
+ union {
+ float mat[DRW_MAT_COUNT][4][4];
+ struct {
+ /* keep in sync with the enum DRWViewportMatrixType. */
+ float persmat[4][4];
+ float persinv[4][4];
+ float viewmat[4][4];
+ float viewinv[4][4];
+ float winmat[4][4];
+ float wininv[4][4];
+ };
+ };
} DRWMatrixState;
void DRW_viewport_init(const bContext *C);
@@ -453,6 +466,12 @@ void DRW_render_object_iter(
void (*callback)(void *vedata, struct Object *ob, struct RenderEngine *engine, struct Depsgraph *depsgraph));
void DRW_render_instance_buffer_finish(void);
+void DRW_custom_pipeline(
+ DrawEngineType *draw_engine_type,
+ struct Depsgraph *depsgraph,
+ void (*callback)(void *vedata, void *user_data),
+ void *user_data);
+
/* ViewLayers */
void *DRW_view_layer_engine_data_get(DrawEngineType *engine_type);
void **DRW_view_layer_engine_data_ensure_ex(
@@ -460,16 +479,14 @@ void **DRW_view_layer_engine_data_ensure_ex(
void **DRW_view_layer_engine_data_ensure(
DrawEngineType *engine_type, void (*callback)(void *storage));
-/* Objects */
-ObjectEngineData *DRW_object_engine_data_get(Object *ob, DrawEngineType *engine_type);
-ObjectEngineData *DRW_object_engine_data_ensure(
- Object *ob,
+/* DrawData */
+DrawData *DRW_drawdata_get(ID *ib, DrawEngineType *engine_type);
+DrawData *DRW_drawdata_ensure(
+ ID *id,
DrawEngineType *engine_type,
size_t size,
- ObjectEngineDataInitCb init_cb,
- ObjectEngineDataFreeCb free_cb);
-struct LampEngineData *DRW_lamp_engine_data_ensure(Object *ob, struct RenderEngineType *engine_type);
-void DRW_lamp_engine_data_free(struct LampEngineData *led);
+ DrawDataInitCb init_cb,
+ DrawDataFreeCb free_cb);
/* Settings */
bool DRW_object_is_renderable(struct Object *ob);
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c
index a1e44e479d4..30f7742fd35 100644
--- a/source/blender/draw/intern/draw_manager.c
+++ b/source/blender/draw/intern/draw_manager.c
@@ -44,6 +44,7 @@
#include "DNA_camera_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
+#include "DNA_world_types.h"
#include "ED_space_api.h"
#include "ED_screen.h"
@@ -696,34 +697,96 @@ void **DRW_view_layer_engine_data_ensure(DrawEngineType *engine_type, void (*cal
/* -------------------------------------------------------------------- */
-/** \name Objects (DRW_object)
+/** \name Draw Data (DRW_drawdata)
* \{ */
-ObjectEngineData *DRW_object_engine_data_get(Object *ob, DrawEngineType *engine_type)
+/* Used for DRW_drawdata_from_id()
+ * All ID-datablocks which have their own 'local' DrawData
+ * should have the same arrangement in their structs.
+ */
+typedef struct IdDdtTemplate {
+ ID id;
+ struct AnimData *adt;
+ DrawDataList drawdata;
+} IdDdtTemplate;
+
+/* Check if ID can have AnimData */
+static bool id_type_can_have_drawdata(const short id_type)
+{
+ /* Only some ID-blocks have this info for now */
+ /* TODO: finish adding this for the other blocktypes */
+ switch (id_type) {
+ /* has DrawData */
+ case ID_OB:
+ case ID_WO:
+ return true;
+
+ /* no DrawData */
+ default:
+ return false;
+ }
+}
+
+static bool id_can_have_drawdata(const ID *id)
+{
+ /* sanity check */
+ if (id == NULL)
+ return false;
+
+ return id_type_can_have_drawdata(GS(id->name));
+}
+
+/* Get DrawData from the given ID-block. In order for this to work, we assume that
+ * the DrawData pointer is stored in the struct in the same fashion as in IdDdtTemplate.
+ */
+DrawDataList *DRW_drawdatalist_from_id(ID *id)
{
- for (ObjectEngineData *oed = ob->drawdata.first; oed; oed = oed->next) {
- if (oed->engine_type == engine_type) {
- return oed;
+ /* only some ID-blocks have this info for now, so we cast the
+ * types that do to be of type IdDdtTemplate, and extract the
+ * DrawData that way
+ */
+ if (id_can_have_drawdata(id)) {
+ IdDdtTemplate *idt = (IdDdtTemplate *)id;
+ return &idt->drawdata;
+ }
+ else
+ return NULL;
+}
+
+DrawData *DRW_drawdata_get(ID *id, DrawEngineType *engine_type)
+{
+ DrawDataList *drawdata = DRW_drawdatalist_from_id(id);
+
+ if (drawdata == NULL)
+ return NULL;
+
+ LISTBASE_FOREACH(DrawData *, dd, drawdata) {
+ if (dd->engine_type == engine_type) {
+ return dd;
}
}
return NULL;
}
-ObjectEngineData *DRW_object_engine_data_ensure(
- Object *ob,
+DrawData *DRW_drawdata_ensure(
+ ID *id,
DrawEngineType *engine_type,
size_t size,
- ObjectEngineDataInitCb init_cb,
- ObjectEngineDataFreeCb free_cb)
+ DrawDataInitCb init_cb,
+ DrawDataFreeCb free_cb)
{
- BLI_assert(size >= sizeof(ObjectEngineData));
+ BLI_assert(size >= sizeof(DrawData));
+ BLI_assert(id_can_have_drawdata(id));
/* Try to re-use existing data. */
- ObjectEngineData *oed = DRW_object_engine_data_get(ob, engine_type);
- if (oed != NULL) {
- return oed;
+ DrawData *dd = DRW_drawdata_get(id, engine_type);
+ if (dd != NULL) {
+ return dd;
}
+
+ DrawDataList *drawdata = DRW_drawdatalist_from_id(id);
+
/* Allocate new data. */
- if ((ob->base_flag & BASE_FROMDUPLI) != 0) {
+ if ((GS(id->name) == ID_OB) && (((Object *)id)->base_flag & BASE_FROMDUPLI) != 0) {
/* NOTE: data is not persistent in this case. It is reset each redraw. */
BLI_assert(free_cb == NULL); /* No callback allowed. */
/* Round to sizeof(float) for DRW_instance_data_request(). */
@@ -734,21 +797,37 @@ ObjectEngineData *DRW_object_engine_data_ensure(
if (DST.object_instance_data[fsize] == NULL) {
DST.object_instance_data[fsize] = DRW_instance_data_request(DST.idatalist, fsize);
}
- oed = (ObjectEngineData *)DRW_instance_data_next(DST.object_instance_data[fsize]);
- memset(oed, 0, size);
+ dd = (DrawData *)DRW_instance_data_next(DST.object_instance_data[fsize]);
+ memset(dd, 0, size);
}
else {
- oed = MEM_callocN(size, "ObjectEngineData");
+ dd = MEM_callocN(size, "DrawData");
}
- oed->engine_type = engine_type;
- oed->free = free_cb;
+ dd->engine_type = engine_type;
+ dd->free = free_cb;
/* Perform user-side initialization, if needed. */
if (init_cb != NULL) {
- init_cb(oed);
+ init_cb(dd);
}
/* Register in the list. */
- BLI_addtail(&ob->drawdata, oed);
- return oed;
+ BLI_addtail((ListBase *)drawdata, dd);
+ return dd;
+}
+
+void DRW_drawdata_free(ID *id)
+{
+ DrawDataList *drawdata = DRW_drawdatalist_from_id(id);
+
+ if (drawdata == NULL)
+ return;
+
+ LISTBASE_FOREACH(DrawData *, dd, drawdata) {
+ if (dd->free != NULL) {
+ dd->free(dd);
+ }
+ }
+
+ BLI_freelistN((ListBase *)drawdata);
}
/** \} */
@@ -794,6 +873,22 @@ static void drw_engines_cache_init(void)
}
}
+static void drw_engines_world_update(Scene *scene)
+{
+ if (scene->world == NULL) {
+ return;
+ }
+
+ for (LinkData *link = DST.enabled_engines.first; link; link = link->next) {
+ DrawEngineType *engine = link->data;
+ ViewportEngineData *data = drw_viewport_engine_data_ensure(engine);
+
+ if (engine->id_update) {
+ engine->id_update(data, &scene->world->id);
+ }
+ }
+}
+
static void drw_engines_cache_populate(Object *ob)
{
DST.ob_state = NULL;
@@ -1161,7 +1256,7 @@ void DRW_notify_view_update(const DRWUpdateContext *update_ctx)
/* XXX Really nasty locking. But else this could
* be executed by the material previews thread
* while rendering a viewport. */
- BLI_mutex_lock(&DST.gl_context_mutex);
+ BLI_ticket_mutex_lock(DST.gl_context_mutex);
/* Reset before using it. */
drw_state_prepare_clean_for_draw(&DST);
@@ -1189,7 +1284,7 @@ void DRW_notify_view_update(const DRWUpdateContext *update_ctx)
drw_engines_disable();
- BLI_mutex_unlock(&DST.gl_context_mutex);
+ BLI_ticket_mutex_unlock(DST.gl_context_mutex);
}
}
@@ -1273,6 +1368,7 @@ void DRW_draw_render_loop_ex(
{
PROFILE_START(stime);
drw_engines_cache_init();
+ drw_engines_world_update(scene);
const int object_type_exclude_viewport = v3d->object_type_exclude_viewport;
DEG_OBJECT_ITER_FOR_RENDER_ENGINE_BEGIN(depsgraph, ob)
@@ -1458,14 +1554,10 @@ void DRW_render_to_image(RenderEngine *engine, struct Depsgraph *depsgraph)
/* Changing Context */
if (re_gl_context != NULL) {
- /* TODO get rid of the blocking. Only here because of the static global DST. */
- BLI_mutex_lock(&DST.gl_context_mutex);
- WM_opengl_context_activate(re_gl_context);
+ DRW_opengl_render_context_enable(re_gl_context);
+ /* We need to query gwn context after a gl context has been bound. */
re_gwn_context = RE_gwn_context_get(render);
- if (GWN_context_active_get() == NULL) {
- GWN_context_active_set(re_gwn_context);
- }
- DRW_shape_cache_reset(); /* XXX fix that too. */
+ DRW_gawain_render_context_enable(re_gwn_context);
}
else {
DRW_opengl_context_enable();
@@ -1544,12 +1636,8 @@ void DRW_render_to_image(RenderEngine *engine, struct Depsgraph *depsgraph)
/* Changing Context */
if (re_gl_context != NULL) {
- DRW_shape_cache_reset(); /* XXX fix that too. */
- glFlush();
- GWN_context_active_set(NULL);
- WM_opengl_context_release(re_gl_context);
- /* TODO get rid of the blocking. */
- BLI_mutex_unlock(&DST.gl_context_mutex);
+ DRW_gawain_render_context_disable(re_gwn_context);
+ DRW_opengl_render_context_disable(re_gl_context);
}
else {
DRW_opengl_context_disable();
@@ -1575,6 +1663,56 @@ void DRW_render_object_iter(
DEG_OBJECT_ITER_FOR_RENDER_ENGINE_END
}
+/* Assume a valid gl context is bound (and that the gl_context_mutex has been aquired).
+ * This function only setup DST and execute the given function.
+ * Warning: similar to DRW_render_to_image you cannot use default lists (dfbl & dtxl). */
+void DRW_custom_pipeline(
+ DrawEngineType *draw_engine_type,
+ struct Depsgraph *depsgraph,
+ void (*callback)(void *vedata, void *user_data),
+ void *user_data)
+{
+ Scene *scene = DEG_get_evaluated_scene(depsgraph);
+ ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph);
+
+ /* Reset before using it. */
+ drw_state_prepare_clean_for_draw(&DST);
+ DST.options.is_image_render = true;
+ DST.options.is_scene_render = true;
+ DST.options.draw_background = false;
+
+ DST.draw_ctx = (DRWContextState){
+ .scene = scene,
+ .view_layer = view_layer,
+ .engine_type = NULL,
+ .depsgraph = depsgraph,
+ .object_mode = OB_MODE_OBJECT,
+ };
+ drw_context_state_init();
+
+ DST.viewport = GPU_viewport_create();
+ const int size[2] = {1, 1};
+ GPU_viewport_size_set(DST.viewport, size);
+
+ drw_viewport_var_init();
+
+ DRW_hair_init();
+
+ ViewportEngineData *data = drw_viewport_engine_data_ensure(draw_engine_type);
+
+ /* Execute the callback */
+ callback(data, user_data);
+ DST.buffer_finish_called = false;
+
+ GPU_viewport_free(DST.viewport);
+ GPU_framebuffer_restore();
+
+#ifdef DEBUG
+ /* Avoid accidental reuse. */
+ drw_state_ensure_not_reused(&DST);
+#endif
+}
+
static struct DRWSelectBuffer {
struct GPUFrameBuffer *framebuffer;
struct GPUTexture *texture_depth;
@@ -1697,6 +1835,7 @@ void DRW_draw_select_loop(
{
drw_engines_cache_init();
+ drw_engines_world_update(scene);
if (use_obedit) {
#if 0
@@ -1891,6 +2030,7 @@ void DRW_draw_depth_loop(
{
drw_engines_cache_init();
+ drw_engines_world_update(scene);
const int object_type_exclude_viewport = v3d->object_type_exclude_viewport;
DEG_OBJECT_ITER_FOR_RENDER_ENGINE_BEGIN(depsgraph, ob)
@@ -2182,7 +2322,7 @@ void DRW_opengl_context_create(void)
{
BLI_assert(DST.gl_context == NULL); /* Ensure it's called once */
- BLI_mutex_init(&DST.gl_context_mutex);
+ DST.gl_context_mutex = BLI_ticket_mutex_alloc();
if (!G.background) {
immDeactivate();
}
@@ -2207,7 +2347,7 @@ void DRW_opengl_context_destroy(void)
GWN_context_active_set(DST.gwn_context);
GWN_context_discard(DST.gwn_context);
WM_opengl_context_dispose(DST.gl_context);
- BLI_mutex_end(&DST.gl_context_mutex);
+ BLI_ticket_mutex_free(DST.gl_context_mutex);
}
}
@@ -2217,7 +2357,7 @@ void DRW_opengl_context_enable(void)
/* IMPORTANT: We dont support immediate mode in render mode!
* This shall remain in effect until immediate mode supports
* multiple threads. */
- BLI_mutex_lock(&DST.gl_context_mutex);
+ BLI_ticket_mutex_lock(DST.gl_context_mutex);
if (BLI_thread_is_main()) {
if (!G.background) {
immDeactivate();
@@ -2251,8 +2391,43 @@ void DRW_opengl_context_disable(void)
GWN_context_active_set(NULL);
}
- BLI_mutex_unlock(&DST.gl_context_mutex);
+ BLI_ticket_mutex_unlock(DST.gl_context_mutex);
}
}
+void DRW_opengl_render_context_enable(void *re_gl_context)
+{
+ /* If thread is main you should use DRW_opengl_context_enable(). */
+ BLI_assert(!BLI_thread_is_main());
+
+ /* TODO get rid of the blocking. Only here because of the static global DST. */
+ BLI_ticket_mutex_lock(DST.gl_context_mutex);
+ WM_opengl_context_activate(re_gl_context);
+}
+
+void DRW_opengl_render_context_disable(void *re_gl_context)
+{
+ glFlush();
+ WM_opengl_context_release(re_gl_context);
+ /* TODO get rid of the blocking. */
+ BLI_ticket_mutex_unlock(DST.gl_context_mutex);
+}
+
+/* Needs to be called AFTER DRW_opengl_render_context_enable() */
+void DRW_gawain_render_context_enable(void *re_gwn_context)
+{
+ /* If thread is main you should use DRW_opengl_context_enable(). */
+ BLI_assert(!BLI_thread_is_main());
+
+ GWN_context_active_set(re_gwn_context);
+ DRW_shape_cache_reset(); /* XXX fix that too. */
+}
+
+/* Needs to be called BEFORE DRW_opengl_render_context_disable() */
+void DRW_gawain_render_context_disable(void *UNUSED(re_gwn_context))
+{
+ DRW_shape_cache_reset(); /* XXX fix that too. */
+ GWN_context_active_set(NULL);
+}
+
/** \} */
diff --git a/source/blender/draw/intern/draw_manager.h b/source/blender/draw/intern/draw_manager.h
index 91a30fa45ae..6eae3459c2b 100644
--- a/source/blender/draw/intern/draw_manager.h
+++ b/source/blender/draw/intern/draw_manager.h
@@ -373,7 +373,7 @@ typedef struct DRWManager {
* the top portion of the struct so DO NOT MOVE IT! */
void *gl_context; /* Unique ghost context used by the draw manager. */
Gwn_Context *gwn_context;
- ThreadMutex gl_context_mutex; /* Mutex to lock the drw manager and avoid concurent context usage. */
+ TicketMutex *gl_context_mutex; /* Mutex to lock the drw manager and avoid concurent context usage. */
/** GPU Resource State: Memory storage between drawing. */
struct {
diff --git a/source/blender/draw/intern/draw_manager_shader.c b/source/blender/draw/intern/draw_manager_shader.c
index 435c6c77e59..b0aec4a7600 100644
--- a/source/blender/draw/intern/draw_manager_shader.c
+++ b/source/blender/draw/intern/draw_manager_shader.c
@@ -154,10 +154,10 @@ static void drw_deferred_shader_compilation_free(void *custom_data)
MEM_freeN(comp);
}
-static void drw_deferred_shader_add(GPUMaterial *mat)
+static void drw_deferred_shader_add(GPUMaterial *mat, bool deferred)
{
/* Do not deferre the compilation if we are rendering for image. */
- if (DRW_state_is_image_render() || !USE_DEFERRED_COMPILATION) {
+ if (DRW_state_is_image_render() || !USE_DEFERRED_COMPILATION || !deferred) {
/* Double checking that this GPUMaterial is not going to be
* compiled by another thread. */
DRW_deferred_shader_remove(mat);
@@ -308,10 +308,10 @@ GPUShader *DRW_shader_create_3D_depth_only(void)
return GPU_shader_get_builtin_shader(GPU_SHADER_3D_DEPTH_ONLY);
}
-GPUMaterial *DRW_shader_find_from_world(World *wo, const void *engine_type, int options)
+GPUMaterial *DRW_shader_find_from_world(World *wo, const void *engine_type, int options, bool deferred)
{
GPUMaterial *mat = GPU_material_from_nodetree_find(&wo->gpumaterial, engine_type, options);
- if (DRW_state_is_image_render()) {
+ if (DRW_state_is_image_render() || !deferred) {
if (mat != NULL && GPU_material_status(mat) == GPU_MAT_QUEUED) {
/* XXX Hack : we return NULL so that the engine will call DRW_shader_create_from_XXX
* with the shader code and we will resume the compilation from there. */
@@ -321,10 +321,10 @@ GPUMaterial *DRW_shader_find_from_world(World *wo, const void *engine_type, int
return mat;
}
-GPUMaterial *DRW_shader_find_from_material(Material *ma, const void *engine_type, int options)
+GPUMaterial *DRW_shader_find_from_material(Material *ma, const void *engine_type, int options, bool deferred)
{
GPUMaterial *mat = GPU_material_from_nodetree_find(&ma->gpumaterial, engine_type, options);
- if (DRW_state_is_image_render()) {
+ if (DRW_state_is_image_render() || !deferred) {
if (mat != NULL && GPU_material_status(mat) == GPU_MAT_QUEUED) {
/* XXX Hack : we return NULL so that the engine will call DRW_shader_create_from_XXX
* with the shader code and we will resume the compilation from there. */
@@ -336,7 +336,7 @@ GPUMaterial *DRW_shader_find_from_material(Material *ma, const void *engine_type
GPUMaterial *DRW_shader_create_from_world(
struct Scene *scene, World *wo, const void *engine_type, int options,
- const char *vert, const char *geom, const char *frag_lib, const char *defines)
+ const char *vert, const char *geom, const char *frag_lib, const char *defines, bool deferred)
{
GPUMaterial *mat = NULL;
if (DRW_state_is_image_render()) {
@@ -350,7 +350,7 @@ GPUMaterial *DRW_shader_create_from_world(
}
if (GPU_material_status(mat) == GPU_MAT_QUEUED) {
- drw_deferred_shader_add(mat);
+ drw_deferred_shader_add(mat, deferred);
}
return mat;
@@ -358,7 +358,7 @@ GPUMaterial *DRW_shader_create_from_world(
GPUMaterial *DRW_shader_create_from_material(
struct Scene *scene, Material *ma, const void *engine_type, int options,
- const char *vert, const char *geom, const char *frag_lib, const char *defines)
+ const char *vert, const char *geom, const char *frag_lib, const char *defines, bool deferred)
{
GPUMaterial *mat = NULL;
if (DRW_state_is_image_render()) {
@@ -372,7 +372,7 @@ GPUMaterial *DRW_shader_create_from_material(
}
if (GPU_material_status(mat) == GPU_MAT_QUEUED) {
- drw_deferred_shader_add(mat);
+ drw_deferred_shader_add(mat, deferred);
}
return mat;