Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Mesa 3-D graphics library
  3.  *
  4.  * Copyright (C) 2010 LunarG Inc.
  5.  *
  6.  * Permission is hereby granted, free of charge, to any person obtaining a
  7.  * copy of this software and associated documentation files (the "Software"),
  8.  * to deal in the Software without restriction, including without limitation
  9.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  10.  * and/or sell copies of the Software, and to permit persons to whom the
  11.  * Software is furnished to do so, subject to the following conditions:
  12.  *
  13.  * The above copyright notice and this permission notice shall be included
  14.  * in all copies or substantial portions of the Software.
  15.  *
  16.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  19.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20.  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  21.  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  22.  * DEALINGS IN THE SOFTWARE.
  23.  *
  24.  * Authors:
  25.  *    Chia-I Wu <olv@lunarg.com>
  26.  */
  27.  
  28. #include <sys/mman.h>
  29. #include <sys/ioctl.h>
  30. #include <linux/fb.h>
  31.  
  32. #include "pipe/p_compiler.h"
  33. #include "util/u_format.h"
  34. #include "util/u_math.h"
  35. #include "util/u_memory.h"
  36. #include "state_tracker/sw_winsys.h"
  37.  
  38. #include "fbdev_sw_winsys.h"
  39.  
  40. struct fbdev_sw_displaytarget
  41. {
  42.    enum pipe_format format;
  43.    unsigned width;
  44.    unsigned height;
  45.    unsigned stride;
  46.  
  47.    void *data;
  48.    void *mapped;
  49. };
  50.  
  51. struct fbdev_sw_winsys
  52. {
  53.    struct sw_winsys base;
  54.  
  55.    int fd;
  56.  
  57.    struct fb_fix_screeninfo finfo;
  58.    unsigned rows;
  59.    unsigned stride;
  60. };
  61.  
  62. static INLINE struct fbdev_sw_displaytarget *
  63. fbdev_sw_displaytarget(struct sw_displaytarget *dt)
  64. {
  65.    return (struct fbdev_sw_displaytarget *) dt;
  66. }
  67.  
  68. static INLINE struct fbdev_sw_winsys *
  69. fbdev_sw_winsys(struct sw_winsys *ws)
  70. {
  71.    return (struct fbdev_sw_winsys *) ws;
  72. }
  73.  
  74. static void
  75. fbdev_displaytarget_display(struct sw_winsys *ws,
  76.                             struct sw_displaytarget *dt,
  77.                             void *winsys_private)
  78. {
  79.    struct fbdev_sw_winsys *fbdev = fbdev_sw_winsys(ws);
  80.    struct fbdev_sw_displaytarget *src = fbdev_sw_displaytarget(dt);
  81.    const struct fbdev_sw_drawable *dst =
  82.       (const struct fbdev_sw_drawable *) winsys_private;
  83.    unsigned height, row_offset, row_len, i;
  84.    void *fbmem;
  85.  
  86.    /* FIXME format conversion */
  87.    if (dst->format != src->format) {
  88.       assert(0);
  89.       return;
  90.    }
  91.  
  92.    height = dst->height;
  93.    if (dst->y + dst->height > fbdev->rows) {
  94.       /* nothing to copy */
  95.       if (dst->y >= fbdev->rows)
  96.          return;
  97.  
  98.       height = fbdev->rows - dst->y;
  99.    }
  100.  
  101.    row_offset = util_format_get_stride(dst->format, dst->x);
  102.    row_len = util_format_get_stride(dst->format, dst->width);
  103.    if (row_offset + row_len > fbdev->stride) {
  104.       /* nothing to copy */
  105.       if (row_offset >= fbdev->stride)
  106.          return;
  107.  
  108.       row_len = fbdev->stride - row_offset;
  109.    }
  110.  
  111.    fbmem = mmap(0, fbdev->finfo.smem_len,
  112.          PROT_WRITE, MAP_SHARED, fbdev->fd, 0);
  113.    if (fbmem == MAP_FAILED)
  114.       return;
  115.  
  116.    for (i = 0; i < height; i++) {
  117.       char *from = (char *) src->data + src->stride * i;
  118.       char *to = (char *) fbmem + fbdev->stride * (dst->y + i) + row_offset;
  119.  
  120.       memcpy(to, from, row_len);
  121.    }
  122.  
  123.    munmap(fbmem, fbdev->finfo.smem_len);
  124. }
  125.  
  126. static void
  127. fbdev_displaytarget_unmap(struct sw_winsys *ws,
  128.                            struct sw_displaytarget *dt)
  129. {
  130.    struct fbdev_sw_displaytarget *fbdt = fbdev_sw_displaytarget(dt);
  131.    fbdt->mapped = NULL;
  132. }
  133.  
  134. static void *
  135. fbdev_displaytarget_map(struct sw_winsys *ws,
  136.                         struct sw_displaytarget *dt,
  137.                         unsigned flags)
  138. {
  139.    struct fbdev_sw_displaytarget *fbdt = fbdev_sw_displaytarget(dt);
  140.    fbdt->mapped = fbdt->data;
  141.    return fbdt->mapped;
  142. }
  143.  
  144. static void
  145. fbdev_displaytarget_destroy(struct sw_winsys *ws,
  146.                             struct sw_displaytarget *dt)
  147. {
  148.    struct fbdev_sw_displaytarget *fbdt = fbdev_sw_displaytarget(dt);
  149.  
  150.    if (fbdt->data)
  151.       align_free(fbdt->data);
  152.  
  153.    FREE(fbdt);
  154. }
  155.  
  156. static struct sw_displaytarget *
  157. fbdev_displaytarget_create(struct sw_winsys *ws,
  158.                            unsigned tex_usage,
  159.                            enum pipe_format format,
  160.                            unsigned width, unsigned height,
  161.                            unsigned alignment,
  162.                            unsigned *stride)
  163. {
  164.    struct fbdev_sw_displaytarget *fbdt;
  165.    unsigned nblocksy, size, format_stride;
  166.  
  167.    fbdt = CALLOC_STRUCT(fbdev_sw_displaytarget);
  168.    if (!fbdt)
  169.       return NULL;
  170.  
  171.    fbdt->format = format;
  172.    fbdt->width = width;
  173.    fbdt->height = height;
  174.  
  175.    format_stride = util_format_get_stride(format, width);
  176.    fbdt->stride = align(format_stride, alignment);
  177.  
  178.    nblocksy = util_format_get_nblocksy(format, height);
  179.    size = fbdt->stride * nblocksy;
  180.  
  181.    fbdt->data = align_malloc(size, alignment);
  182.    if (!fbdt->data) {
  183.       FREE(fbdt);
  184.       return NULL;
  185.    }
  186.  
  187.    *stride = fbdt->stride;
  188.  
  189.    return (struct sw_displaytarget *) fbdt;
  190. }
  191.  
  192. static boolean
  193. fbdev_is_displaytarget_format_supported(struct sw_winsys *ws,
  194.                                         unsigned tex_usage,
  195.                                         enum pipe_format format)
  196. {
  197.    return TRUE;
  198. }
  199.  
  200. static void
  201. fbdev_destroy(struct sw_winsys *ws)
  202. {
  203.    struct fbdev_sw_winsys *fbdev = fbdev_sw_winsys(ws);
  204.  
  205.    FREE(fbdev);
  206. }
  207.  
  208. struct sw_winsys *
  209. fbdev_create_sw_winsys(int fd)
  210. {
  211.    struct fbdev_sw_winsys *fbdev;
  212.  
  213.    fbdev = CALLOC_STRUCT(fbdev_sw_winsys);
  214.    if (!fbdev)
  215.       return NULL;
  216.  
  217.    fbdev->fd = fd;
  218.    if (ioctl(fbdev->fd, FBIOGET_FSCREENINFO, &fbdev->finfo)) {
  219.       FREE(fbdev);
  220.       return NULL;
  221.    }
  222.  
  223.    fbdev->rows = fbdev->finfo.smem_len / fbdev->finfo.line_length;
  224.    fbdev->stride = fbdev->finfo.line_length;
  225.  
  226.    fbdev->base.destroy = fbdev_destroy;
  227.    fbdev->base.is_displaytarget_format_supported =
  228.       fbdev_is_displaytarget_format_supported;
  229.  
  230.    fbdev->base.displaytarget_create = fbdev_displaytarget_create;
  231.    fbdev->base.displaytarget_destroy = fbdev_displaytarget_destroy;
  232.    fbdev->base.displaytarget_map = fbdev_displaytarget_map;
  233.    fbdev->base.displaytarget_unmap = fbdev_displaytarget_unmap;
  234.  
  235.    fbdev->base.displaytarget_display = fbdev_displaytarget_display;
  236.  
  237.    return &fbdev->base;
  238. }
  239.