[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [55316] trunk/blender/source/blender: Fix: multisample viewport drawing didn't work well with selection or particle

Brecht Van Lommel brechtvanlommel at pandora.be
Fri Mar 15 20:56:34 CET 2013


Revision: 55316
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=55316
Author:   blendix
Date:     2013-03-15 19:56:33 +0000 (Fri, 15 Mar 2013)
Log Message:
-----------
Fix: multisample viewport drawing didn't work well with selection or particle
brushes, due to issues with color coded drawing or slow/buggy reading from such
a buffer on some systems.

In case multisample is enabled now, it uses an offscreen buffer for such drawing,
which is not multisampled and so should not cause issues. This does mean there is
some extra GPU memory usage when multisample is enabled, and we could optimize
triple buffer to work together here somehow to share buffers, but it's better than
having selection not working.

Modified Paths:
--------------
    trunk/blender/source/blender/blenloader/intern/readfile.c
    trunk/blender/source/blender/editors/include/ED_view3d.h
    trunk/blender/source/blender/editors/mesh/editface.c
    trunk/blender/source/blender/editors/physics/particle_edit.c
    trunk/blender/source/blender/editors/space_view3d/drawobject.c
    trunk/blender/source/blender/editors/space_view3d/space_view3d.c
    trunk/blender/source/blender/editors/space_view3d/view3d_draw.c
    trunk/blender/source/blender/gpu/GPU_extensions.h
    trunk/blender/source/blender/gpu/intern/gpu_extensions.c
    trunk/blender/source/blender/makesdna/DNA_view3d_types.h

Modified: trunk/blender/source/blender/blenloader/intern/readfile.c
===================================================================
--- trunk/blender/source/blender/blenloader/intern/readfile.c	2013-03-15 19:56:29 UTC (rev 55315)
+++ trunk/blender/source/blender/blenloader/intern/readfile.c	2013-03-15 19:56:33 UTC (rev 55316)
@@ -5917,6 +5917,7 @@
 			rv3d->clipbb = newdataadr(fd, rv3d->clipbb);
 			
 			rv3d->depths = NULL;
+			rv3d->gpuoffscreen = NULL;
 			rv3d->ri = NULL;
 			rv3d->render_engine = NULL;
 			rv3d->sms = NULL;

Modified: trunk/blender/source/blender/editors/include/ED_view3d.h
===================================================================
--- trunk/blender/source/blender/editors/include/ED_view3d.h	2013-03-15 19:56:29 UTC (rev 55315)
+++ trunk/blender/source/blender/editors/include/ED_view3d.h	2013-03-15 19:56:33 UTC (rev 55316)
@@ -260,6 +260,7 @@
 void view3d_operator_needs_opengl(const struct bContext *C);
 void view3d_region_operator_needs_opengl(struct wmWindow *win, struct ARegion *ar);
 bool view3d_get_view_aligned_coordinate(struct ARegion *ar, float fp[3], const int mval[2], const bool do_fallback);
+void view3d_opengl_read_pixels(struct ARegion *ar, int x, int y, int w, int h, int format, int type, void *data);
 void view3d_get_transformation(const struct ARegion *ar, struct RegionView3D *rv3d, struct Object *ob, struct bglMats *mats);
 
 /* XXX should move to BLI_math */

Modified: trunk/blender/source/blender/editors/mesh/editface.c
===================================================================
--- trunk/blender/source/blender/editors/mesh/editface.c	2013-03-15 19:56:29 UTC (rev 55315)
+++ trunk/blender/source/blender/editors/mesh/editface.c	2013-03-15 19:56:33 UTC (rev 55316)
@@ -570,7 +570,7 @@
 
 	ibuf = IMB_allocImBuf(sx, sy, 32, IB_rect);
 	rt = ibuf->rect;
-	glReadPixels(rect->xmin + vc->ar->winrct.xmin,  rect->ymin + vc->ar->winrct.ymin, sx, sy, GL_RGBA, GL_UNSIGNED_BYTE,  ibuf->rect);
+	view3d_opengl_read_pixels(vc->ar, rect->xmin, rect->ymin, sx, sy, GL_RGBA, GL_UNSIGNED_BYTE,  ibuf->rect);
 	if (ENDIAN_ORDER == B_ENDIAN) IMB_convert_rgba_to_abgr(ibuf);
 
 	a = sx * sy;

Modified: trunk/blender/source/blender/editors/physics/particle_edit.c
===================================================================
--- trunk/blender/source/blender/editors/physics/particle_edit.c	2013-03-15 19:56:29 UTC (rev 55315)
+++ trunk/blender/source/blender/editors/physics/particle_edit.c	2013-03-15 19:56:33 UTC (rev 55316)
@@ -430,15 +430,6 @@
 	gluProject(co[0], co[1], co[2], data->mats.modelview, data->mats.projection,
 	           (GLint *)data->mats.viewport, &ux, &uy, &uz);
 
-#if 0 /* works well but too slow on some systems [#23118] */
-	screen_co[0] += (short)data->vc.ar->winrct.xmin;
-	screen_co[1] += (short)data->vc.ar->winrct.ymin;
-
-	/* PE_set_view3d_data calls this. no need to call here */
-	/* view3d_validate_backbuf(&data->vc); */
-	glReadPixels(screen_co[0], screen_co[1], 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth);
-#else /* faster to use depths, these are calculated in PE_set_view3d_data */
-
 	/* check if screen_co is within bounds because brush_cut uses out of screen coords */
 	if (screen_co[0] >= 0 && screen_co[0] < vd->w && screen_co[1] >= 0 && screen_co[1] < vd->h) {
 		BLI_assert(vd && vd->depths);
@@ -447,7 +438,6 @@
 	}
 	else
 		return 0;
-#endif
 
 	if ((float)uz - 0.00001f > depth)
 		return 0;

Modified: trunk/blender/source/blender/editors/space_view3d/drawobject.c
===================================================================
--- trunk/blender/source/blender/editors/space_view3d/drawobject.c	2013-03-15 19:56:29 UTC (rev 55315)
+++ trunk/blender/source/blender/editors/space_view3d/drawobject.c	2013-03-15 19:56:33 UTC (rev 55316)
@@ -808,17 +808,6 @@
 		}
 		
 		for (vos = strings->first; vos; vos = vos->next) {
-			/* too slow, reading opengl info while drawing is very bad,
-			 * better to see if we can use the zbuffer while in pixel space - campbell */
-#if 0
-			if (v3d->zbuf && (vos->flag & V3D_CACHE_TEXT_ZBUF)) {
-				gluProject(vos->vec[0], vos->vec[1], vos->vec[2], mats.modelview, mats.projection, (GLint *)mats.viewport, &ux, &uy, &uz);
-				glReadPixels(ar->winrct.xmin + vos->mval[0] + vos->xoffs, ar->winrct.ymin + vos->mval[1], 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth);
-
-				if (uz > depth)
-					continue;
-			}
-#endif
 			if (vos->sco[0] != IS_CLIPPED) {
 				const char *str = (char *)(vos + 1);
 

Modified: trunk/blender/source/blender/editors/space_view3d/space_view3d.c
===================================================================
--- trunk/blender/source/blender/editors/space_view3d/space_view3d.c	2013-03-15 19:56:29 UTC (rev 55315)
+++ trunk/blender/source/blender/editors/space_view3d/space_view3d.c	2013-03-15 19:56:33 UTC (rev 55316)
@@ -53,6 +53,7 @@
 #include "ED_screen.h"
 #include "ED_object.h"
 
+#include "GPU_extensions.h"
 #include "GPU_material.h"
 
 #include "BIF_gl.h"
@@ -478,6 +479,11 @@
 		RE_engine_free(rv3d->render_engine);
 		rv3d->render_engine = NULL;
 	}
+
+	if (rv3d->gpuoffscreen) {
+		GPU_offscreen_free(rv3d->gpuoffscreen);
+		rv3d->gpuoffscreen = NULL;
+	}
 }
 
 static int view3d_ob_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event))
