#include #include #include #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; }