[Bf-blender-cvs] [cfa2b3019dc] temp-drawcontext: DRW: Add own opengl context to DrawManager.

Clément Foucault noreply at git.blender.org
Fri Feb 9 21:05:23 CET 2018


Commit: cfa2b3019dc759889e50060713e4678f51a87153
Author: Clément Foucault
Date:   Fri Feb 9 21:00:04 2018 +0100
Branches: temp-drawcontext
https://developer.blender.org/rBcfa2b3019dc759889e50060713e4678f51a87153

DRW: Add own opengl context to DrawManager.

We create a new offscreen render context (without a window attached as allowed by ogl > 3.0) and use it to draw everything in the draw manager.
This require the context to be setup right. The output Framebuffer need to be created under the drawmanager context (because FBOs are not shared).
Same goes for deletion. Although, fix for proper deletion will come in another commit.

This should fix the MultiWindow/Threaded Render issue. Now every single batch drawn by the draw manager is declared and drawn by the same context.
So the VAO problem is gone and only one VAO per batch is needed.

VAO deletion is also a concern that still needs to be addressed correctly.

We still have issues with ownership and freeing

===================================================================

M	source/blender/draw/DRW_engine.h
M	source/blender/draw/intern/draw_manager.c
M	source/blender/editors/render/render_internal.c
M	source/blender/editors/render/render_opengl.c
M	source/blender/editors/space_view3d/view3d_draw.c
M	source/blender/editors/space_view3d/view3d_view.c
M	source/blender/gpu/intern/gpu_viewport.c
M	source/blender/windowmanager/CMakeLists.txt
M	source/blender/windowmanager/intern/wm_init_exit.c

===================================================================

diff --git a/source/blender/draw/DRW_engine.h b/source/blender/draw/DRW_engine.h
index 9baad113c42..9a27bbb7c86 100644
--- a/source/blender/draw/DRW_engine.h
+++ b/source/blender/draw/DRW_engine.h
@@ -125,4 +125,9 @@ void EDIT_ARMATURE_collection_settings_create(struct IDProperty *properties);
 void PAINT_WEIGHT_collection_settings_create(struct IDProperty *properties);
 void PAINT_VERTEX_collection_settings_create(struct IDProperty *properties);
 
+void DRW_ogl_ctx_create(void);
+void DRW_ogl_ctx_destroy(void);
+void DRW_ogl_ctx_enable(void);
+void DRW_ogl_ctx_disable(void);
+
 #endif /* __DRW_ENGINE_H__ */
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c
index 96454fd087e..6e50ca1f0ba 100644
--- a/source/blender/draw/intern/draw_manager.c
+++ b/source/blender/draw/intern/draw_manager.c
@@ -30,6 +30,7 @@
 #include "BLI_rect.h"
 #include "BLI_string.h"
 #include "BLI_string_utils.h"
+#include "BLI_threads.h"
 
 #include "BIF_glutil.h"
 
@@ -82,6 +83,7 @@
 
 #include "WM_api.h"
 #include "WM_types.h"
+#include "wm_window.h"
 
 #include "draw_manager_text.h"
 #include "draw_manager_profiling.h"
@@ -374,6 +376,12 @@ static struct DRWMatrixOveride {
 
 ListBase DRW_engines = {NULL, NULL};
 
+/* Unique ghost context used by the draw manager. */
+static void *g_ogl_context = NULL;
+
+/* Mutex to lock the drw manager and avoid concurent context usage. */
+static ThreadRWMutex cache_rwlock = BLI_RWLOCK_INITIALIZER;
+
 #ifdef USE_GPU_SELECT
 static unsigned int g_DRW_select_id = (unsigned int)-1;
 
@@ -3443,6 +3451,7 @@ void DRW_draw_render_loop_ex(
         ARegion *ar, View3D *v3d, const eObjectMode object_mode,
         const bContext *evil_C)
 {
+
 	Scene *scene = DEG_get_evaluated_scene(depsgraph);
 	ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph);
 	RegionView3D *rv3d = ar->regiondata;
@@ -3628,6 +3637,10 @@ void DRW_render_to_image(RenderEngine *re, struct Depsgraph *depsgraph)
 	RenderData *r = &scene->r;
 	Render *render = re->re;
 	const EvaluationContext *eval_ctx = RE_GetEvalCtx(render);
+	/* Changing Context */
+	BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE);
+	/* IMPORTANT: We dont support immediate mode in render mode! */
+	WM_context_activate(g_ogl_context);
 
 	/* Reset before using it. */
 	memset(&DST, 0x0, sizeof(DST));
@@ -3682,6 +3695,10 @@ void DRW_render_to_image(RenderEngine *re, struct Depsgraph *depsgraph)
 	glEnable(GL_SCISSOR_TEST);
 	GPU_framebuffer_restore();
 
