Changeset View
Changeset View
Standalone View
Standalone View
source/blender/draw/intern/draw_manager.c
| Show First 20 Lines • Show All 1,035 Lines • ▼ Show 20 Lines | void DRW_notify_view_update(const DRWUpdateContext *update_ctx) | ||||
| RenderEngineType *engine_type = update_ctx->engine_type; | RenderEngineType *engine_type = update_ctx->engine_type; | ||||
| ARegion *ar = update_ctx->ar; | ARegion *ar = update_ctx->ar; | ||||
| View3D *v3d = update_ctx->v3d; | View3D *v3d = update_ctx->v3d; | ||||
| RegionView3D *rv3d = ar->regiondata; | RegionView3D *rv3d = ar->regiondata; | ||||
| Depsgraph *depsgraph = update_ctx->depsgraph; | Depsgraph *depsgraph = update_ctx->depsgraph; | ||||
| Scene *scene = update_ctx->scene; | Scene *scene = update_ctx->scene; | ||||
| ViewLayer *view_layer = update_ctx->view_layer; | ViewLayer *view_layer = update_ctx->view_layer; | ||||
| if (rv3d->viewport == NULL) { | /* Separate update for each stereo view. */ | ||||
| return; | for (int view = 0; view < 2; view++) { | ||||
| GPUViewport *viewport = WM_draw_region_get_viewport(ar, view); | |||||
| if (!viewport) { | |||||
| continue; | |||||
| } | } | ||||
| /* XXX Really nasty locking. But else this could | /* XXX Really nasty locking. But else this could | ||||
| * be executed by the material previews thread | * be executed by the material previews thread | ||||
| * while rendering a viewport. */ | * while rendering a viewport. */ | ||||
| BLI_mutex_lock(&DST.ogl_context_mutex); | BLI_mutex_lock(&DST.ogl_context_mutex); | ||||
| /* Reset before using it. */ | /* Reset before using it. */ | ||||
| drw_state_prepare_clean_for_draw(&DST); | drw_state_prepare_clean_for_draw(&DST); | ||||
| DST.viewport = rv3d->viewport; | DST.viewport = viewport; | ||||
| DST.draw_ctx = (DRWContextState){ | DST.draw_ctx = (DRWContextState){ | ||||
| .ar = ar, .rv3d = rv3d, .v3d = v3d, | .ar = ar, .rv3d = rv3d, .v3d = v3d, | ||||
| .scene = scene, .view_layer = view_layer, .obact = OBACT(view_layer), | .scene = scene, .view_layer = view_layer, .obact = OBACT(view_layer), | ||||
| .engine_type = engine_type, | .engine_type = engine_type, | ||||
| .depsgraph = depsgraph, .object_mode = OB_MODE_OBJECT, | .depsgraph = depsgraph, .object_mode = OB_MODE_OBJECT, | ||||
| }; | }; | ||||
| drw_engines_enable(view_layer, engine_type); | drw_engines_enable(view_layer, engine_type); | ||||
| for (LinkData *link = DST.enabled_engines.first; link; link = link->next) { | for (LinkData *link = DST.enabled_engines.first; link; link = link->next) { | ||||
| DrawEngineType *draw_engine = link->data; | DrawEngineType *draw_engine = link->data; | ||||
| ViewportEngineData *data = drw_viewport_engine_data_ensure(draw_engine); | ViewportEngineData *data = drw_viewport_engine_data_ensure(draw_engine); | ||||
| if (draw_engine->view_update) { | if (draw_engine->view_update) { | ||||
| draw_engine->view_update(data); | draw_engine->view_update(data); | ||||
| } | } | ||||
| } | } | ||||
| DST.viewport = NULL; | DST.viewport = NULL; | ||||
| drw_engines_disable(); | drw_engines_disable(); | ||||
| BLI_mutex_unlock(&DST.ogl_context_mutex); | BLI_mutex_unlock(&DST.ogl_context_mutex); | ||||
| } | } | ||||
| } | |||||
| /** \} */ | /** \} */ | ||||
| /** \name ID Update | /** \name ID Update | ||||
| * \{ */ | * \{ */ | ||||
| /* TODO(sergey): This code is run for each changed ID (including the ones which | /* TODO(sergey): This code is run for each changed ID (including the ones which | ||||
| * are changed indirectly via update flush. Need to find a way to make this to | * are changed indirectly via update flush. Need to find a way to make this to | ||||
| * run really fast, hopefully without any memory allocations on a heap | * run really fast, hopefully without any memory allocations on a heap | ||||
| * Idea here could be to run every known engine's id_update() and make them | * Idea here could be to run every known engine's id_update() and make them | ||||
| * do nothing if there is no engine-specific data yet. | * do nothing if there is no engine-specific data yet. | ||||
| */ | */ | ||||
| void DRW_notify_id_update(const DRWUpdateContext *update_ctx, ID *id) | void DRW_notify_id_update(const DRWUpdateContext *update_ctx, ID *id) | ||||
| { | { | ||||
| RenderEngineType *engine_type = update_ctx->engine_type; | RenderEngineType *engine_type = update_ctx->engine_type; | ||||
| ARegion *ar = update_ctx->ar; | ARegion *ar = update_ctx->ar; | ||||
| View3D *v3d = update_ctx->v3d; | View3D *v3d = update_ctx->v3d; | ||||
| RegionView3D *rv3d = ar->regiondata; | RegionView3D *rv3d = ar->regiondata; | ||||
| Depsgraph *depsgraph = update_ctx->depsgraph; | Depsgraph *depsgraph = update_ctx->depsgraph; | ||||
| Scene *scene = update_ctx->scene; | Scene *scene = update_ctx->scene; | ||||
| ViewLayer *view_layer = update_ctx->view_layer; | ViewLayer *view_layer = update_ctx->view_layer; | ||||
| if (rv3d->viewport == NULL) { | |||||
| return; | /* Separate update for each stereo view. */ | ||||
| for (int view = 0; view < 2; view++) { | |||||
| GPUViewport *viewport = WM_draw_region_get_viewport(ar, view); | |||||
| if (!viewport) { | |||||
| continue; | |||||
| } | } | ||||
| /* Reset before using it. */ | /* Reset before using it. */ | ||||
| drw_state_prepare_clean_for_draw(&DST); | drw_state_prepare_clean_for_draw(&DST); | ||||
| DST.viewport = rv3d->viewport; | DST.viewport = viewport; | ||||
| DST.draw_ctx = (DRWContextState){ | DST.draw_ctx = (DRWContextState){ | ||||
| .ar = ar, .rv3d = rv3d, .v3d = v3d, | .ar = ar, .rv3d = rv3d, .v3d = v3d, | ||||
| .scene = scene, .view_layer = view_layer, .obact = OBACT(view_layer), | .scene = scene, .view_layer = view_layer, .obact = OBACT(view_layer), | ||||
| .engine_type = engine_type, | .engine_type = engine_type, | ||||
| .depsgraph = depsgraph, .object_mode = OB_MODE_OBJECT, | .depsgraph = depsgraph, .object_mode = OB_MODE_OBJECT, | ||||
| }; | }; | ||||
| drw_engines_enable(view_layer, engine_type); | drw_engines_enable(view_layer, engine_type); | ||||
| for (LinkData *link = DST.enabled_engines.first; link; link = link->next) { | for (LinkData *link = DST.enabled_engines.first; link; link = link->next) { | ||||
| DrawEngineType *draw_engine = link->data; | DrawEngineType *draw_engine = link->data; | ||||
| ViewportEngineData *data = drw_viewport_engine_data_ensure(draw_engine); | ViewportEngineData *data = drw_viewport_engine_data_ensure(draw_engine); | ||||
| if (draw_engine->id_update) { | if (draw_engine->id_update) { | ||||
| draw_engine->id_update(data, id); | draw_engine->id_update(data, id); | ||||
| } | } | ||||
| } | } | ||||
| DST.viewport = NULL; | DST.viewport = NULL; | ||||
| drw_engines_disable(); | drw_engines_disable(); | ||||
| } | } | ||||
| } | |||||
| /** \} */ | /** \} */ | ||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||
| /** \name Main Draw Loops (DRW_draw) | /** \name Main Draw Loops (DRW_draw) | ||||
| * \{ */ | * \{ */ | ||||
| /* Everything starts here. | /* Everything starts here. | ||||
| * This function takes care of calling all cache and rendering functions | * This function takes care of calling all cache and rendering functions | ||||
| * for each relevant engine / mode engine. */ | * for each relevant engine / mode engine. */ | ||||
| void DRW_draw_view(const bContext *C) | void DRW_draw_view(const bContext *C) | ||||
| { | { | ||||
| Depsgraph *depsgraph = CTX_data_depsgraph(C); | Depsgraph *depsgraph = CTX_data_depsgraph(C); | ||||
| ARegion *ar = CTX_wm_region(C); | ARegion *ar = CTX_wm_region(C); | ||||
| View3D *v3d = CTX_wm_view3d(C); | View3D *v3d = CTX_wm_view3d(C); | ||||
| Scene *scene = DEG_get_evaluated_scene(depsgraph); | Scene *scene = DEG_get_evaluated_scene(depsgraph); | ||||
| RenderEngineType *engine_type = ED_view3d_engine_type(scene, v3d->drawtype); | RenderEngineType *engine_type = ED_view3d_engine_type(scene, v3d->drawtype); | ||||
| GPUViewport *viewport = WM_draw_region_get_bound_viewport(ar); | |||||
| /* Reset before using it. */ | /* Reset before using it. */ | ||||
| drw_state_prepare_clean_for_draw(&DST); | drw_state_prepare_clean_for_draw(&DST); | ||||
| DRW_draw_render_loop_ex(depsgraph, engine_type, ar, v3d, C); | DRW_draw_render_loop_ex(depsgraph, engine_type, ar, v3d, viewport, C); | ||||
| } | } | ||||
| /** | /** | ||||
| * Used for both regular and off-screen drawing. | * Used for both regular and off-screen drawing. | ||||
| * Need to reset DST before calling this function | * Need to reset DST before calling this function | ||||
| */ | */ | ||||
| void DRW_draw_render_loop_ex( | void DRW_draw_render_loop_ex( | ||||
| struct Depsgraph *depsgraph, | struct Depsgraph *depsgraph, | ||||
| RenderEngineType *engine_type, | RenderEngineType *engine_type, | ||||
| ARegion *ar, View3D *v3d, | ARegion *ar, View3D *v3d, | ||||
| GPUViewport *viewport, | |||||
| const bContext *evil_C) | const bContext *evil_C) | ||||
| { | { | ||||
| Scene *scene = DEG_get_evaluated_scene(depsgraph); | Scene *scene = DEG_get_evaluated_scene(depsgraph); | ||||
| ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph); | ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph); | ||||
| RegionView3D *rv3d = ar->regiondata; | RegionView3D *rv3d = ar->regiondata; | ||||
| DST.draw_ctx.evil_C = evil_C; | DST.draw_ctx.evil_C = evil_C; | ||||
| DST.viewport = rv3d->viewport; | DST.viewport = viewport; | ||||
| v3d->zbuf = true; | v3d->zbuf = true; | ||||
| /* Setup viewport */ | /* Setup viewport */ | ||||
| GPU_viewport_engines_data_validate(DST.viewport, DRW_engines_get_hash()); | GPU_viewport_engines_data_validate(DST.viewport, DRW_engines_get_hash()); | ||||
| DST.draw_ctx = (DRWContextState){ | DST.draw_ctx = (DRWContextState){ | ||||
| .ar = ar, .rv3d = rv3d, .v3d = v3d, | .ar = ar, .rv3d = rv3d, .v3d = v3d, | ||||
| .scene = scene, .view_layer = view_layer, .obact = OBACT(view_layer), | .scene = scene, .view_layer = view_layer, .obact = OBACT(view_layer), | ||||
| ▲ Show 20 Lines • Show All 118 Lines • ▼ Show 20 Lines | |||||
| #ifdef DEBUG | #ifdef DEBUG | ||||
| /* Avoid accidental reuse. */ | /* Avoid accidental reuse. */ | ||||
| drw_state_ensure_not_reused(&DST); | drw_state_ensure_not_reused(&DST); | ||||
| #endif | #endif | ||||
| } | } | ||||
| void DRW_draw_render_loop( | void DRW_draw_render_loop( | ||||
| struct Depsgraph *depsgraph, | struct Depsgraph *depsgraph, | ||||
| ARegion *ar, View3D *v3d) | ARegion *ar, View3D *v3d, | ||||
| GPUViewport *viewport) | |||||
| { | { | ||||
| /* Reset before using it. */ | /* Reset before using it. */ | ||||
| drw_state_prepare_clean_for_draw(&DST); | drw_state_prepare_clean_for_draw(&DST); | ||||
| Scene *scene = DEG_get_evaluated_scene(depsgraph); | Scene *scene = DEG_get_evaluated_scene(depsgraph); | ||||
| RenderEngineType *engine_type = ED_view3d_engine_type(scene, v3d->drawtype); | RenderEngineType *engine_type = ED_view3d_engine_type(scene, v3d->drawtype); | ||||
| DRW_draw_render_loop_ex(depsgraph, engine_type, ar, v3d, NULL); | DRW_draw_render_loop_ex(depsgraph, engine_type, ar, v3d, viewport, NULL); | ||||
| } | } | ||||
| /* @viewport CAN be NULL, in this case we create one. */ | /* @viewport CAN be NULL, in this case we create one. */ | ||||
| void DRW_draw_render_loop_offscreen( | void DRW_draw_render_loop_offscreen( | ||||
| struct Depsgraph *depsgraph, RenderEngineType *engine_type, | struct Depsgraph *depsgraph, RenderEngineType *engine_type, | ||||
| ARegion *ar, View3D *v3d, | ARegion *ar, View3D *v3d, | ||||
| const bool draw_background, GPUOffScreen *ofs, | const bool draw_background, GPUOffScreen *ofs, | ||||
| GPUViewport *viewport) | GPUViewport *viewport) | ||||
| { | { | ||||
| RegionView3D *rv3d = ar->regiondata; | /* Create temporary viewport if needed. */ | ||||
| GPUViewport *render_viewport = viewport; | |||||
| /* backup */ | |||||
| void *backup_viewport = rv3d->viewport; | |||||
| { | |||||
| /* backup (_never_ use rv3d->viewport) */ | |||||
| if (viewport == NULL) { | if (viewport == NULL) { | ||||
| rv3d->viewport = GPU_viewport_create_from_offscreen(ofs); | render_viewport = GPU_viewport_create_from_offscreen(ofs); | ||||
| } | |||||
| else { | |||||
| rv3d->viewport = viewport; | |||||
| } | |||||
| } | } | ||||
| GPU_framebuffer_restore(); | GPU_framebuffer_restore(); | ||||
| /* Reset before using it. */ | /* Reset before using it. */ | ||||
| drw_state_prepare_clean_for_draw(&DST); | drw_state_prepare_clean_for_draw(&DST); | ||||
| DST.options.is_image_render = true; | DST.options.is_image_render = true; | ||||
| DST.options.draw_background = draw_background; | DST.options.draw_background = draw_background; | ||||
| DRW_draw_render_loop_ex(depsgraph, engine_type, ar, v3d, NULL); | DRW_draw_render_loop_ex(depsgraph, engine_type, ar, v3d, render_viewport, NULL); | ||||
| /* restore */ | /* Free temporary viewport. */ | ||||
| { | |||||
| if (viewport == NULL) { | if (viewport == NULL) { | ||||
| /* don't free data owned by 'ofs' */ | /* don't free data owned by 'ofs' */ | ||||
| GPU_viewport_clear_from_offscreen(rv3d->viewport); | GPU_viewport_clear_from_offscreen(render_viewport); | ||||
| GPU_viewport_free(rv3d->viewport); | GPU_viewport_free(render_viewport); | ||||
| } | |||||
| rv3d->viewport = backup_viewport; | |||||
| } | } | ||||
| /* we need to re-bind (annoying!) */ | /* we need to re-bind (annoying!) */ | ||||
| GPU_offscreen_bind(ofs, false); | GPU_offscreen_bind(ofs, false); | ||||
| } | } | ||||
| void DRW_render_to_image(RenderEngine *engine, struct Depsgraph *depsgraph) | void DRW_render_to_image(RenderEngine *engine, struct Depsgraph *depsgraph) | ||||
| { | { | ||||
| ▲ Show 20 Lines • Show All 153 Lines • ▼ Show 20 Lines | |||||
| #ifndef USE_GPU_SELECT | #ifndef USE_GPU_SELECT | ||||
| UNUSED_VARS(vc, scene, view_layer, v3d, ar, rect); | UNUSED_VARS(vc, scene, view_layer, v3d, ar, rect); | ||||
| #else | #else | ||||
| RegionView3D *rv3d = ar->regiondata; | RegionView3D *rv3d = ar->regiondata; | ||||
| /* Reset before using it. */ | /* Reset before using it. */ | ||||
| drw_state_prepare_clean_for_draw(&DST); | drw_state_prepare_clean_for_draw(&DST); | ||||
| /* backup (_never_ use rv3d->viewport) */ | |||||
| void *backup_viewport = rv3d->viewport; | |||||
| rv3d->viewport = NULL; | |||||
| bool use_obedit = false; | bool use_obedit = false; | ||||
| int obedit_mode = 0; | int obedit_mode = 0; | ||||
| if (obedit != NULL) { | if (obedit != NULL) { | ||||
| if (obedit->type == OB_MBALL) { | if (obedit->type == OB_MBALL) { | ||||
| use_obedit = true; | use_obedit = true; | ||||
| obedit_mode = CTX_MODE_EDIT_METABALL; | obedit_mode = CTX_MODE_EDIT_METABALL; | ||||
| } | } | ||||
| else if (obedit->type == OB_ARMATURE) { | else if (obedit->type == OB_ARMATURE) { | ||||
| ▲ Show 20 Lines • Show All 110 Lines • ▼ Show 20 Lines | |||||
| #ifdef DEBUG | #ifdef DEBUG | ||||
| /* Avoid accidental reuse. */ | /* Avoid accidental reuse. */ | ||||
| drw_state_ensure_not_reused(&DST); | drw_state_ensure_not_reused(&DST); | ||||
| #endif | #endif | ||||
| GPU_framebuffer_restore(); | GPU_framebuffer_restore(); | ||||
| /* Cleanup for selection state */ | /* Cleanup for selection state */ | ||||
| GPU_viewport_free(viewport); | GPU_viewport_free(viewport); | ||||
| /* restore */ | |||||
| rv3d->viewport = backup_viewport; | |||||
| #endif /* USE_GPU_SELECT */ | #endif /* USE_GPU_SELECT */ | ||||
| } | } | ||||
| static void draw_depth_texture_to_screen(GPUTexture *texture) | static void draw_depth_texture_to_screen(GPUTexture *texture) | ||||
| { | { | ||||
| const float w = (float)GPU_texture_width(texture); | const float w = (float)GPU_texture_width(texture); | ||||
| const float h = (float)GPU_texture_height(texture); | const float h = (float)GPU_texture_height(texture); | ||||
| Show All 37 Lines | |||||
| { | { | ||||
| Scene *scene = DEG_get_evaluated_scene(depsgraph); | Scene *scene = DEG_get_evaluated_scene(depsgraph); | ||||
| RenderEngineType *engine_type = ED_view3d_engine_type(scene, v3d->drawtype); | RenderEngineType *engine_type = ED_view3d_engine_type(scene, v3d->drawtype); | ||||
| ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph); | ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph); | ||||
| RegionView3D *rv3d = ar->regiondata; | RegionView3D *rv3d = ar->regiondata; | ||||
| DRW_opengl_context_enable(); | DRW_opengl_context_enable(); | ||||
| /* backup (_never_ use rv3d->viewport) */ | |||||
| void *backup_viewport = rv3d->viewport; | |||||
| rv3d->viewport = NULL; | |||||
| /* Reset before using it. */ | /* Reset before using it. */ | ||||
| drw_state_prepare_clean_for_draw(&DST); | drw_state_prepare_clean_for_draw(&DST); | ||||
| struct GPUViewport *viewport = GPU_viewport_create(); | struct GPUViewport *viewport = GPU_viewport_create(); | ||||
| GPU_viewport_size_set(viewport, (const int[2]){ar->winx, ar->winy}); | GPU_viewport_size_set(viewport, (const int[2]){ar->winx, ar->winy}); | ||||
| /* Setup framebuffer */ | /* Setup framebuffer */ | ||||
| draw_select_framebuffer_setup(&ar->winrct); | draw_select_framebuffer_setup(&ar->winrct); | ||||
| ▲ Show 20 Lines • Show All 80 Lines • ▼ Show 20 Lines | #endif | ||||
| glEnable(GL_DEPTH_TEST); /* Cannot write to depth buffer without testing */ | glEnable(GL_DEPTH_TEST); /* Cannot write to depth buffer without testing */ | ||||
| glDepthFunc(GL_ALWAYS); | glDepthFunc(GL_ALWAYS); | ||||
| draw_depth_texture_to_screen(g_select_buffer.texture_depth); | draw_depth_texture_to_screen(g_select_buffer.texture_depth); | ||||
| glDepthFunc(GL_LEQUAL); | glDepthFunc(GL_LEQUAL); | ||||
| gpuPopMatrix(); | gpuPopMatrix(); | ||||
| gpuPopProjectionMatrix(); | gpuPopProjectionMatrix(); | ||||
| /* restore */ | |||||
| rv3d->viewport = backup_viewport; | |||||
| } | } | ||||
| /** \} */ | /** \} */ | ||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||
| /** \name Draw Manager State (DRW_state) | /** \name Draw Manager State (DRW_state) | ||||
| ▲ Show 20 Lines • Show All 314 Lines • Show Last 20 Lines | |||||