1 /*
2  * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
3  * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice including the dates of first publication and
13  * either this permission notice or a reference to
14  * http://oss.sgi.com/projects/FreeB/
15  * shall be included in all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20  * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
22  * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23  * SOFTWARE.
24  *
25  * Except as contained in this notice, the name of Silicon Graphics, Inc.
26  * shall not be used in advertising or otherwise to promote the sale, use or
27  * other dealings in this Software without prior written authorization from
28  * Silicon Graphics, Inc.
29  */
30 
31 #ifdef HAVE_DIX_CONFIG_H
32 #include <dix-config.h>
33 #endif
34 
35 #include <GL/glxtokens.h>
36 #include <string.h>
37 #include <windowstr.h>
38 #include <os.h>
39 #include <colormapst.h>
40 
41 #include "extinit.h"
42 #include "privates.h"
43 #include "glxserver.h"
44 #include "glxutil.h"
45 #include "glxext.h"
46 #include "protocol-versions.h"
47 
48 #ifdef COMPOSITE
49 #include "compositeext.h"
50 #endif
51 
52 static DevPrivateKeyRec glxScreenPrivateKeyRec;
53 
54 #define glxScreenPrivateKey (&glxScreenPrivateKeyRec)
55 
56 const char GLServerVersion[] = "1.4";
57 static const char GLServerExtensions[] =
58     "GL_ARB_depth_texture "
59     "GL_ARB_draw_buffers "
60     "GL_ARB_fragment_program "
61     "GL_ARB_fragment_program_shadow "
62     "GL_ARB_imaging "
63     "GL_ARB_multisample "
64     "GL_ARB_multitexture "
65     "GL_ARB_occlusion_query "
66     "GL_ARB_point_parameters "
67     "GL_ARB_point_sprite "
68     "GL_ARB_shadow "
69     "GL_ARB_shadow_ambient "
70     "GL_ARB_texture_border_clamp "
71     "GL_ARB_texture_compression "
72     "GL_ARB_texture_cube_map "
73     "GL_ARB_texture_env_add "
74     "GL_ARB_texture_env_combine "
75     "GL_ARB_texture_env_crossbar "
76     "GL_ARB_texture_env_dot3 "
77     "GL_ARB_texture_mirrored_repeat "
78     "GL_ARB_texture_non_power_of_two "
79     "GL_ARB_transpose_matrix "
80     "GL_ARB_vertex_program "
81     "GL_ARB_window_pos "
82     "GL_EXT_abgr "
83     "GL_EXT_bgra "
84     "GL_EXT_blend_color "
85     "GL_EXT_blend_equation_separate "
86     "GL_EXT_blend_func_separate "
87     "GL_EXT_blend_logic_op "
88     "GL_EXT_blend_minmax "
89     "GL_EXT_blend_subtract "
90     "GL_EXT_clip_volume_hint "
91     "GL_EXT_copy_texture "
92     "GL_EXT_draw_range_elements "
93     "GL_EXT_fog_coord "
94     "GL_EXT_framebuffer_object "
95     "GL_EXT_multi_draw_arrays "
96     "GL_EXT_packed_pixels "
97     "GL_EXT_paletted_texture "
98     "GL_EXT_point_parameters "
99     "GL_EXT_polygon_offset "
100     "GL_EXT_rescale_normal "
101     "GL_EXT_secondary_color "
102     "GL_EXT_separate_specular_color "
103     "GL_EXT_shadow_funcs "
104     "GL_EXT_shared_texture_palette "
105     "GL_EXT_stencil_two_side "
106     "GL_EXT_stencil_wrap "
107     "GL_EXT_subtexture "
108     "GL_EXT_texture "
109     "GL_EXT_texture3D "
110     "GL_EXT_texture_compression_dxt1 "
111     "GL_EXT_texture_compression_s3tc "
112     "GL_EXT_texture_edge_clamp "
113     "GL_EXT_texture_env_add "
114     "GL_EXT_texture_env_combine "
115     "GL_EXT_texture_env_dot3 "
116     "GL_EXT_texture_filter_anisotropic "
117     "GL_EXT_texture_lod "
118     "GL_EXT_texture_lod_bias "
119     "GL_EXT_texture_mirror_clamp "
120     "GL_EXT_texture_object "
121     "GL_EXT_texture_rectangle "
122     "GL_EXT_vertex_array "
123     "GL_3DFX_texture_compression_FXT1 "
124     "GL_APPLE_packed_pixels "
125     "GL_ATI_draw_buffers "
126     "GL_ATI_texture_env_combine3 "
127     "GL_ATI_texture_mirror_once "
128     "GL_HP_occlusion_test "
129     "GL_IBM_texture_mirrored_repeat "
130     "GL_INGR_blend_func_separate "
131     "GL_MESA_pack_invert "
132     "GL_MESA_ycbcr_texture "
133     "GL_NV_blend_square "
134     "GL_NV_depth_clamp "
135     "GL_NV_fog_distance "
136     "GL_NV_fragment_program_option "
137     "GL_NV_fragment_program2 "
138     "GL_NV_light_max_exponent "
139     "GL_NV_multisample_filter_hint "
140     "GL_NV_point_sprite "
141     "GL_NV_texgen_reflection "
142     "GL_NV_texture_compression_vtc "
143     "GL_NV_texture_env_combine4 "
144     "GL_NV_texture_expand_normal "
145     "GL_NV_texture_rectangle "
146     "GL_NV_vertex_program2_option "
147     "GL_NV_vertex_program3 "
148     "GL_OES_compressed_paletted_texture "
149     "GL_SGI_color_matrix "
150     "GL_SGI_color_table "
151     "GL_SGIS_generate_mipmap "
152     "GL_SGIS_multisample "
153     "GL_SGIS_point_parameters "
154     "GL_SGIS_texture_border_clamp "
155     "GL_SGIS_texture_edge_clamp "
156     "GL_SGIS_texture_lod "
157     "GL_SGIX_depth_texture "
158     "GL_SGIX_shadow "
159     "GL_SGIX_shadow_ambient "
160     "GL_SUN_slice_accum ";
161 
162 static Bool
glxCloseScreen(ScreenPtr pScreen)163 glxCloseScreen(ScreenPtr pScreen)
164 {
165     __GLXscreen *pGlxScreen = glxGetScreen(pScreen);
166 
167     pScreen->CloseScreen = pGlxScreen->CloseScreen;
168 
169     pGlxScreen->destroy(pGlxScreen);
170 
171     return pScreen->CloseScreen(pScreen);
172 }
173 
174 __GLXscreen *
glxGetScreen(ScreenPtr pScreen)175 glxGetScreen(ScreenPtr pScreen)
176 {
177     return dixLookupPrivate(&pScreen->devPrivates, glxScreenPrivateKey);
178 }
179 
180 GLint
glxConvertToXVisualType(int visualType)181 glxConvertToXVisualType(int visualType)
182 {
183     static const int x_visual_types[] = {
184         TrueColor, DirectColor,
185         PseudoColor, StaticColor,
186         GrayScale, StaticGray
187     };
188 
189     return ((unsigned) (visualType - GLX_TRUE_COLOR) < 6)
190         ? x_visual_types[visualType - GLX_TRUE_COLOR] : -1;
191 }
192 
193 /* This code inspired by composite/compinit.c.  We could move this to
194  * mi/ and share it with composite.*/
195 
196 static VisualPtr
AddScreenVisuals(ScreenPtr pScreen,int count,int d)197 AddScreenVisuals(ScreenPtr pScreen, int count, int d)
198 {
199     int i;
200     DepthPtr depth;
201 
202     depth = NULL;
203     for (i = 0; i < pScreen->numDepths; i++) {
204         if (pScreen->allowedDepths[i].depth == d) {
205             depth = &pScreen->allowedDepths[i];
206             break;
207         }
208     }
209     if (depth == NULL)
210         return NULL;
211 
212     if (ResizeVisualArray(pScreen, count, depth) == FALSE)
213         return NULL;
214 
215     /* Return a pointer to the first of the added visuals. */
216     return pScreen->visuals + pScreen->numVisuals - count;
217 }
218 
219 static int
findFirstSet(unsigned int v)220 findFirstSet(unsigned int v)
221 {
222     int i;
223 
224     for (i = 0; i < 32; i++)
225         if (v & (1 << i))
226             return i;
227 
228     return -1;
229 }
230 
231 static void
initGlxVisual(VisualPtr visual,__GLXconfig * config)232 initGlxVisual(VisualPtr visual, __GLXconfig * config)
233 {
234     int maxBits;
235 
236     maxBits = max(config->redBits, max(config->greenBits, config->blueBits));
237 
238     config->visualID = visual->vid;
239     visual->class = glxConvertToXVisualType(config->visualType);
240     visual->bitsPerRGBValue = maxBits;
241     visual->ColormapEntries = 1 << maxBits;
242     visual->nplanes = config->redBits + config->greenBits + config->blueBits;
243 
244     visual->redMask = config->redMask;
245     visual->greenMask = config->greenMask;
246     visual->blueMask = config->blueMask;
247     visual->offsetRed = findFirstSet(config->redMask);
248     visual->offsetGreen = findFirstSet(config->greenMask);
249     visual->offsetBlue = findFirstSet(config->blueMask);
250 }
251 
252 static __GLXconfig *
pickFBConfig(__GLXscreen * pGlxScreen,VisualPtr visual)253 pickFBConfig(__GLXscreen * pGlxScreen, VisualPtr visual)
254 {
255     __GLXconfig *best = NULL, *config;
256     int best_score = 0;
257 
258     for (config = pGlxScreen->fbconfigs; config != NULL; config = config->next) {
259         int score = 0;
260 
261         if (config->redMask != visual->redMask ||
262             config->greenMask != visual->greenMask ||
263             config->blueMask != visual->blueMask)
264             continue;
265         if (config->visualRating != GLX_NONE)
266             continue;
267         /* Ignore multisampled configs */
268         if (config->sampleBuffers)
269             continue;
270         if (glxConvertToXVisualType(config->visualType) != visual->class)
271             continue;
272         /* If it's the 32-bit RGBA visual, demand a 32-bit fbconfig. */
273         if (visual->nplanes == 32 && config->rgbBits != 32)
274             continue;
275         /* If it's the 32-bit RGBA visual, do not pick sRGB capable config.
276          * This can cause issues with compositors that are not sRGB aware.
277          */
278         if (visual->nplanes == 32 && config->sRGBCapable == GL_TRUE)
279             continue;
280         /* Can't use the same FBconfig for multiple X visuals.  I think. */
281         if (config->visualID != 0)
282             continue;
283 #ifdef COMPOSITE
284         if (!noCompositeExtension) {
285             /* Use only duplicated configs for compIsAlternateVisuals */
286             if (!!compIsAlternateVisual(pGlxScreen->pScreen, visual->vid) !=
287                 !!config->duplicatedForComp)
288                 continue;
289         }
290 #endif
291         /*
292          * If possible, use the same swapmethod for all built-in visual
293          * fbconfigs, to avoid getting the 32-bit composite visual when
294          * requesting, for example, a SWAP_COPY fbconfig.
295          */
296         if (config->swapMethod == GLX_SWAP_UNDEFINED_OML)
297             score += 32;
298         if (config->swapMethod == GLX_SWAP_EXCHANGE_OML)
299             score += 16;
300         if (config->doubleBufferMode > 0)
301             score += 8;
302         if (config->depthBits > 0)
303             score += 4;
304         if (config->stencilBits > 0)
305             score += 2;
306         if (config->alphaBits > 0)
307             score++;
308 
309         if (score > best_score) {
310             best = config;
311             best_score = score;
312         }
313     }
314 
315     return best;
316 }
317 
318 void
__glXScreenInit(__GLXscreen * pGlxScreen,ScreenPtr pScreen)319 __glXScreenInit(__GLXscreen * pGlxScreen, ScreenPtr pScreen)
320 {
321     __GLXconfig *m;
322     __GLXconfig *config;
323     int i;
324 
325     if (!dixRegisterPrivateKey(&glxScreenPrivateKeyRec, PRIVATE_SCREEN, 0))
326         return;
327 
328     pGlxScreen->pScreen = pScreen;
329     pGlxScreen->GLextensions = strdup(GLServerExtensions);
330     pGlxScreen->GLXextensions = NULL;
331 
332     pGlxScreen->CloseScreen = pScreen->CloseScreen;
333     pScreen->CloseScreen = glxCloseScreen;
334 
335     i = 0;
336     for (m = pGlxScreen->fbconfigs; m != NULL; m = m->next) {
337         m->fbconfigID = FakeClientID(0);
338         m->visualID = 0;
339         i++;
340     }
341     pGlxScreen->numFBConfigs = i;
342 
343     pGlxScreen->visuals =
344         calloc(pGlxScreen->numFBConfigs, sizeof(__GLXconfig *));
345 
346     /* First, try to choose featureful FBconfigs for the existing X visuals.
347      * Note that if multiple X visuals end up with the same FBconfig being
348      * chosen, the later X visuals don't get GLX visuals (because we want to
349      * prioritize the root visual being GLX).
350      */
351     for (i = 0; i < pScreen->numVisuals; i++) {
352         VisualPtr visual = &pScreen->visuals[i];
353 
354         config = pickFBConfig(pGlxScreen, visual);
355         if (config) {
356             pGlxScreen->visuals[pGlxScreen->numVisuals++] = config;
357             config->visualID = visual->vid;
358 #ifdef COMPOSITE
359             if (!noCompositeExtension) {
360                 if (compIsAlternateVisual(pScreen, visual->vid))
361                     config->visualSelectGroup++;
362             }
363 #endif
364         }
365     }
366 
367     /* Then, add new visuals corresponding to all FBconfigs that didn't have
368      * an existing, appropriate visual.
369      */
370     for (config = pGlxScreen->fbconfigs; config != NULL; config = config->next) {
371         int depth;
372 
373         VisualPtr visual;
374 
375         if (config->visualID != 0)
376             continue;
377 
378         /* Only count RGB bits and not alpha, as we're not trying to create
379          * visuals for compositing (that's what the 32-bit composite visual
380          * set up above is for.
381          */
382         depth = config->redBits + config->greenBits + config->blueBits;
383 #ifdef COMPOSITE
384         if (!noCompositeExtension) {
385             if (config->duplicatedForComp) {
386                     depth += config->alphaBits;
387                     config->visualSelectGroup++;
388             }
389         }
390 #endif
391         /* Make sure that our FBconfig's depth can actually be displayed
392          * (corresponds to an existing visual).
393          */
394         for (i = 0; i < pScreen->numVisuals; i++) {
395             if (depth == pScreen->visuals[i].nplanes)
396                 break;
397         }
398         /* if it can't, fix up the fbconfig to not advertise window support */
399         if (i == pScreen->numVisuals)
400             config->drawableType &= ~(GLX_WINDOW_BIT);
401 
402         /* fbconfig must support window drawables */
403         if (!(config->drawableType & GLX_WINDOW_BIT)) {
404             config->visualID = 0;
405             continue;
406         }
407 
408         /* Create a new X visual for our FBconfig. */
409         visual = AddScreenVisuals(pScreen, 1, depth);
410         if (visual == NULL)
411             continue;
412 
413 #ifdef COMPOSITE
414         if (!noCompositeExtension) {
415             if (config->duplicatedForComp)
416                 (void) CompositeRegisterAlternateVisuals(pScreen, &visual->vid, 1);
417         }
418 #endif
419         pGlxScreen->visuals[pGlxScreen->numVisuals++] = config;
420         initGlxVisual(visual, config);
421     }
422 
423     dixSetPrivate(&pScreen->devPrivates, glxScreenPrivateKey, pGlxScreen);
424 
425     if (pGlxScreen->glvnd)
426         __glXEnableExtension(pGlxScreen->glx_enable_bits, "GLX_EXT_libglvnd");
427 
428     i = __glXGetExtensionString(pGlxScreen->glx_enable_bits, NULL);
429     if (i > 0) {
430         pGlxScreen->GLXextensions = xnfalloc(i);
431         (void) __glXGetExtensionString(pGlxScreen->glx_enable_bits,
432                                        pGlxScreen->GLXextensions);
433     }
434 
435 }
436 
437 void
__glXScreenDestroy(__GLXscreen * screen)438 __glXScreenDestroy(__GLXscreen * screen)
439 {
440     __GLXconfig *config, *next;
441 
442     free(screen->glvnd);
443     free(screen->GLXextensions);
444     free(screen->GLextensions);
445     free(screen->visuals);
446 
447     for (config = screen->fbconfigs; config != NULL; config = next) {
448         next = config->next;
449         free(config);
450     }
451 }
452