Graphics=========Design overview---------------The app_server drawing system was designed in BeOS with the goal to provide low latency response(it should look fast), making use of the quite powerful CPU, but somewhat limited RAM availableat the time.As a result of these constraints, in BeOS the app_server operated with a single buffer framebuffer(there was not enough RAM and especially not enough video RAM to enable double buffer). It is alsodesigned to use 2D acceleration whenever possible, to free up the CPU for other, more interestingtasks. This is achived by the use of "accelerants", add-ons loaded into app-server that communicatewith the kernel part of graphics drivers. Usually the kernel part will be as minimal as possible,providing low-level access to the video card (command ring buffers, memory mapping of registers,DMA setup, that kind of things), and the accelerant will be doing the higher level work on top ofit. Note, however, that on modern hardware, the graphics card acceleration is often not that fastfor 2D work, compared to the power offered by multi-GigaHerz CPUs. So, Haiku does not currently usemost of these acceleration features, doing its drawing using the CPU instead.The single buffer approach creates a problem: applications that are too slow to redraw things canresult in "glitches" on screen. These are of mainly two types: flickering and stamping. Theapp_server in Haiku takes some care to avoid these.Desktop Initialization-----------------------The graphics hardware is abstracted from the rest of the app_server.When started, the server creates the desktop, which is little more thana collection of workspaces. The desktop actually creates a DisplayDriverand then calls the driver's method Inititialize() before calling a fewhigh-level routines for setup. Below is the process by which theHWDriver class, which is used to access the primary graphics card in thesystem, followed by the steps taken to set up the desktop.Load Accelerant...............First of all, the available video cards are scanned by enumerating the contents of /dev/graphics.For each device, the B_GET_ACCELERANT_SIGNATURE ioctl is used to find the corresponding accelerantname.The app_server looks for an accelerant matching that name in the "accelerants" subdirectory of eachadd-on directory (enumerated using BPathFinder). The first matching accelerant is loadedusing load_add_on(). Then the get_accelerant_hook() function is obtained through get_image_symbol.This is the only needed entry point for the accelerant, and can be used to call all the otherneeded code, starting with B_INIT_ACCELERANT.For more information about the accelerant hooks, see `Writing video card drivers <https://www.haiku-os.org/legacy-docs/writing-video-card-drivers/04-accelerant>`_.Set up workspaces.................Workspace preferences are read in from disk. If they exist, they areused; otherwise the default of 3 workspace, each with the settings640x480x256@59.9Hz, is used. Each workspace is initialized to the properinformation (preferences or default). Additionally, all settings arechecked and possibly "clipped" by information gained through the driverclass. With the desktop having been given the proper settings, thedefault workspace, 0, is activated.Display.......Provided that everything has gone well so far, the screen is filled tothe user-set workspace color or RGB(51,102,160) Also, the globalclipboard is created, which is nothing more than a BClipboard object.The Input Server will notify the app_server of its own existence, at whichpoint the cursor will be set to B_HAND_CURSOR and shown on the screen.Window management-----------------Window management is a complicated issue, requiring the cooperation of anumber of different types of elements. Each BApplication, BWindow, andBView has a counterpart in the app_server which has a role to play.These objects are Decorators, ServerApps, ServerWindows, Layers, andWindowBorders.ServerApps..........ServerApp objects are created when a BApplication notifies theapp_server of its presence. In acknowledging the BApplication'sexistence, the server creates a ServerApp which will handle futureserver-app communications and notifies the BApplication of the port towhich it must send future messages.ServerApps are each an independent thread which has a function similarto that of a BLooper, but with additional tasks. When a BWindow iscreated, it spawns a ServerWindow object to handle the new window. Thesame applies to when a window is destroyed. Cursor commands and allother BApplication functions which require server interaction are alsohandled. B_QUIT_REQUESTED messages are received and passed along to themain thread in order for the ServerApp object to be destroyed. Theserver's Picasso thread also utilizes ServerApp::PingTarget in order todetermine whether the counterpart BApplication is still alive andrunning.ServerWindows.............ServerWindow objects' purpose is to take care of the needs of BWindows.This includes all calls which require a trip to the server, such asBView graphics calls and sending messages to invoke hook functionswithin a window.Layers......Layers are shadowed BViews and are used to handle much BViewfunctionality and also determine invalid screen regions. Hierarchalfunctions, such as AddChild, are mirrored. Invalid regions are trackedand generate Draw requests which are sent to the application for aspecific BView to update its part of the screen.WindowBorders.............WindowBorders are a special kind of Layer with no BView counterpart,designed to handle window management issues, such as click tests, resizeand move events, and ensuring that its decorator updates the screenappropriately.Decorators..........Decorators are addons which are intended to do one thing: draw thewindow frame. The Decorator API and development information is describedin the Decorator Development Reference. They are essentially the meansby which WindowBorders draw to the screen.How It All Works................The app_server is one large, complex beast because of all the tasks itperforms. It also utilizes the various objects to accomplish them. Inputmessages are received from the Input Server and all messages notspecific to the server (such as Ctrl-Alt-Shift-Backspace) are passed tothe active application, if any. Mouse clicks are passed to theServerWindow class for hit testing. These hit tests can result in windowtabs and buttons being clicked, or mouse click messages being passed toa specific view in a window.These input messages which are passed to a running application willsometimes cause things to happen inside it, such as button presses,window closings/openings, etc. which will cause messages to be sent tothe server. These messages are sent either from a BWindow to aServerWindow or a BApplication to a ServerApp. When such messages aresent, then the corresponding app_server object performs an appropriateaction.Screen Updates--------------Managing invalidation.....................The drawing is architectured around a single framebuffer, where all windows can draw.In general, redrawing should be avoided when not necessary, and if possible, multiple drawingrequests should be combined together to avoid redrawing the same area over and over.To achieve this, a protocol to decide which parts of the screen need to be redrawn is implemented.When something needs to change, that region is marked as "invalidated" and the app_server willask the corresponding view to redraw itself. Invalidation can happen in two ways:- Window management events (a window was resized or hidden, for example)- The application asked to redraw something by calling Invalidate()These two are handled slightly differently. When the event comes from window management, one ofthe views involved will have parts of it newly exposed (previously they were hidden by anotherwindow that is now hidden, or they were outside the window bounds, for example). In this case,app_server will immediately fill the newly exposed area with the view color. This avoids one ofthe two drawing problems when applications are too slow to redraw: stamping. For example, if onewindows is not redrawing fast enough, and another is moved above it, that movement will quicklyhide and re-expose parts of the bottom window. If the window does not redraw fast enough, andnothing is done, we would be left with parts of the top window being partially drawn where theyshouldn't be anymore.In the case of invalidation coming from the view itself, however, things are a bit different. Wecan assume that the view had already drawn something at that place. If we cleared the area to theview color, and the view takes a little time to redraw, this would result in flickering: the viewwould be briefly visible with only its view color, and then redrawn with its content again. So,in the case of invalidation, the app_server does nothing, and waits for the view to redraw itself.Getting things drawn on screen..............................Screen updates are done entirely through the BView class or somesubclass thereof, hereafter referred to as a view. A view's drawingcommands will cause its window to store draw command messages in amessage packet. At some point Flush() will be called and the commandpacket will be sent to the window's ServerWindow object inside theserver.The ServerWindow will receive the packet, check to ensure that its sizeis correct, and begin retrieving each command from the packet anddispatching it, taking the appropriate actions. Actual drawing commands,such as StrokeRect, will involve the ServerWindow object calling theappropriate command in the graphics module for the Layer correspondingto the view which sent the command.The commands are grouped together in a drawing session, that corresponds to a call to theBView::Draw() method. In Haiku, the app_server uses double buffering, and all the drawing fromone session will be done on the backbuffer, and moved to the front buffer only when the session iscomplete. The normal workflow is to trigger this by a request to draw something (either an"expose" event because a part of the window has become visible, or a call to the Invalidate functionfrom the application side). However, it is also possible for views to send "unsollicited" drawingcommands outside of an update session. While this will work, the lack of a session means eachcommand will be handled separately, and immediately copied to the front buffer. As a result, therewill be more fickering and the drawing will be a lot slower.When interpreting the drawing commands, app_server will prevent any drawing from happening outsidethe area designated for a given view, including parts of it that could be hidden by other windows.There is an exception to this, however: when using BDirectWindow, it is possible to access thewhole frame buffer. In this case, app_server provides the application with a BRegion it shouldredraw, and it is up to the application to not draw ouside those bounds.Offscreen views...............When a view does very complex drawing, that will take more than a frame to complete, the singleframebuffer design is not desirable, and will result in a lot of flickering as partially drawnstates of the view are shown on screen. To avoid this, the app_server provides the option for aview to draw off-screen, into a BBitmap. When the bitmap is complete, it can then be put on-screenusing another view.This can be done in two ways: either using DrawBitmap() or SetViewBitmap(). The latter is better,since it simply lets app_server know that the view should show that bitmap, and then there is noneed to do anything to handle expose and invalidate events, the app_server can automatically drawthe bitmap instead of using the view color to fill the newly exposed or invalidated area.Overlays........When view bitmaps are not enough, it is possible to go one step further: have the hardware insertthe picture inside a view, instead of app_server having to copy it in the framebuffer. This isachieved using overlays. The API is similar to SetViewBitmap, but the bitmap is allocated directlyin video memory and managed by the video card. Unfortunately, not all video drivers currentlysupport this feature.It is possible to mix overlays with normal drawing. The overlay is normally made visible only whenthe framebuffer is a certain specific color(usually pure green or pure magenta, the specificcolor is determined by the graphics driver and multiple colors may be used for multiple overlaysfrom different views, if the hardware can do that). The application can then simply let the view befilled with that 'color key' (setting it as the view color), or it can draw other things that willbe displayed over the 'overlay' picture.Depending on the graphics hardware, overlays can also be resized in hardware, and use a differentcolorspace from other parts of the framebuffer (for example, a video overlay can be in YUV formatwhile the framebuffer is in RGB or even in a 256 color palette mode).Cursor Management-----------------The app_server handles all messiness to do with the cursor. The cursorcommands which are members of the BApplication class will send a messageto its ServerApp, which will then call the DisplayDriver's appropriatefunction. The DisplayDriver used will actually handle the drawing of thecursor and whether or not to do so at any given time.In addition to the 1 bit per pixel cursors used in BeOS, Haiku also allows to create a BCursorobject from a BBitmap in any colorspace. This allows color cursors and also larger cursor sizes.The default cursors also use greyscale and alpha channel for antialiasing.Display Drivers---------------Unlike the BeOS R5 app_server, Haiku's server has an extra abstraction layer between the graphicdriver and the main drawing functions. This allows to generalize the interface and redirect thedrawing commands in various ways. For example, drawing commands can be redirected to anothermachine for the remote_app_server, or drawing for a specific window can be granted direct accessto the framebuffer on a specific display and video card, while other applications go through thenormal process of drawing only to their currently exposed region only.