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 "privates.h"
42#include "glxserver.h"
43#include "glxutil.h"
44#include "glxext.h"
45#include "protocol-versions.h"
46
47static DevPrivateKeyRec glxScreenPrivateKeyRec;
48#define glxScreenPrivateKey (&glxScreenPrivateKeyRec)
49
50const char GLServerVersion[] = "1.4";
51static const char GLServerExtensions[] =
52			"GL_ARB_depth_texture "
53			"GL_ARB_draw_buffers "
54			"GL_ARB_fragment_program "
55			"GL_ARB_fragment_program_shadow "
56			"GL_ARB_imaging "
57			"GL_ARB_multisample "
58			"GL_ARB_multitexture "
59			"GL_ARB_occlusion_query "
60			"GL_ARB_point_parameters "
61			"GL_ARB_point_sprite "
62			"GL_ARB_shadow "
63			"GL_ARB_shadow_ambient "
64			"GL_ARB_texture_border_clamp "
65			"GL_ARB_texture_compression "
66			"GL_ARB_texture_cube_map "
67			"GL_ARB_texture_env_add "
68			"GL_ARB_texture_env_combine "
69			"GL_ARB_texture_env_crossbar "
70			"GL_ARB_texture_env_dot3 "
71			"GL_ARB_texture_mirrored_repeat "
72			"GL_ARB_texture_non_power_of_two "
73			"GL_ARB_transpose_matrix "
74			"GL_ARB_vertex_program "
75			"GL_ARB_window_pos "
76			"GL_EXT_abgr "
77			"GL_EXT_bgra "
78 			"GL_EXT_blend_color "
79			"GL_EXT_blend_equation_separate "
80			"GL_EXT_blend_func_separate "
81			"GL_EXT_blend_logic_op "
82 			"GL_EXT_blend_minmax "
83 			"GL_EXT_blend_subtract "
84			"GL_EXT_clip_volume_hint "
85			"GL_EXT_copy_texture "
86			"GL_EXT_draw_range_elements "
87			"GL_EXT_fog_coord "
88			"GL_EXT_framebuffer_object "
89			"GL_EXT_multi_draw_arrays "
90			"GL_EXT_packed_pixels "
91			"GL_EXT_paletted_texture "
92			"GL_EXT_point_parameters "
93			"GL_EXT_polygon_offset "
94			"GL_EXT_rescale_normal "
95			"GL_EXT_secondary_color "
96			"GL_EXT_separate_specular_color "
97			"GL_EXT_shadow_funcs "
98			"GL_EXT_shared_texture_palette "
99 			"GL_EXT_stencil_two_side "
100			"GL_EXT_stencil_wrap "
101			"GL_EXT_subtexture "
102			"GL_EXT_texture "
103			"GL_EXT_texture3D "
104			"GL_EXT_texture_compression_dxt1 "
105			"GL_EXT_texture_compression_s3tc "
106			"GL_EXT_texture_edge_clamp "
107 			"GL_EXT_texture_env_add "
108 			"GL_EXT_texture_env_combine "
109 			"GL_EXT_texture_env_dot3 "
110 			"GL_EXT_texture_filter_anisotropic "
111			"GL_EXT_texture_lod "
112 			"GL_EXT_texture_lod_bias "
113 			"GL_EXT_texture_mirror_clamp "
114			"GL_EXT_texture_object "
115			"GL_EXT_texture_rectangle "
116			"GL_EXT_vertex_array "
117			"GL_3DFX_texture_compression_FXT1 "
118			"GL_APPLE_packed_pixels "
119			"GL_ATI_draw_buffers "
120			"GL_ATI_texture_env_combine3 "
121			"GL_ATI_texture_mirror_once "
122 			"GL_HP_occlusion_test "
123			"GL_IBM_texture_mirrored_repeat "
124			"GL_INGR_blend_func_separate "
125			"GL_MESA_pack_invert "
126			"GL_MESA_ycbcr_texture "
127			"GL_NV_blend_square "
128			"GL_NV_depth_clamp "
129			"GL_NV_fog_distance "
130			"GL_NV_fragment_program "
131			"GL_NV_fragment_program_option "
132			"GL_NV_fragment_program2 "
133			"GL_NV_light_max_exponent "
134			"GL_NV_multisample_filter_hint "
135			"GL_NV_point_sprite "
136			"GL_NV_texgen_reflection "
137			"GL_NV_texture_compression_vtc "
138			"GL_NV_texture_env_combine4 "
139			"GL_NV_texture_expand_normal "
140			"GL_NV_texture_rectangle "
141			"GL_NV_vertex_program "
142			"GL_NV_vertex_program1_1 "
143			"GL_NV_vertex_program2 "
144			"GL_NV_vertex_program2_option "
145			"GL_NV_vertex_program3 "
146			"GL_OES_compressed_paletted_texture "
147			"GL_SGI_color_matrix "
148			"GL_SGI_color_table "
149			"GL_SGIS_generate_mipmap "
150			"GL_SGIS_multisample "
151			"GL_SGIS_point_parameters "
152			"GL_SGIS_texture_border_clamp "
153			"GL_SGIS_texture_edge_clamp "
154			"GL_SGIS_texture_lod "
155			"GL_SGIX_depth_texture "
156			"GL_SGIX_shadow "
157			"GL_SGIX_shadow_ambient "
158			"GL_SUN_slice_accum "
159			;
160
161/*
162** We have made the simplifying assuption that the same extensions are
163** supported across all screens in a multi-screen system.
164*/
165static char GLXServerVendorName[] = "SGI";
166unsigned glxMajorVersion = SERVER_GLX_MAJOR_VERSION;
167unsigned glxMinorVersion = SERVER_GLX_MINOR_VERSION;
168static char GLXServerExtensions[] =
169			"GLX_ARB_multisample "
170			"GLX_EXT_visual_info "
171			"GLX_EXT_visual_rating "
172			"GLX_EXT_import_context "
173                        "GLX_EXT_texture_from_pixmap "
174			"GLX_OML_swap_method "
175			"GLX_SGI_make_current_read "
176#ifndef __APPLE__
177			"GLX_SGIS_multisample "
178#endif
179			"GLX_SGIX_fbconfig "
180			"GLX_SGIX_pbuffer "
181			"GLX_MESA_copy_sub_buffer "
182                        "GLX_INTEL_swap_event"
183			;
184
185static Bool
186glxCloseScreen (int index, ScreenPtr pScreen)
187{
188    __GLXscreen *pGlxScreen = glxGetScreen(pScreen);
189
190    pScreen->CloseScreen = pGlxScreen->CloseScreen;
191
192    pGlxScreen->destroy(pGlxScreen);
193
194    return pScreen->CloseScreen(index, pScreen);
195}
196
197__GLXscreen *
198glxGetScreen(ScreenPtr pScreen)
199{
200    return dixLookupPrivate(&pScreen->devPrivates, glxScreenPrivateKey);
201}
202
203_X_EXPORT void GlxSetVisualConfigs(int nconfigs,
204                         void *configs, void **privates)
205{
206    /* We keep this stub around for the DDX drivers that still
207     * call it. */
208}
209
210GLint glxConvertToXVisualType(int visualType)
211{
212    static const int x_visual_types[] = {
213	TrueColor,   DirectColor,
214	PseudoColor, StaticColor,
215	GrayScale,   StaticGray
216    };
217
218    return ( (unsigned) (visualType - GLX_TRUE_COLOR) < 6 )
219	? x_visual_types[ visualType - GLX_TRUE_COLOR ] : -1;
220}
221
222/* This code inspired by composite/compinit.c.  We could move this to
223 * mi/ and share it with composite.*/
224
225static VisualPtr
226AddScreenVisuals(ScreenPtr pScreen, int count, int d)
227{
228    int		 i;
229    DepthPtr	 depth;
230
231    depth = NULL;
232    for (i = 0; i < pScreen->numDepths; i++) {
233	if (pScreen->allowedDepths[i].depth == d) {
234	    depth = &pScreen->allowedDepths[i];
235	    break;
236	}
237    }
238    if (depth == NULL)
239	return NULL;
240
241    if (ResizeVisualArray(pScreen, count, depth) == FALSE)
242        return NULL;
243
244    /* Return a pointer to the first of the added visuals. */
245    return pScreen->visuals + pScreen->numVisuals - count;
246}
247
248static int
249findFirstSet(unsigned int v)
250{
251    int i;
252
253    for (i = 0; i < 32; i++)
254	if (v & (1 << i))
255	    return i;
256
257    return -1;
258}
259
260static void
261initGlxVisual(VisualPtr visual, __GLXconfig *config)
262{
263    int maxBits;
264    maxBits = max(config->redBits, max(config->greenBits, config->blueBits));
265
266    config->visualID = visual->vid;
267    visual->class = glxConvertToXVisualType(config->visualType);
268    visual->bitsPerRGBValue = maxBits;
269    visual->ColormapEntries = 1 << maxBits;
270    visual->nplanes = config->redBits + config->greenBits + config->blueBits;
271
272    visual->redMask = config->redMask;
273    visual->greenMask = config->greenMask;
274    visual->blueMask = config->blueMask;
275    visual->offsetRed = findFirstSet(config->redMask);
276    visual->offsetGreen = findFirstSet(config->greenMask);
277    visual->offsetBlue = findFirstSet(config->blueMask);
278}
279
280static __GLXconfig *
281pickFBConfig(__GLXscreen *pGlxScreen, VisualPtr visual)
282{
283    __GLXconfig *best = NULL, *config;
284    int best_score = 0;
285
286    for (config = pGlxScreen->fbconfigs; config != NULL; config = config->next) {
287	int score = 0;
288
289	if (config->redMask != visual->redMask ||
290	    config->greenMask != visual->greenMask ||
291	    config->blueMask != visual->blueMask)
292	    continue;
293	if (config->visualRating != GLX_NONE)
294	    continue;
295	if (glxConvertToXVisualType(config->visualType) != visual->class)
296	    continue;
297	/* If it's the 32-bit RGBA visual, demand a 32-bit fbconfig. */
298	if (visual->nplanes == 32 && config->rgbBits != 32)
299	    continue;
300	/* Can't use the same FBconfig for multiple X visuals.  I think. */
301	if (config->visualID != 0)
302	    continue;
303
304	if (config->doubleBufferMode > 0)
305	    score += 8;
306	if (config->depthBits > 0)
307	    score += 4;
308	if (config->stencilBits > 0)
309	    score += 2;
310	if (config->alphaBits > 0)
311	    score++;
312
313	if (score > best_score) {
314	    best = config;
315	    best_score = score;
316	}
317    }
318
319    return best;
320}
321
322void __glXScreenInit(__GLXscreen *pGlxScreen, ScreenPtr pScreen)
323{
324    __GLXconfig *m;
325    __GLXconfig *config;
326    int i;
327
328    if (!dixRegisterPrivateKey(&glxScreenPrivateKeyRec, PRIVATE_SCREEN, 0))
329	return;
330
331    pGlxScreen->pScreen       = pScreen;
332    pGlxScreen->GLextensions  = strdup(GLServerExtensions);
333    pGlxScreen->GLXvendor     = strdup(GLXServerVendorName);
334    pGlxScreen->GLXextensions = strdup(GLXServerExtensions);
335
336    /* All GLX providers must support all of the functionality required for at
337     * least GLX 1.2.  If the provider supports a higher version, the GLXminor
338     * version can be changed in the provider's screen-probe routine.  For
339     * most providers, the screen-probe routine is the caller of this
340     * function.
341     */
342    pGlxScreen->GLXmajor      = 1;
343    pGlxScreen->GLXminor      = 2;
344
345    pGlxScreen->CloseScreen = pScreen->CloseScreen;
346    pScreen->CloseScreen = glxCloseScreen;
347
348    i = 0;
349    for (m = pGlxScreen->fbconfigs; m != NULL; m = m->next) {
350	m->fbconfigID = FakeClientID(0);
351	m->visualID = 0;
352	i++;
353    }
354    pGlxScreen->numFBConfigs = i;
355
356    pGlxScreen->visuals =
357	calloc(pGlxScreen->numFBConfigs, sizeof (__GLXconfig *));
358
359    /* First, try to choose featureful FBconfigs for the existing X visuals.
360     * Note that if multiple X visuals end up with the same FBconfig being
361     * chosen, the later X visuals don't get GLX visuals (because we want to
362     * prioritize the root visual being GLX).
363     */
364    for (i = 0; i < pScreen->numVisuals; i++) {
365	VisualPtr visual = &pScreen->visuals[i];
366
367	config = pickFBConfig(pGlxScreen, visual);
368	if (config) {
369	    pGlxScreen->visuals[pGlxScreen->numVisuals++] = config;
370	    config->visualID = visual->vid;
371	}
372    }
373
374    /* Then, add new visuals corresponding to all FBconfigs that didn't have
375     * an existing, appropriate visual.
376     */
377    for (config = pGlxScreen->fbconfigs; config != NULL; config = config->next) {
378	int depth;
379
380	VisualPtr visual;
381
382	if (config->visualID != 0)
383	    continue;
384
385	/* Only count RGB bits and not alpha, as we're not trying to create
386	 * visuals for compositing (that's what the 32-bit composite visual
387	 * set up above is for.
388	 */
389	depth = config->redBits + config->greenBits + config->blueBits;
390
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	pGlxScreen->visuals[pGlxScreen->numVisuals++] = config;
414	initGlxVisual(visual, config);
415    }
416
417    dixSetPrivate(&pScreen->devPrivates, glxScreenPrivateKey, pGlxScreen);
418}
419
420void __glXScreenDestroy(__GLXscreen *screen)
421{
422    free(screen->GLXvendor);
423    free(screen->GLXextensions);
424    free(screen->GLextensions);
425}
426