1Graphics 2========= 3 4Design overview 5--------------- 6 7The app_server drawing system was designed in BeOS with the goal to provide low latency response 8(it should look fast), making use of the quite powerful CPU, but somewhat limited RAM available 9at the time. 10 11As a result of these constraints, in BeOS the app_server operated with a single buffer framebuffer 12(there was not enough RAM and especially not enough video RAM to enable double buffer). It is also 13designed to use 2D acceleration whenever possible, to free up the CPU for other, more interesting 14tasks. This is achived by the use of "accelerants", add-ons loaded into app-server that communicate 15with the kernel part of graphics drivers. Usually the kernel part will be as minimal as possible, 16providing low-level access to the video card (command ring buffers, memory mapping of registers, 17DMA setup, that kind of things), and the accelerant will be doing the higher level work on top of 18it. Note, however, that on modern hardware, the graphics card acceleration is often not that fast 19for 2D work, compared to the power offered by multi-GigaHerz CPUs. So, Haiku does not currently use 20most of these acceleration features, doing its drawing using the CPU instead. 21 22The single buffer approach creates a problem: applications that are too slow to redraw things can 23result in "glitches" on screen. These are of mainly two types: flickering and stamping. The 24app_server in Haiku takes some care to avoid these. 25 26Desktop Initialization 27----------------------- 28 29The graphics hardware is abstracted from the rest of the app_server. 30When started, the server creates the desktop, which is little more than 31a collection of workspaces. The desktop actually creates a DisplayDriver 32and then calls the driver's method Inititialize() before calling a few 33high-level routines for setup. Below is the process by which the 34HWDriver class, which is used to access the primary graphics card in the 35system, followed by the steps taken to set up the desktop. 36 37Load Accelerant 38............... 39 40First of all, the available video cards are scanned by enumerating the contents of /dev/graphics. 41For each device, the B_GET_ACCELERANT_SIGNATURE ioctl is used to find the corresponding accelerant 42name. 43 44The app_server looks for an accelerant matching that name in the "accelerants" subdirectory of each 45add-on directory (enumerated using BPathFinder). The first matching accelerant is loaded 46using load_add_on(). Then the get_accelerant_hook() function is obtained through get_image_symbol. 47This is the only needed entry point for the accelerant, and can be used to call all the other 48needed code, starting with B_INIT_ACCELERANT. 49 50For more information about the accelerant hooks, see `Writing video card drivers <https://www.haiku-os.org/legacy-docs/writing-video-card-drivers/04-accelerant>`_. 51 52Set up workspaces 53................. 54 55Workspace preferences are read in from disk. If they exist, they are 56used; otherwise the default of 3 workspace, each with the settings 57640x480x256@59.9Hz, is used. Each workspace is initialized to the proper 58information (preferences or default). Additionally, all settings are 59checked and possibly "clipped" by information gained through the driver 60class. With the desktop having been given the proper settings, the 61default workspace, 0, is activated. 62 63Display 64....... 65 66Provided that everything has gone well so far, the screen is filled to 67the user-set workspace color or RGB(51,102,160) Also, the global 68clipboard is created, which is nothing more than a BClipboard object. 69 70The Input Server will notify the app_server of its own existence, at which 71point the cursor will be set to B_HAND_CURSOR and shown on the screen. 72 73Window management 74----------------- 75 76Window management is a complicated issue, requiring the cooperation of a 77number of different types of elements. Each BApplication, BWindow, and 78BView has a counterpart in the app_server which has a role to play. 79These objects are Decorators, ServerApps, ServerWindows, Layers, and 80WindowBorders. 81 82ServerApps 83.......... 84 85ServerApp objects are created when a BApplication notifies the 86app_server of its presence. In acknowledging the BApplication's 87existence, the server creates a ServerApp which will handle future 88server-app communications and notifies the BApplication of the port to 89which it must send future messages. 90 91ServerApps are each an independent thread which has a function similar 92to that of a BLooper, but with additional tasks. When a BWindow is 93created, it spawns a ServerWindow object to handle the new window. The 94same applies to when a window is destroyed. Cursor commands and all 95other BApplication functions which require server interaction are also 96handled. B_QUIT_REQUESTED messages are received and passed along to the 97main thread in order for the ServerApp object to be destroyed. The 98server's Picasso thread also utilizes ServerApp::PingTarget in order to 99determine whether the counterpart BApplication is still alive and 100running. 101 102ServerWindows 103............. 104 105ServerWindow objects' purpose is to take care of the needs of BWindows. 106This includes all calls which require a trip to the server, such as 107BView graphics calls and sending messages to invoke hook functions 108within a window. 109 110Layers 111...... 112 113Layers are shadowed BViews and are used to handle much BView 114functionality and also determine invalid screen regions. Hierarchal 115functions, such as AddChild, are mirrored. Invalid regions are tracked 116and generate Draw requests which are sent to the application for a 117specific BView to update its part of the screen. 118 119WindowBorders 120............. 121 122WindowBorders are a special kind of Layer with no BView counterpart, 123designed to handle window management issues, such as click tests, resize 124and move events, and ensuring that its decorator updates the screen 125appropriately. 126 127Decorators 128.......... 129 130Decorators are addons which are intended to do one thing: draw the 131window frame. The Decorator API and development information is described 132in the Decorator Development Reference. They are essentially the means 133by which WindowBorders draw to the screen. 134 135How It All Works 136................ 137 138The app_server is one large, complex beast because of all the tasks it 139performs. It also utilizes the various objects to accomplish them. Input 140messages are received from the Input Server and all messages not 141specific to the server (such as Ctrl-Alt-Shift-Backspace) are passed to 142the active application, if any. Mouse clicks are passed to the 143ServerWindow class for hit testing. These hit tests can result in window 144tabs and buttons being clicked, or mouse click messages being passed to 145a specific view in a window. 146 147These input messages which are passed to a running application will 148sometimes cause things to happen inside it, such as button presses, 149window closings/openings, etc. which will cause messages to be sent to 150the server. These messages are sent either from a BWindow to a 151ServerWindow or a BApplication to a ServerApp. When such messages are 152sent, then the corresponding app_server object performs an appropriate 153action. 154 155Screen Updates 156-------------- 157 158Managing invalidation 159..................... 160 161The drawing is architectured around a single framebuffer, where all windows can draw. 162In general, redrawing should be avoided when not necessary, and if possible, multiple drawing 163requests should be combined together to avoid redrawing the same area over and over. 164 165To achieve this, a protocol to decide which parts of the screen need to be redrawn is implemented. 166 167When something needs to change, that region is marked as "invalidated" and the app_server will 168ask the corresponding view to redraw itself. Invalidation can happen in two ways: 169 170- Window management events (a window was resized or hidden, for example) 171- The application asked to redraw something by calling Invalidate() 172 173These two are handled slightly differently. When the event comes from window management, one of 174the views involved will have parts of it newly exposed (previously they were hidden by another 175window that is now hidden, or they were outside the window bounds, for example). In this case, 176app_server will immediately fill the newly exposed area with the view color. This avoids one of 177the two drawing problems when applications are too slow to redraw: stamping. For example, if one 178windows is not redrawing fast enough, and another is moved above it, that movement will quickly 179hide and re-expose parts of the bottom window. If the window does not redraw fast enough, and 180nothing is done, we would be left with parts of the top window being partially drawn where they 181shouldn't be anymore. 182 183In the case of invalidation coming from the view itself, however, things are a bit different. We 184can assume that the view had already drawn something at that place. If we cleared the area to the 185view color, and the view takes a little time to redraw, this would result in flickering: the view 186would be briefly visible with only its view color, and then redrawn with its content again. So, 187in the case of invalidation, the app_server does nothing, and waits for the view to redraw itself. 188 189Getting things drawn on screen 190.............................. 191 192Screen updates are done entirely through the BView class or some 193subclass thereof, hereafter referred to as a view. A view's drawing 194commands will cause its window to store draw command messages in a 195message packet. At some point Flush() will be called and the command 196packet will be sent to the window's ServerWindow object inside the 197server. 198 199The ServerWindow will receive the packet, check to ensure that its size 200is correct, and begin retrieving each command from the packet and 201dispatching it, taking the appropriate actions. Actual drawing commands, 202such as StrokeRect, will involve the ServerWindow object calling the 203appropriate command in the graphics module for the Layer corresponding 204to the view which sent the command. 205 206The commands are grouped together in a drawing session, that corresponds to a call to the 207BView::Draw() method. In Haiku, the app_server uses double buffering, and all the drawing from 208one session will be done on the backbuffer, and moved to the front buffer only when the session is 209complete. The normal workflow is to trigger this by a request to draw something (either an 210"expose" event because a part of the window has become visible, or a call to the Invalidate function 211from the application side). However, it is also possible for views to send "unsollicited" drawing 212commands outside of an update session. While this will work, the lack of a session means each 213command will be handled separately, and immediately copied to the front buffer. As a result, there 214will be more fickering and the drawing will be a lot slower. 215 216When interpreting the drawing commands, app_server will prevent any drawing from happening outside 217the area designated for a given view, including parts of it that could be hidden by other windows. 218There is an exception to this, however: when using BDirectWindow, it is possible to access the 219whole frame buffer. In this case, app_server provides the application with a BRegion it should 220redraw, and it is up to the application to not draw ouside those bounds. 221 222Offscreen views 223............... 224 225When a view does very complex drawing, that will take more than a frame to complete, the single 226framebuffer design is not desirable, and will result in a lot of flickering as partially drawn 227states of the view are shown on screen. To avoid this, the app_server provides the option for a 228view to draw off-screen, into a BBitmap. When the bitmap is complete, it can then be put on-screen 229using another view. 230 231This can be done in two ways: either using DrawBitmap() or SetViewBitmap(). The latter is better, 232since it simply lets app_server know that the view should show that bitmap, and then there is no 233need to do anything to handle expose and invalidate events, the app_server can automatically draw 234the bitmap instead of using the view color to fill the newly exposed or invalidated area. 235 236Overlays 237........ 238 239When view bitmaps are not enough, it is possible to go one step further: have the hardware insert 240the picture inside a view, instead of app_server having to copy it in the framebuffer. This is 241achieved using overlays. The API is similar to SetViewBitmap, but the bitmap is allocated directly 242in video memory and managed by the video card. Unfortunately, not all video drivers currently 243support this feature. 244 245It is possible to mix overlays with normal drawing. The overlay is normally made visible only when 246the framebuffer is a certain specific color(usually pure green or pure magenta, the specific 247color is determined by the graphics driver and multiple colors may be used for multiple overlays 248from different views, if the hardware can do that). The application can then simply let the view be 249filled with that 'color key' (setting it as the view color), or it can draw other things that will 250be displayed over the 'overlay' picture. 251 252Depending on the graphics hardware, overlays can also be resized in hardware, and use a different 253colorspace from other parts of the framebuffer (for example, a video overlay can be in YUV format 254while the framebuffer is in RGB or even in a 256 color palette mode). 255 256Cursor Management 257----------------- 258 259The app_server handles all messiness to do with the cursor. The cursor 260commands which are members of the BApplication class will send a message 261to its ServerApp, which will then call the DisplayDriver's appropriate 262function. The DisplayDriver used will actually handle the drawing of the 263cursor and whether or not to do so at any given time. 264 265In addition to the 1 bit per pixel cursors used in BeOS, Haiku also allows to create a BCursor 266object from a BBitmap in any colorspace. This allows color cursors and also larger cursor sizes. 267The default cursors also use greyscale and alpha channel for antialiasing. 268 269Display Drivers 270--------------- 271 272Unlike the BeOS R5 app_server, Haiku' server has an extra abstraction layer between the graphic 273driver and the main drawing functions. This allows to generalize the interface and redirect the 274drawing commands in various ways. For example, drawing commands can be redirected to another 275machine for the remote_app_server, or drawing for a specific window can be granted direct access 276to the framebuffer on a specific display and video card, while other applications go through the 277normal process of drawing only to their currently exposed region only. 278 279 280