1 // Copyright 2016 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #pragma once
6 
7 #include <assert.h>
8 
9 #include <gfx/gfx.h>
10 #include <hid/hid.h>
11 #include <lib/fdio/vfs.h>
12 #include <zircon/listnode.h>
13 #include <zircon/thread_annotations.h>
14 #include <port/port.h>
15 #include <stdbool.h>
16 #include <threads.h>
17 
18 #include "textcon.h"
19 
20 #define MAX_COLOR 0xf
21 
22 #if BUILD_FOR_TEST
23 zx_status_t vc_init_gfx(gfx_surface* gfx);
24 #else
25 zx_status_t vc_init_gfx(zx_handle_t fb_vmo, int32_t width, int32_t height,
26                         zx_pixel_format_t format, int32_t stride);
27 void vc_free_gfx();
28 #endif
29 
30 typedef void (*keypress_handler_t)(uint8_t keycode, int modifiers);
31 
32 zx_status_t new_input_device(int fd, keypress_handler_t handler);
33 
34 // constraints on status bar tabs
35 #define MIN_TAB_WIDTH 16
36 #define MAX_TAB_WIDTH 32
37 
38 #define STATUS_COLOR_BG 0
39 #define STATUS_COLOR_DEFAULT 7
40 #define STATUS_COLOR_ACTIVE 11
41 #define STATUS_COLOR_UPDATED 10
42 
43 typedef struct vc {
44     char title[MAX_TAB_WIDTH];
45     // vc title, shown in status bar
46     bool active;
47     unsigned flags;
48 
49     zx_handle_t gfx_vmo;
50 
51     int fd;
52 
53     // backing store
54     const gfx_font* font;
55 
56     vc_char_t* text_buf;
57     // text buffer
58 
59     // Buffer containing scrollback lines.  This is a circular buffer.
60     vc_char_t* scrollback_buf;
61     // Maximum number of rows that may be stored in the scrollback buffer.
62     unsigned scrollback_rows_max;
63     // Number of rows currently stored in the scrollback buffer.
64     unsigned scrollback_rows_count;
65     // Offset, in rows, of the oldest row in the scrollback buffer.
66     unsigned scrollback_offset;
67 
68     unsigned rows, columns;
69     // screen size
70     unsigned charw, charh;
71     // size of character cell
72 
73     int invy0, invy1;
74     // offscreen invalid lines, tracked during textcon drawing
75 
76     unsigned cursor_x, cursor_y;
77     // cursor
78     bool hide_cursor;
79     // cursor visibility
80     int viewport_y;
81     // viewport position, must be <= 0
82 
83     uint32_t palette[16];
84     uint8_t front_color;
85     uint8_t back_color;
86     // color
87 
88     textcon_t textcon;
89 
90     const keychar_t* keymap;
91 
92     struct list_node node;
93     // for virtual console list
94 
95 #if !BUILD_FOR_TEST
96     port_fd_handler fh;
97     zx_handle_t proc;
98     bool is_shell;
99 #endif
100 } vc_t;
101 
102 // When VC_FLAG_HASOUTPUT is set, this indicates that there was output to
103 // the console that hasn't been displayed yet, because this console isn't
104 // visible.
105 #define VC_FLAG_HASOUTPUT   (1 << 0)
106 #define VC_FLAG_FULLSCREEN  (1 << 1)
107 
108 const gfx_font* vc_get_font();
109 zx_status_t vc_alloc(vc_t** out, bool special);
110 void vc_attach_gfx(vc_t* vc);
111 void vc_free(vc_t* vc);
112 void vc_flush(vc_t* vc);
113 void vc_flush_all(vc_t* vc);
114 
115 // called to re-draw the status bar after
116 // status-worthy vc or global state has changed
117 void vc_status_update();
118 
119 // used by vc_status_invalidate to draw the status bar
120 void vc_status_clear();
121 void vc_status_write(int x, unsigned color, const char* text);
122 void vc_status_commit();
123 
124 void vc_render(vc_t* vc);
125 void vc_full_repaint(vc_t* vc);
126 int vc_get_scrollback_lines(vc_t* vc);
127 vc_char_t* vc_get_scrollback_line_ptr(vc_t* vc, unsigned row);
128 void vc_scroll_viewport(vc_t* vc, int dir);
129 void vc_scroll_viewport_top(vc_t* vc);
130 void vc_scroll_viewport_bottom(vc_t* vc);
131 void vc_set_fullscreen(vc_t* vc, bool fullscreen);
132 
133 ssize_t vc_write(vc_t* vc, const void* buf, size_t count,
134                  zx_off_t off);
135 
vc_rows(vc_t * vc)136 static inline int vc_rows(vc_t* vc) {
137     return vc->flags & VC_FLAG_FULLSCREEN ? vc->rows : vc->rows - 1;
138 }
139 
140 // drawing:
141 
142 void vc_gfx_invalidate_all(vc_t* vc);
143 void vc_gfx_invalidate_status();
144 // invalidates a region in characters
145 void vc_gfx_invalidate(vc_t* vc, unsigned x, unsigned y, unsigned w, unsigned h);
146 // invalidates a region in pixels
147 void vc_gfx_invalidate_region(vc_t* vc, unsigned x, unsigned y, unsigned w, unsigned h);
148 void vc_gfx_draw_char(vc_t* vc, vc_char_t ch, unsigned x, unsigned y,
149                       bool invert);
150 
palette_to_color(vc_t * vc,uint8_t color)151 static inline uint32_t palette_to_color(vc_t* vc, uint8_t color) {
152     assert(color <= MAX_COLOR);
153     return vc->palette[color];
154 }
155 
156 extern port_t port;
157 extern bool g_vc_owns_display;
158 extern vc_t* g_active_vc;
159 extern int g_status_width;
160 
161 void handle_key_press(uint8_t keycode, int modifiers);
162 void vc_toggle_framebuffer();
163 
164 zx_status_t vc_create(vc_t** out, bool special);
165 void vc_destroy(vc_t* vc);
166 ssize_t vc_write(vc_t* vc, const void* buf, size_t count, zx_off_t off);
167 zx_status_t vc_set_active(int num, vc_t* vc);
168 void vc_show_active();
169 
170 bool vc_display_init(void);
171 
172 void set_log_listener_active(bool active);
173 zx_status_t handle_device_dir_event(port_handler_t* ph, zx_signals_t signals,
174                                     zx_status_t (*event_handler)(unsigned event, const char* msg));
175