]> icculus.org git repositories - dana/openbox.git/blob - render2/instance.c
add support for shaped surfaces
[dana/openbox.git] / render2 / instance.c
1 #include "instance.h"
2 #include "surface.h"
3 #include "debug.h"
4 #include "glft/glft.h"
5 #include <stdlib.h>
6 #include <assert.h>
7
8 static int glft_init = 0;
9
10 static int glx_rating(Display *display, XVisualInfo *v)
11 {
12     int rating = 0;
13     int val;
14     RrDebug("evaluating visual %d\n", (int)v->visualid);
15     glXGetConfig(display, v, GLX_BUFFER_SIZE, &val);
16     RrDebug("buffer size %d\n", val);
17
18     switch (val) {
19     case 32:
20         rating += 300;
21     break;
22     case 24:
23         rating += 200;
24     break;
25     case 16:
26         rating += 100;
27     break;
28     }
29
30     glXGetConfig(display, v, GLX_LEVEL, &val);
31     RrDebug("level %d\n", val);
32     if (val != 0)
33         rating = -10000;
34
35     glXGetConfig(display, v, GLX_DEPTH_SIZE, &val);
36     RrDebug("depth size %d\n", val);
37     switch (val) {
38     case 32:
39         rating += 30;
40     break;
41     case 24:
42         rating += 20;
43     break;
44     case 16:
45         rating += 10;
46     break;
47     case 0:
48         rating -= 10000;
49     }
50
51     glXGetConfig(display, v, GLX_DOUBLEBUFFER, &val);
52     RrDebug("double buffer %d\n", val);
53     if (val)
54         rating++;
55     return rating;
56 }
57
58 struct RrInstance *RrInstanceNew(Display *display, int screen)
59 {
60     int count, i = 0, val, best = 0, rate = 0, temp;
61     XVisualInfo vimatch, *vilist;
62
63     vimatch.screen = screen;
64     vimatch.class = TrueColor;
65     vilist = XGetVisualInfo(display, VisualScreenMask | VisualClassMask,
66                             &vimatch, &count);
67
68     if (vilist) {
69         RrDebug("looking for a GL visual in %d visuals\n", count);
70         for (i = 0; i < count; i++) {
71             glXGetConfig(display, &vilist[i], GLX_USE_GL, &val);
72             if (val) {
73                 temp = glx_rating(display, &vilist[i]);
74                 if (temp > rate) {
75                     best = i;
76                     rate = temp;
77                 }
78             }
79         }
80     }
81     if (rate > 0) {
82         struct RrInstance *inst;
83
84         RrDebug("picked visual %d with rating %d\n", best, rate);
85
86         if (!glft_init) {
87             if (!GlftInit())
88                 return NULL;
89             glft_init = 1;
90         }
91
92         inst = malloc(sizeof(struct RrInstance));
93         inst->display = display;
94         inst->screen = screen;
95         inst->visinfo = vilist[best];
96         inst->cmap = XCreateColormap(display, RootWindow(display, screen),
97                                      RrVisual(inst), AllocNone);
98         inst->glx_context = glXCreateContext(display, &vilist[best],
99                                              NULL, True);
100         inst->shape_window = XCreateSimpleWindow(display,
101                                                  RootWindow(display, screen),
102                                                  0, 0, 1, 1, 0, 0, 0);
103         inst->surface_map = g_hash_table_new(g_int_hash, g_int_equal);
104
105         assert(inst->glx_context);
106
107         return inst;
108     }
109
110     RrDebug("unable to find a suitable GL visual\n");
111     return NULL;
112 }
113
114 void RrInstanceFree(struct RrInstance *inst)
115 {
116     if (inst) {
117         g_hash_table_destroy(inst->surface_map);
118         glXDestroyContext(inst->display, inst->glx_context);
119         XFreeColormap(inst->display, inst->cmap);
120         free(inst);
121     }
122 }
123
124 int RrInstanceDepth(struct RrInstance *inst)
125 {
126     return inst->visinfo.depth;
127 }
128
129 Colormap RrInstanceColormap(struct RrInstance *inst)
130 {
131     return inst->cmap;
132 }
133
134 Visual *RrInstanceVisual(struct RrInstance *inst)
135 {
136     return inst->visinfo.visual;
137 }
138
139 void RrInstaceAddSurface(struct RrSurface *sur)
140 {
141     g_hash_table_replace(RrSurfaceInstance(sur)->surface_map, &sur->win, sur);
142 }
143
144 void RrInstaceRemoveSurface(struct RrSurface *sur)
145 {
146     g_hash_table_remove(RrSurfaceInstance(sur)->surface_map, &sur->win);
147 }
148
149 struct RrSurface *RrInstaceLookupSurface(struct RrInstance *inst, Window win)
150 {
151     return g_hash_table_lookup(inst->surface_map, &win);
152 }