1 /**************************************************************************
2  *
3  * Copyright 2009, VMware, Inc.
4  * All Rights Reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the
8  * "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sub license, and/or sell copies of the Software, and to
11  * permit persons to whom the Software is furnished to do so, subject to
12  * the following conditions:
13  *
14  * The above copyright notice and this permission notice (including the
15  * next paragraph) shall be included in all copies or substantial portions
16  * of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21  * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25  *
26  **************************************************************************/
27 /*
28  * Author: Keith Whitwell <keithw@vmware.com>
29  * Author: Jakob Bornecrantz <wallbraker@gmail.com>
30  */
31 
32 #include "utils.h"
33 #include "xmlpool.h"
34 
35 #include "dri_screen.h"
36 
37 #include "util/u_inlines.h"
38 #include "pipe/p_screen.h"
39 #include "pipe/p_format.h"
40 #include "state_tracker/st_gl_api.h" /* for st_gl_api_create */
41 
42 #include "util/u_debug.h"
43 
44 #define MSAA_VISUAL_MAX_SAMPLES 8
45 
46 #undef false
47 
48 PUBLIC const char __driConfigOptions[] =
49    DRI_CONF_BEGIN
50       DRI_CONF_SECTION_PERFORMANCE
51          DRI_CONF_FTHROTTLE_MODE(DRI_CONF_FTHROTTLE_IRQS)
52          DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_0)
53       DRI_CONF_SECTION_END
54 
55       DRI_CONF_SECTION_QUALITY
56 /*       DRI_CONF_FORCE_S3TC_ENABLE(false) */
57          DRI_CONF_ALLOW_LARGE_TEXTURES(1)
58          DRI_CONF_PP_CELSHADE(0)
59          DRI_CONF_PP_NORED(0)
60          DRI_CONF_PP_NOGREEN(0)
61          DRI_CONF_PP_NOBLUE(0)
62          DRI_CONF_PP_JIMENEZMLAA(0, 0, 32)
63          DRI_CONF_PP_JIMENEZMLAA_COLOR(0, 0, 32)
64       DRI_CONF_SECTION_END
65 
66       DRI_CONF_SECTION_DEBUG
67          DRI_CONF_FORCE_GLSL_EXTENSIONS_WARN(false)
68       DRI_CONF_SECTION_END
69 
70    DRI_CONF_END;
71 
72 #define false 0
73 
74 static const uint __driNConfigOptions = 10;
75 
76 static const __DRIconfig **
dri_fill_in_modes(struct dri_screen * screen,unsigned pixel_bits)77 dri_fill_in_modes(struct dri_screen *screen,
78 		  unsigned pixel_bits)
79 {
80    __DRIconfig **configs = NULL;
81    __DRIconfig **configs_r5g6b5 = NULL;
82    __DRIconfig **configs_a8r8g8b8 = NULL;
83    __DRIconfig **configs_x8r8g8b8 = NULL;
84    uint8_t depth_bits_array[5];
85    uint8_t stencil_bits_array[5];
86    uint8_t msaa_samples_array[MSAA_VISUAL_MAX_SAMPLES];
87    unsigned depth_buffer_factor;
88    unsigned back_buffer_factor;
89    unsigned msaa_samples_factor, msaa_samples_max;
90    unsigned i;
91    struct pipe_screen *p_screen = screen->base.screen;
92    boolean pf_r5g6b5, pf_a8r8g8b8, pf_x8r8g8b8;
93    boolean pf_z16, pf_x8z24, pf_z24x8, pf_s8z24, pf_z24s8, pf_z32;
94 
95    static const GLenum back_buffer_modes[] = {
96       GLX_NONE, GLX_SWAP_UNDEFINED_OML, GLX_SWAP_COPY_OML
97    };
98 
99    depth_bits_array[0] = 0;
100    stencil_bits_array[0] = 0;
101    depth_buffer_factor = 1;
102 
103    msaa_samples_max = (screen->st_api->feature_mask & ST_API_FEATURE_MS_VISUALS)
104       ? MSAA_VISUAL_MAX_SAMPLES : 1;
105 
106    pf_x8z24 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_Z24X8_UNORM,
107 					    PIPE_TEXTURE_2D, 0,
108                                             PIPE_BIND_DEPTH_STENCIL);
109    pf_z24x8 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_X8Z24_UNORM,
110 					    PIPE_TEXTURE_2D, 0,
111                                             PIPE_BIND_DEPTH_STENCIL);
112    pf_s8z24 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_Z24_UNORM_S8_UINT,
113 					    PIPE_TEXTURE_2D, 0,
114                                             PIPE_BIND_DEPTH_STENCIL);
115    pf_z24s8 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_S8_UINT_Z24_UNORM,
116 					    PIPE_TEXTURE_2D, 0,
117                                             PIPE_BIND_DEPTH_STENCIL);
118    pf_a8r8g8b8 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_B8G8R8A8_UNORM,
119 					       PIPE_TEXTURE_2D, 0,
120                                                PIPE_BIND_RENDER_TARGET);
121    pf_x8r8g8b8 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_B8G8R8X8_UNORM,
122 					       PIPE_TEXTURE_2D, 0,
123                                                PIPE_BIND_RENDER_TARGET);
124    pf_r5g6b5 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_B5G6R5_UNORM,
125 					     PIPE_TEXTURE_2D, 0,
126                                              PIPE_BIND_RENDER_TARGET);
127 
128    /* We can only get a 16 or 32 bit depth buffer with getBuffersWithFormat */
129    if (dri_with_format(screen->sPriv)) {
130       pf_z16 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_Z16_UNORM,
131                                              PIPE_TEXTURE_2D, 0,
132                                              PIPE_BIND_DEPTH_STENCIL);
133       pf_z32 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_Z32_UNORM,
134                                              PIPE_TEXTURE_2D, 0,
135                                              PIPE_BIND_DEPTH_STENCIL);
136    } else {
137       pf_z16 = FALSE;
138       pf_z32 = FALSE;
139    }
140 
141    if (pf_z16) {
142       depth_bits_array[depth_buffer_factor] = 16;
143       stencil_bits_array[depth_buffer_factor++] = 0;
144    }
145    if (pf_x8z24 || pf_z24x8) {
146       depth_bits_array[depth_buffer_factor] = 24;
147       stencil_bits_array[depth_buffer_factor++] = 0;
148       screen->d_depth_bits_last = pf_x8z24;
149    }
150    if (pf_s8z24 || pf_z24s8) {
151       depth_bits_array[depth_buffer_factor] = 24;
152       stencil_bits_array[depth_buffer_factor++] = 8;
153       screen->sd_depth_bits_last = pf_s8z24;
154    }
155    if (pf_z32) {
156       depth_bits_array[depth_buffer_factor] = 32;
157       stencil_bits_array[depth_buffer_factor++] = 0;
158    }
159 
160    msaa_samples_array[0] = 0;
161    back_buffer_factor = 3;
162 
163    /* Also test for color multisample support - just assume it'll work
164     * for all depth buffers.
165     */
166    if (pf_r5g6b5) {
167       msaa_samples_factor = 1;
168       for (i = 2; i <= msaa_samples_max; i++) {
169          if (p_screen->is_format_supported(p_screen, PIPE_FORMAT_B5G6R5_UNORM,
170 						   PIPE_TEXTURE_2D, i,
171                                                    PIPE_BIND_RENDER_TARGET)) {
172             msaa_samples_array[msaa_samples_factor] = i;
173             msaa_samples_factor++;
174          }
175       }
176 
177       configs_r5g6b5 = driCreateConfigs(GL_RGB, GL_UNSIGNED_SHORT_5_6_5,
178                                         depth_bits_array, stencil_bits_array,
179                                         depth_buffer_factor, back_buffer_modes,
180                                         back_buffer_factor,
181                                         msaa_samples_array, msaa_samples_factor,
182                                         GL_TRUE);
183    }
184 
185    if (pf_a8r8g8b8) {
186       msaa_samples_factor = 1;
187       for (i = 2; i <= msaa_samples_max; i++) {
188          if (p_screen->is_format_supported(p_screen, PIPE_FORMAT_B8G8R8A8_UNORM,
189 						   PIPE_TEXTURE_2D, i,
190                                                    PIPE_BIND_RENDER_TARGET)) {
191             msaa_samples_array[msaa_samples_factor] = i;
192             msaa_samples_factor++;
193          }
194       }
195 
196       configs_a8r8g8b8 = driCreateConfigs(GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
197                                           depth_bits_array,
198                                           stencil_bits_array,
199                                           depth_buffer_factor,
200                                           back_buffer_modes,
201                                           back_buffer_factor,
202                                           msaa_samples_array,
203                                           msaa_samples_factor,
204                                           GL_TRUE);
205    }
206 
207    if (pf_x8r8g8b8) {
208       msaa_samples_factor = 1;
209       for (i = 2; i <= msaa_samples_max; i++) {
210          if (p_screen->is_format_supported(p_screen, PIPE_FORMAT_B8G8R8X8_UNORM,
211 						   PIPE_TEXTURE_2D, i,
212                                                    PIPE_BIND_RENDER_TARGET)) {
213             msaa_samples_array[msaa_samples_factor] = i;
214             msaa_samples_factor++;
215          }
216       }
217 
218       configs_x8r8g8b8 = driCreateConfigs(GL_BGR, GL_UNSIGNED_INT_8_8_8_8_REV,
219                                           depth_bits_array,
220                                           stencil_bits_array,
221                                           depth_buffer_factor,
222                                           back_buffer_modes,
223                                           back_buffer_factor,
224                                           msaa_samples_array,
225                                           msaa_samples_factor,
226                                           GL_TRUE);
227    }
228 
229    if (pixel_bits == 16) {
230       configs = configs_r5g6b5;
231       configs = driConcatConfigs(configs, configs_a8r8g8b8);
232       configs = driConcatConfigs(configs, configs_x8r8g8b8);
233    } else {
234       configs = configs_a8r8g8b8;
235       configs = driConcatConfigs(configs, configs_x8r8g8b8);
236       configs = driConcatConfigs(configs, configs_r5g6b5);
237    }
238 
239    if (configs == NULL) {
240       debug_printf("%s: driCreateConfigs failed\n", __FUNCTION__);
241       return NULL;
242    }
243 
244    return (const __DRIconfig **)configs;
245 }
246 
247 /**
248  * Roughly the converse of dri_fill_in_modes.
249  */
250 void
dri_fill_st_visual(struct st_visual * stvis,struct dri_screen * screen,const struct gl_config * mode)251 dri_fill_st_visual(struct st_visual *stvis, struct dri_screen *screen,
252                    const struct gl_config *mode)
253 {
254    memset(stvis, 0, sizeof(*stvis));
255 
256    if (!mode)
257       return;
258 
259    stvis->samples = mode->samples;
260 
261    if (mode->redBits == 8) {
262       if (mode->alphaBits == 8)
263          stvis->color_format = PIPE_FORMAT_B8G8R8A8_UNORM;
264       else
265          stvis->color_format = PIPE_FORMAT_B8G8R8X8_UNORM;
266    } else {
267       stvis->color_format = PIPE_FORMAT_B5G6R5_UNORM;
268    }
269 
270    switch (mode->depthBits) {
271    default:
272    case 0:
273       stvis->depth_stencil_format = PIPE_FORMAT_NONE;
274       break;
275    case 16:
276       stvis->depth_stencil_format = PIPE_FORMAT_Z16_UNORM;
277       break;
278    case 24:
279       if (mode->stencilBits == 0) {
280 	 stvis->depth_stencil_format = (screen->d_depth_bits_last) ?
281                                           PIPE_FORMAT_Z24X8_UNORM:
282                                           PIPE_FORMAT_X8Z24_UNORM;
283       } else {
284 	 stvis->depth_stencil_format = (screen->sd_depth_bits_last) ?
285                                           PIPE_FORMAT_Z24_UNORM_S8_UINT:
286                                           PIPE_FORMAT_S8_UINT_Z24_UNORM;
287       }
288       break;
289    case 32:
290       stvis->depth_stencil_format = PIPE_FORMAT_Z32_UNORM;
291       break;
292    }
293 
294    stvis->accum_format = (mode->haveAccumBuffer) ?
295       PIPE_FORMAT_R16G16B16A16_SNORM : PIPE_FORMAT_NONE;
296 
297    stvis->buffer_mask |= ST_ATTACHMENT_FRONT_LEFT_MASK;
298    stvis->render_buffer = ST_ATTACHMENT_FRONT_LEFT;
299    if (mode->doubleBufferMode) {
300       stvis->buffer_mask |= ST_ATTACHMENT_BACK_LEFT_MASK;
301       stvis->render_buffer = ST_ATTACHMENT_BACK_LEFT;
302    }
303    if (mode->stereoMode) {
304       stvis->buffer_mask |= ST_ATTACHMENT_FRONT_RIGHT_MASK;
305       if (mode->doubleBufferMode)
306          stvis->buffer_mask |= ST_ATTACHMENT_BACK_RIGHT_MASK;
307    }
308 
309    if (mode->haveDepthBuffer || mode->haveStencilBuffer)
310       stvis->buffer_mask |= ST_ATTACHMENT_DEPTH_STENCIL_MASK;
311    /* let the state tracker allocate the accum buffer */
312 }
313 
314 static boolean
dri_get_egl_image(struct st_manager * smapi,void * egl_image,struct st_egl_image * stimg)315 dri_get_egl_image(struct st_manager *smapi,
316                   void *egl_image,
317                   struct st_egl_image *stimg)
318 {
319    struct dri_screen *screen = (struct dri_screen *)smapi;
320    __DRIimage *img = NULL;
321 
322    if (screen->lookup_egl_image) {
323       img = screen->lookup_egl_image(screen, egl_image);
324    }
325 
326    if (!img)
327       return FALSE;
328 
329    stimg->texture = NULL;
330    pipe_resource_reference(&stimg->texture, img->texture);
331    stimg->level = img->level;
332    stimg->layer = img->layer;
333 
334    return TRUE;
335 }
336 
337 static int
dri_get_param(struct st_manager * smapi,enum st_manager_param param)338 dri_get_param(struct st_manager *smapi,
339               enum st_manager_param param)
340 {
341    struct dri_screen *screen = (struct dri_screen *)smapi;
342 
343    switch(param) {
344    case ST_MANAGER_BROKEN_INVALIDATE:
345       return screen->broken_invalidate;
346    default:
347       return 0;
348    }
349 }
350 
351 static void
dri_destroy_option_cache(struct dri_screen * screen)352 dri_destroy_option_cache(struct dri_screen * screen)
353 {
354    int i;
355 
356    if (screen->optionCache.info) {
357       for (i = 0; i < (1 << screen->optionCache.tableSize); ++i) {
358          FREE(screen->optionCache.info[i].name);
359          FREE(screen->optionCache.info[i].ranges);
360       }
361       FREE(screen->optionCache.info);
362    }
363 
364    FREE(screen->optionCache.values);
365 }
366 
367 void
dri_destroy_screen_helper(struct dri_screen * screen)368 dri_destroy_screen_helper(struct dri_screen * screen)
369 {
370    if (screen->st_api && screen->st_api->destroy)
371       screen->st_api->destroy(screen->st_api);
372 
373    if (screen->base.screen)
374       screen->base.screen->destroy(screen->base.screen);
375 
376    dri_destroy_option_cache(screen);
377 }
378 
379 void
dri_destroy_screen(__DRIscreen * sPriv)380 dri_destroy_screen(__DRIscreen * sPriv)
381 {
382    struct dri_screen *screen = dri_screen(sPriv);
383 
384    dri_destroy_screen_helper(screen);
385 
386    FREE(screen);
387    sPriv->driverPrivate = NULL;
388    sPriv->extensions = NULL;
389 }
390 
391 const __DRIconfig **
dri_init_screen_helper(struct dri_screen * screen,struct pipe_screen * pscreen,unsigned pixel_bits)392 dri_init_screen_helper(struct dri_screen *screen,
393                        struct pipe_screen *pscreen,
394                        unsigned pixel_bits)
395 {
396    screen->base.screen = pscreen;
397    if (!screen->base.screen) {
398       debug_printf("%s: failed to create pipe_screen\n", __FUNCTION__);
399       return NULL;
400    }
401 
402    screen->base.get_egl_image = dri_get_egl_image;
403    screen->base.get_param = dri_get_param;
404 
405    screen->st_api = st_gl_api_create();
406    if (!screen->st_api)
407       return NULL;
408 
409    if(pscreen->get_param(pscreen, PIPE_CAP_NPOT_TEXTURES))
410       screen->target = PIPE_TEXTURE_2D;
411    else
412       screen->target = PIPE_TEXTURE_RECT;
413 
414    driParseOptionInfo(&screen->optionCache,
415                       __driConfigOptions, __driNConfigOptions);
416 
417    return dri_fill_in_modes(screen, pixel_bits);
418 }
419 
420 /* vim: set sw=3 ts=8 sts=3 expandtab: */
421