~ubuntu-branches/debian/jessie/xserver-xorg-video-intel/jessie

« back to all changes in this revision

Viewing changes to src/sna/gen7_render.c

  • Committer: Package Import Robot
  • Author(s): Cyril Brulebois
  • Date: 2012-02-24 14:16:47 UTC
  • mfrom: (26.1.12 sid)
  • Revision ID: package-import@ubuntu.com-20120224141647-4aux48xunen1oa16
Tags: 2:2.18.0-1
* New upstream release.
* No SNA for unstable, it's too fast of a moving target for now.
* Since we're building for unstable, let's go back to the previous
  xorg-server build-dep.

Show diffs side-by-side

added added

removed removed

Lines of Context:
50
50
#endif
51
51
 
52
52
#define NO_COMPOSITE 0
 
53
#define NO_COMPOSITE_SPANS 0
53
54
#define NO_COPY 0
54
55
#define NO_COPY_BOXES 0
55
56
#define NO_FILL 0
56
57
#define NO_FILL_BOXES 0
 
58
#define NO_CLEAR 0
57
59
 
58
60
#define GEN7_MAX_SIZE 16384
59
61
 
154
156
        Bool has_mask;
155
157
} wm_kernels[] = {
156
158
        KERNEL(NOMASK, ps_kernel_nomask_affine, FALSE),
157
 
#if 0
158
159
        KERNEL(NOMASK_PROJECTIVE, ps_kernel_nomask_projective, FALSE),
159
160
 
160
161
        KERNEL(MASK, ps_kernel_masknoca_affine, TRUE),
165
166
 
166
167
        KERNEL(MASKCA_SRCALPHA, ps_kernel_maskca_srcalpha_affine, TRUE),
167
168
        KERNEL(MASKCA_SRCALPHA_PROJECTIVE, ps_kernel_maskca_srcalpha_projective, TRUE),
168
 
#endif
169
169
 
170
170
        KERNEL(VIDEO_PLANAR, ps_kernel_planar, FALSE),
171
171
        KERNEL(VIDEO_PACKED, ps_kernel_packed, FALSE),
235
235
#define OUT_VERTEX(x,y) vertex_emit_2s(sna, x,y)
236
236
#define OUT_VERTEX_F(v) vertex_emit(sna, v)
237
237
 
 
238
static inline bool too_large(int width, int height)
 
239
{
 
240
        return width > GEN7_MAX_SIZE || height > GEN7_MAX_SIZE;
 
241
}
 
242
 
238
243
static uint32_t gen7_get_blend(int op,
239
244
                               Bool has_component_alpha,
240
245
                               uint32_t dst_format)
318
323
        return FALSE;
319
324
}
320
325
 
321
 
static uint32_t gen7_get_dest_format_for_depth(int depth)
322
 
{
323
 
        switch (depth) {
324
 
        default: assert(0);
325
 
        case 32:
326
 
        case 24: return GEN7_SURFACEFORMAT_B8G8R8A8_UNORM;
327
 
        case 30: return GEN7_SURFACEFORMAT_B10G10R10A2_UNORM;
328
 
        case 16: return GEN7_SURFACEFORMAT_B5G6R5_UNORM;
329
 
        case 8:  return GEN7_SURFACEFORMAT_A8_UNORM;
330
 
        }
331
 
}
332
 
 
333
 
static uint32_t gen7_get_card_format_for_depth(int depth)
334
 
{
335
 
        switch (depth) {
336
 
        default: assert(0);
337
 
        case 32: return GEN7_SURFACEFORMAT_B8G8R8A8_UNORM;
338
 
        case 30: return GEN7_SURFACEFORMAT_B10G10R10A2_UNORM;
339
 
        case 24: return GEN7_SURFACEFORMAT_B8G8R8X8_UNORM;
340
 
        case 16: return GEN7_SURFACEFORMAT_B5G6R5_UNORM;
341
 
        case 8:  return GEN7_SURFACEFORMAT_A8_UNORM;
 
326
static bool gen7_check_format(uint32_t format)
 
327
{
 
328
        switch (format) {
 
329
        case PICT_a8r8g8b8:
 
330
        case PICT_x8r8g8b8:
 
331
        case PICT_a8b8g8r8:
 
332
        case PICT_x8b8g8r8:
 
333
        case PICT_a2r10g10b10:
 
334
        case PICT_x2r10g10b10:
 
335
        case PICT_r8g8b8:
 
336
        case PICT_r5g6b5:
 
337
        case PICT_a1r5g5b5:
 
338
        case PICT_a8:
 
339
        case PICT_a4r4g4b4:
 
340
        case PICT_x4r4g4b4:
 
341
                return true;
 
342
        default:
 
343
                DBG(("%s: unhandled format: %x\n", __FUNCTION__, format));
 
344
                return false;
342
345
        }
343
346
}
344
347
 
417
420
}
418
421
 
419
422
static void
420
 
gen7_emit_sip(struct sna *sna)
421
 
{
422
 
        /* Set system instruction pointer */
423
 
        OUT_BATCH(GEN7_STATE_SIP | 0);
424
 
        OUT_BATCH(0);
425
 
}
426
 
 
427
 
static void
428
423
gen7_emit_urb(struct sna *sna)
429
424
{
430
425
        OUT_BATCH(GEN7_3DSTATE_PUSH_CONSTANT_ALLOC_PS | (2 - 2));
481
476
static void
482
477
gen7_disable_vs(struct sna *sna)
483
478
{
 
479
        /* For future reference:
 
480
         * A PIPE_CONTROL with post-sync op set to 1 and a depth stall needs
 
481
         * to be emitted just prior to change VS state, i.e. 3DSTATE_VS,
 
482
         * 3DSTATE_URB_VS, 3DSTATE_CONSTANT_VS,
 
483
         * 3DSTATE_BINDING_TABLE_POINTER_VS, 3DSTATE_SAMPLER_STATE_POINTER_VS.
 
484
         *
 
485
         * Here we saved by the full-flush incurred when emitting
 
486
         * the batchbuffer.
 
487
         */
484
488
        OUT_BATCH(GEN7_3DSTATE_VS | (6 - 2));
485
489
        OUT_BATCH(0); /* no VS kernel */
486
490
        OUT_BATCH(0);
653
657
                  GEN7_WM_PERSPECTIVE_PIXEL_BARYCENTRIC);
654
658
        OUT_BATCH(0);
655
659
 
 
660
#if 0
656
661
        /* XXX length bias of 7 in old spec? */
657
662
        OUT_BATCH(GEN7_3DSTATE_CONSTANT_PS | (7 - 2));
658
663
        OUT_BATCH(0);
661
666
        OUT_BATCH(0);
662
667
        OUT_BATCH(0);
663
668
        OUT_BATCH(0);
 
669
#endif
664
670
}
665
671
 
666
672
static void
694
700
        OUT_BATCH(GEN7_3DSTATE_SAMPLE_MASK | (2 - 2));
695
701
        OUT_BATCH(1);
696
702
 
697
 
        gen7_emit_sip(sna);
698
703
        gen7_emit_urb(sna);
699
704
 
700
705
        gen7_emit_state_base_address(sna);
714
719
        sna->render_state.gen7.needs_invariant = FALSE;
715
720
}
716
721
 
717
 
static bool
 
722
static void
718
723
gen7_emit_cc(struct sna *sna, uint32_t blend_offset)
719
724
{
720
725
        struct gen7_render_state *render = &sna->render_state.gen7;
721
726
 
722
727
        if (render->blend == blend_offset)
723
 
                return false;
 
728
                return;
724
729
 
725
730
        /* XXX can have upto 8 blend states preload, selectable via
726
731
         * Render Target Index. What other side-effects of Render Target Index?
731
736
        OUT_BATCH((render->cc_blend + blend_offset) | 1);
732
737
 
733
738
        render->blend = blend_offset;
734
 
        return true;
735
739
}
736
740
 
737
741
static void
806
810
        OUT_BATCH(0); /* kernel 2 */
807
811
}
808
812
 
809
 
static bool
 
813
static void
810
814
gen7_emit_binding_table(struct sna *sna, uint16_t offset)
811
815
{
812
816
        if (sna->render_state.gen7.surface_table == offset)
813
 
                return false;
 
817
                return;
814
818
 
815
819
        /* Binding table pointers */
816
820
        assert(is_aligned(4*offset, 32));
818
822
        OUT_BATCH(offset*4);
819
823
 
820
824
        sna->render_state.gen7.surface_table = offset;
821
 
        return true;
822
825
}
823
826
 
824
827
static void
825
828
gen7_emit_drawing_rectangle(struct sna *sna,
826
 
                            const struct sna_composite_op *op,
827
 
                            bool force)
 
829
                            const struct sna_composite_op *op)
828
830
{
829
831
        uint32_t limit = (op->dst.height - 1) << 16 | (op->dst.width - 1);
830
832
        uint32_t offset = (uint16_t)op->dst.y << 16 | (uint16_t)op->dst.x;
831
833
 
832
 
        if (!force &&
833
 
            sna->render_state.gen7.drawrect_limit == limit &&
 
834
        assert(!too_large(op->dst.x, op->dst.y));
 
835
        assert(!too_large(op->dst.width, op->dst.height));
 
836
 
 
837
        if (sna->render_state.gen7.drawrect_limit == limit &&
834
838
            sna->render_state.gen7.drawrect_offset == offset)
835
839
                return;
836
840
 
924
928
}
925
929
 
926
930
static void
 
931
gen7_emit_flush(struct sna *sna)
 
932
{
 
933
        OUT_BATCH(GEN7_PIPE_CONTROL | (4 - 2));
 
934
        OUT_BATCH(GEN7_PIPE_CONTROL_WC_FLUSH |
 
935
                  GEN7_PIPE_CONTROL_TC_FLUSH |
 
936
                  GEN7_PIPE_CONTROL_CS_STALL);
 
937
        OUT_BATCH(0);
 
938
        OUT_BATCH(0);
 
939
}
 
940
 
 
941
static void
927
942
gen7_emit_state(struct sna *sna,
928
943
                const struct sna_composite_op *op,
929
944
                uint16_t wm_binding_table)
930
945
 
931
946
{
932
 
        bool flushed =
933
 
                (sna->kgem.batch[sna->kgem.nbatch-1] & (0xff<<23)) == MI_FLUSH;
934
 
        bool need_flush;
 
947
        if (kgem_bo_is_dirty(op->src.bo) || kgem_bo_is_dirty(op->mask.bo)) {
 
948
                gen7_emit_flush(sna);
 
949
                kgem_clear_dirty(&sna->kgem);
 
950
                kgem_bo_mark_dirty(op->dst.bo);
 
951
        }
935
952
 
936
 
        need_flush = gen7_emit_cc(sna,
937
 
                                  gen7_get_blend(op->op,
938
 
                                                 op->has_component_alpha,
939
 
                                                 op->dst.format));
 
953
        gen7_emit_cc(sna,
 
954
                     gen7_get_blend(op->op,
 
955
                                    op->has_component_alpha,
 
956
                                    op->dst.format));
940
957
 
941
958
        DBG(("%s: sampler src=(%d, %d), mask=(%d, %d), offset=%d\n",
942
959
             __FUNCTION__,
958
975
                     op->u.gen7.nr_inputs);
959
976
        gen7_emit_vertex_elements(sna, op);
960
977
 
961
 
        /* XXX updating the binding table requires a non-pipelined cmd? */
962
 
        need_flush |= gen7_emit_binding_table(sna, wm_binding_table);
963
 
        gen7_emit_drawing_rectangle(sna, op, need_flush & !flushed);
 
978
        gen7_emit_binding_table(sna, wm_binding_table);
 
979
        gen7_emit_drawing_rectangle(sna, op);
964
980
}
965
981
 
966
982
static void gen7_magic_ca_pass(struct sna *sna,
967
983
                               const struct sna_composite_op *op)
968
984
{
969
985
        struct gen7_render_state *state = &sna->render_state.gen7;
970
 
        bool need_flush;
971
986
 
972
987
        if (!op->need_magic_ca_pass)
973
988
                return;
975
990
        DBG(("%s: CA fixup (%d -> %d)\n", __FUNCTION__,
976
991
             sna->render.vertex_start, sna->render.vertex_index));
977
992
 
978
 
        need_flush =
979
 
                gen7_emit_cc(sna,
980
 
                             gen7_get_blend(PictOpAdd, TRUE, op->dst.format));
 
993
        gen7_emit_flush(sna);
 
994
 
 
995
        gen7_emit_cc(sna, gen7_get_blend(PictOpAdd, TRUE, op->dst.format));
981
996
        gen7_emit_wm(sna,
982
997
                     gen7_choose_composite_kernel(PictOpAdd,
983
998
                                                  TRUE, TRUE,
984
999
                                                  op->is_affine),
985
1000
                     3, 2);
986
1001
 
987
 
        /* XXX We apparently need a non-pipelined op to flush the
988
 
         * pipeline before changing blend state.
989
 
         */
990
 
        if (need_flush)
991
 
                OUT_BATCH(MI_FLUSH | MI_INHIBIT_RENDER_CACHE_FLUSH);
992
 
 
993
1002
        OUT_BATCH(GEN7_3DPRIMITIVE | (7- 2));
994
1003
        OUT_BATCH(GEN7_3DPRIMITIVE_VERTEX_SEQUENTIAL | _3DPRIM_RECTLIST);
995
1004
        OUT_BATCH(sna->render.vertex_index - sna->render.vertex_start);
1003
1012
 
1004
1013
static void gen7_vertex_flush(struct sna *sna)
1005
1014
{
1006
 
        if (sna->render_state.gen7.vertex_offset == 0)
1007
 
                return;
 
1015
        assert(sna->render_state.gen7.vertex_offset);
1008
1016
 
1009
1017
        DBG(("%s[%x] = %d\n", __FUNCTION__,
1010
1018
             4*sna->render_state.gen7.vertex_offset,
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;
1015
 
 
1016
 
        if (sna->render.op)
1017
 
                gen7_magic_ca_pass(sna, sna->render.op);
1018
1023
}
1019
1024
 
1020
 
static void gen7_vertex_finish(struct sna *sna, Bool last)
 
1025
static int gen7_vertex_finish(struct sna *sna)
1021
1026
{
1022
1027
        struct kgem_bo *bo;
1023
 
        unsigned int i, delta;
 
1028
        unsigned int i;
1024
1029
 
1025
 
        gen7_vertex_flush(sna);
1026
 
        if (!sna->render.vertex_used)
1027
 
                return;
 
1030
        assert(sna->render.vertex_used);
1028
1031
 
1029
1032
        /* Note: we only need dword alignment (currently) */
1030
1033
 
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;
 
1035
        if (bo) {
 
1036
                if (sna->render_state.gen7.vertex_offset)
 
1037
                        gen7_vertex_flush(sna);
 
1038
 
 
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]));
 
1043
 
 
1044
                                sna->kgem.batch[sna->render.vertex_reloc[i]] =
 
1045
                                        kgem_add_reloc(&sna->kgem,
 
1046
                                                       sna->render.vertex_reloc[i],
 
1047
                                                       bo,
 
1048
                                                       I915_GEM_DOMAIN_VERTEX << 16,
 
1049
                                                       0);
 
1050
                                sna->kgem.batch[sna->render.vertex_reloc[i]+1] =
 
1051
                                        kgem_add_reloc(&sna->kgem,
 
1052
                                                       sna->render.vertex_reloc[i]+1,
 
1053
                                                       bo,
 
1054
                                                       I915_GEM_DOMAIN_VERTEX << 16,
 
1055
                                                       sna->render.vertex_used * 4 - 1);
 
1056
                                sna->render.vertex_reloc[i] = 0;
 
1057
                        }
 
1058
                }
 
1059
 
 
1060
                sna->render.vertex_used = 0;
 
1061
                sna->render.vertex_index = 0;
 
1062
                sna->render_state.gen7.vb_id = 0;
 
1063
 
 
1064
                kgem_bo_destroy(&sna->kgem, bo);
 
1065
        }
 
1066
 
 
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;
 
1074
                return 0;
 
1075
        }
 
