Fix buffer read error w/ 2 pass select queries

Also don't do second pass when the first has no hits.
This commit is contained in:
Campbell Barton 2017-06-14 17:03:49 +10:00
parent f02e04f133
commit 2462320210
4 changed files with 19 additions and 9 deletions

View File

@ -1191,7 +1191,7 @@ int view3d_opengl_select(
hits = GPU_select_end();
/* second pass, to get the closest object to camera */
if (do_passes) {
if (do_passes && (hits > 0)) {
GPU_select_begin(buffer, bufsize, &rect, GPU_SELECT_NEAREST_SECOND_PASS, hits);
ED_view3d_draw_select_loop(vc, scene, v3d, ar, use_obedit_skip, use_nearest);

View File

@ -1755,7 +1755,7 @@ static int manipulator_selectbuf(Scene *scene, ScrArea *sa, ARegion *ar, const i
hits = GPU_select_end();
if (do_passes) {
if (do_passes && (hits > 0)) {
GPU_select_begin(buffer, 64, &rect, GPU_SELECT_NEAREST_SECOND_PASS, hits);
/* do the drawing */

View File

@ -75,6 +75,12 @@ static GPUSelectState g_select_state = {0};
*/
void GPU_select_begin(unsigned int *buffer, unsigned int bufsize, const rcti *input, char mode, int oldhits)
{
if (mode == GPU_SELECT_NEAREST_SECOND_PASS) {
/* In the case hits was '-1', don't start the second pass since it's not going to give useful results.
* As well as buffer overflow in 'gpu_select_query_load_id'. */
BLI_assert(oldhits != -1);
}
g_select_state.select_is_active = true;
g_select_state.use_gpu_select = GPU_select_query_check_active();
g_select_state.mode = mode;

View File

@ -142,13 +142,17 @@ bool gpu_select_query_load_id(unsigned int id)
g_query_state.active_query++;
g_query_state.query_issued = true;
if (g_query_state.mode == GPU_SELECT_NEAREST_SECOND_PASS && g_query_state.index < g_query_state.oldhits) {
if (g_query_state.buffer[g_query_state.index][3] == id) {
g_query_state.index++;
return true;
}
else {
return false;
if (g_query_state.mode == GPU_SELECT_NEAREST_SECOND_PASS) {
/* Second pass should never run if first pass fails, can read past 'bufsize' in this case. */
BLI_assert(g_query_state.oldhits != -1);
if (g_query_state.index < g_query_state.oldhits) {
if (g_query_state.buffer[g_query_state.index][3] == id) {
g_query_state.index++;
return true;
}
else {
return false;
}
}
}