diff options
Diffstat (limited to 'src/mesa/drivers/dri/i915/intel_tris.c')
-rw-r--r-- | src/mesa/drivers/dri/i915/intel_tris.c | 237 |
1 files changed, 76 insertions, 161 deletions
diff --git a/src/mesa/drivers/dri/i915/intel_tris.c b/src/mesa/drivers/dri/i915/intel_tris.c index 5f4b852212..bbb4e0f3cd 100644 --- a/src/mesa/drivers/dri/i915/intel_tris.c +++ b/src/mesa/drivers/dri/i915/intel_tris.c @@ -25,12 +25,6 @@ * **************************************************************************/ -/** @file intel_tris.c - * - * This file contains functions for managing the vertex buffer and emitting - * primitives into it. - */ - #include "glheader.h" #include "context.h" #include "macros.h" @@ -53,185 +47,111 @@ #include "intel_reg.h" #include "intel_span.h" #include "intel_tex.h" -#include "intel_chipset.h" -#include "i830_context.h" -#include "i830_reg.h" static void intelRenderPrimitive(GLcontext * ctx, GLenum prim); static void intelRasterPrimitive(GLcontext * ctx, GLenum rprim, GLuint hwprim); -/** Sets the primitive type for a primitive sequence, flushing as needed. */ -void intel_set_prim(struct intel_context *intel, uint32_t prim) +/* + */ +static void +intel_flush_inline_primitive(struct intel_context *intel) { - if (prim != intel->prim.primitive) { - INTEL_FIREVERTICES(intel); - intel->prim.primitive = prim; - } -} + GLuint used = intel->batch->ptr - intel->prim.start_ptr; -/** Returns mapped VB space for the given number of vertices */ -uint32_t *intel_get_prim_space(struct intel_context *intel, unsigned int count) -{ - uint32_t *addr; - - /* Check for space in the existing VB */ - if (intel->prim.vb_bo == NULL || - (intel->prim.current_offset + - count * intel->vertex_size * 4) > INTEL_VB_SIZE || - (intel->prim.count + count) >= (1 << 16)) { - /* Flush existing prim if any */ - INTEL_FIREVERTICES(intel); + assert(intel->prim.primitive != ~0); - intel_finish_vb(intel); +/* _mesa_printf("/\n"); */ - /* Start a new VB */ - if (intel->prim.vb == NULL) - intel->prim.vb = malloc(INTEL_VB_SIZE); - intel->prim.vb_bo = dri_bo_alloc(intel->bufmgr, "vb", - INTEL_VB_SIZE, 4); - intel->prim.start_offset = 0; - intel->prim.current_offset = 0; - } + if (used < 8) + goto do_discard; + + *(int *) intel->prim.start_ptr = (_3DPRIMITIVE | + intel->prim.primitive | (used / 4 - 2)); - intel->prim.flush = intel_flush_prim; + goto finished; - addr = (uint32_t *)(intel->prim.vb + intel->prim.current_offset); - intel->prim.current_offset += intel->vertex_size * 4 * count; - intel->prim.count += count; + do_discard: + intel->batch->ptr -= used; - return addr; + finished: + intel->prim.primitive = ~0; + intel->prim.start_ptr = 0; + intel->prim.flush = 0; } -/** Dispatches the accumulated primitive to the batchbuffer. */ -void intel_flush_prim(struct intel_context *intel) + +/* Emit a primitive referencing vertices in a vertex buffer. + */ +void +intelStartInlinePrimitive(struct intel_context *intel, + GLuint prim, GLuint batch_flags) { BATCH_LOCALS; - dri_bo *aper_array[2]; - dri_bo *vb_bo; - - /* Must be called after an intel_start_prim. */ - assert(intel->prim.primitive != ~0); - - if (intel->prim.count == 0) - return; - - /* Keep a reference on the BO as it may get finished as we start the - * batch emit. - */ - vb_bo = intel->prim.vb_bo; - dri_bo_reference(vb_bo); intel_wait_flips(intel); intel->vtbl.emit_state(intel); - aper_array[0] = intel->batch->buf; - aper_array[1] = vb_bo; - if (dri_bufmgr_check_aperture_space(aper_array, 2)) { - intel_batchbuffer_flush(intel->batch); - intel->vtbl.emit_state(intel); - } - - /* Ensure that we don't start a new batch for the following emit, which - * depends on the state just emitted. emit_state should be making sure we - * have the space for this. - */ intel->no_batch_wrap = GL_TRUE; - /* Check that we actually emitted the state into this batch, using the - * UPLOAD_CTX bit as the signal. +/* _mesa_printf("%s *", __progname); */ + + /* Emit a slot which will be filled with the inline primitive + * command later. */ + BEGIN_BATCH(2, batch_flags); + OUT_BATCH(0); + assert((intel->batch->dirty_state & (1<<1)) == 0); -#if 0 - printf("emitting %d..%d=%d vertices size %d\n", intel->prim.start_offset, - intel->prim.current_offset, intel->prim.count, - intel->vertex_size * 4); -#endif + intel->prim.start_ptr = intel->batch->ptr; + intel->prim.primitive = prim; + intel->prim.flush = intel_flush_inline_primitive; - if (IS_9XX(intel->intelScreen->deviceID)) { - BEGIN_BATCH(5, LOOP_CLIPRECTS); - OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | - I1_LOAD_S(0) | I1_LOAD_S(1) | 1); - assert((intel->prim.start_offset & !S0_VB_OFFSET_MASK) == 0); - OUT_RELOC(vb_bo, I915_GEM_DOMAIN_VERTEX, 0, - intel->prim.start_offset); - OUT_BATCH((intel->vertex_size << S1_VERTEX_WIDTH_SHIFT) | - (intel->vertex_size << S1_VERTEX_PITCH_SHIFT)); - - OUT_BATCH(_3DPRIMITIVE | - PRIM_INDIRECT | - PRIM_INDIRECT_SEQUENTIAL | - intel->prim.primitive | - intel->prim.count); - OUT_BATCH(0); /* Beginning vertex index */ - ADVANCE_BATCH(); - } else { - struct i830_context *i830 = i830_context(&intel->ctx); - - BEGIN_BATCH(5, LOOP_CLIPRECTS); - OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | - I1_LOAD_S(0) | I1_LOAD_S(2) | 1); - /* S0 */ - assert((intel->prim.start_offset & !S0_VB_OFFSET_MASK_830) == 0); - OUT_RELOC(vb_bo, I915_GEM_DOMAIN_VERTEX, 0, - intel->prim.start_offset | - (intel->vertex_size << S0_VB_PITCH_SHIFT_830) | - S0_VB_ENABLE_830); - /* S1 - * This is somewhat unfortunate -- VB width is tied up with - * vertex format data that we've already uploaded through - * _3DSTATE_VFT[01]_CMD. We may want to replace emits of VFT state with - * STATE_IMMEDIATE_1 like this to avoid duplication. - */ - OUT_BATCH((i830->state.Ctx[I830_CTXREG_VF] & VFT0_TEX_COUNT_MASK) >> - VFT0_TEX_COUNT_SHIFT << S2_TEX_COUNT_SHIFT_830 | - (i830->state.Ctx[I830_CTXREG_VF2] << 16) | - intel->vertex_size << S2_VERTEX_0_WIDTH_SHIFT_830); - - OUT_BATCH(_3DPRIMITIVE | - PRIM_INDIRECT | - PRIM_INDIRECT_SEQUENTIAL | - intel->prim.primitive | - intel->prim.count); - OUT_BATCH(0); /* Beginning vertex index */ - ADVANCE_BATCH(); - } + OUT_BATCH(0); + ADVANCE_BATCH(); intel->no_batch_wrap = GL_FALSE; - intel->prim.flush = NULL; - intel->prim.start_offset = intel->prim.current_offset; - if (!IS_9XX(intel->intelScreen->deviceID)) - intel->prim.start_offset = ALIGN(intel->prim.start_offset, 128); - intel->prim.count = 0; +/* _mesa_printf(">"); */ +} + + +void +intelWrapInlinePrimitive(struct intel_context *intel) +{ + GLuint prim = intel->prim.primitive; + enum cliprect_mode cliprect_mode = intel->batch->cliprect_mode; - dri_bo_unreference(vb_bo); + intel_flush_inline_primitive(intel); + intel_batchbuffer_flush(intel->batch); + intelStartInlinePrimitive(intel, prim, cliprect_mode); /* ??? */ } -/** - * Uploads the locally-accumulated VB into the buffer object. - * - * This avoids us thrashing the cachelines in and out as the buffer gets - * filled, dispatched, then reused as the hardware completes rendering from it, - * and also lets us clflush less if we dispatch with a partially-filled VB. - * - * This is called normally from get_space when we're finishing a BO, but also - * at batch flush time so that we don't try accessing the contents of a - * just-dispatched buffer. - */ -void intel_finish_vb(struct intel_context *intel) +GLuint * +intelExtendInlinePrimitive(struct intel_context *intel, GLuint dwords) { - if (intel->prim.vb_bo == NULL) - return; + GLuint sz = dwords * sizeof(GLuint); + GLuint *ptr; + + assert(intel->prim.flush == intel_flush_inline_primitive); + + if (intel_batchbuffer_space(intel->batch) < sz) + intelWrapInlinePrimitive(intel); + +/* _mesa_printf("."); */ + + intel->vtbl.assert_not_dirty(intel); - dri_bo_subdata(intel->prim.vb_bo, 0, intel->prim.start_offset, - intel->prim.vb); - dri_bo_unreference(intel->prim.vb_bo); - intel->prim.vb_bo = NULL; + ptr = (GLuint *) intel->batch->ptr; + intel->batch->ptr += sz; + + return ptr; } + + /*********************************************************************** * Emit primitives as inline vertices * ***********************************************************************/ @@ -262,7 +182,7 @@ intel_draw_quad(struct intel_context *intel, intelVertexPtr v1, intelVertexPtr v2, intelVertexPtr v3) { GLuint vertsize = intel->vertex_size; - GLuint *vb = intel_get_prim_space(intel, 6); + GLuint *vb = intelExtendInlinePrimitive(intel, 6 * vertsize); int j; COPY_DWORDS(j, vb, vertsize, v0); @@ -290,7 +210,7 @@ intel_draw_triangle(struct intel_context *intel, intelVertexPtr v0, intelVertexPtr v1, intelVertexPtr v2) { GLuint vertsize = intel->vertex_size; - GLuint *vb = intel_get_prim_space(intel, 3); + GLuint *vb = intelExtendInlinePrimitive(intel, 3 * vertsize); int j; COPY_DWORDS(j, vb, vertsize, v0); @@ -304,7 +224,7 @@ intel_draw_line(struct intel_context *intel, intelVertexPtr v0, intelVertexPtr v1) { GLuint vertsize = intel->vertex_size; - GLuint *vb = intel_get_prim_space(intel, 2); + GLuint *vb = intelExtendInlinePrimitive(intel, 2 * vertsize); int j; COPY_DWORDS(j, vb, vertsize, v0); @@ -316,7 +236,7 @@ static void intel_draw_point(struct intel_context *intel, intelVertexPtr v0) { GLuint vertsize = intel->vertex_size; - GLuint *vb = intel_get_prim_space(intel, 1); + GLuint *vb = intelExtendInlinePrimitive(intel, vertsize); int j; /* Adjust for sub pixel position -- still required for conform. */ @@ -825,7 +745,7 @@ intelFastRenderClippedPoly(GLcontext * ctx, const GLuint * elts, GLuint n) { struct intel_context *intel = intel_context(ctx); const GLuint vertsize = intel->vertex_size; - GLuint *vb = intel_get_prim_space(intel, (n - 2) * 3); + GLuint *vb = intelExtendInlinePrimitive(intel, (n - 2) * 3 * vertsize); GLubyte *vertptr = (GLubyte *) intel->verts; const GLuint *start = (const GLuint *) V(elts[0]); int i, j; @@ -1030,7 +950,7 @@ intelRasterPrimitive(GLcontext * ctx, GLenum rprim, GLuint hwprim) if (hwprim != intel->prim.primitive) { INTEL_FIREVERTICES(intel); - intel_set_prim(intel, hwprim); + intelStartInlinePrimitive(intel, hwprim, LOOP_CLIPRECTS); } } @@ -1163,18 +1083,15 @@ intel_meta_draw_poly(struct intel_context *intel, union fi *vb; GLint i; GLboolean was_locked = intel->locked; - unsigned int saved_vertex_size = intel->vertex_size; if (!was_locked) LOCK_HARDWARE(intel); - intel->vertex_size = 6; - /* All 3d primitives should be emitted with LOOP_CLIPRECTS, * otherwise the drawing origin (DR4) might not be set correctly. */ - intel_set_prim(intel, PRIM3D_TRIFAN); - vb = (union fi *) intel_get_prim_space(intel, n); + intelStartInlinePrimitive(intel, PRIM3D_TRIFAN, LOOP_CLIPRECTS); + vb = (union fi *) intelExtendInlinePrimitive(intel, n * 6); for (i = 0; i < n; i++) { vb[0].f = xy[i][0]; @@ -1188,8 +1105,6 @@ intel_meta_draw_poly(struct intel_context *intel, INTEL_FIREVERTICES(intel); - intel->vertex_size = saved_vertex_size; - if (!was_locked) UNLOCK_HARDWARE(intel); } |