1076
 
 
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;
1038
 
                bo = NULL;
1039
 
                sna->kgem.nbatch += sna->render.vertex_used;
1040
 
        } else {
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);
1046
 
                        return;
 
1081
                       sizeof(float)*sna->render.vertex_used);
 
1082
        }
 
1083
        sna->render.vertex_size = 64 * 1024 - 1;
 
1084
        return sna->render.vertex_size - sna->render.vertex_used;
 
1085
}
 
1086
 
 
1087
static void gen7_vertex_close(struct sna *sna)
 
1088
{
 
1089
        struct kgem_bo *bo;
 
1090
        unsigned int i, delta = 0;
 
1091
 
 
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));
 
1096
                return;
 
1097
        }
 
1098
 
 
1099
        DBG(("%s: used=%d / %d\n", __FUNCTION__,
 
1100
             sna->render.vertex_used, sna->render.vertex_size));
 
1101
 
 
1102
        bo = sna->render.vbo;
 
1103
        if (bo == NULL) {
 
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;
 
1111
                        bo = NULL;
 
1112
                        sna->kgem.nbatch += sna->render.vertex_used;
 
1113
                } else {
 
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);
 
1119
                                goto reset;
 
1120
                        }
 
1121
                        DBG(("%s: new vbo: %d\n", __FUNCTION__,
 
1122
                             sna->render.vertex_used));
1047
1123
                }
1048
 
                delta = 0;
1049
 
                DBG(("%s: new vbo: %d\n", __FUNCTION__,
1050
 
                     sna->render.vertex_used));
1051
1124
        }
1052
1125
 
1053
1126
        for (i = 0; i < ARRAY_SIZE(sna->render.vertex_reloc); i++) {
1074
1147
        if (bo)
1075
1148
                kgem_bo_destroy(&sna->kgem, bo);
1076
1149
 
 
1150
reset:
1077
1151
        sna->render.vertex_used = 0;
1078
1152
        sna->render.vertex_index = 0;
1079
1153
        sna->render_state.gen7.vb_id = 0;
 
1154
 
 
1155
        sna->render.vbo = NULL;
 
1156
        sna->render.vertices = sna->render.vertex_data;
 
1157
        sna->render.vertex_size = ARRAY_SIZE(sna->render.vertex_data);
1080
1158
}
1081
1159
 
1082
 
typedef struct gen7_surface_state_padded {
1083
 
        struct gen7_surface_state state;
1084
 
        char pad[32 - sizeof(struct gen7_surface_state)];
1085
 
} gen7_surface_state_padded;
1086
 
 
1087
1160
static void null_create(struct sna_static_stream *stream)
1088
1161
{
1089
1162
        /* A bunch of zeros useful for legacy border color and depth-stencil */
1186
1259
        uint32_t domains;
1187
1260
        uint16_t offset;
1188
1261
 
 
1262
        COMPILE_TIME_ASSERT(sizeof(struct gen7_surface_state) == 32);
 
1263
 
1189
1264
        /* After the first bind, we manage the cache domains within the batch */
1190
1265
        if (is_dst) {
1191
1266
                domains = I915_GEM_DOMAIN_RENDER << 16 |I915_GEM_DOMAIN_RENDER;
1197
1272
        if (offset)
1198
1273
                return offset;
1199
1274
 
1200
 
        offset = sna->kgem.surface - sizeof(struct gen7_surface_state_padded) / sizeof(uint32_t);
 
1275
        offset = sna->kgem.surface - sizeof(struct gen7_surface_state) / sizeof(uint32_t);
1201
1276
        offset *= sizeof(uint32_t);
1202
1277
 
1203
1278
        sna->kgem.surface -=
1204
 
                sizeof(struct gen7_surface_state_padded) / sizeof(uint32_t);
 
1279
                sizeof(struct gen7_surface_state) / sizeof(uint32_t);
1205
1280
        ss = sna->kgem.batch + sna->kgem.surface;
1206
1281
        ss[0] = (GEN7_SURFACE_2D << GEN7_SURFACE_TYPE_SHIFT |
1207
1282
                 gen7_tiling_bits(bo->tiling) |
1238
1313
                float f;
1239
1314
        } dst;
1240
1315
 
1241
 
        v = sna->render.vertex_data + sna->render.vertex_used;
 
1316
        v = sna->render.vertices + sna->render.vertex_used;
1242
1317
        sna->render.vertex_used += 9;
1243
1318
 
1244
1319
        dst.p.x = r->dst.x + r->width;
1269
1344
        } dst;
1270
1345
        float *v;
1271
1346
 
1272
 
        v = sna->render.vertex_data + sna->render.vertex_used;
 
1347
        v = sna->render.vertices + sna->render.vertex_used;
1273
1348
        sna->render.vertex_used += 9;
1274
1349
 
1275
1350
        dst.p.x = r->dst.x + r->width;
1298
1373
        } dst;
1299
1374
        float *v;
1300
1375
 
1301
 
        v = sna->render.vertex_data + sna->render.vertex_used;
 
1376
        v = sna->render.vertices + sna->render.vertex_used;
1302
1377
        sna->render.vertex_used += 9;
1303
1378
 
1304
1379
        dst.p.x = r->dst.x + r->width;
1351
1426
        w = r->width;
1352
1427
        h = r->height;
1353
1428
 
1354
 
        v = sna->render.vertex_data + sna->render.vertex_used;
 
1429
        v = sna->render.vertices + sna->render.vertex_used;
1355
1430
        sna->render.vertex_used += 15;
1356
1431
 
1357
1432
        dst.p.x = r->dst.x + r->width;
1555
1630
static bool gen7_rectangle_begin(struct sna *sna,
1556
1631
                                 const struct sna_composite_op *op)
1557
1632
{
1558
 
        int id = op->u.gen7.ve_id;
 
1633
        int id = 1 << op->u.gen7.ve_id;
1559
1634
        int ndwords;
1560
1635
 
1561
 
        ndwords = 0;
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)
1563
1638
                ndwords += 5;
1564
 
        if (sna->render_state.gen7.vertex_offset == 0)
1565
 
                ndwords += op->need_magic_ca_pass ? 60 : 6;
1566
 
        if (ndwords == 0)
1567
 
                return true;
1568
 
 
1569
1639
        if (!kgem_check_batch(&sna->kgem, ndwords))
1570
1640
                return false;
1571
1641
 
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);
1576
1644
 
 
1645
        gen7_emit_primitive(sna);
1577
1646
        return true;
1578
1647
}
1579
1648
 
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)
1581
1651
{
1582
 
        if (!kgem_check_batch(&sna->kgem, ca ? 65 : 5))
 
1652
        if (!kgem_check_batch(&sna->kgem, op->need_magic_ca_pass ? 65 : 6))
1583
1653
                return 0;
1584
1654
        if (sna->kgem.nexec > KGEM_EXEC_SIZE(&sna->kgem) - 1)
1585
1655
                return 0;
1586
 
        if (sna->kgem.nreloc > KGEM_RELOC_SIZE(&sna->kgem) - 1)
1587
 
                return 0;
1588
 
 
1589
 
        gen7_vertex_finish(sna, FALSE);
1590
 
        sna->render.vertex_index = 0;
1591
 
 
1592
 
        return  ARRAY_SIZE(sna->render.vertex_data);
 
1656
        if (sna->kgem.nreloc > KGEM_RELOC_SIZE(&sna->kgem) - 2)
 
1657
                return 0;
 
1658
 
 
1659
        if (op->need_magic_ca_pass && sna->render.vbo)
 
1660
                return 0;
 
1661
 
 
1662
        return gen7_vertex_finish(sna);
1593
1663
}
1594
1664
 
1595
1665
inline static int gen7_get_rectangles(struct sna *sna,
1596
1666
                                      const struct sna_composite_op *op,
1597
 
                                      int want)
 
1667
                                      int want,
 
1668
                                      void (*emit_state)(struct sna *sna, const struct sna_composite_op *op))
1598
1669
{
1599
1670
        int rem = vertex_space(sna);
1600
1671
 
1601
 
        if (rem < 3*op->floats_per_vertex) {
 
1672
start:
 
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);
1605
 
                if (rem == 0)
1606
 
                        return 0;
 
1676
                     __FUNCTION__, rem, op->floats_per_rect));
 
1677
                rem = gen7_get_rectangles__flush(sna, op);
 
1678
                if (unlikely(rem == 0))
 
1679
                        goto flush;
1607
1680
        }
1608
1681
 
1609
 
        if (!gen7_rectangle_begin(sna, op))
1610
 
                return 0;
 
1682
        if (unlikely(sna->render_state.gen7.vertex_offset == 0 &&
 
1683
                     !gen7_rectangle_begin(sna, op)))
 
1684
                goto flush;
1611
1685
 
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;
1614
1688
 
1615
1689
        sna->render.vertex_index += 3*want;
1616
1690
        return want;
 
1691
 
 
1692
flush:
 
1693
        if (sna->render_state.gen7.vertex_offset) {
 
1694
                gen7_vertex_flush(sna);
 
1695
                gen7_magic_ca_pass(sna, op);
 
1696
        }
 
1697
        _kgem_submit(&sna->kgem);
 
1698
        emit_state(sna, op);
 
1699
        goto start;
1617
1700
}
1618
1701
 
1619
1702
inline static uint32_t *gen7_composite_get_binding_table(struct sna *sna,
1622
1705
        uint32_t *table;
1623
1706
 
1624
1707
        sna->kgem.surface -=
1625
 
                sizeof(struct gen7_surface_state_padded) / sizeof(uint32_t);
 
1708
                sizeof(struct gen7_surface_state) / sizeof(uint32_t);
1626
1709
        /* Clear all surplus entries to zero in case of prefetch */
1627
1710
        table = memset(sna->kgem.batch + sna->kgem.surface,
1628
 
                       0, sizeof(struct gen7_surface_state_padded));
 
1711
                       0, sizeof(struct gen7_surface_state));
1629
1712
 
1630
1713
        DBG(("%s(%x)\n", __FUNCTION__, 4*sna->kgem.surface));
1631
1714
 
1651
1734
                     __FUNCTION__, sna->kgem.surface - sna->kgem.nbatch,
