Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 6864 → Rev 6865

/contrib/sdk/samples/freetype/txview/pxdraw/context.c
0,0 → 1,339
#include <stdlib.h>
#include <kos32sys.h>
#include "pxdraw.h"
#include "internal.h"
 
ctx_t* create_context(int x, int y, int width, int height)
{
ctx_t *ctx;
 
ctx = malloc(sizeof(ctx_t));
if (ctx == NULL)
goto err_0;
 
ctx->pitch = ALIGN(width * sizeof(color_t), 16);
ctx->size = ALIGN(ctx->pitch * height, 4096);
 
ctx->buffer = user_alloc(ctx->size+4096);
if (ctx->buffer == NULL)
goto err_1;
 
ctx->x = x;
ctx->y = y;
ctx->width = width;
ctx->height = height;
 
ctx->rc.l = 0;
ctx->rc.t = 0;
ctx->rc.r = width;
ctx->rc.b = height;
 
ctx->rcu.l = 0;
ctx->rcu.t = 0;
ctx->rcu.r = ctx->width;
ctx->rcu.b = ctx->height;
ctx->dirty = 1;
 
__builtin_cpu_init ();
if (__builtin_cpu_supports ("sse2"))
ctx->px_rect_simd = px_rect_xmm;
else if (__builtin_cpu_supports ("mmx"))
ctx->px_rect_simd = px_rect_mmx;
else
ctx->px_rect_simd = px_rect_alu;
 
if (__builtin_cpu_supports ("sse2"))
ctx->px_glyph = px_glyph_sse;
else
ctx->px_glyph = px_glyph_alu;
 
return ctx;
 
err_1:
free(ctx);
err_0:
return NULL;
};
 
int resize_context(ctx_t *ctx, int width, int height)
{
int size;
int pitch;
 
pitch = ALIGN(width * sizeof(color_t), 16);
size = ALIGN(pitch * height, 4096);
 
if (size > ctx->size)
{
ctx->buffer = user_realloc(ctx->buffer, size); /* grow buffer */
if (ctx->buffer == NULL)
return -1;
 
ctx->size = size;
}
else if (size < ctx->size)
user_unmap(ctx->buffer, size, ctx->size - size); /* unmap unused pages */
 
ctx->width = width;
ctx->height = height;
ctx->pitch = pitch;
 
ctx->rc.l = 0;
ctx->rc.t = 0;
ctx->rc.r = width;
ctx->rc.b = height;
 
ctx->rcu.l = ctx->rcu.t = 0;
ctx->rcu.r = ctx->rcu.b = 0;
 
return 0;
};
 
void clear_context(ctx_t *ctx, color_t color)
{
size_t size;
 
size = ctx->pitch * ctx->height;
 
if (size >= 1024)
ctx->px_rect_simd(ctx->buffer, ctx->pitch, ctx->width, ctx->height, color);
else
px_rect_alu(ctx->buffer, ctx->pitch, ctx->width, ctx->height, color);
 
ctx->rcu.l = 0;
ctx->rcu.t = 0;
ctx->rcu.r = ctx->width;
ctx->rcu.b = ctx->height;
ctx->dirty = 1;
};
 
void show_context(ctx_t *ctx)
{
struct blit_call bc;
int ret;
 
bc.dstx = ctx->x;
bc.dsty = ctx->y;
bc.w = ctx->width;
bc.h = ctx->height;
bc.srcx = 0;
bc.srcy = 0;
bc.srcw = ctx->width;
bc.srch = ctx->height;
bc.stride = ctx->pitch;
bc.bitmap = ctx->buffer;
 
__asm__ __volatile__(
"int $0x40":"=a"(ret):"a"(73), "b"(0x00),
"c"(&bc):"memory");
 
ctx->dirty = 0;
};
 
void scroll_context(ctx_t *ctx, int dst_y, int src_y, int rows)
{
char *dst;
char *src;
 
dst = ctx->buffer + dst_y * ctx->pitch;
src = ctx->buffer + src_y * ctx->pitch;
 
__builtin_memmove(dst, src, rows * ctx->pitch);
ctx->dirty = 1;
}
 
