From 9f344b3e7d6e23674dd4747faec253f103563b36 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 9 Aug 2006 19:14:05 +0000 Subject: Add Intel i965G/Q DRI driver. This driver comes from Tungsten Graphics, with a few further modifications by Intel. --- src/mesa/drivers/dri/i965/intel_blit.c | 494 +++++++++++++++++++++++++++++++++ 1 file changed, 494 insertions(+) create mode 100644 src/mesa/drivers/dri/i965/intel_blit.c (limited to 'src/mesa/drivers/dri/i965/intel_blit.c') diff --git a/src/mesa/drivers/dri/i965/intel_blit.c b/src/mesa/drivers/dri/i965/intel_blit.c new file mode 100644 index 0000000000..2191dd585e --- /dev/null +++ b/src/mesa/drivers/dri/i965/intel_blit.c @@ -0,0 +1,494 @@ +/************************************************************************** + * + * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + + +#include +#include + +#include "mtypes.h" +#include "context.h" +#include "enums.h" +#include "vblank.h" + +#include "intel_reg.h" +#include "intel_batchbuffer.h" +#include "intel_context.h" +#include "intel_blit.h" +#include "intel_regions.h" + +#include "bufmgr.h" + + + + +/* + * Copy the back buffer to the front buffer. + */ +void intelCopyBuffer( const __DRIdrawablePrivate *dPriv, + const drm_clip_rect_t *rect ) +{ + struct intel_context *intel; + GLboolean missed_target; + int64_t ust; + + DBG("%s\n", __FUNCTION__); + + assert(dPriv); + assert(dPriv->driContextPriv); + assert(dPriv->driContextPriv->driverPrivate); + + intel = (struct intel_context *) dPriv->driContextPriv->driverPrivate; + intelFlush( &intel->ctx ); + + + bmFinishFence(intel, intel->last_swap_fence); + + /* The LOCK_HARDWARE is required for the cliprects. Buffer offsets + * should work regardless. + */ + LOCK_HARDWARE( intel ); + + if (!rect) + { + /* This is a really crappy way to do wait-for-vblank. I guess + * it sortof works in the single-application case. + */ + UNLOCK_HARDWARE( intel ); + driWaitForVBlank( dPriv, &intel->vbl_seq, intel->vblank_flags, & missed_target ); + LOCK_HARDWARE( intel ); + } + + { + intelScreenPrivate *intelScreen = intel->intelScreen; + __DRIdrawablePrivate *dPriv = intel->driDrawable; + int nbox = dPriv->numClipRects; + drm_clip_rect_t *pbox = dPriv->pClipRects; + int cpp = intelScreen->cpp; + struct intel_region *src, *dst; + int BR13, CMD; + int i; + int src_pitch, dst_pitch; + + if (intel->sarea->pf_current_page == 0) { + dst = intel->front_region; + src = intel->back_region; + } + else { + assert(0); + src = intel->front_region; + dst = intel->back_region; + } + + src_pitch = src->pitch * src->cpp; + dst_pitch = dst->pitch * dst->cpp; + + if (cpp == 2) { + BR13 = (0xCC << 16) | (1<<24); + CMD = XY_SRC_COPY_BLT_CMD; + } + else { + BR13 = (0xCC << 16) | (1<<24) | (1<<25); + CMD = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA | + XY_SRC_COPY_BLT_WRITE_RGB); + } + + if (src->tiled) { + CMD |= XY_SRC_TILED; + src_pitch /= 4; + } + + if (dst->tiled) { + CMD |= XY_DST_TILED; + dst_pitch /= 4; + } + + for (i = 0 ; i < nbox; i++, pbox++) + { + drm_clip_rect_t tmp = *pbox; + + if (rect) { + if (!intel_intersect_cliprects(&tmp, &tmp, rect)) + continue; + } + + + if (tmp.x1 > tmp.x2 || + tmp.y1 > tmp.y2 || + tmp.x2 > intelScreen->width || + tmp.y2 > intelScreen->height) + continue; + + BEGIN_BATCH(8, INTEL_BATCH_NO_CLIPRECTS); + OUT_BATCH( CMD ); + OUT_BATCH( dst_pitch | BR13 ); + OUT_BATCH( (tmp.y1 << 16) | tmp.x1 ); + OUT_BATCH( (tmp.y2 << 16) | tmp.x2 ); + OUT_BATCH( bmBufferOffset(intel, dst->buffer) ); + OUT_BATCH( (tmp.y1 << 16) | tmp.x1 ); + OUT_BATCH( src_pitch ); + OUT_BATCH( bmBufferOffset(intel, src->buffer) ); + ADVANCE_BATCH(); + } + } + + intel_batchbuffer_flush( intel->batch ); + intel->second_last_swap_fence = intel->last_swap_fence; + intel->last_swap_fence = bmSetFence( intel ); + UNLOCK_HARDWARE( intel ); + + if (!rect) + { + intel->swap_count++; + (*dri_interface->getUST)(&ust); + if (missed_target) { + intel->swap_missed_count++; + intel->swap_missed_ust = ust - intel->swap_ust; + } + + intel->swap_ust = ust; + } + +} + + + + +void intelEmitFillBlit( struct intel_context *intel, + GLuint cpp, + GLshort dst_pitch, + struct buffer *dst_buffer, + GLuint dst_offset, + GLboolean dst_tiled, + GLshort x, GLshort y, + GLshort w, GLshort h, + GLuint color ) +{ + GLuint BR13, CMD; + BATCH_LOCALS; + + dst_pitch *= cpp; + + switch(cpp) { + case 1: + case 2: + case 3: + BR13 = (0xF0 << 16) | (1<<24); + CMD = XY_COLOR_BLT_CMD; + break; + case 4: + BR13 = (0xF0 << 16) | (1<<24) | (1<<25); + CMD = (XY_COLOR_BLT_CMD | XY_COLOR_BLT_WRITE_ALPHA | + XY_COLOR_BLT_WRITE_RGB); + break; + default: + return; + } + + if (dst_tiled) { + CMD |= XY_DST_TILED; + dst_pitch /= 4; + } + + BEGIN_BATCH(6, INTEL_BATCH_NO_CLIPRECTS); + OUT_BATCH( CMD ); + OUT_BATCH( dst_pitch | BR13 ); + OUT_BATCH( (y << 16) | x ); + OUT_BATCH( ((y+h) << 16) | (x+w) ); + OUT_BATCH( bmBufferOffset(intel, dst_buffer) + dst_offset ); + OUT_BATCH( color ); + ADVANCE_BATCH(); +} + + +/* Copy BitBlt + */ +void intelEmitCopyBlit( struct intel_context *intel, + GLuint cpp, + GLshort src_pitch, + struct buffer *src_buffer, + GLuint src_offset, + GLboolean src_tiled, + GLshort dst_pitch, + struct buffer *dst_buffer, + GLuint dst_offset, + GLboolean dst_tiled, + GLshort src_x, GLshort src_y, + GLshort dst_x, GLshort dst_y, + GLshort w, GLshort h ) +{ + GLuint CMD, BR13; + int dst_y2 = dst_y + h; + int dst_x2 = dst_x + w; + BATCH_LOCALS; + + + DBG("%s src:buf(%d)/%d %d,%d dst:buf(%d)/%d %d,%d sz:%dx%d\n", + __FUNCTION__, + src_buffer, src_pitch, src_x, src_y, + dst_buffer, dst_pitch, dst_x, dst_y, + w,h); + + src_pitch *= cpp; + dst_pitch *= cpp; + + switch(cpp) { + case 1: + case 2: + case 3: + BR13 = (0xCC << 16) | (1<<24); + CMD = XY_SRC_COPY_BLT_CMD; + break; + case 4: + BR13 = (0xCC << 16) | (1<<24) | (1<<25); + CMD = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA | + XY_SRC_COPY_BLT_WRITE_RGB); + break; + default: + return; + } + + if (src_tiled) { + CMD |= XY_SRC_TILED; + src_pitch /= 4; + } + + if (dst_tiled) { + CMD |= XY_DST_TILED; + dst_pitch /= 4; + } + + if (dst_y2 < dst_y || + dst_x2 < dst_x) { + return; + } + + dst_pitch &= 0xffff; + src_pitch &= 0xffff; + + /* Initial y values don't seem to work with negative pitches. If + * we adjust the offsets manually (below), it seems to work fine. + */ + if (0) { + BEGIN_BATCH(8, INTEL_BATCH_NO_CLIPRECTS); + OUT_BATCH( CMD ); + OUT_BATCH( dst_pitch | BR13 ); + OUT_BATCH( (dst_y << 16) | dst_x ); + OUT_BATCH( (dst_y2 << 16) | dst_x2 ); + OUT_BATCH( bmBufferOffset(intel, dst_buffer) + dst_offset ); + OUT_BATCH( (src_y << 16) | src_x ); + OUT_BATCH( src_pitch ); + OUT_BATCH( bmBufferOffset(intel, src_buffer) + src_offset ); + ADVANCE_BATCH(); + } + else { + BEGIN_BATCH(8, INTEL_BATCH_NO_CLIPRECTS); + OUT_BATCH( CMD ); + OUT_BATCH( (dst_pitch & 0xffff) | BR13 ); + OUT_BATCH( (0 << 16) | dst_x ); + OUT_BATCH( (h << 16) | dst_x2 ); + OUT_BATCH( bmBufferOffset(intel, dst_buffer) + dst_offset + dst_y * dst_pitch ); + OUT_BATCH( (0 << 16) | src_x ); + OUT_BATCH( (src_pitch & 0xffff) ); + OUT_BATCH( bmBufferOffset(intel, src_buffer) + src_offset + src_y * src_pitch ); + ADVANCE_BATCH(); + } +} + + + +void intelClearWithBlit(GLcontext *ctx, GLbitfield flags, GLboolean all, + GLint cx1, GLint cy1, GLint cw, GLint ch) +{ + struct intel_context *intel = intel_context( ctx ); + intelScreenPrivate *intelScreen = intel->intelScreen; + GLuint clear_depth, clear_color; + GLint cx, cy; + GLint cpp = intelScreen->cpp; + GLint i; + struct intel_region *front = intel->front_region; + struct intel_region *back = intel->back_region; + struct intel_region *depth = intel->depth_region; + GLuint BR13, FRONT_CMD, BACK_CMD, DEPTH_CMD; + GLuint front_pitch; + GLuint back_pitch; + GLuint depth_pitch; + BATCH_LOCALS; + + + clear_color = intel->ClearColor; + clear_depth = 0; + + if (flags & BUFFER_BIT_DEPTH) { + clear_depth = (GLuint)(ctx->Depth.Clear * intel->ClearDepth); + } + + if (flags & BUFFER_BIT_STENCIL) { + clear_depth |= (ctx->Stencil.Clear & 0xff) << 24; + } + + switch(cpp) { + case 2: + BR13 = (0xF0 << 16) | (1<<24); + BACK_CMD = FRONT_CMD = XY_COLOR_BLT_CMD; + DEPTH_CMD = XY_COLOR_BLT_CMD; + break; + case 4: + BR13 = (0xF0 << 16) | (1<<24) | (1<<25); + BACK_CMD = FRONT_CMD = (XY_COLOR_BLT_CMD | + XY_COLOR_BLT_WRITE_ALPHA | + XY_COLOR_BLT_WRITE_RGB); + DEPTH_CMD = XY_COLOR_BLT_CMD; + if (flags & BUFFER_BIT_DEPTH) DEPTH_CMD |= XY_COLOR_BLT_WRITE_RGB; + if (flags & BUFFER_BIT_STENCIL) DEPTH_CMD |= XY_COLOR_BLT_WRITE_ALPHA; + break; + default: + return; + } + + + + intelFlush( &intel->ctx ); + LOCK_HARDWARE( intel ); + { + /* Refresh the cx/y/w/h values as they may have been invalidated + * by a new window position or size picked up when we did + * LOCK_HARDWARE above. The values passed by mesa are not + * reliable. + */ + { + cx = ctx->DrawBuffer->_Xmin; + cy = ctx->DrawBuffer->_Ymin; + ch = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin; + cw = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin; + } + + /* flip top to bottom */ + cy = intel->driDrawable->h-cy1-ch; + cx = cx1 + intel->drawX; + cy += intel->drawY; + + /* adjust for page flipping */ + if ( intel->sarea->pf_current_page == 0 ) { + front = intel->front_region; + back = intel->back_region; + } + else { + back = intel->front_region; + front = intel->back_region; + } + + front_pitch = front->pitch * front->cpp; + back_pitch = back->pitch * back->cpp; + depth_pitch = depth->pitch * depth->cpp; + + if (front->tiled) { + FRONT_CMD |= XY_DST_TILED; + front_pitch /= 4; + } + + if (back->tiled) { + BACK_CMD |= XY_DST_TILED; + back_pitch /= 4; + } + + if (depth->tiled) { + DEPTH_CMD |= XY_DST_TILED; + depth_pitch /= 4; + } + + for (i = 0 ; i < intel->numClipRects ; i++) + { + drm_clip_rect_t *box = &intel->pClipRects[i]; + drm_clip_rect_t b; + + if (!all) { + GLint x = box->x1; + GLint y = box->y1; + GLint w = box->x2 - x; + GLint h = box->y2 - y; + + if (x < cx) w -= cx - x, x = cx; + if (y < cy) h -= cy - y, y = cy; + if (x + w > cx + cw) w = cx + cw - x; + if (y + h > cy + ch) h = cy + ch - y; + if (w <= 0) continue; + if (h <= 0) continue; + + b.x1 = x; + b.y1 = y; + b.x2 = x + w; + b.y2 = y + h; + } else { + b = *box; + } + + + if (b.x1 > b.x2 || + b.y1 > b.y2 || + b.x2 > intelScreen->width || + b.y2 > intelScreen->height) + continue; + + if ( flags & BUFFER_BIT_FRONT_LEFT ) { + BEGIN_BATCH(6, INTEL_BATCH_NO_CLIPRECTS); + OUT_BATCH( FRONT_CMD ); + OUT_BATCH( front_pitch | BR13 ); + OUT_BATCH( (b.y1 << 16) | b.x1 ); + OUT_BATCH( (b.y2 << 16) | b.x2 ); + OUT_BATCH( bmBufferOffset(intel, front->buffer) ); + OUT_BATCH( clear_color ); + ADVANCE_BATCH(); + } + + if ( flags & BUFFER_BIT_BACK_LEFT ) { + BEGIN_BATCH(6, INTEL_BATCH_NO_CLIPRECTS); + OUT_BATCH( BACK_CMD ); + OUT_BATCH( back_pitch | BR13 ); + OUT_BATCH( (b.y1 << 16) | b.x1 ); + OUT_BATCH( (b.y2 << 16) | b.x2 ); + OUT_BATCH( bmBufferOffset(intel, back->buffer) ); + OUT_BATCH( clear_color ); + ADVANCE_BATCH(); + } + + if ( flags & (BUFFER_BIT_STENCIL | BUFFER_BIT_DEPTH) ) { + BEGIN_BATCH(6, INTEL_BATCH_NO_CLIPRECTS); + OUT_BATCH( DEPTH_CMD ); + OUT_BATCH( depth_pitch | BR13 ); + OUT_BATCH( (b.y1 << 16) | b.x1 ); + OUT_BATCH( (b.y2 << 16) | b.x2 ); + OUT_BATCH( bmBufferOffset(intel, depth->buffer) ); + OUT_BATCH( clear_depth ); + ADVANCE_BATCH(); + } + } + } + intel_batchbuffer_flush( intel->batch ); + UNLOCK_HARDWARE( intel ); +} + + -- cgit v1.2.3