1652
1735
                     150, 4*8));
1653
1736
                kgem_submit(&sna->kgem);
 
1737
                _kgem_set_mode(&sna->kgem, KGEM_RENDER);
1654
1738
        }
1655
1739
 
1656
1740
        if (sna->render_state.gen7.needs_invariant)
1687
1771
                                     FALSE);
1688
1772
        }
1689
1773
 
1690
 
        if (sna->kgem.surface == offset&&
 
1774
        if (sna->kgem.surface == offset &&
1691
1775
            *(uint64_t *)(sna->kgem.batch + sna->render_state.gen7.surface_table) == *(uint64_t*)binding_table &&
1692
1776
            (op->mask.bo == NULL ||
1693
1777
             sna->kgem.batch[sna->render_state.gen7.surface_table+2] == binding_table[2])) {
1694
 
                sna->kgem.surface += sizeof(struct gen7_surface_state_padded) / sizeof(uint32_t);
 
1778
                sna->kgem.surface += sizeof(struct gen7_surface_state) / sizeof(uint32_t);
1695
1779
                offset = sna->render_state.gen7.surface_table;
1696
1780
        }
1697
1781
 
1702
1786
gen7_align_vertex(struct sna *sna, const struct sna_composite_op *op)
1703
1787
{
1704
1788
        if (op->floats_per_vertex != sna->render_state.gen7.floats_per_vertex) {
 
1789
                if (sna->render.vertex_size - sna->render.vertex_used < 2*op->floats_per_rect)
 
1790
                        gen7_vertex_finish(sna);
 
1791
 
1705
1792
                DBG(("aligning vertex: was %d, now %d floats per vertex, %d->%d\n",
1706
1793
                     sna->render_state.gen7.floats_per_vertex,
1707
1794
                     op->floats_per_vertex,
1718
1805
                          const struct sna_composite_op *op,
1719
1806
                          const struct sna_composite_rectangles *r)
1720
1807
{
1721
 
        if (!gen7_get_rectangles(sna, op, 1)) {
1722
 
                gen7_emit_composite_state(sna, op);
1723
 
                gen7_get_rectangles(sna, op, 1);
1724
 
        }
1725
 
 
 
1808
        gen7_get_rectangles(sna, op, 1, gen7_emit_composite_state);
1726
1809
        op->prim_emit(sna, op, r);
1727
1810
}
1728
1811
 
1733
1816
{
1734
1817
        struct sna_composite_rectangles r;
1735
1818
 
1736
 
        if (!gen7_get_rectangles(sna, op, 1)) {
1737
 
                gen7_emit_composite_state(sna, op);
1738
 
                gen7_get_rectangles(sna, op, 1);
1739
 
        }
 
1819
        gen7_get_rectangles(sna, op, 1, gen7_emit_composite_state);
1740
1820
 
1741
1821
        DBG(("  %s: (%d, %d), (%d, %d)\n",
1742
1822
             __FUNCTION__,
1759
1839
        DBG(("composite_boxes(%d)\n", nbox));
1760
1840
 
1761
1841
        do {
1762
 
                int nbox_this_time = gen7_get_rectangles(sna, op, nbox);
1763
 
                if (nbox_this_time == 0) {
1764
 
                        gen7_emit_composite_state(sna, op);
1765
 
                        nbox_this_time = gen7_get_rectangles(sna, op, nbox);
1766
 
                }
 
1842
                int nbox_this_time;
 
1843
 
 
1844
                nbox_this_time = gen7_get_rectangles(sna, op, nbox,
 
1845
                                                     gen7_emit_composite_state);
1767
1846
                nbox -= nbox_this_time;
 
1847
 
1768
1848
                do {
1769
1849
                        struct sna_composite_rectangles r;
1770
1850
 
1807
1887
                        blend->blend0.dest_blend_factor = dst;
1808
1888
                        blend->blend0.source_blend_factor = src;
1809
1889
                        blend->blend0.blend_func = GEN7_BLENDFUNCTION_ADD;
1810
 
                        blend->blend0.blend_enable = 1;
 
1890
                        blend->blend0.blend_enable =
 
1891
                                !(dst == GEN7_BLENDFACTOR_ZERO && src == GEN7_BLENDFACTOR_ONE);
1811
1892
 
1812
1893
                        blend->blend1.post_blend_clamp_enable = 1;
1813
1894
                        blend->blend1.pre_blend_clamp_enable = 1;
1829
1910
{
1830
1911
        struct gen7_surface_state *ss;
1831
1912
 
1832
 
        sna->kgem.surface -= sizeof(struct gen7_surface_state_padded) / sizeof(uint32_t);
 
1913
        sna->kgem.surface -= sizeof(struct gen7_surface_state) / sizeof(uint32_t);
1833
1914
 
1834
1915
        ss = memset(sna->kgem.batch + sna->kgem.surface, 0, sizeof(*ss));
1835
1916
        ss->ss0.surface_type = GEN7_SURFACE_2D;
1850
1931
}
1851
1932
 
1852
1933
static void gen7_emit_video_state(struct sna *sna,
1853
 
                                  struct sna_composite_op *op,
1854
 
                                  struct sna_video_frame *frame)
 
1934
                                  const struct sna_composite_op *op)
1855
1935
{
 
1936
        struct sna_video_frame *frame = op->priv;
1856
1937
        uint32_t src_surf_format;
1857
1938
        uint32_t src_surf_base[6];
1858
1939
        int src_width[6];
1939
2020
             REGION_EXTENTS(NULL, dstRegion)->x2,
1940
2021
             REGION_EXTENTS(NULL, dstRegion)->y2));
1941
2022
 
1942
 
        priv = sna_pixmap_force_to_gpu(pixmap);
 
2023
        priv = sna_pixmap_force_to_gpu(pixmap, MOVE_READ | MOVE_WRITE);
1943
2024
        if (priv == NULL)
1944
2025
                return FALSE;
1945
2026
 
1952
2033
        tmp.dst.format = sna_format_for_depth(pixmap->drawable.depth);
1953
2034
        tmp.dst.bo = priv->gpu_bo;
1954
2035
 
 
2036
        tmp.src.bo = frame->bo;
1955
2037
        tmp.src.filter = SAMPLER_FILTER_BILINEAR;
1956
2038
        tmp.src.repeat = SAMPLER_EXTEND_PAD;
1957
2039
 
 
2040
        tmp.mask.bo = NULL;
 
2041
 
1958
2042
        tmp.is_affine = TRUE;
1959
2043
        tmp.floats_per_vertex = 3;
 
2044
        tmp.floats_per_rect = 9;
1960
2045
 
1961
2046
        if (is_planar_fourcc(frame->id)) {
1962
2047
                tmp.u.gen7.wm_kernel = GEN7_WM_KERNEL_VIDEO_PLANAR;
1967
2052
        }
1968
2053
        tmp.u.gen7.nr_inputs = 1;
1969
2054
        tmp.u.gen7.ve_id = 1;
 
2055
        tmp.priv = frame;
1970
2056
 
1971
 
        if (!kgem_check_bo(&sna->kgem, tmp.dst.bo, frame->bo, NULL))
 
2057
        kgem_set_mode(&sna->kgem, KGEM_RENDER);
 
2058
        if (!kgem_check_bo(&sna->kgem, tmp.dst.bo, frame->bo, NULL)) {
1972
2059
                kgem_submit(&sna->kgem);
1973
 
 
1974
 
        if (kgem_bo_is_dirty(frame->bo))
1975
 
                kgem_emit_flush(&sna->kgem);
1976
 
 
1977
 
        gen7_emit_video_state(sna, &tmp, frame);
 
2060
                assert(kgem_check_bo(&sna->kgem, tmp.dst.bo, frame->bo, NULL));
 
2061
                _kgem_set_mode(&sna->kgem, KGEM_RENDER);
 
2062
        }
 
2063
 
 
2064
        gen7_emit_video_state(sna, &tmp);
1978
2065
        gen7_align_vertex(sna, &tmp);
1979
2066
 
1980
2067
        /* Set up the offset for translating from the given region (in screen
2005
2092
                r.y1 = box->y1 + pix_yoff;
2006
2093
                r.y2 = box->y2 + pix_yoff;
2007
2094
 
2008
 
                if (!gen7_get_rectangles(sna, &tmp, 1)) {
2009
 
                        gen7_emit_video_state(sna, &tmp, frame);
2010
 
                        gen7_get_rectangles(sna, &tmp, 1);
2011
 
                }
 
2095
                gen7_get_rectangles(sna, &tmp, 1, gen7_emit_video_state);
2012
2096
 
2013
2097
                OUT_VERTEX(r.x2, r.y2);
2014
2098
                OUT_VERTEX_F((box->x2 - dxo) * src_scale_x);
2022
2106
                OUT_VERTEX_F((box->x1 - dxo) * src_scale_x);
2023
2107
                OUT_VERTEX_F((box->y1 - dyo) * src_scale_y);
2024
2108
 
2025
 
                sna_damage_add_box(&priv->gpu_damage, &r);
2026
 
                sna_damage_subtract_box(&priv->cpu_damage, &r);
 
2109
                if (!DAMAGE_IS_ALL(priv->gpu_damage)) {
 
2110
                        sna_damage_add_box(&priv->gpu_damage, &r);
 
2111
                        sna_damage_subtract_box(&priv->cpu_damage, &r);
 
2112
                }
2027
2113
                box++;
2028
2114
        }
 
2115
        priv->clear = false;
2029
2116
 
2030
2117
        gen7_vertex_flush(sna);
2031
 
        _kgem_set_mode(&sna->kgem, KGEM_RENDER);
2032
2118
        return TRUE;
2033
2119
}
2034
2120
 
2080
2166
                return sna_render_picture_fixup(sna, picture, channel,
2081
2167
                                                x, y, w, h, dst_x, dst_y);
2082
2168
 
 
2169
        if (picture->alphaMap) {
 
2170
                DBG(("%s -- fallback, alphamap\n", __FUNCTION__));
 
2171
                return sna_render_picture_fixup(sna, picture, channel,
 
2172
                                                x, y, w, h, dst_x, dst_y);
 
2173
        }
 
2174
 
2083
2175
        if (!gen7_check_repeat(picture))
2084
2176
                return sna_render_picture_fixup(sna, picture, channel,
2085
2177
                                                x, y, w, h, dst_x, dst_y);
2109
2201
                channel->transform = picture->transform;
2110
2202
 
2111
2203
        channel->card_format = gen7_get_card_format(picture->format);
2112
 
        if (channel->card_format == (unsigned)-1)
 
2204
        if (channel->card_format == -1)
2113
2205
                return sna_render_picture_convert(sna, picture, channel, pixmap,
2114
2206
                                                  x, y, w, h, dst_x, dst_y);
2115
2207
 
2116
 
        if (pixmap->drawable.width > GEN7_MAX_SIZE ||
2117
 
            pixmap->drawable.height > GEN7_MAX_SIZE) {
 
2208
        if (too_large(pixmap->drawable.width, pixmap->drawable.height)) {
2118
2209
                DBG(("%s: extracting from pixmap %dx%d\n", __FUNCTION__,
2119
2210
                     pixmap->drawable.width, pixmap->drawable.height));
2120
2211
                return sna_render_picture_extract(sna, picture, channel,
2137
2228
static void gen7_render_composite_done(struct sna *sna,
2138
2229
                                       const struct sna_composite_op *op)
2139
2230
{
2140
 
        gen7_vertex_flush(sna);
2141
 
        _kgem_set_mode(&sna->kgem, KGEM_RENDER);
2142
 
        sna->render.op = NULL;
2143
 
 
2144
 
        sna_render_composite_redirect_done(sna, op);
2145
 
 
 
2231
        if (sna->render_state.gen7.vertex_offset) {
 
2232
                gen7_vertex_flush(sna);
 
2233
                gen7_magic_ca_pass(sna, op);
 
2234
        }
 
2235
 
 
2236
        if (op->mask.bo)
 
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);
2148
 
        if (op->mask.bo)
2149
 
                kgem_bo_destroy(&sna->kgem, op->mask.bo);
 
2240
 
 
2241
        sna_render_composite_redirect_done(sna, op);
2150
2242
}
2151
2243
 
2152
2244
static Bool
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)
2154
2246
{
2155
2247
        struct sna_pixmap *priv;
2156
2248
 
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))
2160
2250
                return FALSE;
2161
 
        }
2162
2251
 
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;
 
2256
 
 
2257
        op->dst.bo = NULL;
2167
2258
        priv = sna_pixmap(op->dst.pixmap);
2168
 
 
2169
 
        op->dst.bo = NULL;
2170
 
        if (priv && priv->gpu_bo == NULL) {
 
2259
        if (priv && priv->gpu_bo == NULL &&
 
2260
            I915_TILING_NONE == kgem_choose_tiling(&sna->kgem,
 
2261
                                                   I915_TILING_X,
 
2262
                                                   op->dst.width,
 
2263
                                                   op->dst.height,
 
2264
                                                   op->dst.pixmap->drawable.bitsPerPixel)) {
2171
2265
                op->dst.bo = priv->cpu_bo;
2172
2266
                op->damage = &priv->cpu_damage;
2173
2267
        }
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)
2177
2271
                        return FALSE;
2178
2272
 
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))
2183
 
                        op->damage = NULL;
2184
2275
        }
 
2276
        if (sna_damage_is_all(op->damage, op->dst.width, op->dst.height))
 
2277
                op->damage = NULL;
2185
2278
 
2186
2279
        get_drawable_deltas(dst->pDrawable, op->dst.pixmap,
2187
2280
                            &op->dst.x, &op->dst.y);
2196
2289
}
2197
2290
 
2198
2291
static Bool
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)
2200
2295
{
2201
 
        if (sna->kgem.mode == KGEM_BLT) {
 
2296
        if (sna->kgem.ring != KGEM_RENDER) {
2202
2297
                DBG(("%s: already performing BLT\n", __FUNCTION__));
2203
2298
                return TRUE;
2204
2299
        }
2205
2300
 
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));
2209
2304
                return TRUE;
2210
2305
        }
2211
2306
 
2212
 
        return FALSE;
 
2307
        if (too_large(dst->pDrawable->width, dst->pDrawable->height)) {
 
2308
                DBG(("%s: dst too large for 3D pipe (%d, %d)\n",
 
2309
                     __FUNCTION__,
 
2310
                     dst->pDrawable->width, dst->pDrawable->height));
 
2311
                return TRUE;
 
2312
        }
 
2313
 
 
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",
 
2317
                     __FUNCTION__,
 
2318
                     src->pDrawable->width, src->pDrawable->height));
 
2319
                return TRUE;
 
2320
        }
 
2321
 
 
2322
        return FALSE;
 
2323
}
 
2324
 
 
2325
static bool
 
2326
is_gradient(PicturePtr picture)
 
2327
{
 
2328
        if (picture->pDrawable)
 
2329
                return FALSE;
 
2330
 
 
2331
        return picture->pSourcePict->type != SourcePictTypeSolidFill;
 
2332
}
 
2333
 
 
2334
static bool
 
2335
has_alphamap(PicturePtr p)
 
2336
{
 
2337
        return p->alphaMap != NULL;
 
2338
}
 
2339
 
 
2340
static bool
 
2341
untransformed(PicturePtr p)
 
2342
{
 
2343
        return !p->transform || pixman_transform_is_int_translate(p->transform);
 
2344
}
 
2345
 
 
2346
static bool
 
2347
need_upload(PicturePtr p)
 
2348
{
 
2349
        return p->pDrawable && unattached(p->pDrawable) && untransformed(p);
 
2350
}
 
2351
 
 
2352
static bool
 
2353
source_fallback(PicturePtr p)
 
2354
{
 
2355
        if (sna_picture_is_solid(p, NULL))
 
2356
                return false;
 
2357
 
 
2358
        return (has_alphamap(p) ||
 
2359
                is_gradient(p) ||
 
2360
                !gen7_check_filter(p) ||
 
2361
                !gen7_check_repeat(p) ||
 
2362
                !gen7_check_format(p->format) ||
 
2363
                need_upload(p));
 
2364
}
 
2365
 
 
2366
static bool
 
2367
gen7_composite_fallback(struct sna *sna,
 
2368
                        PicturePtr src,
 
2369
                        PicturePtr mask,
 
2370
                        PicturePtr dst)
 
2371
{
 
2372
        struct sna_pixmap *priv;
 
2373
        PixmapPtr src_pixmap;
 
2374
        PixmapPtr mask_pixmap;
 
2375
        PixmapPtr dst_pixmap;
 
2376
 
 
2377
        if (!gen7_check_dst_format(dst->format)) {
 
2378
                DBG(("%s: unknown destination format: %d\n",
 
2379
                     __FUNCTION__, dst->format));
 
2380
                return TRUE;
 
2381
        }
 
2382
 
 
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;
 
2386
 
 
2387
        /* If we are using the destination as a source and need to
 
2388
         * readback in order to upload the source, do it all
 
2389
         * on the cpu.
 
2390
         */
 
2391
        if (src_pixmap == dst_pixmap && source_fallback(src)) {
 
2392
                DBG(("%s: src is dst and will fallback\n",__FUNCTION__));
 
2393
                return TRUE;
 
2394
        }
 
2395
        if (mask_pixmap == dst_pixmap && source_fallback(mask)) {
 
2396
                DBG(("%s: mask is dst and will fallback\n",__FUNCTION__));
 
2397
                return TRUE;
 
2398
        }
 
2399
 
 
2400
        /* If anything is on the GPU, push everything out to the GPU */
 
2401
        priv = sna_pixmap(dst_pixmap);
 
2402
        if (priv &&
 
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",
 
2406
                     __FUNCTION__));
 
2407
                return FALSE;
 
2408
        }
 
2409
 
 
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",
 
2414
                             __FUNCTION__));
 
2415
                        return FALSE;
 
2416
                }
 
2417
        }
 
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",
 
2422
                             __FUNCTION__));
 
