initial commit
[profile/ivi/xorg-x11-server.git] / glx / glxscreens.c
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
47 static DevPrivateKeyRec glxScreenPrivateKeyRec;
48 #define glxScreenPrivateKey (&glxScreenPrivateKeyRec)
49
50 const char GLServerVersion[] = "1.4";
51 static 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 */
165 static char GLXServerVendorName[] = "SGI";
166 unsigned glxMajorVersion = SERVER_GLX_MAJOR_VERSION;
167 unsigned glxMinorVersion = SERVER_GLX_MINOR_VERSION;
168 static 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                         "GLX_SGIX_hyperpipe "
179                         "GLX_SGIX_swap_barrier "
180 #endif
181                         "GLX_SGIX_fbconfig "
182                         "GLX_SGIX_pbuffer "
183                         "GLX_MESA_copy_sub_buffer "
184                         "GLX_INTEL_swap_event"
185                         ;
186
187 /*
188  * If your DDX driver wants to register support for swap barriers or hyperpipe
189  * topology, it should call __glXHyperpipeInit() or __glXSwapBarrierInit()
190  * with a dispatch table of functions to handle the requests.   In the XFree86
191  * DDX, for example, you would call these near the bottom of the driver's
192  * ScreenInit method, after DRI has been initialized.
193  *
194  * This should be replaced with a better method when we teach the server how
195  * to load DRI drivers.
196  */
197
198 void __glXHyperpipeInit(int screen, __GLXHyperpipeExtensionFuncs *funcs)
199 {
200     __GLXscreen *pGlxScreen = glxGetScreen(screenInfo.screens[screen]);
201
202     pGlxScreen->hyperpipeFuncs = funcs;
203 }
204
205 void __glXSwapBarrierInit(int screen, __GLXSwapBarrierExtensionFuncs *funcs)
206 {
207     __GLXscreen *pGlxScreen = glxGetScreen(screenInfo.screens[screen]);
208
209     pGlxScreen->swapBarrierFuncs = funcs;
210 }
211
212 static Bool
213 glxCloseScreen (int index, ScreenPtr pScreen)
214 {
215     __GLXscreen *pGlxScreen = glxGetScreen(pScreen);
216
217     pScreen->CloseScreen = pGlxScreen->CloseScreen;
218
219     pGlxScreen->destroy(pGlxScreen);
220
221     return pScreen->CloseScreen(index, pScreen);
222 }
223
224 __GLXscreen *
225 glxGetScreen(ScreenPtr pScreen)
226 {
227     return dixLookupPrivate(&pScreen->devPrivates, glxScreenPrivateKey);
228 }
229
230 _X_EXPORT void GlxSetVisualConfigs(int nconfigs,
231                          void *configs, void **privates)
232 {
233     /* We keep this stub around for the DDX drivers that still
234      * call it. */
235 }
236
237 GLint glxConvertToXVisualType(int visualType)
238 {
239     static const int x_visual_types[] = {
240         TrueColor,   DirectColor,
241         PseudoColor, StaticColor,
242         GrayScale,   StaticGray
243     };
244
245     return ( (unsigned) (visualType - GLX_TRUE_COLOR) < 6 )
246         ? x_visual_types[ visualType - GLX_TRUE_COLOR ] : -1;
247 }
248
249 /* This code inspired by composite/compinit.c.  We could move this to
250  * mi/ and share it with composite.*/
251
252 static VisualPtr
253 AddScreenVisuals(ScreenPtr pScreen, int count, int d)
254 {
255     int          i;
256     DepthPtr     depth;
257
258     depth = NULL;
259     for (i = 0; i < pScreen->numDepths; i++) {
260         if (pScreen->allowedDepths[i].depth == d) {
261             depth = &pScreen->allowedDepths[i];
262             break;
263         }
264     }
265     if (depth == NULL)
266         return NULL;
267
268     if (ResizeVisualArray(pScreen, count, depth) == FALSE)
269         return NULL;
270
271     /* Return a pointer to the first of the added visuals. */ 
272     return pScreen->visuals + pScreen->numVisuals - count;
273 }
274
275 static int
276 findFirstSet(unsigned int v)
277 {
278     int i;
279
280     for (i = 0; i < 32; i++)
281         if (v & (1 << i))
282             return i;
283
284     return -1;
285 }
286
287 static void
288 initGlxVisual(VisualPtr visual, __GLXconfig *config)
289 {
290     int maxBits;
291     maxBits = max(config->redBits, max(config->greenBits, config->blueBits));
292
293     config->visualID = visual->vid;
294     visual->class = glxConvertToXVisualType(config->visualType);
295     visual->bitsPerRGBValue = maxBits;
296     visual->ColormapEntries = 1 << maxBits;
297     visual->nplanes = config->redBits + config->greenBits + config->blueBits;
298
299     visual->redMask = config->redMask;
300     visual->greenMask = config->greenMask;
301     visual->blueMask = config->blueMask;
302     visual->offsetRed = findFirstSet(config->redMask);
303     visual->offsetGreen = findFirstSet(config->greenMask);
304     visual->offsetBlue = findFirstSet(config->blueMask);
305 }
306
307 static __GLXconfig *
308 pickFBConfig(__GLXscreen *pGlxScreen, VisualPtr visual)
309 {
310     __GLXconfig *best = NULL, *config;
311     int best_score = 0;
312
313     for (config = pGlxScreen->fbconfigs; config != NULL; config = config->next) {
314         int score = 0;
315
316         if (config->redMask != visual->redMask ||
317             config->greenMask != visual->greenMask ||
318             config->blueMask != visual->blueMask)
319             continue;
320         if (config->visualRating != GLX_NONE)
321             continue;
322         if (glxConvertToXVisualType(config->visualType) != visual->class)
323             continue;
324         /* If it's the 32-bit RGBA visual, demand a 32-bit fbconfig. */
325         if (visual->nplanes == 32 && config->rgbBits != 32)
326             continue;
327         /* Can't use the same FBconfig for multiple X visuals.  I think. */
328         if (config->visualID != 0)
329             continue;
330
331         if (config->doubleBufferMode > 0)
332             score += 8;
333         if (config->depthBits > 0)
334             score += 4;
335         if (config->stencilBits > 0)
336             score += 2;
337         if (config->alphaBits > 0)
338             score++;
339
340         if (score > best_score) {
341             best = config;
342             best_score = score;
343         }
344     }
345
346     return best;
347 }
348
349 void __glXScreenInit(__GLXscreen *pGlxScreen, ScreenPtr pScreen)
350 {
351     __GLXconfig *m;
352     __GLXconfig *config;
353     int i;
354
355     if (!dixRegisterPrivateKey(&glxScreenPrivateKeyRec, PRIVATE_SCREEN, 0))
356         return;
357
358     pGlxScreen->pScreen       = pScreen;
359     pGlxScreen->GLextensions  = strdup(GLServerExtensions);
360     pGlxScreen->GLXvendor     = strdup(GLXServerVendorName);
361     pGlxScreen->GLXextensions = strdup(GLXServerExtensions);
362
363     /* All GLX providers must support all of the functionality required for at
364      * least GLX 1.2.  If the provider supports a higher version, the GLXminor
365      * version can be changed in the provider's screen-probe routine.  For
366      * most providers, the screen-probe routine is the caller of this
367      * function.
368      */
369     pGlxScreen->GLXmajor      = 1;
370     pGlxScreen->GLXminor      = 2;
371
372     pGlxScreen->CloseScreen = pScreen->CloseScreen;
373     pScreen->CloseScreen = glxCloseScreen;
374
375     i = 0;
376     for (m = pGlxScreen->fbconfigs; m != NULL; m = m->next) {
377         m->fbconfigID = FakeClientID(0);
378         m->visualID = 0;
379         i++;
380     }
381     pGlxScreen->numFBConfigs = i;
382
383     pGlxScreen->visuals =
384         calloc(pGlxScreen->numFBConfigs, sizeof (__GLXconfig *));
385
386     /* First, try to choose featureful FBconfigs for the existing X visuals.
387      * Note that if multiple X visuals end up with the same FBconfig being
388      * chosen, the later X visuals don't get GLX visuals (because we want to
389      * prioritize the root visual being GLX).
390      */
391     for (i = 0; i < pScreen->numVisuals; i++) {
392         VisualPtr visual = &pScreen->visuals[i];
393
394         config = pickFBConfig(pGlxScreen, visual);
395         if (config) {
396             pGlxScreen->visuals[pGlxScreen->numVisuals++] = config;
397             config->visualID = visual->vid;
398         }
399     }
400
401     /* Then, add new visuals corresponding to all FBconfigs that didn't have
402      * an existing, appropriate visual.
403      */
404     for (config = pGlxScreen->fbconfigs; config != NULL; config = config->next) {
405         int depth;
406
407         VisualPtr visual;
408
409         if (config->visualID != 0)
410             continue;
411
412         /* Only count RGB bits and not alpha, as we're not trying to create
413          * visuals for compositing (that's what the 32-bit composite visual
414          * set up above is for.
415          */
416         depth = config->redBits + config->greenBits + config->blueBits;
417
418         /* Make sure that our FBconfig's depth can actually be displayed
419          * (corresponds to an existing visual).
420          */
421         for (i = 0; i < pScreen->numVisuals; i++) {
422             if (depth == pScreen->visuals[i].nplanes)
423                 break;
424         }
425         if (i == pScreen->numVisuals)
426             continue;
427
428         /* Create a new X visual for our FBconfig. */
429         visual = AddScreenVisuals(pScreen, 1, depth);
430         if (visual == NULL)
431             continue;
432
433         pGlxScreen->visuals[pGlxScreen->numVisuals++] = config;
434         initGlxVisual(visual, config);
435     }
436
437     dixSetPrivate(&pScreen->devPrivates, glxScreenPrivateKey, pGlxScreen);
438 }
439
440 void __glXScreenDestroy(__GLXscreen *screen)
441 {
442     free(screen->GLXvendor);
443     free(screen->GLXextensions);
444     free(screen->GLextensions);
445 }