diff options
author | Cian Jinks <cjinks99@gmail.com> | 2021-09-22 17:09:31 +0300 |
---|---|---|
committer | Cian Jinks <cjinks99@gmail.com> | 2021-09-22 17:09:31 +0300 |
commit | e734491048ef2436af41e272b8900f20785ecbe6 (patch) | |
tree | 8cee3fc068c782c0ba8cb9a581e768968c565569 /source/blender/draw/engines/external/external_engine.c | |
parent | f21cd0881948f6eaf16af0b354cd904df7407bda (diff) | |
parent | 204b01a254ac2445fea217e5211b2ed6aef631ca (diff) |
Merge branch 'master' into soc-2021-knife-toolssoc-2021-knife-tools
Diffstat (limited to 'source/blender/draw/engines/external/external_engine.c')
-rw-r--r-- | source/blender/draw/engines/external/external_engine.c | 202 |
1 files changed, 193 insertions, 9 deletions
diff --git a/source/blender/draw/engines/external/external_engine.c b/source/blender/draw/engines/external/external_engine.c index 89ee3f1b293..cc548a53a8e 100644 --- a/source/blender/draw/engines/external/external_engine.c +++ b/source/blender/draw/engines/external/external_engine.c @@ -32,13 +32,19 @@ #include "BKE_object.h" #include "BKE_particle.h" +#include "ED_image.h" #include "ED_screen.h" +#include "GPU_batch.h" +#include "GPU_debug.h" #include "GPU_matrix.h" #include "GPU_shader.h" #include "GPU_state.h" #include "GPU_viewport.h" +#include "RE_engine.h" +#include "RE_pipeline.h" + #include "external_engine.h" /* own include */ /* Shaders */ @@ -137,6 +143,22 @@ static void external_engine_init(void *vedata) } } +/* Add shading group call which will take care of writing to the depth buffer, so that the + * alpha-under overlay will happen for the render buffer. */ +static void external_cache_image_add(DRWShadingGroup *grp) +{ + float obmat[4][4]; + unit_m4(obmat); + scale_m4_fl(obmat, 0.5f); + + /* NOTE: Use the same Z-depth value as in the regular image drawing engine. */ + translate_m4(obmat, 1.0f, 1.0f, 0.75f); + + GPUBatch *geom = DRW_cache_quad_get(); + + DRW_shgroup_call_obmat(grp, geom, obmat); +} + static void external_cache_init(void *vedata) { EXTERNAL_PassList *psl = ((EXTERNAL_Data *)vedata)->psl; @@ -162,14 +184,33 @@ static void external_cache_init(void *vedata) stl->g_data->depth_shgrp = DRW_shgroup_create(e_data.depth_sh, psl->depth_pass); } - /* Do not draw depth pass when overlays are turned off. */ - stl->g_data->need_depth = (v3d->flag2 & V3D_HIDE_OVERLAYS) == 0; + if (v3d != NULL) { + /* Do not draw depth pass when overlays are turned off. */ + stl->g_data->need_depth = (v3d->flag2 & V3D_HIDE_OVERLAYS) == 0; + } + else if (draw_ctx->space_data != NULL) { + const eSpace_Type space_type = draw_ctx->space_data->spacetype; + if (space_type == SPACE_IMAGE) { + external_cache_image_add(stl->g_data->depth_shgrp); + + stl->g_data->need_depth = true; + stl->g_data->update_depth = true; + } + } } static void external_cache_populate(void *vedata, Object *ob) { + const DRWContextState *draw_ctx = DRW_context_state_get(); EXTERNAL_StorageList *stl = ((EXTERNAL_Data *)vedata)->stl; + if (draw_ctx->space_data != NULL) { + const eSpace_Type space_type = draw_ctx->space_data->spacetype; + if (space_type == SPACE_IMAGE) { + return; + } + } + if (!(DRW_object_is_renderable(ob) && DRW_object_visibility_in_active_context(ob) & OB_VISIBLE_SELF)) { return; @@ -210,13 +251,11 @@ static void external_cache_finish(void *UNUSED(vedata)) { } -static void external_draw_scene_do(void *vedata) +static void external_draw_scene_do_v3d(void *vedata) { const DRWContextState *draw_ctx = DRW_context_state_get(); - Scene *scene = draw_ctx->scene; RegionView3D *rv3d = draw_ctx->rv3d; ARegion *region = draw_ctx->region; - const RenderEngineType *type; DRW_state_reset_ex(DRW_STATE_DEFAULT & ~DRW_STATE_DEPTH_LESS_EQUAL); @@ -229,8 +268,6 @@ static void external_draw_scene_do(void *vedata) } RenderEngine *engine = RE_engine_create(engine_type); - engine->tile_x = scene->r.tilex; - engine->tile_y = scene->r.tiley; engine_type->view_update(engine, draw_ctx->evil_C, draw_ctx->depsgraph); rv3d->render_engine = engine; } @@ -241,7 +278,7 @@ static void external_draw_scene_do(void *vedata) ED_region_pixelspace(region); /* Render result draw. */ - type = rv3d->render_engine->type; + const RenderEngineType *type = rv3d->render_engine->type; type->view_draw(rv3d->render_engine, draw_ctx->evil_C, draw_ctx->depsgraph); GPU_bgl_end(); @@ -259,6 +296,116 @@ static void external_draw_scene_do(void *vedata) } } +/* Configure current matrix stack so that the external engine can use the same drawing code for + * both viewport and image editor drawing. + * + * The engine draws result in the pixel space, and is applying render offset. For image editor we + * need to switch from normalized space to pixel space, and "un-apply" offset. */ +static void external_image_space_matrix_set(const RenderEngine *engine) +{ + BLI_assert(engine != NULL); + + const DRWContextState *draw_ctx = DRW_context_state_get(); + const DRWView *view = DRW_view_get_active(); + struct SpaceImage *space_image = (struct SpaceImage *)draw_ctx->space_data; + + /* Apply current view as transformation matrix. + * This will configure drawing for normalized space with current zoom and pan applied. */ + + float view_matrix[4][4]; + DRW_view_viewmat_get(view, view_matrix, false); + + float projection_matrix[4][4]; + DRW_view_winmat_get(view, projection_matrix, false); + + GPU_matrix_projection_set(projection_matrix); + GPU_matrix_set(view_matrix); + + /* Switch from normalized space to pixel space. */ + { + int width, height; + ED_space_image_get_size(space_image, &width, &height); + + const float width_inv = width ? 1.0f / width : 0.0f; + const float height_inv = height ? 1.0f / height : 0.0f; + GPU_matrix_scale_2f(width_inv, height_inv); + } + + /* Un-apply render offset. */ + { + Render *render = engine->re; + rctf view_rect; + rcti render_rect; + RE_GetViewPlane(render, &view_rect, &render_rect); + + GPU_matrix_translate_2f(-render_rect.xmin, -render_rect.ymin); + } +} + +static void external_draw_scene_do_image(void *UNUSED(vedata)) +{ + const DRWContextState *draw_ctx = DRW_context_state_get(); + Scene *scene = draw_ctx->scene; + Render *re = RE_GetSceneRender(scene); + RenderEngine *engine = RE_engine_get(re); + + /* Is tested before enabling the drawing engine. */ + BLI_assert(re != NULL); + BLI_assert(engine != NULL); + + const DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); + + /* Clear the depth buffer to the value used by the background overlay so that the overlay is not + * happening outside of the drawn image. + * + * NOTE: The external engine only draws color. The depth is taken care of using the depth pass + * which initialized the depth to the values expected by the background overlay. */ + GPU_framebuffer_clear_depth(dfbl->default_fb, 1.0f); + + GPU_matrix_push_projection(); + GPU_matrix_push(); + + external_image_space_matrix_set(engine); + + GPU_debug_group_begin("External Engine"); + + const RenderEngineType *engine_type = engine->type; + BLI_assert(engine_type != NULL); + BLI_assert(engine_type->draw != NULL); + + engine_type->draw(engine, draw_ctx->evil_C, draw_ctx->depsgraph); + + GPU_debug_group_end(); + + GPU_matrix_pop(); + GPU_matrix_pop_projection(); + + DRW_state_reset(); + GPU_bgl_end(); + + RE_engine_draw_release(re); +} + +static void external_draw_scene_do(void *vedata) +{ + const DRWContextState *draw_ctx = DRW_context_state_get(); + + if (draw_ctx->v3d != NULL) { + external_draw_scene_do_v3d(vedata); + return; + } + + if (draw_ctx->space_data == NULL) { + return; + } + + const eSpace_Type space_type = draw_ctx->space_data->spacetype; + if (space_type == SPACE_IMAGE) { + external_draw_scene_do_image(vedata); + return; + } +} + static void external_draw_scene(void *vedata) { const DRWContextState *draw_ctx = DRW_context_state_get(); @@ -297,7 +444,7 @@ static void external_engine_free(void) static const DrawEngineDataSize external_data_size = DRW_VIEWPORT_DATA_SIZE(EXTERNAL_Data); -static DrawEngineType draw_engine_external_type = { +DrawEngineType draw_engine_external_type = { NULL, NULL, N_("External"), @@ -330,8 +477,45 @@ RenderEngineType DRW_engine_viewport_external_type = { NULL, NULL, NULL, + NULL, + NULL, &draw_engine_external_type, {NULL, NULL, NULL}, }; +bool DRW_engine_external_acquire_for_image_editor(void) +{ + const DRWContextState *draw_ctx = DRW_context_state_get(); + const SpaceLink *space_data = draw_ctx->space_data; + Scene *scene = draw_ctx->scene; + + if (space_data == NULL) { + return false; + } + + const eSpace_Type space_type = draw_ctx->space_data->spacetype; + if (space_type != SPACE_IMAGE) { + return false; + } + + struct SpaceImage *space_image = (struct SpaceImage *)space_data; + const Image *image = ED_space_image(space_image); + if (image == NULL || image->type != IMA_TYPE_R_RESULT) { + return false; + } + + if (image->render_slot != image->last_render_slot) { + return false; + } + + /* Render is allocated on main thread, so it is safe to access it from here. */ + Render *re = RE_GetSceneRender(scene); + + if (re == NULL) { + return false; + } + + return RE_engine_draw_acquire(re); +} + #undef EXTERNAL_ENGINE |