diff options
author | Daniel Dunbar <daniel@zuster.org> | 2005-03-08 22:27:58 +0300 |
---|---|---|
committer | Daniel Dunbar <daniel@zuster.org> | 2005-03-08 22:27:58 +0300 |
commit | 593687000663c3a2cf533f42537e0ecc4e87614a (patch) | |
tree | 41ee0af3df9fd2b45df5482f48bf4d295c643b81 /source/blender/src/glutil.c | |
parent | af092210dbda8a8712d4c307e7425470015fe8c5 (diff) |
Bug fix #2296
- Background image would jitter around on ATI card when zoomed in too
far. It appears that the driver is was multiplying the image width
by the zoom factor at some point and clamping this number, before
clipping the visible image. Somehow this then fed back in to clipping
the zoom factor.
Fix is to only tell GL to draw the smallest number of pixels (width
and height) that would be visible on the screen. Since this is not
a generally bad thing to do applied fix for all users of
glaDrawPixelsSafe.
Diffstat (limited to 'source/blender/src/glutil.c')
-rw-r--r-- | source/blender/src/glutil.c | 93 |
1 files changed, 49 insertions, 44 deletions
diff --git a/source/blender/src/glutil.c b/source/blender/src/glutil.c index c64b07ae4af..5c0f1a7be89 100644 --- a/source/blender/src/glutil.c +++ b/source/blender/src/glutil.c @@ -286,55 +286,60 @@ void glaDrawPixelsTex(float x, float y, int img_w, int img_h, void *rect) void glaDrawPixelsSafe(float x, float y, int img_w, int img_h, void *rect) { unsigned char *uc_rect= (unsigned char*) rect; - float origin_x= 0.375; - float origin_y= 0.375; - /* Trivial case */ - if (x>=origin_x && y>=origin_y) { - glRasterPos2f(x, y); - glDrawPixels(img_w, img_h, GL_RGBA, GL_UNSIGNED_BYTE, uc_rect); - } else { - int old_row_length= glaGetOneInteger(GL_UNPACK_ROW_LENGTH); - float xzoom= glaGetOneFloat(GL_ZOOM_X); - float yzoom= glaGetOneFloat(GL_ZOOM_Y); + float xzoom= glaGetOneFloat(GL_ZOOM_X); + float yzoom= glaGetOneFloat(GL_ZOOM_Y); - /* The pixel space coordinate of the intersection of - * the [zoomed] image with the origin. - */ - float ix= (origin_x-x)/xzoom; - float iy= (origin_y-y)/yzoom; + /* The pixel space coordinate of the intersection of + * the [zoomed] image with the origin. + */ + float ix= -x/xzoom; + float iy= -y/yzoom; - /* The maximum pixel amounts the image can cropped - * without exceeding the origin. - */ - int off_x= floor((ix>origin_x)?ix:origin_x); - int off_y= floor((iy>origin_y)?iy:origin_y); - - /* The zoomed space coordinate of the raster - * position. - */ - float rast_x= x + off_x*xzoom; - float rast_y= y + off_y*yzoom; - - /* We cannot zoom in larger than window size. - * Let's assume that window size is 4 pixels minimum (ton) - */ - if(xzoom>4.0 || yzoom>4.0) { - GLfloat scissor[4]; - glGetFloatv(GL_SCISSOR_BOX, scissor); - - if( scissor[2] <= xzoom && scissor[3] <= floor(yzoom) ) { - printf("GL error; Zoomed in too far\n"); - return; - } - } + /* The maximum pixel amounts the image can be cropped + * at the lower left without exceeding the origin. + */ + int off_x= floor(max(ix, 0)); + int off_y= floor(max(iy, 0)); - if (off_x<img_w && off_y<img_h) { - glaRasterPosSafe2f(rast_x, rast_y, origin_x, origin_y); - glPixelStorei(GL_UNPACK_ROW_LENGTH, img_w); - glDrawPixels(img_w-off_x, img_h-off_y, GL_RGBA, GL_UNSIGNED_BYTE, uc_rect+off_y*img_w*4+off_x*4); - glPixelStorei(GL_UNPACK_ROW_LENGTH, old_row_length); + /* The zoomed space coordinate of the raster position + * (starting at the lower left most unclipped pixel). + */ + float rast_x= x + off_x*xzoom; + float rast_y= y + off_y*yzoom; + + GLfloat scissor[4]; + int draw_w, draw_h; + + /* Determine the smallest number of pixels we need to draw + * before the image would go off the upper right corner. + * + * It may seem this is just an optimization but some graphics + * cards (ATI) freak out if there is a large zoom factor and + * a large number of pixels off the screen (probably at some + * level the number of image pixels to draw is getting multiplied + * by the zoom and then clamped). Making sure we draw the + * fewest pixels possible keeps everyone mostly happy (still + * fails if we zoom in on one really huge pixel so that it + * covers the entire screen). + */ + glGetFloatv(GL_SCISSOR_BOX, scissor); + draw_w = min(img_w-off_x, ceil((scissor[2]-rast_x)/xzoom)); + draw_h = min(img_h-off_y, ceil((scissor[3]-rast_y)/yzoom)); + + if (draw_w>0 && draw_h>0) { + int old_row_length = glaGetOneInteger(GL_UNPACK_ROW_LENGTH); + + /* Don't use safe RasterPos (slower) if we can avoid it. */ + if (rast_x>=0 && rast_y>=0) { + glRasterPos2f(rast_x, rast_y); + } else { + glaRasterPosSafe2f(rast_x, rast_y, 0, 0); } + + glPixelStorei(GL_UNPACK_ROW_LENGTH, img_w); + glDrawPixels(draw_w, draw_h, GL_RGBA, GL_UNSIGNED_BYTE, uc_rect + (off_y*img_w + off_x)*4); + glPixelStorei(GL_UNPACK_ROW_LENGTH, old_row_length); } } |