2423
                        return FALSE;
 
2424
                }
 
2425
        }
 
2426
 
 
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.
 
2430
         */
 
2431
        if (source_fallback(src)) {
 
2432
                DBG(("%s: dst is on the CPU and src will fallback\n",
 
2433
                     __FUNCTION__));
 
2434
                return TRUE;
 
2435
        }
 
2436
 
 
2437
        if (mask && source_fallback(mask)) {
 
2438
                DBG(("%s: dst is on the CPU and mask will fallback\n",
 
2439
                     __FUNCTION__));
 
2440
                return TRUE;
 
2441
        }
 
2442
 
 
2443
        DBG(("%s: dst is not on the GPU and the operation should not fallback\n",
 
2444
             __FUNCTION__));
 
2445
        return FALSE;
 
2446
}
 
2447
 
 
2448
static int
 
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)
 
2452
{
 
2453
        uint32_t color;
 
2454
 
 
2455
        if (src_x != msk_x || src_y != msk_y)
 
2456
                return FALSE;
 
2457
 
 
2458
        if (src == mask) {
 
2459
                DBG(("%s: mask is source\n", __FUNCTION__));
 
2460
                *mc = *sc;
 
2461
                mc->bo = kgem_bo_reference(mc->bo);
 
2462
                return TRUE;
 
2463
        }
 
2464
 
 
2465
        if (sna_picture_is_solid(mask, &color))
 
2466
                return gen7_composite_solid_init(sna, mc, color);
 
2467
 
 
2468
        if (sc->is_solid)
 
2469
                return FALSE;
 
2470
 
 
2471
        if (src->pDrawable == NULL || mask->pDrawable != src->pDrawable)
 
2472
                return FALSE;
 
2473
 
 
2474
        DBG(("%s: mask reuses source drawable\n", __FUNCTION__));
 
2475
 
 
2476
        if (!sna_transform_equal(src->transform, mask->transform))
 
2477
                return FALSE;
 
2478
 
 
2479
        if (!sna_picture_alphamap_equal(src, mask))
 
2480
                return FALSE;
 
2481
 
 
2482
        if (!gen7_check_repeat(mask))
 
2483
                return FALSE;
 
2484
 
 
2485
        if (!gen7_check_filter(mask))
 
2486
                return FALSE;
 
2487
 
 
2488
        if (!gen7_check_format(mask->format))
 
2489
                return FALSE;
 
2490
 
 
2491
        DBG(("%s: reusing source channel for mask with a twist\n",
 
2492
             __FUNCTION__));
 
2493
 
 
2494
        *mc = *sc;
 
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);
 
2500
        return TRUE;
2213
2501
}
2214
2502
 
2215
2503
static Bool
2239
2527
#endif
2240
2528
 
2241
2529
        DBG(("%s: %dx%d, current mode=%d\n", __FUNCTION__,
2242
 
             width, height, sna->kgem.mode));
 
2530
             width, height, sna->kgem.ring));
2243
2531
 
2244
2532
        if (mask == NULL &&
2245
 
            try_blt(sna, width, height) &&
 
2533
            try_blt(sna, dst, src, width, height) &&
2246
2534
            sna_blt_composite(sna, op,
2247
2535
                              src, dst,
2248
2536
                              src_x, src_y,
2250
2538
                              width, height, tmp))
2251
2539
                return TRUE;
2252
2540
 
 
2541
        if (gen7_composite_fallback(sna, src, mask, dst))
 
2542
                return FALSE;
 
2543
 
2253
2544
        if (need_tiling(sna, width, height))
2254
2545
                return sna_tiling_composite(op, src, mask, dst,
2255
2546
                                            src_x, src_y,
2259
2550
                                            tmp);
2260
2551
 
2261
2552
        tmp->op = op;
2262
 
        if (!gen7_composite_set_target(tmp, dst))
 
2553
        if (!gen7_composite_set_target(sna, tmp, dst))
2263
2554
                return FALSE;
 
2555
 
 
2556
        if (mask == NULL && sna->kgem.mode == KGEM_BLT &&
 
2557
            sna_blt_composite(sna, op,
 
2558
                              src, dst,
 
2559
                              src_x, src_y,
 
2560
                              dst_x, dst_y,
 
2561
                              width, height, tmp))
 
2562
                return TRUE;
 
2563
 
2264
2564
        sna_render_reduce_damage(tmp, dst_x, dst_y, width, height);
2265
2565
 
2266
 
        if (tmp->dst.width > GEN7_MAX_SIZE || tmp->dst.height > GEN7_MAX_SIZE) {
 
2566
        if (too_large(tmp->dst.width, tmp->dst.height)) {
2267
2567
                if (!sna_render_composite_redirect(sna, tmp,
2268
2568
                                                   dst_x, dst_y, width, height))
2269
2569
                        return FALSE;
2282
2582
                break;
2283
2583
        }
2284
2584
 
 
2585
        /* Did we just switch rings to prepare the source? */
 
2586
        if (sna->kgem.ring == KGEM_BLT && mask == NULL &&
 
2587
            sna_blt_composite(sna, op,
 
2588
                              src, dst,
 
2589
                              src_x, src_y,
 
2590
                              dst_x, dst_y,
 
2591
                              width, height, tmp)) {
 
2592
                if (tmp->redirect.real_bo)
 
2593
                        kgem_bo_destroy(&sna->kgem, tmp->redirect.real_bo);
 
2594
                kgem_bo_destroy(&sna->kgem, tmp->src.bo);
 
2595
                return TRUE;
 
2596
        }
 
2597
 
2285
2598
        tmp->is_affine = tmp->src.is_affine;
2286
2599
        tmp->has_component_alpha = FALSE;
2287
2600
        tmp->need_magic_ca_pass = FALSE;
2309
2622
                        }
2310
2623
                }
2311
2624
 
2312
 
                switch (gen7_composite_picture(sna, mask, &tmp->mask,
2313
 
                                               msk_x, msk_y,
2314
 
                                               width, height,
2315
 
                                               dst_x, dst_y)) {
2316
 
                case -1:
2317
 
                        goto cleanup_src;
2318
 
                case 0:
2319
 
                        gen7_composite_solid_init(sna, &tmp->mask, 0);
2320
 
                case 1:
2321
 
                        gen7_composite_channel_convert(&tmp->mask);
2322
 
                        break;
 
2625
                if (!reuse_source(sna,
 
2626
                                  src, &tmp->src, src_x, src_y,
 
2627
                                  mask, &tmp->mask, msk_x, msk_y)) {
 
2628
                        switch (gen7_composite_picture(sna, mask, &tmp->mask,
 
2629
                                                       msk_x, msk_y,
 
2630
                                                       width, height,
 
2631
                                                       dst_x, dst_y)) {
 
2632
                        case -1:
 
2633
                                goto cleanup_src;
 
2634
                        case 0:
 
2635
                                gen7_composite_solid_init(sna, &tmp->mask, 0);
 
2636
                        case 1:
 
2637
                                gen7_composite_channel_convert(&tmp->mask);
 
2638
                                break;
 
2639
                        }
2323
2640
                }
2324
2641
 
2325
2642
                tmp->is_affine &= tmp->mask.is_affine;
2338
2655
 
2339
2656
                tmp->floats_per_vertex = 3 + !tmp->is_affine;
2340
2657
        }
 
2658
        tmp->floats_per_rect = 3 * tmp->floats_per_vertex;
2341
2659
 
2342
2660
        tmp->u.gen7.wm_kernel =
2343
2661
                gen7_choose_composite_kernel(tmp->op,
2353
2671
        tmp->boxes = gen7_render_composite_boxes;
2354
2672
        tmp->done  = gen7_render_composite_done;
2355
2673
 
 
2674
        kgem_set_mode(&sna->kgem, KGEM_RENDER);
2356
2675
        if (!kgem_check_bo(&sna->kgem,
2357
2676
                           tmp->dst.bo, tmp->src.bo, tmp->mask.bo,
2358
 
                           NULL))
 
2677
                           NULL)) {
2359
2678
                kgem_submit(&sna->kgem);
2360
 
 
2361
 
        if (kgem_bo_is_dirty(tmp->src.bo) || kgem_bo_is_dirty(tmp->mask.bo))
2362
 
                kgem_emit_flush(&sna->kgem);
 
2679
                if (!kgem_check_bo(&sna->kgem,
 
2680
                                   tmp->dst.bo, tmp->src.bo, tmp->mask.bo,
 
2681
                                   NULL))
 
2682
                        goto cleanup_mask;
 
2683
                _kgem_set_mode(&sna->kgem, KGEM_RENDER);
 
2684
        }
