From 759facb4d87843f6368fad9c5f20a5b1b3d95055 Mon Sep 17 00:00:00 2001 From: Keith Whitwell Date: Mon, 23 Oct 2006 08:43:26 +0000 Subject: [PATCH] Emit cliprects in the userspace driver as required, rather than passing them to the kernel. This works because all drawing commands in the 965 driver are emitted with the lock held and the batchbuffer is always flushed prior to releasing the lock. This allows multiple cliprects to be dealt with, without replaying entire batchbuffers and redundantly re-emitting state. --- src/mesa/drivers/dri/i965/brw_aub_playback.c | 6 +-- src/mesa/drivers/dri/i965/brw_draw.c | 51 +++++++++++++++++-- src/mesa/drivers/dri/i965/brw_misc_state.c | 15 +++--- src/mesa/drivers/dri/i965/bufmgr_fake.c | 2 +- src/mesa/drivers/dri/i965/intel_batchbuffer.c | 20 +------- src/mesa/drivers/dri/i965/intel_buffers.c | 6 +++ src/mesa/drivers/dri/i965/intel_context.c | 6 --- src/mesa/drivers/dri/i965/intel_ioctl.c | 33 +++++------- src/mesa/drivers/dri/i965/intel_ioctl.h | 6 +-- src/mesa/drivers/dri/i965/intel_screen.c | 2 +- 10 files changed, 81 insertions(+), 66 deletions(-) diff --git a/src/mesa/drivers/dri/i965/brw_aub_playback.c b/src/mesa/drivers/dri/i965/brw_aub_playback.c index 49cc967716e..2433d50c116 100644 --- a/src/mesa/drivers/dri/i965/brw_aub_playback.c +++ b/src/mesa/drivers/dri/i965/brw_aub_playback.c @@ -39,7 +39,7 @@ static void flush_and_fence( struct aub_state *s ) buf[0] = intel->vtbl.flush_cmd(); buf[1] = 0; - intel_cmd_ioctl(intel, (char *)&buf, sizeof(buf), GL_TRUE); + intel_cmd_ioctl(intel, (char *)&buf, sizeof(buf)); intelWaitIrq( intel, intelEmitIrqLocked( intel )); } @@ -64,7 +64,7 @@ static void flush_cmds( struct aub_state *s, * This differs slightly from how the stream was executed * initially as this would have been a batchbuffer. */ - intel_cmd_ioctl(s->intel, (void *)data, len, GL_TRUE); + intel_cmd_ioctl(s->intel, (void *)data, len); if (1) flush_and_fence(s); @@ -345,7 +345,7 @@ static int parse_block_header( struct aub_state *s ) } case BH_COMMAND_WRITE: #if 0 - intel_cmd_ioctl(s->intel, (void *)data, len, GL_TRUE); + intel_cmd_ioctl(s->intel, (void *)data, len); #else if (parse_commands(s, data, len) != 0) _mesa_printf("parse_commands failed\n"); diff --git a/src/mesa/drivers/dri/i965/brw_draw.c b/src/mesa/drivers/dri/i965/brw_draw.c index e476b18ceae..5c0c5da7eaa 100644 --- a/src/mesa/drivers/dri/i965/brw_draw.c +++ b/src/mesa/drivers/dri/i965/brw_draw.c @@ -123,6 +123,23 @@ static GLuint trim(GLenum prim, GLuint length) } +static void brw_emit_cliprect( struct brw_context *brw, + const drm_clip_rect_t *rect ) +{ + struct brw_drawrect bdr; + + bdr.header.opcode = CMD_DRAW_RECT; + bdr.header.length = sizeof(bdr)/4 - 2; + bdr.xmin = rect->x1; + bdr.xmax = rect->x2 - 1; + bdr.ymin = rect->y1; + bdr.ymax = rect->y2 - 1; + bdr.xorg = brw->intel.drawX; + bdr.yorg = brw->intel.drawY; + + intel_batchbuffer_data( brw->intel.batch, &bdr, sizeof(bdr), + INTEL_BATCH_NO_CLIPRECTS); +} static void brw_emit_prim( struct brw_context *brw, @@ -149,7 +166,7 @@ static void brw_emit_prim( struct brw_context *brw, if (prim_packet.verts_per_instance) { intel_batchbuffer_data( brw->intel.batch, &prim_packet, sizeof(prim_packet), - INTEL_BATCH_CLIPRECTS); + INTEL_BATCH_NO_CLIPRECTS); } } @@ -277,7 +294,7 @@ static GLboolean brw_try_draw_prims( GLcontext *ctx, struct intel_context *intel = intel_context(ctx); struct brw_context *brw = brw_context(ctx); GLboolean retval = GL_FALSE; - GLuint i; + GLuint i, j; if (ctx->NewState) _mesa_update_state( ctx ); @@ -294,8 +311,17 @@ static GLboolean brw_try_draw_prims( GLcontext *ctx, */ LOCK_HARDWARE(intel); + + if (brw->intel.numClipRects == 0) { + assert(intel->batch->ptr == intel->batch->map + intel->batch->offset); + UNLOCK_HARDWARE(intel); + return GL_TRUE; + } + { assert(intel->locked); + + /* Set the first primitive early, ahead of validate_state: */ @@ -322,10 +348,25 @@ static GLboolean brw_try_draw_prims( GLcontext *ctx, goto out; } - /* Emit prims to batchbuffer: + /* For single cliprect, state is already emitted: */ - for (i = 0; i < nr_prims; i++) { - brw_emit_prim(brw, &prim[i]); + if (brw->intel.numClipRects == 1) { + for (i = 0; i < nr_prims; i++) { + brw_emit_prim(brw, &prim[i]); + } + } + else { + /* Otherwise, explicitly do the cliprects at this point: + */ + for (j = 0; j < brw->intel.numClipRects; j++) { + brw_emit_cliprect(brw, &brw->intel.pClipRects[j]); + + /* Emit prims to batchbuffer: + */ + for (i = 0; i < nr_prims; i++) { + brw_emit_prim(brw, &prim[i]); + } + } } intel->need_flush = GL_TRUE; diff --git a/src/mesa/drivers/dri/i965/brw_misc_state.c b/src/mesa/drivers/dri/i965/brw_misc_state.c index 29296c17e9e..6a6c4503c74 100644 --- a/src/mesa/drivers/dri/i965/brw_misc_state.c +++ b/src/mesa/drivers/dri/i965/brw_misc_state.c @@ -74,7 +74,6 @@ const struct brw_tracked_state brw_blend_constant_color = { /*********************************************************************** * Drawing rectangle -- Need for AUB file only. */ - static void upload_drawing_rect(struct brw_context *brw) { struct intel_context *intel = &brw->intel; @@ -83,13 +82,12 @@ static void upload_drawing_rect(struct brw_context *brw) int x1, y1; int x2, y2; - if (!brw->intel.aub_file) + /* If there is a single cliprect, set it here. Otherwise iterate + * over them in brw_draw_prim(). + */ + if (brw->intel.numClipRects > 1) return; - /* Basically calculate a single cliprect for the whole window. - * Don't bother iterating over cliprects at the moment. - */ - x1 = dPriv->x; y1 = dPriv->y; x2 = dPriv->x + dPriv->w; @@ -110,7 +108,10 @@ static void upload_drawing_rect(struct brw_context *brw) bdr.xorg = dPriv->x; bdr.yorg = dPriv->y; - BRW_CACHED_BATCH_STRUCT(brw, &bdr); + /* Can't use BRW_CACHED_BATCH_STRUCT because this is also emitted + * uncached in brw_draw.c: + */ + BRW_BATCH_STRUCT(brw, &bdr); } const struct brw_tracked_state brw_drawing_rect = { diff --git a/src/mesa/drivers/dri/i965/bufmgr_fake.c b/src/mesa/drivers/dri/i965/bufmgr_fake.c index 30a235a2e53..ed88ab3797a 100644 --- a/src/mesa/drivers/dri/i965/bufmgr_fake.c +++ b/src/mesa/drivers/dri/i965/bufmgr_fake.c @@ -1307,7 +1307,7 @@ unsigned bmSetFence( struct intel_context *intel ) GLuint dword[2]; dword[0] = intel->vtbl.flush_cmd(); dword[1] = 0; - intel_cmd_ioctl(intel, (char *)&dword, sizeof(dword), GL_TRUE); + intel_cmd_ioctl(intel, (char *)&dword, sizeof(dword)); intel->bm->last_fence = intelEmitIrqLocked( intel ); diff --git a/src/mesa/drivers/dri/i965/intel_batchbuffer.c b/src/mesa/drivers/dri/i965/intel_batchbuffer.c index 598ce08735d..64885ed9b4b 100644 --- a/src/mesa/drivers/dri/i965/intel_batchbuffer.c +++ b/src/mesa/drivers/dri/i965/intel_batchbuffer.c @@ -128,7 +128,6 @@ GLboolean intel_batchbuffer_flush( struct intel_batchbuffer *batch ) struct intel_context *intel = batch->intel; GLuint used = batch->ptr - (batch->map + batch->offset); GLuint offset; - GLboolean ignore_cliprects = (batch->flags & INTEL_BATCH_CLIPRECTS) ? GL_FALSE : GL_TRUE; GLint retval = GL_TRUE; assert(intel->locked); @@ -138,22 +137,6 @@ GLboolean intel_batchbuffer_flush( struct intel_batchbuffer *batch ) return GL_TRUE; } - /* Throw away non-effective packets. - */ - if (intel->numClipRects == 0 && !ignore_cliprects) { - batch->ptr = batch->map + batch->offset; - bmReleaseBuffers( batch->intel ); - intel->vtbl.lost_hardware(intel); - batch->flags = 0; - - UNLOCK_HARDWARE(intel); - sched_yield(); - LOCK_HARDWARE(intel); - - return GL_TRUE; - } - - /* Add the MI_BATCH_BUFFER_END. Always add an MI_FLUSH - this is a * performance drain that we would like to avoid. */ @@ -204,8 +187,7 @@ GLboolean intel_batchbuffer_flush( struct intel_batchbuffer *batch ) */ intel_batch_ioctl(batch->intel, offset + batch->offset, - used, - ignore_cliprects); + used); if (intel->aub_file && intel->ctx.DrawBuffer->_ColorDrawBufferMask[0] == BUFFER_BIT_FRONT_LEFT) diff --git a/src/mesa/drivers/dri/i965/intel_buffers.c b/src/mesa/drivers/dri/i965/intel_buffers.c index 9c985715ab4..dc5b9c0bc42 100644 --- a/src/mesa/drivers/dri/i965/intel_buffers.c +++ b/src/mesa/drivers/dri/i965/intel_buffers.c @@ -210,6 +210,12 @@ void intelWindowMoved( struct intel_context *intel ) intel->NewGLState |= _NEW_SCISSOR; } + + /* This works because the lock is always grabbed before emitting + * commands and commands are always flushed prior to releasing + * the lock. + */ + intel->NewGLState |= _NEW_WINDOW_POS; } diff --git a/src/mesa/drivers/dri/i965/intel_context.c b/src/mesa/drivers/dri/i965/intel_context.c index 8be954d51d1..36edd7db7f5 100644 --- a/src/mesa/drivers/dri/i965/intel_context.c +++ b/src/mesa/drivers/dri/i965/intel_context.c @@ -577,12 +577,6 @@ static void intelContendedLock( struct intel_context *intel, GLuint flags ) if (dPriv && intel->lastStamp != dPriv->lastStamp) { intelWindowMoved( intel ); intel->lastStamp = dPriv->lastStamp; - - /* This works because the lock is always grabbed before emitting - * commands and commands are always flushed prior to releasing - * the lock. - */ - intel->NewGLState |= _NEW_WINDOW_POS; } } diff --git a/src/mesa/drivers/dri/i965/intel_ioctl.c b/src/mesa/drivers/dri/i965/intel_ioctl.c index 9297543f82b..d1f2e3f27ca 100644 --- a/src/mesa/drivers/dri/i965/intel_ioctl.c +++ b/src/mesa/drivers/dri/i965/intel_ioctl.c @@ -105,8 +105,7 @@ void intelWaitIrq( struct intel_context *intel, int seq ) void intel_batch_ioctl( struct intel_context *intel, GLuint start_offset, - GLuint used, - GLboolean ignore_cliprects) + GLuint used) { drmI830BatchBuffer batch; @@ -114,27 +113,24 @@ void intel_batch_ioctl( struct intel_context *intel, assert(used); if (0) - fprintf(stderr, "%s used %d offset %x..%x ignore_cliprects %d\n", + fprintf(stderr, "%s used %d offset %x..%x\n", __FUNCTION__, used, start_offset, - start_offset + used, - ignore_cliprects); + start_offset + used); batch.start = start_offset; batch.used = used; - batch.cliprects = intel->pClipRects; - batch.num_cliprects = ignore_cliprects ? 0 : intel->numClipRects; + batch.cliprects = NULL; + batch.num_cliprects = 0; batch.DR1 = 0; - batch.DR4 = ((((GLuint)intel->drawX) & 0xffff) | - (((GLuint)intel->drawY) << 16)); + batch.DR4 = 0; if (INTEL_DEBUG & DEBUG_DMA) - fprintf(stderr, "%s: 0x%x..0x%x DR4: %x cliprects: %d\n", + fprintf(stderr, "%s: 0x%x..0x%x\n", __FUNCTION__, batch.start, - batch.start + batch.used * 4, - batch.DR4, batch.num_cliprects); + batch.start + batch.used * 4); if (!intel->no_hw) { if (drmCommandWrite (intel->driFd, DRM_I830_BATCHBUFFER, &batch, @@ -148,8 +144,7 @@ void intel_batch_ioctl( struct intel_context *intel, void intel_cmd_ioctl( struct intel_context *intel, char *buf, - GLuint used, - GLboolean ignore_cliprects) + GLuint used) { drmI830CmdBuffer cmd; @@ -159,17 +154,15 @@ void intel_cmd_ioctl( struct intel_context *intel, cmd.buf = buf; cmd.sz = used; cmd.cliprects = intel->pClipRects; - cmd.num_cliprects = ignore_cliprects ? 0 : intel->numClipRects; + cmd.num_cliprects = 0; cmd.DR1 = 0; - cmd.DR4 = ((((GLuint)intel->drawX) & 0xffff) | - (((GLuint)intel->drawY) << 16)); + cmd.DR4 = 0; if (INTEL_DEBUG & DEBUG_DMA) - fprintf(stderr, "%s: 0x%x..0x%x DR4: %x cliprects: %d\n", + fprintf(stderr, "%s: 0x%x..0x%x\n", __FUNCTION__, 0, - 0 + cmd.sz, - cmd.DR4, cmd.num_cliprects); + 0 + cmd.sz); if (!intel->no_hw) { if (drmCommandWrite (intel->driFd, DRM_I830_CMDBUFFER, &cmd, diff --git a/src/mesa/drivers/dri/i965/intel_ioctl.h b/src/mesa/drivers/dri/i965/intel_ioctl.h index dcebcb06d1d..df276593626 100644 --- a/src/mesa/drivers/dri/i965/intel_ioctl.h +++ b/src/mesa/drivers/dri/i965/intel_ioctl.h @@ -35,12 +35,10 @@ int intelEmitIrqLocked( struct intel_context *intel ); void intel_batch_ioctl( struct intel_context *intel, GLuint start_offset, - GLuint used, - GLboolean ignore_cliprects); + GLuint used); void intel_cmd_ioctl( struct intel_context *intel, char *buf, - GLuint used, - GLboolean ignore_cliprects); + GLuint used); #endif diff --git a/src/mesa/drivers/dri/i965/intel_screen.c b/src/mesa/drivers/dri/i965/intel_screen.c index 4bc5bedc529..56e6a792fa2 100644 --- a/src/mesa/drivers/dri/i965/intel_screen.c +++ b/src/mesa/drivers/dri/i965/intel_screen.c @@ -272,7 +272,7 @@ static GLboolean intelInitDriver(__DRIscreenPrivate *sPriv) volatile drmI830Sarea *sarea; if (sPriv->devPrivSize != sizeof(I830DRIRec)) { - fprintf(stderr,"\nERROR! sizeof(I830DRIRec) (%ld) does not match passed size from device driver (%d)\n", sizeof(I830DRIRec), sPriv->devPrivSize); + fprintf(stderr,"\nERROR! sizeof(I830DRIRec) (%ld) does not match passed size from device driver (%d)\n", (unsigned long)sizeof(I830DRIRec), sPriv->devPrivSize); return GL_FALSE; } -- 2.30.2