@@ -626,6 +632,10 @@
 		if (rv3d->sms) {
 			MEM_freeN(rv3d->sms);
 		}
+		if (rv3d->gpuoffscreen) {
+			GPU_offscreen_free(rv3d->gpuoffscreen);
+		}
+
 		MEM_freeN(rv3d);
 		ar->regiondata = NULL;
 	}
@@ -644,6 +654,7 @@
 			new->clipbb = MEM_dupallocN(rv3d->clipbb);
 		
 		new->depths = NULL;
+		new->gpuoffscreen = NULL;
 		new->ri = NULL;
 		new->render_engine = NULL;
 		new->gpd = NULL;

Modified: trunk/blender/source/blender/editors/space_view3d/view3d_draw.c
===================================================================
--- trunk/blender/source/blender/editors/space_view3d/view3d_draw.c	2013-03-15 19:56:29 UTC (rev 55315)
+++ trunk/blender/source/blender/editors/space_view3d/view3d_draw.c	2013-03-15 19:56:33 UTC (rev 55316)
@@ -1348,8 +1348,35 @@
 	if (multisample_enabled)
 		glDisable(GL_MULTISAMPLE_ARB);
 
-	glScissor(ar->winrct.xmin, ar->winrct.ymin, BLI_rcti_size_x(&ar->winrct), BLI_rcti_size_y(&ar->winrct));
+	if (U.ogl_multisamples != USER_MULTISAMPLE_NONE) {
+		/* for multisample we use an offscreen FBO. multisample drawing can fail
+		 * with color coded selection drawing, and reading back depths from such
+		 * a buffer can also cause a few seconds freeze on OS X / NVidia. */
+		int w = BLI_rcti_size_x(&ar->winrct);
+		int h = BLI_rcti_size_y(&ar->winrct);
+		char error[256];
 
+		if (rv3d->gpuoffscreen) {
+			if (GPU_offscreen_width(rv3d->gpuoffscreen) != w ||
+			    GPU_offscreen_height(rv3d->gpuoffscreen) != h) {
+				GPU_offscreen_free(rv3d->gpuoffscreen);
+				rv3d->gpuoffscreen = NULL;
+			}
+		}
+
+		if (!rv3d->gpuoffscreen) {
+			rv3d->gpuoffscreen = GPU_offscreen_create(w, h, error);
+
+			if (!rv3d->gpuoffscreen)
+				fprintf(stderr, "Failed to create offscreen selection buffer for multisample: %s\n", error);
+		}
+	}
+
+	if (rv3d->gpuoffscreen)
+		GPU_offscreen_bind(rv3d->gpuoffscreen);
+	else
+		glScissor(ar->winrct.xmin, ar->winrct.ymin, BLI_rcti_size_x(&ar->winrct), BLI_rcti_size_y(&ar->winrct));
+
 	glClearColor(0.0, 0.0, 0.0, 0.0); 
 	if (v3d->zbuf) {
 		glEnable(GL_DEPTH_TEST);
@@ -1367,9 +1394,13 @@
 	
 	if (base && (base->lay & v3d->lay))
 		draw_object_backbufsel(scene, v3d, rv3d, base->object);
+	
+	if (rv3d->gpuoffscreen)
+		GPU_offscreen_unbind(rv3d->gpuoffscreen);
+	else
+		ar->swap = 0; /* mark invalid backbuf for wm draw */
 
 	v3d->flag &= ~V3D_INVALID_BACKBUF;
-	ar->swap = 0; /* mark invalid backbuf for wm draw */
 
 	G.f &= ~G_BACKBUFSEL;
 	v3d->zbuf = FALSE;
@@ -1386,6 +1417,21 @@
 
 }
 
