Ignore:
File:
1 edited

Legend:

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

    r62fbb7e r00ddb40  
    5555#include <async.h>
    5656#include <loc.h>
    57 #include <devman.h>
    58 
    59 #include <event.h>
    60 #include <device/graph_dev.h>
     57
    6158#include <io/keycode.h>
    6259#include <io/mode.h>
    6360#include <io/visualizer.h>
    6461#include <io/window.h>
     62#include <io/console.h>
    6563
    6664#include <transform.h>
     
    8684static sysarg_t coord_origin;
    8785static pixel_t bg_color;
     86static filter_t filter = filter_bilinear;
     87static unsigned int filter_index = 1;
    8888
    8989typedef struct {
     
    146146/** Input server proxy */
    147147static input_t *input;
    148 
     148static bool active = false;
     149
     150static int comp_active(input_t *);
     151static int comp_deactive(input_t *);
    149152static int comp_key_press(input_t *, kbd_event_type_t, keycode_t, keymod_t, wchar_t);
    150153static int comp_mouse_move(input_t *, int, int);
     
    153156
    154157static input_ev_ops_t input_ev_ops = {
     158        .active = comp_active,
     159        .deactive = comp_deactive,
    155160        .key = comp_key_press,
    156161        .move = comp_mouse_move,
     
    158163        .button = comp_mouse_button
    159164};
    160 
    161 static void input_disconnect(void);
    162165
    163166static pointer_t *input_pointer(input_t *input)
     
    232235static void window_destroy(window_t *win)
    233236{
    234         if (win && atomic_get(&win->ref_cnt) == 0) {
     237        if ((win) && (atomic_get(&win->ref_cnt) == 0)) {
    235238                while (!list_empty(&win->queue.list)) {
    236239                        window_event_t *event = (window_event_t *) list_first(&win->queue.list);
     
    238241                        free(event);
    239242                }
    240 
    241                 if (win->surface) {
     243               
     244                if (win->surface)
    242245                        surface_destroy(win->surface);
    243                 }
     246               
    244247                free(win);
    245248        }
     
    253256        transform_invert(&win_trans);
    254257        transform_apply_affine(&win_trans, &x, &y);
    255 
    256         /* Since client coordinate origin is (0, 0), it is necessary to check
     258       
     259        /*
     260         * Since client coordinate origin is (0, 0), it is necessary to check
    257261         * coordinates to avoid underflow. Moreover, it is convenient to also
    258262         * check against provided upper limits to determine whether the converted
    259          * coordinates are within the client window.  */
    260         if (x < 0 || y < 0) {
     263         * coordinates are within the client window.
     264         */
     265        if ((x < 0) || (y < 0))
    261266                return false;
    262         } else {
    263                 (*x_out) = (sysarg_t) (x + 0.5);
    264                 (*y_out) = (sysarg_t) (y + 0.5);
    265 
    266                 if ((*x_out) >= x_lim || (*y_out) >= y_lim) {
    267                         return false;
    268                 } else {
    269                         return true;
    270                 }
    271         }
     267       
     268        (*x_out) = (sysarg_t) (x + 0.5);
     269        (*y_out) = (sysarg_t) (y + 0.5);
     270       
     271        if (((*x_out) >= x_lim) || ((*y_out) >= y_lim))
     272                return false;
     273       
     274        return true;
    272275}
    273276
     
    279282        transform_apply_affine(&win_trans, &x, &y);
    280283       
    281         /* It is assumed that compositor coordinate origin is chosen in such way,
    282          * that underflow/overflow here would be unlikely. */
     284        /*
     285         * It is assumed that compositor coordinate origin is chosen in such way,
     286         * that underflow/overflow here would be unlikely.
     287         */
    283288        (*x_out) = (sysarg_t) (x + 0.5);
    284289        (*y_out) = (sysarg_t) (y + 0.5);
     
    405410
    406411                        source_init(&source);
    407                         source_set_filter(&source, filter_nearest);
     412                        source_set_filter(&source, filter);
    408413                        drawctx_init(&context, vp->surface);
    409414                        drawctx_set_compose(&context, compose_over);
     
    438443                                        transform_translate(&transform, -pos.x, -pos.y);
    439444
    440                                         source_set_transform(&source, transform);                               
    441                                         source_set_texture(&source, win->surface, false);
     445                                        source_set_transform(&source, transform);
     446                                        source_set_texture(&source, win->surface,
     447                                            PIXELMAP_EXTEND_TRANSPARENT_SIDES);
    442448                                        source_set_alpha(&source, PIXEL(win->opacity, 0, 0, 0));
    443449
     
    567573
    568574        /* Notify visualizers about updated regions. */
    569         list_foreach(viewport_list, link, viewport_t, vp) {
    570                 sysarg_t x_dmg_vp, y_dmg_vp, w_dmg_vp, h_dmg_vp;
    571                 surface_get_damaged_region(vp->surface, &x_dmg_vp, &y_dmg_vp, &w_dmg_vp, &h_dmg_vp);
    572                 surface_reset_damaged_region(vp->surface);
    573                 visualizer_update_damaged_region(
    574                     vp->sess, x_dmg_vp, y_dmg_vp, w_dmg_vp, h_dmg_vp, 0, 0);
    575         }
    576 
     575        if (active) {
     576                list_foreach(viewport_list, link, viewport_t, vp) {
     577                        sysarg_t x_dmg_vp, y_dmg_vp, w_dmg_vp, h_dmg_vp;
     578                        surface_get_damaged_region(vp->surface, &x_dmg_vp, &y_dmg_vp, &w_dmg_vp, &h_dmg_vp);
     579                        surface_reset_damaged_region(vp->surface);
     580                        visualizer_update_damaged_region(vp->sess,
     581                            x_dmg_vp, y_dmg_vp, w_dmg_vp, h_dmg_vp, 0, 0);
     582                }
     583        }
     584       
    577585        fibril_mutex_unlock(&viewport_list_mtx);
    578586}
     
    590598                return;
    591599        }
     600       
    592601        int rc = async_data_read_finalize(callid, event, len);
    593602        if (rc != EOK) {
     
    596605                return;
    597606        }
     607       
    598608        async_answer_0(iid, EOK);
    599        
    600609        free(event);
    601610}
     
    608617        double height = IPC_GET_ARG4(*icall);
    609618
    610         if (width == 0 || height == 0) {
     619        if ((width == 0) || (height == 0)) {
    611620                comp_damage(0, 0, UINT32_MAX, UINT32_MAX);
    612621        } else {
     
    665674        transform_identity(&transform);
    666675        temp = transform;
    667         transform_multiply(&transform, &temp, &translate);
     676        transform_product(&transform, &temp, &translate);
    668677        temp = transform;
    669         transform_multiply(&transform, &temp, &rotate);
     678        transform_product(&transform, &temp, &rotate);
    670679        temp = transform;
    671         transform_multiply(&transform, &temp, &scale);
     680        transform_product(&transform, &temp, &scale);
    672681       
    673682        win->transform = transform;
     
    857866
    858867        comp_damage(x, y, width, height);
    859 
    860868        async_answer_0(iid, EOK);
    861869}
     
    863871static void comp_window_close_request(window_t *win, ipc_callid_t iid, ipc_call_t *icall)
    864872{
    865     window_event_t *event = (window_event_t *) malloc(sizeof(window_event_t));
     873        window_event_t *event = (window_event_t *) malloc(sizeof(window_event_t));
    866874        if (event == NULL) {
    867875                async_answer_0(iid, ENOMEM);
     
    10031011                                break;
    10041012                        case WINDOW_CLOSE:
    1005                                 /* Postpone the closing until the phone is hung up to cover
    1006                                  * the case when the client is killed abruptly. */
     1013                                /*
     1014                                 * Postpone the closing until the phone is hung up to cover
     1015                                 * the case when the client is killed abruptly.
     1016                                 */
    10071017                                async_answer_0(callid, EOK);
    10081018                                break;
     
    10191029static void comp_mode_change(viewport_t *vp, ipc_callid_t iid, ipc_call_t *icall)
    10201030{
    1021         int rc;
    10221031        sysarg_t mode_idx = IPC_GET_ARG2(*icall);
    10231032        fibril_mutex_lock(&viewport_list_mtx);
     
    10251034        /* Retrieve the mode that shall be set. */
    10261035        vslmode_t new_mode;
    1027         rc = visualizer_get_mode(vp->sess, &new_mode, mode_idx);
     1036        int rc = visualizer_get_mode(vp->sess, &new_mode, mode_idx);
    10281037        if (rc != EOK) {
    10291038                fibril_mutex_unlock(&viewport_list_mtx);
     
    10431052        /* Try to set the mode and share out the surface. */
    10441053        rc = visualizer_set_mode(vp->sess,
    1045                 new_mode.index, new_mode.version, surface_direct_access(new_surface));
     1054            new_mode.index, new_mode.version, surface_direct_access(new_surface));
    10461055        if (rc != EOK) {
    10471056                surface_destroy(new_surface);
     
    10731082}
    10741083
     1084#if 0
     1085static void comp_shutdown(void)
     1086{
     1087        loc_service_unregister(winreg_id);
     1088        input_disconnect();
     1089       
     1090        /* Close all clients and their windows. */
     1091        fibril_mutex_lock(&window_list_mtx);
     1092        list_foreach(window_list, link, window_t, win) {
     1093                window_event_t *event = (window_event_t *) malloc(sizeof(window_event_t));
     1094                if (event) {
     1095                        link_initialize(&event->link);
     1096                        event->type = WINDOW_CLOSE;
     1097                        prodcons_produce(&win->queue, &event->link);
     1098                }
     1099        }
     1100        fibril_mutex_unlock(&window_list_mtx);
     1101       
     1102        async_answer_0(iid, EOK);
     1103       
     1104        /* All fibrils of the compositor will terminate soon. */
     1105}
     1106#endif
     1107
    10751108static void comp_visualizer_disconnect(viewport_t *vp, ipc_callid_t iid, ipc_call_t *icall)
    10761109{
    10771110        /* Release viewport resources. */
    10781111        fibril_mutex_lock(&viewport_list_mtx);
     1112       
    10791113        list_remove(&vp->link);
    10801114        viewport_destroy(vp);
    1081 
    1082         /* Terminate compositor if there are no more viewports. */
    1083         if (list_empty(&viewport_list)) {
    1084                 fibril_mutex_unlock(&viewport_list_mtx);
    1085                 loc_service_unregister(winreg_id);
    1086                 input_disconnect();
    1087 
    1088                 /* Close all clients and their windows. */
    1089                 fibril_mutex_lock(&window_list_mtx);
    1090                 list_foreach(window_list, link, window_t, win) {
    1091                         window_event_t *event = (window_event_t *) malloc(sizeof(window_event_t));
    1092                         if (event) {
    1093                                 link_initialize(&event->link);
    1094                                 event->type = WINDOW_CLOSE;
    1095                                 prodcons_produce(&win->queue, &event->link);
    1096                         }
    1097                 }
    1098                 fibril_mutex_unlock(&window_list_mtx);
    1099 
    1100                 async_answer_0(iid, EOK);
    1101 
    1102                 /* All fibrils of the compositor will terminate soon. */
    1103         } else {
    1104                 fibril_mutex_unlock(&viewport_list_mtx);
    1105                 async_answer_0(iid, EOK);
    1106 
    1107                 comp_restrict_pointers();
    1108                 comp_damage(0, 0, UINT32_MAX, UINT32_MAX);
    1109         }
     1115       
     1116        fibril_mutex_unlock(&viewport_list_mtx);
     1117       
     1118        async_answer_0(iid, EOK);
     1119       
     1120        comp_restrict_pointers();
     1121        comp_damage(0, 0, UINT32_MAX, UINT32_MAX);
    11101122}
    11111123
     
    11221134        fibril_mutex_unlock(&viewport_list_mtx);
    11231135
    1124         if (!vp) {
     1136        if (!vp)
    11251137                return;
    1126         }
    11271138
    11281139        /* Ignore parameters, the connection is already opened. */
     
    11491160}
    11501161
    1151 static async_sess_t *vsl_connect(const char *svc)
     1162static async_sess_t *vsl_connect(service_id_t sid, const char *svc)
    11521163{
    11531164        int rc;
    11541165        async_sess_t *sess;
    1155         service_id_t dsid;
    1156         devman_handle_t handle;
    1157 
    1158         rc = loc_service_get_id(svc, &dsid, 0);
    1159         if (rc != EOK) {
     1166
     1167        sess = loc_service_connect(EXCHANGE_SERIALIZE, sid, 0);
     1168        if (sess == NULL) {
     1169                printf("%s: Unable to connect to visualizer %s\n", NAME, svc);
    11601170                return NULL;
    11611171        }
    11621172
    1163         rc = devman_fun_sid_to_handle(dsid, &handle);
    1164         if (rc == EOK) {
    1165                 sess = devman_device_connect(EXCHANGE_SERIALIZE, handle, 0);
    1166                 if (sess == NULL) {
    1167                         printf("%s: Unable to connect to visualizer %s\n", NAME, svc);
    1168                         return NULL;
    1169                 }
    1170                 rc = graph_dev_connect(sess);
    1171                 if (rc != EOK) {
    1172                         return NULL;
    1173                 }
    1174         } else if (rc == ENOENT) {
    1175                 sess = loc_service_connect(EXCHANGE_SERIALIZE, dsid, 0);
    1176                 if (sess == NULL) {
    1177                         printf("%s: Unable to connect to visualizer %s\n", NAME, svc);
    1178                         return NULL;
    1179                 }
    1180         } else {
    1181                 return NULL;
    1182         }
    1183 
    11841173        async_exch_t *exch = async_exchange_begin(sess);
    1185         rc = async_connect_to_me(exch, dsid, 0, 0, vsl_notifications, NULL);
     1174        rc = async_connect_to_me(exch, sid, 0, 0, vsl_notifications, NULL);
    11861175        async_exchange_end(exch);
    11871176
     
    11961185}
    11971186
    1198 static viewport_t *viewport_create(const char *vsl_name)
     1187static viewport_t *viewport_create(service_id_t sid)
    11991188{
    12001189        int rc;
    1201 
    1202         viewport_t *vp = (viewport_t *) malloc(sizeof(viewport_t));
    1203         if (!vp) {
    1204                 return NULL;
    1205         }
     1190        char *vsl_name = NULL;
     1191        viewport_t *vp = NULL;
     1192        bool claimed = false;
     1193
     1194        rc = loc_service_get_name(sid, &vsl_name);
     1195        if (rc != EOK)
     1196                goto error;
     1197
     1198        vp = (viewport_t *) calloc(1, sizeof(viewport_t));
     1199        if (!vp)
     1200                goto error;
    12061201
    12071202        link_initialize(&vp->link);
     
    12101205
    12111206        /* Establish output bidirectional connection. */
    1212         vp->sess = vsl_connect(vsl_name);
    1213         rc = loc_service_get_id(vsl_name, &vp->dsid, 0);
    1214         if (vp->sess == NULL || rc != EOK) {
    1215                 free(vp);
    1216                 return NULL;
    1217         }
     1207        vp->dsid = sid;
     1208        vp->sess = vsl_connect(sid, vsl_name);
     1209        if (vp->sess == NULL)
     1210                goto error;
    12181211
    12191212        /* Claim the given visualizer. */
    12201213        rc = visualizer_claim(vp->sess, 0);
    12211214        if (rc != EOK) {
    1222                 async_hangup(vp->sess);
    1223                 free(vp);
    12241215                printf("%s: Unable to claim visualizer (%s)\n", NAME, str_error(rc));
    1225                 return NULL;
    1226         }
     1216                goto error;
     1217        }
     1218
     1219        claimed = true;
    12271220
    12281221        /* Retrieve the default mode. */
    12291222        rc = visualizer_get_default_mode(vp->sess, &vp->mode);
    12301223        if (rc != EOK) {
    1231                 visualizer_yield(vp->sess);
    1232                 async_hangup(vp->sess);
    1233                 free(vp);
    12341224                printf("%s: Unable to retrieve mode (%s)\n", NAME, str_error(rc));
    1235                 return NULL;
     1225                goto error;
    12361226        }
    12371227
     
    12401230            NULL, SURFACE_FLAG_SHARED);
    12411231        if (vp->surface == NULL) {
    1242                 visualizer_yield(vp->sess);
    1243                 async_hangup(vp->sess);
    1244                 free(vp);
    12451232                printf("%s: Unable to create surface (%s)\n", NAME, str_error(rc));
    1246                 return NULL;
     1233                goto error;
    12471234        }
    12481235
    12491236        /* Try to set the mode and share out the surface. */
    12501237        rc = visualizer_set_mode(vp->sess,
    1251                 vp->mode.index, vp->mode.version, surface_direct_access(vp->surface));
     1238            vp->mode.index, vp->mode.version, surface_direct_access(vp->surface));
    12521239        if (rc != EOK) {
     1240                printf("%s: Unable to set mode (%s)\n", NAME, str_error(rc));
     1241                goto error;
     1242        }
     1243
     1244        return vp;
     1245error:
     1246        if (claimed)
    12531247                visualizer_yield(vp->sess);
    1254                 surface_destroy(vp->surface);
     1248       
     1249        if (vp->sess != NULL)
    12551250                async_hangup(vp->sess);
    1256                 free(vp);
    1257                 printf("%s: Unable to set mode (%s)\n", NAME, str_error(rc));
    1258                 return NULL;
    1259         }
    1260 
    1261         return vp;
     1251       
     1252        free(vp);
     1253        free(vsl_name);
     1254        return NULL;
    12621255}
    12631256
     
    17971790}
    17981791
     1792static int comp_active(input_t *input)
     1793{
     1794        active = true;
     1795        comp_damage(0, 0, UINT32_MAX, UINT32_MAX);
     1796       
     1797        return EOK;
     1798}
     1799
     1800static int comp_deactive(input_t *input)
     1801{
     1802        active = false;
     1803        return EOK;
     1804}
     1805
    17991806static int comp_key_press(input_t *input, kbd_event_type_t type, keycode_t key,
    18001807    keymod_t mods, wchar_t c)
     
    18141821            key == KC_O || key == KC_P);
    18151822        bool kconsole_switch = (mods & KM_ALT) && (key == KC_M);
    1816 
    1817         bool filter = (type == KEY_RELEASE) && (win_transform || win_resize ||
     1823        bool filter_switch = (mods & KM_ALT) && (key == KC_Y);
     1824
     1825        bool key_filter = (type == KEY_RELEASE) && (win_transform || win_resize ||
    18181826            win_opacity || win_close || win_switch || viewport_move ||
    1819             viewport_change || kconsole_switch);
    1820 
    1821         if (filter) {
     1827            viewport_change || kconsole_switch || filter_switch);
     1828
     1829        if (key_filter) {
    18221830                /* no-op */
    18231831        } else if (win_transform) {
     
    18391847                                break;
    18401848                        case KC_Q:
    1841                                 win->angle += (PI / 2);
     1849                                win->angle += 0.1;
    18421850                                break;
    18431851                        case KC_E:
    1844                                 win->angle += -(PI / 2);
     1852                                win->angle -= 0.1;
    18451853                                break;
    18461854                        case KC_R:
     
    20852093                fibril_mutex_unlock(&viewport_list_mtx);
    20862094        } else if (kconsole_switch) {
    2087                 __SYSCALL0(SYS_DEBUG_ACTIVATE_CONSOLE);
     2095                if (console_kcon())
     2096                        active = false;
     2097        } else if (filter_switch) {
     2098                filter_index++;
     2099                if (filter_index > 1)
     2100                        filter_index = 0;
     2101                if (filter_index == 0) {
     2102                        filter = filter_nearest;
     2103                }
     2104                else {
     2105                        filter = filter_bilinear;
     2106                }
     2107                comp_damage(0, 0, UINT32_MAX, UINT32_MAX);
    20882108        } else {
    20892109                window_event_t *event = (window_event_t *) malloc(sizeof(window_event_t));
     
    21542174}
    21552175
    2156 static void interrupt_received(ipc_callid_t callid, ipc_call_t *call)
    2157 {
    2158         comp_damage(0, 0, UINT32_MAX, UINT32_MAX);
    2159 }
    2160 
    2161 static int discover_viewports(void)
    2162 {
     2176static void discover_viewports(void)
     2177{
     2178        fibril_mutex_lock(&discovery_mtx);
     2179       
    21632180        /* Create viewports and connect them to visualizers. */
    21642181        category_id_t cat_id;
    21652182        int rc = loc_category_get_id("visualizer", &cat_id, IPC_FLAG_BLOCKING);
    2166         if (rc != EOK) {
    2167                 printf("%s: Failed to get visualizer category.\n", NAME);
    2168                 return -1;
    2169         }
     2183        if (rc != EOK)
     2184                goto ret;
    21702185       
    21712186        service_id_t *svcs;
    21722187        size_t svcs_cnt = 0;
    21732188        rc = loc_category_get_svcs(cat_id, &svcs, &svcs_cnt);
    2174         if (rc != EOK || svcs_cnt == 0) {
    2175                 printf("%s: Failed to get visualizer category services.\n", NAME);
    2176                 return -1;
    2177         }
    2178 
    2179         fibril_mutex_lock(&viewport_list_mtx); 
     2189        if (rc != EOK)
     2190                goto ret;
     2191       
     2192        fibril_mutex_lock(&viewport_list_mtx);
    21802193        for (size_t i = 0; i < svcs_cnt; ++i) {
    21812194                bool exists = false;
     
    21902203                        continue;
    21912204               
    2192                 char *svc_name;
    2193                 rc = loc_service_get_name(svcs[i], &svc_name);
    2194                 if (rc == EOK) {
    2195                         viewport_t *vp = viewport_create(svc_name);
    2196                         if (vp != NULL) {
    2197                                 list_append(&vp->link, &viewport_list);
    2198                         }
    2199                 }
     2205                viewport_t *vp = viewport_create(svcs[i]);
     2206                if (vp != NULL)
     2207                        list_append(&vp->link, &viewport_list);
    22002208        }
    22012209        fibril_mutex_unlock(&viewport_list_mtx);
    22022210       
    2203         /* TODO damage only newly added viewports */
    2204         comp_damage(0, 0, UINT32_MAX, UINT32_MAX);
    2205         return EOK;
     2211        if (!list_empty(&viewport_list))
     2212                input_activate(input);
     2213       
     2214ret:
     2215        fibril_mutex_unlock(&discovery_mtx);
    22062216}
    22072217
    22082218static void category_change_cb(void)
    22092219{
    2210         fibril_mutex_lock(&discovery_mtx);
    22112220        discover_viewports();
    2212         fibril_mutex_unlock(&discovery_mtx);
    22132221}
    22142222
     
    22232231        /* Register compositor server. */
    22242232        async_set_client_connection(client_connection);
     2233       
    22252234        int rc = loc_server_register(NAME);
    22262235        if (rc != EOK) {
    22272236                printf("%s: Unable to register server (%s)\n", NAME, str_error(rc));
    22282237                return -1;
    2229         }
    2230        
    2231         /* Register interrupt handler to switch back from kconsole. */
    2232         async_set_interrupt_received(interrupt_received);
    2233         rc = event_subscribe(EVENT_KCONSOLE, 0);
    2234         if (rc != EOK) {
    2235                 printf("%s: Failed to register kconsole notifications (%s)\n",
    2236                     NAME, str_error(rc));
    22372238        }
    22382239       
     
    22562257                return -1;
    22572258        }
    2258 
     2259       
    22592260        /* Establish input bidirectional connection. */
    22602261        rc = input_connect(input_svc);
     
    22632264                return rc;
    22642265        }
    2265 
     2266       
    22662267        rc = loc_register_cat_change_cb(category_change_cb);
    22672268        if (rc != EOK) {
     
    22692270                input_disconnect();
    22702271                return rc;
    2271         }       
    2272 
    2273         rc = discover_viewports();
    2274         if (rc != EOK) {
    2275                 input_disconnect();
    2276                 return rc;
    2277         }
    2278        
    2279         if (list_empty(&viewport_list)) {
    2280                 printf("%s: Failed to get viewports.\n", NAME);
    2281                 input_disconnect();
    2282                 return -1;
    2283         }
    2284 
     2272        }
     2273       
     2274        discover_viewports();
     2275       
    22852276        comp_restrict_pointers();
    22862277        comp_damage(0, 0, UINT32_MAX, UINT32_MAX);
    2287        
    22882278       
    22892279        return EOK;
Note: See TracChangeset for help on using the changeset viewer.