diff options
author | Clément Foucault <foucault.clem@gmail.com> | 2018-02-26 21:41:17 +0300 |
---|---|---|
committer | Clément Foucault <foucault.clem@gmail.com> | 2018-02-26 21:41:17 +0300 |
commit | 13261304a331b4cff37de477ddf19c915ed64b2c (patch) | |
tree | 3660f94436af2e4d44d8310247280ab456243543 /source/blender | |
parent | 0940e89e604d85d717f792b73e30e5e96a42e7c6 (diff) |
DRW: Add new Draw Manager OpenGL Context.
This separate context allows two things:
- It allows viewports in multi-windows configuration.
- F12 render can use this context in a separate thread and do a non-blocking render.
The downside is that the context cannot be used while rendering so a request to refresh a viewport will lock the UI. This is something that will be adressed in the future.
Under the hood what does that mean:
- Not adding more mess with VAOs management in gawain.
- Doing depth only draw for operators / selection needs to be done in an offscreen buffer.
- The 3D cursor "autodis" operator is still reading the backbuffer so we need to copy the result to it.
- All FBOs needed by the drawmanager must to be created/destroyed with its context active.
- We cannot use batches created for UI in the DRW context and vice-versa. There is a clear separation of resources that enables the use of safe multi-threading.
Diffstat (limited to 'source/blender')
20 files changed, 347 insertions, 22 deletions
diff --git a/source/blender/draw/DRW_engine.h b/source/blender/draw/DRW_engine.h index 9baad113c42..9ed8f776f34 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_opengl_context_create(void); +void DRW_opengl_context_destroy(void); +void DRW_opengl_context_enable(void); +void DRW_opengl_context_disable(void); + #endif /* __DRW_ENGINE_H__ */ diff --git a/source/blender/draw/intern/draw_cache.c b/source/blender/draw/intern/draw_cache.c index 3b4180c0375..6b1a3356b51 100644 --- a/source/blender/draw/intern/draw_cache.c +++ b/source/blender/draw/intern/draw_cache.c @@ -45,6 +45,7 @@ static struct DRWShapeCache { Gwn_Batch *drw_single_vertice; Gwn_Batch *drw_fullscreen_quad; Gwn_Batch *drw_quad; + Gwn_Batch *drw_sphere; Gwn_Batch *drw_screenspace_circle; Gwn_Batch *drw_plain_axes; Gwn_Batch *drw_single_arrow; @@ -266,7 +267,6 @@ Gwn_Batch *DRW_cache_fullscreen_quad_get(void) Gwn_Batch *DRW_cache_quad_get(void) { if (!SHC.drw_quad) { - /* Use a triangle instead of a real quad */ float pos[4][2] = {{-1.0f, -1.0f}, { 1.0f, -1.0f}, {1.0f, 1.0f}, {-1.0f, 1.0f}}; float uvs[4][2] = {{ 0.0f, 0.0f}, { 1.0f, 0.0f}, {1.0f, 1.0f}, { 0.0f, 1.0f}}; @@ -294,7 +294,10 @@ Gwn_Batch *DRW_cache_quad_get(void) /* Sphere */ Gwn_Batch *DRW_cache_sphere_get(void) { - return GPU_batch_preset_sphere(2); + if (!SHC.drw_sphere) { + SHC.drw_sphere = gpu_batch_sphere(32, 24); + } + return SHC.drw_sphere; } /** \} */ diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index 99ea5b259c0..3845ee6a65e 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" @@ -97,6 +99,8 @@ #include "engines/basic/basic_engine.h" #include "engines/external/external_engine.h" +#include "../../../intern/gawain/gawain/gwn_context.h" + #include "DEG_depsgraph.h" #include "DEG_depsgraph_query.h" @@ -369,6 +373,13 @@ static struct DRWMatrixOveride { ListBase DRW_engines = {NULL, NULL}; +/* Unique ghost context used by the draw manager. */ +static void *g_ogl_context = NULL; +static Gwn_Context *g_gwn_context = NULL; + +/* Mutex to lock the drw manager and avoid concurent context usage. */ +static ThreadMutex g_ogl_context_mutex = BLI_MUTEX_INITIALIZER; + #ifdef USE_GPU_SELECT static unsigned int g_DRW_select_id = (unsigned int)-1; @@ -3440,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; @@ -3626,6 +3638,11 @@ void DRW_render_to_image(RenderEngine *engine, struct Depsgraph *depsgraph) RenderData *r = &scene->r; Render *render = engine->re; const EvaluationContext *eval_ctx = RE_GetEvalCtx(render); + /* Changing Context */ + DRW_opengl_context_enable(); + /* IMPORTANT: We dont support immediate mode in render mode! + * This shall remain in effect until immediate mode supports + * multiple threads. */ /* Reset before using it. */ memset(&DST, 0x0, sizeof(DST)); @@ -3705,6 +3722,9 @@ void DRW_render_to_image(RenderEngine *engine, struct Depsgraph *depsgraph) glEnable(GL_SCISSOR_TEST); GPU_framebuffer_restore(); + /* Changing Context */ + DRW_opengl_context_disable(); + #ifdef DEBUG /* Avoid accidental reuse. */ memset(&DST, 0xFF, sizeof(DST)); @@ -3722,6 +3742,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"); + } + } +} + /* Must run after all instance datas have been added. */ void DRW_render_instance_buffer_finish(void) { @@ -3767,13 +3818,20 @@ void DRW_draw_select_loop( } } + gpuPushAttrib(GPU_ENABLE_BIT | GPU_VIEWPORT_BIT); + glDisable(GL_SCISSOR_TEST); + 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); + DRW_framebuffer_clear(false, true, false, NULL, 1.0f); + DST.options.is_select = true; /* Get list of enabled engines */ @@ -3786,7 +3844,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){ @@ -3802,10 +3859,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) { @@ -3843,16 +3897,57 @@ void DRW_draw_select_loop( /* Avoid accidental reuse. */ memset(&DST, 0xFF, sizeof(DST)); #endif + GPU_framebuffer_restore(); /* Cleanup for selection state */ GPU_viewport_free(viewport); MEM_freeN(viewport); + /* Restore Drawing area. */ + gpuPopAttrib(); + glEnable(GL_SCISSOR_TEST); + /* restore */ rv3d->viewport = backup_viewport; #endif /* USE_GPU_SELECT */ } +static void draw_depth_texture_to_screen(GPUTexture *texture) +{ + const float w = (float)GPU_texture_width(texture); + const float h = (float)GPU_texture_height(texture); + + Gwn_VertFormat *format = immVertexFormat(); + unsigned int texcoord = GWN_vertformat_attr_add(format, "texCoord", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_3D_IMAGE_DEPTH_COPY); + + GPU_texture_bind(texture, 0); + + immUniform1i("image", 0); /* default GL_TEXTURE0 unit */ + + immBegin(GWN_PRIM_TRI_STRIP, 4); + + immAttrib2f(texcoord, 0.0f, 0.0f); + immVertex2f(pos, 0.0f, 0.0f); + + immAttrib2f(texcoord, 1.0f, 0.0f); + immVertex2f(pos, w, 0.0f); + + immAttrib2f(texcoord, 0.0f, 1.0f); + immVertex2f(pos, 0.0f, h); + + immAttrib2f(texcoord, 1.0f, 1.0f); + immVertex2f(pos, w, h); + + immEnd(); + + GPU_texture_unbind(texture); + + immUnbindProgram(); +} + /** * object mode select-loop, see: ED_view3d_draw_depth_loop (legacy drawing). */ @@ -3865,6 +3960,8 @@ void DRW_draw_depth_loop( ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph); RegionView3D *rv3d = ar->regiondata; + DRW_opengl_context_enable(); + /* backup (_never_ use rv3d->viewport) */ void *backup_viewport = rv3d->viewport; rv3d->viewport = NULL; @@ -3872,9 +3969,17 @@ void DRW_draw_depth_loop( /* Reset before using it. */ memset(&DST, 0x0, sizeof(DST)); + gpuPushAttrib(GPU_ENABLE_BIT | GPU_VIEWPORT_BIT); + glDisable(GL_SCISSOR_TEST); + struct GPUViewport *viewport = GPU_viewport_create(); GPU_viewport_size_set(viewport, (const int[2]){ar->winx, ar->winy}); + /* Setup framebuffer */ + draw_select_framebuffer_setup(&ar->winrct); + GPU_framebuffer_bind(g_select_buffer.framebuffer); + DRW_framebuffer_clear(false, true, false, NULL, 1.0f); + bool cache_is_dirty; DST.viewport = viewport; v3d->zbuf = true; @@ -3935,10 +4040,35 @@ void DRW_draw_depth_loop( memset(&DST, 0xFF, sizeof(DST)); #endif + /* TODO: Reading depth for operators should be done here. */ + + GPU_framebuffer_restore(); + /* Cleanup for selection state */ GPU_viewport_free(viewport); MEM_freeN(viewport); + /* Restore Drawing area. */ + gpuPopAttrib(); + glEnable(GL_SCISSOR_TEST); + + /* Changin context */ + DRW_opengl_context_disable(); + + /* XXX Drawing the resulting buffer to the BACK_BUFFER */ + gpuPushMatrix(); + gpuPushProjectionMatrix(); + wmOrtho2_region_pixelspace(ar); + gpuLoadIdentity(); + + glEnable(GL_DEPTH_TEST); /* Cannot write to depth buffer without testing */ + glDepthFunc(GL_ALWAYS); + draw_depth_texture_to_screen(g_select_buffer.texture_depth); + glDepthFunc(GL_LEQUAL); + + gpuPopMatrix(); + gpuPopProjectionMatrix(); + /* restore */ rv3d->viewport = backup_viewport; } @@ -4139,6 +4269,11 @@ extern struct GPUUniformBuffer *globals_ubo; /* draw_common.c */ extern struct GPUTexture *globals_ramp; /* draw_common.c */ void DRW_engines_free(void) { + DRW_opengl_context_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(); DRW_globals_free(); @@ -4164,9 +4299,86 @@ void DRW_engines_free(void) MEM_SAFE_FREE(RST.bound_texs); MEM_SAFE_FREE(RST.bound_tex_slots); + DRW_opengl_context_disable(); + #ifdef WITH_CLAY_ENGINE BLI_remlink(&R_engines, &DRW_engine_viewport_clay_type); #endif } /** \} */ + +/** \name Init/Exit (DRW_opengl_ctx) + * \{ */ + +void DRW_opengl_context_create(void) +{ + BLI_assert(g_ogl_context == NULL); /* Ensure it's called once */ + BLI_assert(BLI_thread_is_main()); + + BLI_mutex_init(&g_ogl_context_mutex); + + immDeactivate(); + /* This changes the active context. */ + g_ogl_context = WM_opengl_context_create(); + /* Be sure to create gawain.context too. */ + g_gwn_context = GWN_context_create(); + immActivate(); + /* Set default Blender OpenGL state */ + GPU_state_init(); + /* So we activate the window's one afterwards. */ + wm_window_reset_drawable(); +} + +void DRW_opengl_context_destroy(void) +{ + BLI_assert(BLI_thread_is_main()); + if (g_ogl_context != NULL) { + WM_opengl_context_activate(g_ogl_context); + GWN_context_active_set(g_gwn_context); + GWN_context_discard(g_gwn_context); + WM_opengl_context_dispose(g_ogl_context); + BLI_mutex_end(&g_ogl_context_mutex); + } +} + +void DRW_opengl_context_enable(void) +{ + if (g_ogl_context != NULL) { + /* IMPORTANT: We dont support immediate mode in render mode! + * This shall remain in effect until immediate mode supports + * multiple threads. */ + BLI_mutex_lock(&g_ogl_context_mutex); + if (BLI_thread_is_main()) { + immDeactivate(); + } + WM_opengl_context_activate(g_ogl_context); + GWN_context_active_set(g_gwn_context); + if (BLI_thread_is_main()) { + immActivate(); + } + } +} + +void DRW_opengl_context_disable(void) +{ + if (g_ogl_context != NULL) { +#ifdef __APPLE__ + /* Need to flush before disabling draw context, otherwise it does not + * always finish drawing and viewport can be empty or partially drawn */ + glFlush(); +#endif + + if (BLI_thread_is_main()) { + wm_window_reset_drawable(); + } + else { + WM_opengl_context_release(g_ogl_context); + GWN_context_active_set(NULL); + } + + BLI_mutex_unlock(&g_ogl_context_mutex); + } +} + +/** \} */ diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c index 0130b93babf..98d37eedb1b 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 8eb9283790b..1f9894b3b9f 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_opengl_context_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_opengl_context_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_opengl_context_enable(); /* Offscreen creation needs to be done in DRW context. */ ofs = GPU_offscreen_create(sizex, sizey, full_samples ? 0 : samples, true, true, err_out); + DRW_opengl_context_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_opengl_context_enable(); GPU_offscreen_free(oglrender->ofs); + DRW_opengl_context_disable(); if (oglrender->is_sequencer) { MEM_freeN(oglrender->seq_data.ibufs_arr); diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index 73fd3f562be..1774390a1e5 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -65,6 +65,8 @@ #include "GPU_viewport.h" #include "GPU_matrix.h" +#include "DRW_engine.h" + #include "WM_api.h" #include "WM_types.h" #include "WM_message.h" @@ -572,7 +574,9 @@ static void view3d_main_region_exit(wmWindowManager *wm, ARegion *ar) } if (rv3d->viewport) { + DRW_opengl_context_enable(); GPU_viewport_free(rv3d->viewport); + DRW_opengl_context_disable(); MEM_freeN(rv3d->viewport); rv3d->viewport = NULL; } @@ -757,7 +761,9 @@ static void view3d_main_region_free(ARegion *ar) GPU_fx_compositor_destroy(rv3d->compositor); } if (rv3d->viewport) { + DRW_opengl_context_enable(); GPU_viewport_free(rv3d->viewport); + DRW_opengl_context_disable(); MEM_freeN(rv3d->viewport); } diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 6e3a0883489..68996cdf906 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -2131,11 +2131,13 @@ ImBuf *ED_view3d_draw_offscreen_imbuf( } const bool own_ofs = (ofs == NULL); + DRW_opengl_context_enable(); if (own_ofs) { /* bind */ ofs = GPU_offscreen_create(sizex, sizey, use_full_sample ? 0 : samples, true, false, err_out); if (ofs == NULL) { + DRW_opengl_context_disable(); return NULL; } } @@ -2267,6 +2269,8 @@ ImBuf *ED_view3d_draw_offscreen_imbuf( GPU_offscreen_free(ofs); } + DRW_opengl_context_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 4ccf86138e7..cb329e62e96 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 queries need to be perform on the drawing context. */ + DRW_opengl_context_enable(); +#endif + /* Re-use cache (rect must be smaller then the cached) * other context is assumed to be unchanged */ if (GPU_select_is_cached()) { @@ -941,7 +946,7 @@ int view3d_opengl_select( v3d->zbuf = true; glEnable(GL_DEPTH_TEST); } - + if (vc->rv3d->rflag & RV3D_CLIPPING) ED_view3d_clipping_set(vc->rv3d); @@ -994,6 +999,11 @@ int view3d_opengl_select( ED_view3d_clipping_disable(); finally: + +#ifndef WITH_OPENGL_LEGACY + DRW_opengl_context_disable(); +#endif + if (hits < 0) printf("Too many objects in select buffer\n"); /* XXX make error message */ UI_Theme_Restore(&theme_state); diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt index 189ca8e6a33..5c0115d967a 100644 --- a/source/blender/gpu/CMakeLists.txt +++ b/source/blender/gpu/CMakeLists.txt @@ -150,6 +150,7 @@ data_to_c_simple(shaders/gpu_shader_image_modulate_alpha_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_image_alpha_color_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_image_color_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_image_depth_linear_frag.glsl SRC) +data_to_c_simple(shaders/gpu_shader_image_depth_copy_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_image_interlace_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_3D_image_vert.glsl SRC) data_to_c_simple(shaders/gpu_shader_3D_vert.glsl SRC) diff --git a/source/blender/gpu/GPU_batch.h b/source/blender/gpu/GPU_batch.h index d2f3409dc07..5807af7b359 100644 --- a/source/blender/gpu/GPU_batch.h +++ b/source/blender/gpu/GPU_batch.h @@ -58,6 +58,8 @@ void gpu_batch_init(void); void gpu_batch_exit(void); /* gpu_batch_presets.c */ +/* Only use by draw manager. Use the presets function instead for interface. */ +Gwn_Batch *gpu_batch_sphere(int lat_res, int lon_res) ATTR_WARN_UNUSED_RESULT; /* Replacement for gluSphere */ Gwn_Batch *GPU_batch_preset_sphere(int lod) ATTR_WARN_UNUSED_RESULT; Gwn_Batch *GPU_batch_preset_sphere_wire(int lod) ATTR_WARN_UNUSED_RESULT; diff --git a/source/blender/gpu/GPU_shader.h b/source/blender/gpu/GPU_shader.h index ca6e8343401..def0b0bfbc7 100644 --- a/source/blender/gpu/GPU_shader.h +++ b/source/blender/gpu/GPU_shader.h @@ -134,6 +134,7 @@ typedef enum GPUBuiltinShader { GPU_SHADER_2D_IMAGE_MASK_UNIFORM_COLOR, GPU_SHADER_3D_IMAGE_MODULATE_ALPHA, GPU_SHADER_3D_IMAGE_DEPTH, + GPU_SHADER_3D_IMAGE_DEPTH_COPY, /* stereo 3d */ GPU_SHADER_2D_IMAGE_INTERLACE, /* points */ diff --git a/source/blender/gpu/intern/gpu_batch_presets.c b/source/blender/gpu/intern/gpu_batch_presets.c index 9db04832a51..21d6906083a 100644 --- a/source/blender/gpu/intern/gpu_batch_presets.c +++ b/source/blender/gpu/intern/gpu_batch_presets.c @@ -31,6 +31,7 @@ #include "BLI_utildefines.h" #include "BLI_math.h" +#include "BLI_threads.h" #include "GPU_batch.h" #include "gpu_shader_private.h" @@ -71,7 +72,7 @@ static void batch_sphere_lat_lon_vert( } /* Replacement for gluSphere */ -static Gwn_Batch *batch_sphere(int lat_res, int lon_res) +Gwn_Batch *gpu_batch_sphere(int lat_res, int lon_res) { const float lon_inc = 2 * M_PI / lon_res; const float lat_inc = M_PI / lat_res; @@ -146,6 +147,7 @@ static Gwn_Batch *batch_sphere_wire(int lat_res, int lon_res) Gwn_Batch *GPU_batch_preset_sphere(int lod) { BLI_assert(lod >= 0 && lod <= 2); + BLI_assert(BLI_thread_is_main()); if (lod == 0) { return g_presets_3d.batch.sphere_low; @@ -161,6 +163,7 @@ Gwn_Batch *GPU_batch_preset_sphere(int lod) Gwn_Batch *GPU_batch_preset_sphere_wire(int lod) { BLI_assert(lod >= 0 && lod <= 1); + BLI_assert(BLI_thread_is_main()); if (lod == 0) { return g_presets_3d.batch.sphere_wire_low; @@ -182,9 +185,9 @@ void gpu_batch_presets_init(void) } /* Hard coded resolution */ - g_presets_3d.batch.sphere_low = batch_sphere(8, 16); - g_presets_3d.batch.sphere_med = batch_sphere(16, 10); - g_presets_3d.batch.sphere_high = batch_sphere(32, 24); + g_presets_3d.batch.sphere_low = gpu_batch_sphere(8, 16); + g_presets_3d.batch.sphere_med = gpu_batch_sphere(16, 10); + g_presets_3d.batch.sphere_high = gpu_batch_sphere(32, 24); g_presets_3d.batch.sphere_wire_low = batch_sphere_wire(6, 8); g_presets_3d.batch.sphere_wire_med = batch_sphere_wire(8, 16); diff --git a/source/blender/gpu/intern/gpu_shader.c b/source/blender/gpu/intern/gpu_shader.c index c25d03dff2f..b06ee56c21f 100644 --- a/source/blender/gpu/intern/gpu_shader.c +++ b/source/blender/gpu/intern/gpu_shader.c @@ -77,6 +77,7 @@ extern char datatoc_gpu_shader_image_interlace_frag_glsl[]; extern char datatoc_gpu_shader_image_mask_uniform_color_frag_glsl[]; extern char datatoc_gpu_shader_image_modulate_alpha_frag_glsl[]; extern char datatoc_gpu_shader_image_depth_linear_frag_glsl[]; +extern char datatoc_gpu_shader_image_depth_copy_frag_glsl[]; extern char datatoc_gpu_shader_3D_vert_glsl[]; extern char datatoc_gpu_shader_3D_normal_vert_glsl[]; extern char datatoc_gpu_shader_3D_flat_color_vert_glsl[]; @@ -712,6 +713,8 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader) datatoc_gpu_shader_image_modulate_alpha_frag_glsl }, [GPU_SHADER_3D_IMAGE_DEPTH] = { datatoc_gpu_shader_3D_image_vert_glsl, datatoc_gpu_shader_image_depth_linear_frag_glsl }, + [GPU_SHADER_3D_IMAGE_DEPTH_COPY] = { datatoc_gpu_shader_3D_image_vert_glsl, + datatoc_gpu_shader_image_depth_copy_frag_glsl }, [GPU_SHADER_2D_IMAGE_INTERLACE] = { datatoc_gpu_shader_2D_image_vert_glsl, datatoc_gpu_shader_image_interlace_frag_glsl }, diff --git a/source/blender/gpu/intern/gpu_viewport.c b/source/blender/gpu/intern/gpu_viewport.c index fc045805874..83b9a8f0b0e 100644 --- a/source/blender/gpu/intern/gpu_viewport.c +++ b/source/blender/gpu/intern/gpu_viewport.c @@ -345,6 +345,8 @@ void GPU_viewport_bind(GPUViewport *viewport, const rcti *rect) int rect_w = BLI_rcti_size_x(rect) + 1; int rect_h = BLI_rcti_size_y(rect) + 1; + DRW_opengl_context_enable(); + if (dfbl->default_fb) { if (rect_w != viewport->size[0] || rect_h != viewport->size[1] || U.ogl_multisamples != viewport->samples) { gpu_viewport_buffers_free( @@ -465,6 +467,7 @@ cleanup: if (!ok) { GPU_viewport_free(viewport); MEM_freeN(viewport); + DRW_opengl_context_disable(); return; } @@ -523,7 +526,11 @@ void GPU_viewport_unbind(GPUViewport *viewport) if (dfbl->default_fb) { GPU_framebuffer_texture_unbind(NULL, NULL); GPU_framebuffer_restore(); + } + DRW_opengl_context_disable(); + + if (dfbl->default_fb) { glEnable(GL_SCISSOR_TEST); glDisable(GL_DEPTH_TEST); } @@ -581,6 +588,7 @@ static void gpu_viewport_passes_free(PassList *psl, int psl_len) } } +/* Must be executed inside Drawmanager Opengl Context. */ void GPU_viewport_free(GPUViewport *viewport) { gpu_viewport_engines_data_free(viewport); diff --git a/source/blender/gpu/shaders/gpu_shader_image_depth_copy_frag.glsl b/source/blender/gpu/shaders/gpu_shader_image_depth_copy_frag.glsl new file mode 100644 index 00000000000..10f4dfd5a87 --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_image_depth_copy_frag.glsl @@ -0,0 +1,12 @@ + +in vec2 texCoord_interp; +out vec4 fragColor; + +uniform sampler2D image; + +void main() +{ + float depth = texture(image, texCoord_interp).r; + fragColor = vec4(depth); + gl_FragDepth = depth; +} diff --git a/source/blender/windowmanager/CMakeLists.txt b/source/blender/windowmanager/CMakeLists.txt index 0da45202730..234491a2186 100644 --- a/source/blender/windowmanager/CMakeLists.txt +++ b/source/blender/windowmanager/CMakeLists.txt @@ -35,6 +35,7 @@ set(INC ../compositor ../depsgraph ../editors/include + ../draw ../gpu ../imbuf ../makesdna diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index 4449736d2a5..bf894b2ad03 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -119,6 +119,11 @@ struct bScreen *WM_window_get_active_screen(const struct wmWindow *win) ATTR_NON void WM_window_set_active_screen(struct wmWindow *win, struct WorkSpace *workspace, struct bScreen *screen) ATTR_NONNULL(1); bool WM_window_is_temp_screen(const struct wmWindow *win) ATTR_WARN_UNUSED_RESULT; +void *WM_opengl_context_create(void); +void WM_opengl_context_dispose(void *context); +void WM_opengl_context_activate(void *context); +void WM_opengl_context_release(void *context); + /* defines for 'type' WM_window_open_temp */ enum { WM_WINDOW_RENDER = 1, diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c index 43e4f7757f5..a2f5f1b1e10 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -125,6 +125,8 @@ #include "DEG_depsgraph.h" +#include "DRW_engine.h" + #ifdef WITH_OPENSUBDIV # include "BKE_subsurf.h" #endif @@ -207,6 +209,7 @@ void WM_init(bContext *C, int argc, const char **argv) /* sets 3D mouse deadzone */ WM_ndof_deadzone_set(U.ndof_deadzone); #endif + DRW_opengl_context_create(); GPU_init(); @@ -549,6 +552,10 @@ void WM_exit_ext(bContext *C, const bool do_python) BLF_exit(); + if (!G.background) { + DRW_opengl_context_destroy(); + } + #ifdef WITH_INTERNATIONAL BLF_free_unifont(); BLF_free_unifont_mono(); diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index 103f8d580c1..278a70b9c9d 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -1038,6 +1038,26 @@ void wm_window_make_drawable(wmWindowManager *wm, wmWindow *win) } } +/* Reset active the current window opengl drawing context. */ +void wm_window_reset_drawable(void) +{ + BLI_assert(BLI_thread_is_main()); + wmWindowManager *wm = G.main->wm.first; + + if (wm == NULL) + return; + + wmWindow *win = wm->windrawable; + + if (win && win->ghostwin) { + gpu_batch_presets_reset(); + immDeactivate(); + GHOST_ActivateWindowDrawingContext(win->ghostwin); + GWN_context_active_set(win->gwnctx); + immActivate(); + } +} + /* called by ghost, here we handle events for windows themselves or send to event system */ /* mouse coordinate converversion happens here */ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr) @@ -2044,3 +2064,25 @@ void wm_window_IME_end(wmWindow *win) win->ime_data = NULL; } #endif /* WITH_INPUT_IME */ + +/* ****** direct opengl context management ****** */ + +void *WM_opengl_context_create(void) +{ + return GHOST_CreateOpenGLContext(g_system); +} + +void WM_opengl_context_dispose(void *context) +{ + GHOST_DisposeOpenGLContext(g_system, (GHOST_ContextHandle)context); +} + +void WM_opengl_context_activate(void *context) +{ + GHOST_ActivateOpenGLContext((GHOST_ContextHandle)context); +} + +void WM_opengl_context_release(void *context) +{ + GHOST_ReleaseOpenGLContext((GHOST_ContextHandle)context); +} diff --git a/source/blender/windowmanager/wm_window.h b/source/blender/windowmanager/wm_window.h index 0264955a4c5..652cefb1a54 100644 --- a/source/blender/windowmanager/wm_window.h +++ b/source/blender/windowmanager/wm_window.h @@ -58,6 +58,7 @@ void wm_window_process_events (const bContext *C); void wm_window_process_events_nosleep(void); void wm_window_make_drawable(wmWindowManager *wm, wmWindow *win); +void wm_window_reset_drawable(void); void wm_window_raise (wmWindow *win); void wm_window_lower (wmWindow *win); |