glxscreens.c revision 4642e01f
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
46static int glxScreenPrivateKeyIndex;
47static DevPrivateKey glxScreenPrivateKey = &glxScreenPrivateKeyIndex;
48
49const char GLServerVersion[] = "1.4";
50static const char GLServerExtensions[] =
51			"GL_ARB_depth_texture "
52			"GL_ARB_draw_buffers "
53			"GL_ARB_fragment_program "
54			"GL_ARB_fragment_program_shadow "
55			"GL_ARB_imaging "
56			"GL_ARB_multisample "
57			"GL_ARB_multitexture "
58			"GL_ARB_occlusion_query "
59			"GL_ARB_point_parameters "
60			"GL_ARB_point_sprite "
61			"GL_ARB_shadow "
62			"GL_ARB_shadow_ambient "
63			"GL_ARB_texture_border_clamp "
64			"GL_ARB_texture_compression "
65			"GL_ARB_texture_cube_map "
66			"GL_ARB_texture_env_add "
67			"GL_ARB_texture_env_combine "
68			"GL_ARB_texture_env_crossbar "
69			"GL_ARB_texture_env_dot3 "
70			"GL_ARB_texture_mirrored_repeat "
71			"GL_ARB_texture_non_power_of_two "
72			"GL_ARB_transpose_matrix "
73			"GL_ARB_vertex_program "
74			"GL_ARB_window_pos "
75			"GL_EXT_abgr "
76			"GL_EXT_bgra "
77 			"GL_EXT_blend_color "
78			"GL_EXT_blend_equation_separate "
79			"GL_EXT_blend_func_separate "
80			"GL_EXT_blend_logic_op "
81 			"GL_EXT_blend_minmax "
82 			"GL_EXT_blend_subtract "
83			"GL_EXT_clip_volume_hint "
84			"GL_EXT_copy_texture "
85			"GL_EXT_draw_range_elements "
86			"GL_EXT_fog_coord "
87			"GL_EXT_framebuffer_object "
88			"GL_EXT_multi_draw_arrays "
89			"GL_EXT_packed_pixels "
90			"GL_EXT_paletted_texture "
91			"GL_EXT_point_parameters "
92			"GL_EXT_polygon_offset "
93			"GL_EXT_rescale_normal "
94			"GL_EXT_secondary_color "
95			"GL_EXT_separate_specular_color "
96			"GL_EXT_shadow_funcs "
97			"GL_EXT_shared_texture_palette "
98 			"GL_EXT_stencil_two_side "
99			"GL_EXT_stencil_wrap "
100			"GL_EXT_subtexture "
101			"GL_EXT_texture "
102			"GL_EXT_texture3D "
103			"GL_EXT_texture_compression_dxt1 "
104			"GL_EXT_texture_compression_s3tc "
105			"GL_EXT_texture_edge_clamp "
106 			"GL_EXT_texture_env_add "
107 			"GL_EXT_texture_env_combine "
108 			"GL_EXT_texture_env_dot3 "
109 			"GL_EXT_texture_filter_anisotropic "
110			"GL_EXT_texture_lod "
111 			"GL_EXT_texture_lod_bias "
112 			"GL_EXT_texture_mirror_clamp "
113			"GL_EXT_texture_object "
114			"GL_EXT_texture_rectangle "
115			"GL_EXT_vertex_array "
116			"GL_3DFX_texture_compression_FXT1 "
117			"GL_APPLE_packed_pixels "
118			"GL_ATI_draw_buffers "
119			"GL_ATI_texture_env_combine3 "
120			"GL_ATI_texture_mirror_once "
121 			"GL_HP_occlusion_test "
122			"GL_IBM_texture_mirrored_repeat "
123			"GL_INGR_blend_func_separate "
124			"GL_MESA_pack_invert "
125			"GL_MESA_ycbcr_texture "
126			"GL_NV_blend_square "
127			"GL_NV_depth_clamp "
128			"GL_NV_fog_distance "
129			"GL_NV_fragment_program "
130			"GL_NV_fragment_program_option "
131			"GL_NV_fragment_program2 "
132			"GL_NV_light_max_exponent "
133			"GL_NV_multisample_filter_hint "
134			"GL_NV_point_sprite "
135			"GL_NV_texgen_reflection "
136			"GL_NV_texture_compression_vtc "
137			"GL_NV_texture_env_combine4 "
138			"GL_NV_texture_expand_normal "
139			"GL_NV_texture_rectangle "
140			"GL_NV_vertex_program "
141			"GL_NV_vertex_program1_1 "
142			"GL_NV_vertex_program2 "
143			"GL_NV_vertex_program2_option "
144			"GL_NV_vertex_program3 "
145			"GL_OES_compressed_paletted_texture "
146			"GL_SGI_color_matrix "
147			"GL_SGI_color_table "
148			"GL_SGIS_generate_mipmap "
149			"GL_SGIS_multisample "
150			"GL_SGIS_point_parameters "
151			"GL_SGIS_texture_border_clamp "
152			"GL_SGIS_texture_edge_clamp "
153			"GL_SGIS_texture_lod "
154			"GL_SGIX_depth_texture "
155			"GL_SGIX_shadow "
156			"GL_SGIX_shadow_ambient "
157			"GL_SUN_slice_accum "
158			;
159
160/*
161** We have made the simplifying assuption that the same extensions are
162** supported across all screens in a multi-screen system.
163*/
164static char GLXServerVendorName[] = "SGI";
165static char GLXServerVersion[] = "1.2";
166static char GLXServerExtensions[] =
167			"GLX_ARB_multisample "
168			"GLX_EXT_visual_info "
169			"GLX_EXT_visual_rating "
170			"GLX_EXT_import_context "
171                        "GLX_EXT_texture_from_pixmap "
172			"GLX_OML_swap_method "
173			"GLX_SGI_make_current_read "
174#ifndef __APPLE__
175			"GLX_SGIS_multisample "
176                        "GLX_SGIX_hyperpipe "
177                        "GLX_SGIX_swap_barrier "
178#endif
179			"GLX_SGIX_fbconfig "
180			"GLX_MESA_copy_sub_buffer "
181			;
182
183/*
184 * If your DDX driver wants to register support for swap barriers or hyperpipe
185 * topology, it should call __glXHyperpipeInit() or __glXSwapBarrierInit()
186 * with a dispatch table of functions to handle the requests.   In the XFree86
187 * DDX, for example, you would call these near the bottom of the driver's
188 * ScreenInit method, after DRI has been initialized.
189 *
190 * This should be replaced with a better method when we teach the server how
191 * to load DRI drivers.
192 */
193
194void __glXHyperpipeInit(int screen, __GLXHyperpipeExtensionFuncs *funcs)
195{
196    __GLXscreen *pGlxScreen = glxGetScreen(screenInfo.screens[screen]);
197
198    pGlxScreen->hyperpipeFuncs = funcs;
199}
200
201void __glXSwapBarrierInit(int screen, __GLXSwapBarrierExtensionFuncs *funcs)
202{
203    __GLXscreen *pGlxScreen = glxGetScreen(screenInfo.screens[screen]);
204
205    pGlxScreen->swapBarrierFuncs = funcs;
206}
207
208static Bool
209glxCloseScreen (int index, ScreenPtr pScreen)
210{
211    __GLXscreen *pGlxScreen = glxGetScreen(pScreen);
212
213    pScreen->CloseScreen = pGlxScreen->CloseScreen;
214
215    pGlxScreen->destroy(pGlxScreen);
216
217    return pScreen->CloseScreen(index, pScreen);
218}
219
220__GLXscreen *
221glxGetScreen(ScreenPtr pScreen)
222{
223    return dixLookupPrivate(&pScreen->devPrivates, glxScreenPrivateKey);
224}
225
226void GlxSetVisualConfigs(int nconfigs,
227                         __GLXvisualConfig *configs, void **privates)
228{
229    /* We keep this stub around for the DDX drivers that still
230     * call it. */
231}
232
233GLint glxConvertToXVisualType(int visualType)
234{
235    static const int x_visual_types[] = {
236	TrueColor,   DirectColor,
237	PseudoColor, StaticColor,
238	GrayScale,   StaticGray
239    };
240
241    return ( (unsigned) (visualType - GLX_TRUE_COLOR) < 6 )
242	? x_visual_types[ visualType - GLX_TRUE_COLOR ] : -1;
243}
244
245/* This code inspired by composite/compinit.c.  We could move this to
246 * mi/ and share it with composite.*/
247
248static VisualPtr
249AddScreenVisuals(ScreenPtr pScreen, int count, int d)
250{
251    XID		*installedCmaps, *vids, vid;
252    int		 numInstalledCmaps, numVisuals, i, j;
253    VisualPtr	 visuals;
254    ColormapPtr	 installedCmap;
255    DepthPtr	 depth;
256
257    depth = NULL;
258    for (i = 0; i < pScreen->numDepths; i++) {
259	if (pScreen->allowedDepths[i].depth == d) {
260	    depth = &pScreen->allowedDepths[i];
261	    break;
262	}
263    }
264    if (depth == NULL)
265	return NULL;
266
267    /* Find the installed colormaps */
268    installedCmaps = xalloc (pScreen->maxInstalledCmaps * sizeof (XID));
269    if (!installedCmaps)
270	return NULL;
271
272    numInstalledCmaps = pScreen->ListInstalledColormaps(pScreen, installedCmaps);
273
274    /* realloc the visual array to fit the new one in place */
275    numVisuals = pScreen->numVisuals;
276    visuals = xrealloc(pScreen->visuals, (numVisuals + count) * sizeof(VisualRec));
277    if (!visuals) {
278	xfree(installedCmaps);
279	return NULL;
280    }
281
282    vids = xrealloc(depth->vids, (depth->numVids + count) * sizeof(XID));
283    if (vids == NULL) {
284	xfree(installedCmaps);
285	xfree(visuals);
286	return NULL;
287    }
288
289    /*
290     * Fix up any existing installed colormaps -- we'll assume that
291     * the only ones created so far have been installed.  If this
292     * isn't true, we'll have to walk the resource database looking
293     * for all colormaps.
294     */
295    for (i = 0; i < numInstalledCmaps; i++) {
296	installedCmap = LookupIDByType (installedCmaps[i], RT_COLORMAP);
297	if (!installedCmap)
298	    continue;
299	j = installedCmap->pVisual - pScreen->visuals;
300	installedCmap->pVisual = &visuals[j];
301    }
302
303    xfree(installedCmaps);
304
305    for (i = 0; i < count; i++) {
306	vid = FakeClientID(0);
307	visuals[pScreen->numVisuals + i].vid = vid;
308	vids[depth->numVids + i] = vid;
309    }
310
311    pScreen->visuals = visuals;
312    pScreen->numVisuals += count;
313    depth->vids = vids;
314    depth->numVids += count;
315
316    /* Return a pointer to the first of the added visuals. */
317    return pScreen->visuals + pScreen->numVisuals - count;
318}
319
320static int
321findFirstSet(unsigned int v)
322{
323    int i;
324
325    for (i = 0; i < 32; i++)
326	if (v & (1 << i))
327	    return i;
328
329    return -1;
330}
331
332static void
333initGlxVisual(VisualPtr visual, __GLXconfig *config)
334{
335    int maxBits;
336    maxBits = max(config->redBits, max(config->greenBits, config->blueBits));
337
338    config->visualID = visual->vid;
339    visual->class = glxConvertToXVisualType(config->visualType);
340    visual->bitsPerRGBValue = maxBits;
341    visual->ColormapEntries = 1 << maxBits;
342    visual->nplanes = config->redBits + config->greenBits + config->blueBits;
343
344    visual->redMask = config->redMask;
345    visual->greenMask = config->greenMask;
346    visual->blueMask = config->blueMask;
347    visual->offsetRed = findFirstSet(config->redMask);
348    visual->offsetGreen = findFirstSet(config->greenMask);
349    visual->offsetBlue = findFirstSet(config->blueMask);
350}
351
352static __GLXconfig *
353pickFBConfig(__GLXscreen *pGlxScreen, VisualPtr visual)
354{
355    __GLXconfig *best = NULL, *config;
356    int best_score = 0;
357
358    for (config = pGlxScreen->fbconfigs; config != NULL; config = config->next) {
359	int score = 0;
360
361	if (config->redMask != visual->redMask ||
362	    config->greenMask != visual->greenMask ||
363	    config->blueMask != visual->blueMask)
364	    continue;
365	if (config->visualRating != GLX_NONE)
366	    continue;
367	if (glxConvertToXVisualType(config->visualType) != visual->class)
368	    continue;
369	/* If it's the 32-bit RGBA visual, demand a 32-bit fbconfig. */
370	if (visual->nplanes == 32 && config->rgbBits != 32)
371	    continue;
372	/* Can't use the same FBconfig for multiple X visuals.  I think. */
373	if (config->visualID != 0)
374	    continue;
375
376	if (config->doubleBufferMode > 0)
377	    score += 8;
378	if (config->depthBits > 0)
379	    score += 4;
380	if (config->stencilBits > 0)
381	    score += 2;
382	if (config->alphaBits > 0)
383	    score++;
384
385	if (score > best_score) {
386	    best = config;
387	    best_score = score;
388	}
389    }
390
391    return best;
392}
393
394void __glXScreenInit(__GLXscreen *pGlxScreen, ScreenPtr pScreen)
395{
396    __GLXconfig *m;
397    __GLXconfig *config;
398    int i;
399
400    pGlxScreen->pScreen       = pScreen;
401    pGlxScreen->GLextensions  = xstrdup(GLServerExtensions);
402    pGlxScreen->GLXvendor     = xstrdup(GLXServerVendorName);
403    pGlxScreen->GLXversion    = xstrdup(GLXServerVersion);
404    pGlxScreen->GLXextensions = xstrdup(GLXServerExtensions);
405
406    pGlxScreen->CloseScreen = pScreen->CloseScreen;
407    pScreen->CloseScreen = glxCloseScreen;
408
409    i = 0;
410    for (m = pGlxScreen->fbconfigs; m != NULL; m = m->next) {
411	m->fbconfigID = FakeClientID(0);
412	m->visualID = 0;
413	i++;
414    }
415    pGlxScreen->numFBConfigs = i;
416
417    pGlxScreen->visuals =
418	xcalloc(pGlxScreen->numFBConfigs, sizeof (__GLXconfig *));
419
420    /* First, try to choose featureful FBconfigs for the existing X visuals.
421     * Note that if multiple X visuals end up with the same FBconfig being
422     * chosen, the later X visuals don't get GLX visuals (because we want to
423     * prioritize the root visual being GLX).
424     */
425    for (i = 0; i < pScreen->numVisuals; i++) {
426	VisualPtr visual = &pScreen->visuals[i];
427
428	config = pickFBConfig(pGlxScreen, visual);
429	if (config) {
430	    pGlxScreen->visuals[pGlxScreen->numVisuals++] = config;
431	    config->visualID = visual->vid;
432	}
433    }
434
435    /* Then, add new visuals corresponding to all FBconfigs that didn't have
436     * an existing, appropriate visual.
437     */
438    for (config = pGlxScreen->fbconfigs; config != NULL; config = config->next) {
439	int depth;
440
441	VisualPtr visual;
442
443	if (config->visualID != 0)
444	    continue;
445
446	/* Only count RGB bits and not alpha, as we're not trying to create
447	 * visuals for compositing (that's what the 32-bit composite visual
448	 * set up above is for.
449	 */
450	depth = config->redBits + config->greenBits + config->blueBits;
451
452	/* Make sure that our FBconfig's depth can actually be displayed
453	 * (corresponds to an existing visual).
454	 */
455	for (i = 0; i < pScreen->numVisuals; i++) {
456	    if (depth == pScreen->visuals[i].nplanes)
457		break;
458	}
459	if (i == pScreen->numVisuals)
460	    continue;
461
462	/* Create a new X visual for our FBconfig. */
463	visual = AddScreenVisuals(pScreen, 1, depth);
464	if (visual == NULL)
465	    continue;
466
467	pGlxScreen->visuals[pGlxScreen->numVisuals++] = config;
468	initGlxVisual(visual, config);
469    }
470
471    dixSetPrivate(&pScreen->devPrivates, glxScreenPrivateKey, pGlxScreen);
472}
473
474void __glXScreenDestroy(__GLXscreen *screen)
475{
476    xfree(screen->GLXvendor);
477    xfree(screen->GLXversion);
478    xfree(screen->GLXextensions);
479    xfree(screen->GLextensions);
480}
481