Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/hid/fb/fb.c

    rffa2c8ef rc6f08726  
    4949#include <ipc/ns.h>
    5050#include <ipc/services.h>
    51 #include <kernel/errno.h>
    52 #include <kernel/genarch/fb/visuals.h>
     51#include <errno.h>
     52#include <abi/fb/visuals.h>
    5353#include <io/color.h>
    5454#include <io/style.h>
     
    5959#include <byteorder.h>
    6060#include <io/screenbuffer.h>
    61 
     61#include <imgmap.h>
    6262#include "font-8x16.h"
    6363#include "fb.h"
    6464#include "main.h"
    65 #include "ppm.h"
    66 
    6765#include "pointer.xbm"
    6866#include "pointer_mask.xbm"
    6967
     68// FIXME: remove this header
     69#include <abi/ipc/methods.h>
     70
    7071#define DEFAULT_BGCOLOR  0xf0f0f0
    7172#define DEFAULT_FGCOLOR  0x000000
     
    7576#define MAX_ANIM_LEN    8
    7677#define MAX_ANIMATIONS  4
    77 #define MAX_PIXMAPS     256  /**< Maximum number of saved pixmaps */
     78#define MAX_IMGMAPS     256  /**< Maximum number of saved image maps */
    7879#define MAX_VIEWPORTS   128  /**< Viewport is a rectangular area on the screen */
    7980
     
    159160        unsigned int pos;
    160161        unsigned int animlen;
    161         unsigned int pixmaps[MAX_ANIM_LEN];
     162        unsigned int imgmaps[MAX_ANIM_LEN];
    162163} animation_t;
    163164
     
    165166static bool anims_enabled;
    166167
    167 typedef struct {
    168         unsigned int width;
    169         unsigned int height;
    170         uint8_t *data;
    171 } pixmap_t;
    172 
    173 static pixmap_t pixmaps[MAX_PIXMAPS];
     168static imgmap_t *imgmaps[MAX_IMGMAPS];
    174169static viewport_t viewports[128];
    175170
     
    211206static void draw_vp_glyph(viewport_t *vport, bool cursor, unsigned int col,
    212207    unsigned int row);
    213 
    214208
    215209#define RED(x, bits)                 (((x) >> (8 + 8 + 8 - (bits))) & ((1 << (bits)) - 1))
     
    874868}
    875869
    876 
    877870/** Show cursor if cursor showing is enabled
    878871 *
     
    887880}
    888881
    889 
    890882/** Invert cursor, if it is enabled
    891883 *
     
    898890                cursor_show(vport);
    899891}
    900 
    901892
    902893/** Draw character at given position relative to viewport
     
    980971}
    981972
    982 
    983 static void putpixel_pixmap(void *data, unsigned int x, unsigned int y, uint32_t color)
    984 {
    985         int pm = *((int *) data);
    986         pixmap_t *pmap = &pixmaps[pm];
    987         unsigned int pos = (y * pmap->width + x) * screen.pixelbytes;
    988        
    989         screen.rgb_conv(&pmap->data[pos], color);
    990 }
    991 
    992 
    993 static void putpixel(void *data, unsigned int x, unsigned int y, uint32_t color)
    994 {
    995         viewport_t *vport = (viewport_t *) data;
     973static void putpixel(viewport_t *vport, unsigned int x, unsigned int y,
     974    uint32_t color)
     975{
    996976        unsigned int dx = vport->x + x;
    997977        unsigned int dy = vport->y + y;
     
    1000980}
    1001981
    1002 
    1003 /** Return first free pixmap
    1004  *
    1005  */
    1006 static int find_free_pixmap(void)
     982/** Draw image map
     983 *
     984 * @param[in] img       Image map.
     985 * @param[in] sx        Coordinate of upper left corner.
     986 * @param[in] sy        Coordinate of upper left corner.
     987 * @param[in] maxwidth  Maximum allowed width for picture.
     988 * @param[in] maxheight Maximum allowed height for picture.
     989 * @param[in] vport     Viewport.
     990 *
     991 * @return EOK on success.
     992 *
     993 */
     994static int imgmap_draw(imgmap_t *img, unsigned int sx, unsigned int sy,
     995    unsigned int maxwidth, unsigned int maxheight, void *vport)
     996{
     997        if (img->visual != VISUAL_BGR_8_8_8)
     998                return EINVAL;
     999       
     1000        uint8_t *data = (uint8_t *) img->data;
     1001       
     1002        for (sysarg_t y = 0; y < img->height; y++) {
     1003                for (sysarg_t x = 0; x < img->width; x++) {
     1004                        if ((x > maxwidth) || (y > maxheight)) {
     1005                                data += 3;
     1006                                continue;
     1007                        }
     1008                       
     1009                        uint32_t color = (data[2] << 16) + (data[1] << 8) + data[0];
     1010                       
     1011                        putpixel(vport, sx + x, sy + y, color);
     1012                        data += 3;
     1013                }
     1014        }
     1015       
     1016        return EOK;
     1017}
     1018
     1019/** Return first free image map
     1020 *
     1021 */
     1022static int find_free_imgmap(void)
    10071023{
    10081024        unsigned int i;
    10091025       
    1010         for (i = 0; i < MAX_PIXMAPS; i++)
    1011                 if (!pixmaps[i].data)
     1026        for (i = 0; i < MAX_IMGMAPS; i++)
     1027                if (!imgmaps[i])
    10121028                        return i;
    10131029       
     
    10151031}
    10161032
    1017 
    1018 /** Create a new pixmap and return appropriate ID
    1019  *
    1020  */
    1021 static int shm2pixmap(unsigned char *shm, size_t size)
    1022 {
    1023         int pm;
    1024         pixmap_t *pmap;
    1025        
    1026         pm = find_free_pixmap();
    1027         if (pm == -1)
     1033/** Create a new image map and return appropriate ID
     1034 *
     1035 */
     1036static int shm2imgmap(imgmap_t *shm, size_t size)
     1037{
     1038        int im = find_free_imgmap();
     1039        if (im == -1)
    10281040                return ELIMIT;
    10291041       
    1030         pmap = &pixmaps[pm];
    1031        
    1032         if (ppm_get_data(shm, size, &pmap->width, &pmap->height))
    1033                 return EINVAL;
    1034        
    1035         pmap->data = malloc(pmap->width * pmap->height * screen.pixelbytes);
    1036         if (!pmap->data)
     1042        imgmap_t *imap = malloc(size);
     1043        if (!imap)
    10371044                return ENOMEM;
    10381045       
    1039         ppm_draw(shm, size, 0, 0, pmap->width, pmap->height, putpixel_pixmap, (void *) &pm);
    1040        
    1041         return pm;
    1042 }
    1043 
     1046        memcpy(imap, shm, size);
     1047        imgmaps[im] = imap;
     1048        return im;
     1049}
    10441050
    10451051/** Handle shared memory communication calls
    10461052 *
    1047  * Protocol for drawing pixmaps:
     1053 * Protocol for drawing image maps:
    10481054 * - FB_PREPARE_SHM(client shm identification)
    10491055 * - IPC_M_AS_AREA_SEND
    1050  * - FB_DRAW_PPM(startx, starty)
     1056 * - FB_DRAW_IMGMAP(startx, starty)
    10511057 * - FB_DROP_SHM
    10521058 *
     
    10701076        static size_t intersize = 0;
    10711077       
    1072         static unsigned char *shm = NULL;
     1078        static imgmap_t *shm = NULL;
    10731079        static sysarg_t shm_id = 0;
    10741080        static size_t shm_size;
     
    10921098                                return false;
    10931099                        }
     1100                       
    10941101                        shm = dest;
    1095                        
    1096                         if (shm[0] != 'P')
    1097                                 return false;
    1098                        
    10991102                        return true;
    11001103                } else {
     
    11061109                if (shm_id)
    11071110                        retval = EBUSY;
    1108                 else 
     1111                else
    11091112                        shm_id = IPC_GET_ARG1(*call);
    11101113                break;
    1111                
    11121114        case FB_DROP_SHM:
    11131115                if (shm) {
     
    11171119                shm_id = 0;
    11181120                break;
    1119                
    1120         case FB_SHM2PIXMAP:
     1121        case FB_SHM2IMGMAP:
    11211122                if (!shm) {
    11221123                        retval = EINVAL;
    11231124                        break;
    11241125                }
    1125                 retval = shm2pixmap(shm, shm_size);
    1126                 break;
    1127         case FB_DRAW_PPM:
     1126                retval = shm2imgmap(shm, shm_size);
     1127                break;
     1128        case FB_DRAW_IMGMAP:
    11281129                if (!shm) {
    11291130                        retval = EINVAL;
    11301131                        break;
    11311132                }
     1133               
    11321134                x = IPC_GET_ARG1(*call);
    11331135                y = IPC_GET_ARG2(*call);
     
    11381140                }
    11391141               
    1140                 ppm_draw(shm, shm_size, IPC_GET_ARG1(*call),
    1141                     IPC_GET_ARG2(*call), vport->width - x, vport->height - y, putpixel, (void *) vport);
     1142                imgmap_draw(shm, IPC_GET_ARG1(*call), IPC_GET_ARG2(*call),
     1143                    vport->width - x, vport->height - y, vport);
    11421144                break;
    11431145        case FB_DRAW_TEXT_DATA:
     
    11661168        if (handled)
    11671169                async_answer_0(callid, retval);
     1170       
    11681171        return handled;
    11691172}
    11701173
    1171 
    1172 static void copy_vp_to_pixmap(viewport_t *vport, pixmap_t *pmap)
     1174static void copy_vp_to_imgmap(viewport_t *vport, imgmap_t *imap)
    11731175{
    11741176        unsigned int width = vport->width;
     
    11771179        if (width + vport->x > screen.xres)
    11781180                width = screen.xres - vport->x;
     1181       
    11791182        if (height + vport->y > screen.yres)
    11801183                height = screen.yres - vport->y;
    11811184       
    1182         unsigned int realwidth = pmap->width <= width ? pmap->width : width;
    1183         unsigned int realheight = pmap->height <= height ? pmap->height : height;
     1185        unsigned int realwidth = imap->width <= width ? imap->width : width;
     1186        unsigned int realheight = imap->height <= height ? imap->height : height;
    11841187       
    11851188        unsigned int srcrowsize = vport->width * screen.pixelbytes;
     
    11891192        for (y = 0; y < realheight; y++) {
    11901193                unsigned int tmp = (vport->y + y) * screen.scanline + vport->x * screen.pixelbytes;
    1191                 memcpy(pmap->data + srcrowsize * y, screen.fb_addr + tmp, realrowsize);
    1192         }
    1193 }
    1194 
    1195 
    1196 /** Save viewport to pixmap
    1197  *
    1198  */
    1199 static int save_vp_to_pixmap(viewport_t *vport)
    1200 {
    1201         int pm;
    1202         pixmap_t *pmap;
    1203        
    1204         pm = find_free_pixmap();
    1205         if (pm == -1)
     1194                memcpy(imap->data + srcrowsize * y, screen.fb_addr + tmp, realrowsize);
     1195        }
     1196}
     1197
     1198/** Save viewport to image map
     1199 *
     1200 */
     1201static int save_vp_to_imgmap(viewport_t *vport)
     1202{
     1203        int im = find_free_imgmap();
     1204        if (im == -1)
    12061205                return ELIMIT;
    12071206       
    1208         pmap = &pixmaps[pm];
    1209         pmap->data = malloc(screen.pixelbytes * vport->width * vport->height);
    1210         if (!pmap->data)
     1207        size_t size = screen.pixelbytes * vport->width * vport->height;
     1208        imgmap_t *imap = malloc(sizeof(imgmap_t) + size);
     1209        if (!imap)
    12111210                return ENOMEM;
    12121211       
    1213         pmap->width = vport->width;
    1214         pmap->height = vport->height;
    1215        
    1216         copy_vp_to_pixmap(vport, pmap);
    1217        
    1218         return pm;
    1219 }
    1220 
    1221 
    1222 /** Draw pixmap on screen
    1223  *
    1224  * @param vp Viewport to draw on
    1225  * @param pm Pixmap identifier
    1226  *
    1227  */
    1228 static int draw_pixmap(int vp, int pm)
    1229 {
    1230         pixmap_t *pmap = &pixmaps[pm];
     1212        imap->size = sizeof(imgmap_t) + size;
     1213        imap->width = vport->width;
     1214        imap->height = vport->height;
     1215        imap->visual = (visual_t) -1;
     1216       
     1217        copy_vp_to_imgmap(vport, imap);
     1218        imgmaps[im] = imap;
     1219        return im;
     1220}
     1221
     1222/** Draw image map to screen
     1223 *
     1224 * @param vp Viewport to draw to
     1225 * @param im Image map identifier
     1226 *
     1227 */
     1228static int draw_imgmap(int vp, int im)
     1229{
     1230        imgmap_t *imap = imgmaps[im];
     1231        if (!imap)
     1232                return EINVAL;
     1233       
    12311234        viewport_t *vport = &viewports[vp];
    12321235       
     
    12361239        if (width + vport->x > screen.xres)
    12371240                width = screen.xres - vport->x;
     1241       
    12381242        if (height + vport->y > screen.yres)
    12391243                height = screen.yres - vport->y;
    12401244       
    1241         if (!pmap->data)
    1242                 return EINVAL;
    1243        
    1244         unsigned int realwidth = pmap->width <= width ? pmap->width : width;
    1245         unsigned int realheight = pmap->height <= height ? pmap->height : height;
    1246        
    1247         unsigned int srcrowsize = vport->width * screen.pixelbytes;
    1248         unsigned int realrowsize = realwidth * screen.pixelbytes;
    1249        
    1250         unsigned int y;
    1251         for (y = 0; y < realheight; y++) {
    1252                 unsigned int tmp = (vport->y + y) * screen.scanline + vport->x * screen.pixelbytes;
    1253                 memcpy(screen.fb_addr + tmp, pmap->data + y * srcrowsize, realrowsize);
    1254         }
     1245        unsigned int realwidth = imap->width <= width ? imap->width : width;
     1246        unsigned int realheight = imap->height <= height ? imap->height : height;
     1247       
     1248        if (imap->visual == (visual_t) -1) {
     1249                unsigned int srcrowsize = vport->width * screen.pixelbytes;
     1250                unsigned int realrowsize = realwidth * screen.pixelbytes;
     1251               
     1252                unsigned int y;
     1253                for (y = 0; y < realheight; y++) {
     1254                        unsigned int tmp = (vport->y + y) * screen.scanline + vport->x * screen.pixelbytes;
     1255                        memcpy(screen.fb_addr + tmp, imap->data + y * srcrowsize, realrowsize);
     1256                }
     1257        } else
     1258                imgmap_draw(imap, 0, 0, realwidth, realheight, vport);
    12551259       
    12561260        return EOK;
    12571261}
    1258 
    12591262
    12601263/** Tick animation one step forward
     
    12761279                        continue;
    12771280               
    1278                 draw_pixmap(animations[i].vp, animations[i].pixmaps[animations[i].pos]);
     1281                draw_imgmap(animations[i].vp, animations[i].imgmaps[animations[i].pos]);
    12791282                animations[i].pos = (animations[i].pos + 1) % animations[i].animlen;
    12801283        }
     
    12861289static bool pointer_shown, pointer_enabled;
    12871290static int pointer_vport = -1;
    1288 static int pointer_pixmap = -1;
     1291static int pointer_imgmap = -1;
    12891292
    12901293
     
    13091312        }
    13101313       
    1311         if (pointer_pixmap == -1)
    1312                 pointer_pixmap = save_vp_to_pixmap(&viewports[pointer_vport]);
     1314        if (pointer_imgmap == -1)
     1315                pointer_imgmap = save_vp_to_imgmap(&viewports[pointer_vport]);
    13131316        else
    1314                 copy_vp_to_pixmap(&viewports[pointer_vport], &pixmaps[pointer_pixmap]);
     1317                copy_vp_to_imgmap(&viewports[pointer_vport], imgmaps[pointer_imgmap]);
    13151318       
    13161319        /* Draw mouse pointer. */
     
    13371340        /* Restore image under the pointer. */
    13381341        if (pointer_shown) {
    1339                 draw_pixmap(pointer_vport, pointer_pixmap);
     1342                draw_imgmap(pointer_vport, pointer_imgmap);
    13401343                pointer_shown = 0;
    13411344        }
     
    13921395                animations[i].initialized = 0;
    13931396                break;
    1394         case FB_ANIM_ADDPIXMAP:
     1397        case FB_ANIM_ADDIMGMAP:
    13951398                i = IPC_GET_ARG1(*call);
    13961399                if (i >= MAX_ANIMATIONS || i < 0 ||
     
    14041407                }
    14051408                newval = IPC_GET_ARG2(*call);
    1406                 if (newval < 0 || newval > MAX_PIXMAPS ||
    1407                         !pixmaps[newval].data) {
     1409                if (newval < 0 || newval > MAX_IMGMAPS ||
     1410                        !imgmaps[newval]) {
    14081411                        retval = EINVAL;
    14091412                        break;
    14101413                }
    1411                 animations[i].pixmaps[animations[i].animlen++] = newval;
     1414                animations[i].imgmaps[animations[i].animlen++] = newval;
    14121415                break;
    14131416        case FB_ANIM_CHGVP:
     
    14481451}
    14491452
    1450 
    1451 /** Handler for messages concerning pixmap handling
    1452  *
    1453  */
    1454 static int pixmap_handle(ipc_callid_t callid, ipc_call_t *call, int vp)
     1453/** Handler for messages concerning image map handling
     1454 *
     1455 */
     1456static int imgmap_handle(ipc_callid_t callid, ipc_call_t *call, int vp)
    14551457{
    14561458        bool handled = true;
     
    14591461       
    14601462        switch (IPC_GET_IMETHOD(*call)) {
    1461         case FB_VP_DRAW_PIXMAP:
     1463        case FB_VP_DRAW_IMGMAP:
    14621464                nvp = IPC_GET_ARG1(*call);
    14631465                if (nvp == -1)
    14641466                        nvp = vp;
     1467               
    14651468                if (nvp < 0 || nvp >= MAX_VIEWPORTS ||
    1466                         !viewports[nvp].initialized) {
     1469                    !viewports[nvp].initialized) {
    14671470                        retval = EINVAL;
    14681471                        break;
    14691472                }
     1473               
    14701474                i = IPC_GET_ARG2(*call);
    1471                 retval = draw_pixmap(nvp, i);
    1472                 break;
    1473         case FB_VP2PIXMAP:
     1475                retval = draw_imgmap(nvp, i);
     1476                break;
     1477        case FB_VP2IMGMAP:
    14741478                nvp = IPC_GET_ARG1(*call);
    14751479                if (nvp == -1)
    14761480                        nvp = vp;
     1481               
    14771482                if (nvp < 0 || nvp >= MAX_VIEWPORTS ||
    1478                         !viewports[nvp].initialized)
     1483                    !viewports[nvp].initialized) {
    14791484                        retval = EINVAL;
    1480                 else
    1481                         retval = save_vp_to_pixmap(&viewports[nvp]);
    1482                 break;
    1483         case FB_DROP_PIXMAP:
     1485                        break;
     1486                }
     1487               
     1488                retval = save_vp_to_imgmap(&viewports[nvp]);
     1489                break;
     1490        case FB_DROP_IMGMAP:
    14841491                i = IPC_GET_ARG1(*call);
    1485                 if (i >= MAX_PIXMAPS) {
     1492                if (i >= MAX_IMGMAPS) {
    14861493                        retval = EINVAL;
    14871494                        break;
    14881495                }
    1489                 if (pixmaps[i].data) {
    1490                         free(pixmaps[i].data);
    1491                         pixmaps[i].data = NULL;
    1492                 }
     1496               
     1497                if (imgmaps[i]) {
     1498                        free(imgmaps[i]);
     1499                        imgmaps[i] = NULL;
     1500                }
     1501               
    14931502                break;
    14941503        default:
     
    15751584 *
    15761585 */
    1577 static void fb_client_connection(ipc_callid_t iid, ipc_call_t *icall)
     1586static void fb_client_connection(ipc_callid_t iid, ipc_call_t *icall,
     1587    void *arg)
    15781588{
    15791589        unsigned int vp = 0;
     
    16141624                        continue;
    16151625               
    1616                 if (pixmap_handle(callid, &call, vp))
     1626                if (imgmap_handle(callid, &call, vp))
    16171627                        continue;
    16181628               
     
    16201630                        continue;
    16211631               
    1622                 switch (IPC_GET_IMETHOD(call)) {
    1623                 case IPC_M_PHONE_HUNGUP:
     1632                if (!IPC_GET_IMETHOD(call)) {
    16241633                        client_connected = false;
    16251634                       
     
    16301639                        /* Exit thread */
    16311640                        return;
    1632                
     1641                }
     1642               
     1643                switch (IPC_GET_IMETHOD(call)) {
    16331644                case FB_PUTCHAR:
    16341645                        ch = IPC_GET_ARG1(call);
Note: See TracChangeset for help on using the changeset viewer.