Ignore:
File:
1 edited

Legend:

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

    r00ddb40 r62fbb7e  
    5555#include <async.h>
    5656#include <loc.h>
    57 
     57#include <devman.h>
     58
     59#include <event.h>
     60#include <device/graph_dev.h>
    5861#include <io/keycode.h>
    5962#include <io/mode.h>
    6063#include <io/visualizer.h>
    6164#include <io/window.h>
    62 #include <io/console.h>
    6365
    6466#include <transform.h>
     
    8486static sysarg_t coord_origin;
    8587static pixel_t bg_color;
    86 static filter_t filter = filter_bilinear;
    87 static unsigned int filter_index = 1;
    8888
    8989typedef struct {
     
    146146/** Input server proxy */
    147147static input_t *input;
    148 static bool active = false;
    149 
    150 static int comp_active(input_t *);
    151 static int comp_deactive(input_t *);
     148
    152149static int comp_key_press(input_t *, kbd_event_type_t, keycode_t, keymod_t, wchar_t);
    153150static int comp_mouse_move(input_t *, int, int);
     
    156153
    157154static input_ev_ops_t input_ev_ops = {
    158         .active = comp_active,
    159         .deactive = comp_deactive,
    160155        .key = comp_key_press,
    161156        .move = comp_mouse_move,
     
    163158        .button = comp_mouse_button
    164159};
     160
     161static void input_disconnect(void);
    165162
    166163static pointer_t *input_pointer(input_t *input)
     
    235232static void window_destroy(window_t *win)
    236233{
    237         if ((win) && (atomic_get(&win->ref_cnt) == 0)) {
     234        if (win && atomic_get(&win->ref_cnt) == 0) {
    238235                while (!list_empty(&win->queue.list)) {
    239236                        window_event_t *event = (window_event_t *) list_first(&win->queue.list);
     
    241238                        free(event);
    242239                }
    243                
    244                 if (win->surface)
     240
     241                if (win->surface) {
    245242                        surface_destroy(win->surface);
    246                
     243                }
    247244                free(win);
    248245        }
     
    256253        transform_invert(&win_trans);
    257254        transform_apply_affine(&win_trans, &x, &y);
    258        
    259         /*
    260          * Since client coordinate origin is (0, 0), it is necessary to check
     255
     256        /* Since client coordinate origin is (0, 0), it is necessary to check
    261257         * coordinates to avoid underflow. Moreover, it is convenient to also
    262258         * check against provided upper limits to determine whether the converted
    263          * coordinates are within the client window.
    264          */
    265         if ((x < 0) || (y < 0))
     259         * coordinates are within the client window.  */
     260        if (x < 0 || y < 0) {
    266261                return false;
    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;
     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        }
    275272}
    276273
     
    282279        transform_apply_affine(&win_trans, &x, &y);
    283280       
    284         /*
    285          * It is assumed that compositor coordinate origin is chosen in such way,
    286          * that underflow/overflow here would be unlikely.
    287          */
     281        /* It is assumed that compositor coordinate origin is chosen in such way,
     282         * that underflow/overflow here would be unlikely. */
    288283        (*x_out) = (sysarg_t) (x + 0.5);
    289284        (*y_out) = (sysarg_t) (y + 0.5);
     
    410405
    411406                        source_init(&source);
    412                         source_set_filter(&source, filter);
     407                        source_set_filter(&source, filter_nearest);
    413408                        drawctx_init(&context, vp->surface);
    414409                        drawctx_set_compose(&context, compose_over);
     
    443438                                        transform_translate(&transform, -pos.x, -pos.y);
    444439
    445                                         source_set_transform(&source, transform);
    446                                         source_set_texture(&source, win->surface,
    447                                             PIXELMAP_EXTEND_TRANSPARENT_SIDES);
     440                                        source_set_transform(&source, transform);                               
     441                                        source_set_texture(&source, win->surface, false);
    448442                                        source_set_alpha(&source, PIXEL(win->opacity, 0, 0, 0));
    449443
     
    573567
    574568        /* Notify visualizers about updated regions. */
    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        
     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
    585577        fibril_mutex_unlock(&viewport_list_mtx);
    586578}
     
    598590                return;
    599591        }
    600        
    601592        int rc = async_data_read_finalize(callid, event, len);
    602593        if (rc != EOK) {
     
    605596                return;
    606597        }
    607        
    608598        async_answer_0(iid, EOK);
     599       
    609600        free(event);
    610601}
     
    617608        double height = IPC_GET_ARG4(*icall);
    618609
    619         if ((width == 0) || (height == 0)) {
     610        if (width == 0 || height == 0) {
    620611                comp_damage(0, 0, UINT32_MAX, UINT32_MAX);
    621612        } else {
     
    674665        transform_identity(&transform);
    675666        temp = transform;
    676         transform_product(&transform, &temp, &translate);
     667        transform_multiply(&transform, &temp, &translate);
    677668        temp = transform;
    678         transform_product(&transform, &temp, &rotate);
     669        transform_multiply(&transform, &temp, &rotate);
    679670        temp = transform;
    680         transform_product(&transform, &temp, &scale);
     671        transform_multiply(&transform, &temp, &scale);
    681672       
    682673        win->transform = transform;
     
    866857
    867858        comp_damage(x, y, width, height);
     859
    868860        async_answer_0(iid, EOK);
    869861}
     
    871863static void comp_window_close_request(window_t *win, ipc_callid_t iid, ipc_call_t *icall)
    872864{
    873         window_event_t *event = (window_event_t *) malloc(sizeof(window_event_t));
     865    window_event_t *event = (window_event_t *) malloc(sizeof(window_event_t));
    874866        if (event == NULL) {
    875867                async_answer_0(iid, ENOMEM);
     
    10111003                                break;
    10121004                        case WINDOW_CLOSE:
    1013                                 /*
    1014                                  * Postpone the closing until the phone is hung up to cover
    1015                                  * the case when the client is killed abruptly.
    1016                                  */
     1005                                /* Postpone the closing until the phone is hung up to cover
     1006                                 * the case when the client is killed abruptly. */
    10171007                                async_answer_0(callid, EOK);
    10181008                                break;
     
    10291019static void comp_mode_change(viewport_t *vp, ipc_callid_t iid, ipc_call_t *icall)
    10301020{
     1021        int rc;
    10311022        sysarg_t mode_idx = IPC_GET_ARG2(*icall);
    10321023        fibril_mutex_lock(&viewport_list_mtx);
     
    10341025        /* Retrieve the mode that shall be set. */
    10351026        vslmode_t new_mode;
    1036         int rc = visualizer_get_mode(vp->sess, &new_mode, mode_idx);
     1027        rc = visualizer_get_mode(vp->sess, &new_mode, mode_idx);
    10371028        if (rc != EOK) {
    10381029                fibril_mutex_unlock(&viewport_list_mtx);
     
    10521043        /* Try to set the mode and share out the surface. */
    10531044        rc = visualizer_set_mode(vp->sess,
    1054             new_mode.index, new_mode.version, surface_direct_access(new_surface));
     1045                new_mode.index, new_mode.version, surface_direct_access(new_surface));
    10551046        if (rc != EOK) {
    10561047                surface_destroy(new_surface);
     
    10821073}
    10831074
    1084 #if 0
    1085 static 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 
    11081075static void comp_visualizer_disconnect(viewport_t *vp, ipc_callid_t iid, ipc_call_t *icall)
    11091076{
    11101077        /* Release viewport resources. */
    11111078        fibril_mutex_lock(&viewport_list_mtx);
    1112        
    11131079        list_remove(&vp->link);
    11141080        viewport_destroy(vp);
    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);
     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        }
    11221110}
    11231111
     
    11341122        fibril_mutex_unlock(&viewport_list_mtx);
    11351123
    1136         if (!vp)
     1124        if (!vp) {
    11371125                return;
     1126        }
    11381127
    11391128        /* Ignore parameters, the connection is already opened. */
     
    11601149}
    11611150
    1162 static async_sess_t *vsl_connect(service_id_t sid, const char *svc)
     1151static async_sess_t *vsl_connect(const char *svc)
    11631152{
    11641153        int rc;
    11651154        async_sess_t *sess;
    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);
     1155        service_id_t dsid;
     1156        devman_handle_t handle;
     1157
     1158        rc = loc_service_get_id(svc, &dsid, 0);
     1159        if (rc != EOK) {
    11701160                return NULL;
    11711161        }
    11721162
     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
    11731184        async_exch_t *exch = async_exchange_begin(sess);
    1174         rc = async_connect_to_me(exch, sid, 0, 0, vsl_notifications, NULL);
     1185        rc = async_connect_to_me(exch, dsid, 0, 0, vsl_notifications, NULL);
    11751186        async_exchange_end(exch);
    11761187
     
    11851196}
    11861197
    1187 static viewport_t *viewport_create(service_id_t sid)
     1198static viewport_t *viewport_create(const char *vsl_name)
    11881199{
    11891200        int rc;
    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;
     1201
     1202        viewport_t *vp = (viewport_t *) malloc(sizeof(viewport_t));
     1203        if (!vp) {
     1204                return NULL;
     1205        }
    12011206
    12021207        link_initialize(&vp->link);
     
    12051210
    12061211        /* Establish output bidirectional connection. */
    1207         vp->dsid = sid;
    1208         vp->sess = vsl_connect(sid, vsl_name);
    1209         if (vp->sess == NULL)
    1210                 goto error;
     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        }
    12111218
    12121219        /* Claim the given visualizer. */
    12131220        rc = visualizer_claim(vp->sess, 0);
    12141221        if (rc != EOK) {
     1222                async_hangup(vp->sess);
     1223                free(vp);
    12151224                printf("%s: Unable to claim visualizer (%s)\n", NAME, str_error(rc));
    1216                 goto error;
    1217         }
    1218 
    1219         claimed = true;
     1225                return NULL;
     1226        }
    12201227
    12211228        /* Retrieve the default mode. */
    12221229        rc = visualizer_get_default_mode(vp->sess, &vp->mode);
    12231230        if (rc != EOK) {
     1231                visualizer_yield(vp->sess);
     1232                async_hangup(vp->sess);
     1233                free(vp);
    12241234                printf("%s: Unable to retrieve mode (%s)\n", NAME, str_error(rc));
    1225                 goto error;
     1235                return NULL;
    12261236        }
    12271237
     
    12301240            NULL, SURFACE_FLAG_SHARED);
    12311241        if (vp->surface == NULL) {
     1242                visualizer_yield(vp->sess);
     1243                async_hangup(vp->sess);
     1244                free(vp);
    12321245                printf("%s: Unable to create surface (%s)\n", NAME, str_error(rc));
    1233                 goto error;
     1246                return NULL;
    12341247        }
    12351248
    12361249        /* Try to set the mode and share out the surface. */
    12371250        rc = visualizer_set_mode(vp->sess,
    1238             vp->mode.index, vp->mode.version, surface_direct_access(vp->surface));
     1251                vp->mode.index, vp->mode.version, surface_direct_access(vp->surface));
    12391252        if (rc != EOK) {
     1253                visualizer_yield(vp->sess);
     1254                surface_destroy(vp->surface);
     1255                async_hangup(vp->sess);
     1256                free(vp);
    12401257                printf("%s: Unable to set mode (%s)\n", NAME, str_error(rc));
    1241                 goto error;
     1258                return NULL;
    12421259        }
    12431260
    12441261        return vp;
    1245 error:
    1246         if (claimed)
    1247                 visualizer_yield(vp->sess);
    1248        
    1249         if (vp->sess != NULL)
    1250                 async_hangup(vp->sess);
    1251        
    1252         free(vp);
    1253         free(vsl_name);
    1254         return NULL;
    12551262}
    12561263
     
    17901797}
    17911798
    1792 static 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 
    1800 static int comp_deactive(input_t *input)
    1801 {
    1802         active = false;
    1803         return EOK;
    1804 }
    1805 
    18061799static int comp_key_press(input_t *input, kbd_event_type_t type, keycode_t key,
    18071800    keymod_t mods, wchar_t c)
     
    18211814            key == KC_O || key == KC_P);
    18221815        bool kconsole_switch = (mods & KM_ALT) && (key == KC_M);
    1823         bool filter_switch = (mods & KM_ALT) && (key == KC_Y);
    1824 
    1825         bool key_filter = (type == KEY_RELEASE) && (win_transform || win_resize ||
     1816
     1817        bool filter = (type == KEY_RELEASE) && (win_transform || win_resize ||
    18261818            win_opacity || win_close || win_switch || viewport_move ||
    1827             viewport_change || kconsole_switch || filter_switch);
    1828 
    1829         if (key_filter) {
     1819            viewport_change || kconsole_switch);
     1820
     1821        if (filter) {
    18301822                /* no-op */
    18311823        } else if (win_transform) {
     
    18471839                                break;
    18481840                        case KC_Q:
    1849                                 win->angle += 0.1;
     1841                                win->angle += (PI / 2);
    18501842                                break;
    18511843                        case KC_E:
    1852                                 win->angle -= 0.1;
     1844                                win->angle += -(PI / 2);
    18531845                                break;
    18541846                        case KC_R:
     
    20932085                fibril_mutex_unlock(&viewport_list_mtx);
    20942086        } else if (kconsole_switch) {
    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);
     2087                __SYSCALL0(SYS_DEBUG_ACTIVATE_CONSOLE);
    21082088        } else {
    21092089                window_event_t *event = (window_event_t *) malloc(sizeof(window_event_t));
     
    21742154}
    21752155
    2176 static void discover_viewports(void)
    2177 {
    2178         fibril_mutex_lock(&discovery_mtx);
    2179        
     2156static void interrupt_received(ipc_callid_t callid, ipc_call_t *call)
     2157{
     2158        comp_damage(0, 0, UINT32_MAX, UINT32_MAX);
     2159}
     2160
     2161static int discover_viewports(void)
     2162{
    21802163        /* Create viewports and connect them to visualizers. */
    21812164        category_id_t cat_id;
    21822165        int rc = loc_category_get_id("visualizer", &cat_id, IPC_FLAG_BLOCKING);
    2183         if (rc != EOK)
    2184                 goto ret;
     2166        if (rc != EOK) {
     2167                printf("%s: Failed to get visualizer category.\n", NAME);
     2168                return -1;
     2169        }
    21852170       
    21862171        service_id_t *svcs;
    21872172        size_t svcs_cnt = 0;
    21882173        rc = loc_category_get_svcs(cat_id, &svcs, &svcs_cnt);
    2189         if (rc != EOK)
    2190                 goto ret;
    2191        
    2192         fibril_mutex_lock(&viewport_list_mtx);
     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); 
    21932180        for (size_t i = 0; i < svcs_cnt; ++i) {
    21942181                bool exists = false;
     
    22032190                        continue;
    22042191               
    2205                 viewport_t *vp = viewport_create(svcs[i]);
    2206                 if (vp != NULL)
    2207                         list_append(&vp->link, &viewport_list);
     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                }
    22082200        }
    22092201        fibril_mutex_unlock(&viewport_list_mtx);
    22102202       
    2211         if (!list_empty(&viewport_list))
    2212                 input_activate(input);
    2213        
    2214 ret:
     2203        /* TODO damage only newly added viewports */
     2204        comp_damage(0, 0, UINT32_MAX, UINT32_MAX);
     2205        return EOK;
     2206}
     2207
     2208static void category_change_cb(void)
     2209{
     2210        fibril_mutex_lock(&discovery_mtx);
     2211        discover_viewports();
    22152212        fibril_mutex_unlock(&discovery_mtx);
    2216 }
    2217 
    2218 static void category_change_cb(void)
    2219 {
    2220         discover_viewports();
    22212213}
    22222214
     
    22312223        /* Register compositor server. */
    22322224        async_set_client_connection(client_connection);
    2233        
    22342225        int rc = loc_server_register(NAME);
    22352226        if (rc != EOK) {
    22362227                printf("%s: Unable to register server (%s)\n", NAME, str_error(rc));
    22372228                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));
    22382237        }
    22392238       
     
    22572256                return -1;
    22582257        }
    2259        
     2258
    22602259        /* Establish input bidirectional connection. */
    22612260        rc = input_connect(input_svc);
     
    22642263                return rc;
    22652264        }
    2266        
     2265
    22672266        rc = loc_register_cat_change_cb(category_change_cb);
    22682267        if (rc != EOK) {
     
    22702269                input_disconnect();
    22712270                return rc;
    2272         }
    2273        
    2274         discover_viewports();
    2275        
     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
    22762285        comp_restrict_pointers();
    22772286        comp_damage(0, 0, UINT32_MAX, UINT32_MAX);
     2287       
    22782288       
    22792289        return EOK;
Note: See TracChangeset for help on using the changeset viewer.