+	/* Changing Context */
+	wm_window_reset_drawable();
+	BLI_rw_mutex_unlock(&cache_rwlock);
+
 #ifdef DEBUG
 	/* Avoid accidental reuse. */
 	memset(&DST, 0xFF, sizeof(DST));
@@ -3699,6 +3716,37 @@ void DRW_render_object_iter(
 	DEG_OBJECT_ITER_FOR_RENDER_ENGINE_END
 }
 
+static struct DRWSelectBuffer {
+	struct GPUFrameBuffer *framebuffer;
+	struct GPUTexture *texture_depth;
+} g_select_buffer = {NULL};
+
+static void draw_select_framebuffer_setup(const rcti *rect)
+{
+	if (g_select_buffer.framebuffer == NULL) {
+		g_select_buffer.framebuffer = GPU_framebuffer_create();
+	}
+
+	/* If size mismatch recreate the texture. */
+	if ((g_select_buffer.texture_depth != NULL) &&
+		((GPU_texture_width(g_select_buffer.texture_depth) != BLI_rcti_size_x(rect)) ||
+		 (GPU_texture_height(g_select_buffer.texture_depth) != BLI_rcti_size_y(rect))))
+	{
+		GPU_texture_free(g_select_buffer.texture_depth);
+		g_select_buffer.texture_depth = NULL;
+	}
+
+	if (g_select_buffer.texture_depth == NULL) {
+		g_select_buffer.texture_depth = GPU_texture_create_depth(BLI_rcti_size_x(rect), BLI_rcti_size_y(rect), NULL);
+
+		GPU_framebuffer_texture_attach(g_select_buffer.framebuffer, g_select_buffer.texture_depth, 0, 0);
+
+		if (!GPU_framebuffer_check_valid(g_select_buffer.framebuffer, NULL)) {
+			printf("Error invalid selection framebuffer\n");
+		}
+	}
+}
+
 /**
  * object mode select-loop, see: ED_view3d_draw_select_loop (legacy drawing).
  */