+void view3d_opengl_read_pixels(ARegion *ar, int x, int y, int w, int h, int format, int type, void *data)
+{
+	RegionView3D *rv3d = ar->regiondata;
+
+	if (rv3d->gpuoffscreen) {
+		GPU_offscreen_bind(rv3d->gpuoffscreen);
+		glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
+		glReadPixels(x, y, w, h, format, type, data);
+		GPU_offscreen_unbind(rv3d->gpuoffscreen);
+	}
+	else {
+		glReadPixels(ar->winrct.xmin + x, ar->winrct.ymin + y, w, h, format, type, data);
+	}
+}
+
 void view3d_validate_backbuf(ViewContext *vc)
 {
 	if (vc->v3d->flag & V3D_INVALID_BACKBUF)
@@ -1401,12 +1447,9 @@
 		return 0;
 	}
 
-	x += vc->ar->winrct.xmin;
-	y += vc->ar->winrct.ymin;
-	
 	view3d_validate_backbuf(vc);
 
-	glReadPixels(x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &col);
+	view3d_opengl_read_pixels(vc->ar, x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &col);
 	glReadBuffer(GL_BACK);
 	
 	if (ENDIAN_ORDER == B_ENDIAN) {
@@ -1437,8 +1480,8 @@
 
 	view3d_validate_backbuf(vc);
 
-	glReadPixels(vc->ar->winrct.xmin + xminc,
-	             vc->ar->winrct.ymin + yminc,
+	view3d_opengl_read_pixels(vc->ar,
+	             xminc, yminc,
 	             (xmaxc - xminc + 1),
 	             (ymaxc - yminc + 1),
 	             GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect);
@@ -2104,7 +2147,7 @@
 	}
 
 	if (d->damaged) {
-		glReadPixels(ar->winrct.xmin + d->x, ar->winrct.ymin + d->y, d->w, d->h, GL_DEPTH_COMPONENT, GL_FLOAT, d->depths);
+		view3d_opengl_read_pixels(ar, d->x, d->y, d->w, d->h, GL_DEPTH_COMPONENT, GL_FLOAT, d->depths);
 		glGetDoublev(GL_DEPTH_RANGE, d->depth_range);
 		d->damaged = FALSE;
 	}
@@ -2132,9 +2175,7 @@
 		}
 		
 		if (d->damaged) {
-			glReadPixels(ar->winrct.xmin, ar->winrct.ymin, d->w, d->h,
-			             GL_DEPTH_COMPONENT, GL_FLOAT, d->depths);
-			
+			view3d_opengl_read_pixels(ar, 0, 0, d->w, d->h, GL_DEPTH_COMPONENT, GL_FLOAT, d->depths);
 			glGetDoublev(GL_DEPTH_RANGE, d->depth_range);
 			
 			d->damaged = 0;

Modified: trunk/blender/source/blender/gpu/GPU_extensions.h
===================================================================
--- trunk/blender/source/blender/gpu/GPU_extensions.h	2013-03-15 19:56:29 UTC (rev 55315)
+++ trunk/blender/source/blender/gpu/GPU_extensions.h	2013-03-15 19:56:33 UTC (rev 55316)
@@ -157,6 +157,8 @@
 void GPU_offscreen_bind(GPUOffScreen *ofs);
 void GPU_offscreen_unbind(GPUOffScreen *ofs);
 void GPU_offscreen_read_pixels(GPUOffScreen *ofs, int type, void *pixels);
+int GPU_offscreen_width(GPUOffScreen *ofs);
+int GPU_offscreen_height(GPUOffScreen *ofs);
 
 /* GPU Shader
  * - only for fragment shaders now

Modified: trunk/blender/source/blender/gpu/intern/gpu_extensions.c
===================================================================

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list