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/draw_manager.c')
-rw-r--r--source/blender/draw/intern/draw_manager.c1121
1 files changed, 853 insertions, 268 deletions
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c
index 970bd2f6dee..d2d98f15fa9 100644
--- a/source/blender/draw/intern/draw_manager.c
+++ b/source/blender/draw/intern/draw_manager.c
@@ -19,12 +19,13 @@
*
*/
-/** \file blender/draw/draw_manager.c
+/** \file blender/draw/intern/draw_manager.c
* \ingroup draw
*/
#include <stdio.h>
+#include "BLI_dynstr.h"
#include "BLI_listbase.h"
#include "BLI_rect.h"
#include "BLI_string.h"
@@ -34,35 +35,43 @@
#include "BKE_global.h"
#include "BLT_translation.h"
+#include "BLF_api.h"
#include "DRW_engine.h"
#include "DRW_render.h"
#include "DNA_view3d_types.h"
+#include "DNA_screen_types.h"
+
+#include "ED_space_api.h"
+#include "ED_screen.h"
-#include "GPU_basic_shader.h"
#include "GPU_batch.h"
#include "GPU_draw.h"
#include "GPU_extensions.h"
#include "GPU_framebuffer.h"
-#include "GPU_immediate.h"
-#include "GPU_matrix.h"
#include "GPU_shader.h"
#include "GPU_texture.h"
#include "GPU_uniformbuffer.h"
#include "GPU_viewport.h"
+#include "GPU_matrix.h"
+
+#include "PIL_time.h"
#include "RE_engine.h"
#include "UI_resources.h"
+#include "draw_mode_engines.h"
#include "clay.h"
+#include "eevee.h"
#define MAX_ATTRIB_NAME 32
+#define MAX_PASS_NAME 32
extern char datatoc_gpu_shader_2D_vert_glsl[];
extern char datatoc_gpu_shader_3D_vert_glsl[];
-extern char datatoc_gpu_shader_basic_vert_glsl[];
+extern char datatoc_gpu_shader_fullscreen_vert_glsl[];
/* Structures */
typedef enum {
@@ -81,7 +90,7 @@ typedef enum {
DRW_ATTRIB_FLOAT,
} DRWAttribType;
-typedef struct DRWUniform {
+struct DRWUniform {
struct DRWUniform *next, *prev;
DRWUniformType type;
int location;
@@ -89,7 +98,7 @@ typedef struct DRWUniform {
int arraysize;
int bindloc;
const void *value;
-} DRWUniform;
+};
typedef struct DRWAttrib {
struct DRWAttrib *next, *prev;
@@ -108,11 +117,14 @@ struct DRWInterface {
int attribs_size[16];
int attribs_loc[16];
/* matrices locations */
+ int model;
int modelview;
int projection;
+ int view;
int modelviewprojection;
int viewprojection;
int normal;
+ int worldnormal;
int eye;
/* Dynamic batch */
GLuint instance_vbo;
@@ -123,7 +135,13 @@ struct DRWInterface {
struct DRWPass {
ListBase shgroups; /* DRWShadingGroup */
DRWState state;
- float state_param; /* Line / Point width */
+ char name[MAX_PASS_NAME];
+ /* use two query to not stall the cpu waiting for queries to complete */
+ unsigned int timer_queries[2];
+ /* alternate between front and back query */
+ unsigned int front_idx;
+ unsigned int back_idx;
+ bool wasdrawn; /* if it was drawn during this frame */
};
typedef struct DRWCall {
@@ -143,7 +161,7 @@ struct DRWShadingGroup {
struct GPUShader *shader; /* Shader to bind */
struct DRWInterface *interface; /* Uniforms pointers */
ListBase calls; /* DRWCall or DRWDynamicCall depending of type*/
- int state; /* State changes for this batch only */
+ DRWState state; /* State changes for this batch only */
int type;
Batch *instance_geom; /* Geometry to instance */
@@ -158,22 +176,33 @@ enum {
DRW_SHG_INSTANCE,
};
+/* only 16 bits long */
+enum {
+ STENCIL_SELECT = (1 << 0),
+ STENCIL_ACTIVE = (1 << 1),
+};
+
/* Render State */
-static struct DRWGlobalState{
+static struct DRWGlobalState {
+ /* Rendering state */
GPUShader *shader;
- struct GPUFrameBuffer *default_framebuffer;
- FramebufferList *current_fbl;
- TextureList *current_txl;
- PassList *current_psl;
ListBase bound_texs;
int tex_bind_id;
+
+ /* Per viewport */
+ GPUViewport *viewport;
+ struct GPUFrameBuffer *default_framebuffer;
float size[2];
float screenvecs[2][3];
float pixsize;
- /* Current rendering context set by DRW_viewport_init */
+
+ /* Current rendering context */
const struct bContext *context;
+ ListBase enabled_engines; /* RenderEngineType */
} DST = {NULL};
+ListBase DRW_engines = {NULL, NULL};
+
/* ***************************************** TEXTURES ******************************************/
static void drw_texture_get_format(DRWTextureFormat format, GPUTextureFormat *data_type, int *channels)
{
@@ -183,13 +212,13 @@ static void drw_texture_get_format(DRWTextureFormat format, GPUTextureFormat *da
case DRW_TEX_RG_16: *data_type = GPU_RG16F; break;
case DRW_TEX_RG_32: *data_type = GPU_RG32F; break;
case DRW_TEX_R_8: *data_type = GPU_R8; break;
+ case DRW_TEX_R_16: *data_type = GPU_R16F; break;
#if 0
case DRW_TEX_RGBA_32: *data_type = GPU_RGBA32F; break;
case DRW_TEX_RGB_8: *data_type = GPU_RGB8; break;
case DRW_TEX_RGB_16: *data_type = GPU_RGB16F; break;
case DRW_TEX_RGB_32: *data_type = GPU_RGB32F; break;
case DRW_TEX_RG_8: *data_type = GPU_RG8; break;
- case DRW_TEX_R_16: *data_type = GPU_R16F; break;
case DRW_TEX_R_32: *data_type = GPU_R32F; break;
#endif
case DRW_TEX_DEPTH_16: *data_type = GPU_DEPTH_COMPONENT16; break;
@@ -299,6 +328,44 @@ GPUShader *DRW_shader_create(const char *vert, const char *geom, const char *fra
return GPU_shader_create(vert, frag, geom, NULL, defines, 0, 0, 0);
}
+GPUShader *DRW_shader_create_with_lib(const char *vert, const char *geom, const char *frag, const char *lib, const char *defines)
+{
+ GPUShader *sh;
+ char *vert_with_lib = NULL;
+ char *frag_with_lib = NULL;
+ char *geom_with_lib = NULL;
+
+ DynStr *ds_vert = BLI_dynstr_new();
+ BLI_dynstr_append(ds_vert, lib);
+ BLI_dynstr_append(ds_vert, vert);
+ vert_with_lib = BLI_dynstr_get_cstring(ds_vert);
+ BLI_dynstr_free(ds_vert);
+
+ DynStr *ds_frag = BLI_dynstr_new();
+ BLI_dynstr_append(ds_frag, lib);
+ BLI_dynstr_append(ds_frag, frag);
+ frag_with_lib = BLI_dynstr_get_cstring(ds_frag);
+ BLI_dynstr_free(ds_frag);
+
+ if (geom) {
+ DynStr *ds_geom = BLI_dynstr_new();
+ BLI_dynstr_append(ds_geom, lib);
+ BLI_dynstr_append(ds_geom, geom);
+ geom_with_lib = BLI_dynstr_get_cstring(ds_geom);
+ BLI_dynstr_free(ds_geom);
+ }
+
+ sh = GPU_shader_create(vert_with_lib, frag_with_lib, geom_with_lib, NULL, defines, 0, 0, 0);
+
+ MEM_freeN(vert_with_lib);
+ MEM_freeN(frag_with_lib);
+ if (geom) {
+ MEM_freeN(geom_with_lib);
+ }
+
+ return sh;
+}
+
GPUShader *DRW_shader_create_2D(const char *frag, const char *defines)
{
return GPU_shader_create(datatoc_gpu_shader_2D_vert_glsl, frag, NULL, NULL, defines, 0, 0, 0);
@@ -309,6 +376,11 @@ GPUShader *DRW_shader_create_3D(const char *frag, const char *defines)
return GPU_shader_create(datatoc_gpu_shader_3D_vert_glsl, frag, NULL, NULL, defines, 0, 0, 0);
}
+GPUShader *DRW_shader_create_fullscreen(const char *frag, const char *defines)
+{
+ return GPU_shader_create(datatoc_gpu_shader_fullscreen_vert_glsl, frag, NULL, NULL, defines, 0, 0, 0);
+}
+
GPUShader *DRW_shader_create_3D_depth_only(void)
{
return GPU_shader_get_builtin_shader(GPU_SHADER_3D_DEPTH_ONLY);
@@ -325,11 +397,14 @@ static DRWInterface *DRW_interface_create(GPUShader *shader)
{
DRWInterface *interface = MEM_mallocN(sizeof(DRWInterface), "DRWInterface");
+ interface->model = GPU_shader_get_uniform(shader, "ModelMatrix");
interface->modelview = GPU_shader_get_uniform(shader, "ModelViewMatrix");
interface->projection = GPU_shader_get_uniform(shader, "ProjectionMatrix");
+ interface->view = GPU_shader_get_uniform(shader, "ViewMatrix");
interface->viewprojection = GPU_shader_get_uniform(shader, "ViewProjectionMatrix");
interface->modelviewprojection = GPU_shader_get_uniform(shader, "ModelViewProjectionMatrix");
interface->normal = GPU_shader_get_uniform(shader, "NormalMatrix");
+ interface->worldnormal = GPU_shader_get_uniform(shader, "WorldNormalMatrix");
interface->eye = GPU_shader_get_uniform(shader, "eye");
interface->instance_count = 0;
interface->attribs_count = 0;
@@ -457,7 +532,11 @@ void DRW_shgroup_free(struct DRWShadingGroup *shgroup)
BLI_freelistN(&shgroup->calls);
BLI_freelistN(&shgroup->interface->uniforms);
BLI_freelistN(&shgroup->interface->attribs);
- /* TODO free instance vbo */
+
+ if (shgroup->interface->instance_vbo) {
+ glDeleteBuffers(1, &shgroup->interface->instance_vbo);
+ }
+
MEM_freeN(shgroup->interface);
if (shgroup->batch_geom) {
@@ -467,14 +546,14 @@ void DRW_shgroup_free(struct DRWShadingGroup *shgroup)
void DRW_shgroup_call_add(DRWShadingGroup *shgroup, Batch *geom, float (*obmat)[4])
{
- if (geom) {
- DRWCall *call = MEM_callocN(sizeof(DRWCall), "DRWCall");
+ BLI_assert(geom != NULL);
- call->obmat = obmat;
- call->geometry = geom;
+ DRWCall *call = MEM_callocN(sizeof(DRWCall), "DRWCall");
- BLI_addtail(&shgroup->calls, call);
- }
+ call->obmat = obmat;
+ call->geometry = geom;
+
+ BLI_addtail(&shgroup->calls, call);
}
void DRW_shgroup_dynamic_call_add(DRWShadingGroup *shgroup, ...)
@@ -519,10 +598,9 @@ void DRW_shgroup_uniform_block(DRWShadingGroup *shgroup, const char *name, const
DRW_interface_uniform(shgroup, name, DRW_UNIFORM_BLOCK, ubo, 0, 0, loc);
}
-void DRW_shgroup_uniform_buffer(DRWShadingGroup *shgroup, const char *name, const int value, int loc)
+void DRW_shgroup_uniform_buffer(DRWShadingGroup *shgroup, const char *name, GPUTexture **tex, int loc)
{
- /* we abuse the lenght attrib to store the buffer index */
- DRW_interface_uniform(shgroup, name, DRW_UNIFORM_BUFFER, NULL, value, 0, loc);
+ DRW_interface_uniform(shgroup, name, DRW_UNIFORM_BUFFER, tex, 0, 0, loc);
}
void DRW_shgroup_uniform_bool(DRWShadingGroup *shgroup, const char *name, const bool *value, int arraysize)
@@ -672,9 +750,12 @@ static void shgroup_dynamic_instance(DRWShadingGroup *shgroup)
static void shgroup_dynamic_batch_from_calls(DRWShadingGroup *shgroup)
{
-#ifdef WITH_VIEWPORT_CACHE_TEST
- if (shgroup->interface->instance_vbo || shgroup->batch_geom) return;
-#endif
+ if ((shgroup->interface->instance_vbo || shgroup->batch_geom) &&
+ (G.debug_value == 667))
+ {
+ return;
+ }
+
if (shgroup->type == DRW_SHG_INSTANCE) {
shgroup_dynamic_instance(shgroup);
}
@@ -689,6 +770,7 @@ DRWPass *DRW_pass_create(const char *name, DRWState state)
{
DRWPass *pass = MEM_callocN(sizeof(DRWPass), name);
pass->state = state;
+ BLI_strncpy(pass->name, name, MAX_PASS_NAME);
BLI_listbase_clear(&pass->shgroups);
@@ -700,87 +782,136 @@ void DRW_pass_free(DRWPass *pass)
for (DRWShadingGroup *shgroup = pass->shgroups.first; shgroup; shgroup = shgroup->next) {
DRW_shgroup_free(shgroup);
}
+
+ glDeleteQueries(2, pass->timer_queries);
BLI_freelistN(&pass->shgroups);
}
/* ****************************************** DRAW ******************************************/
-void DRW_draw_background(void)
+#ifdef WITH_CLAY_ENGINE
+static void set_state(DRWState flag, const bool reset)
{
- /* Just to make sure */
- glDepthMask(GL_TRUE);
- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
-
- if (UI_GetThemeValue(TH_SHOW_BACK_GRAD)) {
- /* Gradient background Color */
- gpuMatrixBegin3D(); /* TODO: finish 2D API */
-
- glClear(GL_DEPTH_BUFFER_BIT);
-
- VertexFormat *format = immVertexFormat();
- unsigned pos = add_attrib(format, "pos", COMP_F32, 2, KEEP_FLOAT);
- unsigned color = add_attrib(format, "color", COMP_U8, 3, NORMALIZE_INT_TO_FLOAT);
- unsigned char col_hi[3], col_lo[3];
+ /* TODO Keep track of the state and only revert what is needed */
- immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
+ if (reset) {
+ /* Depth Write */
+ if (flag & DRW_STATE_WRITE_DEPTH)
+ glDepthMask(GL_TRUE);
+ else
+ glDepthMask(GL_FALSE);
+
+ /* Color Write */
+ if (flag & DRW_STATE_WRITE_COLOR)
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ else
+ glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+
+ /* Backface Culling */
+ if (flag & DRW_STATE_CULL_BACK ||
+ flag & DRW_STATE_CULL_FRONT)
+ {
+ glEnable(GL_CULL_FACE);
- UI_GetThemeColor3ubv(TH_LOW_GRAD, col_lo);
- UI_GetThemeColor3ubv(TH_HIGH_GRAD, col_hi);
+ if (flag & DRW_STATE_CULL_BACK)
+ glCullFace(GL_BACK);
+ else if (flag & DRW_STATE_CULL_FRONT)
+ glCullFace(GL_FRONT);
+ }
+ else {
+ glDisable(GL_CULL_FACE);
+ }
- immBegin(GL_QUADS, 4);
- immAttrib3ubv(color, col_lo);
- immVertex2f(pos, -1.0f, -1.0f);
- immVertex2f(pos, 1.0f, -1.0f);
+ /* Depht Test */
+ if (flag & (DRW_STATE_DEPTH_LESS | DRW_STATE_DEPTH_EQUAL | DRW_STATE_DEPTH_GREATER))
+ {
+ glEnable(GL_DEPTH_TEST);
+
+ if (flag & DRW_STATE_DEPTH_LESS)
+ glDepthFunc(GL_LEQUAL);
+ else if (flag & DRW_STATE_DEPTH_EQUAL)
+ glDepthFunc(GL_EQUAL);
+ else if (flag & DRW_STATE_DEPTH_GREATER)
+ glDepthFunc(GL_GREATER);
+ }
+ else {
+ glDisable(GL_DEPTH_TEST);
+ }
+ }
- immAttrib3ubv(color, col_hi);
- immVertex2f(pos, 1.0f, 1.0f);
- immVertex2f(pos, -1.0f, 1.0f);
- immEnd();
+ /* Wire Width */
+ if (flag & DRW_STATE_WIRE) {
+ glLineWidth(1.0f);
+ }
+ else if (flag & DRW_STATE_WIRE_LARGE) {
+ glLineWidth(UI_GetThemeValuef(TH_OUTLINE_WIDTH) * 2.0f);
+ }
- immUnbindProgram();
+ /* Points Size */
+ if (flag & DRW_STATE_POINT) {
+ GPU_enable_program_point_size();
+ glPointSize(5.0f);
+ }
+ else if (reset) {
+ GPU_disable_program_point_size();
+ }
- gpuMatrixEnd();
+ /* Blending (all buffer) */
+ if (flag & DRW_STATE_BLEND) {
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
- else {
- /* Solid background Color */
- UI_ThemeClearColorAlpha(TH_HIGH_GRAD, 1.0f);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ else if (reset) {
+ glDisable(GL_BLEND);
}
-}
-#ifdef WITH_CLAY_ENGINE
-/* Only alter the state (does not reset it like set_state() ) */
-static void shgroup_set_state(DRWShadingGroup *shgroup)
-{
- if (shgroup->state) {
- /* Blend */
- if (shgroup->state & DRW_STATE_BLEND) {
- glEnable(GL_BLEND);
- }
- /* Wire width */
- if (shgroup->state & DRW_STATE_WIRE) {
- glLineWidth(1.0f);
- }
- else if (shgroup->state & DRW_STATE_WIRE_LARGE) {
- glLineWidth(UI_GetThemeValuef(TH_OUTLINE_WIDTH) * 2.0f);
- }
+ /* Line Stipple */
+ if (flag & DRW_STATE_STIPPLE_2) {
+ setlinestyle(2);
+ }
+ else if (flag & DRW_STATE_STIPPLE_3) {
+ setlinestyle(3);
+ }
+ else if (flag & DRW_STATE_STIPPLE_4) {
+ setlinestyle(4);
+ }
+ else if (reset) {
+ setlinestyle(0);
+ }
- /* Line Stipple */
- if (shgroup->state & DRW_STATE_STIPPLE_2) {
- setlinestyle(2);
+ /* Stencil */
+ if (flag & (DRW_STATE_WRITE_STENCIL_SELECT | DRW_STATE_WRITE_STENCIL_ACTIVE |
+ DRW_STATE_TEST_STENCIL_SELECT | DRW_STATE_TEST_STENCIL_ACTIVE))
+ {
+ glEnable(GL_STENCIL_TEST);
+
+ /* Stencil Write */
+ if (flag & DRW_STATE_WRITE_STENCIL_SELECT) {
+ glStencilMask(STENCIL_SELECT);
+ glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
+ glStencilFunc(GL_ALWAYS, 0xFF, STENCIL_SELECT);
}
- else if (shgroup->state & DRW_STATE_STIPPLE_3) {
- setlinestyle(3);
+ else if (flag & DRW_STATE_WRITE_STENCIL_ACTIVE) {
+ glStencilMask(STENCIL_ACTIVE);
+ glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
+ glStencilFunc(GL_ALWAYS, 0xFF, STENCIL_ACTIVE);
}
- else if (shgroup->state & DRW_STATE_STIPPLE_4) {
- setlinestyle(4);
+ /* Stencil Test */
+ else if (flag & DRW_STATE_TEST_STENCIL_SELECT) {
+ glStencilMask(0x00); /* disable write */
+ glStencilFunc(GL_NOTEQUAL, 0xFF, STENCIL_SELECT);
}
-
- if (shgroup->state & DRW_STATE_POINT) {
- GPU_enable_program_point_size();
- glPointSize(5.0f);
+ else if (flag & DRW_STATE_TEST_STENCIL_ACTIVE) {
+ glStencilMask(0x00); /* disable write */
+ glStencilFunc(GL_NOTEQUAL, 0xFF, STENCIL_ACTIVE);
}
}
+ else if (reset) {
+ /* disable write & test */
+ glStencilMask(0x00);
+ glStencilFunc(GL_ALWAYS, 1, 0xFF);
+ glDisable(GL_STENCIL_TEST);
+ }
}
typedef struct DRWBoundTexture {
@@ -792,13 +923,14 @@ static void draw_geometry(DRWShadingGroup *shgroup, Batch *geom, const float (*o
{
RegionView3D *rv3d = CTX_wm_region_view3d(DST.context);
DRWInterface *interface = shgroup->interface;
-
- float mvp[4][4], mv[4][4], n[3][3];
+
+ float mvp[4][4], mv[4][4], n[3][3], wn[3][3];
float eye[3] = { 0.0f, 0.0f, 1.0f }; /* looking into the screen */
bool do_mvp = (interface->modelviewprojection != -1);
bool do_mv = (interface->modelview != -1);
bool do_n = (interface->normal != -1);
+ bool do_wn = (interface->worldnormal != -1);
bool do_eye = (interface->eye != -1);
if (do_mvp) {
@@ -812,6 +944,11 @@ static void draw_geometry(DRWShadingGroup *shgroup, Batch *geom, const float (*o
invert_m3(n);
transpose_m3(n);
}
+ if (do_wn) {
+ copy_m3_m4(wn, obmat);
+ invert_m3(wn);
+ transpose_m3(wn);
+ }
if (do_eye) {
/* Used by orthographic wires */
float tmp[3][3];
@@ -822,6 +959,9 @@ static void draw_geometry(DRWShadingGroup *shgroup, Batch *geom, const float (*o
/* Should be really simple */
/* step 1 : bind object dependent matrices */
+ if (interface->model != -1) {
+ GPU_shader_uniform_vector(shgroup->shader, interface->model, 16, 1, (float *)obmat);
+ }
if (interface->modelviewprojection != -1) {
GPU_shader_uniform_vector(shgroup->shader, interface->modelviewprojection, 16, 1, (float *)mvp);
}
@@ -831,12 +971,18 @@ static void draw_geometry(DRWShadingGroup *shgroup, Batch *geom, const float (*o
if (interface->projection != -1) {
GPU_shader_uniform_vector(shgroup->shader, interface->projection, 16, 1, (float *)rv3d->winmat);
}
+ if (interface->view != -1) {
+ GPU_shader_uniform_vector(shgroup->shader, interface->view, 16, 1, (float *)rv3d->viewmat);
+ }
if (interface->modelview != -1) {
GPU_shader_uniform_vector(shgroup->shader, interface->modelview, 16, 1, (float *)mv);
}
if (interface->normal != -1) {
GPU_shader_uniform_vector(shgroup->shader, interface->normal, 9, 1, (float *)n);
}
+ if (interface->worldnormal != -1) {
+ GPU_shader_uniform_vector(shgroup->shader, interface->worldnormal, 9, 1, (float *)wn);
+ }
if (interface->eye != -1) {
GPU_shader_uniform_vector(shgroup->shader, interface->eye, 3, 1, (float *)eye);
}
@@ -858,6 +1004,7 @@ static void draw_shgroup(DRWShadingGroup *shgroup)
BLI_assert(shgroup->interface);
DRWInterface *interface = shgroup->interface;
+ GPUTexture *tex;
if (DST.shader != shgroup->shader) {
if (DST.shader) GPU_shader_unbind();
@@ -869,7 +1016,9 @@ static void draw_shgroup(DRWShadingGroup *shgroup)
shgroup_dynamic_batch_from_calls(shgroup);
}
- shgroup_set_state(shgroup);
+ if (shgroup->state != 0) {
+ set_state(shgroup->state, false);
+ }
/* Binding Uniform */
/* Don't check anything, Interface should already contain the least uniform as possible */
@@ -887,25 +1036,26 @@ static void draw_shgroup(DRWShadingGroup *shgroup)
GPU_shader_uniform_vector(shgroup->shader, uni->location, uni->length, uni->arraysize, (float *)uni->value);
break;
case DRW_UNIFORM_TEXTURE:
- GPU_texture_bind((GPUTexture *)uni->value, uni->bindloc);
+ tex = (GPUTexture *)uni->value;
+ GPU_texture_bind(tex, uni->bindloc);
bound_tex = MEM_callocN(sizeof(DRWBoundTexture), "DRWBoundTexture");
- bound_tex->tex = (GPUTexture *)uni->value;
+ bound_tex->tex = tex;
BLI_addtail(&DST.bound_texs, bound_tex);
- GPU_shader_uniform_texture(shgroup->shader, uni->location, (GPUTexture *)uni->value);
+ GPU_shader_uniform_texture(shgroup->shader, uni->location, tex);
break;
case DRW_UNIFORM_BUFFER:
- /* restore index from lenght we abused */
- GPU_texture_bind(DST.current_txl->textures[uni->length], uni->bindloc);
- GPU_texture_compare_mode(DST.current_txl->textures[uni->length], false);
- GPU_texture_filter_mode(DST.current_txl->textures[uni->length], false);
-
+ tex = *((GPUTexture **)uni->value);
+ GPU_texture_bind(tex, uni->bindloc);
+ GPU_texture_compare_mode(tex, false);
+ GPU_texture_filter_mode(tex, false);
+
bound_tex = MEM_callocN(sizeof(DRWBoundTexture), "DRWBoundTexture");
- bound_tex->tex = DST.current_txl->textures[uni->length];
+ bound_tex->tex = tex;
BLI_addtail(&DST.bound_texs, bound_tex);
- GPU_shader_uniform_texture(shgroup->shader, uni->location, DST.current_txl->textures[uni->length]);
+ GPU_shader_uniform_texture(shgroup->shader, uni->location, tex);
break;
case DRW_UNIFORM_BLOCK:
GPU_uniformbuffer_bind((GPUUniformBuffer *)uni->value, uni->bindloc);
@@ -937,100 +1087,37 @@ static void draw_shgroup(DRWShadingGroup *shgroup)
}
}
-static void set_state(short flag)
+void DRW_draw_pass(DRWPass *pass)
{
- /* TODO Keep track of the state and only revert what is needed */
-
- /* Depth Write */
- if (flag & DRW_STATE_WRITE_DEPTH)
- glDepthMask(GL_TRUE);
- else
- glDepthMask(GL_FALSE);
-
- /* Color Write */
- if (flag & DRW_STATE_WRITE_COLOR)
- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
- else
- glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
-
- /* Backface Culling */
- if (flag & DRW_STATE_CULL_BACK ||
- flag & DRW_STATE_CULL_FRONT) {
-
- glEnable(GL_CULL_FACE);
-
- if (flag & DRW_STATE_CULL_BACK)
- glCullFace(GL_BACK);
- else if (flag & DRW_STATE_CULL_FRONT)
- glCullFace(GL_FRONT);
- }
- else {
- glDisable(GL_CULL_FACE);
- }
-
- /* Depht Test */
- if (flag & DRW_STATE_DEPTH_LESS ||
- flag & DRW_STATE_DEPTH_EQUAL) {
+ /* Start fresh */
+ DST.shader = NULL;
+ DST.tex_bind_id = 0;
- glEnable(GL_DEPTH_TEST);
+ set_state(pass->state, true);
+ BLI_listbase_clear(&DST.bound_texs);
- if (flag & DRW_STATE_DEPTH_LESS)
- glDepthFunc(GL_LEQUAL);
- else if (flag & DRW_STATE_DEPTH_EQUAL)
- glDepthFunc(GL_EQUAL);
- }
- else {
- glDisable(GL_DEPTH_TEST);
- }
+ pass->wasdrawn = true;
- /* Wire Width */
- if (flag & DRW_STATE_WIRE) {
- glLineWidth(1.0f);
- }
- else if (flag & DRW_STATE_WIRE_LARGE) {
- glLineWidth(UI_GetThemeValuef(TH_OUTLINE_WIDTH) * 2.0f);
- }
-
- /* Points Size */
- if (flag & DRW_STATE_POINT) {
- GPU_enable_program_point_size();
- glPointSize(5.0f);
- }
- else {
- GPU_disable_program_point_size();
- }
+ /* Init Timer queries */
+ if (pass->timer_queries[0] == 0) {
+ pass->front_idx = 0;
+ pass->back_idx = 1;
- /* Blending (all buffer) */
- if (flag & DRW_STATE_BLEND) {
- glEnable(GL_BLEND);
- }
- else {
- glDisable(GL_BLEND);
- }
+ glGenQueries(2, pass->timer_queries);
- /* Line Stipple */
- if (flag & DRW_STATE_STIPPLE_2) {
- setlinestyle(2);
- }
- else if (flag & DRW_STATE_STIPPLE_3) {
- setlinestyle(3);
- }
- else if (flag & DRW_STATE_STIPPLE_4) {
- setlinestyle(4);
+ /* dummy query, avoid gl error */
+ glBeginQuery(GL_TIME_ELAPSED, pass->timer_queries[pass->front_idx]);
+ glEndQuery(GL_TIME_ELAPSED);
}
else {
- setlinestyle(0);
+ /* swap indices */
+ unsigned int tmp = pass->back_idx;
+ pass->back_idx = pass->front_idx;
+ pass->front_idx = tmp;
}
-}
-
-void DRW_draw_pass(DRWPass *pass)
-{
- /* Start fresh */
- DST.shader = NULL;
- DST.tex_bind_id = 0;
- set_state(pass->state);
- BLI_listbase_clear(&DST.bound_texs);
+ /* issue query for the next frame */
+ glBeginQuery(GL_TIME_ELAPSED, pass->timer_queries[pass->back_idx]);
for (DRWShadingGroup *shgroup = pass->shgroups.first; shgroup; shgroup = shgroup->next) {
draw_shgroup(shgroup);
@@ -1047,6 +1134,30 @@ void DRW_draw_pass(DRWPass *pass)
GPU_shader_unbind();
DST.shader = NULL;
}
+
+ glEndQuery(GL_TIME_ELAPSED);
+}
+
+void DRW_draw_callbacks_pre_scene(void)
+{
+ struct ARegion *ar = CTX_wm_region(DST.context);
+ RegionView3D *rv3d = CTX_wm_region_view3d(DST.context);
+
+ gpuLoadProjectionMatrix3D(rv3d->winmat);
+ gpuLoadMatrix3D(rv3d->viewmat);
+
+ ED_region_draw_cb_draw(DST.context, ar, REGION_DRAW_PRE_VIEW);
+}
+
+void DRW_draw_callbacks_post_scene(void)
+{
+ struct ARegion *ar = CTX_wm_region(DST.context);
+ RegionView3D *rv3d = CTX_wm_region_view3d(DST.context);
+
+ gpuLoadProjectionMatrix3D(rv3d->winmat);
+ gpuLoadMatrix3D(rv3d->viewmat);
+
+ ED_region_draw_cb_draw(DST.context, ar, REGION_DRAW_POST_VIEW);
}
/* Reset state to not interfer with other UI drawcall */
@@ -1056,102 +1167,81 @@ void DRW_state_reset(void)
state |= DRW_STATE_WRITE_DEPTH;
state |= DRW_STATE_WRITE_COLOR;
state |= DRW_STATE_DEPTH_LESS;
- set_state(state);
+ set_state(state, true);
}
-#endif
-/* ****************************************** Settings ******************************************/
-void *DRW_material_settings_get(Material *ma, const char *engine_name)
-{
- MaterialEngineSettings *ms = NULL;
-
- ms = BLI_findstring(&ma->engines_settings, engine_name, offsetof(MaterialEngineSettings, name));
-
-#ifdef WITH_CLAY_ENGINE
- /* If the settings does not exists yet, create it */
- if (ms == NULL) {
- ms = MEM_callocN(sizeof(RenderEngineSettings), "RenderEngineSettings");
- BLI_strncpy(ms->name, engine_name, 32);
-
- /* TODO make render_settings_create a polymorphic function */
- if (STREQ(engine_name, RE_engine_id_BLENDER_CLAY)) {
- ms->data = CLAY_material_settings_create();
- }
- else {
- /* No engine matched */
- BLI_assert(false);
- }
-
- BLI_addtail(&ma->engines_settings, ms);
- }
#else
- return NULL;
+void DRW_draw_pass(DRWPass *UNUSED(pass))
+{
+}
+
#endif
- return ms->data;
-}
+/* ****************************************** Settings ******************************************/
-/* If scene is NULL, use context scene */
-void *DRW_render_settings_get(Scene *scene, const char *engine_name)
+bool DRW_is_object_renderable(Object *ob)
{
- RenderEngineSettings *rs = NULL;
+ Scene *scene = CTX_data_scene(DST.context);
+ Object *obedit = scene->obedit;
- if (scene == NULL)
- scene = CTX_data_scene(DST.context);
+ if (ob->type == OB_MESH) {
+ if (ob == obedit) {
+ IDProperty *props = BKE_object_collection_engine_get(ob, COLLECTION_MODE_EDIT, "");
+ bool do_occlude_wire = BKE_collection_engine_property_value_get_bool(props, "show_occlude_wire");
- rs = BLI_findstring(&scene->engines_settings, engine_name, offsetof(RenderEngineSettings, name));
+ if (do_occlude_wire)
+ return false;
+ }
+ }
-#ifdef WITH_CLAY_ENGINE
- /* If the settings does not exists yet, create it */
- if (rs == NULL) {
- rs = MEM_callocN(sizeof(RenderEngineSettings), "RenderEngineSettings");
+ return true;
+}
- BLI_strncpy(rs->name, engine_name, 32);
+/* ****************************************** Framebuffers ******************************************/
- /* TODO make render_settings_create a polymorphic function */
- if (STREQ(engine_name, RE_engine_id_BLENDER_CLAY)) {
- rs->data = CLAY_render_settings_create();
- }
- else {
- /* No engine matched */
+static GPUTextureFormat convert_tex_format(int fbo_format, int *channels)
+{
+ switch (fbo_format) {
+ case DRW_BUF_RGBA_8: *channels = 4; return GPU_RGBA8;
+ case DRW_BUF_RGBA_16: *channels = 4; return GPU_RGBA16F;
+ case DRW_BUF_DEPTH_24: *channels = 1; return GPU_DEPTH_COMPONENT24;
+ default:
BLI_assert(false);
- }
-
- BLI_addtail(&scene->engines_settings, rs);
+ *channels = 4; return GPU_RGBA8;
}
-#else
- return NULL;
-#endif
-
- return rs->data;
}
-/* ****************************************** Framebuffers ******************************************/
+
void DRW_framebuffer_init(struct GPUFrameBuffer **fb, int width, int height, DRWFboTexture textures[MAX_FBO_TEX],
int texnbr)
{
+ BLI_assert(texnbr <= MAX_FBO_TEX);
+
if (!*fb) {
int color_attachment = -1;
*fb = GPU_framebuffer_create();
- for (int i = 0; i < texnbr; ++i)
- {
+ for (int i = 0; i < texnbr; ++i) {
DRWFboTexture fbotex = textures[i];
-
+
if (!*fbotex.tex) {
+ int channels;
+ GPUTextureFormat gpu_format = convert_tex_format(fbotex.format, &channels);
+
/* TODO refine to opengl formats */
if (fbotex.format == DRW_BUF_DEPTH_16 ||
- fbotex.format == DRW_BUF_DEPTH_24) {
+ fbotex.format == DRW_BUF_DEPTH_24)
+ {
*fbotex.tex = GPU_texture_create_depth(width, height, NULL);
GPU_texture_compare_mode(*fbotex.tex, false);
GPU_texture_filter_mode(*fbotex.tex, false);
}
else {
- *fbotex.tex = GPU_texture_create_2D(width, height, NULL, NULL);
+ *fbotex.tex = GPU_texture_create_2D_custom(width, height, channels, gpu_format, NULL, NULL);
++color_attachment;
}
}
-
+
GPU_framebuffer_texture_attach(*fb, *fbotex.tex, color_attachment);
}
@@ -1168,6 +1258,24 @@ void DRW_framebuffer_bind(struct GPUFrameBuffer *fb)
GPU_framebuffer_bind(fb);
}
+void DRW_framebuffer_clear(bool color, bool depth, bool stencil, float clear_col[4], float clear_depth)
+{
+ if (color) {
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ glClearColor(clear_col[0], clear_col[1], clear_col[2], clear_col[3]);
+ }
+ if (depth) {
+ glDepthMask(GL_TRUE);
+ glClearDepth(clear_depth);
+ }
+ if (stencil) {
+ glStencilMask(0xFF);
+ }
+ glClear(((color) ? GL_COLOR_BUFFER_BIT : 0) |
+ ((depth) ? GL_DEPTH_BUFFER_BIT : 0) |
+ ((stencil) ? GL_STENCIL_BUFFER_BIT : 0));
+}
+
void DRW_framebuffer_texture_attach(struct GPUFrameBuffer *fb, GPUTexture *tex, int slot)
{
GPU_framebuffer_texture_attach(fb, tex, slot);
@@ -1178,7 +1286,21 @@ void DRW_framebuffer_texture_detach(GPUTexture *tex)
GPU_framebuffer_texture_detach(tex);
}
+void DRW_framebuffer_blit(struct GPUFrameBuffer *fb_read, struct GPUFrameBuffer *fb_write, bool depth)
+{
+ GPU_framebuffer_blit(fb_read, 0, fb_write, 0, depth);
+}
+
/* ****************************************** Viewport ******************************************/
+static void *DRW_viewport_engine_data_get(void *engine_type)
+{
+ void *data = GPU_viewport_engine_data_get(DST.viewport, engine_type);
+
+ if (data == NULL) {
+ data = GPU_viewport_engine_data_create(DST.viewport, engine_type);
+ }
+ return data;
+}
float *DRW_viewport_size_get(void)
{
@@ -1195,25 +1317,23 @@ float *DRW_viewport_pixelsize_get(void)
return &DST.pixsize;
}
-void DRW_viewport_init(const bContext *C, void **buffers, void **textures, void **passes, void **storage)
+/* It also stores viewport variable to an immutable place: DST
+ * This is because a cache uniform only store reference
+ * to its value. And we don't want to invalidate the cache
+ * if this value change per viewport */
+static void DRW_viewport_var_init(const bContext *C)
{
RegionView3D *rv3d = CTX_wm_region_view3d(C);
- GPUViewport *viewport = rv3d->viewport;
-
- GPU_viewport_get_engine_data(viewport, buffers, textures, passes, storage);
/* Refresh DST.size */
- DefaultTextureList *txl = (DefaultTextureList *)*textures;
- DST.size[0] = (float)GPU_texture_width(txl->color);
- DST.size[1] = (float)GPU_texture_height(txl->color);
+ int size[2];
+ GPU_viewport_size_get(DST.viewport, size);
+ DST.size[0] = size[0];
+ DST.size[1] = size[1];
- DefaultFramebufferList *fbl = (DefaultFramebufferList *)*buffers;
+ DefaultFramebufferList *fbl = (DefaultFramebufferList *)GPU_viewport_framebuffer_list_get(DST.viewport);
DST.default_framebuffer = fbl->default_fb;
- DST.current_txl = (TextureList *)*textures;
- DST.current_fbl = (FramebufferList *)*buffers;
- DST.current_psl = (PassList *)*passes;
-
/* Refresh DST.screenvecs */
copy_v3_v3(DST.screenvecs[0], rv3d->viewinv[0]);
copy_v3_v3(DST.screenvecs[1], rv3d->viewinv[1]);
@@ -1233,8 +1353,10 @@ void DRW_viewport_matrix_get(float mat[4][4], DRWViewportMatrixType type)
if (type == DRW_MAT_PERS)
copy_m4_m4(mat, rv3d->persmat);
- else if (type == DRW_MAT_WIEW)
+ else if (type == DRW_MAT_VIEW)
copy_m4_m4(mat, rv3d->viewmat);
+ else if (type == DRW_MAT_VIEWINV)
+ copy_m4_m4(mat, rv3d->viewinv);
else if (type == DRW_MAT_WIN)
copy_m4_m4(mat, rv3d->winmat);
}
@@ -1245,28 +1367,491 @@ bool DRW_viewport_is_persp_get(void)
return rv3d->is_persp;
}
-bool DRW_viewport_cache_is_dirty(void)
+DefaultFramebufferList *DRW_viewport_framebuffer_list_get(void)
+{
+ return GPU_viewport_framebuffer_list_get(DST.viewport);
+}
+
+DefaultTextureList *DRW_viewport_texture_list_get(void)
+{
+ return GPU_viewport_texture_list_get(DST.viewport);
+}
+
+/* **************************************** OBJECTS *************************************** */
+
+typedef struct ObjectEngineData {
+ struct ObjectEngineData *next, *prev;
+ DrawEngineType *engine_type;
+ void *storage;
+} ObjectEngineData;
+
+void **DRW_object_engine_data_get(Object *ob, DrawEngineType *engine_type)
+{
+ ObjectEngineData *oed;
+
+ for (oed = ob->drawdata.first; oed; oed = oed->next) {
+ if (oed->engine_type == engine_type) {
+ return &oed->storage;
+ }
+ }
+
+ oed = MEM_callocN(sizeof(ObjectEngineData), "ObjectEngineData");
+ oed->engine_type = engine_type;
+ BLI_addtail(&ob->drawdata, oed);
+
+ return &oed->storage;
+}
+
+void DRW_object_engine_data_free(Object *ob)
+{
+ for (ObjectEngineData *oed = ob->drawdata.first; oed; oed = oed->next) {
+ if (oed->storage) {
+ MEM_freeN(oed->storage);
+ }
+ }
+
+ BLI_freelistN(&ob->drawdata);
+}
+
+/* **************************************** RENDERING ************************************** */
+
+#define TIMER_FALLOFF 0.1f
+
+static void DRW_engines_init(void)
+{
+ for (LinkData *link = DST.enabled_engines.first; link; link = link->next) {
+ DrawEngineType *engine = link->data;
+ ViewportEngineData *data = DRW_viewport_engine_data_get(engine);
+ double stime = PIL_check_seconds_timer();
+
+ if (engine->engine_init) {
+ engine->engine_init(data);
+ }
+
+ double ftime = (PIL_check_seconds_timer() - stime) * 1e3;
+ data->init_time = data->init_time * (1.0f - TIMER_FALLOFF) + ftime * TIMER_FALLOFF; /* exp average */
+ }
+}
+
+static void DRW_engines_cache_init(void)
+{
+ for (LinkData *link = DST.enabled_engines.first; link; link = link->next) {
+ DrawEngineType *engine = link->data;
+ ViewportEngineData *data = DRW_viewport_engine_data_get(engine);
+ double stime = PIL_check_seconds_timer();
+ data->cache_time = 0.0;
+
+ if (engine->cache_init) {
+ engine->cache_init(data);
+ }
+
+ data->cache_time += (PIL_check_seconds_timer() - stime) * 1e3;
+ }
+}
+
+static void DRW_engines_cache_populate(Object *ob)
+{
+ for (LinkData *link = DST.enabled_engines.first; link; link = link->next) {
+ DrawEngineType *engine = link->data;
+ ViewportEngineData *data = DRW_viewport_engine_data_get(engine);
+ double stime = PIL_check_seconds_timer();
+
+ if (engine->cache_populate) {
+ engine->cache_populate(data, ob);
+ }
+
+ data->cache_time += (PIL_check_seconds_timer() - stime) * 1e3;
+ }
+}
+
+static void DRW_engines_cache_finish(void)
+{
+ for (LinkData *link = DST.enabled_engines.first; link; link = link->next) {
+ DrawEngineType *engine = link->data;
+ ViewportEngineData *data = DRW_viewport_engine_data_get(engine);
+ double stime = PIL_check_seconds_timer();
+
+ if (engine->cache_finish) {
+ engine->cache_finish(data);
+ }
+
+ data->cache_time += (PIL_check_seconds_timer() - stime) * 1e3;
+ }
+}
+
+static void DRW_engines_draw_background(void)
+{
+ for (LinkData *link = DST.enabled_engines.first; link; link = link->next) {
+ DrawEngineType *engine = link->data;
+ ViewportEngineData *data = DRW_viewport_engine_data_get(engine);
+ double stime = PIL_check_seconds_timer();
+
+ if (engine->draw_background) {
+ engine->draw_background(data);
+ return;
+ }
+
+ double ftime = (PIL_check_seconds_timer() - stime) * 1e3;
+ data->background_time = data->background_time * (1.0f - TIMER_FALLOFF) + ftime * TIMER_FALLOFF; /* exp average */
+ }
+
+ /* No draw_background found, doing default background */
+ DRW_draw_background();
+}
+
+static void DRW_engines_draw_scene(void)
+{
+ for (LinkData *link = DST.enabled_engines.first; link; link = link->next) {
+ DrawEngineType *engine = link->data;
+ ViewportEngineData *data = DRW_viewport_engine_data_get(engine);
+ double stime = PIL_check_seconds_timer();
+
+ if (engine->draw_scene) {
+ engine->draw_scene(data);
+ }
+
+ double ftime = (PIL_check_seconds_timer() - stime) * 1e3;
+ data->render_time = data->render_time * (1.0f - TIMER_FALLOFF) + ftime * TIMER_FALLOFF; /* exp average */
+ }
+}
+
+static void use_drw_engine(DrawEngineType *engine)
+{
+ LinkData *ld = MEM_callocN(sizeof(LinkData), "enabled engine link data");
+ ld->data = engine;
+ BLI_addtail(&DST.enabled_engines, ld);
+}
+
+/* TODO revisit this when proper layering is implemented */
+/* Gather all draw engines needed and store them in DST.enabled_engines
+ * That also define the rendering order of engines */
+static void DRW_engines_enable(const bContext *C)
+{
+ /* TODO layers */
+ Scene *scene = CTX_data_scene(C);
+ RenderEngineType *type = RE_engines_find(scene->r.engine);
+ use_drw_engine(type->draw_engine);
+
+ /* TODO Refine the folowing logic based on objects states
+ * not on global state.
+ * Order is important */
+ use_drw_engine(&draw_engine_object_type);
+
+ switch (CTX_data_mode_enum(C)) {
+ case CTX_MODE_EDIT_MESH:
+ use_drw_engine(&draw_engine_edit_mesh_type);
+ break;
+ case CTX_MODE_EDIT_CURVE:
+ use_drw_engine(&draw_engine_edit_curve_type);
+ break;
+ case CTX_MODE_EDIT_SURFACE:
+ use_drw_engine(&draw_engine_edit_surface_type);
+ break;
+ case CTX_MODE_EDIT_TEXT:
+ use_drw_engine(&draw_engine_edit_text_type);
+ break;
+ case CTX_MODE_EDIT_ARMATURE:
+ use_drw_engine(&draw_engine_edit_armature_type);
+ break;
+ case CTX_MODE_EDIT_METABALL:
+ use_drw_engine(&draw_engine_edit_metaball_type);
+ break;
+ case CTX_MODE_EDIT_LATTICE:
+ use_drw_engine(&draw_engine_edit_lattice_type);
+ break;
+ case CTX_MODE_POSE:
+ use_drw_engine(&draw_engine_pose_type);
+ break;
+ case CTX_MODE_SCULPT:
+ use_drw_engine(&draw_engine_sculpt_type);
+ break;
+ case CTX_MODE_PAINT_WEIGHT:
+ use_drw_engine(&draw_engine_paint_weight_type);
+ break;
+ case CTX_MODE_PAINT_VERTEX:
+ use_drw_engine(&draw_engine_paint_vertex_type);
+ break;
+ case CTX_MODE_PAINT_TEXTURE:
+ use_drw_engine(&draw_engine_paint_texture_type);
+ break;
+ case CTX_MODE_PARTICLE:
+ use_drw_engine(&draw_engine_particle_type);
+ break;
+ case CTX_MODE_OBJECT:
+ break;
+ }
+}
+
+static void DRW_engines_disable(void)
+{
+ BLI_freelistN(&DST.enabled_engines);
+}
+
+static unsigned int DRW_engines_get_hash(void)
+{
+ unsigned int hash = 0;
+ /* The cache depends on enabled engines */
+ /* FIXME : if collision occurs ... segfault */
+ for (LinkData *link = DST.enabled_engines.first; link; link = link->next) {
+ DrawEngineType *engine = link->data;
+ hash += BLI_ghashutil_strhash_p(engine->idname);
+ }
+
+ return hash;
+}
+
+static void draw_stat(rcti *rect, int u, int v, const char *txt, const int size)
+{
+ BLF_draw_default_ascii(rect->xmin + (1 + u * 5) * U.widget_unit,
+ rect->ymax - (3 + v++) * U.widget_unit, 0.0f,
+ txt, size);
+}
+
+/* CPU stats */
+static void DRW_debug_cpu_stats(void)
+{
+ int u, v;
+ double cache_tot_time = 0.0, init_tot_time = 0.0, background_tot_time = 0.0, render_tot_time = 0.0, tot_time = 0.0;
+ /* local coordinate visible rect inside region, to accomodate overlapping ui */
+ rcti rect;
+ struct ARegion *ar = CTX_wm_region(DST.context);
+ ED_region_visible_rect(ar, &rect);
+
+ UI_FontThemeColor(BLF_default(), TH_TEXT_HI);
+
+ /* row by row */
+ v = 0; u = 0;
+ /* Label row */
+ char col_label[32];
+ sprintf(col_label, "Engine");
+ draw_stat(&rect, u++, v, col_label, sizeof(col_label));
+ sprintf(col_label, "Cache");
+ draw_stat(&rect, u++, v, col_label, sizeof(col_label));
+ sprintf(col_label, "Init");
+ draw_stat(&rect, u++, v, col_label, sizeof(col_label));
+ sprintf(col_label, "Background");
+ draw_stat(&rect, u++, v, col_label, sizeof(col_label));
+ sprintf(col_label, "Render");
+ draw_stat(&rect, u++, v, col_label, sizeof(col_label));
+ sprintf(col_label, "Total (w/o cache)");
+ draw_stat(&rect, u++, v, col_label, sizeof(col_label));
+ v++;
+
+ /* Engines rows */
+ char time_to_txt[16];
+ for (LinkData *link = DST.enabled_engines.first; link; link = link->next) {
+ u = 0;
+ DrawEngineType *engine = link->data;
+ ViewportEngineData *data = DRW_viewport_engine_data_get(engine);
+
+ draw_stat(&rect, u++, v, engine->idname, sizeof(engine->idname));
+
+ cache_tot_time += data->cache_time;
+ sprintf(time_to_txt, "%.2fms", data->cache_time);
+ draw_stat(&rect, u++, v, time_to_txt, sizeof(time_to_txt));
+
+ init_tot_time += data->init_time;
+ sprintf(time_to_txt, "%.2fms", data->init_time);
+ draw_stat(&rect, u++, v, time_to_txt, sizeof(time_to_txt));
+
+ background_tot_time += data->background_time;
+ sprintf(time_to_txt, "%.2fms", data->background_time);
+ draw_stat(&rect, u++, v, time_to_txt, sizeof(time_to_txt));
+
+ render_tot_time += data->render_time;
+ sprintf(time_to_txt, "%.2fms", data->render_time);
+ draw_stat(&rect, u++, v, time_to_txt, sizeof(time_to_txt));
+
+ tot_time += data->init_time + data->background_time + data->render_time;
+ sprintf(time_to_txt, "%.2fms", data->init_time + data->background_time + data->render_time);
+ draw_stat(&rect, u++, v, time_to_txt, sizeof(time_to_txt));
+ v++;
+ }
+
+ /* Totals row */
+ u = 0;
+ sprintf(col_label, "Sub Total");
+ draw_stat(&rect, u++, v, col_label, sizeof(col_label));
+ sprintf(time_to_txt, "%.2fms", cache_tot_time);
+ draw_stat(&rect, u++, v, time_to_txt, sizeof(time_to_txt));
+ sprintf(time_to_txt, "%.2fms", init_tot_time);
+ draw_stat(&rect, u++, v, time_to_txt, sizeof(time_to_txt));
+ sprintf(time_to_txt, "%.2fms", background_tot_time);
+ draw_stat(&rect, u++, v, time_to_txt, sizeof(time_to_txt));
+ sprintf(time_to_txt, "%.2fms", render_tot_time);
+ draw_stat(&rect, u++, v, time_to_txt, sizeof(time_to_txt));
+ sprintf(time_to_txt, "%.2fms", tot_time);
+ draw_stat(&rect, u++, v, time_to_txt, sizeof(time_to_txt));
+}
+
+/* Display GPU time for each passes */
+static void DRW_debug_gpu_stats(void)
+{
+ /* local coordinate visible rect inside region, to accomodate overlapping ui */
+ rcti rect;
+ struct ARegion *ar = CTX_wm_region(DST.context);
+ ED_region_visible_rect(ar, &rect);
+
+ UI_FontThemeColor(BLF_default(), TH_TEXT_HI);
+
+ char time_to_txt[16];
+ char pass_name[MAX_PASS_NAME + 8];
+ int v = BLI_listbase_count(&DST.enabled_engines) + 3;
+ GLuint64 tot_time = 0;
+
+ for (LinkData *link = DST.enabled_engines.first; link; link = link->next) {
+ GLuint64 engine_time = 0;
+ DrawEngineType *engine = link->data;
+ ViewportEngineData *data = DRW_viewport_engine_data_get(engine);
+ int vsta = v;
+
+ draw_stat(&rect, 0, v, engine->idname, sizeof(engine->idname));
+ v++;
+
+ for (int i = 0; i < MAX_PASSES; ++i) {
+ DRWPass *pass = data->psl->passes[i];
+ if (pass != NULL) {
+ GLuint64 time;
+ glGetQueryObjectui64v(pass->timer_queries[pass->front_idx], GL_QUERY_RESULT, &time);
+ tot_time += time;
+ engine_time += time;
+
+ sprintf(pass_name, " |--> %s", pass->name);
+ draw_stat(&rect, 0, v, pass_name, sizeof(pass_name));
+
+ if (pass->wasdrawn)
+ sprintf(time_to_txt, "%.2fms", time / 1000000.0);
+ else
+ sprintf(time_to_txt, "Not drawn");
+ draw_stat(&rect, 2, v++, time_to_txt, sizeof(time_to_txt));
+
+ pass->wasdrawn = false;
+ }
+ }
+ /* engine total time */
+ sprintf(time_to_txt, "%.2fms", engine_time / 1000000.0);
+ draw_stat(&rect, 2, vsta, time_to_txt, sizeof(time_to_txt));
+ v++;
+ }
+
+ sprintf(pass_name, "Total GPU time %.2fms (%.1f fps)", tot_time / 1000000.0, 1000000000.0 / tot_time);
+ draw_stat(&rect, 0, v, pass_name, sizeof(pass_name));
+}
+
+/* Everything starts here.
+ * This function takes care of calling all cache and rendering functions
+ * for each relevant engine / mode engine. */
+void DRW_draw_view(const bContext *C)
+{
+ bool cache_is_dirty;
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ DST.viewport = rv3d->viewport;
+ v3d->zbuf = true;
+
+ /* Get list of enabled engines */
+ DRW_engines_enable(C);
+
+ /* Setup viewport */
+ cache_is_dirty = GPU_viewport_cache_validate(DST.viewport, DRW_engines_get_hash());
+ DRW_viewport_var_init(C);
+
+ /* Update ubos */
+ DRW_globals_update();
+
+ /* Init engines */
+ DRW_engines_init();
+
+ /* TODO : tag to refresh by the deps graph */
+ /* ideally only refresh when objects are added/removed */
+ /* or render properties / materials change */
+ if (cache_is_dirty) {
+ SceneLayer *sl = CTX_data_scene_layer(C);
+
+ DRW_engines_cache_init();
+ DEG_OBJECT_ITER(sl, ob);
+ {
+ DRW_engines_cache_populate(ob);
+ }
+ DEG_OBJECT_ITER_END
+ DRW_engines_cache_finish();
+ }
+
+ /* Start Drawing */
+ DRW_engines_draw_background();
+
+ DRW_draw_callbacks_pre_scene();
+ // DRW_draw_grid();
+ DRW_engines_draw_scene();
+ DRW_draw_callbacks_post_scene();
+
+ DRW_draw_region_info();
+
+ if (G.debug_value > 20) {
+ DRW_debug_cpu_stats();
+ DRW_debug_gpu_stats();
+ }
+
+ DRW_state_reset();
+ DRW_engines_disable();
+}
+
+/* ****************************************** OTHER ***************************************** */
+
+const bContext *DRW_get_context(void)
{
- /* TODO Use a dirty flag */
- return (DST.current_psl->passes[0] == NULL);
+ return DST.context;
}
-/* ****************************************** INIT ******************************************/
+/* ****************************************** INIT ***************************************** */
+
+void DRW_engine_register(DrawEngineType *draw_engine_type)
+{
+ BLI_addtail(&DRW_engines, draw_engine_type);
+}
-void DRW_engines_init(void)
+void DRW_engines_register(void)
{
#ifdef WITH_CLAY_ENGINE
RE_engines_register(NULL, &viewport_clay_type);
+ RE_engines_register(NULL, &viewport_eevee_type);
+
+ DRW_engine_register(&draw_engine_object_type);
+ DRW_engine_register(&draw_engine_edit_armature_type);
+ DRW_engine_register(&draw_engine_edit_curve_type);
+ DRW_engine_register(&draw_engine_edit_lattice_type);
+ DRW_engine_register(&draw_engine_edit_mesh_type);
+ DRW_engine_register(&draw_engine_edit_metaball_type);
+ DRW_engine_register(&draw_engine_edit_surface_type);
+ DRW_engine_register(&draw_engine_edit_text_type);
+ DRW_engine_register(&draw_engine_paint_texture_type);
+ DRW_engine_register(&draw_engine_paint_vertex_type);
+ DRW_engine_register(&draw_engine_paint_weight_type);
+ DRW_engine_register(&draw_engine_particle_type);
+ DRW_engine_register(&draw_engine_pose_type);
+ DRW_engine_register(&draw_engine_sculpt_type);
#endif
}
+extern struct GPUUniformBuffer *globals_ubo; /* draw_common.c */
void DRW_engines_free(void)
{
#ifdef WITH_CLAY_ENGINE
- clay_engine_free();
-
DRW_shape_cache_free();
+ DrawEngineType *next;
+ for (DrawEngineType *type = DRW_engines.first; type; type = next) {
+ next = type->next;
+ BLI_remlink(&R_engines, type);
+
+ if (type->engine_free) {
+ type->engine_free();
+ }
+ }
+
+ if (globals_ubo)
+ GPU_uniformbuffer_free(globals_ubo);
+
BLI_remlink(&R_engines, &viewport_clay_type);
#endif
-} \ No newline at end of file
+}