2363
2685
 
2364
2686
        gen7_emit_composite_state(sna, tmp);
2365
2687
        gen7_align_vertex(sna, tmp);
2366
 
 
2367
 
        sna->render.op = tmp;
2368
2688
        return TRUE;
2369
2689
 
 
2690
cleanup_mask:
 
2691
        if (tmp->mask.bo)
 
2692
                kgem_bo_destroy(&sna->kgem, tmp->mask.bo);
2370
2693
cleanup_src:
2371
2694
        if (tmp->src.bo)
2372
2695
                kgem_bo_destroy(&sna->kgem, tmp->src.bo);
2376
2699
        return FALSE;
2377
2700
}
2378
2701
 
 
2702
/* A poor man's span interface. But better than nothing? */
 
2703
#if !NO_COMPOSITE_SPANS
 
2704
static Bool
 
2705
gen7_composite_alpha_gradient_init(struct sna *sna,
 
2706
                                   struct sna_composite_channel *channel)
 
2707
{
 
2708
        DBG(("%s\n", __FUNCTION__));
 
2709
 
 
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;
 
2718
 
 
2719
        channel->bo = sna_render_get_alpha_gradient(sna);
 
2720
 
 
2721
        channel->scale[0]  = channel->scale[1]  = 1;
 
2722
        channel->offset[0] = channel->offset[1] = 0;
 
2723
        return channel->bo != NULL;
 
2724
}
 
2725
 
 
2726
inline static void
 
2727
gen7_emit_composite_texcoord(struct sna *sna,
 
2728
                             const struct sna_composite_channel *channel,
 
2729
                             int16_t x, int16_t y)
 
2730
{
 
2731
        float t[3];
 
2732
 
 
2733
        if (channel->is_affine) {
 
2734
                sna_get_transformed_coordinates(x + channel->offset[0],
 
2735
                                                y + channel->offset[1],
 
2736
                                                channel->transform,
 
2737
                                                &t[0], &t[1]);
 
2738
                OUT_VERTEX_F(t[0] * channel->scale[0]);
 
2739
                OUT_VERTEX_F(t[1] * channel->scale[1]);
 
2740
        } else {
 
2741
                t[0] = t[1] = 0; t[2] = 1;
 
2742
                sna_get_transformed_coordinates_3d(x + channel->offset[0],
 
2743
                                                   y + channel->offset[1],
 
2744
                                                   channel->transform,
 
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]);
 
2748
                OUT_VERTEX_F(t[2]);
 
2749
        }
 
2750
}
 
2751
 
 
2752
inline static void
 
2753
gen7_emit_composite_texcoord_affine(struct sna *sna,
 
2754
                                    const struct sna_composite_channel *channel,
 
2755
                                    int16_t x, int16_t y)
 
2756
{
 
2757
        float t[2];
 
2758
 
 
2759
        sna_get_transformed_coordinates(x + channel->offset[0],
 
2760
                                        y + channel->offset[1],
 
2761
                                        channel->transform,
 
2762
                                        &t[0], &t[1]);
 
2763
        OUT_VERTEX_F(t[0] * channel->scale[0]);
 
2764
        OUT_VERTEX_F(t[1] * channel->scale[1]);
 
2765
}
 
2766
 
 
2767
inline static void
 
2768
gen7_emit_composite_spans_vertex(struct sna *sna,
 
2769
                                 const struct sna_composite_spans_op *op,
 
2770
                                 int16_t x, int16_t y)
 
2771
{
 
2772
        OUT_VERTEX(x, y);
 
2773
        gen7_emit_composite_texcoord(sna, &op->base.src, x, y);
 
2774
}
 
2775
 
 
2776
fastcall static void
 
2777
gen7_emit_composite_spans_primitive(struct sna *sna,
 
2778
                                    const struct sna_composite_spans_op *op,
 
2779
                                    const BoxRec *box,
 
2780
                                    float opacity)
 
2781
{
 
2782
        gen7_emit_composite_spans_vertex(sna, op, box->x2, box->y2);
 
2783
        OUT_VERTEX_F(opacity);
 
2784
        OUT_VERTEX_F(1);
 
2785
        if (!op->base.is_affine)
 
2786
                OUT_VERTEX_F(1);
 
2787
 
 
2788
        gen7_emit_composite_spans_vertex(sna, op, box->x1, box->y2);
 
2789
        OUT_VERTEX_F(opacity);
 
2790
        OUT_VERTEX_F(1);
 
2791
        if (!op->base.is_affine)
 
2792
                OUT_VERTEX_F(1);
 
2793
 
 
2794
        gen7_emit_composite_spans_vertex(sna, op, box->x1, box->y1);
 
2795
        OUT_VERTEX_F(opacity);
 
2796
        OUT_VERTEX_F(0);
 
2797
        if (!op->base.is_affine)
 
2798
                OUT_VERTEX_F(1);
 
2799
}
 
2800
 
 
2801
fastcall static void
 
2802
gen7_emit_composite_spans_solid(struct sna *sna,
 
2803
                                const struct sna_composite_spans_op *op,
 
2804
                                const BoxRec *box,
 
2805
                                float opacity)
 
2806
{
 
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);
 
2810
 
 
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);
 
2814
 
 
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);
 
2818
}
 
2819
 
 
2820
fastcall static void
 
2821
gen7_emit_composite_spans_identity(struct sna *sna,
 
2822
                                   const struct sna_composite_spans_op *op,
 
2823
                                   const BoxRec *box,
 
2824
                                   float opacity)
 
2825
{
 
2826
        float *v;
 
2827
        union {
 
2828
                struct sna_coordinate p;
 
2829
                float f;
 
2830
        } dst;
 
2831
 
 
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];
 
2836
 
 
2837
        v = sna->render.vertices + sna->render.vertex_used;
 
2838
        sna->render.vertex_used += 3*5;
 
2839
 
 
2840
        dst.p.x = box->x2;
 
2841
        dst.p.y = box->y2;
 
2842
        v[0] = dst.f;
 
2843
        v[1] = (box->x2 + tx) * sx;
 
2844
        v[7] = v[2] = (box->y2 + ty) * sy;
 
2845
        v[13] = v[8] = v[3] = opacity;
 
2846
        v[9] = v[4] = 1;
 
2847
 
 
2848
        dst.p.x = box->x1;
 
2849
        v[5] = dst.f;
 
2850
        v[11] = v[6] = (box->x1 + tx) * sx;
 
2851
 
 
2852
        dst.p.y = box->y1;
 
2853
        v[10] = dst.f;
 
2854
        v[12] = (box->y1 + ty) * sy;
 
2855
        v[14] = 0;
 
2856
}
 
2857
 
 
2858
fastcall static void
 
2859
gen7_emit_composite_spans_simple(struct sna *sna,
 
2860
                                 const struct sna_composite_spans_op *op,
 
2861
                                 const BoxRec *box,
 
2862
                                 float opacity)
 
2863
{
 
2864
        float *v;
 
2865
        union {
 
2866
                struct sna_coordinate p;
 
2867
                float f;
 
2868
        } dst;
 
2869
 
 
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];
 
2878
 
 
2879
        v = sna->render.vertices + sna->render.vertex_used;
 
2880
        sna->render.vertex_used += 3*5;
 
2881
 
 
2882
        dst.p.x = box->x2;
 
2883
        dst.p.y = box->y2;
 
2884
        v[0] = dst.f;
 
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;
 
2888
        v[9] = v[4] = 1;
 
2889
 
 
2890
        dst.p.x = box->x1;
 
2891
        v[5] = dst.f;
 
2892
        v[11] = v[6] = ((box->x1 + tx) * xx + x0) * sx;
 
2893
 
 
2894
        dst.p.y = box->y1;
 
2895
        v[10] = dst.f;
 
2896
        v[12] = ((box->y1 + ty) * yy + y0) * sy;
 
2897
        v[14] = 0;
 
2898
}
 
2899
 
 
2900
fastcall static void
 
2901
gen7_emit_composite_spans_affine(struct sna *sna,
 
2902
                                 const struct sna_composite_spans_op *op,
 
2903
                                 const BoxRec *box,
 
2904
                                 float opacity)
 
2905
{
 
2906
        OUT_VERTEX(box->x2, box->y2);
 
2907
        gen7_emit_composite_texcoord_affine(sna, &op->base.src,
 
2908
                                            box->x2, box->y2);
 
2909
        OUT_VERTEX_F(opacity);
 
2910
        OUT_VERTEX_F(1);
 
2911
 
 
2912
        OUT_VERTEX(box->x1, box->y2);
 
2913
        gen7_emit_composite_texcoord_affine(sna, &op->base.src,
 
2914
                                            box->x1, box->y2);
 
2915
        OUT_VERTEX_F(opacity);
 
2916
        OUT_VERTEX_F(1);
 
2917
 
 
2918
        OUT_VERTEX(box->x1, box->y1);
 
2919
        gen7_emit_composite_texcoord_affine(sna, &op->base.src,
 
2920
                                            box->x1, box->y1);
 
2921
        OUT_VERTEX_F(opacity);
 
2922
        OUT_VERTEX_F(0);
 
2923
}
 
2924
 
 
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)
 
2929
{
 
2930
        DBG(("%s: src=+(%d, %d), opacity=%f, dst=+(%d, %d), box=(%d, %d) x (%d, %d)\n",
 
2931
             __FUNCTION__,
 
2932
             op->base.src.offset[0], op->base.src.offset[1],
 
2933
             opacity,
 
2934
             op->base.dst.x, op->base.dst.y,
 
2935
             box->x1, box->y1,
 
2936
             box->x2 - box->x1,
 
2937
             box->y2 - box->y1));
 
2938
 
 
2939
        gen7_get_rectangles(sna, &op->base, 1, gen7_emit_composite_state);
 
2940
        op->prim_emit(sna, op, box, opacity);
 
2941
}
 
2942
 
 
2943
static void
 
2944
gen7_render_composite_spans_boxes(struct sna *sna,
 
2945
                                  const struct sna_composite_spans_op *op,
 
2946
                                  const BoxRec *box, int nbox,
 
2947
                                  float opacity)
 
2948
{
 
2949
        DBG(("%s: nbox=%d, src=+(%d, %d), opacity=%f, dst=+(%d, %d)\n",
 
2950
             __FUNCTION__, nbox,
 
2951
             op->base.src.offset[0], op->base.src.offset[1],
 
2952
             opacity,
 
2953
             op->base.dst.x, op->base.dst.y));
 
2954
 
 
2955
        do {
 
2956
                int nbox_this_time;
 
2957
 
 
2958
                nbox_this_time = gen7_get_rectangles(sna, &op->base, nbox,
 
2959
                                                     gen7_emit_composite_state);
 
2960
                nbox -= nbox_this_time;
 
2961
 
 
2962
                do {
 
2963
                        DBG(("  %s: (%d, %d) x (%d, %d)\n", __FUNCTION__,
 
2964
                             box->x1, box->y1,
 
2965
                             box->x2 - box->x1,
 
2966
                             box->y2 - box->y1));
 
2967
 
 
2968
                        op->prim_emit(sna, op, box++, opacity);
 
2969
                } while (--nbox_this_time);
 
2970
        } while (nbox);
 
2971
}
 
2972
 
 
2973
fastcall static void
 
2974
gen7_render_composite_spans_done(struct sna *sna,
 
2975
                                 const struct sna_composite_spans_op *op)
 
2976
{
 
2977
        if (sna->render_state.gen7.vertex_offset)
 
2978
                gen7_vertex_flush(sna);
 
2979
 
 
2980
        DBG(("%s()\n", __FUNCTION__));
 
2981
 
 
2982
        if (op->base.src.bo)
 
2983
                kgem_bo_destroy(&sna->kgem, op->base.src.bo);
 
2984
 
 
2985
        sna_render_composite_redirect_done(sna, &op->base);
 
2986
}
 
2987
 
 
2988
static Bool
 
2989
gen7_render_composite_spans(struct sna *sna,
 
2990
                            uint8_t op,
 
2991
                            PicturePtr src,
 
2992
                            PicturePtr dst,
 
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,
 
2996
                            unsigned flags,
 
2997
                            struct sna_composite_spans_op *tmp)
 
2998
{
 
2999
        DBG(("%s: %dx%d with flags=%x, current mode=%d\n", __FUNCTION__,
 
3000
             width, height, flags, sna->kgem.ring));
 
3001
 
 
3002
        if ((flags & COMPOSITE_SPANS_RECTILINEAR) == 0)
 
3003
                return FALSE;
 
3004
 
 
3005
        if (op >= ARRAY_SIZE(gen7_blend_op))
 
3006
                return FALSE;
 
3007
 
 
3008
        if (need_tiling(sna, width, height))
 
3009
                return FALSE;
 
3010
 
 
3011
        if (gen7_composite_fallback(sna, src, NULL, dst))
 
3012
                return FALSE;
 
3013
 
 
3014
        tmp->base.op = op;
 
3015
        if (!gen7_composite_set_target(sna, &tmp->base, dst))
 
3016
                return FALSE;
 
3017
        sna_render_reduce_damage(&tmp->base, dst_x, dst_y, width, height);
 
3018
 
 
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))
 
