Possible fix for T62999: Crash when select in edit mode.
authormano-wii <germano.costa@ig.com.br>
Thu, 28 Mar 2019 17:17:00 +0000 (14:17 -0300)
committermano-wii <germano.costa@ig.com.br>
Thu, 28 Mar 2019 17:19:21 +0000 (14:19 -0300)
Apparently some drivers don't allow `glReadPixel` read out pixels of texture boundaries.
Intersect `rect` to avoid such cases.

source/blender/draw/intern/draw_manager.c
source/blender/gpu/GPU_select.h
source/blender/gpu/intern/gpu_select_pick.c

index 9dd6d08afcccfcd2fadad4001b9f7022bffe3b06..8a532ecdb7d85b006b5e2f82737279d6c4147a27 100644 (file)
@@ -59,6 +59,7 @@
 #include "GPU_uniformbuffer.h"
 #include "GPU_viewport.h"
 #include "GPU_matrix.h"
+#include "GPU_select.h"
 
 #include "IMB_colormanagement.h"
 
@@ -2547,8 +2548,23 @@ void DRW_framebuffer_select_id_release(ARegion *ar)
 /* Read a block of pixels from the select frame buffer. */
 void DRW_framebuffer_select_id_read(const rcti *rect, uint *r_buf)
 {
+       /* clamp rect by texture */
+       rcti r = {
+               .xmin = 0,
+               .xmax = GPU_texture_width(g_select_buffer.texture_u32),
+               .ymin = 0,
+               .ymax = GPU_texture_height(g_select_buffer.texture_u32),
+       };
+
+       rcti rect_clamp = *rect;
+       BLI_rcti_isect(&r, rect, &rect_clamp);
+
        GPU_texture_read_rect(
-               g_select_buffer.texture_u32, GPU_DATA_UNSIGNED_INT, rect, r_buf);
+               g_select_buffer.texture_u32, GPU_DATA_UNSIGNED_INT, &rect_clamp, r_buf);
+
+       if (!BLI_rcti_compare(rect, &rect_clamp)) {
+               GPU_select_buffer_stride_realign(rect, &rect_clamp, r_buf);
+       }
 }
 
 /** \} */
index e1396b49c151f09a7c74d2a68353c7f3725f536d..b9dbeeccf3048f3ddb022649d758b31cc97f64c1 100644 (file)
@@ -52,5 +52,6 @@ void GPU_select_cache_end(void);
 
 /* utilities */
 const uint *GPU_select_buffer_near(const uint *buffer, int hits);
+void GPU_select_buffer_stride_realign(const struct rcti *src, const struct rcti *dst, uint *r_buf);
 
 #endif
index 22388deccdb5e39fe6526f82b3ba625b0c83ed7a..bfd2f3c1ee79aa4f6e7b2f99ef4dba05c4711834 100644 (file)
@@ -90,6 +90,30 @@ static void rect_subregion_stride_calc(const rcti *src, const rcti *dst, SubRect
        r_sub->skip     = (uint)(src_x - dst_x);
 }
 
+void GPU_select_buffer_stride_realign(
+        const rcti *src, const rcti *dst, uint *r_buf)
+{
+       SubRectStride sub;
+       rect_subregion_stride_calc(src, dst, &sub);
+
+       int last_px_written = sub.span * sub.span_len - 1;
+       int last_px_id = sub.start + last_px_written + (sub.span_len - 1) * sub.skip;
+
+       while (sub.span_len--) {
+               int i;
+               for (i = sub.span; i--;) {
+                       r_buf[last_px_id--] = r_buf[last_px_written--];
+               }
+               if (last_px_written < 0) {
+                       break;
+               }
+               for (i = sub.skip; i--;) {
+                       r_buf[last_px_id--] = 0u;
+               }
+       }
+       memset(r_buf, 0, (last_px_id + 1) * sizeof(*r_buf));
+}
+
 /**
  * Ignore depth clearing as a change,
  * only check if its been changed _and_ filled in (ignore clearing since XRAY does this).