summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2011-07-01 08:50:58 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2011-07-01 21:41:23 +0100
commitecbf6bbd27b1205dcf76cfe34ae2a7a3f5ec195a (patch)
tree3567b6c62c9f23a22e5136867074a0fd34f2b1e9
parentc89b37d7b43c9e588097b7fadcba3bc13a03f8bc (diff)
sna/gen2: Implement composite-spans
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r--src/sna/gen2_render.c569
-rw-r--r--src/sna/gen2_render.h14
-rw-r--r--src/sna/sna_render.c20
-rw-r--r--src/sna/sna_render.h1
-rw-r--r--src/sna/sna_trapezoids.c2
5 files changed, 511 insertions, 95 deletions
diff --git a/src/sna/gen2_render.c b/src/sna/gen2_render.c
index 06cab3c1..82c7e151 100644
--- a/src/sna/gen2_render.c
+++ b/src/sna/gen2_render.c
@@ -330,12 +330,9 @@ gen2_get_blend_factors(const struct sna_composite_op *op,
* pictures, but we need to implement it for 830/845 and there's no
* harm done in leaving it in.
*/
- cblend =
- TB0C_LAST_STAGE | TB0C_RESULT_SCALE_1X | TB0C_OP_MODULE |
- TB0C_OUTPUT_WRITE_CURRENT;
- ablend =
- TB0A_RESULT_SCALE_1X | TB0A_OP_MODULE |
- TB0A_OUTPUT_WRITE_CURRENT;
+ cblend = TB0C_LAST_STAGE | TB0C_RESULT_SCALE_1X | TB0C_OUTPUT_WRITE_CURRENT;
+ ablend = TB0A_RESULT_SCALE_1X | TB0A_OUTPUT_WRITE_CURRENT;
+
/* Get the source picture's channels into TBx_ARG1 */
if ((op->has_component_alpha && gen2_blend_op[op->op].src_alpha) ||
@@ -359,13 +356,18 @@ gen2_get_blend_factors(const struct sna_composite_op *op,
}
if (op->mask.bo) {
+ cblend |= TB0C_OP_MODULATE;
cblend |= TB0C_ARG2_SEL_TEXEL1;
- if (op->dst.format == PICT_a8 || !op->has_component_alpha)
+ if (op->dst.format == PICT_a8 ||
+ !op->has_component_alpha ||
+ PICT_FORMAT_RGB(op->mask.pict_format) == 0)
cblend |= TB0C_ARG2_REPLICATE_ALPHA;
+
ablend |= TB0A_ARG2_SEL_TEXEL1;
+ ablend |= TB0A_OP_MODULATE;
} else {
- cblend |= TB0C_ARG2_SEL_ONE;
- ablend |= TB0A_ARG2_SEL_ONE;
+ cblend |= TB0C_OP_ARG1;
+ ablend |= TB0A_OP_ARG1;
}
*c_out = cblend;
@@ -413,21 +415,6 @@ static void gen2_emit_invariant(struct sna *sna)
OUT_BATCH(_3DSTATE_MAP_CUBE | MAP_UNIT(2));
OUT_BATCH(_3DSTATE_MAP_CUBE | MAP_UNIT(3));
- OUT_BATCH(_3DSTATE_DFLT_DIFFUSE_CMD);
- OUT_BATCH(0);
-
- OUT_BATCH(_3DSTATE_DFLT_SPEC_CMD);
- OUT_BATCH(0);
-
- OUT_BATCH(_3DSTATE_DFLT_Z_CMD);
- OUT_BATCH(0);
-
- OUT_BATCH(_3DSTATE_FOG_MODE_CMD);
- OUT_BATCH(FOGFUNC_ENABLE |
- FOG_LINEAR_CONST | FOGSRC_INDEX_Z | ENABLE_FOG_DENSITY);
- OUT_BATCH(0);
- OUT_BATCH(0);
-
OUT_BATCH(_3DSTATE_MAP_TEX_STREAM_CMD |
MAP_UNIT(0) |
DISABLE_TEX_STREAM_BUMP |
@@ -473,12 +460,10 @@ static void gen2_emit_invariant(struct sna *sna)
ENABLE_TRI_FAN_PROVOKE_VRTX |
ENABLE_TRI_STRIP_PROVOKE_VRTX |
LINE_STRIP_PROVOKE_VRTX(1) |
- TRI_FAN_PROVOKE_VRTX(2) | TRI_STRIP_PROVOKE_VRTX(2));
+ TRI_FAN_PROVOKE_VRTX(2) |
+ TRI_STRIP_PROVOKE_VRTX(2));
OUT_BATCH(_3DSTATE_SCISSOR_ENABLE_CMD | DISABLE_SCISSOR_RECT);
- OUT_BATCH(_3DSTATE_SCISSOR_RECT_0_CMD);
- OUT_BATCH(0);
- OUT_BATCH(0);
OUT_BATCH(_3DSTATE_VERTEX_TRANSFORM);
OUT_BATCH(DISABLE_VIEWPORT_TRANSFORM | DISABLE_PERSPECTIVE_DIVIDE);
@@ -487,9 +472,6 @@ static void gen2_emit_invariant(struct sna *sna)
OUT_BATCH(MAGIC_W_STATE_DWORD1);
OUT_BATCH_F(1.0);
- OUT_BATCH(_3DSTATE_COLOR_FACTOR_CMD);
- OUT_BATCH(0x80808080); /* .5 required in alpha for GL_DOT3_RGBA_EXT */
-
OUT_BATCH(_3DSTATE_MAP_COORD_SETBIND_CMD);
OUT_BATCH(TEXBIND_SET3(TEXCOORDSRC_VTXSET_3) |
TEXBIND_SET2(TEXCOORDSRC_VTXSET_2) |
@@ -500,51 +482,22 @@ static void gen2_emit_invariant(struct sna *sna)
DISABLE_INDPT_ALPHA_BLEND |
ENABLE_ALPHA_BLENDFUNC | ABLENDFUNC_ADD);
- OUT_BATCH(_3DSTATE_FOG_COLOR_CMD |
- FOG_COLOR_RED(0) | FOG_COLOR_GREEN(0) | FOG_COLOR_BLUE(0));
-
OUT_BATCH(_3DSTATE_CONST_BLEND_COLOR_CMD);
OUT_BATCH(0);
OUT_BATCH(_3DSTATE_MODES_1_CMD |
ENABLE_COLR_BLND_FUNC |
BLENDFUNC_ADD |
- ENABLE_SRC_BLND_FACTOR |
- SRC_BLND_FACT(BLENDFACTOR_ONE) |
+ ENABLE_SRC_BLND_FACTOR | SRC_BLND_FACT(BLENDFACTOR_ONE) |
ENABLE_DST_BLND_FACTOR | DST_BLND_FACT(BLENDFACTOR_ZERO));
- OUT_BATCH(_3DSTATE_MODES_2_CMD |
- ENABLE_GLOBAL_DEPTH_BIAS |
- GLOBAL_DEPTH_BIAS(0) |
- ENABLE_ALPHA_TEST_FUNC |
- ALPHA_TEST_FUNC(0) | /* always */
- ALPHA_REF_VALUE(0));
+ OUT_BATCH(_3DSTATE_MODES_2_CMD);
OUT_BATCH(_3DSTATE_MODES_3_CMD |
- ENABLE_DEPTH_TEST_FUNC |
- DEPTH_TEST_FUNC(0x2) | /* COMPAREFUNC_LESS */
ENABLE_ALPHA_SHADE_MODE | ALPHA_SHADE_MODE(SHADE_MODE_LINEAR) |
ENABLE_FOG_SHADE_MODE | FOG_SHADE_MODE(SHADE_MODE_LINEAR) |
ENABLE_SPEC_SHADE_MODE | SPEC_SHADE_MODE(SHADE_MODE_LINEAR) |
ENABLE_COLOR_SHADE_MODE | COLOR_SHADE_MODE(SHADE_MODE_LINEAR) |
ENABLE_CULL_MODE | CULLMODE_NONE);
- OUT_BATCH(_3DSTATE_MODES_4_CMD |
- ENABLE_LOGIC_OP_FUNC | LOGIC_OP_FUNC(LOGICOP_COPY) |
- ENABLE_STENCIL_TEST_MASK | STENCIL_TEST_MASK(0xff) |
- ENABLE_STENCIL_WRITE_MASK | STENCIL_WRITE_MASK(0xff));
-
- OUT_BATCH(_3DSTATE_STENCIL_TEST_CMD |
- ENABLE_STENCIL_PARMS |
- STENCIL_FAIL_OP(0) | /* STENCILOP_KEEP */
- STENCIL_PASS_DEPTH_FAIL_OP(0) | /* STENCILOP_KEEP */
- STENCIL_PASS_DEPTH_PASS_OP(0) | /* STENCILOP_KEEP */
- ENABLE_STENCIL_TEST_FUNC | STENCIL_TEST_FUNC(0) | /* COMPAREFUNC_ALWAYS */
- ENABLE_STENCIL_REF_VALUE | STENCIL_REF_VALUE(0));
-
- OUT_BATCH(_3DSTATE_MODES_5_CMD |
- ENABLE_SPRITE_POINT_TEX | SPRITE_POINT_TEX_OFF |
- ENABLE_FIXED_LINE_WIDTH | FIXED_LINE_WIDTH(0x2) | /* 1.0 */
- ENABLE_FIXED_POINT_WIDTH | FIXED_POINT_WIDTH(1));
-
OUT_BATCH(_3DSTATE_ENABLES_1_CMD |
DISABLE_LOGIC_OP |
DISABLE_STENCIL_TEST |
@@ -567,22 +520,30 @@ static void gen2_emit_invariant(struct sna *sna)
/* Set default blend state */
OUT_BATCH(_3DSTATE_MAP_BLEND_OP_CMD(0) |
TEXPIPE_COLOR |
- ENABLE_TEXOUTPUT_WRT_SEL | TEXOP_OUTPUT_CURRENT |
+ ENABLE_TEXOUTPUT_WRT_SEL |
+ TEXOP_OUTPUT_CURRENT |
DISABLE_TEX_CNTRL_STAGE |
- TEXOP_SCALE_1X | TEXOP_MODIFY_PARMS |
- TEXOP_LAST_STAGE | TEXBLENDOP_ARG1);
+ TEXOP_SCALE_1X |
+ TEXOP_MODIFY_PARMS |
+ TEXOP_LAST_STAGE |
+ TEXBLENDOP_ARG1);
OUT_BATCH(_3DSTATE_MAP_BLEND_OP_CMD(0) |
TEXPIPE_ALPHA |
- ENABLE_TEXOUTPUT_WRT_SEL | TEXOP_OUTPUT_CURRENT |
- TEXOP_SCALE_1X | TEXOP_MODIFY_PARMS | TEXBLENDOP_ARG1);
+ ENABLE_TEXOUTPUT_WRT_SEL |
+ TEXOP_OUTPUT_CURRENT |
+ TEXOP_SCALE_1X |
+ TEXOP_MODIFY_PARMS |
+ TEXBLENDOP_ARG1);
OUT_BATCH(_3DSTATE_MAP_BLEND_ARG_CMD(0) |
TEXPIPE_COLOR |
TEXBLEND_ARG1 |
- TEXBLENDARG_MODIFY_PARMS | TEXBLENDARG_DIFFUSE);
+ TEXBLENDARG_MODIFY_PARMS |
+ TEXBLENDARG_DIFFUSE);
OUT_BATCH(_3DSTATE_MAP_BLEND_ARG_CMD(0) |
TEXPIPE_ALPHA |
TEXBLEND_ARG1 |
- TEXBLENDARG_MODIFY_PARMS | TEXBLENDARG_DIFFUSE);
+ TEXBLENDARG_MODIFY_PARMS |
+ TEXBLENDARG_DIFFUSE);
OUT_BATCH(_3DSTATE_AA_CMD |
AA_LINE_ECAAR_WIDTH_ENABLE |
@@ -626,13 +587,12 @@ gen2_get_batch(struct sna *sna,
gen2_emit_invariant(sna);
}
-static void gen2_emit_composite_state(struct sna *sna,
- const struct sna_composite_op *op)
+static void gen2_emit_target(struct sna *sna, const struct sna_composite_op *op)
{
- uint32_t texcoordfmt;
- uint32_t cblend, ablend;
-
- gen2_get_batch(sna, op);
+ if (sna->render_state.gen2.target == op->dst.bo->unique_id) {
+ kgem_bo_mark_dirty(op->dst.bo);
+ return;
+ }
OUT_BATCH(_3DSTATE_BUF_INFO_CMD);
OUT_BATCH(BUF_3D_ID_COLOR_BACK |
@@ -654,6 +614,18 @@ static void gen2_emit_composite_state(struct sna *sna,
DRAW_XMAX(op->dst.width - 1));
OUT_BATCH(0); /* yorig, xorig */
+ sna->render_state.gen2.target = op->dst.bo->unique_id;
+}
+
+static void gen2_emit_composite_state(struct sna *sna,
+ const struct sna_composite_op *op)
+{
+ uint32_t texcoordfmt;
+ uint32_t cblend, ablend;
+
+ gen2_get_batch(sna, op);
+ gen2_emit_target(sna, op);
+
OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 |
I1_LOAD_S(2) | I1_LOAD_S(3) | I1_LOAD_S(8) | 2);
OUT_BATCH((1 + (op->mask.bo != NULL)) << 12);
@@ -1042,7 +1014,7 @@ gen2_composite_picture(struct sna *sna,
x, y, w, h, dst_x, dst_y);
channel->pict_format = picture->format;
- if (pixmap->drawable.width > 8192 || pixmap->drawable.height > 8192)
+ if (pixmap->drawable.width > 2048 || pixmap->drawable.height > 2048)
return sna_render_picture_extract(sna, picture, channel,
x, y, w, h, dst_x, dst_y);
@@ -1228,8 +1200,16 @@ gen2_render_composite(struct sna *sna,
if (!kgem_check_bo(&sna->kgem, tmp->mask.bo))
kgem_submit(&sna->kgem);
- if (kgem_bo_is_dirty(tmp->src.bo) || kgem_bo_is_dirty(tmp->mask.bo))
- kgem_emit_flush(&sna->kgem);
+ if (kgem_bo_is_dirty(tmp->src.bo) || kgem_bo_is_dirty(tmp->mask.bo)) {
+ if (tmp->src.bo == tmp->dst.bo || tmp->mask.bo == tmp->dst.bo) {
+ kgem_emit_flush(&sna->kgem);
+ } else {
+ OUT_BATCH(_3DSTATE_MODES_5_CMD |
+ PIPELINE_FLUSH_RENDER_CACHE |
+ PIPELINE_FLUSH_TEXTURE_CACHE);
+ kgem_clear_dirty(&sna->kgem);
+ }
+ }
gen2_emit_composite_state(sna, tmp);
@@ -1246,21 +1226,441 @@ cleanup_dst:
}
static void
-gen2_render_reset(struct sna *sna)
+gen2_emit_composite_spans_vertex(struct sna *sna,
+ const struct sna_composite_spans_op *op,
+ int16_t x, int16_t y,
+ float opacity)
{
- sna->render_state.gen2.need_invariant = TRUE;
- sna->render_state.gen2.vertex_offset = 0;
+ gen2_emit_composite_dstcoord(sna, x + op->base.dst.x, y + op->base.dst.y);
+ OUT_BATCH((uint8_t)(opacity * 255) << 24);
+ gen2_emit_composite_texcoord(sna, &op->base.src, x, y);
}
static void
-gen2_render_flush(struct sna *sna)
+gen2_emit_composite_spans_primitive(struct sna *sna,
+ const struct sna_composite_spans_op *op,
+ const BoxRec *box,
+ float opacity)
+{
+ gen2_emit_composite_spans_vertex(sna, op, box->x2, box->y2, opacity);
+ gen2_emit_composite_spans_vertex(sna, op, box->x1, box->y2, opacity);
+ gen2_emit_composite_spans_vertex(sna, op, box->x1, box->y1, opacity);
+}
+
+#if 0
+static void gen2_emit_fill_blend_op(struct sna *sna)
+{
+ /* Set default blend state */
+ OUT_BATCH(_3DSTATE_MAP_BLEND_OP_CMD(0) |
+ TEXPIPE_COLOR |
+ ENABLE_TEXOUTPUT_WRT_SEL |
+ TEXOP_OUTPUT_CURRENT |
+ DISABLE_TEX_CNTRL_STAGE |
+ TEXOP_SCALE_1X |
+ TEXOP_MODIFY_PARMS |
+ TEXOP_LAST_STAGE |
+ TEXBLENDOP_ARG1);
+ OUT_BATCH(_3DSTATE_MAP_BLEND_OP_CMD(0) |
+ TEXPIPE_ALPHA |
+ ENABLE_TEXOUTPUT_WRT_SEL |
+ TEXOP_OUTPUT_CURRENT |
+ TEXOP_SCALE_1X |
+ TEXOP_MODIFY_PARMS |
+ TEXBLENDOP_ARG1);
+ OUT_BATCH(_3DSTATE_MAP_BLEND_ARG_CMD(0) |
+ TEXPIPE_COLOR |
+ TEXBLEND_ARG1 |
+ TEXBLENDARG_MODIFY_PARMS |
+ TEXBLENDARG_DIFFUSE);
+ OUT_BATCH(_3DSTATE_MAP_BLEND_ARG_CMD(0) |
+ TEXPIPE_ALPHA |
+ TEXBLEND_ARG1 |
+ TEXBLENDARG_MODIFY_PARMS |
+ TEXBLENDARG_DIFFUSE);
+}
+#endif
+
+static void
+gen2_emit_spans_blend_op(struct sna *sna,
+ const struct sna_composite_spans_op *op)
+{
+ uint32_t cblend, ablend;
+
+ cblend =
+ TB0C_LAST_STAGE | TB0C_RESULT_SCALE_1X | TB0C_OP_MODULATE |
+ TB0C_ARG1_SEL_DIFFUSE | TB0C_ARG1_REPLICATE_ALPHA |
+ TB0C_OUTPUT_WRITE_CURRENT;
+ ablend =
+ TB0A_RESULT_SCALE_1X | TB0A_OP_MODULATE |
+ TB0A_ARG1_SEL_DIFFUSE |
+ TB0A_OUTPUT_WRITE_CURRENT;
+
+ if (op->base.dst.format == PICT_a8) {
+ ablend |= TB0A_ARG2_SEL_TEXEL0;
+ cblend |= TB0C_ARG2_SEL_TEXEL0 | TB0C_ARG2_REPLICATE_ALPHA;;
+ } else {
+ if (PICT_FORMAT_RGB(op->base.src.pict_format) != 0)
+ cblend |= TB0C_ARG2_SEL_TEXEL0;
+ else
+ cblend |= TB0C_ARG2_SEL_ONE | TB0C_ARG2_INVERT;
+
+ if (op->base.src.is_opaque)
+ ablend |= TB0A_ARG2_SEL_ONE;
+ else
+ ablend |= TB0A_ARG2_SEL_TEXEL0;
+ }
+
+ OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_2 |
+ LOAD_TEXTURE_BLEND_STAGE(0) | 1);
+ OUT_BATCH(cblend);
+ OUT_BATCH(ablend);
+}
+
+static void gen2_emit_composite_spans_state(struct sna *sna,
+ const struct sna_composite_spans_op *op)
+{
+ gen2_get_batch(sna, &op->base);
+ gen2_emit_target(sna, &op->base);
+
+ OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 |
+ I1_LOAD_S(2) | I1_LOAD_S(3) | I1_LOAD_S(8) | 2);
+ OUT_BATCH(1 << 12);
+ OUT_BATCH(S3_CULLMODE_NONE | S3_VERTEXHAS_XY | S3_DIFFUSE_PRESENT);
+ OUT_BATCH(S8_ENABLE_COLOR_BLEND | S8_BLENDFUNC_ADD |
+ gen2_get_blend_cntl(op->base.op, FALSE, op->base.dst.format) |
+ S8_ENABLE_COLOR_BUFFER_WRITE);
+
+ gen2_emit_spans_blend_op(sna, op);
+
+ OUT_BATCH(_3DSTATE_VERTEX_FORMAT_2_CMD |
+ (op->base.src.is_affine ? TEXCOORDFMT_2D : TEXCOORDFMT_3D));
+
+ gen2_emit_texture(sna, &op->base.src, 0);
+}
+
+static void
+gen2_render_composite_spans_boxes(struct sna *sna,
+ const struct sna_composite_spans_op *op,
+ const BoxRec *box, int nbox,
+ float opacity)
+{
+ DBG(("%s: nbox=%d, src=+(%d, %d), opacity=%f, dst=+(%d, %d)\n",
+ __FUNCTION__, nbox,
+ op->base.src.offset[0], op->base.src.offset[1],
+ opacity,
+ op->base.dst.x, op->base.dst.y));
+
+ do {
+ int nbox_this_time;
+
+ nbox_this_time = gen2_get_rectangles(sna, &op->base, nbox);
+ if (nbox_this_time == 0) {
+ gen2_emit_composite_spans_state(sna, op);
+ nbox_this_time = gen2_get_rectangles(sna, &op->base, nbox);
+ }
+ nbox -= nbox_this_time;
+
+ do {
+ DBG((" %s: (%d, %d) x (%d, %d)\n", __FUNCTION__,
+ box->x1, box->y1,
+ box->x2 - box->x1,
+ box->y2 - box->y1));
+
+ op->prim_emit(sna, op, box++, opacity);
+ } while (--nbox_this_time);
+ } while (nbox);
+}
+
+static void
+gen2_render_composite_spans_done(struct sna *sna,
+ const struct sna_composite_spans_op *op)
{
gen2_vertex_flush(sna);
+ _kgem_set_mode(&sna->kgem, KGEM_RENDER);
+
+ DBG(("%s()\n", __FUNCTION__));
+
+ sna_render_composite_redirect_done(sna, &op->base);
+ if (op->base.src.bo)
+ kgem_bo_destroy(&sna->kgem, op->base.src.bo);
+}
+
+static Bool
+gen2_render_composite_spans(struct sna *sna,
+ uint8_t op,
+ PicturePtr src,
+ PicturePtr dst,
+ int16_t src_x, int16_t src_y,
+ int16_t dst_x, int16_t dst_y,
+ int16_t width, int16_t height,
+ struct sna_composite_spans_op *tmp)
+{
+ DBG(("%s(src=(%d, %d), dst=(%d, %d), size=(%d, %d))\n", __FUNCTION__,
+ src_x, src_y, dst_x, dst_y, width, height));
+
+#if NO_COMPOSITE_SPANS
+ return FALSE;
+#endif
+
+ if (op >= ARRAY_SIZE(gen2_blend_op)) {
+ DBG(("%s: fallback due to unhandled blend op: %d\n",
+ __FUNCTION__, op));
+ return FALSE;
+ }
+
+ if (!gen2_check_dst_format(dst->format)) {
+ DBG(("%s: fallback due to unhandled dst format: %x\n",
+ __FUNCTION__, dst->format));
+ return FALSE;
+ }
+
+ if (need_tiling(sna, width, height))
+ return FALSE;
+
+ if (!gen2_composite_set_target(sna, &tmp->base, dst)) {
+ DBG(("%s: unable to set render target\n",
+ __FUNCTION__));
+ return FALSE;
+ }
+
+ tmp->base.op = op;
+ if (tmp->base.dst.width > 2048 ||
+ tmp->base.dst.height > 2048 ||
+ tmp->base.dst.bo->pitch > 8192) {
+ if (!sna_render_composite_redirect(sna, &tmp->base,
+ dst_x, dst_y, width, height))
+ return FALSE;
+ }
+
+ switch (gen2_composite_picture(sna, src, &tmp->base.src,
+ src_x, src_y,
+ width, height,
+ dst_x, dst_y)) {
+ case -1:
+ goto cleanup_dst;
+ case 0:
+ gen2_composite_solid_init(sna, &tmp->base.src, 0);
+ case 1:
+ break;
+ }
+
+ tmp->prim_emit = gen2_emit_composite_spans_primitive;
+ tmp->base.floats_per_vertex = 3;
+ if (tmp->base.src.bo)
+ tmp->base.floats_per_vertex += tmp->base.src.is_affine ? 2 : 3;
+
+ tmp->boxes = gen2_render_composite_spans_boxes;
+ tmp->done = gen2_render_composite_spans_done;
+
+ if (!kgem_check_bo(&sna->kgem, tmp->base.dst.bo))
+ kgem_submit(&sna->kgem);
+ if (!kgem_check_bo(&sna->kgem, tmp->base.src.bo))
+ kgem_submit(&sna->kgem);
+
+ if (kgem_bo_is_dirty(tmp->base.src.bo)) {
+ if (tmp->base.src.bo == tmp->base.dst.bo) {
+ kgem_emit_flush(&sna->kgem);
+ } else {
+ OUT_BATCH(_3DSTATE_MODES_5_CMD |
+ PIPELINE_FLUSH_RENDER_CACHE |
+ PIPELINE_FLUSH_TEXTURE_CACHE);
+ kgem_clear_dirty(&sna->kgem);
+ }
+ }
+
+ gen2_emit_composite_spans_state(sna, tmp);
+ return TRUE;
+
+cleanup_dst:
+ if (tmp->base.redirect.real_bo)
+ kgem_bo_destroy(&sna->kgem, tmp->base.dst.bo);
+ return FALSE;
}
static void
-gen2_render_fini(struct sna *sna)
+gen2_emit_fill_blend_op(struct sna *sna, const struct sna_composite_op *op)
{
+ uint32_t blend;
+
+ OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_2 |
+ LOAD_TEXTURE_BLEND_STAGE(0) | 1);
+ blend = TB0C_LAST_STAGE | TB0C_RESULT_SCALE_1X | TB0C_OP_ARG1 |
+ TB0C_ARG1_SEL_DIFFUSE |
+ TB0C_OUTPUT_WRITE_CURRENT;
+
+ if (op->dst.format == PICT_a8)
+ blend |= TB0C_ARG1_REPLICATE_ALPHA;
+
+ OUT_BATCH(blend);
+ OUT_BATCH(TB0A_RESULT_SCALE_1X | TB0A_OP_ARG1 |
+ TB0A_ARG1_SEL_DIFFUSE |
+ TB0A_OUTPUT_WRITE_CURRENT);
+}
+
+static void gen2_emit_fill_composite_state(struct sna *sna,
+ const struct sna_composite_op *op,
+ uint32_t pixel)
+{
+ gen2_get_batch(sna, op);
+ gen2_emit_target(sna, op);
+
+ OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 |
+ I1_LOAD_S(2) | I1_LOAD_S(3) | I1_LOAD_S(8) | 2);
+ OUT_BATCH(0);
+ OUT_BATCH(S3_CULLMODE_NONE | S3_VERTEXHAS_XY);
+ OUT_BATCH(S8_ENABLE_COLOR_BLEND | S8_BLENDFUNC_ADD |
+ gen2_get_blend_cntl(op->op, FALSE, op->dst.format) |
+ S8_ENABLE_COLOR_BUFFER_WRITE);
+
+ gen2_emit_fill_blend_op(sna, op);
+
+ OUT_BATCH(_3DSTATE_DFLT_DIFFUSE_CMD);
+ OUT_BATCH(pixel);
+}
+
+static Bool
+gen2_render_fill_boxes_try_blt(struct sna *sna,
+ CARD8 op, PictFormat format,
+ const xRenderColor *color,
+ PixmapPtr dst, struct kgem_bo *dst_bo,
+ const BoxRec *box, int n)
+{
+ uint8_t alu = GXcopy;
+ uint32_t pixel;
+
+ if (!sna_get_pixel_from_rgba(&pixel,
+ color->red,
+ color->green,
+ color->blue,
+ color->alpha,
+ format))
+ return FALSE;
+
+ if (op == PictOpClear) {
+ alu = GXclear;
+ pixel = 0;
+ op = PictOpSrc;
+ }
+
+ if (op == PictOpOver) {
+ if ((pixel & 0xff000000) == 0xff000000)
+ op = PictOpSrc;
+ }
+
+ if (op != PictOpSrc)
+ return FALSE;
+
+ return sna_blt_fill_boxes(sna, alu,
+ dst_bo, dst->drawable.bitsPerPixel,
+ pixel, box, n);
+}
+
+static Bool
+gen2_render_fill_boxes(struct sna *sna,
+ CARD8 op,
+ PictFormat format,
+ const xRenderColor *color,
+ PixmapPtr dst, struct kgem_bo *dst_bo,
+ const BoxRec *box, int n)
+{
+ struct sna_composite_op tmp;
+ uint32_t pixel;
+
+#if NO_FILL_BOXES
+ return gen2_render_fill_boxes_try_blt(sna, op, format, color,
+ dst, dst_bo,
+ box, n);
+#endif
+
+ DBG(("%s (op=%d, format=%x, color=(%04x,%04x,%04x, %04x))\n",
+ __FUNCTION__, op, (int)format,
+ color->red, color->green, color->blue, color->alpha));
+
+ if (op >= ARRAY_SIZE(gen2_blend_op)) {
+ DBG(("%s: fallback due to unhandled blend op: %d\n",
+ __FUNCTION__, op));
+ return FALSE;
+ }
+
+ if (dst->drawable.width > 2048 ||
+ dst->drawable.height > 2048 ||
+ dst_bo->pitch > 8192 ||
+ !gen2_check_dst_format(format))
+ return gen2_render_fill_boxes_try_blt(sna, op, format, color,
+ dst, dst_bo,
+ box, n);
+
+ if (gen2_render_fill_boxes_try_blt(sna, op, format, color,
+ dst, dst_bo,
+ box, n))
+ return TRUE;
+
+ if (!sna_get_pixel_from_rgba(&pixel,
+ color->red,
+ color->green,
+ color->blue,
+ color->alpha,
+ PICT_a8r8g8b8))
+ return FALSE;
+
+ DBG(("%s: using shader for op=%d, format=%x, pixel=%x\n",
+ __FUNCTION__, op, (int)format, pixel));
+
+ if (pixel == 0)
+ op = PictOpClear;
+
+ memset(&tmp, 0, sizeof(tmp));
+ tmp.op = op;
+ tmp.dst.pixmap = dst;
+ tmp.dst.width = dst->drawable.width;
+ tmp.dst.height = dst->drawable.height;
+ tmp.dst.format = format;
+ tmp.dst.bo = dst_bo;
+ tmp.floats_per_vertex = 2;
+
+ if (!kgem_check_bo(&sna->kgem, dst_bo))
+ kgem_submit(&sna->kgem);
+
+ gen2_emit_fill_composite_state(sna, &tmp, pixel);
+
+ do {
+ int n_this_time = gen2_get_rectangles(sna, &tmp, n);
+ if (n_this_time == 0) {
+ gen2_emit_fill_composite_state(sna, &tmp, pixel);
+ n_this_time = gen2_get_rectangles(sna, &tmp, n);
+ }
+ n -= n_this_time;
+
+ do {
+ DBG((" (%d, %d), (%d, %d): %x\n",
+ box->x1, box->y1, box->x2, box->y2, pixel));
+ OUT_VERTEX(box->x2);
+ OUT_VERTEX(box->y2);
+ OUT_VERTEX(box->x1);
+ OUT_VERTEX(box->y2);
+ OUT_VERTEX(box->x1);
+ OUT_VERTEX(box->y1);
+ box++;
+ } while (--n_this_time);
+ } while (n);
+
+ gen2_vertex_flush(sna);
+ _kgem_set_mode(&sna->kgem, KGEM_RENDER);
+ return TRUE;
+}
+
+static void
+gen2_render_reset(struct sna *sna)
+{
+ sna->render_state.gen2.need_invariant = TRUE;
+ sna->render_state.gen2.vertex_offset = 0;
+ sna->render_state.gen2.target = 0;
+}
+
+static void
+gen2_render_flush(struct sna *sna)
+{
+ gen2_vertex_flush(sna);
}
Bool gen2_render_init(struct sna *sna)
@@ -1271,12 +1671,13 @@ Bool gen2_render_init(struct sna *sna)
* use the texture combiners.
*/
render->composite = gen2_render_composite;
+ render->composite_spans = gen2_render_composite_spans;
+ render->fill_boxes = gen2_render_fill_boxes;
/* XXX Y-tiling copies */
render->reset = gen2_render_reset;
render->flush = gen2_render_flush;
- render->fini = gen2_render_fini;
render->max_3d_size = 2048;
return TRUE;
diff --git a/src/sna/gen2_render.h b/src/sna/gen2_render.h
index 945cd846..a1767ad0 100644
--- a/src/sna/gen2_render.h
+++ b/src/sna/gen2_render.h
@@ -447,9 +447,8 @@
#define _3DSTATE_MODES_5_CMD (CMD_3D|(0x0c<<24))
#define ENABLE_SPRITE_POINT_TEX (1<<23)
#define SPRITE_POINT_TEX_ON (1<<22)
-#define SPRITE_POINT_TEX_OFF 0
-#define FLUSH_RENDER_CACHE (1<<18)
-#define FLUSH_TEXTURE_CACHE (1<<16)
+#define PIPELINE_FLUSH_RENDER_CACHE (1<<18)
+#define PIPELINE_FLUSH_TEXTURE_CACHE (1<<16)
#define FIXED_LINE_WIDTH_MASK 0xfc00
#define ENABLE_FIXED_LINE_WIDTH (1<<15)
#define FIXED_LINE_WIDTH(x) ((x)<<10)
@@ -735,7 +734,8 @@
#define TB0C_RESULT_SCALE_1X (0 << 29)
#define TB0C_RESULT_SCALE_2X (1 << 29)
#define TB0C_RESULT_SCALE_4X (2 << 29)
-#define TB0C_OP_MODULE (3 << 25)
+#define TB0C_OP_ARG1 (1 << 25)
+#define TB0C_OP_MODULATE (3 << 25)
#define TB0C_OUTPUT_WRITE_CURRENT (0 << 24)
#define TB0C_OUTPUT_WRITE_ACCUM (1 << 24)
#define TB0C_ARG3_REPLICATE_ALPHA (1<<23)
@@ -752,6 +752,7 @@
#define TB0C_ARG1_REPLICATE_ALPHA (1<<11)
#define TB0C_ARG1_INVERT (1<<10)
#define TB0C_ARG1_SEL_ONE (0 << 6)
+#define TB0C_ARG1_SEL_DIFFUSE (3 << 6)
#define TB0C_ARG1_SEL_TEXEL0 (6 << 6)
#define TB0C_ARG1_SEL_TEXEL1 (7 << 6)
#define TB0C_ARG1_SEL_TEXEL2 (8 << 6)
@@ -763,7 +764,8 @@
#define TB0A_RESULT_SCALE_1X (0 << 29)
#define TB0A_RESULT_SCALE_2X (1 << 29)
#define TB0A_RESULT_SCALE_4X (2 << 29)
-#define TB0A_OP_MODULE (3 << 25)
+#define TB0A_OP_ARG1 (1 << 25)
+#define TB0A_OP_MODULATE (3 << 25)
#define TB0A_OUTPUT_WRITE_CURRENT (0<<24)
#define TB0A_OUTPUT_WRITE_ACCUM (1<<24)
#define TB0A_CTR_STAGE_SEL_BITS_XXX
@@ -771,12 +773,14 @@
#define TB0A_ARG3_INVERT (1<<17)
#define TB0A_ARG2_INVERT (1<<16)
#define TB0A_ARG2_SEL_ONE (0 << 12)
+#define TB0A_ARG2_SEL_DIFFUSE (3 << 12)
#define TB0A_ARG2_SEL_TEXEL0 (6 << 12)
#define TB0A_ARG2_SEL_TEXEL1 (7 << 12)
#define TB0A_ARG2_SEL_TEXEL2 (8 << 12)
#define TB0A_ARG2_SEL_TEXEL3 (9 << 12)
#define TB0A_ARG1_INVERT (1<<10)
#define TB0A_ARG1_SEL_ONE (0 << 6)
+#define TB0A_ARG1_SEL_DIFFUSE (3 << 6)
#define TB0A_ARG1_SEL_TEXEL0 (6 << 6)
#define TB0A_ARG1_SEL_TEXEL1 (7 << 6)
#define TB0A_ARG1_SEL_TEXEL2 (8 << 6)
diff --git a/src/sna/sna_render.c b/src/sna/sna_render.c
index 21afd26e..72a3c1e2 100644
--- a/src/sna/sna_render.c
+++ b/src/sna/sna_render.c
@@ -437,7 +437,7 @@ sna_render_picture_extract(struct sna *sna,
{
struct kgem_bo *bo = NULL;
PixmapPtr pixmap = get_drawable_pixmap(picture->pDrawable);
- int16_t ox, oy;
+ int16_t ox, oy, ow, oh;
BoxRec box;
#if NO_EXTRACT
@@ -452,6 +452,9 @@ sna_render_picture_extract(struct sna *sna,
return -1;
}
+ ow = w;
+ oh = h;
+
ox = box.x1 = x;
oy = box.y1 = y;
box.x2 = x + w;
@@ -482,7 +485,11 @@ sna_render_picture_extract(struct sna *sna,
if (!channel->is_affine) {
DBG(("%s: fallback -- repeating project transform too large for texture\n",
__FUNCTION__));
- return -1;
+ return sna_render_picture_fixup(sna,
+ picture,
+ channel,
+ x, y, ow, oh,
+ dst_x, dst_y);
}
}
} else {
@@ -510,7 +517,8 @@ sna_render_picture_extract(struct sna *sna,
if (w > sna->render.max_3d_size || h > sna->render.max_3d_size) {
DBG(("%s: fallback -- sample too large for texture (%d, %d)x(%d, %d)\n",
__FUNCTION__, box.x1, box.y1, w, h));
- return -1;
+ return sna_render_picture_fixup(sna, picture, channel,
+ x, y, ow, oh, dst_x, dst_y);
}
if (texture_is_cpu(pixmap, &box) && !move_to_gpu(pixmap, &box)) {
@@ -528,7 +536,8 @@ sna_render_picture_extract(struct sna *sna,
if (!sna_pixmap_move_to_gpu(pixmap)) {
DBG(("%s: falback -- pixmap is not on the GPU\n",
__FUNCTION__));
- return -1;
+ return sna_render_picture_fixup(sna, picture, channel,
+ x, y, ow, oh, dst_x, dst_y);
}
bo = kgem_create_2d(&sna->kgem, w, h,
@@ -550,7 +559,8 @@ sna_render_picture_extract(struct sna *sna,
&box, 1)) {
DBG(("%s: fallback -- unable to copy boxes\n",
__FUNCTION__));
- return -1;
+ return sna_render_picture_fixup(sna, picture, channel,
+ x, y, ow, oh, dst_x, dst_y);
}
}
diff --git a/src/sna/sna_render.h b/src/sna/sna_render.h
index c2d6f12e..5b51be95 100644
--- a/src/sna/sna_render.h
+++ b/src/sna/sna_render.h
@@ -236,6 +236,7 @@ struct sna_render {
};
struct gen2_render_state {
+ uint32_t target;
Bool need_invariant;
uint16_t vertex_offset;
};
diff --git a/src/sna/sna_trapezoids.c b/src/sna/sna_trapezoids.c
index db9e085b..536034fd 100644
--- a/src/sna/sna_trapezoids.c
+++ b/src/sna/sna_trapezoids.c
@@ -2073,7 +2073,7 @@ composite_unaligned_boxes(CARD8 op,
DBG(("%s\n", __FUNCTION__));
- /* XXX need a span converter to handle overlapping traps */
+ /* need a span converter to handle overlapping traps */
if (ntrap > 1 && maskFormat)
return false;