void intel_batch_emit_flush(ScrnInfoPtr scrn) { intel_screen_private *intel = intel_get_screen_private(scrn); int flags; assert (!intel->in_batch_atomic); /* Big hammer, look to the pipelined flushes in future. */ if ((INTEL_INFO(intel)->gen >= 060)) { if (intel->current_batch == BLT_BATCH) { BEGIN_BATCH_BLT(4); OUT_BATCH(MI_FLUSH_DW | 2); OUT_BATCH(0); OUT_BATCH(0); OUT_BATCH(0); ADVANCE_BATCH(); } else { if ((INTEL_INFO(intel)->gen == 060)) { /* HW-Workaround for Sandybdrige */ intel_emit_post_sync_nonzero_flush(scrn); } else { BEGIN_BATCH(4); OUT_BATCH(BRW_PIPE_CONTROL | (4 - 2)); OUT_BATCH(BRW_PIPE_CONTROL_WC_FLUSH | BRW_PIPE_CONTROL_TC_FLUSH | BRW_PIPE_CONTROL_NOWRITE); OUT_BATCH(0); /* write address */ OUT_BATCH(0); /* write data */ ADVANCE_BATCH(); } } } else { flags = MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE; if (INTEL_INFO(intel)->gen >= 040) flags = 0; BEGIN_BATCH(1); OUT_BATCH(MI_FLUSH | flags); ADVANCE_BATCH(); } intel_batch_do_flush(scrn); }
static void i915_emit_composite_setup(ScrnInfoPtr scrn) { intel_screen_private *intel = intel_get_screen_private(scrn); int op = intel->i915_render_state.op; PicturePtr mask_picture = intel->render_mask_picture; PicturePtr dest_picture = intel->render_dest_picture; PixmapPtr mask = intel->render_mask; PixmapPtr dest = intel->render_dest; Bool is_solid_src, is_solid_mask; int tex_count, t; intel->needs_render_state_emit = FALSE; IntelEmitInvarientState(scrn); intel->last_3d = LAST_3D_RENDER; is_solid_src = intel->render_source_is_solid; is_solid_mask = intel->render_mask_is_solid; tex_count = 0; tex_count += ! is_solid_src; tex_count += mask && ! is_solid_mask; assert(intel->in_batch_atomic); if (tex_count != 0) { OUT_BATCH(_3DSTATE_MAP_STATE | (3 * tex_count)); OUT_BATCH((1 << tex_count) - 1); for (t = 0; t < tex_count; t++) { OUT_RELOC_PIXMAP(intel->texture[t], I915_GEM_DOMAIN_SAMPLER, 0, 0); OUT_BATCH(intel->mapstate[3*t + 1]); OUT_BATCH(intel->mapstate[3*t + 2]); } OUT_BATCH(_3DSTATE_SAMPLER_STATE | (3 * tex_count)); OUT_BATCH((1 << tex_count) - 1); for (t = 0; t < tex_count; t++) { OUT_BATCH(intel->samplerstate[3*t + 0]); OUT_BATCH(intel->samplerstate[3*t + 1]); OUT_BATCH(intel->samplerstate[3*t + 2]); } } if (is_solid_src) { OUT_BATCH (_3DSTATE_DFLT_DIFFUSE_CMD); OUT_BATCH (intel->render_source_solid); } if (mask && is_solid_mask) { OUT_BATCH (_3DSTATE_DFLT_SPEC_CMD); OUT_BATCH (intel->render_mask_solid); } /* BUF_INFO is an implicit flush, so avoid if the target has not changed. * XXX However for reasons unfathomed, correct rendering in KDE requires * at least a MI_FLUSH | INHIBIT_RENDER_CACHE_FLUSH here. */ if (1 || dest != intel->render_current_dest) { uint32_t tiling_bits; intel_batch_do_flush(scrn); if (intel_pixmap_tiled(dest)) { tiling_bits = BUF_3D_TILED_SURFACE; if (intel_get_pixmap_private(dest)->tiling == I915_TILING_Y) tiling_bits |= BUF_3D_TILE_WALK_Y; } else tiling_bits = 0; OUT_BATCH(_3DSTATE_BUF_INFO_CMD); OUT_BATCH(BUF_3D_ID_COLOR_BACK | tiling_bits | BUF_3D_PITCH(intel_pixmap_pitch(dest))); OUT_RELOC_PIXMAP(dest, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0); OUT_BATCH(_3DSTATE_DST_BUF_VARS_CMD); OUT_BATCH(intel->i915_render_state.dst_format); /* draw rect is unconditional */ OUT_BATCH(_3DSTATE_DRAW_RECT_CMD); OUT_BATCH(0x00000000); OUT_BATCH(0x00000000); /* ymin, xmin */ OUT_BATCH(DRAW_YMAX(dest->drawable.height - 1) | DRAW_XMAX(dest->drawable.width - 1)); /* yorig, xorig (relate to color buffer?) */ OUT_BATCH(0x00000000); intel->render_current_dest = dest; } { uint32_t ss2; ss2 = ~0; t = 0; if (! is_solid_src) { ss2 &= ~S2_TEXCOORD_FMT(t, TEXCOORDFMT_NOT_PRESENT); ss2 |= S2_TEXCOORD_FMT(t, intel_transform_is_affine(intel->transform[t]) ? TEXCOORDFMT_2D : TEXCOORDFMT_4D); t++; } if (mask && ! is_solid_mask) { ss2 &= ~S2_TEXCOORD_FMT(t, TEXCOORDFMT_NOT_PRESENT); ss2 |= S2_TEXCOORD_FMT(t, intel_transform_is_affine(intel->transform[t]) ? TEXCOORDFMT_2D : TEXCOORDFMT_4D); t++; } if (intel->needs_render_ca_pass) { OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(2) | 0); OUT_BATCH(ss2); } else { OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(2) | I1_LOAD_S(6) | 1); OUT_BATCH(ss2); OUT_BATCH(i915_get_blend_cntl(op, mask_picture, dest_picture->format)); } } if (! intel->needs_render_ca_pass) i915_composite_emit_shader(intel, op); }
Bool i915_prepare_composite(int op, PicturePtr source_picture, PicturePtr mask_picture, PicturePtr dest_picture, PixmapPtr source, PixmapPtr mask, PixmapPtr dest) { ScrnInfoPtr scrn = xf86Screens[dest_picture->pDrawable->pScreen->myNum]; intel_screen_private *intel = intel_get_screen_private(scrn); drm_intel_bo *bo_table[] = { NULL, /* batch_bo */ intel_get_pixmap_bo(dest), source ? intel_get_pixmap_bo(source) : NULL, mask ? intel_get_pixmap_bo(mask) : NULL, }; int tex_unit = 0; int floats_per_vertex; intel->render_source_picture = source_picture; intel->render_source = source; intel->render_mask_picture = mask_picture; intel->render_mask = mask; intel->render_dest_picture = dest_picture; intel->render_dest = dest; intel->render_source_is_solid = FALSE; if (source_picture->pSourcePict) { SourcePict *source = source_picture->pSourcePict; if (source->type == SourcePictTypeSolidFill) { intel->render_source_is_solid = TRUE; intel->render_source_solid = source->solidFill.color; } } if (!intel->render_source_is_solid && !intel_check_pitch_3d(source)) return FALSE; intel->render_mask_is_solid = FALSE; if (mask) { if (mask_picture->pSourcePict) { SourcePict *source = mask_picture->pSourcePict; if (source->type == SourcePictTypeSolidFill) { intel->render_mask_is_solid = TRUE; intel->render_mask_solid = source->solidFill.color; } } if (!intel->render_mask_is_solid && !intel_check_pitch_3d(mask)) return FALSE; } if (!intel_check_pitch_3d(dest)) return FALSE; if (!i915_get_dest_format(dest_picture, &intel->i915_render_state.dst_format)) return FALSE; if (!intel_get_aperture_space(scrn, bo_table, ARRAY_SIZE(bo_table))) return FALSE; intel->needs_render_ca_pass = FALSE; if (mask_picture != NULL && mask_picture->componentAlpha && PICT_FORMAT_RGB(mask_picture->format)) { /* Check if it's component alpha that relies on a source alpha * and on the source value. We can only get one of those * into the single source value that we get to blend with. */ if (i915_blend_op[op].src_alpha && (i915_blend_op[op].src_blend != BLENDFACT_ZERO)) { if (op != PictOpOver) return FALSE; intel->needs_render_ca_pass = TRUE; } } intel->transform[0] = NULL; intel->scale_units[0][0] = -1; intel->scale_units[0][1] = -1; intel->transform[1] = NULL; intel->scale_units[1][0] = -1; intel->scale_units[1][1] = -1; floats_per_vertex = 2; /* dest x/y */ if (! intel->render_source_is_solid) { if (!i915_texture_setup(source_picture, source, tex_unit++)) { intel_debug_fallback(scrn, "fail to setup src texture\n"); return FALSE; } if (intel_transform_is_affine(source_picture->transform)) floats_per_vertex += 2; /* src x/y */ else floats_per_vertex += 4; /* src x/y/z/w */ } if (mask != NULL) { if (! intel->render_mask_is_solid) { if (!i915_texture_setup(mask_picture, mask, tex_unit++)) { intel_debug_fallback(scrn, "fail to setup mask texture\n"); return FALSE; } if (intel_transform_is_affine(mask_picture->transform)) floats_per_vertex += 2; /* mask x/y */ else floats_per_vertex += 4; /* mask x/y/z/w */ } } intel->i915_render_state.op = op; /* BUF_INFO is an implicit flush */ if (dest != intel->render_current_dest) intel_batch_do_flush(scrn); else if((source && intel_pixmap_is_dirty(source)) || (mask && intel_pixmap_is_dirty(mask))) intel_batch_emit_flush(scrn); intel->needs_render_state_emit = TRUE; intel->prim_emit = i915_emit_composite_primitive; if (!mask) { if (intel->render_source_is_solid) intel->prim_emit = i915_emit_composite_primitive_constant; else if (intel->transform[0] == NULL) intel->prim_emit = i915_emit_composite_primitive_identity_source; else if (intel_transform_is_affine(intel->transform[0])) intel->prim_emit = i915_emit_composite_primitive_affine_source; } else { if (intel->transform[0] == NULL) { if (intel->render_source_is_solid) intel->prim_emit = i915_emit_composite_primitive_constant_identity_mask; else if (intel->transform[1] == NULL) intel->prim_emit = i915_emit_composite_primitive_identity_source_mask; } } if (floats_per_vertex != intel->floats_per_vertex) { intel->floats_per_vertex = floats_per_vertex; intel->needs_render_vertex_emit = TRUE; } return TRUE; }