static int clip_rect(const rect_t *clip, rect_t *rc)
{
if (rc->l > rc->r)
return 1;
if (rc->t > rc->b)
return 1;
 
if (rc->l < clip->l)
rc->l = clip->l;
else if (rc->l >= clip->r)
return 1;
 
if (rc->t < clip->t)
rc->t = clip->t;
else if (rc->t >= clip->b)
return 1;
 
if (rc->r < clip->l)
return 1;
else if (rc->r > clip->r)
rc->r = clip->r;
 
if (rc->b < clip->t)
return 1;
else if (rc->b > clip->b)
rc->b = clip->b;
 
if ((rc->l == rc->r) ||
(rc->t == rc->b))
return 1;
return 0;
}
 
int px_hline(ctx_t*ctx, int x, int y, int width, color_t color)
{
char *dst_addr;
 
int xr = x + width;
 
if(y < ctx->rc.t)
return 0;
else if(y >= ctx->rc.b)
return 0;
 
if(x < ctx->rc.l)
x = ctx->rc.l;
else if(x >= ctx->rc.r)
return 0;
 
if(xr <= ctx->rc.l)
return 0;
else if(xr > ctx->rc.r)
xr = ctx->rc.r;
 
dst_addr = ctx->buffer;
dst_addr+= ctx->pitch * y + x * sizeof(color_t);
 
__asm__ __volatile__
(" cld; rep stosl\n\t"
:: "D" (dst_addr),"c" (xr-x), "a" (color)
: "flags");
};
 
void px_vline(ctx_t*ctx, int x, int y, int height, color_t color)
{
char *dst_addr;
 
int yb = y + height;
 
if(x < ctx->rc.l)
return;
else if(x >= ctx->rc.r)
return;
 
if(y < ctx->rc.t)
y = ctx->rc.t;
else if(y >= ctx->rc.b)
return;
 
if(yb <= ctx->rc.t)
return;
else if(yb > ctx->rc.b)
yb = ctx->rc.b;
 
dst_addr = ctx->buffer;
dst_addr+= ctx->pitch * y + x * sizeof(color_t);
 
while(y < yb)
{
color_t *t = (color_t*)dst_addr;
*t = color;
y++;
dst_addr+= ctx->pitch;
};
};
 
static int do_fill_rect(ctx_t *ctx, rect_t *rc, color_t color)
{
if (!clip_rect(&ctx->rc, rc))
{
int w, h;
char *dst_addr;
 
w = rc->r - rc->l;
h = rc->b - rc->t;
 
dst_addr = ctx->buffer;
dst_addr += ctx->pitch * rc->t + rc->l * sizeof(color_t);
if (w * h >= 256)
ctx->px_rect_simd(dst_addr, ctx->pitch, w, h, color);
else
px_rect_alu(dst_addr, ctx->pitch, w, h, color);
return 1;
};
return 0;
};
 
void px_fill_rect(ctx_t *ctx, const rect_t *src, color_t color)
{
rect_t rc = *src;
int update;
 
update = do_fill_rect(ctx, &rc, color);
 
if(update)
{
if (rc.l < ctx->rcu.l)
ctx->rcu.l = rc.l;
if (rc.t < ctx->rcu.t)
ctx->rcu.t = rc.t;
if (rc.r > ctx->rcu.r)
ctx->rcu.r = rc.r;
if (rc.b > ctx->rcu.b)
ctx->rcu.b = rc.b;
ctx->dirty = 1;
};
}
 
void px_fill_region(ctx_t *ctx, const rgn_t *rgn, color_t color)
{
int update = 0;
 
for (int i = 0; i < rgn->num_rects; i++)
{
rect_t rc = rgn->rects[i];
update |= do_fill_rect(ctx, &rc, color);
}
 
if (update)
{
if (rgn->extents.l < ctx->rcu.l)
ctx->rcu.l = rgn->extents.l;
if (rgn->extents.t < ctx->rcu.t)
ctx->rcu.t = rgn->extents.t;
if (rgn->extents.r > ctx->rcu.r)
ctx->rcu.r = rgn->extents.r;
if (rgn->extents.b > ctx->rcu.b)
ctx->rcu.b = rgn->extents.b;
ctx->dirty = 1;
};
}
 
