summaryrefslogtreecommitdiff
path: root/i915/intel_batchbuffer.c
diff options
context:
space:
mode:
Diffstat (limited to 'i915/intel_batchbuffer.c')
-rw-r--r--i915/intel_batchbuffer.c829
1 files changed, 829 insertions, 0 deletions
diff --git a/i915/intel_batchbuffer.c b/i915/intel_batchbuffer.c
new file mode 100644
index 0000000..803b41b
--- /dev/null
+++ b/i915/intel_batchbuffer.c
@@ -0,0 +1,829 @@
+/**************************************************************************
+ *
+ * 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 <stdio.h>
+#include <errno.h>
+
+#include "mtypes.h"
+#include "context.h"
+#include "enums.h"
+#include "vblank.h"
+
+#include "intel_reg.h"
+#include "intel_batchbuffer.h"
+#include "intel_context.h"
+
+
+
+
+/* ================================================================
+ * Performance monitoring functions
+ */
+
+static void intel_fill_box( intelContextPtr intel,
+ GLshort x, GLshort y,
+ GLshort w, GLshort h,
+ GLubyte r, GLubyte g, GLubyte b )
+{
+ x += intel->drawX;
+ y += intel->drawY;
+
+ if (x >= 0 && y >= 0 &&
+ x+w < intel->intelScreen->width &&
+ y+h < intel->intelScreen->height)
+ intelEmitFillBlitLocked( intel,
+ intel->intelScreen->cpp,
+ intel->intelScreen->back.pitch,
+ intel->intelScreen->back.offset,
+ x, y, w, h,
+ INTEL_PACKCOLOR(intel->intelScreen->fbFormat,
+ r,g,b,0xff));
+}
+
+static void intel_draw_performance_boxes( intelContextPtr intel )
+{
+ /* Purple box for page flipping
+ */
+ if ( intel->perf_boxes & I830_BOX_FLIP )
+ intel_fill_box( intel, 4, 4, 8, 8, 255, 0, 255 );
+
+ /* Red box if we have to wait for idle at any point
+ */
+ if ( intel->perf_boxes & I830_BOX_WAIT )
+ intel_fill_box( intel, 16, 4, 8, 8, 255, 0, 0 );
+
+ /* Blue box: lost context?
+ */
+ if ( intel->perf_boxes & I830_BOX_LOST_CONTEXT )
+ intel_fill_box( intel, 28, 4, 8, 8, 0, 0, 255 );
+
+ /* Yellow box for texture swaps
+ */
+ if ( intel->perf_boxes & I830_BOX_TEXTURE_LOAD )
+ intel_fill_box( intel, 40, 4, 8, 8, 255, 255, 0 );
+
+ /* Green box if hardware never idles (as far as we can tell)
+ */
+ if ( !(intel->perf_boxes & I830_BOX_RING_EMPTY) )
+ intel_fill_box( intel, 64, 4, 8, 8, 0, 255, 0 );
+
+
+ /* Draw bars indicating number of buffers allocated
+ * (not a great measure, easily confused)
+ */
+#if 0
+ if (intel->dma_used) {
+ int bar = intel->dma_used / 10240;
+ if (bar > 100) bar = 100;
+ if (bar < 1) bar = 1;
+ intel_fill_box( intel, 4, 16, bar, 4, 196, 128, 128 );
+ intel->dma_used = 0;
+ }
+#endif
+
+ intel->perf_boxes = 0;
+}
+
+
+
+
+
+
+static int bad_prim_vertex_nr( int primitive, int nr )
+{
+ switch (primitive & PRIM3D_MASK) {
+ case PRIM3D_POINTLIST:
+ return nr < 1;
+ case PRIM3D_LINELIST:
+ return (nr & 1) || nr == 0;
+ case PRIM3D_LINESTRIP:
+ return nr < 2;
+ case PRIM3D_TRILIST:
+ case PRIM3D_RECTLIST:
+ return nr % 3 || nr == 0;
+ case PRIM3D_POLY:
+ case PRIM3D_TRIFAN:
+ case PRIM3D_TRISTRIP:
+ case PRIM3D_TRISTRIP_RVRSE:
+ return nr < 3;
+ default:
+ return 1;
+ }
+}
+
+static void intel_flush_inline_primitive( GLcontext *ctx )
+{
+ intelContextPtr intel = INTEL_CONTEXT( ctx );
+ GLuint used = intel->batch.ptr - intel->prim.start_ptr;
+ GLuint vertcount;
+
+ assert(intel->prim.primitive != ~0);
+
+ if (1) {
+ /* Check vertex size against the vertex we're specifying to
+ * hardware. If it's wrong, ditch the primitive.
+ */
+ if (!intel->vtbl.check_vertex_size( intel, intel->vertex_size ))
+ goto do_discard;
+
+ vertcount = (used - 4)/ (intel->vertex_size * 4);
+
+ if (!vertcount)
+ goto do_discard;
+
+ if (vertcount * intel->vertex_size * 4 != used - 4) {
+ fprintf(stderr, "vertex size confusion %d %d\n", used,
+ intel->vertex_size * vertcount * 4);
+ goto do_discard;
+ }
+
+ if (bad_prim_vertex_nr( intel->prim.primitive, vertcount )) {
+ fprintf(stderr, "bad_prim_vertex_nr %x %d\n", intel->prim.primitive,
+ vertcount);
+ goto do_discard;
+ }
+ }
+
+ if (used < 8)
+ goto do_discard;
+
+ *(int *)intel->prim.start_ptr = (_3DPRIMITIVE |
+ intel->prim.primitive |
+ (used/4-2));
+
+ goto finished;
+
+ do_discard:
+ intel->batch.ptr -= used;
+ intel->batch.space += used;
+ assert(intel->batch.space >= 0);
+
+ finished:
+ intel->prim.primitive = ~0;
+ intel->prim.start_ptr = 0;
+ intel->prim.flush = 0;
+}
+
+
+/* Emit a primitive referencing vertices in a vertex buffer.
+ */
+void intelStartInlinePrimitive( intelContextPtr intel, GLuint prim )
+{
+ BATCH_LOCALS;
+
+ if (0)
+ fprintf(stderr, "%s %x\n", __FUNCTION__, prim);
+
+
+ /* Finish any in-progress primitive:
+ */
+ INTEL_FIREVERTICES( intel );
+
+ /* Emit outstanding state:
+ */
+ intel->vtbl.emit_state( intel );
+
+ /* Make sure there is some space in this buffer:
+ */
+ if (intel->vertex_size * 10 * sizeof(GLuint) >= intel->batch.space) {
+ intelFlushBatch(intel, GL_TRUE);
+ intel->vtbl.emit_state( intel );
+ }
+
+#if 1
+ if (((unsigned long)intel->batch.ptr) & 0x4) {
+ BEGIN_BATCH(1);
+ OUT_BATCH(0);
+ ADVANCE_BATCH();
+ }
+#endif
+
+ /* Emit a slot which will be filled with the inline primitive
+ * command later.
+ */
+ BEGIN_BATCH(2);
+ OUT_BATCH( 0 );
+
+ intel->prim.start_ptr = batch_ptr;
+ intel->prim.primitive = prim;
+ intel->prim.flush = intel_flush_inline_primitive;
+ intel->batch.contains_geometry = 1;
+
+ OUT_BATCH( 0 );
+ ADVANCE_BATCH();
+}
+
+
+void intelRestartInlinePrimitive( intelContextPtr intel )
+{
+ GLuint prim = intel->prim.primitive;
+
+ intel_flush_inline_primitive( &intel->ctx );
+ if (1) intelFlushBatch(intel, GL_TRUE); /* GL_TRUE - is critical */
+ intelStartInlinePrimitive( intel, prim );
+}
+
+
+
+void intelWrapInlinePrimitive( intelContextPtr intel )
+{
+ GLuint prim = intel->prim.primitive;
+
+ if (0)
+ fprintf(stderr, "%s\n", __FUNCTION__);
+ intel_flush_inline_primitive( &intel->ctx );
+ intelFlushBatch(intel, GL_TRUE);
+ intelStartInlinePrimitive( intel, prim );
+}
+
+
+/* Emit a primitive with space for inline vertices.
+ */
+GLuint *intelEmitInlinePrimitiveLocked(intelContextPtr intel,
+ int primitive,
+ int dwords,
+ int vertex_size )
+{
+ GLuint *tmp = 0;
+ BATCH_LOCALS;
+
+ if (0)
+ fprintf(stderr, "%s 0x%x %d\n", __FUNCTION__, primitive, dwords);
+
+ /* Emit outstanding state:
+ */
+ intel->vtbl.emit_state( intel );
+
+ if ((1+dwords)*4 >= intel->batch.space) {
+ intelFlushBatch(intel, GL_TRUE);
+ intel->vtbl.emit_state( intel );
+ }
+
+
+ if (1) {
+ int used = dwords * 4;
+ int vertcount;
+
+ /* Check vertex size against the vertex we're specifying to
+ * hardware. If it's wrong, ditch the primitive.
+ */
+ if (!intel->vtbl.check_vertex_size( intel, vertex_size ))
+ goto do_discard;
+
+ vertcount = dwords / vertex_size;
+
+ if (dwords % vertex_size) {
+ fprintf(stderr, "did not request a whole number of vertices\n");
+ goto do_discard;
+ }
+
+ if (bad_prim_vertex_nr( primitive, vertcount )) {
+ fprintf(stderr, "bad_prim_vertex_nr %x %d\n", primitive, vertcount);
+ goto do_discard;
+ }
+
+ if (used < 8)
+ goto do_discard;
+ }
+
+ /* Emit 3D_PRIMITIVE commands:
+ */
+ BEGIN_BATCH(1 + dwords);
+ OUT_BATCH( _3DPRIMITIVE |
+ primitive |
+ (dwords-1) );
+
+ tmp = (GLuint *)batch_ptr;
+ batch_ptr += dwords * 4;
+
+ ADVANCE_BATCH();
+
+ intel->batch.contains_geometry = 1;
+
+ do_discard:
+ return tmp;
+}
+
+
+static void intelWaitForFrameCompletion( intelContextPtr intel )
+{
+ drm_i915_sarea_t *sarea = (drm_i915_sarea_t *)intel->sarea;
+
+ if (intel->do_irqs) {
+ if (intelGetLastFrame(intel) < sarea->last_dispatch) {
+ if (!intel->irqsEmitted) {
+ while (intelGetLastFrame (intel) < sarea->last_dispatch)
+ ;
+ }
+ else {
+ intelWaitIrq( intel, intel->alloc.irq_emitted );
+ }
+ intel->irqsEmitted = 10;
+ }
+
+ if (intel->irqsEmitted) {
+ LOCK_HARDWARE( intel );
+ intelEmitIrqLocked( intel );
+ intel->irqsEmitted--;
+ UNLOCK_HARDWARE( intel );
+ }
+ }
+ else {
+ while (intelGetLastFrame (intel) < sarea->last_dispatch) {
+ if (intel->do_usleeps)
+ DO_USLEEP( 1 );
+ }
+ }
+}
+
+/*
+ * Copy the back buffer to the front buffer.
+ */
+void intelCopyBuffer( const __DRIdrawablePrivate *dPriv,
+ const drm_clip_rect_t *rect)
+{
+ intelContextPtr intel;
+ const intelScreenPrivate *intelScreen;
+ GLboolean missed_target;
+ int64_t ust;
+
+ if (0)
+ fprintf(stderr, "%s\n", __FUNCTION__);
+
+ assert(dPriv);
+ assert(dPriv->driContextPriv);
+ assert(dPriv->driContextPriv->driverPrivate);
+
+ intel = (intelContextPtr) dPriv->driContextPriv->driverPrivate;
+
+ intelFlush( &intel->ctx );
+
+ intelScreen = intel->intelScreen;
+
+ if (!rect && !intel->swap_scheduled && intelScreen->drmMinor >= 6 &&
+ !(intel->vblank_flags & VBLANK_FLAG_NO_IRQ) &&
+ intelScreen->current_rotation == 0) {
+ unsigned int interval = driGetVBlankInterval(dPriv, intel->vblank_flags);
+ unsigned int target;
+ drm_i915_vblank_swap_t swap;
+
+ swap.drawable = dPriv->hHWDrawable;
+ swap.seqtype = DRM_VBLANK_ABSOLUTE;
+ target = swap.sequence = intel->vbl_seq + interval;
+
+ if (intel->vblank_flags & VBLANK_FLAG_SYNC) {
+ swap.seqtype |= DRM_VBLANK_NEXTONMISS;
+ } else if (interval == 0) {
+ goto noschedule;
+ }
+
+ if ( intel->vblank_flags & VBLANK_FLAG_SECONDARY ) {
+ swap.seqtype |= DRM_VBLANK_SECONDARY;
+ }
+
+ if (!drmCommandWriteRead(intel->driFd, DRM_I915_VBLANK_SWAP, &swap,
+ sizeof(swap))) {
+ intel->swap_scheduled = 1;
+ intel->vbl_seq = swap.sequence;
+ swap.sequence -= target;
+ missed_target = swap.sequence > 0 && swap.sequence <= (1 << 23);
+ }
+ } else {
+ intel->swap_scheduled = 0;
+ }
+noschedule:
+
+ if (!intel->swap_scheduled) {
+ intelWaitForFrameCompletion( intel );
+ LOCK_HARDWARE( intel );
+
+ if (!rect)
+ {
+ UNLOCK_HARDWARE( intel );
+ driWaitForVBlank( dPriv, &intel->vbl_seq, intel->vblank_flags, & missed_target );
+ LOCK_HARDWARE( intel );
+ }
+ {
+ const intelScreenPrivate *intelScreen = intel->intelScreen;
+ const __DRIdrawablePrivate *dPriv = intel->driDrawable;
+ const int nbox = dPriv->numClipRects;
+ const drm_clip_rect_t *pbox = dPriv->pClipRects;
+ drm_clip_rect_t box;
+ const int cpp = intelScreen->cpp;
+ const int pitch = intelScreen->front.pitch; /* in bytes */
+ int i;
+ GLuint CMD, BR13;
+ BATCH_LOCALS;
+
+ switch(cpp) {
+ case 2:
+ BR13 = (pitch) | (0xCC << 16) | (1<<24);
+ CMD = XY_SRC_COPY_BLT_CMD;
+ break;
+ case 4:
+ BR13 = (pitch) | (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:
+ BR13 = (pitch) | (0xCC << 16) | (1<<24);
+ CMD = XY_SRC_COPY_BLT_CMD;
+ break;
+ }
+
+ if (0)
+ intel_draw_performance_boxes( intel );
+
+ for (i = 0 ; i < nbox; i++, pbox++)
+ {
+ if (pbox->x1 > pbox->x2 ||
+ pbox->y1 > pbox->y2 ||
+ pbox->x2 > intelScreen->width ||
+ pbox->y2 > intelScreen->height) {
+ _mesa_warning(&intel->ctx, "Bad cliprect in intelCopyBuffer()");
+ continue;
+ }
+
+ box = *pbox;
+
+ if (rect)
+ {
+ if (rect->x1 > box.x1)
+ box.x1 = rect->x1;
+ if (rect->y1 > box.y1)
+ box.y1 = rect->y1;
+ if (rect->x2 < box.x2)
+ box.x2 = rect->x2;
+ if (rect->y2 < box.y2)
+ box.y2 = rect->y2;
+
+ if (box.x1 > box.x2 || box.y1 > box.y2)
+ continue;
+ }
+
+ BEGIN_BATCH( 8);
+ OUT_BATCH( CMD );
+ OUT_BATCH( BR13 );
+ OUT_BATCH( (box.y1 << 16) | box.x1 );
+ OUT_BATCH( (box.y2 << 16) | box.x2 );
+
+ if (intel->sarea->pf_current_page == 0)
+ OUT_BATCH( intelScreen->front.offset );
+ else
+ OUT_BATCH( intelScreen->back.offset );
+
+ OUT_BATCH( (box.y1 << 16) | box.x1 );
+ OUT_BATCH( BR13 & 0xffff );
+
+ if (intel->sarea->pf_current_page == 0)
+ OUT_BATCH( intelScreen->back.offset );
+ else
+ OUT_BATCH( intelScreen->front.offset );
+
+ ADVANCE_BATCH();
+ }
+ }
+ intelFlushBatchLocked( intel, GL_TRUE, GL_TRUE, GL_TRUE );
+ 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 intelEmitFillBlitLocked( intelContextPtr intel,
+ GLuint cpp,
+ GLshort dst_pitch, /* in bytes */
+ GLuint dst_offset,
+ GLshort x, GLshort y,
+ GLshort w, GLshort h,
+ GLuint color )
+{
+ GLuint BR13, CMD;
+ BATCH_LOCALS;
+
+ switch(cpp) {
+ case 1:
+ case 2:
+ case 3:
+ BR13 = dst_pitch | (0xF0 << 16) | (1<<24);
+ CMD = XY_COLOR_BLT_CMD;
+ break;
+ case 4:
+ BR13 = dst_pitch | (0xF0 << 16) | (1<<24) | (1<<25);
+ CMD = (XY_COLOR_BLT_CMD | XY_COLOR_BLT_WRITE_ALPHA |
+ XY_COLOR_BLT_WRITE_RGB);
+ break;
+ default:
+ return;
+ }
+
+ BEGIN_BATCH( 6);
+ OUT_BATCH( CMD );
+ OUT_BATCH( BR13 );
+ OUT_BATCH( (y << 16) | x );
+ OUT_BATCH( ((y+h) << 16) | (x+w) );
+ OUT_BATCH( dst_offset );
+ OUT_BATCH( color );
+ ADVANCE_BATCH();
+}
+
+
+/* Copy BitBlt
+ */
+void intelEmitCopyBlitLocked( intelContextPtr intel,
+ GLuint cpp,
+ GLshort src_pitch,
+ GLuint src_offset,
+ GLshort dst_pitch,
+ GLuint dst_offset,
+ 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;
+
+ src_pitch *= cpp;
+ dst_pitch *= cpp;
+
+ switch(cpp) {
+ case 1:
+ case 2:
+ case 3:
+ BR13 = dst_pitch | (0xCC << 16) | (1<<24);
+ CMD = XY_SRC_COPY_BLT_CMD;
+ break;
+ case 4:
+ BR13 = dst_pitch | (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 (dst_y2 < dst_y ||
+ dst_x2 < dst_x) {
+ return;
+ }
+
+ BEGIN_BATCH( 12);
+ OUT_BATCH( CMD );
+ OUT_BATCH( BR13 );
+ OUT_BATCH( (dst_y << 16) | dst_x );
+ OUT_BATCH( (dst_y2 << 16) | dst_x2 );
+ OUT_BATCH( dst_offset );
+ OUT_BATCH( (src_y << 16) | src_x );
+ OUT_BATCH( src_pitch );
+ OUT_BATCH( src_offset );
+ ADVANCE_BATCH();
+}
+
+
+
+void intelClearWithBlit(GLcontext *ctx, GLbitfield buffers, GLboolean allFoo,
+ GLint cx1Foo, GLint cy1Foo, GLint cwFoo, GLint chFoo)
+{
+ intelContextPtr intel = INTEL_CONTEXT( ctx );
+ intelScreenPrivate *intelScreen = intel->intelScreen;
+ GLuint clear_depth, clear_color;
+ GLint cx, cy, cw, ch;
+ GLboolean all;
+ GLint pitch;
+ GLint cpp = intelScreen->cpp;
+ GLint i;
+ GLuint BR13, CMD, D_CMD;
+ BATCH_LOCALS;
+
+ intelFlush( &intel->ctx );
+ LOCK_HARDWARE( intel );
+
+ /* get clear bounds after locking */
+ cx = intel->ctx.DrawBuffer->_Xmin;
+ cy = intel->ctx.DrawBuffer->_Ymin;
+ cw = intel->ctx.DrawBuffer->_Xmax - cx;
+ ch = intel->ctx.DrawBuffer->_Ymax - cy;
+ all = (cw == intel->ctx.DrawBuffer->Width &&
+ ch == intel->ctx.DrawBuffer->Height);
+
+ pitch = intelScreen->front.pitch;
+
+ clear_color = intel->ClearColor;
+ clear_depth = 0;
+
+ if (buffers & BUFFER_BIT_DEPTH) {
+ clear_depth = (GLuint)(ctx->Depth.Clear * intel->ClearDepth);
+ }
+
+ if (buffers & BUFFER_BIT_STENCIL) {
+ clear_depth |= (ctx->Stencil.Clear & 0xff) << 24;
+ }
+
+ switch(cpp) {
+ case 2:
+ BR13 = (0xF0 << 16) | (pitch) | (1<<24);
+ D_CMD = CMD = XY_COLOR_BLT_CMD;
+ break;
+ case 4:
+ BR13 = (0xF0 << 16) | (pitch) | (1<<24) | (1<<25);
+ CMD = (XY_COLOR_BLT_CMD |
+ XY_COLOR_BLT_WRITE_ALPHA |
+ XY_COLOR_BLT_WRITE_RGB);
+ D_CMD = XY_COLOR_BLT_CMD;
+ if (buffers & BUFFER_BIT_DEPTH) D_CMD |= XY_COLOR_BLT_WRITE_RGB;
+ if (buffers & BUFFER_BIT_STENCIL) D_CMD |= XY_COLOR_BLT_WRITE_ALPHA;
+ break;
+ default:
+ BR13 = (0xF0 << 16) | (pitch) | (1<<24);
+ D_CMD = CMD = XY_COLOR_BLT_CMD;
+ break;
+ }
+
+ {
+ /* flip top to bottom */
+ cy = intel->driDrawable->h - cy - ch;
+ cx = cx + intel->drawX;
+ cy += intel->drawY;
+
+ /* adjust for page flipping */
+ if ( intel->sarea->pf_current_page == 1 ) {
+ GLuint tmp = buffers;
+
+ buffers &= ~(BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT);
+ if ( tmp & BUFFER_BIT_FRONT_LEFT ) buffers |= BUFFER_BIT_BACK_LEFT;
+ if ( tmp & BUFFER_BIT_BACK_LEFT ) buffers |= BUFFER_BIT_FRONT_LEFT;
+ }
+
+ 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 ( buffers & BUFFER_BIT_FRONT_LEFT ) {
+ BEGIN_BATCH( 6);
+ OUT_BATCH( CMD );
+ OUT_BATCH( BR13 );
+ OUT_BATCH( (b.y1 << 16) | b.x1 );
+ OUT_BATCH( (b.y2 << 16) | b.x2 );
+ OUT_BATCH( intelScreen->front.offset );
+ OUT_BATCH( clear_color );
+ ADVANCE_BATCH();
+ }
+
+ if ( buffers & BUFFER_BIT_BACK_LEFT ) {
+ BEGIN_BATCH( 6);
+ OUT_BATCH( CMD );
+ OUT_BATCH( BR13 );
+ OUT_BATCH( (b.y1 << 16) | b.x1 );
+ OUT_BATCH( (b.y2 << 16) | b.x2 );
+ OUT_BATCH( intelScreen->back.offset );
+ OUT_BATCH( clear_color );
+ ADVANCE_BATCH();
+ }
+
+ if ( buffers & (BUFFER_BIT_STENCIL | BUFFER_BIT_DEPTH) ) {
+ BEGIN_BATCH( 6);
+ OUT_BATCH( D_CMD );
+ OUT_BATCH( BR13 );
+ OUT_BATCH( (b.y1 << 16) | b.x1 );
+ OUT_BATCH( (b.y2 << 16) | b.x2 );
+ OUT_BATCH( intelScreen->depth.offset );
+ OUT_BATCH( clear_depth );
+ ADVANCE_BATCH();
+ }
+ }
+ }
+ intelFlushBatchLocked( intel, GL_TRUE, GL_FALSE, GL_TRUE );
+ UNLOCK_HARDWARE( intel );
+}
+
+
+
+
+void intelDestroyBatchBuffer( GLcontext *ctx )
+{
+ intelContextPtr intel = INTEL_CONTEXT(ctx);
+
+ if (intel->alloc.offset) {
+ intelFreeAGP( intel, intel->alloc.ptr );
+ intel->alloc.ptr = NULL;
+ intel->alloc.offset = 0;
+ }
+ else if (intel->alloc.ptr) {
+ free(intel->alloc.ptr);
+ intel->alloc.ptr = NULL;
+ }
+
+ memset(&intel->batch, 0, sizeof(intel->batch));
+}
+
+
+void intelInitBatchBuffer( GLcontext *ctx )
+{
+ intelContextPtr intel = INTEL_CONTEXT(ctx);
+
+ /* This path isn't really safe with rotate:
+ */
+ if (getenv("INTEL_BATCH") && intel->intelScreen->allow_batchbuffer) {
+ switch (intel->intelScreen->deviceID) {
+ case PCI_CHIP_I865_G:
+ /* HW bug? Seems to crash if batchbuffer crosses 4k boundary.
+ */
+ intel->alloc.size = 8 * 1024;
+ break;
+ default:
+ /* This is the smallest amount of memory the kernel deals with.
+ * We'd ideally like to make this smaller.
+ */
+ intel->alloc.size = 1 << intel->intelScreen->logTextureGranularity;
+ break;
+ }
+
+ intel->alloc.ptr = intelAllocateAGP( intel, intel->alloc.size );
+ if (intel->alloc.ptr)
+ intel->alloc.offset =
+ intelAgpOffsetFromVirtual( intel, intel->alloc.ptr );
+ else
+ intel->alloc.offset = 0; /* OK? */
+ }
+
+ /* The default is now to use a local buffer and pass that to the
+ * kernel. This is also a fallback if allocation fails on the
+ * above path:
+ */
+ if (!intel->alloc.ptr) {
+ intel->alloc.size = 8 * 1024;
+ intel->alloc.ptr = malloc( intel->alloc.size );
+ intel->alloc.offset = 0;
+ }
+
+ assert(intel->alloc.ptr);
+}