• Immutable Page
  • Info
  • Attachments

Multihead and Compiz

Scope of this document

This document is mainly intended for developers or advanced users. It does not cover configuration of X for specific video cards or situations. It is meant to explain how Compiz deals with multihead, not how to set up X.

Two fundamentally different ways of doing multihead

Multihead is when more than one monitor, projector, TV, etc. (ie. head) is hooked up to the same computer.

There are two fundamentally different approaches to this in X:

  • one big screen (bigscreen)

  • multiple screens (multiscreen)

Note that there are different implementations of bigscreen multihead. As far as Compiz is concerned, Xinerama, MergedFB, TwinView and XRandR are the same. XRandR does have a different way of getting information, but for plugins, all of these different approaches are transparent.

In the traditional multihead setup, each head provides one screen. For Compiz, this means one compiz instance per screen. They share the same display. For two heads, this would give us a DISPLAY variable :0.0 for the first screen, and :0.1 for the second. These heads are mostly independent of each other. This means that windows can't be moved between them, among other things. The main reason for using this setup is to be able to use multiple video cards. It is easier to provide several screens with the needed functionality (DRI, Composite, etc.) when you are using several video cards than it is to provide a single big screen. Another rather neat result is that you get one cube per head; these can rotate independently of each other.

What Compiz needs from X

Compiz supports both bigscreen multihead, and multiscreen. However, that does not mean it will work.

With nVidia, you should have no real problems. Just set up TwinView and you should be good to go. nVidia users can also use multiscreen, although it is not as polished driver-wise as TwinView.

ATI users might run into problems, as the open source drivers do not provide DRI on both screens in multihead.

Intel users using the i810 driver generally will not have problems; they will just need to make sure that each head is the same resolution. The new world (intel) driver with X.org 7.3, with XRandR 1.2 support, should fix this.

Compiz needs a working AIGLX, Xgl or nVidia rendering path for all screens to work. Compiz also needs Composite working on all screens. Check for these in the X log if you are having trouble starting Compiz on multiscreen.

There isn't much to think about for most programmers when it comes to multiscreen, since there is only one Compiz instance per screen. X11 Display information is also handled on a per-screen basis.

For multiscreen you also have to make sure the OpenGL context is correct before modifying textures. This can easily be done by passing GLScreen::get (screen)->makeCurrent () before modifying a texture. All core functions that deals with textures do this.

Bigscreen, however, is slightly more complicated. With bigscreen, we only deal with one CompScreen, but the CompScreen::outputDevs () comes into play. For instance, remember the difference between the monitor width and screen width. In addition to that, Compiz also sets up different CompOutput targets for drawing.

For each head in a bigscreen environment, the GLScreenInterface::glPaintOutput() procs are called. They are called at the "bottom" of the paintScreen (), which is only called once per actual screen. The CompScreen::fullscreenOutput () also makes things even more complicated, which is a special CompOutput which causes us to draw to the entire screen, not just one head.

The reason you have to deal with CompScreen::fullscreenOutput () is the OpenGL viewport. Usually we draw each head by it self, and that's fine, but this means we move the OpenGL viewport for each draw, but we do not adjust the projection matrix. That means that if you zoom out to the same coordinates on two heads without CompScreen::fullscreenOutput (), you will break the picture, because you are zooming two different images to the center of EACH output head. Using CompScreen::fullscreenOutput () means that you draw "both" images as one, and therefore don't break them when you zoom them, because they are transformed as one.

You want to use CompScreen::fullscreenOutput () whenever you are doing animations that affect the entire viewport, like cube rotations, expo and more.

It is always a good idea to give the user a few options in this area. A setup like this can be split over two identical monitors, or maybe one of them is a TV that is usually turned off.

Common pitfalls

  • Using CompScreen::width () and CompScreen::height () when you should be using the output-specific widths and heights.

  • Assuming the heads are symmetrical and to the left/right of each other.
  • Not using GLScreen::Get (screen)->makeScreenCurrent () when dealing with textures.

Development/zero-nine/Multihead (last edited 2010-07-25 09:04:16 by 124-169-107-122)