1012
1020
sna->kgem.batch[sna->render_state.gen7.vertex_offset] =
1013
1021
sna->render.vertex_index - sna->render.vertex_start;
1014
1022
sna->render_state.gen7.vertex_offset = 0;
1017
gen7_magic_ca_pass(sna, sna->render.op);
1020
static void gen7_vertex_finish(struct sna *sna, Bool last)
1025
static int gen7_vertex_finish(struct sna *sna)
1022
1027
struct kgem_bo *bo;
1023
unsigned int i, delta;
1025
gen7_vertex_flush(sna);
1026
if (!sna->render.vertex_used)
1030
assert(sna->render.vertex_used);
1029
1032
/* Note: we only need dword alignment (currently) */
1031
if (last && sna->kgem.nbatch + sna->render.vertex_used <= sna->kgem.surface) {
1032
DBG(("%s: copy to batch: %d @ %d\n", __FUNCTION__,
1033
sna->render.vertex_used, sna->kgem.nbatch));
1034
memcpy(sna->kgem.batch + sna->kgem.nbatch,
1034
bo = sna->render.vbo;
1036
if (sna->render_state.gen7.vertex_offset)
1037
gen7_vertex_flush(sna);
1039
for (i = 0; i < ARRAY_SIZE(sna->render.vertex_reloc); i++) {
1040
if (sna->render.vertex_reloc[i]) {
1041
DBG(("%s: reloc[%d] = %d\n", __FUNCTION__,
1042
i, sna->render.vertex_reloc[i]));
1044
sna->kgem.batch[sna->render.vertex_reloc[i]] =
1045
kgem_add_reloc(&sna->kgem,
1046
sna->render.vertex_reloc[i],
1048
I915_GEM_DOMAIN_VERTEX << 16,
1050
sna->kgem.batch[sna->render.vertex_reloc[i]+1] =
1051
kgem_add_reloc(&sna->kgem,
1052
sna->render.vertex_reloc[i]+1,
1054
I915_GEM_DOMAIN_VERTEX << 16,
1055
sna->render.vertex_used * 4 - 1);
1056
sna->render.vertex_reloc[i] = 0;
1060
sna->render.vertex_used = 0;
1061
sna->render.vertex_index = 0;
1062
sna->render_state.gen7.vb_id = 0;
1064
kgem_bo_destroy(&sna->kgem, bo);
1067
sna->render.vertices = NULL;
1068
sna->render.vbo = kgem_create_linear(&sna->kgem, 256*1024);
1069
if (sna->render.vbo)
1070
sna->render.vertices = kgem_bo_map__cpu(&sna->kgem, sna->render.vbo);
1071
if (sna->render.vertices == NULL) {
1072
kgem_bo_destroy(&sna->kgem, sna->render.vbo);
1073
sna->render.vbo = NULL;
1077
kgem_bo_sync__cpu(&sna->kgem, sna->render.vbo);
1078
if (sna->render.vertex_used) {
1079
memcpy(sna->render.vertices,
1035
1080
sna->render.vertex_data,
1036
sna->render.vertex_used * 4);
1037
delta = sna->kgem.nbatch * 4;
1039
sna->kgem.nbatch += sna->render.vertex_used;
1041
bo = kgem_create_linear(&sna->kgem, 4*sna->render.vertex_used);
1042
if (bo && !kgem_bo_write(&sna->kgem, bo,
1043
sna->render.vertex_data,
1044
4*sna->render.vertex_used)) {
1045
kgem_bo_destroy(&sna->kgem, bo);
1081
sizeof(float)*sna->render.vertex_used);
1083
sna->render.vertex_size = 64 * 1024 - 1;
1084
return sna->render.vertex_size - sna->render.vertex_used;
1087
static void gen7_vertex_close(struct sna *sna)
1090
unsigned int i, delta = 0;
1092
if (!sna->render.vertex_used) {
1093
assert(sna->render.vbo == NULL);
1094
assert(sna->render.vertices == sna->render.vertex_data);
1095
assert(sna->render.vertex_size == ARRAY_SIZE(sna->render.vertex_data));
1099
DBG(("%s: used=%d / %d\n", __FUNCTION__,
1100
sna->render.vertex_used, sna->render.vertex_size));
1102
bo = sna->render.vbo;
1104
if (sna->kgem.nbatch + sna->render.vertex_used <= sna->kgem.surface) {
1105
DBG(("%s: copy to batch: %d @ %d\n", __FUNCTION__,
1106
sna->render.vertex_used, sna->kgem.nbatch));
1107
memcpy(sna->kgem.batch + sna->kgem.nbatch,
1108
sna->render.vertex_data,
1109
sna->render.vertex_used * 4);
1110
delta = sna->kgem.nbatch * 4;
1112
sna->kgem.nbatch += sna->render.vertex_used;
1114
bo = kgem_create_linear(&sna->kgem, 4*sna->render.vertex_used);
1115
if (bo && !kgem_bo_write(&sna->kgem, bo,
1116
sna->render.vertex_data,
1117
4*sna->render.vertex_used)) {
1118
kgem_bo_destroy(&sna->kgem, bo);
1121
DBG(("%s: new vbo: %d\n", __FUNCTION__,
1122
sna->render.vertex_used));
1049
DBG(("%s: new vbo: %d\n", __FUNCTION__,
1050
sna->render.vertex_used));
1053
1126
for (i = 0; i < ARRAY_SIZE(sna->render.vertex_reloc); i++) {
1555
1630
static bool gen7_rectangle_begin(struct sna *sna,
1556
1631
const struct sna_composite_op *op)
1558
int id = op->u.gen7.ve_id;
1633
int id = 1 << op->u.gen7.ve_id;
1562
if ((sna->render_state.gen7.vb_id & (1 << id)) == 0)
1636
ndwords = op->need_magic_ca_pass ? 60 : 6;
1637
if ((sna->render_state.gen7.vb_id & id) == 0)
1564
if (sna->render_state.gen7.vertex_offset == 0)
1565
ndwords += op->need_magic_ca_pass ? 60 : 6;
1569
1639
if (!kgem_check_batch(&sna->kgem, ndwords))
1572
if ((sna->render_state.gen7.vb_id & (1 << id)) == 0)
1642
if ((sna->render_state.gen7.vb_id & id) == 0)
1573
1643
gen7_emit_vertex_buffer(sna, op);
1574
if (sna->render_state.gen7.vertex_offset == 0)
1575
gen7_emit_primitive(sna);
1645
gen7_emit_primitive(sna);
1580
static int gen7_get_rectangles__flush(struct sna *sna, bool ca)
1649
static int gen7_get_rectangles__flush(struct sna *sna,
1650
const struct sna_composite_op *op)
1582
if (!kgem_check_batch(&sna->kgem, ca ? 65 : 5))
1652
if (!kgem_check_batch(&sna->kgem, op->need_magic_ca_pass ? 65 : 6))
1584
1654
if (sna->kgem.nexec > KGEM_EXEC_SIZE(&sna->kgem) - 1)
1586
if (sna->kgem.nreloc > KGEM_RELOC_SIZE(&sna->kgem) - 1)
1589
gen7_vertex_finish(sna, FALSE);
1590
sna->render.vertex_index = 0;
1592
return ARRAY_SIZE(sna->render.vertex_data);
1656
if (sna->kgem.nreloc > KGEM_RELOC_SIZE(&sna->kgem) - 2)
1659
if (op->need_magic_ca_pass && sna->render.vbo)
1662
return gen7_vertex_finish(sna);
1595
1665
inline static int gen7_get_rectangles(struct sna *sna,
1596
1666
const struct sna_composite_op *op,
1668
void (*emit_state)(struct sna *sna, const struct sna_composite_op *op))
1599
1670
int rem = vertex_space(sna);
1601
if (rem < 3*op->floats_per_vertex) {
1673
rem = vertex_space(sna);
1674
if (rem < op->floats_per_rect) {
1602
1675
DBG(("flushing vbo for %s: %d < %d\n",
1603
__FUNCTION__, rem, 3*op->floats_per_vertex));
1604
rem = gen7_get_rectangles__flush(sna, op->need_magic_ca_pass);
1676
__FUNCTION__, rem, op->floats_per_rect));
1677
rem = gen7_get_rectangles__flush(sna, op);
1678
if (unlikely(rem == 0))
1609
if (!gen7_rectangle_begin(sna, op))
1682
if (unlikely(sna->render_state.gen7.vertex_offset == 0 &&
1683
!gen7_rectangle_begin(sna, op)))
1612
if (want > 1 && want * op->floats_per_vertex*3 > rem)
1613
want = rem / (3*op->floats_per_vertex);
1686
if (want > 1 && want * op->floats_per_rect > rem)
1687
want = rem / op->floats_per_rect;
1615
1689
sna->render.vertex_index += 3*want;
1693
if (sna->render_state.gen7.vertex_offset) {
1694
gen7_vertex_flush(sna);
1695
gen7_magic_ca_pass(sna, op);
1697
_kgem_submit(&sna->kgem);
1698
emit_state(sna, op);
1619
1702
inline static uint32_t *gen7_composite_get_binding_table(struct sna *sna,
2137
2228
static void gen7_render_composite_done(struct sna *sna,
2138
2229
const struct sna_composite_op *op)
2140
gen7_vertex_flush(sna);
2141
_kgem_set_mode(&sna->kgem, KGEM_RENDER);
2142
sna->render.op = NULL;
2144
sna_render_composite_redirect_done(sna, op);
2231
if (sna->render_state.gen7.vertex_offset) {
2232
gen7_vertex_flush(sna);
2233
gen7_magic_ca_pass(sna, op);
2237
kgem_bo_destroy(&sna->kgem, op->mask.bo);
2146
2238
if (op->src.bo)
2147
2239
kgem_bo_destroy(&sna->kgem, op->src.bo);
2149
kgem_bo_destroy(&sna->kgem, op->mask.bo);
2241
sna_render_composite_redirect_done(sna, op);
2153
gen7_composite_set_target(struct sna_composite_op *op, PicturePtr dst)
2245
gen7_composite_set_target(struct sna *sna, struct sna_composite_op *op, PicturePtr dst)
2155
2247
struct sna_pixmap *priv;
2157
if (!gen7_check_dst_format(dst->format)) {
2158
DBG(("%s: unsupported target format %08x\n",
2159
__FUNCTION__, dst->format));
2249
if (!gen7_check_dst_format(dst->format))
2163
2252
op->dst.pixmap = get_drawable_pixmap(dst->pDrawable);
2164
2253
op->dst.width = op->dst.pixmap->drawable.width;
2165
2254
op->dst.height = op->dst.pixmap->drawable.height;
2166
2255
op->dst.format = dst->format;
2167
2258
priv = sna_pixmap(op->dst.pixmap);
2170
if (priv && priv->gpu_bo == NULL) {
2259
if (priv && priv->gpu_bo == NULL &&
2260
I915_TILING_NONE == kgem_choose_tiling(&sna->kgem,
2264
op->dst.pixmap->drawable.bitsPerPixel)) {
2171
2265
op->dst.bo = priv->cpu_bo;
2172
2266
op->damage = &priv->cpu_damage;
2174
2268
if (op->dst.bo == NULL) {
2175
priv = sna_pixmap_force_to_gpu(op->dst.pixmap);
2269
priv = sna_pixmap_force_to_gpu(op->dst.pixmap, MOVE_READ | MOVE_WRITE);
2176
2270
if (priv == NULL)
2179
2273
op->dst.bo = priv->gpu_bo;
2180
2274
op->damage = &priv->gpu_damage;
2181
if (sna_damage_is_all(&priv->gpu_damage,
2182
op->dst.width, op->dst.height))
2276
if (sna_damage_is_all(op->damage, op->dst.width, op->dst.height))
2186
2279
get_drawable_deltas(dst->pDrawable, op->dst.pixmap,
2187
2280
&op->dst.x, &op->dst.y);
2199
try_blt(struct sna *sna, int width, int height)
2292
try_blt(struct sna *sna,
2293
PicturePtr dst, PicturePtr src,
2294
int width, int height)
2201
if (sna->kgem.mode == KGEM_BLT) {
2296
if (sna->kgem.ring != KGEM_RENDER) {
2202
2297
DBG(("%s: already performing BLT\n", __FUNCTION__));
2206
if (width > GEN7_MAX_SIZE || height > GEN7_MAX_SIZE) {
2301
if (too_large(width, height)) {
2207
2302
DBG(("%s: operation too large for 3D pipe (%d, %d)\n",
2208
2303
__FUNCTION__, width, height));
2307
if (too_large(dst->pDrawable->width, dst->pDrawable->height)) {
2308
DBG(("%s: dst too large for 3D pipe (%d, %d)\n",
2310
dst->pDrawable->width, dst->pDrawable->height));
2314
if (src->pDrawable &&
2315
too_large(src->pDrawable->width, src->pDrawable->height)) {
2316
DBG(("%s: src too large for 3D pipe (%d, %d)\n",
2318
src->pDrawable->width, src->pDrawable->height));
2326
is_gradient(PicturePtr picture)
2328
if (picture->pDrawable)
2331
return picture->pSourcePict->type != SourcePictTypeSolidFill;
2335
has_alphamap(PicturePtr p)
2337
return p->alphaMap != NULL;
2341
untransformed(PicturePtr p)
2343
return !p->transform || pixman_transform_is_int_translate(p->transform);
2347
need_upload(PicturePtr p)
2349
return p->pDrawable && unattached(p->pDrawable) && untransformed(p);
2353
source_fallback(PicturePtr p)
2355
if (sna_picture_is_solid(p, NULL))
2358
return (has_alphamap(p) ||
2360
!gen7_check_filter(p) ||
2361
!gen7_check_repeat(p) ||
2362
!gen7_check_format(p->format) ||
2367
gen7_composite_fallback(struct sna *sna,
2372
struct sna_pixmap *priv;
2373
PixmapPtr src_pixmap;
2374
PixmapPtr mask_pixmap;
2375
PixmapPtr dst_pixmap;
2377
if (!gen7_check_dst_format(dst->format)) {
2378
DBG(("%s: unknown destination format: %d\n",
2379
__FUNCTION__, dst->format));
2383
dst_pixmap = get_drawable_pixmap(dst->pDrawable);
2384
src_pixmap = src->pDrawable ? get_drawable_pixmap(src->pDrawable) : NULL;
2385
mask_pixmap = (mask && mask->pDrawable) ? get_drawable_pixmap(mask->pDrawable) : NULL;
2387
/* If we are using the destination as a source and need to
2388
* readback in order to upload the source, do it all
2391
if (src_pixmap == dst_pixmap && source_fallback(src)) {
2392
DBG(("%s: src is dst and will fallback\n",__FUNCTION__));
2395
if (mask_pixmap == dst_pixmap && source_fallback(mask)) {
2396
DBG(("%s: mask is dst and will fallback\n",__FUNCTION__));
2400
/* If anything is on the GPU, push everything out to the GPU */
2401
priv = sna_pixmap(dst_pixmap);
2403
((priv->gpu_damage && !priv->clear) ||
2404
(priv->cpu_bo && kgem_bo_is_busy(priv->cpu_bo)))) {
2405
DBG(("%s: dst is already on the GPU, try to use GPU\n",
2410
if (src_pixmap && !source_fallback(src)) {
2411
priv = sna_pixmap(src_pixmap);
2412
if (priv && priv->gpu_damage && !priv->cpu_damage) {
2413
DBG(("%s: src is already on the GPU, try to use GPU\n",
2418
if (mask_pixmap && !source_fallback(mask)) {
2419
priv = sna_pixmap(mask_pixmap);
2420
if (priv && priv->gpu_damage && !priv->cpu_damage) {
2421
DBG(("%s: mask is already on the GPU, try to use GPU\n",
2427
/* However if the dst is not on the GPU and we need to
2428
* render one of the sources using the CPU, we may
2429
* as well do the entire operation in place onthe CPU.
2431
if (source_fallback(src)) {
2432
DBG(("%s: dst is on the CPU and src will fallback\n",
2437
if (mask && source_fallback(mask)) {
2438
DBG(("%s: dst is on the CPU and mask will fallback\n",
2443
DBG(("%s: dst is not on the GPU and the operation should not fallback\n",
2449
reuse_source(struct sna *sna,
2450
PicturePtr src, struct sna_composite_channel *sc, int src_x, int src_y,
2451
PicturePtr mask, struct sna_composite_channel *mc, int msk_x, int msk_y)
2455
if (src_x != msk_x || src_y != msk_y)
2459
DBG(("%s: mask is source\n", __FUNCTION__));
2461
mc->bo = kgem_bo_reference(mc->bo);
2465
if (sna_picture_is_solid(mask, &color))
2466
return gen7_composite_solid_init(sna, mc, color);
2471
if (src->pDrawable == NULL || mask->pDrawable != src->pDrawable)
2474
DBG(("%s: mask reuses source drawable\n", __FUNCTION__));
2476
if (!sna_transform_equal(src->transform, mask->transform))
2479
if (!sna_picture_alphamap_equal(src, mask))
2482
if (!gen7_check_repeat(mask))
2485
if (!gen7_check_filter(mask))
2488
if (!gen7_check_format(mask->format))
2491
DBG(("%s: reusing source channel for mask with a twist\n",
2495
mc->repeat = gen7_repeat(mask->repeat ? mask->repeatType : RepeatNone);
2496
mc->filter = gen7_filter(mask->filter);
2497
mc->pict_format = mask->format;
2498
mc->card_format = gen7_get_card_format(mask->format);
2499
mc->bo = kgem_bo_reference(mc->bo);
2702
/* A poor man's span interface. But better than nothing? */
2703
#if !NO_COMPOSITE_SPANS
2705
gen7_composite_alpha_gradient_init(struct sna *sna,
2706
struct sna_composite_channel *channel)
2708
DBG(("%s\n", __FUNCTION__));
2710
channel->filter = PictFilterNearest;
2711
channel->repeat = RepeatPad;
2712
channel->is_affine = TRUE;
2713
channel->is_solid = FALSE;
2714
channel->transform = NULL;
2715
channel->width = 256;
2716
channel->height = 1;
2717
channel->card_format = GEN7_SURFACEFORMAT_B8G8R8A8_UNORM;
2719
channel->bo = sna_render_get_alpha_gradient(sna);
2721
channel->scale[0] = channel->scale[1] = 1;
2722
channel->offset[0] = channel->offset[1] = 0;
2723
return channel->bo != NULL;
2727
gen7_emit_composite_texcoord(struct sna *sna,
2728
const struct sna_composite_channel *channel,
2729
int16_t x, int16_t y)
2733
if (channel->is_affine) {
2734
sna_get_transformed_coordinates(x + channel->offset[0],
2735
y + channel->offset[1],
2738
OUT_VERTEX_F(t[0] * channel->scale[0]);
2739
OUT_VERTEX_F(t[1] * channel->scale[1]);
2741
t[0] = t[1] = 0; t[2] = 1;
2742
sna_get_transformed_coordinates_3d(x + channel->offset[0],
2743
y + channel->offset[1],
2745
&t[0], &t[1], &t[2]);
2746
OUT_VERTEX_F(t[0] * channel->scale[0]);
2747
OUT_VERTEX_F(t[1] * channel->scale[1]);
2753
gen7_emit_composite_texcoord_affine(struct sna *sna,
2754
const struct sna_composite_channel *channel,
2755
int16_t x, int16_t y)
2759
sna_get_transformed_coordinates(x + channel->offset[0],
2760
y + channel->offset[1],
2763
OUT_VERTEX_F(t[0] * channel->scale[0]);
2764
OUT_VERTEX_F(t[1] * channel->scale[1]);
2768
gen7_emit_composite_spans_vertex(struct sna *sna,
2769
const struct sna_composite_spans_op *op,
2770
int16_t x, int16_t y)
2773
gen7_emit_composite_texcoord(sna, &op->base.src, x, y);
2776
fastcall static void
2777
gen7_emit_composite_spans_primitive(struct sna *sna,
2778
const struct sna_composite_spans_op *op,
2782
gen7_emit_composite_spans_vertex(sna, op, box->x2, box->y2);
2783
OUT_VERTEX_F(opacity);
2785
if (!op->base.is_affine)
2788
gen7_emit_composite_spans_vertex(sna, op, box->x1, box->y2);
2789
OUT_VERTEX_F(opacity);
2791
if (!op->base.is_affine)
2794
gen7_emit_composite_spans_vertex(sna, op, box->x1, box->y1);
2795
OUT_VERTEX_F(opacity);
2797
if (!op->base.is_affine)
2801
fastcall static void
2802
gen7_emit_composite_spans_solid(struct sna *sna,
2803
const struct sna_composite_spans_op *op,
2807
OUT_VERTEX(box->x2, box->y2);
2808
OUT_VERTEX_F(1); OUT_VERTEX_F(1);
2809
OUT_VERTEX_F(opacity); OUT_VERTEX_F(1);
2811
OUT_VERTEX(box->x1, box->y2);
2812
OUT_VERTEX_F(0); OUT_VERTEX_F(1);
2813
OUT_VERTEX_F(opacity); OUT_VERTEX_F(1);
2815
OUT_VERTEX(box->x1, box->y1);
2816
OUT_VERTEX_F(0); OUT_VERTEX_F(0);
2817
OUT_VERTEX_F(opacity); OUT_VERTEX_F(0);
2820
fastcall static void
2821
gen7_emit_composite_spans_identity(struct sna *sna,
2822
const struct sna_composite_spans_op *op,
2828
struct sna_coordinate p;
2832
float sx = op->base.src.scale[0];
2833
float sy = op->base.src.scale[1];
2834
int16_t tx = op->base.src.offset[0];
2835
int16_t ty = op->base.src.offset[1];
2837
v = sna->render.vertices + sna->render.vertex_used;
2838
sna->render.vertex_used += 3*5;
2843
v[1] = (box->x2 + tx) * sx;
2844
v[7] = v[2] = (box->y2 + ty) * sy;
2845
v[13] = v[8] = v[3] = opacity;
2850
v[11] = v[6] = (box->x1 + tx) * sx;
2854
v[12] = (box->y1 + ty) * sy;
2858
fastcall static void
2859
gen7_emit_composite_spans_simple(struct sna *sna,
2860
const struct sna_composite_spans_op *op,
2866
struct sna_coordinate p;
2870
float xx = op->base.src.transform->matrix[0][0];
2871
float x0 = op->base.src.transform->matrix[0][2];
2872
float yy = op->base.src.transform->matrix[1][1];
2873
float y0 = op->base.src.transform->matrix[1][2];
2874
float sx = op->base.src.scale[0];
2875
float sy = op->base.src.scale[1];
2876
int16_t tx = op->base.src.offset[0];
2877
int16_t ty = op->base.src.offset[1];
2879
v = sna->render.vertices + sna->render.vertex_used;
2880
sna->render.vertex_used += 3*5;
2885
v[1] = ((box->x2 + tx) * xx + x0) * sx;
2886
v[7] = v[2] = ((box->y2 + ty) * yy + y0) * sy;
2887
v[13] = v[8] = v[3] = opacity;
2892
v[11] = v[6] = ((box->x1 + tx) * xx + x0) * sx;
2896
v[12] = ((box->y1 + ty) * yy + y0) * sy;
2900
fastcall static void
2901
gen7_emit_composite_spans_affine(struct sna *sna,
2902
const struct sna_composite_spans_op *op,
2906
OUT_VERTEX(box->x2, box->y2);
2907
gen7_emit_composite_texcoord_affine(sna, &op->base.src,
2909
OUT_VERTEX_F(opacity);
2912
OUT_VERTEX(box->x1, box->y2);
2913
gen7_emit_composite_texcoord_affine(sna, &op->base.src,
2915
OUT_VERTEX_F(opacity);
2918
OUT_VERTEX(box->x1, box->y1);
2919
gen7_emit_composite_texcoord_affine(sna, &op->base.src,
2921
OUT_VERTEX_F(opacity);
2925
fastcall static void
2926
gen7_render_composite_spans_box(struct sna *sna,
2927
const struct sna_composite_spans_op *op,
2928
const BoxRec *box, float opacity)
2930
DBG(("%s: src=+(%d, %d), opacity=%f, dst=+(%d, %d), box=(%d, %d) x (%d, %d)\n",
2932
op->base.src.offset[0], op->base.src.offset[1],
2934
op->base.dst.x, op->base.dst.y,
2937
box->y2 - box->y1));
2939
gen7_get_rectangles(sna, &op->base, 1, gen7_emit_composite_state);
2940
op->prim_emit(sna, op, box, opacity);
2944
gen7_render_composite_spans_boxes(struct sna *sna,
2945
const struct sna_composite_spans_op *op,
2946
const BoxRec *box, int nbox,
2949
DBG(("%s: nbox=%d, src=+(%d, %d), opacity=%f, dst=+(%d, %d)\n",
2951
op->base.src.offset[0], op->base.src.offset[1],
2953
op->base.dst.x, op->base.dst.y));
2958
nbox_this_time = gen7_get_rectangles(sna, &op->base, nbox,
2959
gen7_emit_composite_state);
2960
nbox -= nbox_this_time;
2963
DBG((" %s: (%d, %d) x (%d, %d)\n", __FUNCTION__,
2966
box->y2 - box->y1));
2968
op->prim_emit(sna, op, box++, opacity);
2969
} while (--nbox_this_time);
2973
fastcall static void
2974
gen7_render_composite_spans_done(struct sna *sna,
2975
const struct sna_composite_spans_op *op)
2977
if (sna->render_state.gen7.vertex_offset)
2978
gen7_vertex_flush(sna);
2980
DBG(("%s()\n", __FUNCTION__));
2982
if (op->base.src.bo)
2983
kgem_bo_destroy(&sna->kgem, op->base.src.bo);
2985
sna_render_composite_redirect_done(sna, &op->base);
2989
gen7_render_composite_spans(struct sna *sna,
2993
int16_t src_x, int16_t src_y,
2994
int16_t dst_x, int16_t dst_y,
2995
int16_t width, int16_t height,
2997
struct sna_composite_spans_op *tmp)
2999
DBG(("%s: %dx%d with flags=%x, current mode=%d\n", __FUNCTION__,
3000
width, height, flags, sna->kgem.ring));
3002
if ((flags & COMPOSITE_SPANS_RECTILINEAR) == 0)
3005
if (op >= ARRAY_SIZE(gen7_blend_op))
3008
if (need_tiling(sna, width, height))
3011
if (gen7_composite_fallback(sna, src, NULL, dst))
3015
if (!gen7_composite_set_target(sna, &tmp->base, dst))
3017
sna_render_reduce_damage(&tmp->base, dst_x, dst_y, width, height);
3019
if (too_large(tmp->base.dst.width, tmp->base.dst.height)) {
3020
if (!sna_render_composite_redirect(sna, &tmp->base,
3021
dst_x, dst_y, width, height))
3025
switch (gen7_composite_picture(sna, src, &tmp->base.src,
3032
gen7_composite_solid_init(sna, &tmp->base.src, 0);
3034
gen7_composite_channel_convert(&tmp->base.src);
3038
tmp->base.mask.bo = NULL;
3040
tmp->base.is_affine = tmp->base.src.is_affine;
3041
tmp->base.has_component_alpha = FALSE;
3042
tmp->base.need_magic_ca_pass = FALSE;
3044
gen7_composite_alpha_gradient_init(sna, &tmp->base.mask);
3046
tmp->prim_emit = gen7_emit_composite_spans_primitive;
3047
if (tmp->base.src.is_solid) {
3048
tmp->prim_emit = gen7_emit_composite_spans_solid;
3049
} else if (tmp->base.src.transform == NULL) {
3050
tmp->prim_emit = gen7_emit_composite_spans_identity;
3051
} else if (tmp->base.is_affine) {
3052
if (tmp->base.src.transform->matrix[0][1] == 0 &&
3053
tmp->base.src.transform->matrix[1][0] == 0) {
3054
tmp->base.src.scale[0] /= tmp->base.src.transform->matrix[2][2];
3055
tmp->base.src.scale[1] /= tmp->base.src.transform->matrix[2][2];
3056
tmp->prim_emit = gen7_emit_composite_spans_simple;
3058
tmp->prim_emit = gen7_emit_composite_spans_affine;
3060
tmp->base.floats_per_vertex = 5 + 2*!tmp->base.is_affine;
3061
tmp->base.floats_per_rect = 3 * tmp->base.floats_per_vertex;
3063
tmp->base.u.gen7.wm_kernel =
3064
gen7_choose_composite_kernel(tmp->base.op,
3066
tmp->base.is_affine);
3067
tmp->base.u.gen7.nr_surfaces = 3;
3068
tmp->base.u.gen7.nr_inputs = 2;
3069
tmp->base.u.gen7.ve_id = 1 << 1 | tmp->base.is_affine;
3071
tmp->box = gen7_render_composite_spans_box;
3072
tmp->boxes = gen7_render_composite_spans_boxes;
3073
tmp->done = gen7_render_composite_spans_done;
3075
kgem_set_mode(&sna->kgem, KGEM_RENDER);
3076
if (!kgem_check_bo(&sna->kgem,
3077
tmp->base.dst.bo, tmp->base.src.bo,
3079
kgem_submit(&sna->kgem);
3080
if (!kgem_check_bo(&sna->kgem,
3081
tmp->base.dst.bo, tmp->base.src.bo,
3084
_kgem_set_mode(&sna->kgem, KGEM_RENDER);
3087
gen7_emit_composite_state(sna, &tmp->base);
3088
gen7_align_vertex(sna, &tmp->base);
3092
if (tmp->base.src.bo)
3093
kgem_bo_destroy(&sna->kgem, tmp->base.src.bo);
3095
if (tmp->base.redirect.real_bo)
3096
kgem_bo_destroy(&sna->kgem, tmp->base.dst.bo);
2380
3102
gen7_emit_copy_state(struct sna *sna,
2381
3103
const struct sna_composite_op *op)
2442
if (!(alu == GXcopy || alu == GXclear) || src_bo == dst_bo ||
2443
src->drawable.width > GEN7_MAX_SIZE ||
2444
src->drawable.height > GEN7_MAX_SIZE ||
2445
dst->drawable.width > GEN7_MAX_SIZE ||
2446
dst->drawable.height > GEN7_MAX_SIZE) {
3221
if (!(alu == GXcopy || alu == GXclear) ||
3222
overlaps(src_bo, src_dx, src_dy,
3223
dst_bo, dst_dx, dst_dy,
2447
3226
if (!sna_blt_compare_depth(&src->drawable, &dst->drawable))
2450
return sna_blt_copy_boxes(sna, alu,
2451
src_bo, src_dx, src_dy,
2452
dst_bo, dst_dx, dst_dy,
2453
dst->drawable.bitsPerPixel,
3229
return sna_blt_copy_boxes_fallback(sna, alu,
3230
src, src_bo, src_dx, src_dy,
3231
dst, dst_bo, dst_dx, dst_dy,
3235
if (dst->drawable.depth == src->drawable.depth) {
3236
tmp.dst.format = sna_render_format_for_depth(dst->drawable.depth);
3237
tmp.src.pict_format = tmp.dst.format;
3239
tmp.dst.format = sna_format_for_depth(dst->drawable.depth);
3240
tmp.src.pict_format = sna_format_for_depth(src->drawable.depth);
3242
if (!gen7_check_format(tmp.src.pict_format))
2456
3245
tmp.op = alu == GXcopy ? PictOpSrc : PictOpClear;
2458
3247
tmp.dst.pixmap = dst;
2459
tmp.dst.x = tmp.dst.y = 0;
2460
3248
tmp.dst.width = dst->drawable.width;
2461
3249
tmp.dst.height = dst->drawable.height;
2462
tmp.dst.format = sna_format_for_depth(dst->drawable.depth);
2463
3250
tmp.dst.bo = dst_bo;
2467
tmp.src.bo = src_bo;
3251
tmp.dst.x = tmp.dst.y = 0;
3254
sna_render_composite_redirect_init(&tmp);
3255
if (too_large(tmp.dst.width, tmp.dst.height)) {
3256
BoxRec extents = box[0];
3259
for (i = 1; i < n; i++) {
3260
if (extents.x1 < box[i].x1)
3261
extents.x1 = box[i].x1;
3262
if (extents.y1 < box[i].y1)
3263
extents.y1 = box[i].y1;
3265
if (extents.x2 > box[i].x2)
3266
extents.x2 = box[i].x2;
3267
if (extents.y2 > box[i].y2)
3268
extents.y2 = box[i].y2;
3270
if (!sna_render_composite_redirect(sna, &tmp,
3271
extents.x1 + dst_dx,
3272
extents.y1 + dst_dy,
3273
extents.x2 - extents.x1,
3274
extents.y2 - extents.y1))
3275
goto fallback_tiled;
2468
3278
tmp.src.filter = SAMPLER_FILTER_NEAREST;
2469
3279
tmp.src.repeat = SAMPLER_EXTEND_NONE;
2470
tmp.src.card_format =
2471
gen7_get_card_format_for_depth(src->drawable.depth),
2472
tmp.src.width = src->drawable.width;
2473
tmp.src.height = src->drawable.height;
3280
tmp.src.card_format = gen7_get_card_format(tmp.src.pict_format);
3281
if (too_large(src->drawable.width, src->drawable.height)) {
3282
BoxRec extents = box[0];
3285
for (i = 1; i < n; i++) {
3286
if (extents.x1 < box[i].x1)
3287
extents.x1 = box[i].x1;
3288
if (extents.y1 < box[i].y1)
3289
extents.y1 = box[i].y1;
3291
if (extents.x2 > box[i].x2)
3292
extents.x2 = box[i].x2;
3293
if (extents.y2 > box[i].y2)
3294
extents.y2 = box[i].y2;
3297
if (!sna_render_pixmap_partial(sna, src, src_bo, &tmp.src,
3298
extents.x1 + src_dx,
3299
extents.y1 + src_dy,
3300
extents.x2 - extents.x1,
3301
extents.y2 - extents.y1))
3302
goto fallback_tiled_dst;
3304
tmp.src.bo = kgem_bo_reference(src_bo);
3305
tmp.src.width = src->drawable.width;
3306
tmp.src.height = src->drawable.height;
3307
tmp.src.offset[0] = tmp.src.offset[1] = 0;
3308
tmp.src.scale[0] = 1.f/src->drawable.width;
3309
tmp.src.scale[1] = 1.f/src->drawable.height;
2475
3312
tmp.mask.bo = NULL;
2476
3313
tmp.mask.filter = SAMPLER_FILTER_NEAREST;
3090
3962
gen7_vertex_flush(sna);
3091
3963
kgem_bo_destroy(&sna->kgem, tmp.src.bo);
3092
_kgem_set_mode(&sna->kgem, KGEM_RENDER);
3969
gen7_render_clear_try_blt(struct sna *sna, PixmapPtr dst, struct kgem_bo *bo)
3975
box.x2 = dst->drawable.width;
3976
box.y2 = dst->drawable.height;
3978
return sna_blt_fill_boxes(sna, GXclear,
3979
bo, dst->drawable.bitsPerPixel,
3984
gen7_render_clear(struct sna *sna, PixmapPtr dst, struct kgem_bo *bo)
3986
struct sna_composite_op tmp;
3989
return gen7_render_clear_try_blt(sna, dst, bo);
3994
dst->drawable.width,
3995
dst->drawable.height));
3997
/* Prefer to use the BLT if already engaged */
3998
if (sna->kgem.ring == KGEM_BLT &&
3999
gen7_render_clear_try_blt(sna, dst, bo))
4002
/* Must use the BLT if we can't RENDER... */
4003
if (too_large(dst->drawable.width, dst->drawable.height))
4004
return gen7_render_clear_try_blt(sna, dst, bo);
4006
tmp.op = PictOpClear;
4008
tmp.dst.pixmap = dst;
4009
tmp.dst.width = dst->drawable.width;
4010
tmp.dst.height = dst->drawable.height;
4011
tmp.dst.format = sna_format_for_depth(dst->drawable.depth);
4013
tmp.dst.x = tmp.dst.y = 0;
4015
tmp.src.bo = sna_render_get_solid(sna, 0);
4016
tmp.src.filter = SAMPLER_FILTER_NEAREST;
4017
tmp.src.repeat = SAMPLER_EXTEND_REPEAT;
4020
tmp.mask.filter = SAMPLER_FILTER_NEAREST;
4021
tmp.mask.repeat = SAMPLER_EXTEND_NONE;
4023
tmp.is_affine = TRUE;
4024
tmp.floats_per_vertex = 3;
4025
tmp.floats_per_rect = 9;
4026
tmp.has_component_alpha = 0;
4027
tmp.need_magic_ca_pass = FALSE;
4029
tmp.u.gen7.wm_kernel = GEN7_WM_KERNEL_NOMASK;
4030
tmp.u.gen7.nr_surfaces = 2;
4031
tmp.u.gen7.nr_inputs = 1;
4032
tmp.u.gen7.ve_id = 1;
4034
if (!kgem_check_bo(&sna->kgem, bo, NULL)) {
4035
_kgem_submit(&sna->kgem);
4036
assert(kgem_check_bo(&sna->kgem, bo, NULL));
4039
gen7_emit_fill_state(sna, &tmp);
4040
gen7_align_vertex(sna, &tmp);
4042
gen7_get_rectangles(sna, &tmp, 1, gen7_emit_fill_state);
4044
OUT_VERTEX(dst->drawable.width, dst->drawable.height);
4048
OUT_VERTEX(0, dst->drawable.height);
4056
gen7_vertex_flush(sna);
4057
kgem_bo_destroy(&sna->kgem, tmp.src.bo);
3097
4062
static void gen7_render_flush(struct sna *sna)
3099
gen7_vertex_finish(sna, TRUE);
4064
gen7_vertex_close(sna);