st/dri: Remove DRI1 support
[mesa.git] / src / gallium / state_trackers / dri / common / dri_screen.c
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 #ifndef __NOT_HAVE_DRM_H
34 #include "vblank.h"
35 #endif
36 #include "xmlpool.h"
37
38 #include "dri_screen.h"
39 #include "dri_context.h"
40 #include "dri_drawable.h"
41 #include "dri1_helper.h"
42 #ifndef __NOT_HAVE_DRM_H
43 #include "dri2.h"
44 #else
45 #include "drisw.h"
46 #endif
47
48 #include "util/u_inlines.h"
49 #include "pipe/p_screen.h"
50 #include "pipe/p_format.h"
51 #include "state_tracker/st_gl_api.h" /* for st_gl_api_create */
52
53 #include "util/u_debug.h"
54
55 PUBLIC const char __driConfigOptions[] =
56 DRI_CONF_BEGIN DRI_CONF_SECTION_PERFORMANCE
57 DRI_CONF_FTHROTTLE_MODE(DRI_CONF_FTHROTTLE_IRQS)
58 DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_0)
59 DRI_CONF_SECTION_END DRI_CONF_SECTION_QUALITY
60 /* DRI_CONF_FORCE_S3TC_ENABLE(false) */
61 DRI_CONF_ALLOW_LARGE_TEXTURES(1)
62 DRI_CONF_SECTION_END DRI_CONF_END;
63
64 static const uint __driNConfigOptions = 3;
65
66 static const __DRIconfig **
67 dri_fill_in_modes(struct dri_screen *screen,
68 unsigned pixel_bits)
69 {
70 __DRIconfig **configs = NULL;
71 __DRIconfig **configs_r5g6b5 = NULL;
72 __DRIconfig **configs_a8r8g8b8 = NULL;
73 __DRIconfig **configs_x8r8g8b8 = NULL;
74 uint8_t depth_bits_array[5];
75 uint8_t stencil_bits_array[5];
76 uint8_t msaa_samples_array[5];
77 unsigned depth_buffer_factor;
78 unsigned back_buffer_factor;
79 unsigned msaa_samples_factor;
80 unsigned i;
81 struct pipe_screen *p_screen = screen->base.screen;
82 boolean pf_r5g6b5, pf_a8r8g8b8, pf_x8r8g8b8;
83 boolean pf_z16, pf_x8z24, pf_z24x8, pf_s8z24, pf_z24s8, pf_z32;
84
85 static const GLenum back_buffer_modes[] = {
86 GLX_NONE, GLX_SWAP_UNDEFINED_OML, GLX_SWAP_COPY_OML
87 };
88
89 depth_bits_array[0] = 0;
90 stencil_bits_array[0] = 0;
91 depth_buffer_factor = 1;
92
93 pf_x8z24 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_Z24X8_UNORM,
94 PIPE_TEXTURE_2D, 0,
95 PIPE_BIND_DEPTH_STENCIL, 0);
96 pf_z24x8 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_X8Z24_UNORM,
97 PIPE_TEXTURE_2D, 0,
98 PIPE_BIND_DEPTH_STENCIL, 0);
99 pf_s8z24 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_Z24_UNORM_S8_USCALED,
100 PIPE_TEXTURE_2D, 0,
101 PIPE_BIND_DEPTH_STENCIL, 0);
102 pf_z24s8 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_S8_USCALED_Z24_UNORM,
103 PIPE_TEXTURE_2D, 0,
104 PIPE_BIND_DEPTH_STENCIL, 0);
105 pf_a8r8g8b8 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_B8G8R8A8_UNORM,
106 PIPE_TEXTURE_2D, 0,
107 PIPE_BIND_RENDER_TARGET, 0);
108 pf_x8r8g8b8 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_B8G8R8X8_UNORM,
109 PIPE_TEXTURE_2D, 0,
110 PIPE_BIND_RENDER_TARGET, 0);
111 pf_r5g6b5 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_B5G6R5_UNORM,
112 PIPE_TEXTURE_2D, 0,
113 PIPE_BIND_RENDER_TARGET, 0);
114
115 /* We can only get a 16 or 32 bit depth buffer with getBuffersWithFormat */
116 if (dri_with_format(screen->sPriv)) {
117 pf_z16 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_Z16_UNORM,
118 PIPE_TEXTURE_2D, 0,
119 PIPE_BIND_DEPTH_STENCIL, 0);
120 pf_z32 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_Z32_UNORM,
121 PIPE_TEXTURE_2D, 0,
122 PIPE_BIND_DEPTH_STENCIL, 0);
123 } else {
124 pf_z16 = FALSE;
125 pf_z32 = FALSE;
126 }
127
128 if (pf_z16) {
129 depth_bits_array[depth_buffer_factor] = 16;
130 stencil_bits_array[depth_buffer_factor++] = 0;
131 }
132 if (pf_x8z24 || pf_z24x8) {
133 depth_bits_array[depth_buffer_factor] = 24;
134 stencil_bits_array[depth_buffer_factor++] = 0;
135 screen->d_depth_bits_last = pf_x8z24;
136 }
137 if (pf_s8z24 || pf_z24s8) {
138 depth_bits_array[depth_buffer_factor] = 24;
139 stencil_bits_array[depth_buffer_factor++] = 8;
140 screen->sd_depth_bits_last = pf_s8z24;
141 }
142 if (pf_z32) {
143 depth_bits_array[depth_buffer_factor] = 32;
144 stencil_bits_array[depth_buffer_factor++] = 0;
145 }
146
147 msaa_samples_array[0] = 0;
148 back_buffer_factor = 3;
149
150 /* also test color for msaa 2/4/6/8 - just assume it'll work for all depth buffers */
151 if (pf_r5g6b5) {
152 msaa_samples_factor = 1;
153 for (i = 1; i < 5; i++) {
154 if (p_screen->is_format_supported(p_screen, PIPE_FORMAT_B5G6R5_UNORM,
155 PIPE_TEXTURE_2D, i*2,
156 PIPE_BIND_RENDER_TARGET, 0)) {
157 msaa_samples_array[msaa_samples_factor] = i * 2;
158 msaa_samples_factor++;
159 }
160 }
161
162 configs_r5g6b5 = driCreateConfigs(GL_RGB, GL_UNSIGNED_SHORT_5_6_5,
163 depth_bits_array, stencil_bits_array,
164 depth_buffer_factor, back_buffer_modes,
165 back_buffer_factor,
166 msaa_samples_array, msaa_samples_factor,
167 GL_TRUE);
168 }
169
170 if (pf_a8r8g8b8) {
171 msaa_samples_factor = 1;
172 for (i = 1; i < 5; i++) {
173 if (p_screen->is_format_supported(p_screen, PIPE_FORMAT_B8G8R8A8_UNORM,
174 PIPE_TEXTURE_2D, i*2,
175 PIPE_BIND_RENDER_TARGET, 0)) {
176 msaa_samples_array[msaa_samples_factor] = i * 2;
177 msaa_samples_factor++;
178 }
179 }
180
181 configs_a8r8g8b8 = driCreateConfigs(GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
182 depth_bits_array,
183 stencil_bits_array,
184 depth_buffer_factor,
185 back_buffer_modes,
186 back_buffer_factor,
187 msaa_samples_array,
188 msaa_samples_factor,
189 GL_TRUE);
190 }
191
192 if (pf_x8r8g8b8) {
193 msaa_samples_factor = 1;
194 for (i = 1; i < 5; i++) {
195 if (p_screen->is_format_supported(p_screen, PIPE_FORMAT_B8G8R8X8_UNORM,
196 PIPE_TEXTURE_2D, i*2,
197 PIPE_BIND_RENDER_TARGET, 0)) {
198 msaa_samples_array[msaa_samples_factor] = i * 2;
199 msaa_samples_factor++;
200 }
201 }
202
203 configs_x8r8g8b8 = driCreateConfigs(GL_BGR, GL_UNSIGNED_INT_8_8_8_8_REV,
204 depth_bits_array,
205 stencil_bits_array,
206 depth_buffer_factor,
207 back_buffer_modes,
208 back_buffer_factor,
209 msaa_samples_array,
210 msaa_samples_factor,
211 GL_TRUE);
212 }
213
214 if (pixel_bits == 16) {
215 configs = configs_r5g6b5;
216 if (configs_a8r8g8b8)
217 configs = configs ? driConcatConfigs(configs, configs_a8r8g8b8) : configs_a8r8g8b8;
218 if (configs_x8r8g8b8)
219 configs = configs ? driConcatConfigs(configs, configs_x8r8g8b8) : configs_x8r8g8b8;
220 } else {
221 configs = configs_a8r8g8b8;
222 if (configs_x8r8g8b8)
223 configs = configs ? driConcatConfigs(configs, configs_x8r8g8b8) : configs_x8r8g8b8;
224 if (configs_r5g6b5)
225 configs = configs ? driConcatConfigs(configs, configs_r5g6b5) : configs_r5g6b5;
226 }
227
228 if (configs == NULL) {
229 debug_printf("%s: driCreateConfigs failed\n", __FUNCTION__);
230 return NULL;
231 }
232
233 return (const __DRIconfig **)configs;
234 }
235
236 /**
237 * Roughly the converse of dri_fill_in_modes.
238 */
239 void
240 dri_fill_st_visual(struct st_visual *stvis, struct dri_screen *screen,
241 const __GLcontextModes *mode)
242 {
243 memset(stvis, 0, sizeof(*stvis));
244
245 stvis->samples = mode->samples;
246 stvis->render_buffer = ST_ATTACHMENT_INVALID;
247
248 if (mode->redBits == 8) {
249 if (mode->alphaBits == 8)
250 stvis->color_format = PIPE_FORMAT_B8G8R8A8_UNORM;
251 else
252 stvis->color_format = PIPE_FORMAT_B8G8R8X8_UNORM;
253 } else {
254 stvis->color_format = PIPE_FORMAT_B5G6R5_UNORM;
255 }
256
257 switch (mode->depthBits) {
258 default:
259 case 0:
260 stvis->depth_stencil_format = PIPE_FORMAT_NONE;
261 break;
262 case 16:
263 stvis->depth_stencil_format = PIPE_FORMAT_Z16_UNORM;
264 break;
265 case 24:
266 if (mode->stencilBits == 0) {
267 stvis->depth_stencil_format = (screen->d_depth_bits_last) ?
268 PIPE_FORMAT_Z24X8_UNORM:
269 PIPE_FORMAT_X8Z24_UNORM;
270 } else {
271 stvis->depth_stencil_format = (screen->sd_depth_bits_last) ?
272 PIPE_FORMAT_Z24_UNORM_S8_USCALED:
273 PIPE_FORMAT_S8_USCALED_Z24_UNORM;
274 }
275 break;
276 case 32:
277 stvis->depth_stencil_format = PIPE_FORMAT_Z32_UNORM;
278 break;
279 }
280
281 stvis->accum_format = (mode->haveAccumBuffer) ?
282 PIPE_FORMAT_R16G16B16A16_SNORM : PIPE_FORMAT_NONE;
283
284 stvis->buffer_mask |= ST_ATTACHMENT_FRONT_LEFT_MASK;
285 if (mode->doubleBufferMode)
286 stvis->buffer_mask |= ST_ATTACHMENT_BACK_LEFT_MASK;
287 if (mode->stereoMode) {
288 stvis->buffer_mask |= ST_ATTACHMENT_FRONT_RIGHT_MASK;
289 if (mode->doubleBufferMode)
290 stvis->buffer_mask |= ST_ATTACHMENT_BACK_RIGHT_MASK;
291 }
292
293 if (mode->haveDepthBuffer || mode->haveStencilBuffer)
294 stvis->buffer_mask |= ST_ATTACHMENT_DEPTH_STENCIL_MASK;
295 /* let the state tracker allocate the accum buffer */
296 }
297
298 static boolean
299 dri_get_egl_image(struct st_manager *smapi,
300 struct st_context_iface *stctxi,
301 void *egl_image,
302 struct st_egl_image *stimg)
303 {
304 struct dri_context *ctx =
305 (struct dri_context *)stctxi->st_manager_private;
306 struct dri_screen *screen = dri_screen(ctx->sPriv);
307 __DRIimage *img = NULL;
308
309 if (screen->lookup_egl_image) {
310 img = screen->lookup_egl_image(ctx, egl_image);
311 }
312
313 if (!img)
314 return FALSE;
315
316 stimg->texture = NULL;
317 pipe_resource_reference(&stimg->texture, img->texture);
318 stimg->face = img->face;
319 stimg->level = img->level;
320 stimg->zslice = img->zslice;
321
322 return TRUE;
323 }
324
325 static int
326 dri_get_param(struct st_manager *smapi,
327 enum st_manager_param param)
328 {
329 struct dri_screen *screen = (struct dri_screen *)smapi;
330
331 switch(param) {
332 case ST_MANAGER_BROKEN_INVALIDATE:
333 return screen->broken_invalidate;
334 default:
335 return 0;
336 }
337 }
338
339 static void
340 dri_destroy_option_cache(struct dri_screen * screen)
341 {
342 int i;
343
344 if (screen->optionCache.info) {
345 for (i = 0; i < (1 << screen->optionCache.tableSize); ++i) {
346 FREE(screen->optionCache.info[i].name);
347 FREE(screen->optionCache.info[i].ranges);
348 }
349 FREE(screen->optionCache.info);
350 }
351
352 FREE(screen->optionCache.values);
353 }
354
355 void
356 dri_destroy_screen_helper(struct dri_screen * screen)
357 {
358 dri1_destroy_pipe_context(screen);
359
360 if (screen->st_api && screen->st_api->destroy)
361 screen->st_api->destroy(screen->st_api);
362
363 if (screen->base.screen)
364 screen->base.screen->destroy(screen->base.screen);
365
366 dri_destroy_option_cache(screen);
367 }
368
369 static void
370 dri_destroy_screen(__DRIscreen * sPriv)
371 {
372 struct dri_screen *screen = dri_screen(sPriv);
373
374 dri_destroy_screen_helper(screen);
375
376 FREE(screen);
377 sPriv->private = NULL;
378 sPriv->extensions = NULL;
379 }
380
381 const __DRIconfig **
382 dri_init_screen_helper(struct dri_screen *screen,
383 struct pipe_screen *pscreen,
384 unsigned pixel_bits)
385 {
386 screen->base.screen = pscreen;
387 if (!screen->base.screen) {
388 debug_printf("%s: failed to create pipe_screen\n", __FUNCTION__);
389 return NULL;
390 }
391
392 screen->base.get_egl_image = dri_get_egl_image;
393 screen->base.get_param = dri_get_param;
394 screen->st_api = st_gl_api_create();
395
396 if (!screen->st_api)
397 return NULL;
398
399 driParseOptionInfo(&screen->optionCache,
400 __driConfigOptions, __driNConfigOptions);
401
402 return dri_fill_in_modes(screen, pixel_bits);
403 }
404
405 /**
406 * DRI driver virtual function table.
407 *
408 * DRI versions differ in their implementation of init_screen and swap_buffers.
409 */
410 const struct __DriverAPIRec driDriverAPI = {
411 .DestroyScreen = dri_destroy_screen,
412 .CreateContext = dri_create_context,
413 .DestroyContext = dri_destroy_context,
414 .CreateBuffer = dri_create_buffer,
415 .DestroyBuffer = dri_destroy_buffer,
416 .MakeCurrent = dri_make_current,
417 .UnbindContext = dri_unbind_context,
418
419 #ifndef __NOT_HAVE_DRM_H
420
421 .GetSwapInfo = NULL,
422 .GetDrawableMSC = NULL,
423 .WaitForMSC = NULL,
424 .InitScreen2 = dri2_init_screen,
425
426 .InitScreen = NULL,
427 .SwapBuffers = NULL,
428 .CopySubBuffer = NULL,
429
430 #else
431
432 .InitScreen = drisw_init_screen,
433 .SwapBuffers = drisw_swap_buffers,
434
435 #endif
436
437 };
438
439 /* vim: set sw=3 ts=8 sts=3 expandtab: */