3022
                        return FALSE;
 
3023
        }
 
3024
 
 
3025
        switch (gen7_composite_picture(sna, src, &tmp->base.src,
 
3026
                                       src_x, src_y,
 
3027
                                       width, height,
 
3028
                                       dst_x, dst_y)) {
 
3029
        case -1:
 
3030
                goto cleanup_dst;
 
3031
        case 0:
 
3032
                gen7_composite_solid_init(sna, &tmp->base.src, 0);
 
3033
        case 1:
 
3034
                gen7_composite_channel_convert(&tmp->base.src);
 
3035
                break;
 
3036
        }
 
3037
 
 
3038
        tmp->base.mask.bo = NULL;
 
3039
 
 
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;
 
3043
 
 
3044
        gen7_composite_alpha_gradient_init(sna, &tmp->base.mask);
 
3045
 
 
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;
 
3057
                } else
 
3058
                        tmp->prim_emit = gen7_emit_composite_spans_affine;
 
3059
        }
 
3060
        tmp->base.floats_per_vertex = 5 + 2*!tmp->base.is_affine;
 
3061
        tmp->base.floats_per_rect = 3 * tmp->base.floats_per_vertex;
 
3062
 
 
3063
        tmp->base.u.gen7.wm_kernel =
 
3064
                gen7_choose_composite_kernel(tmp->base.op,
 
3065
                                             TRUE, FALSE,
 
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;
 
3070
 
 
3071
        tmp->box   = gen7_render_composite_spans_box;
 
3072
        tmp->boxes = gen7_render_composite_spans_boxes;
 
3073
        tmp->done  = gen7_render_composite_spans_done;
 
3074
 
 
3075
        kgem_set_mode(&sna->kgem, KGEM_RENDER);
 
3076
        if (!kgem_check_bo(&sna->kgem,
 
3077
                           tmp->base.dst.bo, tmp->base.src.bo,
 
3078
                           NULL)) {
 
3079
                kgem_submit(&sna->kgem);
 
3080
                if (!kgem_check_bo(&sna->kgem,
 
3081
                                   tmp->base.dst.bo, tmp->base.src.bo,
 
3082
                                   NULL))
 
3083
                        goto cleanup_src;
 
3084
                _kgem_set_mode(&sna->kgem, KGEM_RENDER);
 
3085
        }
 
3086
 
 
3087
        gen7_emit_composite_state(sna, &tmp->base);
 
3088
        gen7_align_vertex(sna, &tmp->base);
 
3089
        return TRUE;
 
3090
 
 
3091
cleanup_src:
 
3092
        if (tmp->base.src.bo)
 
3093
                kgem_bo_destroy(&sna->kgem, tmp->base.src.bo);
 
3094
cleanup_dst:
 
3095
        if (tmp->base.redirect.real_bo)
 
3096
                kgem_bo_destroy(&sna->kgem, tmp->base.dst.bo);
 
3097
        return FALSE;
 
3098
}
 
3099
#endif
 
3100
 
2379
3101
static void
2380
3102
gen7_emit_copy_state(struct sna *sna,
2381
3103
                     const struct sna_composite_op *op)
2390
3112
        binding_table[0] =
2391
3113
                gen7_bind_bo(sna,
2392
3114
                             op->dst.bo, op->dst.width, op->dst.height,
2393
 
                             gen7_get_dest_format_for_depth(op->dst.pixmap->drawable.depth),
 
3115
                             gen7_get_dest_format(op->dst.format),
2394
3116
                             TRUE);
2395
3117
        binding_table[1] =
2396
3118
                gen7_bind_bo(sna,
2400
3122
 
2401
3123
        if (sna->kgem.surface == offset &&
2402
3124
            *(uint64_t *)(sna->kgem.batch + sna->render_state.gen7.surface_table) == *(uint64_t*)binding_table) {
2403
 
                sna->kgem.surface += sizeof(struct gen7_surface_state_padded) / sizeof(uint32_t);
 
3125
                sna->kgem.surface += sizeof(struct gen7_surface_state) / sizeof(uint32_t);
2404
3126
                offset = sna->render_state.gen7.surface_table;
2405
3127
        }
2406
3128
 
2407
3129
        gen7_emit_state(sna, op, offset);
2408
3130
}
2409
3131
 
 
3132
static inline bool untiled_tlb_miss(struct kgem_bo *bo)
 
3133
{
 
3134
        return bo->tiling == I915_TILING_NONE && bo->pitch >= 4096;
 
3135
}
 
3136
 
 
3137
static bool prefer_blt_bo(struct sna *sna,
 
3138
                          PixmapPtr pixmap,
 
3139
                          struct kgem_bo *bo)
 
3140
{
 
3141
        return (too_large(pixmap->drawable.width, pixmap->drawable.height) ||
 
3142
                untiled_tlb_miss(bo)) &&
 
3143
                kgem_bo_can_blt(&sna->kgem, bo);
 
3144
}
 
3145
 
 
3146
static inline bool prefer_blt_copy(struct sna *sna,
 
3147
                                   PixmapPtr src, struct kgem_bo *src_bo,
 
3148
                                   PixmapPtr dst, struct kgem_bo *dst_bo)
 
3149
{
 
3150
        return (sna->kgem.ring != KGEM_RENDER ||
 
3151
                prefer_blt_bo(sna, src, src_bo) ||
 
3152
                prefer_blt_bo(sna, dst, dst_bo));
 
3153
}
 
3154
 
 
3155
static inline bool
 
3156
overlaps(struct kgem_bo *src_bo, int16_t src_dx, int16_t src_dy,
 
3157
         struct kgem_bo *dst_bo, int16_t dst_dx, int16_t dst_dy,
 
3158
         const BoxRec *box, int n)
 
3159
{
 
3160
        BoxRec extents;
 
3161
 
 
3162
        if (src_bo != dst_bo)
 
3163
                return false;
 
3164
 
 
3165
        extents = box[0];
 
3166
        while (--n) {
 
3167
                box++;
 
3168
 
 
3169
                if (box->x1 < extents.x1)
 
3170
                        extents.x1 = box->x1;
 
3171
                if (box->x2 > extents.x2)
 
3172
                        extents.x2 = box->x2;
 
3173
 
 
3174
                if (box->y1 < extents.y1)
 
3175
                        extents.y1 = box->y1;
 
3176
                if (box->y2 > extents.y2)
 
3177
                        extents.y2 = box->y2;
 
3178
        }
 
3179
 
 
3180
        return (extents.x2 + src_dx > extents.x1 + dst_dx &&
 
3181
                extents.x1 + src_dx < extents.x2 + dst_dx &&
 
3182
                extents.y2 + src_dy > extents.y1 + dst_dy &&
 
3183
                extents.y1 + src_dy < extents.y2 + dst_dy);
 
3184
}
 
3185
 
2410
3186
static Bool
2411
3187
gen7_render_copy_boxes(struct sna *sna, uint8_t alu,
2412
3188
                       PixmapPtr src, struct kgem_bo *src_bo, int16_t src_dx, int16_t src_dy,
2426
3202
                                  box, n);
2427
3203
#endif
2428
3204
 
2429
 
        DBG(("%s (%d, %d)->(%d, %d) x %d, alu=%x, self-copy=%d\n",
 
3205
        DBG(("%s (%d, %d)->(%d, %d) x %d, alu=%x, self-copy=%d, overlaps? %d\n",
2430
3206
             __FUNCTION__, src_dx, src_dy, dst_dx, dst_dy, n, alu,
2431
 
             src_bo == dst_bo));
 
3207
             src_bo == dst_bo,
 
3208
             overlaps(src_bo, src_dx, src_dy,
 
3209
                      dst_bo, dst_dx, dst_dy,
 
3210
                      box, n)));
2432
3211
 
2433
 
        if (sna->kgem.mode == KGEM_BLT &&
 
3212
        if (prefer_blt_copy(sna, src, src_bo, dst, dst_bo) &&
2434
3213
            sna_blt_compare_depth(&src->drawable, &dst->drawable) &&
2435
3214
            sna_blt_copy_boxes(sna, alu,
2436
3215
                               src_bo, src_dx, src_dy,
2439
3218
                               box, n))
2440
3219
                return TRUE;
2441
3220
 
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,
 
3224
                     box, n)) {
 
3225
fallback_blt:
2447
3226
                if (!sna_blt_compare_depth(&src->drawable, &dst->drawable))
2448
 
                        return FALSE;
2449
 
 
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,
2454
 
                                          box, n);
2455
 
        }
 
3227
                        return false;
 
3228
 
 
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,
 
3232
                                                 box, n);
 
3233
        }
 
3234
 
 
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;
 
3238
        } else {
 
3239
                tmp.dst.format = sna_format_for_depth(dst->drawable.depth);
 
3240
                tmp.src.pict_format = sna_format_for_depth(src->drawable.depth);
 
3241
        }
 
3242
        if (!gen7_check_format(tmp.src.pict_format))
 
3243
                goto fallback_blt;
 
3244
 
2456
3245
        tmp.op = alu == GXcopy ? PictOpSrc : PictOpClear;
2457
3246
 
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;
2464
 
        tmp.dst.x = dst_dx;
2465
 
        tmp.dst.y = dst_dy;
2466
 
 
2467
 
        tmp.src.bo = src_bo;
 
3251
        tmp.dst.x = tmp.dst.y = 0;
 
3252
        tmp.damage = NULL;
 
3253
 
 
3254
        sna_render_composite_redirect_init(&tmp);
 
3255
        if (too_large(tmp.dst.width, tmp.dst.height)) {
 
3256
                BoxRec extents = box[0];
 
3257
                int i;
 
3258
 
 
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;
 
3264
 
 
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;
 
3269
                }
 
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;
 
3276
        }
 
3277
 
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];
 
3283
                int i;
 
3284
 
 
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;
 
3290
 
 
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;
 
3295
                }
 
3296
 
 
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;
 
3303
        } else {
 
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;
 
3310
        }
2474
3311
 
2475
3312
        tmp.mask.bo = NULL;
2476
3313
        tmp.mask.filter = SAMPLER_FILTER_NEAREST;
2478
3315
 
2479
3316
        tmp.is_affine = TRUE;
2480
3317
        tmp.floats_per_vertex = 3;
 
3318
        tmp.floats_per_rect = 9;
2481
3319
        tmp.has_component_alpha = 0;
2482
3320
        tmp.need_magic_ca_pass = 0;
2483
3321
 
2484
 
        tmp.u.gen7.wm_kernel = GEN7_WM_KERNEL_NOMASK;
 
3322
        tmp.u.gen7.wm_kernel = GEN6_WM_KERNEL_NOMASK;
2485
3323
        tmp.u.gen7.nr_surfaces = 2;
2486
3324
        tmp.u.gen7.nr_inputs = 1;
2487
3325
        tmp.u.gen7.ve_id = 1;
2488
3326
 
2489
 
        if (!kgem_check_bo(&sna->kgem, dst_bo, src_bo, NULL))
 
3327
        kgem_set_mode(&sna->kgem, KGEM_RENDER);
 
3328
        if (!kgem_check_bo(&sna->kgem, dst_bo, src_bo, NULL)) {
2490
3329
                kgem_submit(&sna->kgem);
2491
 
 
2492
 
        if (kgem_bo_is_dirty(src_bo))
2493
 
                kgem_emit_flush(&sna->kgem);
 
3330
                if (!kgem_check_bo(&sna->kgem, dst_bo, src_bo, NULL))
 
3331
                        goto fallback_tiled_src;
 
3332
                _kgem_set_mode(&sna->kgem, KGEM_RENDER);
 
3333
        }
 
3334
 
 
3335
        dst_dx += tmp.dst.x;
 
3336
        dst_dy += tmp.dst.y;
 
3337
        tmp.dst.x = tmp.dst.y = 0;
 
3338
 
 
3339
        src_dx += tmp.src.offset[0];
 
3340
        src_dy += tmp.src.offset[1];
2494
3341
 
2495
3342
        gen7_emit_copy_state(sna, &tmp);
2496
3343
        gen7_align_vertex(sna, &tmp);
2497
3344
 
2498
 
        tmp.src.scale[0] = 1.f / src->drawable.width;
2499
 
        tmp.src.scale[1] = 1.f / src->drawable.height;
2500
3345
        do {
2501
3346
                float *v;
2502
 
                int n_this_time = gen7_get_rectangles(sna, &tmp, n);
2503
 
                if (n_this_time == 0) {
2504
 
                        gen7_emit_copy_state(sna, &tmp);
2505
 
                        n_this_time = gen7_get_rectangles(sna, &tmp, n);
2506
 
                }
 
3347
                int n_this_time;
 
3348
 
 
3349
                n_this_time = gen7_get_rectangles(sna, &tmp, n,
 
3350
                                                  gen7_emit_copy_state);
2507
3351
                n -= n_this_time;
2508
3352
 
2509
 
                v = sna->render.vertex_data + sna->render.vertex_used;
 
3353
                v = sna->render.vertices + sna->render.vertex_used;
2510
3354
                sna->render.vertex_used += 9 * n_this_time;
2511
3355
                do {
2512
3356
 
2514
3358
                             box->x1 + src_dx, box->y1 + src_dy,
2515
3359
                             box->x1 + dst_dx, box->y1 + dst_dy,
2516
3360
                             box->x2 - box->x1, box->y2 - box->y1));
