Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. #include <stdlib.h>
  2. #include <kos32sys.h>
  3. #include "pxdraw.h"
  4. #include "internal.h"
  5.  
  6. ctx_t* create_context(int x, int y, int width, int height)
  7. {
  8.         ctx_t *ctx;
  9.  
  10.         ctx = malloc(sizeof(ctx_t));
  11.         if (ctx == NULL)
  12.         goto err_0;
  13.  
  14.     ctx->pitch = ALIGN(width * sizeof(color_t), 16);
  15.     ctx->size = ALIGN(ctx->pitch * height, 4096);
  16.  
  17.     ctx->buffer = user_alloc(ctx->size+4096);
  18.     if (ctx->buffer == NULL)
  19.         goto err_1;
  20.  
  21.         ctx->x = x;
  22.         ctx->y = y;
  23.         ctx->width = width;
  24.         ctx->height = height;
  25.  
  26.         ctx->rc.l = 0;
  27.         ctx->rc.t = 0;
  28.         ctx->rc.r = width;
  29.         ctx->rc.b = height;
  30.  
  31.         ctx->rcu.l = 0;
  32.         ctx->rcu.t = 0;
  33.         ctx->rcu.r = ctx->width;
  34.         ctx->rcu.b = ctx->height;
  35.     ctx->dirty = 1;
  36.  
  37.     __builtin_cpu_init ();
  38.     if (__builtin_cpu_supports ("sse2"))
  39.         ctx->px_rect_simd = px_rect_xmm;
  40.     else if (__builtin_cpu_supports ("mmx"))
  41.         ctx->px_rect_simd = px_rect_mmx;
  42.     else
  43.         ctx->px_rect_simd = px_rect_alu;
  44.  
  45.     if (__builtin_cpu_supports ("sse2"))
  46.                 ctx->px_glyph = px_glyph_sse;
  47.         else
  48.         ctx->px_glyph = px_glyph_alu;
  49.  
  50.         return ctx;
  51.  
  52. err_1:
  53.     free(ctx);
  54. err_0:
  55.     return NULL;
  56. };
  57.  
  58. int resize_context(ctx_t *ctx, int width, int height)
  59. {
  60.     int size;
  61.     int pitch;
  62.  
  63.     pitch = ALIGN(width * sizeof(color_t), 16);
  64.     size = ALIGN(pitch * height, 4096);
  65.  
  66.     if (size > ctx->size)
  67.     {
  68.         ctx->buffer = user_realloc(ctx->buffer, size);    /* grow buffer */
  69.         if (ctx->buffer == NULL)
  70.             return -1;
  71.  
  72.         ctx->size = size;
  73.     }
  74.     else if (size < ctx->size)
  75.         user_unmap(ctx->buffer, size, ctx->size - size); /* unmap unused pages */
  76.  
  77.     ctx->width  = width;
  78.     ctx->height = height;
  79.     ctx->pitch  = pitch;
  80.  
  81.     ctx->rc.l   = 0;
  82.     ctx->rc.t   = 0;
  83.     ctx->rc.r   = width;
  84.     ctx->rc.b   = height;
  85.  
  86.     ctx->rcu.l  = ctx->rcu.t = 0;
  87.     ctx->rcu.r  = ctx->rcu.b = 0;
  88.  
  89.     return 0;
  90. };
  91.  
  92. void clear_context(ctx_t *ctx, color_t color)
  93. {
  94.         size_t size;
  95.  
  96.         size = ctx->pitch * ctx->height;
  97.  
  98.         if (size >= 1024)
  99.                 ctx->px_rect_simd(ctx->buffer, ctx->pitch, ctx->width, ctx->height, color);
  100.         else
  101.                 px_rect_alu(ctx->buffer, ctx->pitch, ctx->width, ctx->height, color);
  102.  
  103.         ctx->rcu.l = 0;
  104.         ctx->rcu.t = 0;
  105.         ctx->rcu.r = ctx->width;
  106.         ctx->rcu.b = ctx->height;
  107.     ctx->dirty = 1;
  108. };
  109.  
  110. void show_context(ctx_t *ctx)
  111. {
  112.     struct blit_call bc;
  113.     int ret;
  114.  
  115.     bc.dstx   = ctx->x;
  116.     bc.dsty   = ctx->y;
  117.     bc.w      = ctx->width;
  118.     bc.h      = ctx->height;
  119.     bc.srcx   = 0;
  120.     bc.srcy   = 0;
  121.     bc.srcw   = ctx->width;
  122.     bc.srch   = ctx->height;
  123.     bc.stride = ctx->pitch;
  124.     bc.bitmap = ctx->buffer;
  125.  
  126.     __asm__ __volatile__(
  127.     "int $0x40":"=a"(ret):"a"(73), "b"(0x00),
  128.     "c"(&bc):"memory");
  129.  
  130.     ctx->dirty = 0;
  131. };
  132.  
  133. void scroll_context(ctx_t *ctx, int dst_y, int  src_y, int rows)
  134. {
  135.     char *dst;
  136.     char *src;
  137.  
  138.     dst = ctx->buffer + dst_y * ctx->pitch;
  139.     src = ctx->buffer + src_y * ctx->pitch;
  140.  
  141.     __builtin_memmove(dst, src, rows * ctx->pitch);
  142.     ctx->dirty = 1;
  143. }
  144.  
  145. static int clip_rect(const rect_t *clip, rect_t *rc)
  146. {
  147.         if (rc->l > rc->r)
  148.                 return 1;
  149.         if (rc->t > rc->b)
  150.                 return 1;
  151.  
  152.         if (rc->l < clip->l)
  153.                 rc->l = clip->l;
  154.         else if (rc->l >= clip->r)
  155.                 return 1;
  156.  
  157.         if (rc->t < clip->t)
  158.                 rc->t = clip->t;
  159.         else if (rc->t >= clip->b)
  160.                 return 1;
  161.  
  162.         if (rc->r < clip->l)
  163.                 return 1;
  164.         else if (rc->r > clip->r)
  165.                 rc->r = clip->r;
  166.  
  167.         if (rc->b < clip->t)
  168.                 return 1;
  169.         else if (rc->b > clip->b)
  170.                 rc->b = clip->b;
  171.  
  172.         if ((rc->l == rc->r) ||
  173.                 (rc->t == rc->b))
  174.                 return 1;
  175.         return 0;
  176. }
  177.  
  178. int px_hline(ctx_t*ctx, int x, int y, int width, color_t color)
  179. {
  180.     char *dst_addr;
  181.  
  182.     int xr = x + width;
  183.  
  184.     if(y < ctx->rc.t)
  185.         return 0;
  186.     else if(y >= ctx->rc.b)
  187.         return 0;
  188.  
  189.     if(x < ctx->rc.l)
  190.         x = ctx->rc.l;
  191.     else if(x >= ctx->rc.r)
  192.         return 0;
  193.  
  194.     if(xr <= ctx->rc.l)
  195.         return 0;
  196.     else if(xr > ctx->rc.r)
  197.         xr = ctx->rc.r;
  198.  
  199.     dst_addr = ctx->buffer;
  200.     dst_addr+= ctx->pitch * y + x * sizeof(color_t);
  201.  
  202.     __asm__ __volatile__
  203.     (" cld; rep stosl\n\t"
  204.       :: "D" (dst_addr),"c" (xr-x), "a" (color)
  205.       : "flags");
  206. };
  207.  
  208. void px_vline(ctx_t*ctx, int x, int y, int height, color_t color)
  209. {
  210.     char *dst_addr;
  211.  
  212.     int yb = y + height;
  213.  
  214.     if(x < ctx->rc.l)
  215.         return;
  216.     else if(x >= ctx->rc.r)
  217.         return;
  218.  
  219.     if(y < ctx->rc.t)
  220.         y = ctx->rc.t;
  221.     else if(y >= ctx->rc.b)
  222.         return;
  223.  
  224.     if(yb <= ctx->rc.t)
  225.         return;
  226.     else if(yb > ctx->rc.b)
  227.         yb = ctx->rc.b;
  228.  
  229.     dst_addr = ctx->buffer;
  230.     dst_addr+= ctx->pitch * y + x * sizeof(color_t);
  231.  
  232.     while(y < yb)
  233.     {
  234.         color_t *t = (color_t*)dst_addr;
  235.         *t = color;
  236.         y++;
  237.         dst_addr+= ctx->pitch;
  238.     };
  239. };
  240.  
  241. static int do_fill_rect(ctx_t *ctx, rect_t *rc, color_t color)
  242. {
  243.         if (!clip_rect(&ctx->rc, rc))
  244.         {
  245.                 int w, h;
  246.                 char *dst_addr;
  247.  
  248.                 w = rc->r - rc->l;
  249.                 h = rc->b - rc->t;
  250.  
  251.                 dst_addr = ctx->buffer;
  252.                 dst_addr += ctx->pitch * rc->t + rc->l * sizeof(color_t);
  253.                 if (w * h >= 256)
  254.                         ctx->px_rect_simd(dst_addr, ctx->pitch, w, h, color);
  255.                 else
  256.                         px_rect_alu(dst_addr, ctx->pitch, w, h, color);
  257.                 return 1;
  258.         };
  259.         return 0;
  260. };
  261.  
  262. void px_fill_rect(ctx_t *ctx, const rect_t *src, color_t color)
  263. {
  264.         rect_t rc = *src;
  265.         int update;
  266.  
  267.         update = do_fill_rect(ctx, &rc, color);
  268.  
  269.         if(update)
  270.         {
  271.                 if (rc.l < ctx->rcu.l)
  272.                         ctx->rcu.l = rc.l;
  273.                 if (rc.t < ctx->rcu.t)
  274.                         ctx->rcu.t = rc.t;
  275.                 if (rc.r > ctx->rcu.r)
  276.                         ctx->rcu.r = rc.r;
  277.                 if (rc.b > ctx->rcu.b)
  278.                         ctx->rcu.b = rc.b;
  279.         ctx->dirty = 1;
  280.         };
  281. }
  282.  
  283. void px_fill_region(ctx_t *ctx, const rgn_t *rgn, color_t color)
  284. {
  285.         int update = 0;
  286.  
  287.         for (int i = 0; i < rgn->num_rects; i++)
  288.         {
  289.                 rect_t rc = rgn->rects[i];
  290.                 update |= do_fill_rect(ctx, &rc, color);
  291.         }
  292.  
  293.         if (update)
  294.         {
  295.                 if (rgn->extents.l < ctx->rcu.l)
  296.                         ctx->rcu.l = rgn->extents.l;
  297.                 if (rgn->extents.t < ctx->rcu.t)
  298.                         ctx->rcu.t = rgn->extents.t;
  299.                 if (rgn->extents.r > ctx->rcu.r)
  300.                         ctx->rcu.r = rgn->extents.r;
  301.                 if (rgn->extents.b > ctx->rcu.b)
  302.                         ctx->rcu.b = rgn->extents.b;
  303.         ctx->dirty = 1;
  304.         };
  305. }
  306.  
  307. void px_draw_glyph(ctx_t *ctx, const void *buffer, int pitch, const rect_t *rc, color_t color)
  308. {
  309.         rect_t rc_dst = *rc;
  310.         int srcx, srcy;
  311.  
  312.         if (!clip_rect(&ctx->rc, &rc_dst))
  313.         {
  314.                 int width;
  315.                 int height;
  316.                 unsigned char *dst = ctx->buffer;
  317.                 const unsigned char *src = buffer;
  318.  
  319.                 width = rc_dst.r - rc_dst.l;
  320.                 height = rc_dst.b - rc_dst.t;
  321.  
  322.                 srcx = rc_dst.l - rc->l;
  323.                 srcy = rc_dst.t - rc->t;
  324.                 dst += ctx->pitch * rc_dst.t + rc_dst.l * sizeof(color_t);
  325.                 src += pitch * srcy + srcx;
  326.         ctx->px_glyph(dst, ctx->pitch, src, pitch, width, height, color);
  327.  
  328.                 if (rc_dst.l < ctx->rcu.l)
  329.                         ctx->rcu.l = rc_dst.l;
  330.                 if (rc_dst.t < ctx->rcu.t)
  331.                         ctx->rcu.t = rc_dst.t;
  332.                 if (rc_dst.r > ctx->rcu.r)
  333.                         ctx->rcu.r = rc_dst.r;
  334.                 if (rc_dst.b > ctx->rcu.b)
  335.                         ctx->rcu.b = rc_dst.b;
  336.  
  337.         ctx->dirty = 1;
  338.         };
  339. };
  340.