Commit: a459ef2827f1bb9e6ce92b0946a7463061c9ac55
Author: Campbell Barton
Date:   Thu Mar 1 16:31:36 2018 +1100
Branches: blender2.8
https://developer.blender.org/rBa459ef2827f1bb9e6ce92b0946a7463061c9ac55

Fix T54190: Occlusion query select failed

By default select wasn't picking the nearest object,
this could have been fixed by not clearing the depth buffer,
but calling GPU_select_(begin/end) without the binded frame-buffer
caused issues for depth-picking. So move GPU_select begin/end to a
callback.

This also has the advantage that only needs to populate the engines once
to draw two passes.

Note that cycling through objects fails with occlusion queries still,
will fix shortly.

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

M       source/blender/draw/DRW_engine.h
M       source/blender/draw/intern/draw_manager.c
M       source/blender/editors/space_view3d/view3d_view.c

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

diff --git a/source/blender/draw/DRW_engine.h b/source/blender/draw/DRW_engine.h
index 9ed8f776f34..4043f39b46d 100644
--- a/source/blender/draw/DRW_engine.h
+++ b/source/blender/draw/DRW_engine.h
@@ -88,6 +88,11 @@ typedef struct DRWUpdateContext {
 void DRW_notify_view_update(const DRWUpdateContext *update_ctx);
 void DRW_notify_id_update(const DRWUpdateContext *update_ctx, struct ID *id);
 
+
+typedef enum eDRWSelectStage { DRW_SELECT_PASS_PRE = 1, DRW_SELECT_PASS_POST, 
} eDRWSelectStage;
+typedef bool (*DRW_SelectPassFn)(
+        eDRWSelectStage stage, void *user_data);
+
 void DRW_draw_view(const struct bContext *C);
 
 void DRW_draw_render_loop_ex(
@@ -108,7 +113,8 @@ void DRW_draw_render_loop_offscreen(
 void DRW_draw_select_loop(
         struct Depsgraph *depsgraph,
         struct ARegion *ar, struct View3D *v3d, const eObjectMode object_mode,
-        bool use_obedit_skip, bool use_nearest, const struct rcti *rect);
+        bool use_obedit_skip, bool use_nearest, const struct rcti *rect,
+        DRW_SelectPassFn select_pass_fn, void *select_pass_user_data);
 void DRW_draw_depth_loop(
         struct Depsgraph *depsgraph,
         struct ARegion *ar, struct View3D *v3d, const eObjectMode object_mode);
diff --git a/source/blender/draw/intern/draw_manager.c 
b/source/blender/draw/intern/draw_manager.c
index 62042a44434..037053399c7 100644
--- a/source/blender/draw/intern/draw_manager.c
+++ b/source/blender/draw/intern/draw_manager.c
@@ -1384,7 +1384,8 @@ void DRW_render_instance_buffer_finish(void)
 void DRW_draw_select_loop(
         struct Depsgraph *depsgraph,
         ARegion *ar, View3D *v3d, const eObjectMode object_mode,
-        bool UNUSED(use_obedit_skip), bool UNUSED(use_nearest), const rcti 
*rect)
+        bool UNUSED(use_obedit_skip), bool UNUSED(use_nearest), const rcti 
*rect,
+        DRW_SelectPassFn select_pass_fn, void *select_pass_user_data)
 {
        Scene *scene = DEG_get_evaluated_scene(depsgraph);
        RenderEngineType *engine_type = 
RE_engines_find(scene->view_render.engine_id);
@@ -1484,12 +1485,21 @@ void DRW_draw_select_loop(
        /* Start Drawing */
        DRW_state_reset();
        DRW_draw_callbacks_pre_scene();
-       drw_engines_draw_scene();
-       DRW_draw_callbacks_post_scene();
 
-#ifdef USE_GPU_SELECT
-       GPU_select_finalize();
-#endif
+       /* Only 1-2 passes. */
+       while (true) {
+               if (!select_pass_fn(DRW_SELECT_PASS_PRE, 
select_pass_user_data)) {
+                       break;
+               }
+
+               drw_engines_draw_scene();
+
+               if (!select_pass_fn(DRW_SELECT_PASS_POST, 
select_pass_user_data)) {
+                       break;
+               }
+       }
+
+       DRW_draw_callbacks_post_scene();
 
        DRW_state_reset();
        drw_engines_disable();
diff --git a/source/blender/editors/space_view3d/view3d_view.c 
b/source/blender/editors/space_view3d/view3d_view.c
index cb329e62e96..0afef34194c 100644
--- a/source/blender/editors/space_view3d/view3d_view.c
+++ b/source/blender/editors/space_view3d/view3d_view.c
@@ -861,6 +861,45 @@ void view3d_opengl_select_cache_end(void)
        GPU_select_cache_end();
 }
 
+#ifndef WITH_OPENGL_LEGACY
+struct DrawSelectLoopUserData {
+       uint  pass;
+       uint  hits;
+       uint *buffer;
+       uint  buffer_len;
+       const rcti *rect;
+       char gpu_select_mode;
+};
+
+static bool drw_select_loop_pass(eDRWSelectStage stage, void *user_data)
+{
+       bool continue_pass = false;
+       struct DrawSelectLoopUserData *data = user_data;
+       if (stage == DRW_SELECT_PASS_PRE) {
+               GPU_select_begin(data->buffer, data->buffer_len, data->rect, 
data->gpu_select_mode, data->hits);
+               /* always run POST after PRE. */
+               continue_pass = true;
+       }
+       else if (stage == DRW_SELECT_PASS_POST) {
+               int hits = GPU_select_end();
+               if (data->pass == 0) {
+                       /* quirk of GPU_select_end, only take hits value from 
first call. */
+                       data->hits = hits;
+               }
+               if (data->gpu_select_mode == GPU_SELECT_NEAREST_FIRST_PASS) {
+                       data->gpu_select_mode = GPU_SELECT_NEAREST_SECOND_PASS;
+                       continue_pass = true;
+               }
+               data->pass += 1;
+       }
+       else {
+               BLI_assert(0);
+       }
+       return continue_pass;
+
+}
+#endif /* WITH_OPENGL_LEGACY */
+
 /**
  * \warning be sure to account for a negative return value
  * This is an error, "Too many objects in select buffer"
@@ -950,43 +989,40 @@ int view3d_opengl_select(
        if (vc->rv3d->rflag & RV3D_CLIPPING)
                ED_view3d_clipping_set(vc->rv3d);
        
-       GPU_select_begin(buffer, bufsize, &rect, gpu_select_mode, 0);
 
 #ifdef WITH_OPENGL_LEGACY
        if (IS_VIEWPORT_LEGACY(vc->v3d)) {
+               GPU_select_begin(buffer, bufsize, &rect, gpu_select_mode, 0);
                ED_view3d_draw_select_loop(vc, scene, sl, v3d, ar, 
use_obedit_skip, use_nearest);
+               hits = GPU_select_end();
+
+               if (do_passes && (hits > 0)) {
+                       GPU_select_begin(buffer, bufsize, &rect, 
GPU_SELECT_NEAREST_SECOND_PASS, hits);
+                       ED_view3d_draw_select_loop(vc, scene, sl, v3d, ar, 
use_obedit_skip, use_nearest);
+                       GPU_select_end();
+               }
        }
        else
 #else
        {
+               /* We need to call "GPU_select_*" API's inside 
DRW_draw_select_loop
+                * because the OpenGL context created & destroyed inside this 
function. */
+               struct DrawSelectLoopUserData drw_select_loop_user_data = {
+                       .pass = 0,
+                       .hits = 0,
+                       .buffer = buffer,
+                       .buffer_len = bufsize,
+                       .rect = &rect,
+                       .gpu_select_mode = gpu_select_mode,
+               };
                DRW_draw_select_loop(
                        graph, ar, v3d, eval_ctx->object_mode,
-                       use_obedit_skip, use_nearest, &rect);
+                       use_obedit_skip, use_nearest, &rect,
+                       drw_select_loop_pass, &drw_select_loop_user_data);
+               hits = drw_select_loop_user_data.hits;
        }
 #endif /* WITH_OPENGL_LEGACY */
 
-       hits = GPU_select_end();
-       
-       /* second pass, to get the closest object to camera */
-       if (do_passes && (hits > 0)) {
-               GPU_select_begin(buffer, bufsize, &rect, 
GPU_SELECT_NEAREST_SECOND_PASS, hits);
-
-#ifdef WITH_OPENGL_LEGACY
-               if (IS_VIEWPORT_LEGACY(vc->v3d)) {
-                       ED_view3d_draw_select_loop(vc, scene, sl, v3d, ar, 
use_obedit_skip, use_nearest);
-               }
-               else
-#else
-               {
-                       DRW_draw_select_loop(
-                               graph, ar, v3d, eval_ctx->object_mode,
-                               use_obedit_skip, use_nearest, &rect);
-               }
-#endif /* WITH_OPENGL_LEGACY */
-
-               GPU_select_end();
-       }
-
        G.f &= ~G_PICKSEL;
        ED_view3d_draw_setup_view(vc->win, eval_ctx, scene, ar, v3d, 
vc->rv3d->viewmat, NULL, NULL);

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
https://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to