1 This tries to document the mess that is DisplayState in QEMU. 2 See "console.h" for the main definitions, and below for some 3 explanations: 4 5 6 DISPLAY STATE OBJECTS: 7 ====================== 8 9 A DisplayState holds state for stuff to be displayed on QEMU. More 10 precisely: 11 12 - A DisplayState owns a 'DisplaySurface' which is nothing more than a 13 pixel buffer with specific dimensions, pitch and format plus bytes 14 to carry its content. 15 16 - A DisplayState also holds a 'DisplayAllocator' which allows it to 17 allocate its surface through a proper API. For example, this is 18 used in the upstream sdl UI backend to allocate the surface pixels 19 through SDL_SetVideoMode(). The default allocator simply uses 20 'malloc' to do the allocation (with 32-bits/pixel). 21 22 - A DisplayState also holds a list of DisplayChangeListener object. 23 Each listener contains a small set of callbacks that will be called 24 whenever an "event" happens on the display state. Events examples 25 are: 26 27 dpy_update: a rectangular portion of the surface has been updated. 28 dpy_resize: the hardware decided to resize the framebuffer. 29 dpy_refresh: called periodically by the GUI timer. 30 dpy_copy: the hardware performed a rectangular copy operation. 31 dpy_fill: the hardware performed a rectangular fill operation. 32 dpy_setdata: the hardware decided to change the framebuffer address. 33 dpy_text_cursor: the hardware placed the text cursor at a given (x,y). 34 35 NOTE: dpy_setdata is essentially the same than dpy_resize except that 36 there is a guarantee that the size didn't change. 37 38 More on DisplayChangeListeners below. 39 40 - The file "console.h" provides many helper functions to call all listeners 41 registered for a given DisplayState. For example, dpy_update(ds,x,y,w,h) 42 will call the 'dpy_update' callback of all listeners for the display 43 state 'ds'. 44 45 46 CONSOLES: 47 ========= 48 49 A "console" is something that can write pixels into a DisplayState. 50 There are two kinds of consoles, and they're fairly different in usage. 51 52 GRAPHICAL CONSOLE: 53 ------------------ 54 55 A "Graphical console" creates and owns a DisplayState. It is used when one 56 needs to write directly to the DisplaySurface pixel buffer. A typical 57 hardware framebuffer emulator (e.g. hw/vga-pic.c) will call the 58 function graphic_console_init() to create the DisplayState. Note that 59 this functions accepts several callbacks and is defined as: 60 61 typedef void (*vga_hw_update_ptr)(void *); 62 typedef void (*vga_hw_invalidate_ptr)(void *); 63 typedef void (*vga_hw_screen_dump_ptr)(void *, const char *); 64 typedef void (*vga_hw_text_update_ptr)(void *, console_ch_t *); 65 66 DisplayState *graphic_console_init(vga_hw_update_ptr update, 67 vga_hw_invalidate_ptr invalidate, 68 vga_hw_screen_dump_ptr screen_dump, 69 vga_hw_text_update_ptr text_update, 70 void *opaque); 71 72 The update/invalidate/screen_dump/text_update functions must be provided 73 by the hardware framebuffer emulation, and will be called under various 74 circumstances: 75 76 'update' is called periodically to check for any hw framebuffer 77 updates (and then copy them to the DisplayState, to finally send 78 them through dpy_update() to the listeners). 79 80 'invalidate' is called to indicate that the next call to 'update' 81 should send the content of _all_ the framebuffer, instead of only 82 the smallest possible update. 83 84 'screen_dump' is called to force a screen dump (i.e. print the 85 content of the framebuffer to a ppm file, which name is passed as 86 a parameter). 87 88 'text_update' is called to display one single character. XXX: Code is 89 not very clear, but probably related to text console. 90 91 92 TEXT CONSOLES: 93 -------------- 94 95 A "Text console" attaches to an existing DisplayState, and is able to 96 take over its rendering in order to display a text *terminal*. It's not 97 sure whether this emulates VT101 or something else (see the code inside 98 the console_putchar() for all the gory details), but the main idea is 99 that you create a console with a call to: 100 101 CharDriverState* text_console_init(const char* p); 102 103 The function returns a CharDriverState* (see docs/CHAR-DEVICES.TXT) that 104 will be connected to a host device identified by the string in 'p'. This 105 allows you, for example, to connect the console to stdio. 106 107 The text console code is capable of producing a bitmap each time you update 108 its content (i.e. it includes code to manage fixed-size font rendering, 109 scrolling, escape sequences, color, blinking cursor, etc...). 110 111 - By default, the graphics console writes to its DisplayState, but you can 112 use console_select() to change that at runtime. This function can be used 113 to force switching between virtual terminals and the graphics display. 114 There can be several text consoles associated to a single DisplayState 115 object. 116 117 118 DISPLAY CHANGE LISTENERES: 119 ========================== 120 121 There QEMU sources provide the implementation for various 122 DisplayChangeListeners, most notables are the following: 123 124 - In sdl.c: This one uses the SDL library to display the content of a 125 DisplaySurface through a SDL_Window. The implementation also supports 126 zooming the output to an arbitrary size (using SDL functions). 127 128 - In vnc.c: This listener implements a VNC Server that can be used to 129 display the DisplaySurface remotely through the RDP protocol. 130 131 - In curses.c: This listener is used to display text consoles through the 132 "curses" library on Unix systems. It cannot be used to display any 133 graphics though. 134 135 NOTE: The initialization sequence in vl.c only allows for a single listener 136 on the main display state, but the rest of the code deals with several 137 listeners per DisplayState just fine. 138 139 Each DisplayChangeListener can specify a refresh period (e.g. every 1/60th 140 of second). QEMU will then create a timer that will be programmed to called 141 the listener's 'dpy_refresh' callback periodically. The point of this 142 callback is to perform the following: 143 144 - poll for new user input events from the underlying UI (e.g. from the SDL 145 event loop, or from the network for VNC). These should be translated into 146 guest event codes with functions like 'kbd_put_keycode' or 'kbd_mouse_event'. 147 148 - call the global vga_hw_update() function. It will, if the graphics console 149 is being displayed, call the 'update' callback that was passed to 150 graphic_console_init(). If a text console is being displayed, the does 151 nothing. 152 153 - eventually call the global vga_hw_invalidate() to indicate that the whole 154 framebuffer content should be resent as an update. This can happen when a 155 UI window was minimized and is made visible again, for example. 156 157 158 INITIALIZATION AND RUNTIME EXECUTION: 159 ===================================== 160 161 Initialization happens in the qemu main() function in the vl.c source file. 162 163 First, the hardware machine is initialized. The hardware fraembuffer emulation 164 shall call graphic_console_init() to create a new DisplayState. Note that the 165 object returned by this function has a default DisplaySurface of 640x480 pixels 166 allocated through malloc(). In other words, the hardware emulation does not 167 set the size of the display state by default! 168 169 After that, the listener's initialization function (e.g. sdl_display_init) 170 is called. It is passed the DisplayState object and can replace the 171 corresponding DisplaySurface with another one with proper dimensions, and 172 eventually created with a different DisplayAllocator. It also registers a 173 DisplayChangeListener to receive later state changes. 174 175 Note that the VNC listener doesn't change the dimension of the DisplayState 176 surface it is initialized with. However, it will react to dpy_resize events 177 accordingly. 178 179 NOTE: dpy_resize()s are currently only generated when switching between 180 consoles, or when the framebuffer's size is modified by the guest kernel. 181 182 183 The GUI timer, corresponding to the first listener than has one refresh 184 period, drives the whole update process (if no listener provides a refresh 185 period, a default 'no_graphic' timer is setup with a default refresh period 186 of 30 frame/s). 187 188 Things happen in this order: 189 190 - the GUI timer kicks in, and calls the 'dpy_refresh()' callback of 191 the listener (each listener has its own timer, btw). 192 193 - the listener callback polls for user events, and calls vga_hw_update() 194 to see if there are hardware framebuffer updates. 195 196 - vga_hw_update() checks that the graphics console is displayed (otherwise 197 it exits) 198 199 - it then calls the graphics console's 'update' callback 200 201 - the callback, implemented by the framebuffer hw emulation, checks for 202 dirty pages in order to detect what changed since it was invoked. 203 204 For every rectangle of the hw framebuffer that was modified, it copies 205 the pixels from VRAM into the DisplayState's surface buffer (eventually 206 performing format conversion at the same time). 207 208 After that, it calls dpy_update() to send the update to all registered 209 listeners for the DisplayState. 210 211 - The listener's 'dpy_update' callback is called and receives a pointer 212 to the DisplayState, and the rectangle corresponding to the update. Its 213 implementation can then update the content of the screen (or the internal 214 VNC framebuffer). 215 216 Eventually, hardware emulation can also trigger other dpy_xxxx events (e.g. 217 dpy_resize, dpy_copy, dpy_fill....) 218 219 Here's a simplified diagram of what happens in the typical case: 220 221 _____________ 222 | | 223 | hardware | 224 | framebuffer |-------+ 225 | | | 226 |_____________| | 227 ^ | 228 | | 229 | 3/ ds.update() | 4/ dpy_update(ds,x,y,w,h) 230 | | 231 | | 232 _____________ | 233 | | | 234 | Display | <-----+ 235 | State | 236 | | ----------+ 237 |_____________| | 238 ^ | 239 | | 240 | 2/ vga_hw_update() | 241 | | 242 | | 243 | | 244 | +---------------+ 245 | | | 246 | | 5/listener.dpy_update(ds,x,y,w,h) 247 | | | 248 | | | 6/listener.dpy_update(...) 249 | | | 250 | v v 251 _____________ _____________ 252 | | | | 253 | SDL | | VNC | 254 | Listener | | Listener | 255 | | | | 256 |_____________| |_____________| 257 ^ 258 | 259 | 1/ listener.dpy_refresh() 260 | 261 262 GUI timer 263 264