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