/* Push the state into the sarea and/or texture memory. */ static void i915_emit_state(struct intel_context *intel) { struct i915_context *i915 = i915_context(&intel->ctx); struct i915_hw_state *state = i915->current; int i; GLuint dirty; BATCH_LOCALS; /* We don't hold the lock at this point, so want to make sure that * there won't be a buffer wrap. * * It might be better to talk about explicit places where * scheduling is allowed, rather than assume that it is whenever a * batchbuffer fills up. */ intel_batchbuffer_require_space(intel->batch, get_state_size(state), 0); /* Do this here as we may have flushed the batchbuffer above, * causing more state to be dirty! */ dirty = get_dirty(state); if (INTEL_DEBUG & DEBUG_STATE) fprintf(stderr, "%s dirty: %x\n", __FUNCTION__, dirty); if (dirty & I915_UPLOAD_INVARIENT) { if (INTEL_DEBUG & DEBUG_STATE) fprintf(stderr, "I915_UPLOAD_INVARIENT:\n"); i915_emit_invarient_state(intel); } if (dirty & I915_UPLOAD_CTX) { if (INTEL_DEBUG & DEBUG_STATE) fprintf(stderr, "I915_UPLOAD_CTX:\n"); emit(intel, state->Ctx, sizeof(state->Ctx)); } if (dirty & I915_UPLOAD_BUFFERS) { if (INTEL_DEBUG & DEBUG_STATE) fprintf(stderr, "I915_UPLOAD_BUFFERS:\n"); BEGIN_BATCH(I915_DEST_SETUP_SIZE + 2, 0); OUT_BATCH(state->Buffer[I915_DESTREG_CBUFADDR0]); OUT_BATCH(state->Buffer[I915_DESTREG_CBUFADDR1]); OUT_RELOC(state->draw_region->buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE, DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE, state->draw_region->draw_offset); if (state->depth_region) { OUT_BATCH(state->Buffer[I915_DESTREG_DBUFADDR0]); OUT_BATCH(state->Buffer[I915_DESTREG_DBUFADDR1]); OUT_RELOC(state->depth_region->buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE, DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE, state->depth_region->draw_offset); } OUT_BATCH(state->Buffer[I915_DESTREG_DV0]); OUT_BATCH(state->Buffer[I915_DESTREG_DV1]); OUT_BATCH(state->Buffer[I915_DESTREG_SENABLE]); OUT_BATCH(state->Buffer[I915_DESTREG_SR0]); OUT_BATCH(state->Buffer[I915_DESTREG_SR1]); OUT_BATCH(state->Buffer[I915_DESTREG_SR2]); ADVANCE_BATCH(); } if (dirty & I915_UPLOAD_STIPPLE) { if (INTEL_DEBUG & DEBUG_STATE) fprintf(stderr, "I915_UPLOAD_STIPPLE:\n"); emit(intel, state->Stipple, sizeof(state->Stipple)); } if (dirty & I915_UPLOAD_FOG) { if (INTEL_DEBUG & DEBUG_STATE) fprintf(stderr, "I915_UPLOAD_FOG:\n"); emit(intel, state->Fog, sizeof(state->Fog)); } /* Combine all the dirty texture state into a single command to * avoid lockups on I915 hardware. */ if (dirty & I915_UPLOAD_TEX_ALL) { int nr = 0; for (i = 0; i < I915_TEX_UNITS; i++) if (dirty & I915_UPLOAD_TEX(i)) nr++; BEGIN_BATCH(2 + nr * 3, 0); OUT_BATCH(_3DSTATE_MAP_STATE | (3 * nr)); OUT_BATCH((dirty & I915_UPLOAD_TEX_ALL) >> I915_UPLOAD_TEX_0_SHIFT); for (i = 0; i < I915_TEX_UNITS; i++) if (dirty & I915_UPLOAD_TEX(i)) { if (state->tex_buffer[i]) { OUT_RELOC(state->tex_buffer[i], DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ, DRM_BO_MASK_MEM | DRM_BO_FLAG_READ, state->tex_offset[i]); } else { assert(i == 0); assert(state == &i915->meta); OUT_BATCH(0); } OUT_BATCH(state->Tex[i][I915_TEXREG_MS3]); OUT_BATCH(state->Tex[i][I915_TEXREG_MS4]); } ADVANCE_BATCH(); BEGIN_BATCH(2 + nr * 3, 0); OUT_BATCH(_3DSTATE_SAMPLER_STATE | (3 * nr)); OUT_BATCH((dirty & I915_UPLOAD_TEX_ALL) >> I915_UPLOAD_TEX_0_SHIFT); for (i = 0; i < I915_TEX_UNITS; i++) if (dirty & I915_UPLOAD_TEX(i)) { OUT_BATCH(state->Tex[i][I915_TEXREG_SS2]); OUT_BATCH(state->Tex[i][I915_TEXREG_SS3]); OUT_BATCH(state->Tex[i][I915_TEXREG_SS4]); } ADVANCE_BATCH(); }
/* Push the state into the sarea and/or texture memory. */ static void i915_emit_state(struct intel_context *intel) { struct i915_context *i915 = i915_context(&intel->ctx); struct i915_hw_state *state = &i915->state; int i, count, aper_count; GLuint dirty; drm_intel_bo *aper_array[3 + I915_TEX_UNITS]; GET_CURRENT_CONTEXT(ctx); BATCH_LOCALS; /* We don't hold the lock at this point, so want to make sure that * there won't be a buffer wrap between the state emits and the primitive * emit header. * * It might be better to talk about explicit places where * scheduling is allowed, rather than assume that it is whenever a * batchbuffer fills up. */ intel_batchbuffer_require_space(intel, get_state_size(state) + INTEL_PRIM_EMIT_SIZE); count = 0; again: if (intel->batch.bo == NULL) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "i915 emit state"); assert(0); } aper_count = 0; dirty = get_dirty(state); aper_array[aper_count++] = intel->batch.bo; if (dirty & I915_UPLOAD_BUFFERS) { if (state->draw_region) aper_array[aper_count++] = state->draw_region->bo; if (state->depth_region) aper_array[aper_count++] = state->depth_region->bo; } if (dirty & I915_UPLOAD_TEX_ALL) { for (i = 0; i < I915_TEX_UNITS; i++) { if (dirty & I915_UPLOAD_TEX(i)) { if (state->tex_buffer[i]) { aper_array[aper_count++] = state->tex_buffer[i]; } } } } if (dri_bufmgr_check_aperture_space(aper_array, aper_count)) { if (count == 0) { count++; intel_batchbuffer_flush(intel); goto again; } else { _mesa_error(ctx, GL_OUT_OF_MEMORY, "i915 emit state"); assert(0); } } /* work out list of buffers to emit */ /* Do this here as we may have flushed the batchbuffer above, * causing more state to be dirty! */ dirty = get_dirty(state); state->emitted |= dirty; assert(get_dirty(state) == 0); if (INTEL_DEBUG & DEBUG_STATE) fprintf(stderr, "%s dirty: %x\n", __func__, dirty); if (dirty & I915_UPLOAD_INVARIENT) { if (INTEL_DEBUG & DEBUG_STATE) fprintf(stderr, "I915_UPLOAD_INVARIENT:\n"); i915_emit_invarient_state(intel); } if (dirty & I915_UPLOAD_RASTER_RULES) { if (INTEL_DEBUG & DEBUG_STATE) fprintf(stderr, "I915_UPLOAD_RASTER_RULES:\n"); emit(intel, state->RasterRules, sizeof(state->RasterRules)); } if (dirty & I915_UPLOAD_CTX) { if (INTEL_DEBUG & DEBUG_STATE) fprintf(stderr, "I915_UPLOAD_CTX:\n"); emit(intel, state->Ctx, sizeof(state->Ctx)); } if (dirty & I915_UPLOAD_BLEND) { if (INTEL_DEBUG & DEBUG_STATE) fprintf(stderr, "I915_UPLOAD_BLEND:\n"); emit(intel, state->Blend, sizeof(state->Blend)); } if (dirty & I915_UPLOAD_BUFFERS) { GLuint count; if (INTEL_DEBUG & DEBUG_STATE) fprintf(stderr, "I915_UPLOAD_BUFFERS:\n"); count = 17; if (state->Buffer[I915_DESTREG_DRAWRECT0] != MI_NOOP) count++; BEGIN_BATCH(count); OUT_BATCH(state->Buffer[I915_DESTREG_CBUFADDR0]); OUT_BATCH(state->Buffer[I915_DESTREG_CBUFADDR1]); if (state->draw_region) { OUT_RELOC(state->draw_region->bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0); } else { OUT_BATCH(0); } OUT_BATCH(state->Buffer[I915_DESTREG_DBUFADDR0]); OUT_BATCH(state->Buffer[I915_DESTREG_DBUFADDR1]); if (state->depth_region) { OUT_RELOC(state->depth_region->bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0); } else { OUT_BATCH(0); } OUT_BATCH(state->Buffer[I915_DESTREG_DV0]); OUT_BATCH(state->Buffer[I915_DESTREG_DV1]); OUT_BATCH(state->Buffer[I915_DESTREG_SR0]); OUT_BATCH(state->Buffer[I915_DESTREG_SR1]); OUT_BATCH(state->Buffer[I915_DESTREG_SR2]); OUT_BATCH(state->Buffer[I915_DESTREG_SENABLE]); if (state->Buffer[I915_DESTREG_DRAWRECT0] != MI_NOOP) OUT_BATCH(state->Buffer[I915_DESTREG_DRAWRECT0]); OUT_BATCH(state->Buffer[I915_DESTREG_DRAWRECT1]); OUT_BATCH(state->Buffer[I915_DESTREG_DRAWRECT2]); OUT_BATCH(state->Buffer[I915_DESTREG_DRAWRECT3]); OUT_BATCH(state->Buffer[I915_DESTREG_DRAWRECT4]); OUT_BATCH(state->Buffer[I915_DESTREG_DRAWRECT5]); ADVANCE_BATCH(); } if (dirty & I915_UPLOAD_STIPPLE) { if (INTEL_DEBUG & DEBUG_STATE) fprintf(stderr, "I915_UPLOAD_STIPPLE:\n"); emit(intel, state->Stipple, sizeof(state->Stipple)); } /* Combine all the dirty texture state into a single command to * avoid lockups on I915 hardware. */ if (dirty & I915_UPLOAD_TEX_ALL) { int nr = 0; GLuint unwind; for (i = 0; i < I915_TEX_UNITS; i++) if (dirty & I915_UPLOAD_TEX(i)) nr++; BEGIN_BATCH(2 + nr * 3); OUT_BATCH(_3DSTATE_MAP_STATE | (3 * nr)); OUT_BATCH((dirty & I915_UPLOAD_TEX_ALL) >> I915_UPLOAD_TEX_0_SHIFT); for (i = 0; i < I915_TEX_UNITS; i++) if (dirty & I915_UPLOAD_TEX(i)) { OUT_RELOC(state->tex_buffer[i], I915_GEM_DOMAIN_SAMPLER, 0, state->tex_offset[i]); OUT_BATCH(state->Tex[i][I915_TEXREG_MS3]); OUT_BATCH(state->Tex[i][I915_TEXREG_MS4]); } ADVANCE_BATCH(); unwind = intel->batch.used; BEGIN_BATCH(2 + nr * 3); OUT_BATCH(_3DSTATE_SAMPLER_STATE | (3 * nr)); OUT_BATCH((dirty & I915_UPLOAD_TEX_ALL) >> I915_UPLOAD_TEX_0_SHIFT); for (i = 0; i < I915_TEX_UNITS; i++) if (dirty & I915_UPLOAD_TEX(i)) { OUT_BATCH(state->Tex[i][I915_TEXREG_SS2]); OUT_BATCH(state->Tex[i][I915_TEXREG_SS3]); OUT_BATCH(state->Tex[i][I915_TEXREG_SS4]); } ADVANCE_BATCH(); if (i915->last_sampler && memcmp(intel->batch.map + i915->last_sampler, intel->batch.map + unwind, (2 + nr*3)*sizeof(int)) == 0) intel->batch.used = unwind; else i915->last_sampler = unwind; }
/* Push the state into the sarea and/or texture memory. */ static void i915_emit_state(struct intel_context *intel) { struct i915_context *i915 = i915_context(&intel->ctx); struct i915_hw_state *state = i915->current; int i; int ret, count; GLuint dirty; GET_CURRENT_CONTEXT(ctx); BATCH_LOCALS; /* We don't hold the lock at this point, so want to make sure that * there won't be a buffer wrap between the state emits and the primitive * emit header. * * It might be better to talk about explicit places where * scheduling is allowed, rather than assume that it is whenever a * batchbuffer fills up. * * Set the space as LOOP_CLIPRECTS now, since that's what our primitives * will be emitted under. */ intel_batchbuffer_require_space(intel->batch, get_state_size(state) + 8, LOOP_CLIPRECTS); count = 0; again: dirty = get_dirty(state); ret = 0; if (dirty & I915_UPLOAD_BUFFERS) { ret |= dri_bufmgr_check_aperture_space(state->draw_region->buffer); if (state->depth_region) ret |= dri_bufmgr_check_aperture_space(state->depth_region->buffer); } if (dirty & I915_UPLOAD_TEX_ALL) { for (i = 0; i < I915_TEX_UNITS; i++) if (dirty & I915_UPLOAD_TEX(i)) { if (state->tex_buffer[i]) { ret |= dri_bufmgr_check_aperture_space(state->tex_buffer[i]); } } } if (ret) { if (count == 0) { count++; intel_batchbuffer_flush(intel->batch); goto again; } else { _mesa_error(ctx, GL_OUT_OF_MEMORY, "i915 emit state"); assert(0); } } /* work out list of buffers to emit */ /* Do this here as we may have flushed the batchbuffer above, * causing more state to be dirty! */ dirty = get_dirty(state); state->emitted |= dirty; assert(get_dirty(state) == 0); if (INTEL_DEBUG & DEBUG_STATE) fprintf(stderr, "%s dirty: %x\n", __FUNCTION__, dirty); if (dirty & I915_UPLOAD_INVARIENT) { if (INTEL_DEBUG & DEBUG_STATE) fprintf(stderr, "I915_UPLOAD_INVARIENT:\n"); i915_emit_invarient_state(intel); } if (dirty & I915_UPLOAD_CTX) { if (INTEL_DEBUG & DEBUG_STATE) fprintf(stderr, "I915_UPLOAD_CTX:\n"); emit(intel, state->Ctx, sizeof(state->Ctx)); } if (dirty & I915_UPLOAD_BUFFERS) { if (INTEL_DEBUG & DEBUG_STATE) fprintf(stderr, "I915_UPLOAD_BUFFERS:\n"); BEGIN_BATCH(I915_DEST_SETUP_SIZE + 2, IGNORE_CLIPRECTS); OUT_BATCH(state->Buffer[I915_DESTREG_CBUFADDR0]); OUT_BATCH(state->Buffer[I915_DESTREG_CBUFADDR1]); OUT_RELOC(state->draw_region->buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE, state->draw_region->draw_offset); if (state->depth_region) { OUT_BATCH(state->Buffer[I915_DESTREG_DBUFADDR0]); OUT_BATCH(state->Buffer[I915_DESTREG_DBUFADDR1]); OUT_RELOC(state->depth_region->buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE, state->depth_region->draw_offset); } OUT_BATCH(state->Buffer[I915_DESTREG_DV0]); OUT_BATCH(state->Buffer[I915_DESTREG_DV1]); OUT_BATCH(state->Buffer[I915_DESTREG_SENABLE]); OUT_BATCH(state->Buffer[I915_DESTREG_SR0]); OUT_BATCH(state->Buffer[I915_DESTREG_SR1]); OUT_BATCH(state->Buffer[I915_DESTREG_SR2]); ADVANCE_BATCH(); } if (dirty & I915_UPLOAD_STIPPLE) { if (INTEL_DEBUG & DEBUG_STATE) fprintf(stderr, "I915_UPLOAD_STIPPLE:\n"); emit(intel, state->Stipple, sizeof(state->Stipple)); } if (dirty & I915_UPLOAD_FOG) { if (INTEL_DEBUG & DEBUG_STATE) fprintf(stderr, "I915_UPLOAD_FOG:\n"); emit(intel, state->Fog, sizeof(state->Fog)); } /* Combine all the dirty texture state into a single command to * avoid lockups on I915 hardware. */ if (dirty & I915_UPLOAD_TEX_ALL) { int nr = 0; for (i = 0; i < I915_TEX_UNITS; i++) if (dirty & I915_UPLOAD_TEX(i)) nr++; BEGIN_BATCH(2 + nr * 3, IGNORE_CLIPRECTS); OUT_BATCH(_3DSTATE_MAP_STATE | (3 * nr)); OUT_BATCH((dirty & I915_UPLOAD_TEX_ALL) >> I915_UPLOAD_TEX_0_SHIFT); for (i = 0; i < I915_TEX_UNITS; i++) if (dirty & I915_UPLOAD_TEX(i)) { if (state->tex_buffer[i]) { OUT_RELOC(state->tex_buffer[i], DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ, state->tex_offset[i]); } else if (state == &i915->meta) { assert(i == 0); OUT_BATCH(0); } else { OUT_BATCH(state->tex_offset[i]); } OUT_BATCH(state->Tex[i][I915_TEXREG_MS3]); OUT_BATCH(state->Tex[i][I915_TEXREG_MS4]); } ADVANCE_BATCH(); BEGIN_BATCH(2 + nr * 3, IGNORE_CLIPRECTS); OUT_BATCH(_3DSTATE_SAMPLER_STATE | (3 * nr)); OUT_BATCH((dirty & I915_UPLOAD_TEX_ALL) >> I915_UPLOAD_TEX_0_SHIFT); for (i = 0; i < I915_TEX_UNITS; i++) if (dirty & I915_UPLOAD_TEX(i)) { OUT_BATCH(state->Tex[i][I915_TEXREG_SS2]); OUT_BATCH(state->Tex[i][I915_TEXREG_SS3]); OUT_BATCH(state->Tex[i][I915_TEXREG_SS4]); } ADVANCE_BATCH(); }