void px_draw_glyph(ctx_t *ctx, const void *buffer, int pitch, const rect_t *rc, color_t color)
{
rect_t rc_dst = *rc;
int srcx, srcy;
 
if (!clip_rect(&ctx->rc, &rc_dst))
{
int width;
int height;
unsigned char *dst = ctx->buffer;
const unsigned char *src = buffer;
 
width = rc_dst.r - rc_dst.l;
height = rc_dst.b - rc_dst.t;
 
srcx = rc_dst.l - rc->l;
srcy = rc_dst.t - rc->t;
dst += ctx->pitch * rc_dst.t + rc_dst.l * sizeof(color_t);
src += pitch * srcy + srcx;
ctx->px_glyph(dst, ctx->pitch, src, pitch, width, height, color);
 
if (rc_dst.l < ctx->rcu.l)
ctx->rcu.l = rc_dst.l;
if (rc_dst.t < ctx->rcu.t)
ctx->rcu.t = rc_dst.t;
if (rc_dst.r > ctx->rcu.r)
ctx->rcu.r = rc_dst.r;
if (rc_dst.b > ctx->rcu.b)
ctx->rcu.b = rc_dst.b;
 
ctx->dirty = 1;
};
};
/contrib/sdk/samples/freetype/txview/pxdraw/dutils.c
0,0 → 1,226
#include <mmintrin.h>
#include <xmmintrin.h>
#include <emmintrin.h>
 
typedef unsigned int color_t;
 
void px_rect_alu(void *dst_addr, int pitch, int w, int h, color_t src_color)
{
while (h--)
{
char *tmp = dst_addr;
dst_addr = tmp + pitch;
__asm__ __volatile__(
"cld; rep stosl\n\t"
:: "D"(tmp), "a"(src_color), "c"(w)
: "flags");
};
};
 
void px_rect_mmx(void *dst_addr, int pitch, int w, int h, color_t src_color)
{
register __m64 color;
 
color = _mm_cvtsi32_si64(src_color);
color = _mm_unpacklo_pi32(color, color);
 
while (h--)
{
char *tmp = dst_addr;
char *end = tmp + w * sizeof(color_t);
dst_addr = tmp + pitch;
 
int t = (int)tmp;
if (t & 4)
{
*(color_t*)tmp = src_color;
tmp += 4;
};
 
while (tmp + 64 <= end)
{
__m64 *_tmp = (__m64*)tmp;
_tmp[0] = color;
_tmp[1] = color;
_tmp[2] = color;
_tmp[3] = color;
_tmp[4] = color;
_tmp[5] = color;
_tmp[6] = color;
_tmp[7] = color;
tmp += 64;
};
if (tmp + 32 <= end)
{
__m64 *_tmp = (__m64*)tmp;
_tmp[0] = color;
_tmp[1] = color;
_tmp[2] = color;
_tmp[3] = color;
tmp += 32;
};
if (tmp + 16 <= end)
{
__m64 *_tmp = (__m64*)tmp;
_tmp[0] = color;
_tmp[1] = color;
tmp += 16;
};
if (tmp + 8 <= end)
{
__m64 *_tmp = (__m64*)tmp;
_tmp[0] = color;
tmp += 8;
};
if (tmp < end)
*(color_t*)tmp = src_color;
};
_mm_empty();
};
 
void px_rect_xmm(void *dst_addr, int pitch, int w, int h, color_t dst_color)
{
__m128i color;
 
color = _mm_set_epi32(dst_color, dst_color, dst_color, dst_color);
 
while (h--)
{
char *tmp = dst_addr;
char *end = tmp + w * sizeof(color_t);
dst_addr = tmp + pitch;
 
if ((int)tmp & 4)
{
*(color_t*)tmp = dst_color;
tmp += 4;
};
if ((int)tmp & 8)
{
__m128i *_tmp = (__m128i*)tmp;
_mm_storel_epi64(_tmp, color);
tmp += 8;
};
 
while (tmp + 128 <= end)
{
__m128i *_tmp = (__m128i*)tmp;
_mm_store_si128(&_tmp[0], color);
_mm_store_si128(&_tmp[1], color);
_mm_store_si128(&_tmp[2], color);
_mm_store_si128(&_tmp[3], color);
_mm_store_si128(&_tmp[4], color);
_mm_store_si128(&_tmp[5], color);
_mm_store_si128(&_tmp[6], color);
_mm_store_si128(&_tmp[7], color);
tmp += 128;
};
if (tmp + 64 <= end)
{
__m128i *_tmp = (__m128i*)tmp;
_mm_store_si128(&_tmp[0], color);
_mm_store_si128(&_tmp[1], color);
_mm_store_si128(&_tmp[2], color);
_mm_store_si128(&_tmp[3], color);
tmp += 64;
};
if (tmp + 32 <= end)
{
__m128i *_tmp = (__m128i*)tmp;
_mm_store_si128(&_tmp[0], color);
_mm_store_si128(&_tmp[1], color);
tmp += 32;
};
if (tmp + 16 <= end)
{
__m128i *_tmp = (__m128i*)tmp;
_mm_store_si128(&_tmp[0], color);
tmp += 16;
};
if (tmp + 8 <= end)
{
__m128i *_tmp = (__m128i*)tmp;
_mm_storel_epi64(_tmp, color);
tmp += 8;
};
if (tmp < end)
*(color_t*)tmp = dst_color;
};
}
 
