From 4aea628194876b2790ff38d928dc0eaa0a91b4be Mon Sep 17 00:00:00 2001 From: Keith Whitwell Date: Thu, 23 Feb 2006 14:23:50 +0000 Subject: [PATCH] Fix clipping for copypixel --- src/mesa/drivers/dri/i915/intel_pixel.c | 88 +++++++++-- src/mesa/drivers/dri/i915/intel_pixel.h | 11 ++ src/mesa/drivers/dri/i915/intel_pixel_copy.c | 155 ++++++++++++++----- 3 files changed, 201 insertions(+), 53 deletions(-) diff --git a/src/mesa/drivers/dri/i915/intel_pixel.c b/src/mesa/drivers/dri/i915/intel_pixel.c index e38c6be576b..e80ecd4412d 100644 --- a/src/mesa/drivers/dri/i915/intel_pixel.c +++ b/src/mesa/drivers/dri/i915/intel_pixel.c @@ -1,6 +1,7 @@ #include "swrast/swrast.h" #include "intel_context.h" #include "intel_pixel.h" +#include "intel_regions.h" @@ -115,23 +116,84 @@ GLboolean intel_clip_to_framebuffer( GLcontext *ctx, +GLboolean intel_clip_to_drawable( GLcontext *ctx, + const __DRIdrawablePrivate *dPriv, + GLint *x, GLint *y, + GLsizei *width, GLsizei *height ) +{ + /* left clipping */ + if (*x < dPriv->x) { + *width -= (dPriv->x - *x); + *x = dPriv->x; + } + + /* right clipping */ + if (*x + *width > dPriv->x + dPriv->w) + *width -= (*x + *width) - (dPriv->x + dPriv->w); + + if (*width <= 0) + return GL_FALSE; + + /* bottom clipping */ + if (*y < dPriv->y) { + *height -= (dPriv->y - *y); + *y = dPriv->y; + } + + /* top clipping */ + if (*y + *height > dPriv->y + dPriv->h) + *height -= (*y + *height) - (dPriv->y + dPriv->w); + + if (*height <= 0) + return GL_FALSE; + + return GL_TRUE; +} + + +GLboolean intel_clip_to_region( GLcontext *ctx, + const struct intel_region *region, + GLint *x, GLint *y, + GLsizei *width, GLsizei *height ) +{ + /* left clipping */ + if (*x < 0) { + *width -= (0 - *x); + *x = 0; + } + + /* right clipping */ + if (*x + *width > region->pitch) + *width -= (*x + *width) - region->pitch; + + if (*width <= 0) + return GL_FALSE; + + /* bottom clipping */ + if (*y < 0) { + *height -= (0 - *y); + *y = 0; + } + + /* top clipping */ + if (*y + *height > region->height) + *height -= (*y + *height) - region->height; + + if (*height <= 0) + return GL_FALSE; + + return GL_TRUE; +} + + + void intelInitPixelFuncs( struct dd_function_table *functions ) { - /* Pixel path fallbacks. - */ functions->Accum = _swrast_Accum; functions->Bitmap = _swrast_Bitmap; - - if (getenv("INTEL_NO_BLITS") == 0) { - functions->CopyPixels = intelCopyPixels; - functions->ReadPixels = intelReadPixels; - functions->DrawPixels = intelDrawPixels; - } - else { - functions->CopyPixels = _swrast_CopyPixels; - functions->ReadPixels = _swrast_ReadPixels; - functions->DrawPixels = _swrast_DrawPixels; - } + functions->CopyPixels = intelCopyPixels; + functions->ReadPixels = intelReadPixels; + functions->DrawPixels = intelDrawPixels; } diff --git a/src/mesa/drivers/dri/i915/intel_pixel.h b/src/mesa/drivers/dri/i915/intel_pixel.h index de101d7f297..c24ca08a22e 100644 --- a/src/mesa/drivers/dri/i915/intel_pixel.h +++ b/src/mesa/drivers/dri/i915/intel_pixel.h @@ -39,6 +39,17 @@ GLboolean intel_clip_to_framebuffer( GLcontext *ctx, GLint *x, GLint *y, GLsizei *width, GLsizei *height ); +GLboolean intel_clip_to_drawable( GLcontext *ctx, + const __DRIdrawablePrivate *dPriv, + GLint *x, GLint *y, + GLsizei *width, GLsizei *height ); + +GLboolean intel_clip_to_region( GLcontext *ctx, + const struct intel_region *region, + GLint *x, GLint *y, + GLsizei *width, GLsizei *height ); + + void intelReadPixels( GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, diff --git a/src/mesa/drivers/dri/i915/intel_pixel_copy.c b/src/mesa/drivers/dri/i915/intel_pixel_copy.c index 4f4f7fbaa6b..8743902dc58 100644 --- a/src/mesa/drivers/dri/i915/intel_pixel_copy.c +++ b/src/mesa/drivers/dri/i915/intel_pixel_copy.c @@ -41,49 +41,17 @@ #include "bufmgr.h" - - -static GLboolean do_texture_copypixels( GLcontext *ctx, - GLint srcx, GLint srcy, - GLsizei width, GLsizei height, - GLint dstx, GLint dsty, - GLenum type ) +static struct intel_region *copypix_src_region( struct intel_context *intel, + GLenum type ) { - return GL_FALSE; -} - - -/** - * CopyPixels with the blitter. Don't support zooming, pixel transfer, etc. - */ -static GLboolean do_blit_copypixels( GLcontext *ctx, - GLint srcx, GLint srcy, - GLsizei width, GLsizei height, - GLint dstx, GLint dsty, - GLenum type ) -{ - struct intel_context *intel = intel_context( ctx ); - struct intel_region *dst = intel_drawbuf_region( intel ); - struct intel_region *src = NULL; - - /* Copypixels can be more than a straight copy. Ensure all the - * extra operations are disabled: - */ - if (!intel_check_color_per_fragment_ops(ctx) || - ctx->Pixel.ZoomX != 1.0F || - ctx->Pixel.ZoomY != 1.0F) - return GL_FALSE; - switch (type) { case GL_COLOR: - src = intel_readbuf_region( intel ); - break; + return intel_readbuf_region( intel ); case GL_DEPTH: /* Don't think this is really possible execpt at 16bpp, when we have no stencil. */ if (intel->intelScreen->cpp == 2) - src = intel->depth_region; - break; + return intel->depth_region; case GL_STENCIL: /* Don't think this is really possible. */ @@ -91,15 +59,24 @@ static GLboolean do_blit_copypixels( GLcontext *ctx, case GL_DEPTH_STENCIL_EXT: /* Does it matter whether it is stencil/depth or depth/stencil? */ - src = intel->depth_region; - break; + return intel->depth_region; default: break; } - if (!src || !dst) - return GL_FALSE; + return NULL; +} +static GLboolean do_texture_copypixels( GLcontext *ctx, + GLint srcx, GLint srcy, + GLsizei width, GLsizei height, + GLint dstx, GLint dsty, + GLenum type ) +{ +#if 0 + struct intel_context *intel = intel_context( ctx ); + struct intel_region *dst = intel_drawbuf_region( intel ); + struct intel_region *src = copypix_src_region(intel); intelFlush( &intel->ctx ); @@ -171,6 +148,104 @@ static GLboolean do_blit_copypixels( GLcontext *ctx, intel_batchbuffer_flush( intel->batch ); UNLOCK_HARDWARE( intel ); return GL_TRUE; +#endif + + return GL_FALSE; +} + + + + + +/** + * CopyPixels with the blitter. Don't support zooming, pixel transfer, etc. + */ +static GLboolean do_blit_copypixels( GLcontext *ctx, + GLint srcx, GLint srcy, + GLsizei width, GLsizei height, + GLint dstx, GLint dsty, + GLenum type ) +{ + struct intel_context *intel = intel_context( ctx ); + struct intel_region *dst = intel_drawbuf_region( intel ); + struct intel_region *src = copypix_src_region( intel, type ); + + /* Copypixels can be more than a straight copy. Ensure all the + * extra operations are disabled: + */ + if (!intel_check_color_per_fragment_ops(ctx) || + ctx->Pixel.ZoomX != 1.0F || + ctx->Pixel.ZoomY != 1.0F) + return GL_FALSE; + + if (!src || !dst) + return GL_FALSE; + + + + intelFlush( &intel->ctx ); + LOCK_HARDWARE( intel ); + { + __DRIdrawablePrivate *dPriv = intel->driDrawable; + drm_clip_rect_t *box = dPriv->pClipRects; + GLint nbox = dPriv->numClipRects; + GLint delta_x = srcx - dstx; + GLint delta_y = srcy - dsty; + GLuint i; + + + dsty = dPriv->h - dsty - height; /* convert from gl to hardware coords */ + srcy = dPriv->h - srcy - height; /* convert from gl to hardware coords */ + dstx += dPriv->x; + dsty += dPriv->y; + srcx += dPriv->x; + srcy += dPriv->y; + + /* Clip against the source region. This is the only source + * clipping we do. Dst is clipped with cliprects below. + * + * TODO: Scissor? + */ + if (!intel_clip_to_region(ctx, src, &srcx, &srcy, &width, &height)) + goto out; + + dstx = srcx - delta_x; + dsty = srcy - delta_y; + + /* Could do slightly more clipping: Eg, take the intersection of + * the existing set of cliprects and those cliprects translated + * by delta_x, delta_y: + * + * This code will not overwrite other windows, but will + * introduce garbage when copying from obscured window regions. + */ + for (i = 0 ; i < nbox ; i++ ) + { + GLint bx = box[i].x1; + GLint by = box[i].y1; + GLint bw = box[i].x2 - bx; + GLint bh = box[i].y2 - by; + + if (bx < dstx) bw -= dstx - bx, bx = dstx; + if (by < dsty) bh -= dsty - by, by = dsty; + if (bx + bw > dstx + width) bw = dstx + width - bx; + if (by + bh > dsty + height) bh = dsty + height - by; + if (bw <= 0) continue; + if (bh <= 0) continue; + + intelEmitCopyBlit( intel, + dst->cpp, + src->pitch, src->buffer, 0, + dst->pitch, dst->buffer, 0, + bx + delta_x, by + delta_y, /* srcx, srcy */ + bx, by, /* dstx, dsty */ + bw, bh ); + } + } + out: + intel_batchbuffer_flush( intel->batch ); + UNLOCK_HARDWARE( intel ); + return GL_TRUE; }