diff options
Diffstat (limited to 'src/mesa/drivers/dri/i965/intel_batchbuffer.c')
-rw-r--r-- | src/mesa/drivers/dri/i965/intel_batchbuffer.c | 250 |
1 files changed, 250 insertions, 0 deletions
diff --git a/src/mesa/drivers/dri/i965/intel_batchbuffer.c b/src/mesa/drivers/dri/i965/intel_batchbuffer.c new file mode 100644 index 0000000000..441412a7c2 --- /dev/null +++ b/src/mesa/drivers/dri/i965/intel_batchbuffer.c @@ -0,0 +1,250 @@ +/************************************************************************** + * + * Copyright 2006 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 "imports.h" +#include "intel_batchbuffer.h" +#include "intel_ioctl.h" +#include "bufmgr.h" + + +static void intel_batchbuffer_reset( struct intel_batchbuffer *batch ) +{ + assert(batch->map == NULL); + + batch->offset = (unsigned long)batch->ptr; + batch->offset = (batch->offset + 63) & ~63; + batch->ptr = (unsigned char *) batch->offset; + + if (BATCH_SZ - batch->offset < BATCH_REFILL) { + bmBufferData(batch->intel, + batch->buffer, + BATCH_SZ, + NULL, + 0); + batch->offset = 0; + batch->ptr = NULL; + } + + batch->flags = 0; +} + +static void intel_batchbuffer_reset_cb( struct intel_context *intel, + void *ptr ) +{ + struct intel_batchbuffer *batch = (struct intel_batchbuffer *)ptr; + assert(batch->map == NULL); + batch->flags = 0; + batch->offset = 0; + batch->ptr = NULL; +} + +void intel_batchbuffer_map( struct intel_batchbuffer *batch ) +{ + if (!batch->map) { + batch->map = bmMapBuffer(batch->intel, batch->buffer, + BM_MEM_AGP|BM_MEM_LOCAL|BM_CLIENT|BM_WRITE); + batch->ptr += (unsigned long)batch->map; + } + assert(batch->map); +} + +void intel_batchbuffer_unmap( struct intel_batchbuffer *batch ) +{ + if (batch->map) { + batch->ptr -= (unsigned long)batch->map; + batch->map = NULL; + bmUnmapBuffer(batch->intel, batch->buffer); + } +} + + + +/*====================================================================== + * Public functions + */ +struct intel_batchbuffer *intel_batchbuffer_alloc( struct intel_context *intel ) +{ + struct intel_batchbuffer *batch = calloc(sizeof(*batch), 1); + + batch->intel = intel; + + bmGenBuffers(intel, "batch", 1, &batch->buffer); + + bmBufferSetInvalidateCB(intel, batch->buffer, + intel_batchbuffer_reset_cb, + batch, + GL_TRUE); + + bmBufferData(batch->intel, + batch->buffer, + BATCH_SZ, + NULL, + 0); + + + return batch; +} + +void intel_batchbuffer_free( struct intel_batchbuffer *batch ) +{ + if (batch->map) + bmUnmapBuffer(batch->intel, batch->buffer); + + bmDeleteBuffers(batch->intel, 1, &batch->buffer); + free(batch); +} + + +#define MI_BATCH_BUFFER_END (0xA<<23) + + +void 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; + + assert(intel->locked); + + if (used == 0) { + bmReleaseBuffers( batch->intel ); + return; + } + + /* 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; + } + + + /* Add the MI_BATCH_BUFFER_END. Always add an MI_FLUSH - this is a + * performance drain that we would like to avoid. + */ + if (used & 4) { + ((int *)batch->ptr)[0] = MI_BATCH_BUFFER_END; + batch->ptr += 4; + used += 4; + } + else { + ((int *)batch->ptr)[0] = 0; + ((int *)batch->ptr)[1] = MI_BATCH_BUFFER_END; + + batch->ptr += 8; + used += 8; + } + + intel_batchbuffer_unmap(batch); + + /* Get the batch buffer offset: Must call bmBufferOffset() before + * bmValidateBuffers(), otherwise the buffer won't be on the inuse + * list. + */ + offset = bmBufferOffset(batch->intel, batch->buffer); + + if (!bmValidateBuffers( batch->intel )) { + assert(0); + } + + + if (intel->aub_file) { + /* Send buffered commands to aubfile as a single packet. + */ + intel_batchbuffer_map(batch); + ((int *)batch->ptr)[-1] = intel->vtbl.flush_cmd(); + intel->vtbl.aub_commands(intel, + offset, /* Fulsim wierdness - don't adjust */ + batch->map + batch->offset, + used); + ((int *)batch->ptr)[-1] = MI_BATCH_BUFFER_END; + intel_batchbuffer_unmap(batch); + } + + + /* Fire the batch buffer, which was uploaded above: + */ + intel_batch_ioctl(batch->intel, + offset + batch->offset, + used, + ignore_cliprects); + + if (intel->aub_file && + intel->ctx.DrawBuffer->_ColorDrawBufferMask[0] == BUFFER_BIT_FRONT_LEFT) + intel->vtbl.aub_dump_bmp( intel, 0 ); + + /* Reset the buffer: + */ + intel_batchbuffer_reset( batch ); + intel_batchbuffer_map( batch ); +} + + + + + + + +void intel_batchbuffer_align( struct intel_batchbuffer *batch, + GLuint align, + GLuint sz ) +{ + unsigned long ptr = (unsigned long) batch->ptr; + unsigned long aptr = (ptr + align) & ~((unsigned long)align-1); + GLuint fixup = aptr - ptr; + + if (intel_batchbuffer_space(batch) < fixup + sz) + intel_batchbuffer_flush(batch); + else { + memset(batch->ptr, 0, fixup); + batch->ptr += fixup; + } +} + + + + +void intel_batchbuffer_data(struct intel_batchbuffer *batch, + const void *data, + GLuint bytes, + GLuint flags) +{ + assert((bytes & 3) == 0); + intel_batchbuffer_require_space(batch, bytes, flags); + __memcpy(batch->ptr, data, bytes); + batch->ptr += bytes; +} + |