@@ -3740,10 +3788,13 @@ void DRW_draw_select_loop(
 	struct GPUViewport *viewport = GPU_viewport_create();
 	GPU_viewport_size_set(viewport, (const int[2]){BLI_rcti_size_x(rect), BLI_rcti_size_y(rect)});
 
-	bool cache_is_dirty;
 	DST.viewport = viewport;
 	v3d->zbuf = true;
 
+	/* Setup framebuffer */
+	draw_select_framebuffer_setup(rect);
+	GPU_framebuffer_bind(g_select_buffer.framebuffer);
+
 	DST.options.is_select = true;
 
 	/* Get list of enabled engines */
@@ -3756,7 +3807,6 @@ void DRW_draw_select_loop(
 	}
 
 	/* Setup viewport */
-	cache_is_dirty = true;
 
 	/* Instead of 'DRW_context_state_init(C, &DST.draw_ctx)', assign from args */
 	DST.draw_ctx = (DRWContextState){
@@ -3772,10 +3822,7 @@ void DRW_draw_select_loop(
 	/* Init engines */
 	drw_engines_init();
 
-	/* TODO : tag to refresh by the dependency graph */
-	/* ideally only refresh when objects are added/removed */
-	/* or render properties / materials change */
-	if (cache_is_dirty) {
+	{
 		drw_engines_cache_init();
 
 		if (use_obedit) {
@@ -4097,6 +4144,11 @@ extern struct GPUUniformBuffer *globals_ubo; /* draw_common.c */
 extern struct GPUTexture *globals_ramp; /* draw_common.c */
 void DRW_engines_free(void)
 {
+	DRW_ogl_ctx_enable();
+
+	DRW_TEXTURE_FREE_SAFE(g_select_buffer.texture_depth);
+	DRW_FRAMEBUFFER_FREE_SAFE(g_select_buffer.framebuffer);
+
 	DRW_shape_cache_free();
 	DRW_stats_free();
 
@@ -4119,9 +4171,51 @@ void DRW_engines_free(void)
 	MEM_SAFE_FREE(RST.bound_texs);
 	MEM_SAFE_FREE(RST.bound_tex_slots);
 
+	DRW_ogl_ctx_disable();
+
 #ifdef WITH_CLAY_ENGINE
 	BLI_remlink(&R_engines, &DRW_engine_viewport_clay_type);
 #endif
 }
 
 /** \} */
+
+/** \name Init/Exit (DRW_opengl_ctx)
+ * \{ */
+
+void DRW_ogl_ctx_create(void)
+{
+	BLI_assert(g_ogl_context == NULL); /* Ensure it's called once */
+
+	/* This changes the active context. */
+	g_ogl_context = WM_context_create();
+	/* So we activate the window's one afterwards. */
+	wm_window_reset_drawable();
+}
+
+void DRW_ogl_ctx_destroy(void)
+{
+	if (g_ogl_context != NULL) {
+		WM_context_dispose(g_ogl_context);
+	}
+}
+
+void DRW_ogl_ctx_enable(void)
+{
+	if (g_ogl_context != NULL) {
+		BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE);
+		immDeactivate();
+		WM_context_activate(g_ogl_context);
+		immActivate();
+	}
+}
+
+void DRW_ogl_ctx_disable(void)
+{
+	if (g_ogl_context != NULL) {
+		wm_window_reset_drawable();
+		BLI_rw_mutex_unlock(&cache_rwlock);
+	}
+}
+
+/** \} */
diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c
index 8e410a3abbb..4750840be96 100644
--- a/source/blender/editors/render/render_internal.c
+++ b/source/blender/editors/render/render_internal.c
@@ -869,15 +869,6 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even
 		return OPERATOR_CANCELLED;
 	}
 
-	/* XXX FIXME If engine is an OpenGL engine do not run modal.
-	 * This is a problem for animation rendering since you cannot abort them.
-	 * This also does not open an image editor space. */
-	if (RE_engine_is_opengl(re_type)) {
-		/* ensure at least 1 area shows result */
-		render_view_open(C, event->x, event->y, op->reports);
-		return screen_render_exec(C, op);
-	}
-	
 	/* only one render job at a time */
 	if (WM_jobs_test(CTX_wm_manager(C), scene, WM_JOB_TYPE_RENDER))
 		return OPERATOR_CANCELLED;
diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c
index 6e969067985..6c3d0d18ac6 100644
--- a/source/blender/editors/render/render_opengl.c
+++ b/source/blender/editors/render/render_opengl.c
@@ -57,6 +57,8 @@
 
 #include "DEG_depsgraph.h"
 
+#include "DRW_engine.h"
+
 #include "WM_api.h"
 #include "WM_types.h"
 
@@ -323,6 +325,7 @@ static void screen_opengl_render_doit(const bContext *C, OGLRender *oglrender, R
 			unsigned char *gp_rect;
 			unsigned char *render_rect = (unsigned char *)RE_RenderViewGetById(rr, oglrender->view_id)->rect32;
 
+			DRW_ogl_ctx_enable();
 			GPU_offscreen_bind(oglrender->ofs, true);
 
 			glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
@@ -342,6 +345,7 @@ static void screen_opengl_render_doit(const bContext *C, OGLRender *oglrender, R
 				blend_color_mix_byte(&render_rect[i], &render_rect[i], &gp_rect[i]);
 			}
 			GPU_offscreen_unbind(oglrender->ofs, true);
+			DRW_ogl_ctx_disable();
 
 			MEM_freeN(gp_rect);
 		}
@@ -652,7 +656,9 @@ static bool screen_opengl_render_init(bContext *C, wmOperator *op)
 	sizey = (scene->r.size * scene->r.ysch) / 100;
 
 	/* corrects render size with actual size, not every card supports non-power-of-two dimensions */
+	DRW_ogl_ctx_enable(); /* Offscreen creation needs to be done in DRW context. */
 	ofs = GPU_offscreen_create(sizex, sizey, full_samples ? 0 : samples, true, err_out);
+	DRW_ogl_ctx_disable();
 
 	if (!ofs) {
 		BKE_reportf(op->reports, RPT_ERROR, "Failed to create OpenGL off-screen buffer, %s", err_out);
@@ -841,7 +847,9 @@ static void screen_opengl_render_end(bContext *C, OGLRender *oglrender)
 	if (oglrender->fx)
 		GPU_fx_compositor_destroy(oglrender->fx);
 
+	DRW_ogl_ctx_enable();
 	GPU_offscreen_free(oglrender->ofs);
+	DRW_ogl_ctx_disable();
 
 	if (oglrender->is_sequencer) {
 		MEM_freeN(oglrender->seq_data.ibufs_arr);
diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c
index af8a3369732..eafac06f6a7 100644
--- a/source/blender/editors/space_view3d/view3d_draw.c
+++ b/source/blender/editors/space_view3d/view3d_draw.c
@@ -2130,6 +2130,7 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(
 	}
 
 	const bool own_ofs = (ofs == NULL);
+	DRW_ogl_ctx_enable();
 
 	if (own_ofs) {
 		/* bind */
@@ -2266,6 +2267,8 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(
 		GPU_offscreen_free(ofs);
 	}
 
+	DRW_ogl_ctx_disable();
+
 	if (ibuf->rect_float && ibuf->rect)
 		IMB_rect_from_float(ibuf);
 
diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c
index a0918066887..74cab25bdc7 100644
--- a/source/blender/editors/space_view3d/view3d_view.c
+++ b/source/blender/editors/space_view3d/view3d_view.c
@@ -922,6 +922,11 @@ int view3d_opengl_select(
 	UI_Theme_Store(&theme_state);
 	UI_SetTheme(SPACE_VIEW3D, RGN_TYPE_WINDOW);
 
+#ifndef WITH_OPENGL_LEGACY
+	/* All of the

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list