2517
 
                        v[0] = pack_2s(box->x2, box->y2);
2518
 
                        v[3] = pack_2s(box->x1, box->y2);
2519
 
                        v[6] = pack_2s(box->x1, box->y1);
 
3361
                        v[0] = pack_2s(box->x2 + dst_dx, box->y2 + dst_dy);
 
3362
                        v[3] = pack_2s(box->x1 + dst_dx, box->y2 + dst_dy);
 
3363
                        v[6] = pack_2s(box->x1 + dst_dx, box->y1 + dst_dy);
2520
3364
 
2521
3365
                        v[1] = (box->x2 + src_dx) * tmp.src.scale[0];
2522
3366
                        v[7] = v[4] = (box->x1 + src_dx) * tmp.src.scale[0];
2530
3374
        } while (n);
2531
3375
 
2532
3376
        gen7_vertex_flush(sna);
2533
 
        _kgem_set_mode(&sna->kgem, KGEM_RENDER);
 
3377
        sna_render_composite_redirect_done(sna, &tmp);
 
3378
        kgem_bo_destroy(&sna->kgem, tmp.src.bo);
2534
3379
        return TRUE;
 
3380
 
 
3381
fallback_tiled_src:
 
3382
        kgem_bo_destroy(&sna->kgem, tmp.src.bo);
 
3383
fallback_tiled_dst:
 
3384
        if (tmp.redirect.real_bo)
 
3385
                kgem_bo_destroy(&sna->kgem, tmp.dst.bo);
 
3386
fallback_tiled:
 
3387
        return sna_tiling_copy_boxes(sna, alu,
 
3388
                                     src, src_bo, src_dx, src_dy,
 
3389
                                     dst, dst_bo, dst_dx, dst_dy,
 
3390
                                     box, n);
2535
3391
}
2536
3392
 
2537
3393
static void
2541
3397
                     int16_t w,  int16_t h,
2542
3398
                     int16_t dx, int16_t dy)
2543
3399
{
2544
 
        if (!gen7_get_rectangles(sna, &op->base, 1)) {
2545
 
                gen7_emit_copy_state(sna, &op->base);
2546
 
                gen7_get_rectangles(sna, &op->base, 1);
2547
 
        }
 
3400
        gen7_get_rectangles(sna, &op->base, 1, gen7_emit_copy_state);
2548
3401
 
2549
3402
        OUT_VERTEX(dx+w, dy+h);
2550
3403
        OUT_VERTEX_F((sx+w)*op->base.src.scale[0]);
2562
3415
static void
2563
3416
gen7_render_copy_done(struct sna *sna, const struct sna_copy_op *op)
2564
3417
{
2565
 
        gen7_vertex_flush(sna);
2566
 
        _kgem_set_mode(&sna->kgem, KGEM_RENDER);
 
3418
        if (sna->render_state.gen7.vertex_offset)
 
3419
                gen7_vertex_flush(sna);
2567
3420
}
2568
3421
 
2569
3422
static Bool
2587
3440
             src->drawable.width, src->drawable.height,
2588
3441
             dst->drawable.width, dst->drawable.height));
2589
3442
 
2590
 
        if (sna->kgem.mode == KGEM_BLT &&
 
3443
        if (prefer_blt_copy(sna, src, src_bo, dst, dst_bo) &&
2591
3444
            sna_blt_compare_depth(&src->drawable, &dst->drawable) &&
2592
3445
            sna_blt_copy(sna, alu,
2593
3446
                         src_bo, dst_bo,
2596
3449
                return TRUE;
2597
3450
 
2598
3451
        if (!(alu == GXcopy || alu == GXclear) || src_bo == dst_bo ||
2599
 
            src->drawable.width > GEN7_MAX_SIZE ||
2600
 
            src->drawable.height > GEN7_MAX_SIZE ||
2601
 
            dst->drawable.width > GEN7_MAX_SIZE ||
2602
 
            dst->drawable.height > GEN7_MAX_SIZE) {
 
3452
            too_large(src->drawable.width, src->drawable.height) ||
 
3453
            too_large(dst->drawable.width, dst->drawable.height)) {
 
3454
fallback:
2603
3455
                if (!sna_blt_compare_depth(&src->drawable, &dst->drawable))
2604
3456
                        return FALSE;
2605
3457
 
2608
3460
                                    op);
2609
3461
        }
2610
3462
 
 
3463
        if (dst->drawable.depth == src->drawable.depth) {
 
3464
                op->base.dst.format = sna_render_format_for_depth(dst->drawable.depth);
 
3465
                op->base.src.pict_format = op->base.dst.format;
 
3466
        } else {
 
3467
                op->base.dst.format = sna_format_for_depth(dst->drawable.depth);
 
3468
                op->base.src.pict_format = sna_format_for_depth(src->drawable.depth);
 
3469
        }
 
3470
        if (!gen7_check_format(op->base.src.pict_format))
 
3471
                goto fallback;
 
3472
 
2611
3473
        op->base.op = alu == GXcopy ? PictOpSrc : PictOpClear;
2612
3474
 
2613
3475
        op->base.dst.pixmap = dst;
2614
3476
        op->base.dst.width  = dst->drawable.width;
2615
3477
        op->base.dst.height = dst->drawable.height;
2616
 
        op->base.dst.format = sna_format_for_depth(dst->drawable.depth);
2617
3478
        op->base.dst.bo = dst_bo;
2618
3479
 
2619
3480
        op->base.src.bo = src_bo;
2620
3481
        op->base.src.card_format =
2621
 
                gen7_get_card_format_for_depth(src->drawable.depth),
 
3482
                gen7_get_card_format(op->base.src.pict_format);
2622
3483
        op->base.src.width  = src->drawable.width;
2623
3484
        op->base.src.height = src->drawable.height;
2624
3485
        op->base.src.scale[0] = 1.f/src->drawable.width;
2626
3487
        op->base.src.filter = SAMPLER_FILTER_NEAREST;
2627
3488
        op->base.src.repeat = SAMPLER_EXTEND_NONE;
2628
3489
 
 
3490
        op->base.mask.bo = NULL;
 
3491
 
2629
3492
        op->base.is_affine = true;
2630
3493
        op->base.floats_per_vertex = 3;
 
3494
        op->base.floats_per_rect = 9;
2631
3495
 
2632
3496
        op->base.u.gen7.wm_kernel = GEN7_WM_KERNEL_NOMASK;
2633
3497
        op->base.u.gen7.nr_surfaces = 2;
2634
3498
        op->base.u.gen7.nr_inputs = 1;
2635
3499
        op->base.u.gen7.ve_id = 1;
2636
3500
 
2637
 
        if (!kgem_check_bo(&sna->kgem, dst_bo, src_bo, NULL))
 
3501
        kgem_set_mode(&sna->kgem, KGEM_RENDER);
 
3502
        if (!kgem_check_bo(&sna->kgem, dst_bo, src_bo, NULL)) {
2638
3503
                kgem_submit(&sna->kgem);
2639
 
 
2640
 
        if (kgem_bo_is_dirty(src_bo))
2641
 
                kgem_emit_flush(&sna->kgem);
 
3504
                if (!kgem_check_bo(&sna->kgem, dst_bo, src_bo, NULL))
 
3505
                        goto fallback;
 
3506
                _kgem_set_mode(&sna->kgem, KGEM_RENDER);
 
3507
        }
2642
3508
 
2643
3509
        gen7_emit_copy_state(sna, &op->base);
2644
3510
        gen7_align_vertex(sna, &op->base);
2678
3544
        if (sna->kgem.surface == offset &&
2679
3545
            *(uint64_t *)(sna->kgem.batch + sna->render_state.gen7.surface_table) == *(uint64_t*)binding_table) {
2680
3546
                sna->kgem.surface +=
2681
 
                        sizeof(struct gen7_surface_state_padded)/sizeof(uint32_t);
 
3547
                        sizeof(struct gen7_surface_state)/sizeof(uint32_t);
2682
3548
                offset = sna->render_state.gen7.surface_table;
2683
3549
        }
2684
3550
 
2685
3551
        gen7_emit_state(sna, op, offset);
2686
3552
}
2687
3553
 
 
3554
static inline bool prefer_blt_fill(struct sna *sna,
 
3555
                                   struct kgem_bo *bo)
 
3556
{
 
3557
        return sna->kgem.ring != KGEM_RENDER || untiled_tlb_miss(bo);
 
3558
}
 
3559
 
2688
3560
static Bool
2689
3561
gen7_render_fill_boxes(struct sna *sna,
2690
3562
                       CARD8 op,
2706
3578
                return FALSE;
2707
3579
        }
2708
3580
 
2709
 
        if (sna->kgem.mode == KGEM_BLT ||
2710
 
            dst->drawable.width > GEN7_MAX_SIZE ||
2711
 
            dst->drawable.height > GEN7_MAX_SIZE ||
 
3581
        if (prefer_blt_fill(sna, dst_bo) ||
 
3582
            too_large(dst->drawable.width, dst->drawable.height) ||
2712
3583
            !gen7_check_dst_format(format)) {
2713
3584
                uint8_t alu = -1;
2714
3585
 
2735
3606
                                       pixel, box, n))
2736
3607
                        return TRUE;
2737
3608
 
2738
 
                if (dst->drawable.width > GEN7_MAX_SIZE ||
2739
 
                    dst->drawable.height > GEN7_MAX_SIZE ||
2740
 
                    !gen7_check_dst_format(format))
 
3609
                if (!gen7_check_dst_format(format))
2741
3610
                        return FALSE;
 
3611
 
 
3612
                if (too_large(dst->drawable.width, dst->drawable.height))
 
3613
                        return sna_tiling_fill_boxes(sna, op, format, color,
 
3614
                                                     dst, dst_bo, box, n);
2742
3615
        }
2743
3616
 
2744
3617
#if NO_FILL_BOXES
2745
3618
        return FALSE;
2746
3619
#endif
2747
3620
 
2748
 
        if (op ==PictOpClear)
 
3621
        if (op == PictOpClear)
2749
3622
                pixel = 0;
