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