• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1This tries to document the mess that is DisplayState in QEMU.
2See "console.h" for the main definitions, and below for some
3explanations:
4
5
6DISPLAY STATE OBJECTS:
7======================
8
9A DisplayState holds state for stuff to be displayed on QEMU. More
10precisely:
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
46CONSOLES:
47=========
48
49A "console" is something that can write pixels into a DisplayState.
50There 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
118DISPLAY CHANGE LISTENERES:
119==========================
120
121There QEMU sources provide the implementation for various
122DisplayChangeListeners, 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
135NOTE: The initialization sequence in vl.c only allows for a single listener
136on the main display state, but the rest of the code deals with several
137listeners per DisplayState just fine.
138
139Each DisplayChangeListener can specify a refresh period (e.g. every 1/60th
140of second). QEMU will then create a timer that will be programmed to called
141the listener's 'dpy_refresh' callback periodically. The point of this
142callback 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
158INITIALIZATION AND RUNTIME EXECUTION:
159=====================================
160
161Initialization happens in the qemu main() function in the vl.c source file.
162
163First, the hardware machine is initialized. The hardware fraembuffer emulation
164shall call graphic_console_init() to create a new DisplayState. Note that the
165object returned by this function has a default DisplaySurface of 640x480 pixels
166allocated through malloc(). In other words, the hardware emulation does not
167set the size of the display state by default!
168
169After that, the listener's initialization function (e.g. sdl_display_init)
170is called. It is passed the DisplayState object and can replace the
171corresponding DisplaySurface with another one with proper dimensions, and
172eventually created with a different DisplayAllocator. It also registers a
173DisplayChangeListener to receive later state changes.
174
175Note that the VNC listener doesn't change the dimension of the DisplayState
176surface it is initialized with. However, it will react to dpy_resize events
177accordingly.
178
179NOTE: dpy_resize()s are currently only generated when switching between
180consoles, or when the framebuffer's size is modified by the guest kernel.
181
182
183The GUI timer, corresponding to the first listener than has one refresh
184period, drives the whole update process (if no listener provides a refresh
185period, a default 'no_graphic' timer is setup with a default refresh period
186of 30 frame/s).
187
188Things 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
216Eventually, hardware emulation can also trigger other dpy_xxxx events (e.g.
217dpy_resize, dpy_copy, dpy_fill....)
218
219Here'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