2750
3623
        else if (!sna_get_pixel_from_rgba(&pixel,
2751
3624
                                     color->red,
2775
3648
 
2776
3649
        tmp.is_affine = TRUE;
2777
3650
        tmp.floats_per_vertex = 3;
 
3651
        tmp.floats_per_rect = 9;
2778
3652
 
2779
3653
        tmp.u.gen7.wm_kernel = GEN7_WM_KERNEL_NOMASK;
2780
3654
        tmp.u.gen7.nr_surfaces = 2;
2781
3655
        tmp.u.gen7.nr_inputs = 1;
2782
3656
        tmp.u.gen7.ve_id = 1;
2783
3657
 
2784
 
        if (!kgem_check_bo(&sna->kgem, dst_bo, NULL))
 
3658
        if (!kgem_check_bo(&sna->kgem, dst_bo, NULL)) {
2785
3659
                kgem_submit(&sna->kgem);
 
3660
                assert(kgem_check_bo(&sna->kgem, dst_bo, NULL));
 
3661
        }
2786
3662
 
2787
3663
        gen7_emit_fill_state(sna, &tmp);
2788
3664
        gen7_align_vertex(sna, &tmp);
2789
3665
 
2790
3666
        do {
2791
 
                int n_this_time = gen7_get_rectangles(sna, &tmp, n);
2792
 
                if (n_this_time == 0) {
2793
 
                        gen7_emit_fill_state(sna, &tmp);
2794
 
                        n_this_time = gen7_get_rectangles(sna, &tmp, n);
2795
 
                }
 
3667
                int n_this_time;
 
3668
 
 
3669
                n_this_time = gen7_get_rectangles(sna, &tmp, n,
 
3670
                                                  gen7_emit_fill_state);
2796
3671
                n -= n_this_time;
 
3672
 
2797
3673
                do {
2798
3674
                        DBG(("  (%d, %d), (%d, %d)\n",
2799
3675
                             box->x1, box->y1, box->x2, box->y2));
2815
3691
 
2816
3692
        gen7_vertex_flush(sna);
2817
3693
        kgem_bo_destroy(&sna->kgem, tmp.src.bo);
2818
 
        _kgem_set_mode(&sna->kgem, KGEM_RENDER);
2819
3694
        return TRUE;
2820
3695
}
2821
3696
 
2826
3701
{
2827
3702
        DBG(("%s: (%d, %d)x(%d, %d)\n", __FUNCTION__, x, y, w, h));
2828
3703
 
2829
 
        if (!gen7_get_rectangles(sna, &op->base, 1)) {
2830
 
                gen7_emit_fill_state(sna, &op->base);
2831
 
                gen7_get_rectangles(sna, &op->base, 1);
2832
 
        }
 
3704
        gen7_get_rectangles(sna, &op->base, 1, gen7_emit_fill_state);
2833
3705
 
2834
3706
        OUT_VERTEX(x+w, y+h);
2835
3707
        OUT_VERTEX_F(1);
2852
3724
        DBG(("%s: (%d, %d),(%d, %d)\n", __FUNCTION__,
2853
3725
             box->x1, box->y1, box->x2, box->y2));
2854
3726
 
2855
 
        if (!gen7_get_rectangles(sna, &op->base, 1)) {
2856
 
                gen7_emit_fill_state(sna, &op->base);
2857
 
                gen7_get_rectangles(sna, &op->base, 1);
2858
 
        }
 
3727
        gen7_get_rectangles(sna, &op->base, 1, gen7_emit_fill_state);
2859
3728
 
2860
3729
        OUT_VERTEX(box->x2, box->y2);
2861
3730
        OUT_VERTEX_F(1);
2880
3749
             box->x1, box->y1, box->x2, box->y2, nbox));
2881
3750
 
2882
3751
        do {
2883
 
                int nbox_this_time = gen7_get_rectangles(sna, &op->base, nbox);
2884
 
                if (nbox_this_time == 0) {
2885
 
                        gen7_emit_fill_state(sna, &op->base);
2886
 
                        nbox_this_time = gen7_get_rectangles(sna, &op->base, nbox);
2887
 
                }
 
3752
                int nbox_this_time;
 
3753
 
 
3754
                nbox_this_time = gen7_get_rectangles(sna, &op->base, nbox,
 
3755
                                                     gen7_emit_fill_state);
2888
3756
                nbox -= nbox_this_time;
2889
3757
 
2890
3758
                do {
2907
3775
static void
2908
3776
gen7_render_fill_op_done(struct sna *sna, const struct sna_fill_op *op)
2909
3777
{
2910
 
        gen7_vertex_flush(sna);
 
3778
        if (sna->render_state.gen7.vertex_offset)
 
3779
                gen7_vertex_flush(sna);
2911
3780
        kgem_bo_destroy(&sna->kgem, op->base.src.bo);
2912
 
        _kgem_set_mode(&sna->kgem, KGEM_RENDER);
2913
3781
}
2914
3782
 
2915
3783
static Bool
2927
3795
                            op);
2928
3796
#endif
2929
3797
 
2930
 
        if (sna->kgem.mode == KGEM_BLT &&
 
3798
        if (prefer_blt_fill(sna, dst_bo) &&
2931
3799
            sna_blt_fill(sna, alu,
2932
3800
                         dst_bo, dst->drawable.bitsPerPixel,
2933
3801
                         color,
2935
3803
                return TRUE;
2936
3804
 
2937
3805
        if (!(alu == GXcopy || alu == GXclear) ||
2938
 
            dst->drawable.width > GEN7_MAX_SIZE ||
2939
 
            dst->drawable.height > GEN7_MAX_SIZE)
 
3806
            too_large(dst->drawable.width, dst->drawable.height))
2940
3807
                return sna_blt_fill(sna, alu,
2941
3808
                                    dst_bo, dst->drawable.bitsPerPixel,
2942
3809
                                    color,
2966
3833
        op->base.mask.repeat = SAMPLER_EXTEND_NONE;
2967
3834
 
2968
3835
        op->base.is_affine = TRUE;
 
3836
        op->base.has_component_alpha = FALSE;
 
3837
        op->base.need_magic_ca_pass = FALSE;
2969
3838
        op->base.floats_per_vertex = 3;
 
3839
        op->base.floats_per_rect = 9;
2970
3840
 
2971
3841
        op->base.u.gen7.wm_kernel = GEN7_WM_KERNEL_NOMASK;
2972
3842
        op->base.u.gen7.nr_surfaces = 2;
2973
3843
        op->base.u.gen7.nr_inputs = 1;
2974
3844
        op->base.u.gen7.ve_id = 1;
2975
3845
 
2976
 
        if (!kgem_check_bo(&sna->kgem, dst_bo, NULL))
 
3846
        if (!kgem_check_bo(&sna->kgem, dst_bo, NULL)) {
2977
3847
                kgem_submit(&sna->kgem);
 
3848
                assert(kgem_check_bo(&sna->kgem, dst_bo, NULL));
 
3849
        }
2978
3850
 
2979
3851
        gen7_emit_fill_state(sna, &op->base);
2980
3852
        gen7_align_vertex(sna, &op->base);
3019
3891
#endif
3020
3892
 
3021
3893
        /* Prefer to use the BLT if already engaged */
3022
 
        if (sna->kgem.mode != KGEM_RENDER &&
 
3894
        if (prefer_blt_fill(sna, bo) &&
3023
3895
            gen7_render_fill_one_try_blt(sna, dst, bo, color,
3024
3896
                                         x1, y1, x2, y2, alu))
3025
3897
                return TRUE;
3026
3898
 
3027
3899
        /* Must use the BLT if we can't RENDER... */
3028
3900
        if (!(alu == GXcopy || alu == GXclear) ||
3029
 
            dst->drawable.width > 8192 || dst->drawable.height > 8192)
 
3901
            too_large(dst->drawable.width, dst->drawable.height))
3030
3902
                return gen7_render_fill_one_try_blt(sna, dst, bo, color,
3031
3903
                                                    x1, y1, x2, y2, alu);
3032
3904
 
3055
3927
 
3056
3928
        tmp.is_affine = TRUE;
3057
3929
        tmp.floats_per_vertex = 3;
 
3930
        tmp.floats_per_rect = 9;
3058
3931
        tmp.has_component_alpha = 0;
3059
3932
        tmp.need_magic_ca_pass = FALSE;
3060
3933
 
3061
 
        tmp.u.gen7.wm_kernel = GEN6_WM_KERNEL_NOMASK;
 
3934
        tmp.u.gen7.wm_kernel = GEN7_WM_KERNEL_NOMASK;
3062
3935
        tmp.u.gen7.nr_surfaces = 2;
3063
3936
        tmp.u.gen7.nr_inputs = 1;
3064
3937
        tmp.u.gen7.ve_id = 1;
3065
3938
 
3066
 
        if (!kgem_check_bo(&sna->kgem, bo, NULL))
 
3939
        if (!kgem_check_bo(&sna->kgem, bo, NULL)) {
3067
3940
                _kgem_submit(&sna->kgem);
 
3941
                assert(kgem_check_bo(&sna->kgem, bo, NULL));
 
3942
        }
3068
3943
 
3069
3944
        gen7_emit_fill_state(sna, &tmp);
3070
3945
        gen7_align_vertex(sna, &tmp);
3071
3946
 
3072
 
        if (!gen7_get_rectangles(sna, &tmp, 1)) {
3073
 
                gen7_emit_fill_state(sna, &tmp);
3074
 
                gen7_get_rectangles(sna, &tmp, 1);
3075
 
        }
 
3947
        gen7_get_rectangles(sna, &tmp, 1, gen7_emit_fill_state);
3076
3948
 
3077
3949
        DBG(("  (%d, %d), (%d, %d)\n", x1, y1, x2, y2));
3078
3950
        OUT_VERTEX(x2, y2);
3089
3961
 
3090
3962
        gen7_vertex_flush(sna);
3091
3963
        kgem_bo_destroy(&sna->kgem, tmp.src.bo);
3092
 
        _kgem_set_mode(&sna->kgem, KGEM_RENDER);
 
3964
 
 
3965
        return TRUE;
 
3966
}
 
3967
 
 
3968
static Bool
 
3969
gen7_render_clear_try_blt(struct sna *sna, PixmapPtr dst, struct kgem_bo *bo)
 
3970
{
 
3971
        BoxRec box;
 
3972
 
 
3973
        box.x1 = 0;
 
3974
        box.y1 = 0;
 
3975
        box.x2 = dst->drawable.width;
 
3976
        box.y2 = dst->drawable.height;
 
3977
 
 
3978
        return sna_blt_fill_boxes(sna, GXclear,
 
3979
                                  bo, dst->drawable.bitsPerPixel,
 
3980
                                  0, &box, 1);
 
3981
}
 
3982
 
 
3983
static Bool
 
3984
gen7_render_clear(struct sna *sna, PixmapPtr dst, struct kgem_bo *bo)
 
3985
{
 
3986
        struct sna_composite_op tmp;
 
3987
 
 
3988
#if NO_CLEAR
 
3989
        return gen7_render_clear_try_blt(sna, dst, bo);
 
3990
#endif
 
3991
 
 
3992
        DBG(("%s: %dx%d\n",
 
3993
             __FUNCTION__,
 
3994
             dst->drawable.width,
 
3995
             dst->drawable.height));
 
3996
 
 
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))
 
4000
                return TRUE;
 
4001
 
 
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);
 
4005
 
 
4006
        tmp.op = PictOpClear;
 
4007
 
 
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);
 
4012
        tmp.dst.bo = bo;
 
4013
        tmp.dst.x = tmp.dst.y = 0;
 
4014
 
 
4015
        tmp.src.bo = sna_render_get_solid(sna, 0);
 
4016
        tmp.src.filter = SAMPLER_FILTER_NEAREST;
 
4017
        tmp.src.repeat = SAMPLER_EXTEND_REPEAT;
 
4018
 
 
4019
        tmp.mask.bo = NULL;
 
4020
        tmp.mask.filter = SAMPLER_FILTER_NEAREST;
 
4021
        tmp.mask.repeat = SAMPLER_EXTEND_NONE;
 
4022
 
 
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;
 
4028
 
 
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;
 
4033
 
 
4034
        if (!kgem_check_bo(&sna->kgem, bo, NULL)) {
 
4035
                _kgem_submit(&sna->kgem);
 
4036
                assert(kgem_check_bo(&sna->kgem, bo, NULL));
 
4037
        }
 
4038
 
 
4039
        gen7_emit_fill_state(sna, &tmp);
 
4040
        gen7_align_vertex(sna, &tmp);
 
4041
 
 
4042
        gen7_get_rectangles(sna, &tmp, 1, gen7_emit_fill_state);
 
4043
 
 
4044
        OUT_VERTEX(dst->drawable.width, dst->drawable.height);
 
4045
        OUT_VERTEX_F(1);
 
4046
        OUT_VERTEX_F(1);
 
4047
 
 
4048
        OUT_VERTEX(0, dst->drawable.height);
 
4049
        OUT_VERTEX_F(0);
 
4050
        OUT_VERTEX_F(1);
 
4051
 
 
4052
        OUT_VERTEX(0, 0);
 
4053
        OUT_VERTEX_F(0);
 
4054
        OUT_VERTEX_F(0);
 
4055
 
 
4056
        gen7_vertex_flush(sna);
 
4057
        kgem_bo_destroy(&sna->kgem, tmp.src.bo);
3093
4058
 
3094
4059
        return TRUE;
3095
4060
}
3096
4061
 
3097
4062
static void gen7_render_flush(struct sna *sna)
3098
4063
{
3099
 
        gen7_vertex_finish(sna, TRUE);
 
4064
        gen7_vertex_close(sna);
3100
4065
}
3101
4066
 
3102
4067
static void
3107
4072
                return;
3108
4073
 
3109
4074
        if (kgem->mode)
3110
 
                _kgem_submit(kgem);
 
4075
                kgem_submit(kgem);
3111
4076
 
3112
4077
        kgem->ring = new_mode;
3113
4078
}
3114
4079
 
 
4080
static void
 
4081
gen7_render_retire(struct kgem *kgem)
 
4082
{
 
4083
        if (kgem->ring && (kgem->has_semaphores || !kgem->need_retire))
 
4084
                kgem->ring = kgem->mode;
 
4085
}
 
4086
 
3115
4087
static void gen7_render_reset(struct sna *sna)
3116
4088
{
3117
4089
        sna->render_state.gen7.needs_invariant = TRUE;
3184
4156
                return FALSE;
3185
4157
 
3186
4158
        sna->kgem.context_switch = gen7_render_context_switch;
 
4159
        sna->kgem.retire = gen7_render_retire;
3187
4160
 
3188
4161
        sna->render.composite = gen7_render_composite;
 
4162
#if !NO_COMPOSITE_SPANS
 
4163
        sna->render.composite_spans = gen7_render_composite_spans;
 
4164
#endif
3189
4165
        sna->render.video = gen7_render_video;
3190
4166
 
3191
4167
        sna->render.copy_boxes = gen7_render_copy_boxes;
3194
4170
        sna->render.fill_boxes = gen7_render_fill_boxes;
3195
4171
        sna->render.fill = gen7_render_fill;
3196
4172
        sna->render.fill_one = gen7_render_fill_one;
 
4173
        sna->render.clear = gen7_render_clear;
3197
4174
 
3198
4175
        sna->render.flush = gen7_render_flush;
3199
4176
        sna->render.reset = gen7_render_reset;
3200
4177
        sna->render.fini = gen7_render_fini;
3201
4178
 
3202
4179
        sna->render.max_3d_size = GEN7_MAX_SIZE;
 
4180
        sna->render.max_3d_pitch = 1 << 18;
3203
4181
        return TRUE;
3204
4182
}