summaryrefslogtreecommitdiff
path: root/Multihead
blob: 7f428e4f02ffaefe336b5cc92093ca650285bb37 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
WARNING: Incomplete and possibly incorrect information follows.

Multihead and beryl
===================
0. Scope of this document
1. Two fundamentally diffrent ways of doing multihead
2. What Compiz needs from X
3. Code-related concerns.


0. Scope of this document
=========================
This document is meant mainly for developers or advanced users. It does not
cover configuration of X for specific video cards or situations. It is meant
to explain how Beryl deals with multihead, not how you set up X.

1. Two fundamentally diffrent ways of doing multihead
=====================================================
Multihead is when more than one monitor, projector, tv, etc (head) is 
hooked up to the same computer. 

There are two fundamentally different approaches to this in X. Xinerama
and "multiscreen" or traditional multihead.

Note that certain hardware vendors implement their own xinerama-like
functionality. Examples are nVidia's TwinView and ATI's mergedfb, also
xrandr acts the same way for what plugins are concerned.

In the traditional multihead setup, each head provides one screen.
For Compiz, this means one CompScreen each. 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 windows can't be moved between them, among
other things. The main reason for using this setup is for people with
multiple video cards. It's 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 which can
rotate independently of each other. 

2. 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, though it is not
as polished driver-wise as TwinView.

FIXME: Better input from Intel/ATI users.

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

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. 

3. Code-related concerns.
=========================

There isn't much to think about for most programmers when it comes to
multiscreen. Just make sure you don't mix the CompDisplay and CompScreen
data. Also, never use d->screens without cycling through it. On normal
setups, d->screens refers to the one and only screen, but on multiscreen,
it only refers to the first one. A rule of thumb is to pass the CompScreen
somehow whenever you know the function will use it. It's safe to get
CompDisplay from screen->display, but not vice versa.

The biggest challange with multiscreen is knowing when to share what. If
you're unsure, save on a per-screen basis. It might duplicate information
in multiscreen, but at least it will work.

For multiscreen you also have to make sure the OpenGL context is correct
before modifying textures. This can easily be done by passing
makeScreenCurrent (s) before modifying a texture. 

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

For each head in a bigscreen environment, the paintOutput() procs 
are called. They are called at the "bottom" of the paintScreen (), which is
only called once per actual screen. The fullscreenOutput also makes things
even more difficult, 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 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 s->fullscreenOutput, you will break the picture, because you are
zooming two different images to the center of EACH screen. Using
s->fullscreenOutput means that you draw "both" images as one, and therefor
don't break them when you zoom them.

You want to use fullscreenOutput whenever you are doing animations that
affect the entire viewport, like cube rotations (still doesn't do it at
present, and the result is obvious), expo and more.

Author: Kristian LyngstĂžl <kristian@beryl-project.org>