summaryrefslogtreecommitdiff
path: root/blitter.c
blob: 0c982efb614c446db9828d3ba791878631cce77a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
#include <stdio.h>
#include <pixman.h>
#include <stddef.h>
#include "simplex86.h"
#include "simple-reg.h"
#include "stack-man.h"

static const reg_pool_t gp64 =
{
    15, 8,
    {
	rax, rbx, rcx, rdx, rdi, rsi, rbp,
	r8, r9, r10, r11, r12, r13, r14, r15
    }
};

static const reg_pool_t xmm =
{
    15, 16,
    {
	xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7,
	xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15,
    }
};

typedef struct jit_t jit_t;
struct jit_t
{
    pixman_op_t			op;
    pixman_format_code_t	src_format;
    pixman_format_code_t	dest_format;
    pixman_format_code_t	mask_format;

    assembler_t *		assembler;
    fragment_t *		fragment;
    stack_man_t			stack_man;
};

typedef struct
{
    pixman_op_t              op;
    pixman_image_t *         src_image;
    pixman_image_t *         mask_image;
    pixman_image_t *         dest_image;
    int32_t                  src_x;
    int32_t                  src_y;
    int32_t                  mask_x;
    int32_t                  mask_y;
    int32_t                  dest_x;
    int32_t                  dest_y;
    int32_t                  width;
    int32_t                  height;

    uint32_t                 src_flags;
    uint32_t                 mask_flags;
    uint32_t                 dest_flags;
} pixman_composite_info_t;

typedef struct image_common image_common_t;
typedef struct bits_image bits_image_t;

typedef enum
{
    BITS,
    LINEAR,
    CONICAL,
    RADIAL,
    SOLID
} image_type_t;

struct image_common
{
    image_type_t                type;
    int32_t                     ref_count;
    pixman_region32_t           clip_region;
    int32_t			alpha_count;	    /* How many times this image is being used as an alpha map */
    pixman_bool_t               have_clip_region;   /* FALSE if there is no clip */
    pixman_bool_t               client_clip;        /* Whether the source clip was
						       set by a client */
    pixman_bool_t               clip_sources;       /* Whether the clip applies when
						     * the image is used as a source
						     */
    pixman_bool_t		dirty;
    pixman_transform_t *        transform;
    pixman_repeat_t             repeat;
    pixman_filter_t             filter;
    pixman_fixed_t *            filter_params;
    int                         n_filter_params;
    bits_image_t *              alpha_map;
    int                         alpha_origin_x;
    int                         alpha_origin_y;
    pixman_bool_t               component_alpha;
    void *     property_changed;

    pixman_image_destroy_func_t destroy_func;
    void *                      destroy_data;

    uint32_t			flags;
    pixman_format_code_t	extended_format_code;
};

struct bits_image
{
    image_common_t             common;
    pixman_format_code_t       format;
    const pixman_indexed_t *   indexed;
    int                        width;
    int                        height;
    uint32_t *                 bits;
    uint32_t *                 free_me;
    int                        rowstride;  /* in number of uint32_t's */

    void *           fetch_scanline_32;
    void *	       fetch_pixel_32;
    void *           store_scanline_32;

    void *           fetch_scanline_64;
    void *	       fetch_pixel_64;
    void *           store_scanline_64;

    /* Used for indirect access to the bits */
    void *  read_func;
    void * write_func;
};


#define PIXMAN_null             PIXMAN_FORMAT (0, 0, 0, 0, 0, 0)
#define PIXMAN_solid            PIXMAN_FORMAT (0, 1, 0, 0, 0, 0)
#define PIXMAN_pixbuf		PIXMAN_FORMAT (0, 2, 0, 0, 0, 0)
#define PIXMAN_rpixbuf		PIXMAN_FORMAT (0, 3, 0, 0, 0, 0)
#define PIXMAN_unknown		PIXMAN_FORMAT (0, 4, 0, 0, 0, 0)
#define PIXMAN_any		PIXMAN_FORMAT (0, 5, 0, 0, 0, 0)


static bool_t
create_blitter (fragment_t *            fragment,
                reg_context_t *         gp_context,
                reg_context_t *         xmm_context,
                pixman_op_t             op,
                pixman_format_code_t    src_format,
                pixman_format_code_t    mask_format,
                pixman_format_code_t    dest_format)
{
    reg_t width, height, dst, dst_stride, mask, mask_stride, src, src_stride;
    reg_context_t args;
    reg_t w, info, tmp;
    int dst_shift;

    switch (PIXMAN_FORMAT_BPP (dest_format))
    {
    case 32:
        dst_shift = 2;
        break;

    case 16:
        dst_shift = 1;
        break;

    case 8:
        dst_shift = 0;
        break;

    default:
        return FALSE;
    }

    reg_context_init (&args, gp_context, 1, rsi);

    info = rsi;
    width = reg_context_alloc (&args, fragment);
    height = reg_context_alloc (&args, fragment);
    dst = reg_context_alloc (&args, fragment);
    dst_stride = reg_context_alloc (&args, fragment);
    tmp = reg_context_alloc (&args, fragment);

    BEGIN_ASM (fragment)
        I_mov, width, BASE (info, offsetof (pixman_composite_info_t, width)),
        I_mov, height, BASE (info, offsetof (pixman_composite_info_t, height)),
        I_mov, tmp, BASE (info, offsetof (pixman_composite_info_t, dest_image)),

        /* Get stride in bytes */
        I_mov, dst_stride, BASE (tmp, offsetof (bits_image_t, rowstride)),
        I_shl, dst_stride, IMM (2), /* Convert to bytes */

        /* Compute dest origin */
        I_mov, dst, BASE (tmp, offsetof (bits_image_t, bits)),
        I_mov, tmp, BASE (info, offsetof (pixman_composite_info_t, dest_y)),
        I_imul2, tmp, dst_stride,
        I_add, dst, tmp,                /* dst = base + stride * y */

        I_mov, tmp, BASE (info, offsetof (pixman_composite_info_t, dest_x)),
        I_lea, dst, INDEX (dst, 0, tmp, dst_shift),  /* dst = dst + dst_x * dst_bpp*/
    END_ASM ();

    reg_context_free (&args, tmp);
    reg_context_free (&args, info);

    BEGIN_ASM (fragment)
        DEFINE_LABEL ("main"),
    END_ASM ();

    w = reg_context_alloc (&args, fragment);

    BEGIN_ASM (fragment)
        I_mov, w, width,
        DEFINE_LABEL ("scanline"),

        I_sub, w, IMM (1),
        I_jnz, LABEL ("scanline"),
    END_ASM ();

    BEGIN_ASM (fragment)
        I_sub, height, IMM (1),
        I_jnz, LABEL ("main"),
    END_ASM ();

    reg_context_fini (&args, fragment, 0);

    return TRUE;
}

int
main ()
{
    assembler_t *as = assembler_new ("pixman");
    fragment_t *fragment = fragment_new (as);
    reg_alloc_t gp_alloc, xmm_alloc;
    stack_man_t stack_man;
    reg_context_t gp_context, xmm_context;
    uint8_t *c;

    stack_manager_init (&stack_man);

    reg_alloc_init (&gp_alloc, &gp64, &stack_man, &gp_context, 0);
    reg_alloc_init (&xmm_alloc, &xmm, &stack_man, &xmm_context, 0);

    create_blitter (fragment, &gp_context, &xmm_context,
                    PIXMAN_OP_IN,
                    PIXMAN_a8r8g8b8,
                    PIXMAN_a8,
                    PIXMAN_r5g6b5);

    c = assembler_link (as, fragment, NULL);



    return 0;
}