2
* Copyright © 2006,2011 Intel Corporation
4
* Permission is hereby granted, free of charge, to any person obtaining a
5
* copy of this software and associated documentation files (the "Software"),
6
* to deal in the Software without restriction, including without limitation
7
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
8
* and/or sell copies of the Software, and to permit persons to whom the
9
* Software is furnished to do so, subject to the following conditions:
11
* The above copyright notice and this permission notice (including the next
12
* paragraph) shall be included in all copies or substantial portions of the
15
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24
* Wang Zhenyu <zhenyu.z.wang@intel.com>
25
* Eric Anholt <eric@anholt.net>
26
* Chris Wilson <chris@chris-wilson.co.uk>
36
#include "sna_render.h"
37
#include "sna_render_inline.h"
38
#include "sna_video.h"
40
#include "gen2_render.h"
42
#define NO_COMPOSITE 0
43
#define NO_COMPOSITE_SPANS 0
45
#define NO_COPY_BOXES 0
48
#define NO_FILL_BOXES 0
50
#define MAX_3D_SIZE 2048
51
#define MAX_3D_PITCH 8192
52
#define MAX_INLINE (1 << 18)
54
#define BATCH(v) batch_emit(sna, v)
55
#define BATCH_ALIGNED(v, a) batch_emit_aligned(sna, v, a)
56
#define BATCH_F(v) batch_emit_float(sna, v)
57
#define VERTEX(v) batch_emit_float(sna, v)
59
static const struct blendinfo {
66
{0, 0, BLENDFACTOR_ZERO, BLENDFACTOR_ZERO},
68
{0, 0, BLENDFACTOR_ONE, BLENDFACTOR_ZERO},
70
{0, 0, BLENDFACTOR_ZERO, BLENDFACTOR_ONE},
72
{0, 1, BLENDFACTOR_ONE, BLENDFACTOR_INV_SRC_ALPHA},
74
{1, 0, BLENDFACTOR_INV_DST_ALPHA, BLENDFACTOR_ONE},
76
{1, 0, BLENDFACTOR_DST_ALPHA, BLENDFACTOR_ZERO},
78
{0, 1, BLENDFACTOR_ZERO, BLENDFACTOR_SRC_ALPHA},
80
{1, 0, BLENDFACTOR_INV_DST_ALPHA, BLENDFACTOR_ZERO},
82
{0, 1, BLENDFACTOR_ZERO, BLENDFACTOR_INV_SRC_ALPHA},
84
{1, 1, BLENDFACTOR_DST_ALPHA, BLENDFACTOR_INV_SRC_ALPHA},
86
{1, 1, BLENDFACTOR_INV_DST_ALPHA, BLENDFACTOR_SRC_ALPHA},
88
{1, 1, BLENDFACTOR_INV_DST_ALPHA, BLENDFACTOR_INV_SRC_ALPHA},
90
{0, 0, BLENDFACTOR_ONE, BLENDFACTOR_ONE},
93
static const struct formatinfo {
96
} i8xx_tex_formats[] = {
97
{PICT_a8, MAPSURF_8BIT | MT_8BIT_A8},
98
{PICT_a8r8g8b8, MAPSURF_32BIT | MT_32BIT_ARGB8888},
99
{PICT_a8b8g8r8, MAPSURF_32BIT | MT_32BIT_ABGR8888},
100
{PICT_r5g6b5, MAPSURF_16BIT | MT_16BIT_RGB565},
101
{PICT_a1r5g5b5, MAPSURF_16BIT | MT_16BIT_ARGB1555},
102
{PICT_a4r4g4b4, MAPSURF_16BIT | MT_16BIT_ARGB4444},
103
}, i85x_tex_formats[] = {
104
{PICT_x8r8g8b8, MAPSURF_32BIT | MT_32BIT_XRGB8888},
105
{PICT_x8b8g8r8, MAPSURF_32BIT | MT_32BIT_XBGR8888},
109
too_large(int width, int height)
111
return width > MAX_3D_SIZE || height > MAX_3D_SIZE;
114
static inline uint32_t
115
gen2_buf_tiling(uint32_t tiling)
123
v |= BUF_3D_TILE_WALK_Y;
126
v |= BUF_3D_TILED_SURFACE;
128
case I915_TILING_NONE:
135
gen2_get_dst_format(uint32_t format)
137
#define BIAS DSTORG_HORT_BIAS(0x8) | DSTORG_VERT_BIAS(0x8)
144
return COLR_BUF_ARGB8888 | BIAS;
146
return COLR_BUF_RGB565 | BIAS;
149
return COLR_BUF_ARGB1555 | BIAS;
151
return COLR_BUF_8BIT | BIAS;
154
return COLR_BUF_ARGB4444 | BIAS;
160
gen2_check_dst_format(uint32_t format)
178
gen2_get_card_format(struct sna *sna, uint32_t format)
182
for (i = 0; i < ARRAY_SIZE(i8xx_tex_formats); i++)
183
if (i8xx_tex_formats[i].fmt == format)
184
return i8xx_tex_formats[i].card_fmt;
186
if (sna->kgem.gen < 021) {
187
/* Whilst these are not directly supported on 830/845,
188
* we only enable them when we can implicitly convert
189
* them to a supported variant through the texture
192
for (i = 0; i < ARRAY_SIZE(i85x_tex_formats); i++)
193
if (i85x_tex_formats[i].fmt == format)
194
return i8xx_tex_formats[1+i].card_fmt;
196
for (i = 0; i < ARRAY_SIZE(i85x_tex_formats); i++)
197
if (i85x_tex_formats[i].fmt == format)
198
return i85x_tex_formats[i].card_fmt;
206
gen2_check_format(struct sna *sna, PicturePtr p)
210
for (i = 0; i < ARRAY_SIZE(i8xx_tex_formats); i++)
211
if (i8xx_tex_formats[i].fmt == p->format)
214
if (sna->kgem.gen > 021) {
215
for (i = 0; i < ARRAY_SIZE(i85x_tex_formats); i++)
216
if (i85x_tex_formats[i].fmt == p->format)
224
gen2_sampler_tiling_bits(uint32_t tiling)
232
bits |= TM0S1_TILE_WALK;
235
bits |= TM0S1_TILED_SURFACE;
237
case I915_TILING_NONE:
244
gen2_check_filter(PicturePtr picture)
246
switch (picture->filter) {
247
case PictFilterNearest:
248
case PictFilterBilinear:
256
gen2_check_repeat(PicturePtr picture)
258
if (!picture->repeat)
261
switch (picture->repeatType) {
273
gen2_emit_texture(struct sna *sna,
274
const struct sna_composite_channel *channel,
277
uint32_t wrap_mode_u, wrap_mode_v;
278
uint32_t texcoordtype;
283
if (channel->is_affine)
284
texcoordtype = TEXCOORDTYPE_CARTESIAN;
286
texcoordtype = TEXCOORDTYPE_HOMOGENEOUS;
288
switch (channel->repeat) {
293
wrap_mode_u = TEXCOORDMODE_CLAMP_BORDER;
296
wrap_mode_u = TEXCOORDMODE_WRAP;
299
wrap_mode_u = TEXCOORDMODE_CLAMP;
302
wrap_mode_u = TEXCOORDMODE_MIRROR;
305
if (channel->is_linear)
306
wrap_mode_v = TEXCOORDMODE_WRAP;
308
wrap_mode_v = wrap_mode_u;
310
switch (channel->filter) {
314
case PictFilterNearest:
315
filter = (FILTER_NEAREST << TM0S3_MAG_FILTER_SHIFT |
316
FILTER_NEAREST << TM0S3_MIN_FILTER_SHIFT |
317
MIPFILTER_NONE << TM0S3_MIP_FILTER_SHIFT);
319
case PictFilterBilinear:
320
filter = (FILTER_LINEAR << TM0S3_MAG_FILTER_SHIFT |
321
FILTER_LINEAR << TM0S3_MIN_FILTER_SHIFT |
322
MIPFILTER_NONE << TM0S3_MIP_FILTER_SHIFT);
326
BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_2 | LOAD_TEXTURE_MAP(unit) | 4);
327
BATCH(kgem_add_reloc(&sna->kgem, sna->kgem.nbatch,
329
I915_GEM_DOMAIN_SAMPLER << 16,
331
BATCH(((channel->height - 1) << TM0S1_HEIGHT_SHIFT) |
332
((channel->width - 1) << TM0S1_WIDTH_SHIFT) |
333
gen2_get_card_format(sna, channel->pict_format) |
334
gen2_sampler_tiling_bits(channel->bo->tiling));
335
BATCH((channel->bo->pitch / 4 - 1) << TM0S2_PITCH_SHIFT | TM0S2_MAP_2D);
337
BATCH(0); /* default color */
339
BATCH(_3DSTATE_MAP_COORD_SET_CMD | TEXCOORD_SET(unit) |
340
ENABLE_TEXCOORD_PARAMS | TEXCOORDS_ARE_NORMAL | texcoordtype |
341
ENABLE_ADDR_V_CNTL | TEXCOORD_ADDR_V_MODE(wrap_mode_v) |
342
ENABLE_ADDR_U_CNTL | TEXCOORD_ADDR_U_MODE(wrap_mode_u));
346
gen2_get_blend_factors(const struct sna_composite_op *op,
351
uint32_t cblend, ablend;
353
/* If component alpha is active in the mask and the blend operation
354
* uses the source alpha, then we know we don't need the source
355
* value (otherwise we would have hit a fallback earlier), so we
356
* provide the source alpha (src.A * mask.X) as output color.
357
* Conversely, if CA is set and we don't need the source alpha, then
358
* we produce the source value (src.X * mask.X) and the source alpha
359
* is unused.. Otherwise, we provide the non-CA source value
362
* The PICT_FORMAT_RGB(pict) == 0 fixups are not needed on 855+'s a8
363
* pictures, but we need to implement it for 830/845 and there's no
364
* harm done in leaving it in.
366
cblend = TB0C_LAST_STAGE | TB0C_RESULT_SCALE_1X | TB0C_OUTPUT_WRITE_CURRENT;
367
ablend = TB0A_RESULT_SCALE_1X | TB0A_OUTPUT_WRITE_CURRENT;
369
/* Get the source picture's channels into TBx_ARG1 */
370
if ((op->has_component_alpha && gen2_blend_op[blend].src_alpha) ||
371
op->dst.format == PICT_a8) {
372
/* Producing source alpha value, so the first set of channels
373
* is src.A instead of src.X. We also do this if the destination
374
* is a8, in which case src.G is what's written, and the other
375
* channels are ignored.
377
if (op->src.is_opaque) {
378
ablend |= TB0C_ARG1_SEL_ONE;
379
cblend |= TB0C_ARG1_SEL_ONE;
380
} else if (op->src.is_solid) {
381
ablend |= TB0C_ARG1_SEL_DIFFUSE;
382
cblend |= TB0C_ARG1_SEL_DIFFUSE | TB0C_ARG1_REPLICATE_ALPHA;
384
ablend |= TB0C_ARG1_SEL_TEXEL0;
385
cblend |= TB0C_ARG1_SEL_TEXEL0 | TB0C_ARG1_REPLICATE_ALPHA;
388
if (op->src.is_solid)
389
cblend |= TB0C_ARG1_SEL_DIFFUSE;
390
else if (PICT_FORMAT_RGB(op->src.pict_format) != 0)
391
cblend |= TB0C_ARG1_SEL_TEXEL0;
393
cblend |= TB0C_ARG1_SEL_ONE | TB0C_ARG1_INVERT; /* 0.0 */
395
if (op->src.is_opaque)
396
ablend |= TB0A_ARG1_SEL_ONE;
397
else if (op->src.is_solid)
398
ablend |= TB0A_ARG1_SEL_DIFFUSE;
400
ablend |= TB0A_ARG1_SEL_TEXEL0;
404
if (op->src.is_solid) {
405
cblend |= TB0C_ARG2_SEL_TEXEL0;
406
ablend |= TB0A_ARG2_SEL_TEXEL0;
408
cblend |= TB0C_ARG2_SEL_TEXEL1;
409
ablend |= TB0A_ARG2_SEL_TEXEL1;
412
if (op->dst.format == PICT_a8 || !op->has_component_alpha)
413
cblend |= TB0C_ARG2_REPLICATE_ALPHA;
415
cblend |= TB0C_OP_MODULATE;
416
ablend |= TB0A_OP_MODULATE;
417
} else if (op->mask.is_solid) {
418
cblend |= TB0C_ARG2_SEL_DIFFUSE;
419
ablend |= TB0A_ARG2_SEL_DIFFUSE;
421
if (op->dst.format == PICT_a8 || !op->has_component_alpha)
422
cblend |= TB0C_ARG2_REPLICATE_ALPHA;
424
cblend |= TB0C_OP_MODULATE;
425
ablend |= TB0A_OP_MODULATE;
427
cblend |= TB0C_OP_ARG1;
428
ablend |= TB0A_OP_ARG1;
435
static uint32_t gen2_get_blend_cntl(int op,
436
bool has_component_alpha,
439
uint32_t sblend, dblend;
442
return S8_ENABLE_COLOR_BUFFER_WRITE;
444
sblend = gen2_blend_op[op].src_blend;
445
dblend = gen2_blend_op[op].dst_blend;
447
if (gen2_blend_op[op].dst_alpha) {
448
/* If there's no dst alpha channel, adjust the blend op so that
449
* we'll treat it as always 1.
451
if (PICT_FORMAT_A(dst_format) == 0) {
452
if (sblend == BLENDFACTOR_DST_ALPHA)
453
sblend = BLENDFACTOR_ONE;
454
else if (sblend == BLENDFACTOR_INV_DST_ALPHA)
455
sblend = BLENDFACTOR_ZERO;
458
/* gen2 engine reads 8bit color buffer into green channel
459
* in cases like color buffer blending etc., and also writes
460
* back green channel. So with dst_alpha blend we should use
463
if (dst_format == PICT_a8) {
464
if (sblend == BLENDFACTOR_DST_ALPHA)
465
sblend = BLENDFACTOR_DST_COLR;
466
else if (sblend == BLENDFACTOR_INV_DST_ALPHA)
467
sblend = BLENDFACTOR_INV_DST_COLR;
471
/* If the source alpha is being used, then we should only be in a case
472
* where the source blend factor is 0, and the source blend value is
473
* the mask channels multiplied by the source picture's alpha.
475
if (has_component_alpha && gen2_blend_op[op].src_alpha) {
476
if (dblend == BLENDFACTOR_SRC_ALPHA)
477
dblend = BLENDFACTOR_SRC_COLR;
478
else if (dblend == BLENDFACTOR_INV_SRC_ALPHA)
479
dblend = BLENDFACTOR_INV_SRC_COLR;
482
return (sblend << S8_SRC_BLEND_FACTOR_SHIFT |
483
dblend << S8_DST_BLEND_FACTOR_SHIFT |
484
S8_ENABLE_COLOR_BLEND | S8_BLENDFUNC_ADD |
485
S8_ENABLE_COLOR_BUFFER_WRITE);
488
static void gen2_emit_invariant(struct sna *sna)
492
for (i = 0; i < 4; i++) {
493
BATCH(_3DSTATE_MAP_CUBE | MAP_UNIT(i));
494
BATCH(_3DSTATE_MAP_TEX_STREAM_CMD | MAP_UNIT(i) |
495
DISABLE_TEX_STREAM_BUMP |
496
ENABLE_TEX_STREAM_COORD_SET | TEX_STREAM_COORD_SET(i) |
497
ENABLE_TEX_STREAM_MAP_IDX | TEX_STREAM_MAP_IDX(i));
498
BATCH(_3DSTATE_MAP_COORD_TRANSFORM);
499
BATCH(DISABLE_TEX_TRANSFORM | TEXTURE_SET(i));
502
BATCH(_3DSTATE_MAP_COORD_SETBIND_CMD);
503
BATCH(TEXBIND_SET3(TEXCOORDSRC_VTXSET_3) |
504
TEXBIND_SET2(TEXCOORDSRC_VTXSET_2) |
505
TEXBIND_SET1(TEXCOORDSRC_VTXSET_1) |
506
TEXBIND_SET0(TEXCOORDSRC_VTXSET_0));
508
BATCH(_3DSTATE_SCISSOR_ENABLE_CMD | DISABLE_SCISSOR_RECT);
510
BATCH(_3DSTATE_VERTEX_TRANSFORM);
511
BATCH(DISABLE_VIEWPORT_TRANSFORM | DISABLE_PERSPECTIVE_DIVIDE);
513
BATCH(_3DSTATE_W_STATE_CMD);
514
BATCH(MAGIC_W_STATE_DWORD1);
517
BATCH(_3DSTATE_INDPT_ALPHA_BLEND_CMD |
518
DISABLE_INDPT_ALPHA_BLEND |
519
ENABLE_ALPHA_BLENDFUNC | ABLENDFUNC_ADD);
521
BATCH(_3DSTATE_CONST_BLEND_COLOR_CMD);
524
BATCH(_3DSTATE_MODES_1_CMD |
525
ENABLE_COLR_BLND_FUNC | BLENDFUNC_ADD |
526
ENABLE_SRC_BLND_FACTOR | SRC_BLND_FACT(BLENDFACTOR_ONE) |
527
ENABLE_DST_BLND_FACTOR | DST_BLND_FACT(BLENDFACTOR_ZERO));
529
BATCH(_3DSTATE_ENABLES_1_CMD |
531
DISABLE_STENCIL_TEST |
539
BATCH(_3DSTATE_ENABLES_2_CMD |
540
DISABLE_STENCIL_WRITE |
542
DISABLE_DEPTH_WRITE |
547
BATCH(_3DSTATE_STIPPLE);
550
BATCH(_3DSTATE_MAP_BLEND_OP_CMD(0) |
552
ENABLE_TEXOUTPUT_WRT_SEL |
553
TEXOP_OUTPUT_CURRENT |
554
DISABLE_TEX_CNTRL_STAGE |
556
TEXOP_MODIFY_PARMS | TEXOP_LAST_STAGE |
558
BATCH(_3DSTATE_MAP_BLEND_OP_CMD(0) |
560
ENABLE_TEXOUTPUT_WRT_SEL |
561
TEXOP_OUTPUT_CURRENT |
562
TEXOP_SCALE_1X | TEXOP_MODIFY_PARMS |
564
BATCH(_3DSTATE_MAP_BLEND_ARG_CMD(0) |
567
TEXBLENDARG_MODIFY_PARMS |
568
TEXBLENDARG_DIFFUSE);
569
BATCH(_3DSTATE_MAP_BLEND_ARG_CMD(0) |
572
TEXBLENDARG_MODIFY_PARMS |
573
TEXBLENDARG_DIFFUSE);
575
#define INVARIANT_SIZE 35
577
sna->render_state.gen2.need_invariant = false;
581
gen2_get_batch(struct sna *sna, const struct sna_composite_op *op)
583
kgem_set_mode(&sna->kgem, KGEM_RENDER, op->dst.bo);
585
/* +7 for i830 3DSTATE_BUFFER_INFO w/a */
586
if (!kgem_check_batch(&sna->kgem, INVARIANT_SIZE+40+7)) {
587
DBG(("%s: flushing batch: size %d > %d\n",
588
__FUNCTION__, INVARIANT_SIZE+40,
589
sna->kgem.surface-sna->kgem.nbatch));
590
kgem_submit(&sna->kgem);
591
_kgem_set_mode(&sna->kgem, KGEM_RENDER);
594
if (!kgem_check_reloc(&sna->kgem, 3)) {
595
DBG(("%s: flushing batch: reloc %d >= %d\n",
597
sna->kgem.nreloc + 3,
598
(int)KGEM_RELOC_SIZE(&sna->kgem)));
599
kgem_submit(&sna->kgem);
600
_kgem_set_mode(&sna->kgem, KGEM_RENDER);
603
if (!kgem_check_exec(&sna->kgem, 3)) {
604
DBG(("%s: flushing batch: exec %d >= %d\n",
607
(int)KGEM_EXEC_SIZE(&sna->kgem)));
608
kgem_submit(&sna->kgem);
609
_kgem_set_mode(&sna->kgem, KGEM_RENDER);
612
if (sna->render_state.gen2.need_invariant)
613
gen2_emit_invariant(sna);
616
static void gen2_emit_target(struct sna *sna,
622
assert(!too_large(width, height));
623
assert(bo->pitch >= 8 && bo->pitch <= MAX_3D_PITCH);
624
assert(sna->render.vertex_offset == 0);
626
assert(bo->unique_id);
627
if (sna->render_state.gen2.target == bo->unique_id) {
628
kgem_bo_mark_dirty(bo);
633
* i830 w/a: 3DSTATE_BUFFER_INFO
634
* must not straddle two cachelines.
636
if (intel_get_device_id(sna->dev) == 0x3577)
637
BATCH_ALIGNED(_3DSTATE_BUF_INFO_CMD, 8);
639
BATCH(_3DSTATE_BUF_INFO_CMD);
640
BATCH(BUF_3D_ID_COLOR_BACK |
641
gen2_buf_tiling(bo->tiling) |
642
BUF_3D_PITCH(bo->pitch));
643
BATCH(kgem_add_reloc(&sna->kgem, sna->kgem.nbatch,
645
I915_GEM_DOMAIN_RENDER << 16 |
646
I915_GEM_DOMAIN_RENDER,
649
BATCH(_3DSTATE_DST_BUF_VARS_CMD);
650
BATCH(gen2_get_dst_format(format));
652
BATCH(_3DSTATE_DRAW_RECT_CMD);
654
BATCH(0); /* ymin, xmin */
655
BATCH(DRAW_YMAX(height - 1) |
656
DRAW_XMAX(width - 1));
657
BATCH(0); /* yorig, xorig */
659
sna->render_state.gen2.target = bo->unique_id;
662
static void gen2_disable_logic_op(struct sna *sna)
664
if (!sna->render_state.gen2.logic_op_enabled)
667
DBG(("%s\n", __FUNCTION__));
669
BATCH(_3DSTATE_ENABLES_1_CMD |
670
DISABLE_LOGIC_OP | ENABLE_COLOR_BLEND);
672
sna->render_state.gen2.logic_op_enabled = 0;
675
static void gen2_enable_logic_op(struct sna *sna, int op)
677
static const uint8_t logic_op[] = {
678
LOGICOP_CLEAR, /* GXclear */
679
LOGICOP_AND, /* GXand */
680
LOGICOP_AND_RVRSE, /* GXandReverse */
681
LOGICOP_COPY, /* GXcopy */
682
LOGICOP_AND_INV, /* GXandInverted */
683
LOGICOP_NOOP, /* GXnoop */
684
LOGICOP_XOR, /* GXxor */
685
LOGICOP_OR, /* GXor */
686
LOGICOP_NOR, /* GXnor */
687
LOGICOP_EQUIV, /* GXequiv */
688
LOGICOP_INV, /* GXinvert */
689
LOGICOP_OR_RVRSE, /* GXorReverse */
690
LOGICOP_COPY_INV, /* GXcopyInverted */
691
LOGICOP_OR_INV, /* GXorInverted */
692
LOGICOP_NAND, /* GXnand */
693
LOGICOP_SET /* GXset */
696
if (sna->render_state.gen2.logic_op_enabled != op+1) {
697
if (!sna->render_state.gen2.logic_op_enabled) {
698
if (op == GXclear || op == GXcopy)
701
DBG(("%s\n", __FUNCTION__));
703
BATCH(_3DSTATE_ENABLES_1_CMD |
704
ENABLE_LOGIC_OP | DISABLE_COLOR_BLEND);
707
BATCH(_3DSTATE_MODES_4_CMD |
708
ENABLE_LOGIC_OP_FUNC | LOGIC_OP_FUNC(logic_op[op]));
709
sna->render_state.gen2.logic_op_enabled = op+1;
713
static void gen2_emit_composite_state(struct sna *sna,
714
const struct sna_composite_op *op)
716
uint32_t texcoordfmt, v, unwind;
717
uint32_t cblend, ablend;
720
gen2_get_batch(sna, op);
722
if (kgem_bo_is_dirty(op->src.bo) || kgem_bo_is_dirty(op->mask.bo)) {
723
if (op->src.bo == op->dst.bo || op->mask.bo == op->dst.bo)
724
BATCH(MI_FLUSH | MI_INVALIDATE_MAP_CACHE);
726
BATCH(_3DSTATE_MODES_5_CMD |
727
PIPELINE_FLUSH_RENDER_CACHE |
728
PIPELINE_FLUSH_TEXTURE_CACHE);
729
kgem_clear_dirty(&sna->kgem);
732
gen2_emit_target(sna,
738
unwind = sna->kgem.nbatch;
739
BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 |
740
I1_LOAD_S(2) | I1_LOAD_S(3) | I1_LOAD_S(8) | 2);
741
BATCH((!op->src.is_solid + (op->mask.bo != NULL)) << 12);
742
BATCH(S3_CULLMODE_NONE | S3_VERTEXHAS_XY);
743
BATCH(gen2_get_blend_cntl(op->op,
744
op->has_component_alpha,
746
if (memcmp(sna->kgem.batch + sna->render_state.gen2.ls1 + 1,
747
sna->kgem.batch + unwind + 1,
748
3 * sizeof(uint32_t)) == 0)
749
sna->kgem.nbatch = unwind;
751
sna->render_state.gen2.ls1 = unwind;
753
gen2_disable_logic_op(sna);
755
gen2_get_blend_factors(op, op->op, &cblend, &ablend);
756
unwind = sna->kgem.nbatch;
757
BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_2 |
758
LOAD_TEXTURE_BLEND_STAGE(0) | 1);
761
if (memcmp(sna->kgem.batch + sna->render_state.gen2.ls2 + 1,
762
sna->kgem.batch + unwind + 1,
763
2 * sizeof(uint32_t)) == 0)
764
sna->kgem.nbatch = unwind;
766
sna->render_state.gen2.ls2 = unwind;
768
tex = texcoordfmt = 0;
769
if (!op->src.is_solid) {
770
if (op->src.is_affine)
771
texcoordfmt |= TEXCOORDFMT_2D << (2*tex);
773
texcoordfmt |= TEXCOORDFMT_3D << (2*tex);
774
gen2_emit_texture(sna, &op->src, tex++);
776
if (op->src.u.gen2.pixel != sna->render_state.gen2.diffuse) {
777
BATCH(_3DSTATE_DFLT_DIFFUSE_CMD);
778
BATCH(op->src.u.gen2.pixel);
779
sna->render_state.gen2.diffuse = op->src.u.gen2.pixel;
783
if (op->mask.is_affine)
784
texcoordfmt |= TEXCOORDFMT_2D << (2*tex);
786
texcoordfmt |= TEXCOORDFMT_3D << (2*tex);
787
gen2_emit_texture(sna, &op->mask, tex++);
788
} else if (op->mask.is_solid) {
789
if (op->mask.u.gen2.pixel != sna->render_state.gen2.diffuse) {
790
BATCH(_3DSTATE_DFLT_DIFFUSE_CMD);
791
BATCH(op->mask.u.gen2.pixel);
792
sna->render_state.gen2.diffuse = op->mask.u.gen2.pixel;
796
v = _3DSTATE_VERTEX_FORMAT_2_CMD | texcoordfmt;
797
if (sna->render_state.gen2.vft != v) {
799
sna->render_state.gen2.vft = v;
804
gen2_emit_composite_dstcoord(struct sna *sna, int dstX, int dstY)
811
gen2_emit_composite_linear(struct sna *sna,
812
const struct sna_composite_channel *channel,
813
int16_t x, int16_t y)
817
v = (x * channel->u.linear.dx +
818
y * channel->u.linear.dy +
819
channel->u.linear.offset);
820
DBG(("%s: (%d, %d) -> %f\n", __FUNCTION__, x, y, v));
826
gen2_emit_composite_texcoord(struct sna *sna,
827
const struct sna_composite_channel *channel,
828
int16_t x, int16_t y)
830
float s = 0, t = 0, w = 1;
832
x += channel->offset[0];
833
y += channel->offset[1];
835
if (channel->is_affine) {
836
sna_get_transformed_coordinates(x, y,
839
VERTEX(s * channel->scale[0]);
840
VERTEX(t * channel->scale[1]);
842
sna_get_transformed_coordinates_3d(x, y,
845
VERTEX(s * channel->scale[0]);
846
VERTEX(t * channel->scale[1]);
852
gen2_emit_composite_vertex(struct sna *sna,
853
const struct sna_composite_op *op,
854
int16_t srcX, int16_t srcY,
855
int16_t mskX, int16_t mskY,
856
int16_t dstX, int16_t dstY)
858
gen2_emit_composite_dstcoord(sna, dstX, dstY);
859
if (op->src.is_linear)
860
gen2_emit_composite_linear(sna, &op->src, srcX, srcY);
861
else if (!op->src.is_solid)
862
gen2_emit_composite_texcoord(sna, &op->src, srcX, srcY);
864
if (op->mask.is_linear)
865
gen2_emit_composite_linear(sna, &op->mask, mskX, mskY);
866
else if (op->mask.bo)
867
gen2_emit_composite_texcoord(sna, &op->mask, mskX, mskY);
871
gen2_emit_composite_primitive(struct sna *sna,
872
const struct sna_composite_op *op,
873
const struct sna_composite_rectangles *r)
875
gen2_emit_composite_vertex(sna, op,
877
r->src.y + r->height,
878
r->mask.x + r->width,
879
r->mask.y + r->height,
880
op->dst.x + r->dst.x + r->width,
881
op->dst.y + r->dst.y + r->height);
882
gen2_emit_composite_vertex(sna, op,
884
r->src.y + r->height,
886
r->mask.y + r->height,
887
op->dst.x + r->dst.x,
888
op->dst.y + r->dst.y + r->height);
889
gen2_emit_composite_vertex(sna, op,
894
op->dst.x + r->dst.x,
895
op->dst.y + r->dst.y);
899
gen2_emit_composite_primitive_constant(struct sna *sna,
900
const struct sna_composite_op *op,
901
const struct sna_composite_rectangles *r)
903
int16_t dst_x = r->dst.x + op->dst.x;
904
int16_t dst_y = r->dst.y + op->dst.y;
906
gen2_emit_composite_dstcoord(sna, dst_x + r->width, dst_y + r->height);
907
gen2_emit_composite_dstcoord(sna, dst_x, dst_y + r->height);
908
gen2_emit_composite_dstcoord(sna, dst_x, dst_y);
912
gen2_emit_composite_primitive_linear(struct sna *sna,
913
const struct sna_composite_op *op,
914
const struct sna_composite_rectangles *r)
916
int16_t dst_x = r->dst.x + op->dst.x;
917
int16_t dst_y = r->dst.y + op->dst.y;
919
gen2_emit_composite_dstcoord(sna, dst_x + r->width, dst_y + r->height);
920
gen2_emit_composite_linear(sna, &op->src,
921
r->src.x + r->width, r->src.y + r->height);
923
gen2_emit_composite_dstcoord(sna, dst_x, dst_y + r->height);
924
gen2_emit_composite_linear(sna, &op->src,
925
r->src.x, r->src.y + r->height);
927
gen2_emit_composite_dstcoord(sna, dst_x, dst_y);
928
gen2_emit_composite_linear(sna, &op->src,
933
gen2_emit_composite_primitive_identity(struct sna *sna,
934
const struct sna_composite_op *op,
935
const struct sna_composite_rectangles *r)
941
v = (float *)sna->kgem.batch + sna->kgem.nbatch;
942
sna->kgem.nbatch += 12;
944
v[8] = v[4] = r->dst.x + op->dst.x;
947
v[9] = r->dst.y + op->dst.y;
948
v[5] = v[1] = v[9] + h;
950
v[10] = v[6] = (r->src.x + op->src.offset[0]) * op->src.scale[0];
951
v[2] = v[6] + w * op->src.scale[0];
953
v[11] = (r->src.y + op->src.offset[1]) * op->src.scale[1];
954
v[7] = v[3] = v[11] + h * op->src.scale[1];
958
gen2_emit_composite_primitive_affine(struct sna *sna,
959
const struct sna_composite_op *op,
960
const struct sna_composite_rectangles *r)
962
PictTransform *transform = op->src.transform;
963
int src_x = r->src.x + (int)op->src.offset[0];
964
int src_y = r->src.y + (int)op->src.offset[1];
967
v = (float *)sna->kgem.batch + sna->kgem.nbatch;
968
sna->kgem.nbatch += 12;
970
v[8] = v[4] = r->dst.x + op->dst.x;
971
v[0] = v[4] + r->width;
973
v[9] = r->dst.y + op->dst.y;
974
v[5] = v[1] = v[9] + r->height;
976
_sna_get_transformed_scaled(src_x + r->width, src_y + r->height,
977
transform, op->src.scale,
980
_sna_get_transformed_scaled(src_x, src_y + r->height,
981
transform, op->src.scale,
984
_sna_get_transformed_scaled(src_x, src_y,
985
transform, op->src.scale,
990
gen2_emit_composite_primitive_constant_identity_mask(struct sna *sna,
991
const struct sna_composite_op *op,
992
const struct sna_composite_rectangles *r)
998
v = (float *)sna->kgem.batch + sna->kgem.nbatch;
999
sna->kgem.nbatch += 12;
1001
v[8] = v[4] = r->dst.x + op->dst.x;
1004
v[9] = r->dst.y + op->dst.y;
1005
v[5] = v[1] = v[9] + h;
1007
v[10] = v[6] = (r->mask.x + op->mask.offset[0]) * op->mask.scale[0];
1008
v[2] = v[6] + w * op->mask.scale[0];
1010
v[11] = (r->mask.y + op->mask.offset[1]) * op->mask.scale[1];
1011
v[7] = v[3] = v[11] + h * op->mask.scale[1];
1014
#if defined(sse2) && !defined(__x86_64__)
1015
sse2 fastcall static void
1016
gen2_emit_composite_primitive_constant__sse2(struct sna *sna,
1017
const struct sna_composite_op *op,
1018
const struct sna_composite_rectangles *r)
1020
int16_t dst_x = r->dst.x + op->dst.x;
1021
int16_t dst_y = r->dst.y + op->dst.y;
1023
gen2_emit_composite_dstcoord(sna, dst_x + r->width, dst_y + r->height);
1024
gen2_emit_composite_dstcoord(sna, dst_x, dst_y + r->height);
1025
gen2_emit_composite_dstcoord(sna, dst_x, dst_y);
1028
sse2 fastcall static void
1029
gen2_emit_composite_primitive_linear__sse2(struct sna *sna,
1030
const struct sna_composite_op *op,
1031
const struct sna_composite_rectangles *r)
1033
int16_t dst_x = r->dst.x + op->dst.x;
1034
int16_t dst_y = r->dst.y + op->dst.y;
1036
gen2_emit_composite_dstcoord(sna, dst_x + r->width, dst_y + r->height);
1037
gen2_emit_composite_linear(sna, &op->src,
1038
r->src.x + r->width, r->src.y + r->height);
1040
gen2_emit_composite_dstcoord(sna, dst_x, dst_y + r->height);
1041
gen2_emit_composite_linear(sna, &op->src,
1042
r->src.x, r->src.y + r->height);
1044
gen2_emit_composite_dstcoord(sna, dst_x, dst_y);
1045
gen2_emit_composite_linear(sna, &op->src,
1046
r->src.x, r->src.y);
1049
sse2 fastcall static void
1050
gen2_emit_composite_primitive_identity__sse2(struct sna *sna,
1051
const struct sna_composite_op *op,
1052
const struct sna_composite_rectangles *r)
1055
float h = r->height;
1058
v = (float *)sna->kgem.batch + sna->kgem.nbatch;
1059
sna->kgem.nbatch += 12;
1061
v[8] = v[4] = r->dst.x + op->dst.x;
1064
v[9] = r->dst.y + op->dst.y;
1065
v[5] = v[1] = v[9] + h;
1067
v[10] = v[6] = (r->src.x + op->src.offset[0]) * op->src.scale[0];
1068
v[2] = v[6] + w * op->src.scale[0];
1070
v[11] = (r->src.y + op->src.offset[1]) * op->src.scale[1];
1071
v[7] = v[3] = v[11] + h * op->src.scale[1];
1074
sse2 fastcall static void
1075
gen2_emit_composite_primitive_affine__sse2(struct sna *sna,
1076
const struct sna_composite_op *op,
1077
const struct sna_composite_rectangles *r)
1079
PictTransform *transform = op->src.transform;
1080
int src_x = r->src.x + (int)op->src.offset[0];
1081
int src_y = r->src.y + (int)op->src.offset[1];
1084
v = (float *)sna->kgem.batch + sna->kgem.nbatch;
1085
sna->kgem.nbatch += 12;
1087
v[8] = v[4] = r->dst.x + op->dst.x;
1088
v[0] = v[4] + r->width;
1090
v[9] = r->dst.y + op->dst.y;
1091
v[5] = v[1] = v[9] + r->height;
1093
_sna_get_transformed_scaled(src_x + r->width, src_y + r->height,
1094
transform, op->src.scale,
1097
_sna_get_transformed_scaled(src_x, src_y + r->height,
1098
transform, op->src.scale,
1101
_sna_get_transformed_scaled(src_x, src_y,
1102
transform, op->src.scale,
1106
sse2 fastcall static void
1107
gen2_emit_composite_primitive_constant_identity_mask__sse2(struct sna *sna,
1108
const struct sna_composite_op *op,
1109
const struct sna_composite_rectangles *r)
1112
float h = r->height;
1115
v = (float *)sna->kgem.batch + sna->kgem.nbatch;
1116
sna->kgem.nbatch += 12;
1118
v[8] = v[4] = r->dst.x + op->dst.x;
1121
v[9] = r->dst.y + op->dst.y;
1122
v[5] = v[1] = v[9] + h;
1124
v[10] = v[6] = (r->mask.x + op->mask.offset[0]) * op->mask.scale[0];
1125
v[2] = v[6] + w * op->mask.scale[0];
1127
v[11] = (r->mask.y + op->mask.offset[1]) * op->mask.scale[1];
1128
v[7] = v[3] = v[11] + h * op->mask.scale[1];
1132
static void gen2_magic_ca_pass(struct sna *sna,
1133
const struct sna_composite_op *op)
1135
uint32_t ablend, cblend, *src, *dst;
1138
if (!op->need_magic_ca_pass)
1141
DBG(("%s: batch=%x, vertex=%x\n", __FUNCTION__,
1142
sna->kgem.nbatch, sna->render.vertex_offset));
1144
assert(op->mask.bo);
1145
assert(op->has_component_alpha);
1147
BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(8) | 0);
1148
BATCH(BLENDFACTOR_ONE << S8_SRC_BLEND_FACTOR_SHIFT |
1149
BLENDFACTOR_ONE << S8_DST_BLEND_FACTOR_SHIFT |
1150
S8_ENABLE_COLOR_BLEND | S8_BLENDFUNC_ADD |
1151
S8_ENABLE_COLOR_BUFFER_WRITE);
1152
sna->render_state.gen2.ls1 = 0;
1154
gen2_get_blend_factors(op, PictOpAdd, &cblend, &ablend);
1155
BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_2 |
1156
LOAD_TEXTURE_BLEND_STAGE(0) | 1);
1159
sna->render_state.gen2.ls2 = 0;
1161
src = sna->kgem.batch + sna->render.vertex_offset;
1162
dst = sna->kgem.batch + sna->kgem.nbatch;
1163
n = 1 + sna->render.vertex_index;
1164
sna->kgem.nbatch += n;
1165
assert(sna->kgem.nbatch <= KGEM_BATCH_SIZE(&sna->kgem));
1170
static void gen2_vertex_flush(struct sna *sna,
1171
const struct sna_composite_op *op)
1173
if (sna->render.vertex_index == 0)
1176
sna->kgem.batch[sna->render.vertex_offset] |=
1177
sna->render.vertex_index - 1;
1179
gen2_magic_ca_pass(sna, op);
1181
sna->render.vertex_offset = 0;
1182
sna->render.vertex_index = 0;
1185
inline static int gen2_get_rectangles(struct sna *sna,
1186
const struct sna_composite_op *op,
1189
int rem = batch_space(sna), size, need;
1191
DBG(("%s: want=%d, floats_per_vertex=%d, rem=%d\n",
1192
__FUNCTION__, want, op->floats_per_vertex, rem));
1194
assert(op->floats_per_vertex);
1195
assert(op->floats_per_rect == 3 * op->floats_per_vertex);
1198
size = op->floats_per_rect;
1199
if (op->need_magic_ca_pass)
1200
need += 6 + size*sna->render.vertex_index, size *= 2;
1202
DBG(("%s: want=%d, need=%d,size=%d, rem=%d\n",
1203
__FUNCTION__, want, need, size, rem));
1204
if (rem < need + size) {
1205
gen2_vertex_flush(sna, op);
1206
kgem_submit(&sna->kgem);
1207
_kgem_set_mode(&sna->kgem, KGEM_RENDER);
1212
if (sna->render.vertex_offset == 0) {
1213
if ((sna->kgem.batch[sna->kgem.nbatch-1] & ~0xffff) ==
1214
(PRIM3D_INLINE | PRIM3D_RECTLIST)) {
1215
uint32_t *b = &sna->kgem.batch[sna->kgem.nbatch-1];
1216
assert(*b & 0xffff);
1217
sna->render.vertex_index = 1 + (*b & 0xffff);
1218
*b = PRIM3D_INLINE | PRIM3D_RECTLIST;
1219
sna->render.vertex_offset = sna->kgem.nbatch - 1;
1220
assert(!op->need_magic_ca_pass);
1222
sna->render.vertex_offset = sna->kgem.nbatch;
1223
BATCH(PRIM3D_INLINE | PRIM3D_RECTLIST);
1228
need = sna->kgem.nbatch - sna->render.vertex_offset;
1230
if (rem > MAX_INLINE - need)
1231
rem = MAX_INLINE -need;
1233
if (want > 1 && want * size > rem)
1237
sna->render.vertex_index += want*op->floats_per_rect;
1241
fastcall static void
1242
gen2_render_composite_blt(struct sna *sna,
1243
const struct sna_composite_op *op,
1244
const struct sna_composite_rectangles *r)
1246
if (!gen2_get_rectangles(sna, op, 1)) {
1247
gen2_emit_composite_state(sna, op);
1248
gen2_get_rectangles(sna, op, 1);
1251
op->prim_emit(sna, op, r);
1254
fastcall static void
1255
gen2_render_composite_box(struct sna *sna,
1256
const struct sna_composite_op *op,
1259
struct sna_composite_rectangles r;
1261
if (!gen2_get_rectangles(sna, op, 1)) {
1262
gen2_emit_composite_state(sna, op);
1263
gen2_get_rectangles(sna, op, 1);
1266
DBG((" %s: (%d, %d) x (%d, %d)\n", __FUNCTION__,
1269
box->y2 - box->y1));
1271
r.dst.x = box->x1; r.dst.y = box->y1;
1272
r.width = box->x2 - box->x1;
1273
r.height = box->y2 - box->y1;
1274
r.src = r.mask = r.dst;
1276
op->prim_emit(sna, op, &r);
1280
gen2_render_composite_boxes(struct sna *sna,
1281
const struct sna_composite_op *op,
1282
const BoxRec *box, int nbox)
1287
nbox_this_time = gen2_get_rectangles(sna, op, nbox);
1288
if (nbox_this_time == 0) {
1289
gen2_emit_composite_state(sna, op);
1290
nbox_this_time = gen2_get_rectangles(sna, op, nbox);
1292
nbox -= nbox_this_time;
1295
struct sna_composite_rectangles r;
1297
DBG((" %s: (%d, %d) x (%d, %d)\n", __FUNCTION__,
1300
box->y2 - box->y1));
1302
r.dst.x = box->x1; r.dst.y = box->y1;
1303
r.width = box->x2 - box->x1;
1304
r.height = box->y2 - box->y1;
1305
r.src = r.mask = r.dst;
1307
op->prim_emit(sna, op, &r);
1309
} while (--nbox_this_time);
1313
static void gen2_render_composite_done(struct sna *sna,
1314
const struct sna_composite_op *op)
1316
gen2_vertex_flush(sna, op);
1319
kgem_bo_destroy(&sna->kgem, op->mask.bo);
1321
kgem_bo_destroy(&sna->kgem, op->src.bo);
1322
sna_render_composite_redirect_done(sna, op);
1326
gen2_composite_solid_init(struct sna *sna,
1327
struct sna_composite_channel *channel,
1330
channel->filter = PictFilterNearest;
1331
channel->repeat = RepeatNormal;
1332
channel->is_solid = true;
1333
channel->is_affine = true;
1335
channel->height = 1;
1336
channel->pict_format = PICT_a8r8g8b8;
1339
channel->u.gen2.pixel = color;
1341
channel->scale[0] = channel->scale[1] = 1;
1342
channel->offset[0] = channel->offset[1] = 0;
1346
#define xFixedToDouble(f) pixman_fixed_to_double(f)
1349
gen2_composite_linear_init(struct sna *sna,
1351
struct sna_composite_channel *channel,
1354
int dst_x, int dst_y)
1356
PictLinearGradient *linear =
1357
(PictLinearGradient *)picture->pSourcePict;
1358
pixman_fixed_t tx, ty;
1362
DBG(("%s: p1=(%f, %f), p2=(%f, %f)\n",
1364
xFixedToDouble(linear->p1.x), xFixedToDouble(linear->p1.y),
1365
xFixedToDouble(linear->p2.x), xFixedToDouble(linear->p2.y)));
1367
if (linear->p2.x == linear->p1.x && linear->p2.y == linear->p1.y)
1370
if (!sna_transform_is_affine(picture->transform)) {
1371
DBG(("%s: fallback due to projective transform\n",
1373
return sna_render_picture_fixup(sna, picture, channel,
1374
x, y, w, h, dst_x, dst_y);
1377
channel->bo = sna_render_get_gradient(sna, (PictGradient *)linear);
1381
channel->filter = PictFilterNearest;
1382
channel->repeat = picture->repeat ? picture->repeatType : RepeatNone;
1383
channel->is_linear = true;
1384
channel->width = channel->bo->pitch / 4;
1385
channel->height = 1;
1386
channel->pict_format = PICT_a8r8g8b8;
1388
channel->scale[0] = channel->scale[1] = 1;
1389
channel->offset[0] = channel->offset[1] = 0;
1391
if (sna_transform_is_translation(picture->transform, &tx, &ty)) {
1392
dx = xFixedToDouble(linear->p2.x - linear->p1.x);
1393
dy = xFixedToDouble(linear->p2.y - linear->p1.y);
1395
x0 = xFixedToDouble(linear->p1.x);
1396
y0 = xFixedToDouble(linear->p1.y);
1399
x0 -= pixman_fixed_to_double(tx);
1400
y0 -= pixman_fixed_to_double(ty);
1403
struct pixman_f_vector p1, p2;
1404
struct pixman_f_transform m, inv;
1406
pixman_f_transform_from_pixman_transform(&m, picture->transform);
1407
DBG(("%s: transform = [%f %f %f, %f %f %f, %f %f %f]\n",
1409
m.m[0][0], m.m[0][1], m.m[0][2],
1410
m.m[1][0], m.m[1][1], m.m[1][2],
1411
m.m[2][0], m.m[2][1], m.m[2][2]));
1412
if (!pixman_f_transform_invert(&inv, &m))
1415
p1.v[0] = pixman_fixed_to_double(linear->p1.x);
1416
p1.v[1] = pixman_fixed_to_double(linear->p1.y);
1418
pixman_f_transform_point(&inv, &p1);
1420
p2.v[0] = pixman_fixed_to_double(linear->p2.x);
1421
p2.v[1] = pixman_fixed_to_double(linear->p2.y);
1423
pixman_f_transform_point(&inv, &p2);
1425
DBG(("%s: untransformed: p1=(%f, %f, %f), p2=(%f, %f, %f)\n",
1427
p1.v[0], p1.v[1], p1.v[2],
1428
p2.v[0], p2.v[1], p2.v[2]));
1430
dx = p2.v[0] - p1.v[0];
1431
dy = p2.v[1] - p1.v[1];
1441
channel->u.linear.dx = dx;
1442
channel->u.linear.dy = dy;
1443
channel->u.linear.offset = -dx*(x0+dst_x-x) + -dy*(y0+dst_y-y);
1445
DBG(("%s: dx=%f, dy=%f, offset=%f\n",
1446
__FUNCTION__, dx, dy, channel->u.linear.offset));
1448
return channel->bo != NULL;
1451
static bool source_is_covered(PicturePtr picture,
1453
int width, int height)
1457
if (picture->repeat && picture->repeatType != RepeatNone)
1460
if (picture->pDrawable == NULL)
1463
if (picture->transform) {
1464
pixman_box16_t sample;
1468
sample.x2 = x + width;
1469
sample.y2 = y + height;
1471
pixman_transform_bounds(picture->transform, &sample);
1485
x1 >= 0 && y1 >= 0 &&
1486
x2 <= picture->pDrawable->width &&
1487
y2 <= picture->pDrawable->height;
1491
gen2_check_card_format(struct sna *sna,
1493
struct sna_composite_channel *channel,
1494
int x, int y, int w, int h,
1497
uint32_t format = picture->format;
1500
for (i = 0; i < ARRAY_SIZE(i8xx_tex_formats); i++) {
1501
if (i8xx_tex_formats[i].fmt == format)
1505
for (i = 0; i < ARRAY_SIZE(i85x_tex_formats); i++) {
1506
if (i85x_tex_formats[i].fmt == format) {
1507
if (sna->kgem.gen >= 021)
1510
if (source_is_covered(picture, x, y, w,h)) {
1511
channel->is_opaque = true;
1515
*fixup_alpha = true;
1520
*fixup_alpha = false;
1525
gen2_composite_picture(struct sna *sna,
1527
struct sna_composite_channel *channel,
1530
int dst_x, int dst_y,
1538
DBG(("%s: (%d, %d)x(%d, %d), dst=(%d, %d)\n",
1539
__FUNCTION__, x, y, w, h, dst_x, dst_y));
1541
channel->is_solid = false;
1542
channel->is_linear = false;
1543
channel->is_opaque = false;
1544
channel->is_affine = true;
1545
channel->transform = NULL;
1546
channel->card_format = -1;
1548
if (sna_picture_is_solid(picture, &color))
1549
return gen2_composite_solid_init(sna, channel, color);
1551
if (!gen2_check_repeat(picture)) {
1552
DBG(("%s -- fallback, unhandled repeat %d\n",
1553
__FUNCTION__, picture->repeat));
1554
return sna_render_picture_fixup(sna, picture, channel,
1555
x, y, w, h, dst_x, dst_y);
1558
if (!gen2_check_filter(picture)) {
1559
DBG(("%s -- fallback, unhandled filter %d\n",
1560
__FUNCTION__, picture->filter));
1561
return sna_render_picture_fixup(sna, picture, channel,
1562
x, y, w, h, dst_x, dst_y);
1565
if (picture->pDrawable == NULL) {
1568
if (picture->pSourcePict->type == SourcePictTypeLinear)
1569
return gen2_composite_linear_init(sna, picture, channel,
1574
DBG(("%s -- fallback, unhandled source %d\n",
1575
__FUNCTION__, picture->pSourcePict->type));
1578
ret = sna_render_picture_approximate_gradient(sna, picture, channel,
1579
x, y, w, h, dst_x, dst_y);
1581
ret = sna_render_picture_fixup(sna, picture, channel,
1582
x, y, w, h, dst_x, dst_y);
1586
if (picture->alphaMap) {
1587
DBG(("%s -- fallback, alphamap\n", __FUNCTION__));
1588
return sna_render_picture_fixup(sna, picture, channel,
1589
x, y, w, h, dst_x, dst_y);
1592
channel->repeat = picture->repeat ? picture->repeatType : RepeatNone;
1593
channel->filter = picture->filter;
1595
pixmap = get_drawable_pixmap(picture->pDrawable);
1596
get_drawable_deltas(picture->pDrawable, pixmap, &dx, &dy);
1598
x += dx + picture->pDrawable->x;
1599
y += dy + picture->pDrawable->y;
1601
channel->is_affine = sna_transform_is_affine(picture->transform);
1602
if (sna_transform_is_imprecise_integer_translation(picture->transform, picture->filter, precise, &dx, &dy)) {
1603
DBG(("%s: integer translation (%d, %d), removing\n",
1604
__FUNCTION__, dx, dy));
1607
channel->transform = NULL;
1608
channel->filter = PictFilterNearest;
1610
if (channel->repeat &&
1613
x + w <= pixmap->drawable.width &&
1614
y + h <= pixmap->drawable.height)) {
1615
struct sna_pixmap *priv = sna_pixmap(pixmap);
1616
if (priv && priv->clear) {
1617
DBG(("%s: converting large pixmap source into solid [%08x]\n", __FUNCTION__, priv->clear_color));
1618
return gen2_composite_solid_init(sna, channel, solid_color(picture->format, priv->clear_color));
1622
channel->transform = picture->transform;
1624
if (!gen2_check_card_format(sna, picture, channel, x, y, w ,h, &fixup_alpha))
1625
return sna_render_picture_convert(sna, picture, channel, pixmap,
1626
x, y, w, h, dst_x, dst_y, fixup_alpha);
1628
channel->pict_format = picture->format;
1629
if (too_large(pixmap->drawable.width, pixmap->drawable.height))
1630
return sna_render_picture_extract(sna, picture, channel,
1631
x, y, w, h, dst_x, dst_y);
1633
return sna_render_pixmap_bo(sna, channel, pixmap,
1634
x, y, w, h, dst_x, dst_y);
1638
gen2_composite_set_target(struct sna *sna,
1639
struct sna_composite_op *op,
1641
int x, int y, int w, int h,
1647
op->dst.pixmap = get_drawable_pixmap(dst->pDrawable);
1648
op->dst.format = dst->format;
1649
op->dst.width = op->dst.pixmap->drawable.width;
1650
op->dst.height = op->dst.pixmap->drawable.height;
1658
sna_render_picture_extents(dst, &box);
1660
hint = PREFER_GPU | RENDER_GPU;
1661
if (!need_tiling(sna, op->dst.width, op->dst.height))
1664
hint |= IGNORE_DAMAGE;
1665
if (w == op->dst.width && h == op->dst.height)
1669
op->dst.bo = sna_drawable_use_bo(dst->pDrawable, hint, &box, &op->damage);
1670
if (op->dst.bo == NULL)
1673
if (hint & REPLACES) {
1674
struct sna_pixmap *priv = sna_pixmap(op->dst.pixmap);
1675
kgem_bo_pair_undo(&sna->kgem, priv->gpu_bo, priv->cpu_bo);
1678
assert((op->dst.bo->pitch & 7) == 0);
1680
get_drawable_deltas(dst->pDrawable, op->dst.pixmap,
1681
&op->dst.x, &op->dst.y);
1683
DBG(("%s: pixmap=%ld, format=%08x, size=%dx%d, pitch=%d, delta=(%d,%d),damage=%p\n",
1685
op->dst.pixmap->drawable.serialNumber, (int)op->dst.format,
1686
op->dst.width, op->dst.height,
1688
op->dst.x, op->dst.y,
1689
op->damage ? *op->damage : (void *)-1));
1691
assert(op->dst.bo->proxy == NULL);
1693
if (((too_large(op->dst.width, op->dst.height) ||
1694
op->dst.bo->pitch > MAX_3D_PITCH)) &&
1695
!sna_render_composite_redirect(sna, op, x, y, w, h, partial))
1702
is_unhandled_gradient(PicturePtr picture, bool precise)
1704
if (picture->pDrawable)
1707
switch (picture->pSourcePict->type) {
1708
case SourcePictTypeSolidFill:
1709
case SourcePictTypeLinear:
1717
has_alphamap(PicturePtr p)
1719
return p->alphaMap != NULL;
1723
need_upload(PicturePtr p)
1725
return p->pDrawable && unattached(p->pDrawable) && untransformed(p);
1729
source_is_busy(PixmapPtr pixmap)
1731
struct sna_pixmap *priv = sna_pixmap(pixmap);
1738
if (priv->gpu_bo && kgem_bo_is_busy(priv->gpu_bo))
1741
if (priv->cpu_bo && kgem_bo_is_busy(priv->cpu_bo))
1744
return priv->gpu_damage && !priv->cpu_damage;
1748
source_fallback(PicturePtr p, PixmapPtr pixmap, bool precise)
1750
if (sna_picture_is_solid(p, NULL))
1753
if (is_unhandled_gradient(p, precise) || !gen2_check_repeat(p))
1756
if (pixmap && source_is_busy(pixmap))
1759
return has_alphamap(p) || !gen2_check_filter(p) || need_upload(p);
1763
gen2_composite_fallback(struct sna *sna,
1768
PixmapPtr src_pixmap;
1769
PixmapPtr mask_pixmap;
1770
PixmapPtr dst_pixmap;
1771
bool src_fallback, mask_fallback;
1773
if (!gen2_check_dst_format(dst->format)) {
1774
DBG(("%s: unknown destination format: %d\n",
1775
__FUNCTION__, dst->format));
1779
dst_pixmap = get_drawable_pixmap(dst->pDrawable);
1781
src_pixmap = src->pDrawable ? get_drawable_pixmap(src->pDrawable) : NULL;
1782
src_fallback = source_fallback(src, src_pixmap,
1783
dst->polyMode == PolyModePrecise);
1786
mask_pixmap = mask->pDrawable ? get_drawable_pixmap(mask->pDrawable) : NULL;
1787
mask_fallback = source_fallback(mask, mask_pixmap,
1788
dst->polyMode == PolyModePrecise);
1791
mask_fallback = NULL;
1794
/* If we are using the destination as a source and need to
1795
* readback in order to upload the source, do it all
1798
if (src_pixmap == dst_pixmap && src_fallback) {
1799
DBG(("%s: src is dst and will fallback\n",__FUNCTION__));
1802
if (mask_pixmap == dst_pixmap && mask_fallback) {
1803
DBG(("%s: mask is dst and will fallback\n",__FUNCTION__));
1807
/* If anything is on the GPU, push everything out to the GPU */
1808
if (dst_use_gpu(dst_pixmap)) {
1809
DBG(("%s: dst is already on the GPU, try to use GPU\n",
1814
if (src_pixmap && !src_fallback) {
1815
DBG(("%s: src is already on the GPU, try to use GPU\n",
1819
if (mask_pixmap && !mask_fallback) {
1820
DBG(("%s: mask is already on the GPU, try to use GPU\n",
1825
/* However if the dst is not on the GPU and we need to
1826
* render one of the sources using the CPU, we may
1827
* as well do the entire operation in place onthe CPU.
1830
DBG(("%s: dst is on the CPU and src will fallback\n",
1835
if (mask && mask_fallback) {
1836
DBG(("%s: dst is on the CPU and mask will fallback\n",
1841
if (too_large(dst_pixmap->drawable.width,
1842
dst_pixmap->drawable.height) &&
1843
dst_is_cpu(dst_pixmap)) {
1844
DBG(("%s: dst is on the CPU and too large\n", __FUNCTION__));
1848
DBG(("%s: dst is not on the GPU and the operation should not fallback\n",
1850
return dst_use_cpu(dst_pixmap);
1854
reuse_source(struct sna *sna,
1855
PicturePtr src, struct sna_composite_channel *sc, int src_x, int src_y,
1856
PicturePtr mask, struct sna_composite_channel *mc, int msk_x, int msk_y)
1860
if (src_x != msk_x || src_y != msk_y)
1863
if (sna_picture_is_solid(mask, &color))
1864
return gen2_composite_solid_init(sna, mc, color);
1870
DBG(("%s: mask is source\n", __FUNCTION__));
1872
mc->bo = kgem_bo_reference(mc->bo);
1876
if (src->pDrawable == NULL || mask->pDrawable != src->pDrawable)
1879
DBG(("%s: mask reuses source drawable\n", __FUNCTION__));
1881
if (!sna_transform_equal(src->transform, mask->transform))
1884
if (!sna_picture_alphamap_equal(src, mask))
1887
if (!gen2_check_repeat(mask))
1890
if (!gen2_check_filter(mask))
1893
if (!gen2_check_format(sna, mask))
1896
DBG(("%s: reusing source channel for mask with a twist\n",
1900
mc->repeat = mask->repeat ? mask->repeatType : RepeatNone;
1901
mc->filter = mask->filter;
1902
mc->pict_format = mask->format;
1903
mc->bo = kgem_bo_reference(mc->bo);
1908
gen2_render_composite(struct sna *sna,
1913
int16_t src_x, int16_t src_y,
1914
int16_t mask_x, int16_t mask_y,
1915
int16_t dst_x, int16_t dst_y,
1916
int16_t width, int16_t height,
1918
struct sna_composite_op *tmp)
1920
DBG(("%s()\n", __FUNCTION__));
1922
if (op >= ARRAY_SIZE(gen2_blend_op)) {
1923
DBG(("%s: fallback due to unhandled blend op: %d\n",
1929
sna_blt_composite(sna, op, src, dst,
1936
if (gen2_composite_fallback(sna, src, mask, dst))
1939
if (need_tiling(sna, width, height))
1940
return sna_tiling_composite(op, src, mask, dst,
1948
sna_render_composite_redirect_init(tmp);
1950
if (!gen2_composite_set_target(sna, tmp, dst,
1951
dst_x, dst_y, width, height,
1952
flags & COMPOSITE_PARTIAL || op > PictOpSrc)) {
1953
DBG(("%s: unable to set render target\n",
1958
switch (gen2_composite_picture(sna, src, &tmp->src,
1962
dst->polyMode == PolyModePrecise)) {
1964
DBG(("%s: fallback -- unable to prepare source\n",
1968
gen2_composite_solid_init(sna, &tmp->src, 0);
1971
if (mask == NULL && tmp->src.bo &&
1972
sna_blt_composite__convert(sna,
1973
dst_x, dst_y, width, height,
1980
if (!reuse_source(sna,
1981
src, &tmp->src, src_x, src_y,
1982
mask, &tmp->mask, mask_x, mask_y)) {
1983
switch (gen2_composite_picture(sna, mask, &tmp->mask,
1987
dst->polyMode == PolyModePrecise)) {
1989
DBG(("%s: fallback -- unable to prepare mask\n",
1993
gen2_composite_solid_init(sna, &tmp->mask, 0);
1999
if (mask->componentAlpha && PICT_FORMAT_RGB(mask->format)) {
2000
/* Check if it's component alpha that relies on a source alpha
2001
* and on the source value. We can only get one of those
2002
* into the single source value that we get to blend with.
2004
tmp->has_component_alpha = true;
2005
if (gen2_blend_op[op].src_alpha &&
2006
(gen2_blend_op[op].src_blend != BLENDFACTOR_ZERO)) {
2007
if (op != PictOpOver) {
2008
DBG(("%s: fallback -- unsupported CA blend (src_blend=%d)\n",
2010
gen2_blend_op[op].src_blend));
2014
tmp->need_magic_ca_pass = true;
2015
tmp->op = PictOpOutReverse;
2019
/* convert solid to a texture (pure convenience) */
2020
if (tmp->mask.is_solid && tmp->src.is_solid) {
2021
assert(tmp->mask.is_affine);
2022
tmp->mask.bo = sna_render_get_solid(sna, tmp->mask.u.gen2.pixel);
2028
tmp->floats_per_vertex = 2;
2029
if (!tmp->src.is_solid)
2030
tmp->floats_per_vertex += tmp->src.is_affine ? 2 : 3;
2032
tmp->floats_per_vertex += tmp->mask.is_affine ? 2 : 3;
2033
tmp->floats_per_rect = 3*tmp->floats_per_vertex;
2035
tmp->prim_emit = gen2_emit_composite_primitive;
2037
if (tmp->mask.transform == NULL) {
2038
if (tmp->src.is_solid) {
2039
assert(tmp->floats_per_rect == 12);
2040
#if defined(sse2) && !defined(__x86_64__)
2041
if (sna->cpu_features & SSE2) {
2042
tmp->prim_emit = gen2_emit_composite_primitive_constant_identity_mask__sse2;
2046
tmp->prim_emit = gen2_emit_composite_primitive_constant_identity_mask;
2051
if (tmp->src.is_solid) {
2052
assert(tmp->floats_per_rect == 6);
2053
#if defined(sse2) && !defined(__x86_64__)
2054
if (sna->cpu_features & SSE2) {
2055
tmp->prim_emit = gen2_emit_composite_primitive_constant__sse2;
2059
tmp->prim_emit = gen2_emit_composite_primitive_constant;
2061
} else if (tmp->src.is_linear) {
2062
assert(tmp->floats_per_rect == 12);
2063
#if defined(sse2) && !defined(__x86_64__)
2064
if (sna->cpu_features & SSE2) {
2065
tmp->prim_emit = gen2_emit_composite_primitive_linear__sse2;
2069
tmp->prim_emit = gen2_emit_composite_primitive_linear;
2071
} else if (tmp->src.transform == NULL) {
2072
assert(tmp->floats_per_rect == 12);
2073
#if defined(sse2) && !defined(__x86_64__)
2074
if (sna->cpu_features & SSE2) {
2075
tmp->prim_emit = gen2_emit_composite_primitive_identity__sse2;
2079
tmp->prim_emit = gen2_emit_composite_primitive_identity;
2081
} else if (tmp->src.is_affine) {
2082
assert(tmp->floats_per_rect == 12);
2083
tmp->src.scale[0] /= tmp->src.transform->matrix[2][2];
2084
tmp->src.scale[1] /= tmp->src.transform->matrix[2][2];
2085
#if defined(sse2) && !defined(__x86_64__)
2086
if (sna->cpu_features & SSE2) {
2087
tmp->prim_emit = gen2_emit_composite_primitive_affine__sse2;
2091
tmp->prim_emit = gen2_emit_composite_primitive_affine;
2096
tmp->blt = gen2_render_composite_blt;
2097
tmp->box = gen2_render_composite_box;
2098
tmp->boxes = gen2_render_composite_boxes;
2099
tmp->done = gen2_render_composite_done;
2101
if (!kgem_check_bo(&sna->kgem,
2102
tmp->dst.bo, tmp->src.bo, tmp->mask.bo,
2104
kgem_submit(&sna->kgem);
2105
if (!kgem_check_bo(&sna->kgem,
2106
tmp->dst.bo, tmp->src.bo, tmp->mask.bo,
2108
DBG(("%s: fallback, operation does not fit into GTT\n",
2114
gen2_emit_composite_state(sna, tmp);
2119
kgem_bo_destroy(&sna->kgem, tmp->mask.bo);
2120
tmp->mask.bo = NULL;
2124
kgem_bo_destroy(&sna->kgem, tmp->src.bo);
2128
if (tmp->redirect.real_bo) {
2129
kgem_bo_destroy(&sna->kgem, tmp->dst.bo);
2130
tmp->redirect.real_bo = NULL;
2133
return (mask == NULL &&
2134
sna_blt_composite(sna, op, src, dst,
2138
flags | COMPOSITE_FALLBACK, tmp));
2141
fastcall static void
2142
gen2_emit_composite_spans_primitive_constant(struct sna *sna,
2143
const struct sna_composite_spans_op *op,
2147
float *v = (float *)sna->kgem.batch + sna->kgem.nbatch;
2148
uint32_t alpha = (uint8_t)(255 * opacity) << 24;
2149
sna->kgem.nbatch += 9;
2151
v[0] = op->base.dst.x + box->x2;
2152
v[1] = op->base.dst.y + box->y2;
2153
*((uint32_t *)v + 2) = alpha;
2155
v[3] = op->base.dst.x + box->x1;
2157
*((uint32_t *)v + 5) = alpha;
2160
v[7] = op->base.dst.y + box->y1;
2161
*((uint32_t *)v + 8) = alpha;
2164
fastcall static void
2165
gen2_emit_composite_spans_primitive_linear(struct sna *sna,
2166
const struct sna_composite_spans_op *op,
2175
alpha.u = (uint8_t)(255 * opacity) << 24;
2177
gen2_emit_composite_dstcoord(sna,
2178
op->base.dst.x + box->x2,
2179
op->base.dst.y + box->y2);
2181
gen2_emit_composite_linear(sna, &op->base.src, box->x2, box->y2);
2183
gen2_emit_composite_dstcoord(sna,
2184
op->base.dst.x + box->x1,
2185
op->base.dst.y + box->y2);
2187
gen2_emit_composite_linear(sna, &op->base.src, box->x1, box->y2);
2189
gen2_emit_composite_dstcoord(sna,
2190
op->base.dst.x + box->x1,
2191
op->base.dst.y + box->y1);
2193
gen2_emit_composite_linear(sna, &op->base.src, box->x1, box->y1);
2196
fastcall static void
2197
gen2_emit_composite_spans_primitive_identity_source(struct sna *sna,
2198
const struct sna_composite_spans_op *op,
2202
float *v = (float *)sna->kgem.batch + sna->kgem.nbatch;
2203
uint32_t alpha = (uint8_t)(255 * opacity) << 24;
2204
sna->kgem.nbatch += 15;
2206
v[0] = op->base.dst.x + box->x2;
2207
v[1] = op->base.dst.y + box->y2;
2208
*((uint32_t *)v + 2) = alpha;
2209
v[3] = (op->base.src.offset[0] + box->x2) * op->base.src.scale[0];
2210
v[4] = (op->base.src.offset[1] + box->y2) * op->base.src.scale[1];
2212
v[5] = op->base.dst.x + box->x1;
2214
*((uint32_t *)v + 7) = alpha;
2215
v[8] = (op->base.src.offset[0] + box->x1) * op->base.src.scale[0];
2219
v[11] = op->base.dst.y + box->y1;
2220
*((uint32_t *)v + 12) = alpha;
2222
v[14] = (op->base.src.offset[1] + box->y1) * op->base.src.scale[1];
2225
fastcall static void
2226
gen2_emit_composite_spans_primitive_affine_source(struct sna *sna,
2227
const struct sna_composite_spans_op *op,
2231
PictTransform *transform = op->base.src.transform;
2232
uint32_t alpha = (uint8_t)(255 * opacity) << 24;
2235
v = (float *)sna->kgem.batch + sna->kgem.nbatch;
2236
sna->kgem.nbatch += 15;
2238
v[0] = op->base.dst.x + box->x2;
2239
v[6] = v[1] = op->base.dst.y + box->y2;
2240
v[10] = v[5] = op->base.dst.x + box->x1;
2241
v[11] = op->base.dst.y + box->y1;
2242
*((uint32_t *)v + 2) = alpha;
2243
*((uint32_t *)v + 7) = alpha;
2244
*((uint32_t *)v + 12) = alpha;
2246
_sna_get_transformed_scaled((int)op->base.src.offset[0] + box->x2,
2247
(int)op->base.src.offset[1] + box->y2,
2248
transform, op->base.src.scale,
2251
_sna_get_transformed_scaled((int)op->base.src.offset[0] + box->x1,
2252
(int)op->base.src.offset[1] + box->y2,
2253
transform, op->base.src.scale,
2256
_sna_get_transformed_scaled((int)op->base.src.offset[0] + box->x1,
2257
(int)op->base.src.offset[1] + box->y1,
2258
transform, op->base.src.scale,
2262
#if defined(sse2) && !defined(__x86_64__)
2263
sse2 fastcall static void
2264
gen2_emit_composite_spans_primitive_constant__sse2(struct sna *sna,
2265
const struct sna_composite_spans_op *op,
2269
float *v = (float *)sna->kgem.batch + sna->kgem.nbatch;
2270
uint32_t alpha = (uint8_t)(255 * opacity) << 24;
2271
sna->kgem.nbatch += 9;
2273
v[0] = op->base.dst.x + box->x2;
2274
v[1] = op->base.dst.y + box->y2;
2275
*((uint32_t *)v + 2) = alpha;
2277
v[3] = op->base.dst.x + box->x1;
2279
*((uint32_t *)v + 5) = alpha;
2282
v[7] = op->base.dst.y + box->y1;
2283
*((uint32_t *)v + 8) = alpha;
2286
sse2 fastcall static void
2287
gen2_emit_composite_spans_primitive_linear__sse2(struct sna *sna,
2288
const struct sna_composite_spans_op *op,
2297
alpha.u = (uint8_t)(255 * opacity) << 24;
2299
gen2_emit_composite_dstcoord(sna,
2300
op->base.dst.x + box->x2,
2301
op->base.dst.y + box->y2);
2303
gen2_emit_composite_linear(sna, &op->base.src, box->x2, box->y2);
2305
gen2_emit_composite_dstcoord(sna,
2306
op->base.dst.x + box->x1,
2307
op->base.dst.y + box->y2);
2309
gen2_emit_composite_linear(sna, &op->base.src, box->x1, box->y2);
2311
gen2_emit_composite_dstcoord(sna,
2312
op->base.dst.x + box->x1,
2313
op->base.dst.y + box->y1);
2315
gen2_emit_composite_linear(sna, &op->base.src, box->x1, box->y1);
2318
sse2 fastcall static void
2319
gen2_emit_composite_spans_primitive_identity_source__sse2(struct sna *sna,
2320
const struct sna_composite_spans_op *op,
2324
float *v = (float *)sna->kgem.batch + sna->kgem.nbatch;
2325
uint32_t alpha = (uint8_t)(255 * opacity) << 24;
2326
sna->kgem.nbatch += 15;
2328
v[0] = op->base.dst.x + box->x2;
2329
v[1] = op->base.dst.y + box->y2;
2330
*((uint32_t *)v + 2) = alpha;
2331
v[3] = (op->base.src.offset[0] + box->x2) * op->base.src.scale[0];
2332
v[4] = (op->base.src.offset[1] + box->y2) * op->base.src.scale[1];
2334
v[5] = op->base.dst.x + box->x1;
2336
*((uint32_t *)v + 7) = alpha;
2337
v[8] = (op->base.src.offset[0] + box->x1) * op->base.src.scale[0];
2341
v[11] = op->base.dst.y + box->y1;
2342
*((uint32_t *)v + 12) = alpha;
2344
v[14] = (op->base.src.offset[1] + box->y1) * op->base.src.scale[1];
2347
sse2 fastcall static void
2348
gen2_emit_composite_spans_primitive_affine_source__sse2(struct sna *sna,
2349
const struct sna_composite_spans_op *op,
2353
PictTransform *transform = op->base.src.transform;
2354
uint32_t alpha = (uint8_t)(255 * opacity) << 24;
2357
v = (float *)sna->kgem.batch + sna->kgem.nbatch;
2358
sna->kgem.nbatch += 15;
2360
v[0] = op->base.dst.x + box->x2;
2361
v[6] = v[1] = op->base.dst.y + box->y2;
2362
v[10] = v[5] = op->base.dst.x + box->x1;
2363
v[11] = op->base.dst.y + box->y1;
2364
*((uint32_t *)v + 2) = alpha;
2365
*((uint32_t *)v + 7) = alpha;
2366
*((uint32_t *)v + 12) = alpha;
2368
_sna_get_transformed_scaled((int)op->base.src.offset[0] + box->x2,
2369
(int)op->base.src.offset[1] + box->y2,
2370
transform, op->base.src.scale,
2373
_sna_get_transformed_scaled((int)op->base.src.offset[0] + box->x1,
2374
(int)op->base.src.offset[1] + box->y2,
2375
transform, op->base.src.scale,
2378
_sna_get_transformed_scaled((int)op->base.src.offset[0] + box->x1,
2379
(int)op->base.src.offset[1] + box->y1,
2380
transform, op->base.src.scale,
2386
gen2_emit_composite_spans_vertex(struct sna *sna,
2387
const struct sna_composite_spans_op *op,
2388
int16_t x, int16_t y,
2391
gen2_emit_composite_dstcoord(sna, x + op->base.dst.x, y + op->base.dst.y);
2392
BATCH((uint8_t)(opacity * 255) << 24);
2393
assert(!op->base.src.is_solid);
2394
if (op->base.src.is_linear)
2395
gen2_emit_composite_linear(sna, &op->base.src, x, y);
2397
gen2_emit_composite_texcoord(sna, &op->base.src, x, y);
2400
fastcall static void
2401
gen2_emit_composite_spans_primitive(struct sna *sna,
2402
const struct sna_composite_spans_op *op,
2406
gen2_emit_composite_spans_vertex(sna, op, box->x2, box->y2, opacity);
2407
gen2_emit_composite_spans_vertex(sna, op, box->x1, box->y2, opacity);
2408
gen2_emit_composite_spans_vertex(sna, op, box->x1, box->y1, opacity);
2412
gen2_emit_spans_pipeline(struct sna *sna,
2413
const struct sna_composite_spans_op *op)
2415
uint32_t cblend, ablend;
2419
TB0C_LAST_STAGE | TB0C_RESULT_SCALE_1X | TB0C_OP_MODULATE |
2420
TB0C_ARG1_SEL_DIFFUSE | TB0C_ARG1_REPLICATE_ALPHA |
2421
TB0C_OUTPUT_WRITE_CURRENT;
2423
TB0A_RESULT_SCALE_1X | TB0A_OP_MODULATE |
2424
TB0A_ARG1_SEL_DIFFUSE |
2425
TB0A_OUTPUT_WRITE_CURRENT;
2427
if (op->base.src.is_solid) {
2428
ablend |= TB0A_ARG2_SEL_SPECULAR;
2429
cblend |= TB0C_ARG2_SEL_SPECULAR;
2430
if (op->base.dst.format == PICT_a8)
2431
cblend |= TB0C_ARG2_REPLICATE_ALPHA;
2432
} else if (op->base.dst.format == PICT_a8) {
2433
ablend |= TB0A_ARG2_SEL_TEXEL0;
2434
cblend |= TB0C_ARG2_SEL_TEXEL0 | TB0C_ARG2_REPLICATE_ALPHA;
2436
if (PICT_FORMAT_RGB(op->base.src.pict_format) != 0)
2437
cblend |= TB0C_ARG2_SEL_TEXEL0;
2439
cblend |= TB0C_ARG2_SEL_ONE | TB0C_ARG2_INVERT;
2441
if (op->base.src.is_opaque)
2442
ablend |= TB0A_ARG2_SEL_ONE;
2444
ablend |= TB0A_ARG2_SEL_TEXEL0;
2447
unwind = sna->kgem.nbatch;
2448
BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_2 |
2449
LOAD_TEXTURE_BLEND_STAGE(0) | 1);
2452
if (memcmp(sna->kgem.batch + sna->render_state.gen2.ls2 + 1,
2453
sna->kgem.batch + unwind + 1,
2454
2 * sizeof(uint32_t)) == 0)
2455
sna->kgem.nbatch = unwind;
2457
sna->render_state.gen2.ls2 = unwind;
2460
static void gen2_emit_composite_spans_state(struct sna *sna,
2461
const struct sna_composite_spans_op *op)
2465
gen2_get_batch(sna, &op->base);
2466
gen2_emit_target(sna,
2469
op->base.dst.height,
2470
op->base.dst.format);
2472
unwind = sna->kgem.nbatch;
2473
BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 |
2474
I1_LOAD_S(2) | I1_LOAD_S(3) | I1_LOAD_S(8) | 2);
2475
BATCH(!op->base.src.is_solid << 12);
2476
BATCH(S3_CULLMODE_NONE | S3_VERTEXHAS_XY | S3_DIFFUSE_PRESENT);
2477
BATCH(gen2_get_blend_cntl(op->base.op, false, op->base.dst.format));
2478
if (memcmp(sna->kgem.batch + sna->render_state.gen2.ls1 + 1,
2479
sna->kgem.batch + unwind + 1,
2480
3 * sizeof(uint32_t)) == 0)
2481
sna->kgem.nbatch = unwind;
2483
sna->render_state.gen2.ls1 = unwind;
2485
gen2_disable_logic_op(sna);
2486
gen2_emit_spans_pipeline(sna, op);
2488
if (op->base.src.is_solid) {
2489
if (op->base.src.u.gen2.pixel != sna->render_state.gen2.specular) {
2490
BATCH(_3DSTATE_DFLT_SPECULAR_CMD);
2491
BATCH(op->base.src.u.gen2.pixel);
2492
sna->render_state.gen2.specular = op->base.src.u.gen2.pixel;
2495
uint32_t v =_3DSTATE_VERTEX_FORMAT_2_CMD |
2496
(op->base.src.is_affine ? TEXCOORDFMT_2D : TEXCOORDFMT_3D);
2497
if (sna->render_state.gen2.vft != v) {
2499
sna->render_state.gen2.vft = v;
2501
gen2_emit_texture(sna, &op->base.src, 0);
2505
fastcall static void
2506
gen2_render_composite_spans_box(struct sna *sna,
2507
const struct sna_composite_spans_op *op,
2508
const BoxRec *box, float opacity)
2510
DBG(("%s: src=+(%d, %d), opacity=%f, dst=+(%d, %d), box=(%d, %d) x (%d, %d)\n",
2512
op->base.src.offset[0], op->base.src.offset[1],
2514
op->base.dst.x, op->base.dst.y,
2517
box->y2 - box->y1));
2519
if (gen2_get_rectangles(sna, &op->base, 1) == 0) {
2520
gen2_emit_composite_spans_state(sna, op);
2521
gen2_get_rectangles(sna, &op->base, 1);
2524
op->prim_emit(sna, op, box, opacity);
2528
gen2_render_composite_spans_boxes(struct sna *sna,
2529
const struct sna_composite_spans_op *op,
2530
const BoxRec *box, int nbox,
2533
DBG(("%s: nbox=%d, src=+(%d, %d), opacity=%f, dst=+(%d, %d)\n",
2535
op->base.src.offset[0], op->base.src.offset[1],
2537
op->base.dst.x, op->base.dst.y));
2542
nbox_this_time = gen2_get_rectangles(sna, &op->base, nbox);
2543
if (nbox_this_time == 0) {
2544
gen2_emit_composite_spans_state(sna, op);
2545
nbox_this_time = gen2_get_rectangles(sna, &op->base, nbox);
2547
nbox -= nbox_this_time;
2550
DBG((" %s: (%d, %d) x (%d, %d)\n", __FUNCTION__,
2553
box->y2 - box->y1));
2555
op->prim_emit(sna, op, box++, opacity);
2556
} while (--nbox_this_time);
2560
fastcall static void
2561
gen2_render_composite_spans_done(struct sna *sna,
2562
const struct sna_composite_spans_op *op)
2564
DBG(("%s()\n", __FUNCTION__));
2566
gen2_vertex_flush(sna, &op->base);
2568
if (op->base.src.bo)
2569
kgem_bo_destroy(&sna->kgem, op->base.src.bo);
2571
sna_render_composite_redirect_done(sna, &op->base);
2575
gen2_check_composite_spans(struct sna *sna,
2576
uint8_t op, PicturePtr src, PicturePtr dst,
2577
int16_t width, int16_t height, unsigned flags)
2579
if (op >= ARRAY_SIZE(gen2_blend_op))
2582
if (gen2_composite_fallback(sna, src, NULL, dst))
2585
if (need_tiling(sna, width, height)) {
2586
if (!is_gpu(sna, dst->pDrawable, PREFER_GPU_SPANS)) {
2587
DBG(("%s: fallback, tiled operation not on GPU\n",
2597
gen2_render_composite_spans(struct sna *sna,
2601
int16_t src_x, int16_t src_y,
2602
int16_t dst_x, int16_t dst_y,
2603
int16_t width, int16_t height,
2605
struct sna_composite_spans_op *tmp)
2607
DBG(("%s(src=(%d, %d), dst=(%d, %d), size=(%d, %d))\n", __FUNCTION__,
2608
src_x, src_y, dst_x, dst_y, width, height));
2610
assert(gen2_check_composite_spans(sna, op, src, dst, width, height, flags));
2611
if (need_tiling(sna, width, height)) {
2612
DBG(("%s: tiling, operation (%dx%d) too wide for pipeline\n",
2613
__FUNCTION__, width, height));
2614
return sna_tiling_composite_spans(op, src, dst,
2615
src_x, src_y, dst_x, dst_y,
2616
width, height, flags, tmp);
2620
sna_render_composite_redirect_init(&tmp->base);
2621
if (!gen2_composite_set_target(sna, &tmp->base, dst,
2622
dst_x, dst_y, width, height,
2624
DBG(("%s: unable to set render target\n",
2629
switch (gen2_composite_picture(sna, src, &tmp->base.src,
2633
dst->polyMode == PolyModePrecise)) {
2637
gen2_composite_solid_init(sna, &tmp->base.src, 0);
2641
assert(tmp->base.src.bo || tmp->base.src.is_solid);
2643
tmp->prim_emit = gen2_emit_composite_spans_primitive;
2644
tmp->base.floats_per_vertex = 3;
2645
if (tmp->base.src.is_solid) {
2646
#if defined(sse2) && !defined(__x86_64__)
2647
if (sna->cpu_features & SSE2) {
2648
tmp->prim_emit = gen2_emit_composite_spans_primitive_constant__sse2;
2652
tmp->prim_emit = gen2_emit_composite_spans_primitive_constant;
2654
} else if (tmp->base.src.is_linear) {
2655
tmp->base.floats_per_vertex += 2;
2656
#if defined(sse2) && !defined(__x86_64__)
2657
if (sna->cpu_features & SSE2) {
2658
tmp->prim_emit = gen2_emit_composite_spans_primitive_linear__sse2;
2662
tmp->prim_emit = gen2_emit_composite_spans_primitive_linear;
2665
assert(tmp->base.src.bo);
2666
tmp->base.floats_per_vertex += tmp->base.src.is_affine ? 2 : 3;
2667
if (tmp->base.src.transform == NULL) {
2668
#if defined(sse2) && !defined(__x86_64__)
2669
if (sna->cpu_features & SSE2) {
2670
tmp->prim_emit = gen2_emit_composite_spans_primitive_identity_source__sse2;
2674
tmp->prim_emit = gen2_emit_composite_spans_primitive_identity_source;
2676
} else if (tmp->base.src.is_affine) {
2677
tmp->base.src.scale[0] /= tmp->base.src.transform->matrix[2][2];
2678
tmp->base.src.scale[1] /= tmp->base.src.transform->matrix[2][2];
2679
#if defined(sse2) && !defined(__x86_64__)
2680
if (sna->cpu_features & SSE2) {
2681
tmp->prim_emit = gen2_emit_composite_spans_primitive_affine_source__sse2;
2685
tmp->prim_emit = gen2_emit_composite_spans_primitive_affine_source;
2689
tmp->base.mask.bo = NULL;
2690
tmp->base.floats_per_rect = 3*tmp->base.floats_per_vertex;
2692
tmp->box = gen2_render_composite_spans_box;
2693
tmp->boxes = gen2_render_composite_spans_boxes;
2694
tmp->done = gen2_render_composite_spans_done;
2696
if (!kgem_check_bo(&sna->kgem,
2697
tmp->base.dst.bo, tmp->base.src.bo,
2699
kgem_submit(&sna->kgem);
2700
if (!kgem_check_bo(&sna->kgem,
2701
tmp->base.dst.bo, tmp->base.src.bo,
2706
gen2_emit_composite_spans_state(sna, tmp);
2710
if (tmp->base.src.bo)
2711
kgem_bo_destroy(&sna->kgem, tmp->base.src.bo);
2713
if (tmp->base.redirect.real_bo)
2714
kgem_bo_destroy(&sna->kgem, tmp->base.dst.bo);
2719
gen2_emit_fill_pipeline(struct sna *sna, const struct sna_composite_op *op)
2721
uint32_t blend, unwind;
2723
unwind = sna->kgem.nbatch;
2724
BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_2 |
2725
LOAD_TEXTURE_BLEND_STAGE(0) | 1);
2727
blend = TB0C_LAST_STAGE | TB0C_RESULT_SCALE_1X | TB0C_OP_ARG1 |
2728
TB0C_ARG1_SEL_DIFFUSE |
2729
TB0C_OUTPUT_WRITE_CURRENT;
2730
if (op->dst.format == PICT_a8)
2731
blend |= TB0C_ARG1_REPLICATE_ALPHA;
2734
BATCH(TB0A_RESULT_SCALE_1X | TB0A_OP_ARG1 |
2735
TB0A_ARG1_SEL_DIFFUSE |
2736
TB0A_OUTPUT_WRITE_CURRENT);
2738
if (memcmp(sna->kgem.batch + sna->render_state.gen2.ls2 + 1,
2739
sna->kgem.batch + unwind + 1,
2740
2 * sizeof(uint32_t)) == 0)
2741
sna->kgem.nbatch = unwind;
2743
sna->render_state.gen2.ls2 = unwind;
2746
static void gen2_emit_fill_composite_state(struct sna *sna,
2747
const struct sna_composite_op *op,
2752
gen2_get_batch(sna, op);
2753
gen2_emit_target(sna,
2759
ls1 = sna->kgem.nbatch;
2760
BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 |
2761
I1_LOAD_S(2) | I1_LOAD_S(3) | I1_LOAD_S(8) | 2);
2763
BATCH(S3_CULLMODE_NONE | S3_VERTEXHAS_XY);
2764
BATCH(gen2_get_blend_cntl(op->op, false, op->dst.format));
2765
if (memcmp(sna->kgem.batch + sna->render_state.gen2.ls1 + 1,
2766
sna->kgem.batch + ls1 + 1,
2767
3 * sizeof(uint32_t)) == 0)
2768
sna->kgem.nbatch = ls1;
2770
sna->render_state.gen2.ls1 = ls1;
2772
gen2_emit_fill_pipeline(sna, op);
2774
if (pixel != sna->render_state.gen2.diffuse) {
2775
BATCH(_3DSTATE_DFLT_DIFFUSE_CMD);
2777
sna->render_state.gen2.diffuse = pixel;
2782
gen2_render_fill_boxes_try_blt(struct sna *sna,
2783
CARD8 op, PictFormat format,
2784
const xRenderColor *color,
2785
const DrawableRec *dst, struct kgem_bo *dst_bo,
2786
const BoxRec *box, int n)
2794
if (op == PictOpClear) {
2797
} else if (!sna_get_pixel_from_rgba(&pixel,
2807
return sna_blt_fill_boxes(sna, alu,
2808
dst_bo, dst->bitsPerPixel,
2813
gen2_render_fill_boxes(struct sna *sna,
2816
const xRenderColor *color,
2817
const DrawableRec *dst, struct kgem_bo *dst_bo,
2818
const BoxRec *box, int n)
2820
struct sna_composite_op tmp;
2823
if (op >= ARRAY_SIZE(gen2_blend_op)) {
2824
DBG(("%s: fallback due to unhandled blend op: %d\n",
2830
return gen2_render_fill_boxes_try_blt(sna, op, format, color,
2834
if (gen2_render_fill_boxes_try_blt(sna, op, format, color,
2840
DBG(("%s (op=%d, format=%x, color=(%04x,%04x,%04x, %04x))\n",
2841
__FUNCTION__, op, (int)format,
2842
color->red, color->green, color->blue, color->alpha));
2844
if (too_large(dst->width, dst->height) ||
2845
dst_bo->pitch < 8 || dst_bo->pitch > MAX_3D_PITCH ||
2846
!gen2_check_dst_format(format)) {
2847
DBG(("%s: try blt, too large or incompatible destination\n",
2849
if (!gen2_check_dst_format(format))
2852
assert(dst_bo->pitch >= 8);
2853
return sna_tiling_fill_boxes(sna, op, format, color,
2854
dst, dst_bo, box, n);
2857
if (op == PictOpClear)
2859
else if (!sna_get_pixel_from_rgba(&pixel,
2867
DBG(("%s: using shader for op=%d, format=%x, pixel=%x\n",
2868
__FUNCTION__, op, (int)format, pixel));
2870
memset(&tmp, 0, sizeof(tmp));
2872
tmp.dst.pixmap = (PixmapPtr)dst;
2873
tmp.dst.width = dst->width;
2874
tmp.dst.height = dst->height;
2875
tmp.dst.format = format;
2876
tmp.dst.bo = dst_bo;
2877
tmp.floats_per_vertex = 2;
2878
tmp.floats_per_rect = 6;
2880
if (!kgem_check_bo(&sna->kgem, dst_bo, NULL)) {
2881
kgem_submit(&sna->kgem);
2882
if (!kgem_check_bo(&sna->kgem, dst_bo, NULL))
2886
gen2_emit_fill_composite_state(sna, &tmp, pixel);
2889
int n_this_time = gen2_get_rectangles(sna, &tmp, n);
2890
if (n_this_time == 0) {
2891
gen2_emit_fill_composite_state(sna, &tmp, pixel);
2892
n_this_time = gen2_get_rectangles(sna, &tmp, n);
2897
DBG((" (%d, %d), (%d, %d): %x\n",
2898
box->x1, box->y1, box->x2, box->y2, pixel));
2906
} while (--n_this_time);
2909
gen2_vertex_flush(sna, &tmp);
2913
static void gen2_emit_fill_state(struct sna *sna,
2914
const struct sna_composite_op *op)
2918
gen2_get_batch(sna, op);
2919
gen2_emit_target(sna,
2925
ls1 = sna->kgem.nbatch;
2926
BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 |
2927
I1_LOAD_S(2) | I1_LOAD_S(3) | I1_LOAD_S(8) | 2);
2929
BATCH(S3_CULLMODE_NONE | S3_VERTEXHAS_XY);
2930
BATCH(S8_ENABLE_COLOR_BUFFER_WRITE);
2931
if (memcmp(sna->kgem.batch + sna->render_state.gen2.ls1 + 1,
2932
sna->kgem.batch + ls1 + 1,
2933
3 * sizeof(uint32_t)) == 0)
2934
sna->kgem.nbatch = ls1;
2936
sna->render_state.gen2.ls1 = ls1;
2938
gen2_enable_logic_op(sna, op->op);
2939
gen2_emit_fill_pipeline(sna, op);
2941
if (op->src.u.gen2.pixel != sna->render_state.gen2.diffuse) {
2942
BATCH(_3DSTATE_DFLT_DIFFUSE_CMD);
2943
BATCH(op->src.u.gen2.pixel);
2944
sna->render_state.gen2.diffuse = op->src.u.gen2.pixel;
2949
gen2_render_fill_op_blt(struct sna *sna,
2950
const struct sna_fill_op *op,
2951
int16_t x, int16_t y, int16_t w, int16_t h)
2953
if (!gen2_get_rectangles(sna, &op->base, 1)) {
2954
gen2_emit_fill_state(sna, &op->base);
2955
gen2_get_rectangles(sna, &op->base, 1);
2966
fastcall static void
2967
gen2_render_fill_op_box(struct sna *sna,
2968
const struct sna_fill_op *op,
2971
if (!gen2_get_rectangles(sna, &op->base, 1)) {
2972
gen2_emit_fill_state(sna, &op->base);
2973
gen2_get_rectangles(sna, &op->base, 1);
2984
fastcall static void
2985
gen2_render_fill_op_boxes(struct sna *sna,
2986
const struct sna_fill_op *op,
2990
DBG(("%s: (%d, %d),(%d, %d)... x %d\n", __FUNCTION__,
2991
box->x1, box->y1, box->x2, box->y2, nbox));
2994
int nbox_this_time = gen2_get_rectangles(sna, &op->base, nbox);
2995
if (nbox_this_time == 0) {
2996
gen2_emit_fill_state(sna, &op->base);
2997
nbox_this_time = gen2_get_rectangles(sna, &op->base, nbox);
2999
nbox -= nbox_this_time;
3009
} while (--nbox_this_time);
3014
gen2_render_fill_op_done(struct sna *sna, const struct sna_fill_op *op)
3016
gen2_vertex_flush(sna, &op->base);
3020
gen2_render_fill(struct sna *sna, uint8_t alu,
3021
PixmapPtr dst, struct kgem_bo *dst_bo,
3022
uint32_t color, unsigned flags,
3023
struct sna_fill_op *tmp)
3026
return sna_blt_fill(sna, alu,
3027
dst_bo, dst->drawable.bitsPerPixel,
3032
/* Prefer to use the BLT if already engaged */
3033
if (sna_blt_fill(sna, alu,
3034
dst_bo, dst->drawable.bitsPerPixel,
3039
/* Must use the BLT if we can't RENDER... */
3040
if (too_large(dst->drawable.width, dst->drawable.height) ||
3041
dst_bo->pitch < 8 || dst_bo->pitch > MAX_3D_PITCH)
3045
tmp->base.dst.pixmap = dst;
3046
tmp->base.dst.width = dst->drawable.width;
3047
tmp->base.dst.height = dst->drawable.height;
3048
tmp->base.dst.format = sna_format_for_depth(dst->drawable.depth);
3049
tmp->base.dst.bo = dst_bo;
3050
tmp->base.dst.x = tmp->base.dst.y = 0;
3051
tmp->base.floats_per_vertex = 2;
3052
tmp->base.floats_per_rect = 6;
3054
tmp->base.src.u.gen2.pixel =
3055
sna_rgba_for_color(color, dst->drawable.depth);
3057
if (!kgem_check_bo(&sna->kgem, dst_bo, NULL)) {
3058
kgem_submit(&sna->kgem);
3059
return sna_blt_fill(sna, alu,
3060
dst_bo, dst->drawable.bitsPerPixel,
3065
tmp->blt = gen2_render_fill_op_blt;
3066
tmp->box = gen2_render_fill_op_box;
3067
tmp->boxes = gen2_render_fill_op_boxes;
3069
tmp->done = gen2_render_fill_op_done;
3071
gen2_emit_fill_state(sna, &tmp->base);
3076
gen2_render_fill_one_try_blt(struct sna *sna, PixmapPtr dst, struct kgem_bo *bo,
3078
int16_t x1, int16_t y1, int16_t x2, int16_t y2,
3088
return sna_blt_fill_boxes(sna, alu,
3089
bo, dst->drawable.bitsPerPixel,
3094
gen2_render_fill_one(struct sna *sna, PixmapPtr dst, struct kgem_bo *bo,
3096
int16_t x1, int16_t y1,
3097
int16_t x2, int16_t y2,
3100
struct sna_composite_op tmp;
3103
return gen2_render_fill_one_try_blt(sna, dst, bo, color,
3104
x1, y1, x2, y2, alu);
3107
/* Prefer to use the BLT if already engaged */
3108
if (gen2_render_fill_one_try_blt(sna, dst, bo, color,
3109
x1, y1, x2, y2, alu))
3112
/* Must use the BLT if we can't RENDER... */
3113
if (too_large(dst->drawable.width, dst->drawable.height) ||
3114
bo->pitch < 8 || bo->pitch > MAX_3D_PITCH)
3117
if (!kgem_check_bo(&sna->kgem, bo, NULL)) {
3118
kgem_submit(&sna->kgem);
3120
if (gen2_render_fill_one_try_blt(sna, dst, bo, color,
3121
x1, y1, x2, y2, alu))
3124
if (!kgem_check_bo(&sna->kgem, bo, NULL))
3129
tmp.dst.pixmap = dst;
3130
tmp.dst.width = dst->drawable.width;
3131
tmp.dst.height = dst->drawable.height;
3132
tmp.dst.format = sna_format_for_depth(dst->drawable.depth);
3134
tmp.floats_per_vertex = 2;
3135
tmp.floats_per_rect = 6;
3136
tmp.need_magic_ca_pass = false;
3138
tmp.src.u.gen2.pixel =
3139
sna_rgba_for_color(color, dst->drawable.depth);
3141
gen2_emit_fill_state(sna, &tmp);
3142
gen2_get_rectangles(sna, &tmp, 1);
3143
DBG(("%s: (%d, %d), (%d, %d): %x\n", __FUNCTION__,
3144
x1, y1, x2, y2, tmp.src.u.gen2.pixel));
3151
gen2_vertex_flush(sna, &tmp);
3157
gen2_emit_video_state(struct sna *sna,
3158
struct sna_video *video,
3159
struct sna_video_frame *frame,
3161
struct kgem_bo *dst_bo,
3162
int width, int height,
3165
uint32_t ms1, v, unwind;
3167
gen2_emit_target(sna, dst_bo, width, height,
3168
sna_format_for_depth(pixmap->drawable.depth));
3170
unwind = sna->kgem.nbatch;
3171
BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 |
3172
I1_LOAD_S(2) | I1_LOAD_S(3) | I1_LOAD_S(8) | 2);
3174
BATCH(S3_CULLMODE_NONE | S3_VERTEXHAS_XY);
3175
BATCH(S8_ENABLE_COLOR_BUFFER_WRITE);
3176
if (memcmp(sna->kgem.batch + sna->render_state.gen2.ls1 + 1,
3177
sna->kgem.batch + unwind + 1,
3178
3 * sizeof(uint32_t)) == 0)
3179
sna->kgem.nbatch = unwind;
3181
sna->render_state.gen2.ls1 = unwind;
3183
gen2_disable_logic_op(sna);
3185
unwind = sna->kgem.nbatch;
3186
BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_2 |
3187
LOAD_TEXTURE_BLEND_STAGE(0) | 1);
3188
BATCH(TB0C_LAST_STAGE | TB0C_RESULT_SCALE_1X | TB0C_OUTPUT_WRITE_CURRENT |
3189
TB0C_OP_ARG1 | TB0C_ARG1_SEL_TEXEL0);
3190
BATCH(TB0A_RESULT_SCALE_1X | TB0A_OUTPUT_WRITE_CURRENT |
3191
TB0A_OP_ARG1 | TB0A_ARG1_SEL_ONE);
3192
if (memcmp(sna->kgem.batch + sna->render_state.gen2.ls2 + 1,
3193
sna->kgem.batch + unwind + 1,
3194
2 * sizeof(uint32_t)) == 0)
3195
sna->kgem.nbatch = unwind;
3197
sna->render_state.gen2.ls2 = unwind;
3199
BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_2 | LOAD_TEXTURE_MAP(0) | 4);
3200
BATCH(kgem_add_reloc(&sna->kgem, sna->kgem.nbatch,
3202
I915_GEM_DOMAIN_SAMPLER << 16,
3204
ms1 = MAPSURF_422 | TM0S1_COLORSPACE_CONVERSION;
3205
switch (frame->id) {
3207
ms1 |= MT_422_YCRCB_NORMAL;
3210
ms1 |= MT_422_YCRCB_SWAPY;
3213
BATCH(((frame->height - 1) << TM0S1_HEIGHT_SHIFT) |
3214
((frame->width - 1) << TM0S1_WIDTH_SHIFT) |
3216
gen2_sampler_tiling_bits(frame->bo->tiling));
3217
BATCH((frame->pitch[0] / 4 - 1) << TM0S2_PITCH_SHIFT | TM0S2_MAP_2D);
3219
BATCH(FILTER_LINEAR << TM0S3_MAG_FILTER_SHIFT |
3220
FILTER_LINEAR << TM0S3_MIN_FILTER_SHIFT |
3221
MIPFILTER_NONE << TM0S3_MIP_FILTER_SHIFT);
3223
BATCH(FILTER_NEAREST << TM0S3_MAG_FILTER_SHIFT |
3224
FILTER_NEAREST << TM0S3_MIN_FILTER_SHIFT |
3225
MIPFILTER_NONE << TM0S3_MIP_FILTER_SHIFT);
3226
BATCH(0); /* default color */
3228
BATCH(_3DSTATE_MAP_COORD_SET_CMD | TEXCOORD_SET(0) |
3229
ENABLE_TEXCOORD_PARAMS | TEXCOORDS_ARE_NORMAL | TEXCOORDTYPE_CARTESIAN |
3230
ENABLE_ADDR_V_CNTL | TEXCOORD_ADDR_V_MODE(TEXCOORDMODE_CLAMP) |
3231
ENABLE_ADDR_U_CNTL | TEXCOORD_ADDR_U_MODE(TEXCOORDMODE_CLAMP));
3233
v = _3DSTATE_VERTEX_FORMAT_2_CMD | TEXCOORDFMT_2D;
3234
if (sna->render_state.gen2.vft != v) {
3236
sna->render_state.gen2.vft = v;
3241
gen2_video_get_batch(struct sna *sna, struct kgem_bo *bo)
3243
kgem_set_mode(&sna->kgem, KGEM_RENDER, bo);
3245
if (!kgem_check_batch(&sna->kgem, 120) ||
3246
!kgem_check_reloc(&sna->kgem, 4) ||
3247
!kgem_check_exec(&sna->kgem, 2)) {
3248
_kgem_submit(&sna->kgem);
3249
_kgem_set_mode(&sna->kgem, KGEM_RENDER);
3252
if (sna->render_state.gen2.need_invariant)
3253
gen2_emit_invariant(sna);
3257
gen2_get_inline_rectangles(struct sna *sna, int want, int floats_per_vertex)
3259
int size = floats_per_vertex * 3;
3260
int rem = batch_space(sna) - 1;
3262
if (rem > MAX_INLINE)
3265
if (size * want > rem)
3272
gen2_render_video(struct sna *sna,
3273
struct sna_video *video,
3274
struct sna_video_frame *frame,
3275
RegionPtr dstRegion,
3278
struct sna_pixmap *priv = sna_pixmap(pixmap);
3279
const BoxRec *pbox = region_rects(dstRegion);
3280
int nbox = region_num_rects(dstRegion);
3281
int dst_width = dstRegion->extents.x2 - dstRegion->extents.x1;
3282
int dst_height = dstRegion->extents.y2 - dstRegion->extents.y1;
3283
int src_width = frame->src.x2 - frame->src.x1;
3284
int src_height = frame->src.y2 - frame->src.y1;
3285
float src_offset_x, src_offset_y;
3286
float src_scale_x, src_scale_y;
3287
int pix_xoff, pix_yoff;
3288
struct kgem_bo *dst_bo;
3292
DBG(("%s: src:%dx%d (frame:%dx%d) -> dst:%dx%d\n", __FUNCTION__,
3293
src_width, src_height, frame->width, frame->height, dst_width, dst_height));
3295
assert(priv->gpu_bo);
3296
dst_bo = priv->gpu_bo;
3298
bilinear = src_width != dst_width || src_height != dst_height;
3300
src_scale_x = (float)src_width / dst_width / frame->width;
3301
src_offset_x = (float)frame->src.x1 / frame->width - dstRegion->extents.x1 * src_scale_x;
3303
src_scale_y = (float)src_height / dst_height / frame->height;
3304
src_offset_y = (float)frame->src.y1 / frame->height - dstRegion->extents.y1 * src_scale_y;
3305
DBG(("%s: src offset (%f, %f), scale (%f, %f)\n",
3306
__FUNCTION__, src_offset_x, src_offset_y, src_scale_x, src_scale_y));
3308
if (too_large(pixmap->drawable.width, pixmap->drawable.height) ||
3309
dst_bo->pitch > MAX_3D_PITCH) {
3310
int bpp = pixmap->drawable.bitsPerPixel;
3312
if (too_large(dst_width, dst_height))
3315
dst_bo = kgem_create_2d(&sna->kgem,
3316
dst_width, dst_height, bpp,
3317
kgem_choose_tiling(&sna->kgem,
3319
dst_width, dst_height, bpp),
3324
pix_xoff = -dstRegion->extents.x1;
3325
pix_yoff = -dstRegion->extents.y1;
3328
/* Set up the offset for translating from the given region
3329
* (in screen coordinates) to the backing pixmap.
3332
pix_xoff = -pixmap->screen_x + pixmap->drawable.x;
3333
pix_yoff = -pixmap->screen_y + pixmap->drawable.y;
3339
dst_width = pixmap->drawable.width;
3340
dst_height = pixmap->drawable.height;
3343
gen2_video_get_batch(sna, dst_bo);
3344
gen2_emit_video_state(sna, video, frame, pixmap,
3345
dst_bo, dst_width, dst_height, bilinear);
3347
int nbox_this_time = gen2_get_inline_rectangles(sna, nbox, 4);
3348
if (nbox_this_time == 0) {
3349
gen2_video_get_batch(sna, dst_bo);
3350
gen2_emit_video_state(sna, video, frame, pixmap,
3351
dst_bo, dst_width, dst_height, bilinear);
3352
nbox_this_time = gen2_get_inline_rectangles(sna, nbox, 4);
3353
assert(nbox_this_time);
3355
nbox -= nbox_this_time;
3357
BATCH(PRIM3D_INLINE | PRIM3D_RECTLIST |
3358
((12 * nbox_this_time) - 1));
3360
int box_x1 = pbox->x1;
3361
int box_y1 = pbox->y1;
3362
int box_x2 = pbox->x2;
3363
int box_y2 = pbox->y2;
3367
DBG(("%s: dst (%d, %d), (%d, %d) + (%d, %d); src (%f, %f), (%f, %f)\n",
3368
__FUNCTION__, box_x1, box_y1, box_x2, box_y2, pix_xoff, pix_yoff,
3369
box_x1 * src_scale_x + src_offset_x,
3370
box_y1 * src_scale_y + src_offset_y,
3371
box_x2 * src_scale_x + src_offset_x,
3372
box_y2 * src_scale_y + src_offset_y));
3375
BATCH_F(box_x2 + pix_xoff);
3376
BATCH_F(box_y2 + pix_yoff);
3377
BATCH_F(box_x2 * src_scale_x + src_offset_x);
3378
BATCH_F(box_y2 * src_scale_y + src_offset_y);
3381
BATCH_F(box_x1 + pix_xoff);
3382
BATCH_F(box_y2 + pix_yoff);
3383
BATCH_F(box_x1 * src_scale_x + src_offset_x);
3384
BATCH_F(box_y2 * src_scale_y + src_offset_y);
3387
BATCH_F(box_x1 + pix_xoff);
3388
BATCH_F(box_y1 + pix_yoff);
3389
BATCH_F(box_x1 * src_scale_x + src_offset_x);
3390
BATCH_F(box_y1 * src_scale_y + src_offset_y);
3391
} while (--nbox_this_time);
3396
pix_xoff = -pixmap->screen_x + pixmap->drawable.x;
3397
pix_yoff = -pixmap->screen_y + pixmap->drawable.y;
3402
sna_blt_copy_boxes(sna, GXcopy,
3403
dst_bo, -dstRegion->extents.x1, -dstRegion->extents.y1,
3404
priv->gpu_bo, pix_xoff, pix_yoff,
3405
pixmap->drawable.bitsPerPixel,
3406
region_rects(dstRegion),
3407
region_num_rects(dstRegion));
3409
kgem_bo_destroy(&sna->kgem, dst_bo);
3412
if (!DAMAGE_IS_ALL(priv->gpu_damage)) {
3413
if ((pix_xoff | pix_yoff) == 0) {
3414
sna_damage_add(&priv->gpu_damage, dstRegion);
3416
sna_damage_add_boxes(&priv->gpu_damage,
3417
region_rects(dstRegion),
3418
region_num_rects(dstRegion),
3419
pix_xoff, pix_yoff);
3427
gen2_render_copy_setup_source(struct sna_composite_channel *channel,
3428
const DrawableRec *draw,
3431
assert(draw->width && draw->height);
3433
channel->filter = PictFilterNearest;
3434
channel->repeat = RepeatNone;
3435
channel->width = draw->width;
3436
channel->height = draw->height;
3437
channel->scale[0] = 1.f/draw->width;
3438
channel->scale[1] = 1.f/draw->height;
3439
channel->offset[0] = 0;
3440
channel->offset[1] = 0;
3441
channel->pict_format = sna_format_for_depth(draw->depth);
3443
channel->is_affine = 1;
3445
DBG(("%s: source=%d, (%dx%d), format=%08x\n",
3446
__FUNCTION__, bo->handle,
3447
channel->width, channel->height,
3448
channel->pict_format));
3452
gen2_emit_copy_pipeline(struct sna *sna, const struct sna_composite_op *op)
3454
uint32_t blend, unwind;
3456
unwind = sna->kgem.nbatch;
3457
BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_2 |
3458
LOAD_TEXTURE_BLEND_STAGE(0) | 1);
3460
blend = TB0C_LAST_STAGE | TB0C_RESULT_SCALE_1X | TB0C_OP_ARG1 |
3461
TB0C_OUTPUT_WRITE_CURRENT;
3462
if (op->dst.format == PICT_a8)
3463
blend |= TB0C_ARG1_REPLICATE_ALPHA | TB0C_ARG1_SEL_TEXEL0;
3464
else if (PICT_FORMAT_RGB(op->src.pict_format) != 0)
3465
blend |= TB0C_ARG1_SEL_TEXEL0;
3467
blend |= TB0C_ARG1_SEL_ONE | TB0C_ARG1_INVERT; /* 0.0 */
3470
blend = TB0A_RESULT_SCALE_1X | TB0A_OP_ARG1 |
3471
TB0A_OUTPUT_WRITE_CURRENT;
3472
if (PICT_FORMAT_A(op->src.pict_format) == 0)
3473
blend |= TB0A_ARG1_SEL_ONE;
3475
blend |= TB0A_ARG1_SEL_TEXEL0;
3478
if (memcmp(sna->kgem.batch + sna->render_state.gen2.ls2 + 1,
3479
sna->kgem.batch + unwind + 1,
3480
2 * sizeof(uint32_t)) == 0)
3481
sna->kgem.nbatch = unwind;
3483
sna->render_state.gen2.ls2 = unwind;
3486
static void gen2_emit_copy_state(struct sna *sna, const struct sna_composite_op *op)
3490
gen2_get_batch(sna, op);
3492
if (kgem_bo_is_dirty(op->src.bo)) {
3493
if (op->src.bo == op->dst.bo)
3494
BATCH(MI_FLUSH | MI_INVALIDATE_MAP_CACHE);
3496
BATCH(_3DSTATE_MODES_5_CMD |
3497
PIPELINE_FLUSH_RENDER_CACHE |
3498
PIPELINE_FLUSH_TEXTURE_CACHE);
3499
kgem_clear_dirty(&sna->kgem);
3501
gen2_emit_target(sna,
3507
ls1 = sna->kgem.nbatch;
3508
BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 |
3509
I1_LOAD_S(2) | I1_LOAD_S(3) | I1_LOAD_S(8) | 2);
3511
BATCH(S3_CULLMODE_NONE | S3_VERTEXHAS_XY);
3512
BATCH(S8_ENABLE_COLOR_BUFFER_WRITE);
3513
if (memcmp(sna->kgem.batch + sna->render_state.gen2.ls1 + 1,
3514
sna->kgem.batch + ls1 + 1,
3515
3 * sizeof(uint32_t)) == 0)
3516
sna->kgem.nbatch = ls1;
3518
sna->render_state.gen2.ls1 = ls1;
3520
gen2_enable_logic_op(sna, op->op);
3521
gen2_emit_copy_pipeline(sna, op);
3523
v = _3DSTATE_VERTEX_FORMAT_2_CMD | TEXCOORDFMT_2D;
3524
if (sna->render_state.gen2.vft != v) {
3526
sna->render_state.gen2.vft = v;
3529
gen2_emit_texture(sna, &op->src, 0);
3533
gen2_render_copy_boxes(struct sna *sna, uint8_t alu,
3534
const DrawableRec *src, struct kgem_bo *src_bo, int16_t src_dx, int16_t src_dy,
3535
const DrawableRec *dst, struct kgem_bo *dst_bo, int16_t dst_dx, int16_t dst_dy,
3536
const BoxRec *box, int n, unsigned flags)
3538
struct sna_composite_op tmp;
3541
if (!sna_blt_compare_depth(&src->drawable, &dst->drawable))
3544
return sna_blt_copy_boxes(sna, alu,
3545
src_bo, src_dx, src_dy,
3546
dst_bo, dst_dx, dst_dy,
3547
dst->drawable.bitsPerPixel,
3551
DBG(("%s (%d, %d)->(%d, %d) x %d\n",
3552
__FUNCTION__, src_dx, src_dy, dst_dx, dst_dy, n));
3554
if (sna_blt_compare_depth(src, dst) &&
3555
sna_blt_copy_boxes(sna, alu,
3556
src_bo, src_dx, src_dy,
3557
dst_bo, dst_dx, dst_dy,
3562
if (src_bo == dst_bo || /* XXX handle overlap using 3D ? */
3563
too_large(src->width, src->height) ||
3564
src_bo->pitch > MAX_3D_PITCH || dst_bo->pitch < 8) {
3566
return sna_blt_copy_boxes_fallback(sna, alu,
3567
src, src_bo, src_dx, src_dy,
3568
dst, dst_bo, dst_dx, dst_dy,
3572
if (!kgem_check_bo(&sna->kgem, dst_bo, src_bo, NULL)) {
3573
kgem_submit(&sna->kgem);
3574
if (!kgem_check_bo(&sna->kgem, dst_bo, src_bo, NULL))
3578
assert(dst_bo->pitch >= 8);
3580
memset(&tmp, 0, sizeof(tmp));
3583
tmp.dst.pixmap = (PixmapPtr)dst;
3584
tmp.dst.width = dst->width;
3585
tmp.dst.height = dst->height;
3586
tmp.dst.format = sna_format_for_depth(dst->depth);
3587
tmp.dst.bo = dst_bo;
3588
tmp.dst.x = tmp.dst.y = 0;
3591
DBG(("%s: target=%d, format=%08x, size=%dx%d\n",
3592
__FUNCTION__, dst_bo->handle,
3593
(unsigned)tmp.dst.format,
3597
sna_render_composite_redirect_init(&tmp);
3598
if (too_large(tmp.dst.width, tmp.dst.height) ||
3599
dst_bo->pitch > MAX_3D_PITCH) {
3600
BoxRec extents = box[0];
3603
for (i = 1; i < n; i++) {
3604
if (box[i].x1 < extents.x1)
3605
extents.x1 = box[i].x1;
3606
if (box[i].y1 < extents.y1)
3607
extents.y1 = box[i].y1;
3609
if (box[i].x2 > extents.x2)
3610
extents.x2 = box[i].x2;
3611
if (box[i].y2 > extents.y2)
3612
extents.y2 = box[i].y2;
3614
if (!sna_render_composite_redirect(sna, &tmp,
3615
extents.x1 + dst_dx,
3616
extents.y1 + dst_dy,
3617
extents.x2 - extents.x1,
3618
extents.y2 - extents.y1,
3619
alu != GXcopy || n > 1))
3620
goto fallback_tiled;
3623
tmp.floats_per_vertex = 4;
3624
tmp.floats_per_rect = 12;
3626
dst_dx += tmp.dst.x;
3627
dst_dy += tmp.dst.y;
3628
tmp.dst.x = tmp.dst.y = 0;
3630
gen2_render_copy_setup_source(&tmp.src, src, src_bo);
3631
gen2_emit_copy_state(sna, &tmp);
3635
n_this_time = gen2_get_rectangles(sna, &tmp, n);
3636
if (n_this_time == 0) {
3637
gen2_emit_copy_state(sna, &tmp);
3638
n_this_time = gen2_get_rectangles(sna, &tmp, n);
3643
DBG((" (%d, %d) -> (%d, %d) + (%d, %d)\n",
3644
box->x1 + src_dx, box->y1 + src_dy,
3645
box->x1 + dst_dx, box->y1 + dst_dy,
3646
box->x2 - box->x1, box->y2 - box->y1));
3647
VERTEX(box->x2 + dst_dx);
3648
VERTEX(box->y2 + dst_dy);
3649
VERTEX((box->x2 + src_dx) * tmp.src.scale[0]);
3650
VERTEX((box->y2 + src_dy) * tmp.src.scale[1]);
3652
VERTEX(box->x1 + dst_dx);
3653
VERTEX(box->y2 + dst_dy);
3654
VERTEX((box->x1 + src_dx) * tmp.src.scale[0]);
3655
VERTEX((box->y2 + src_dy) * tmp.src.scale[1]);
3657
VERTEX(box->x1 + dst_dx);
3658
VERTEX(box->y1 + dst_dy);
3659
VERTEX((box->x1 + src_dx) * tmp.src.scale[0]);
3660
VERTEX((box->y1 + src_dy) * tmp.src.scale[1]);
3663
} while (--n_this_time);
3666
gen2_vertex_flush(sna, &tmp);
3667
sna_render_composite_redirect_done(sna, &tmp);
3671
return sna_tiling_copy_boxes(sna, alu,
3672
src, src_bo, src_dx, src_dy,
3673
dst, dst_bo, dst_dx, dst_dy,
3678
gen2_render_copy_blt(struct sna *sna,
3679
const struct sna_copy_op *op,
3680
int16_t sx, int16_t sy,
3681
int16_t w, int16_t h,
3682
int16_t dx, int16_t dy)
3684
if (!gen2_get_rectangles(sna, &op->base, 1)) {
3685
gen2_emit_copy_state(sna, &op->base);
3686
gen2_get_rectangles(sna, &op->base, 1);
3691
VERTEX((sx+w)*op->base.src.scale[0]);
3692
VERTEX((sy+h)*op->base.src.scale[1]);
3696
VERTEX(sx*op->base.src.scale[0]);
3697
VERTEX((sy+h)*op->base.src.scale[1]);
3701
VERTEX(sx*op->base.src.scale[0]);
3702
VERTEX(sy*op->base.src.scale[1]);
3706
gen2_render_copy_done(struct sna *sna, const struct sna_copy_op *op)
3708
gen2_vertex_flush(sna, &op->base);
3712
gen2_render_copy(struct sna *sna, uint8_t alu,
3713
PixmapPtr src, struct kgem_bo *src_bo,
3714
PixmapPtr dst, struct kgem_bo *dst_bo,
3715
struct sna_copy_op *tmp)
3718
if (!sna_blt_compare_depth(&src->drawable, &dst->drawable))
3721
return sna_blt_copy(sna, alu,
3723
dst->drawable.bitsPerPixel,
3727
/* Prefer to use the BLT */
3728
if (sna_blt_compare_depth(&src->drawable, &dst->drawable) &&
3729
sna_blt_copy(sna, alu,
3731
dst->drawable.bitsPerPixel,
3735
/* Must use the BLT if we can't RENDER... */
3736
if (too_large(src->drawable.width, src->drawable.height) ||
3737
too_large(dst->drawable.width, dst->drawable.height) ||
3738
src_bo->pitch > MAX_3D_PITCH ||
3739
dst_bo->pitch < 8 || dst_bo->pitch > MAX_3D_PITCH) {
3741
if (!sna_blt_compare_depth(&src->drawable, &dst->drawable))
3744
return sna_blt_copy(sna, alu, src_bo, dst_bo,
3745
dst->drawable.bitsPerPixel,
3751
tmp->base.dst.pixmap = dst;
3752
tmp->base.dst.width = dst->drawable.width;
3753
tmp->base.dst.height = dst->drawable.height;
3754
tmp->base.dst.format = sna_format_for_depth(dst->drawable.depth);
3755
tmp->base.dst.bo = dst_bo;
3757
gen2_render_copy_setup_source(&tmp->base.src, &src->drawable, src_bo);
3758
tmp->base.mask.bo = NULL;
3760
tmp->base.floats_per_vertex = 4;
3761
tmp->base.floats_per_rect = 12;
3763
if (!kgem_check_bo(&sna->kgem, dst_bo, src_bo, NULL)) {
3764
kgem_submit(&sna->kgem);
3765
if (!kgem_check_bo(&sna->kgem, dst_bo, src_bo, NULL))
3769
tmp->blt = gen2_render_copy_blt;
3770
tmp->done = gen2_render_copy_done;
3772
gen2_emit_composite_state(sna, &tmp->base);
3777
gen2_render_reset(struct sna *sna)
3779
sna->render_state.gen2.need_invariant = true;
3780
sna->render_state.gen2.logic_op_enabled = 0;
3781
sna->render_state.gen2.target = 0;
3783
sna->render_state.gen2.ls1 = 0;
3784
sna->render_state.gen2.ls2 = 0;
3785
sna->render_state.gen2.vft = 0;
3787
sna->render_state.gen2.diffuse = 0x0c0ffee0;
3788
sna->render_state.gen2.specular = 0x0c0ffee0;
3792
gen2_render_flush(struct sna *sna)
3794
assert(sna->render.vertex_index == 0);
3795
assert(sna->render.vertex_offset == 0);
3799
gen2_render_context_switch(struct kgem *kgem,
3802
struct sna *sna = container_of(kgem, struct sna, kgem);
3807
/* Reload BLT registers following a lost context */
3808
sna->blt_state.fill_bo = 0;
3810
if (kgem_ring_is_idle(kgem, kgem->ring)) {
3811
DBG(("%s: GPU idle, flushing\n", __FUNCTION__));
3816
const char *gen2_render_init(struct sna *sna, const char *backend)
3818
struct sna_render *render = &sna->render;
3820
sna->kgem.context_switch = gen2_render_context_switch;
3822
/* Use the BLT (and overlay) for everything except when forced to
3823
* use the texture combiners.
3826
render->composite = gen2_render_composite;
3827
render->prefer_gpu |= PREFER_GPU_RENDER;
3829
#if !NO_COMPOSITE_SPANS
3830
render->check_composite_spans = gen2_check_composite_spans;
3831
render->composite_spans = gen2_render_composite_spans;
3832
render->prefer_gpu |= PREFER_GPU_SPANS;
3834
render->fill_boxes = gen2_render_fill_boxes;
3835
render->fill = gen2_render_fill;
3836
render->fill_one = gen2_render_fill_one;
3837
render->copy = gen2_render_copy;
3838
render->copy_boxes = gen2_render_copy_boxes;
3840
render->video = gen2_render_video;
3842
render->reset = gen2_render_reset;
3843
render->flush = gen2_render_flush;
3845
render->max_3d_size = MAX_3D_SIZE;
3846
render->max_3d_pitch = MAX_3D_PITCH;
3847
return "Almador (gen2)";