void px_glyph_alu(void *dst_addr, int dst_pitch,const void *src_addr, int src_pitch,
int width, int height, color_t src_color)
{
while (height-- > 0)
{
int w = width;
const unsigned char *src = src_addr;
color_t *dst = dst_addr;
 
dst_addr = (char*)dst + dst_pitch;
src_addr = src + src_pitch;
 
while (w-- > 0)
{
unsigned char a = *src++;
color_t dst_color = *(color_t*)dst;
unsigned int rb = dst_color & 0xff00ff;
unsigned int g = dst_color & 0x00ff00;
 
rb += ((src_color & 0xff00ff) - rb) * a >> 8;
g += ((src_color & 0x00ff00) - g) * a >> 8;
 
*dst++ = (src_color & 0xFF000000) | (rb & 0xff00ff) | (g & 0xff00);
};
}
}
 
__m64 m_4x0080 = { 0x00800080, 0x00800080 };
__m64 m_4x0101 = { 0x01010101, 0x01010101 };
__m64 m_4x00FF = { 0x00FF00FF, 0x00FF00FF };
__m64 m_zero = { 0 };
 
void px_glyph_sse(void *dst_addr, int dst_pitch, const void *src_addr, int src_pitch,
int width, int height, color_t src_color)
{
static __m64 m_4x0080 = { 0x00800080, 0x00800080 };
static __m64 m_4x0101 = { 0x01010101, 0x01010101 };
static __m64 m_4x00FF = { 0x00FF00FF, 0x00FF00FF };
static __m64 m_zero = { 0 };
 
__m64 color;
 
color = _mm_cvtsi32_si64(src_color);
color = _m_punpcklbw(color, m_zero);
while (height-- > 0)
{
int w = width;
const unsigned char *tmpsrc = src_addr;
color_t *tmpdst = dst_addr;
 
dst_addr = (char*)tmpdst + dst_pitch;
src_addr = tmpsrc + src_pitch;
 
while (w-- > 0)
{
__m64 m_alpha, m_1_minus_alpha;
__m64 src_alpha, dst_color;
 
unsigned int alpha = *tmpsrc++;
m_alpha = _mm_cvtsi32_si64((alpha << 16) | alpha);
dst_color = _mm_cvtsi32_si64(*(int*)tmpdst);
 
m_alpha = _mm_unpacklo_pi32(m_alpha, m_alpha);
m_1_minus_alpha = _m_psubb(m_4x00FF, m_alpha);
dst_color = _m_punpcklbw(dst_color, m_zero);
src_alpha = _m_pmullw(color, m_alpha);
dst_color = _m_pmullw(dst_color, m_1_minus_alpha);
dst_color = _m_paddw(src_alpha, dst_color);
dst_color = _m_paddw(dst_color, m_4x0080);
dst_color = _mm_mulhi_pu16(dst_color, m_4x0101);
dst_color = _mm_packs_pu16(dst_color, dst_color);
*tmpdst++ = _mm_cvtsi64_si32(dst_color);
};
}
_mm_empty();
};
/contrib/sdk/samples/freetype/txview/pxdraw/internal.h
0,0 → 1,31
 
#define __ALIGN_MASK(x,mask) (((x)+(mask))&~(mask))
#define ALIGN(x,a) __ALIGN_MASK(x,(typeof(x))(a)-1)
 
struct context
{
int x;
int y;
int width;
int height;
rect_t rc;
rect_t rcu;
void *buffer;
size_t pitch;
size_t size;
int dirty;
void (*px_rect_simd)(void *dst_addr, int pitch, int w, int h, color_t dst_color);
void (*px_glyph)(void *dst_addr, int dst_pitch, const void *src_addr, int src_pitch,
int width, int height, color_t src_color);
};
 
 
void px_rect_alu(void *dst_addr, int pitch, int w, int h, color_t src_color);
void px_rect_mmx(void *dst_addr, int pitch, int w, int h, color_t src_color);
void px_rect_xmm(void *dst_addr, int pitch, int w, int h, color_t dst_color);
void px_glyph_alu(void *dst_addr, int dst_pitch,const void *src_addr,
int src_pitch, int width, int height, color_t src_color);
 
