From 0ec320783ec5867cc9c29fff9a09a4d8f1b7fbdf Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 21 Oct 2010 07:38:09 +0000 Subject: fix [#24339] Auto Depth, makes viewport lag. The problem is the opensource nvidia nouveau drivers are slow running glReadPixels(), was hanging on memcpy(). However for autodepth its not needed to update the entire 3D view depths, so added view3d_update_depths_rect() to get the depths for a smaller area. --- source/blender/editors/include/ED_view3d.h | 1 + source/blender/editors/space_view3d/view3d_draw.c | 68 ++++++++++++ source/blender/editors/space_view3d/view3d_edit.c | 117 +++++---------------- .../blender/editors/space_view3d/view3d_intern.h | 2 + 4 files changed, 96 insertions(+), 92 deletions(-) (limited to 'source') diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h index f5a84aa4c19..fe024be29e0 100644 --- a/source/blender/editors/include/ED_view3d.h +++ b/source/blender/editors/include/ED_view3d.h @@ -63,6 +63,7 @@ typedef struct ViewContext { typedef struct ViewDepths { unsigned short w, h; + short x, y; /* only for temp use for sub-rects, added to ar->winx/y */ float *depths; double depth_range[2]; diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 1d18f484ae0..7722ca5605b 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -1569,7 +1569,51 @@ static void draw_dupli_objects(Scene *scene, ARegion *ar, View3D *v3d, Base *bas draw_dupli_objects_color(scene, ar, v3d, base, color); } +void view3d_update_depths_rect(ARegion *ar, ViewDepths *d, rcti *rect) +{ + int x, y, w, h; + /* clamp rect by area */ + + /* Constrain rect to depth bounds */ + if (rect->xmin < 0) rect->xmin = 0; + if (rect->ymin < 0) rect->ymin = 0; + if (rect->xmax >= ar->winx) rect->xmax = ar->winx-1; + if (rect->ymax >= ar->winy) rect->ymax = ar->winy-1; + + /* assign values to compare with the ViewDepths */ + x= ar->winrct.xmin + rect->xmin; + y= ar->winrct.ymin + rect->ymin; + + w= rect->xmax - rect->xmin; + h= rect->ymax - rect->ymin; + + if( d->w != w || + d->h != h || + d->x != x || + d->y != y || + d->depths==NULL + ) { + d->x= x; + d->y= y; + d->w= w; + d->h= h; + + if(d->depths) + MEM_freeN(d->depths); + + d->depths= MEM_mallocN(sizeof(float)*d->w*d->h,"View depths Subset"); + + d->damaged= 1; + } + 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); + glGetDoublev(GL_DEPTH_RANGE,d->depth_range); + d->damaged= 0; + } +} + +/* note, with nouveau drivers the glReadPixels() is very slow. [#24339] */ void view3d_update_depths(ARegion *ar) { RegionView3D *rv3d= ar->regiondata; @@ -1600,6 +1644,30 @@ void view3d_update_depths(ARegion *ar) } } +/* utility function to find the closest Z value, use for autodepth */ +float view3d_depth_near(ViewDepths *d) +{ + /* convert to float for comparisons */ + const float near= (float)d->depth_range[0]; + const float far_real= (float)d->depth_range[1]; + float far= far_real; + + const float *depths= d->depths; + float depth= FLT_MAX; + int i= d->w * d->h; + + /* far is both the starting 'far' value + * and the closest value found. */ + while(i--) { + depth= *depths++; + if((depth < far) && (depth > near)) { + far= depth; + } + } + + return far == far_real ? FLT_MAX : far; +} + void draw_depth_gpencil(Scene *scene, ARegion *ar, View3D *v3d) { short zbuf= v3d->zbuf; diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index dc75efcc5ca..a5cca6341f6 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -63,6 +63,7 @@ #include "ED_screen.h" #include "ED_transform.h" #include "ED_mesh.h" +#include "ED_view3d.h" #include "PIL_time.h" /* smoothview */ @@ -1667,10 +1668,8 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op) /* ZBuffer depth vars */ bglMats mats; - float depth, depth_close= FLT_MAX; - int had_depth = 0; + float depth_close= FLT_MAX; double cent[2], p[3]; - int xs, ys; /* note; otherwise opengl won't work */ view3d_operator_needs_opengl(C); @@ -1684,38 +1683,19 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op) /* Get Z Depths, needed for perspective, nice for ortho */ bgl_get_mats(&mats); draw_depth(scene, ar, v3d, NULL); + + { + /* avoid allocating the whole depth buffer */ + ViewDepths depth_temp= {0}; - /* force updating */ - if (rv3d->depths) { - had_depth = 1; - rv3d->depths->damaged = 1; - } - - view3d_update_depths(ar); - - /* Constrain rect to depth bounds */ - if (rect.xmin < 0) rect.xmin = 0; - if (rect.ymin < 0) rect.ymin = 0; - if (rect.xmax >= rv3d->depths->w) rect.xmax = rv3d->depths->w-1; - if (rect.ymax >= rv3d->depths->h) rect.ymax = rv3d->depths->h-1; - - /* Find the closest Z pixel */ - for (xs=rect.xmin; xs < rect.xmax; xs++) { - for (ys=rect.ymin; ys < rect.ymax; ys++) { - depth= rv3d->depths->depths[ys*rv3d->depths->w+xs]; - if(depth < rv3d->depths->depth_range[1] && depth > rv3d->depths->depth_range[0]) { - if (depth_close > depth) { - depth_close = depth; - } - } - } - } - - if (had_depth==0) { - MEM_freeN(rv3d->depths->depths); - rv3d->depths->depths = NULL; + /* avoid view3d_update_depths() for speed. */ + view3d_update_depths_rect(ar, &depth_temp, &rect); + + /* find the closest Z pixel */ + depth_close= view3d_depth_near(&depth_temp); + + MEM_freeN(depth_temp.depths); } - rv3d->depths->damaged = 1; cent[0] = (((double)rect.xmin)+((double)rect.xmax)) / 2; cent[1] = (((double)rect.ymin)+((double)rect.ymax)) / 2; @@ -2574,88 +2554,49 @@ void VIEW3D_OT_enable_manipulator(wmOperatorType *ot) static float view_autodist_depth_margin(ARegion *ar, short *mval, int margin) { - RegionView3D *rv3d= ar->regiondata; - float depth= FLT_MAX; + ViewDepths depth_temp= {0}; + rcti rect; + float depth_close; if(margin==0) { - if (mval[0] < 0) return 0; - if (mval[1] < 0) return 0; - if (mval[0] >= rv3d->depths->w) return 0; - if (mval[1] >= rv3d->depths->h) return 0; - /* Get Z Depths, needed for perspective, nice for ortho */ - depth= rv3d->depths->depths[mval[1]*rv3d->depths->w+mval[0]]; - if(depth >= rv3d->depths->depth_range[1] || depth <= rv3d->depths->depth_range[0]) { - depth= FLT_MAX; - } + rect.xmin= mval[0]; + rect.ymin= mval[1]; + rect.xmax= mval[0] + 1; + rect.ymax= mval[1] + 1; } else { - rcti rect; - float depth_close= FLT_MAX; - int xs, ys; - rect.xmax = mval[0] + margin; rect.ymax = mval[1] + margin; rect.xmin = mval[0] - margin; rect.ymin = mval[1] - margin; + } - /* Constrain rect to depth bounds */ - if (rect.xmin < 0) rect.xmin = 0; - if (rect.ymin < 0) rect.ymin = 0; - if (rect.xmax >= rv3d->depths->w) rect.xmax = rv3d->depths->w-1; - if (rect.ymax >= rv3d->depths->h) rect.ymax = rv3d->depths->h-1; - - /* Find the closest Z pixel */ - for (xs=rect.xmin; xs < rect.xmax; xs++) { - for (ys=rect.ymin; ys < rect.ymax; ys++) { - depth= rv3d->depths->depths[ys*rv3d->depths->w+xs]; - if(depth < rv3d->depths->depth_range[1] && depth > rv3d->depths->depth_range[0]) { - if (depth_close > depth) { - depth_close = depth; - } - } - } - } + view3d_update_depths_rect(ar, &depth_temp, &rect); + depth_close= view3d_depth_near(&depth_temp); - depth= depth_close; - } + MEM_freeN(depth_temp.depths); - return depth; + return depth_close; } /* XXX todo Zooms in on a border drawn by the user */ int view_autodist(Scene *scene, ARegion *ar, View3D *v3d, short *mval, float mouse_worldloc[3] ) //, float *autodist ) { - RegionView3D *rv3d= ar->regiondata; bglMats mats; /* ZBuffer depth vars */ float depth_close= FLT_MAX; - int had_depth = 0; double cent[2], p[3]; /* Get Z Depths, needed for perspective, nice for ortho */ bgl_get_mats(&mats); draw_depth(scene, ar, v3d, NULL); - /* force updating */ - if (rv3d->depths) { - had_depth = 1; - rv3d->depths->damaged = 1; - } - - view3d_update_depths(ar); - depth_close= view_autodist_depth_margin(ar, mval, 4); if (depth_close==FLT_MAX) return 0; - if (had_depth==0) { - MEM_freeN(rv3d->depths->depths); - rv3d->depths->depths = NULL; - } - rv3d->depths->damaged = 1; - cent[0] = (double)mval[0]; cent[1] = (double)mval[1]; @@ -2670,8 +2611,6 @@ int view_autodist(Scene *scene, ARegion *ar, View3D *v3d, short *mval, float mou int view_autodist_init(Scene *scene, ARegion *ar, View3D *v3d, int mode) //, float *autodist ) { - RegionView3D *rv3d= ar->regiondata; - /* Get Z Depths, needed for perspective, nice for ortho */ switch(mode) { case 0: @@ -2682,12 +2621,6 @@ int view_autodist_init(Scene *scene, ARegion *ar, View3D *v3d, int mode) //, flo break; } - /* force updating */ - if (rv3d->depths) { - rv3d->depths->damaged = 1; - } - - view3d_update_depths(ar); return 1; } diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h index d6d8fddd442..e81d0b87589 100644 --- a/source/blender/editors/space_view3d/view3d_intern.h +++ b/source/blender/editors/space_view3d/view3d_intern.h @@ -131,6 +131,8 @@ void add_view3d_after(ListBase *lb, Base *base, int flag); void circf(float x, float y, float rad); void circ(float x, float y, float rad); void view3d_update_depths(struct ARegion *ar); +void view3d_update_depths_rect(struct ARegion *ar, struct ViewDepths *d, struct rcti *rect); +float view3d_depth_near(struct ViewDepths *d); /* view3d_select.c */ void VIEW3D_OT_select(struct wmOperatorType *ot); -- cgit v1.2.3