void px_glyph_sse(void *dst_addr, int dst_pitch, const void *src_addr,
int src_pitch, int width, int height, color_t src_color);
 
/contrib/sdk/samples/freetype/txview/pxdraw/pxdraw.h
0,0 → 1,46
#ifndef __PXDRAW_H__
#define __PXDRAW_H__
 
#include <stdint.h>
 
#if defined __cplusplus
extern "C" {
#endif
 
typedef unsigned int color_t;
typedef struct context ctx_t;
 
typedef struct
{
int l;
int t;
int r;
int b;
}rect_t;
 
typedef struct
{
int num_rects;
rect_t *rects;
rect_t extents;
}rgn_t;
 
rgn_t* create_round_rect_rgn(int left, int top, int right, int bottom,
int ellipse_width, int ellipse_height);
void destroy_region(rgn_t *rgn);
 
ctx_t* create_context(int x, int y, int width, int height);
int resize_context(ctx_t *ctx, int width, int height);
void clear_context(ctx_t *ctx, color_t color);
void show_context(ctx_t *ctx);
void scroll_context(ctx_t *ctx, int dst_y, int src_y, int rows);
 
int px_hline(ctx_t*ctx, int x, int y, int width, color_t color);
void px_vline(ctx_t*ctx, int x, int y, int height, color_t color);
void px_fill_rect(ctx_t *ctx, const rect_t *src, color_t color);
void px_draw_glyph(ctx_t *ctx, const void *buffer, int pitch, const rect_t *rc, color_t color);
 
#if defined __cplusplus
}
#endif
#endif /* __PXDRAW_H__ */
/contrib/sdk/samples/freetype/txview/pxdraw/region.c
0,0 → 1,93
#include <stdlib.h>
#include "pxdraw.h"
 
#define max(a,b) (((a) > (b)) ? (a) : (b))
#define min(a,b) (((a) < (b)) ? (a) : (b))
 
rgn_t* create_round_rect_rgn(int left, int top, int right, int bottom,
int ellipse_width, int ellipse_height)
{
rgn_t *obj;
rect_t *rects;
int a, b, i, x, y;
int64_t asq, bsq, dx, dy, err;
 
right--;
bottom--;
 
ellipse_width = min(right - left, abs(ellipse_width));
ellipse_height = min(bottom - top, abs(ellipse_height));
 
obj = malloc(sizeof(rgn_t));
if (obj == NULL)
return NULL;
 
obj->num_rects = ellipse_height;
obj->extents.l = left;
obj->extents.t = top;
obj->extents.r = right;
obj->extents.b = bottom;
 
obj->rects = rects = malloc(obj->num_rects * sizeof(rect_t));
if (rects == NULL)
{
free(obj);
return NULL;
};
 
/* based on an algorithm by Alois Zingl */
 
a = ellipse_width - 1;
b = ellipse_height - 1;
asq = (int64_t)8 * a * a;
bsq = (int64_t)8 * b * b;
dx = (int64_t)4 * b * b * (1 - a);
dy = (int64_t)4 * a * a * (1 + (b % 2));
err = dx + dy + a * a * (b % 2);
 
x = 0;
y = ellipse_height / 2;
 
rects[y].l = left;
rects[y].r = right;
 
while (x <= ellipse_width / 2)
{
int64_t e2 = 2 * err;
if (e2 >= dx)
{
x++;
err += dx += bsq;
}
if (e2 <= dy)
{
y++;
err += dy += asq;
rects[y].l = left + x;
rects[y].r = right - x;
}
}
 
for (i = 0; i < ellipse_height / 2; i++)
{
rects[i].l = rects[b - i].l;
rects[i].r = rects[b - i].r;
rects[i].t = top + i;
rects[i].b = rects[i].t + 1;
}
for (; i < ellipse_height; i++)
{
rects[i].t = bottom - ellipse_height + i;
rects[i].b = rects[i].t + 1;
}
rects[ellipse_height / 2].t = top + ellipse_height / 2; /* extend to top of rectangle */
 
return obj;
};
 
void destroy_region(rgn_t *rgn)
{
free(rgn->rects);
free(rgn);
};