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
34#include "dri_screen.h"
35#include "dri_context.h"
36
37#include "util/u_inlines.h"
38#include "pipe/p_screen.h"
39#include "pipe/p_format.h"
40#include "pipe-loader/pipe_loader.h"
41#include "state_tracker/st_gl_api.h" /* for st_gl_api_create */
42#include "state_tracker/drm_driver.h"
43
44#include "util/u_debug.h"
45#include "util/u_format_s3tc.h"
46
47#define MSAA_VISUAL_MAX_SAMPLES 32
48
49#undef false
50
51const __DRIconfigOptionsExtension gallium_config_options = {
52   .base = { __DRI_CONFIG_OPTIONS, 2 },
53   .xml = gallium_driinfo_xml,
54   .getXml = pipe_loader_get_driinfo_xml
55};
56
57#define false 0
58
59static void
60dri_fill_st_options(struct dri_screen *screen)
61{
62   struct st_config_options *options = &screen->options;
63   const struct driOptionCache *optionCache = &screen->dev->option_cache;
64
65   options->disable_blend_func_extended =
66      driQueryOptionb(optionCache, "disable_blend_func_extended");
67   options->disable_glsl_line_continuations =
68      driQueryOptionb(optionCache, "disable_glsl_line_continuations");
69   options->force_glsl_extensions_warn =
70      driQueryOptionb(optionCache, "force_glsl_extensions_warn");
71   options->force_glsl_version =
72      driQueryOptioni(optionCache, "force_glsl_version");
73   options->allow_glsl_extension_directive_midshader =
74      driQueryOptionb(optionCache, "allow_glsl_extension_directive_midshader");
75   options->allow_glsl_builtin_const_expression =
76      driQueryOptionb(optionCache, "allow_glsl_builtin_const_expression");
77   options->allow_glsl_relaxed_es =
78      driQueryOptionb(optionCache, "allow_glsl_relaxed_es");
79   options->allow_glsl_builtin_variable_redeclaration =
80      driQueryOptionb(optionCache, "allow_glsl_builtin_variable_redeclaration");
81   options->allow_higher_compat_version =
82      driQueryOptionb(optionCache, "allow_higher_compat_version");
83   options->glsl_zero_init = driQueryOptionb(optionCache, "glsl_zero_init");
84   options->force_glsl_abs_sqrt =
85      driQueryOptionb(optionCache, "force_glsl_abs_sqrt");
86   options->allow_glsl_cross_stage_interpolation_mismatch =
87      driQueryOptionb(optionCache, "allow_glsl_cross_stage_interpolation_mismatch");
88   options->allow_glsl_layout_qualifier_on_function_parameters =
89      driQueryOptionb(optionCache, "allow_glsl_layout_qualifier_on_function_parameters");
90
91   driComputeOptionsSha1(optionCache, options->config_options_sha1);
92}
93
94static unsigned
95dri_loader_get_cap(struct dri_screen *screen, enum dri_loader_cap cap)
96{
97   const __DRIdri2LoaderExtension *dri2_loader = screen->sPriv->dri2.loader;
98   const __DRIimageLoaderExtension *image_loader = screen->sPriv->image.loader;
99
100   if (dri2_loader && dri2_loader->base.version >= 4 &&
101       dri2_loader->getCapability)
102      return dri2_loader->getCapability(screen->sPriv->loaderPrivate, cap);
103
104   if (image_loader && image_loader->base.version >= 2 &&
105       image_loader->getCapability)
106      return image_loader->getCapability(screen->sPriv->loaderPrivate, cap);
107
108   return 0;
109}
110
111static const __DRIconfig **
112dri_fill_in_modes(struct dri_screen *screen)
113{
114   static const mesa_format mesa_formats[] = {
115      MESA_FORMAT_B10G10R10A2_UNORM,
116      MESA_FORMAT_B10G10R10X2_UNORM,
117      MESA_FORMAT_R10G10B10A2_UNORM,
118      MESA_FORMAT_R10G10B10X2_UNORM,
119      MESA_FORMAT_B8G8R8A8_UNORM,
120      MESA_FORMAT_B8G8R8X8_UNORM,
121      MESA_FORMAT_B8G8R8A8_SRGB,
122      MESA_FORMAT_B8G8R8X8_SRGB,
123      MESA_FORMAT_B5G6R5_UNORM,
124
125      /* The 32-bit RGBA format must not precede the 32-bit BGRA format.
126       * Likewise for RGBX and BGRX.  Otherwise, the GLX client and the GLX
127       * server may disagree on which format the GLXFBConfig represents,
128       * resulting in swapped color channels.
129       *
130       * The problem, as of 2017-05-30:
131       * When matching a GLXFBConfig to a __DRIconfig, GLX ignores the channel
132       * order and chooses the first __DRIconfig with the expected channel
133       * sizes. Specifically, GLX compares the GLXFBConfig's and __DRIconfig's
134       * __DRI_ATTRIB_{CHANNEL}_SIZE but ignores __DRI_ATTRIB_{CHANNEL}_MASK.
135       *
136       * EGL does not suffer from this problem. It correctly compares the
137       * channel masks when matching EGLConfig to __DRIconfig.
138       */
139
140      /* Required by Android, for HAL_PIXEL_FORMAT_RGBA_8888. */
141      MESA_FORMAT_R8G8B8A8_UNORM,
142
143      /* Required by Android, for HAL_PIXEL_FORMAT_RGBX_8888. */
144      MESA_FORMAT_R8G8B8X8_UNORM,
145   };
146   static const enum pipe_format pipe_formats[] = {
147      PIPE_FORMAT_B10G10R10A2_UNORM,
148      PIPE_FORMAT_B10G10R10X2_UNORM,
149      PIPE_FORMAT_R10G10B10A2_UNORM,
150      PIPE_FORMAT_R10G10B10X2_UNORM,
151      PIPE_FORMAT_BGRA8888_UNORM,
152      PIPE_FORMAT_BGRX8888_UNORM,
153      PIPE_FORMAT_BGRA8888_SRGB,
154      PIPE_FORMAT_BGRX8888_SRGB,
155      PIPE_FORMAT_B5G6R5_UNORM,
156      PIPE_FORMAT_RGBA8888_UNORM,
157      PIPE_FORMAT_RGBX8888_UNORM,
158   };
159   mesa_format format;
160   __DRIconfig **configs = NULL;
161   uint8_t depth_bits_array[5];
162   uint8_t stencil_bits_array[5];
163   unsigned depth_buffer_factor;
164   unsigned msaa_samples_max;
165   unsigned i;
166   struct pipe_screen *p_screen = screen->base.screen;
167   boolean pf_z16, pf_x8z24, pf_z24x8, pf_s8z24, pf_z24s8, pf_z32;
168   boolean mixed_color_depth;
169   boolean allow_rgb10;
170
171   static const GLenum back_buffer_modes[] = {
172      __DRI_ATTRIB_SWAP_NONE, __DRI_ATTRIB_SWAP_UNDEFINED,
173      __DRI_ATTRIB_SWAP_COPY
174   };
175
176   if (driQueryOptionb(&screen->dev->option_cache, "always_have_depth_buffer")) {
177      /* all visuals will have a depth buffer */
178      depth_buffer_factor = 0;
179   }
180   else {
181      depth_bits_array[0] = 0;
182      stencil_bits_array[0] = 0;
183      depth_buffer_factor = 1;
184   }
185
186   allow_rgb10 = driQueryOptionb(&screen->dev->option_cache, "allow_rgb10_configs");
187
188   msaa_samples_max = (screen->st_api->feature_mask & ST_API_FEATURE_MS_VISUALS_MASK)
189      ? MSAA_VISUAL_MAX_SAMPLES : 1;
190
191   pf_x8z24 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_Z24X8_UNORM,
192					    PIPE_TEXTURE_2D, 0, 0,
193                                            PIPE_BIND_DEPTH_STENCIL);
194   pf_z24x8 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_X8Z24_UNORM,
195					    PIPE_TEXTURE_2D, 0, 0,
196                                            PIPE_BIND_DEPTH_STENCIL);
197   pf_s8z24 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_Z24_UNORM_S8_UINT,
198					    PIPE_TEXTURE_2D, 0, 0,
199                                            PIPE_BIND_DEPTH_STENCIL);
200   pf_z24s8 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_S8_UINT_Z24_UNORM,
201					    PIPE_TEXTURE_2D, 0, 0,
202                                            PIPE_BIND_DEPTH_STENCIL);
203   pf_z16 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_Z16_UNORM,
204                                          PIPE_TEXTURE_2D, 0, 0,
205                                          PIPE_BIND_DEPTH_STENCIL);
206   pf_z32 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_Z32_UNORM,
207                                          PIPE_TEXTURE_2D, 0, 0,
208                                          PIPE_BIND_DEPTH_STENCIL);
209
210   if (pf_z16) {
211      depth_bits_array[depth_buffer_factor] = 16;
212      stencil_bits_array[depth_buffer_factor++] = 0;
213   }
214   if (pf_x8z24 || pf_z24x8) {
215      depth_bits_array[depth_buffer_factor] = 24;
216      stencil_bits_array[depth_buffer_factor++] = 0;
217      screen->d_depth_bits_last = pf_x8z24;
218   }
219   if (pf_s8z24 || pf_z24s8) {
220      depth_bits_array[depth_buffer_factor] = 24;
221      stencil_bits_array[depth_buffer_factor++] = 8;
222      screen->sd_depth_bits_last = pf_s8z24;
223   }
224   if (pf_z32) {
225      depth_bits_array[depth_buffer_factor] = 32;
226      stencil_bits_array[depth_buffer_factor++] = 0;
227   }
228
229   mixed_color_depth =
230      p_screen->get_param(p_screen, PIPE_CAP_MIXED_COLOR_DEPTH_BITS);
231
232   assert(ARRAY_SIZE(mesa_formats) == ARRAY_SIZE(pipe_formats));
233
234   /* Expose only BGRA ordering if the loader doesn't support RGBA ordering. */
235   unsigned num_formats;
236   if (dri_loader_get_cap(screen, DRI_LOADER_CAP_RGBA_ORDERING))
237      num_formats = ARRAY_SIZE(mesa_formats);
238   else
239      num_formats = ARRAY_SIZE(mesa_formats) - 2; /* all - RGBA_ORDERING formats */
240
241   /* Add configs. */
242   for (format = 0; format < num_formats; format++) {
243      __DRIconfig **new_configs = NULL;
244      unsigned num_msaa_modes = 0; /* includes a single-sample mode */
245      uint8_t msaa_modes[MSAA_VISUAL_MAX_SAMPLES];
246
247      if (!allow_rgb10 &&
248          (mesa_formats[format] == MESA_FORMAT_B10G10R10A2_UNORM ||
249           mesa_formats[format] == MESA_FORMAT_B10G10R10X2_UNORM ||
250           mesa_formats[format] == MESA_FORMAT_R10G10B10A2_UNORM ||
251           mesa_formats[format] == MESA_FORMAT_R10G10B10X2_UNORM))
252         continue;
253
254      if (!p_screen->is_format_supported(p_screen, pipe_formats[format],
255                                         PIPE_TEXTURE_2D, 0, 0,
256                                         PIPE_BIND_RENDER_TARGET |
257                                         PIPE_BIND_DISPLAY_TARGET))
258         continue;
259
260      for (i = 1; i <= msaa_samples_max; i++) {
261         int samples = i > 1 ? i : 0;
262
263         if (p_screen->is_format_supported(p_screen, pipe_formats[format],
264                                           PIPE_TEXTURE_2D, samples, samples,
265                                           PIPE_BIND_RENDER_TARGET)) {
266            msaa_modes[num_msaa_modes++] = samples;
267         }
268      }
269
270      if (num_msaa_modes) {
271         /* Single-sample configs with an accumulation buffer. */
272         new_configs = driCreateConfigs(mesa_formats[format],
273                                        depth_bits_array, stencil_bits_array,
274                                        depth_buffer_factor, back_buffer_modes,
275                                        ARRAY_SIZE(back_buffer_modes),
276                                        msaa_modes, 1,
277                                        GL_TRUE, !mixed_color_depth, GL_FALSE);
278         configs = driConcatConfigs(configs, new_configs);
279
280         /* Multi-sample configs without an accumulation buffer. */
281         if (num_msaa_modes > 1) {
282            new_configs = driCreateConfigs(mesa_formats[format],
283                                           depth_bits_array, stencil_bits_array,
284                                           depth_buffer_factor, back_buffer_modes,
285                                           ARRAY_SIZE(back_buffer_modes),
286                                           msaa_modes+1, num_msaa_modes-1,
287                                           GL_FALSE, !mixed_color_depth, GL_FALSE);
288            configs = driConcatConfigs(configs, new_configs);
289         }
290      }
291   }
292
293   if (configs == NULL) {
294      debug_printf("%s: driCreateConfigs failed\n", __FUNCTION__);
295      return NULL;
296   }
297
298   return (const __DRIconfig **)configs;
299}
300
301/**
302 * Roughly the converse of dri_fill_in_modes.
303 */
304void
305dri_fill_st_visual(struct st_visual *stvis,
306                   const struct dri_screen *screen,
307                   const struct gl_config *mode)
308{
309   memset(stvis, 0, sizeof(*stvis));
310
311   if (!mode) {
312      stvis->no_config = true;
313      return;
314   }
315
316   /* Deduce the color format. */
317   switch (mode->redMask) {
318   case 0x3FF00000:
319      if (mode->alphaMask) {
320         assert(mode->alphaMask == 0xC0000000);
321         stvis->color_format = PIPE_FORMAT_B10G10R10A2_UNORM;
322      } else {
323         stvis->color_format = PIPE_FORMAT_B10G10R10X2_UNORM;
324      }
325      break;
326
327   case 0x000003FF:
328      if (mode->alphaMask) {
329         assert(mode->alphaMask == 0xC0000000);
330         stvis->color_format = PIPE_FORMAT_R10G10B10A2_UNORM;
331      } else {
332         stvis->color_format = PIPE_FORMAT_R10G10B10X2_UNORM;
333      }
334      break;
335
336   case 0x00FF0000:
337      if (mode->alphaMask) {
338         assert(mode->alphaMask == 0xFF000000);
339         stvis->color_format = mode->sRGBCapable ?
340                                  PIPE_FORMAT_BGRA8888_SRGB :
341                                  PIPE_FORMAT_BGRA8888_UNORM;
342      } else {
343         stvis->color_format = mode->sRGBCapable ?
344                                  PIPE_FORMAT_BGRX8888_SRGB :
345                                  PIPE_FORMAT_BGRX8888_UNORM;
346      }
347      break;
348
349   case 0x000000FF:
350      if (mode->alphaMask) {
351         assert(mode->alphaMask == 0xFF000000);
352         stvis->color_format = mode->sRGBCapable ?
353                                  PIPE_FORMAT_RGBA8888_SRGB :
354                                  PIPE_FORMAT_RGBA8888_UNORM;
355      } else {
356         stvis->color_format = mode->sRGBCapable ?
357                                  PIPE_FORMAT_RGBX8888_SRGB :
358                                  PIPE_FORMAT_RGBX8888_UNORM;
359      }
360      break;
361
362   case 0x0000F800:
363      stvis->color_format = PIPE_FORMAT_B5G6R5_UNORM;
364      break;
365
366   default:
367      assert(!"unsupported visual: invalid red mask");
368      return;
369   }
370
371   if (mode->sampleBuffers) {
372      stvis->samples = mode->samples;
373   }
374
375   switch (mode->depthBits) {
376   default:
377   case 0:
378      stvis->depth_stencil_format = PIPE_FORMAT_NONE;
379      break;
380   case 16:
381      stvis->depth_stencil_format = PIPE_FORMAT_Z16_UNORM;
382      break;
383   case 24:
384      if (mode->stencilBits == 0) {
385	 stvis->depth_stencil_format = (screen->d_depth_bits_last) ?
386                                          PIPE_FORMAT_Z24X8_UNORM:
387                                          PIPE_FORMAT_X8Z24_UNORM;
388      } else {
389	 stvis->depth_stencil_format = (screen->sd_depth_bits_last) ?
390                                          PIPE_FORMAT_Z24_UNORM_S8_UINT:
391                                          PIPE_FORMAT_S8_UINT_Z24_UNORM;
392      }
393      break;
394   case 32:
395      stvis->depth_stencil_format = PIPE_FORMAT_Z32_UNORM;
396      break;
397   }
398
399   stvis->accum_format = (mode->haveAccumBuffer) ?
400      PIPE_FORMAT_R16G16B16A16_SNORM : PIPE_FORMAT_NONE;
401
402   stvis->buffer_mask |= ST_ATTACHMENT_FRONT_LEFT_MASK;
403   stvis->render_buffer = ST_ATTACHMENT_FRONT_LEFT;
404   if (mode->doubleBufferMode) {
405      stvis->buffer_mask |= ST_ATTACHMENT_BACK_LEFT_MASK;
406      stvis->render_buffer = ST_ATTACHMENT_BACK_LEFT;
407   }
408   if (mode->stereoMode) {
409      stvis->buffer_mask |= ST_ATTACHMENT_FRONT_RIGHT_MASK;
410      if (mode->doubleBufferMode)
411         stvis->buffer_mask |= ST_ATTACHMENT_BACK_RIGHT_MASK;
412   }
413
414   if (mode->haveDepthBuffer || mode->haveStencilBuffer)
415      stvis->buffer_mask |= ST_ATTACHMENT_DEPTH_STENCIL_MASK;
416   /* let the state tracker allocate the accum buffer */
417}
418
419static boolean
420dri_get_egl_image(struct st_manager *smapi,
421                  void *egl_image,
422                  struct st_egl_image *stimg)
423{
424   struct dri_screen *screen = (struct dri_screen *)smapi;
425   __DRIimage *img = NULL;
426
427   if (screen->lookup_egl_image) {
428      img = screen->lookup_egl_image(screen, egl_image);
429   }
430
431   if (!img)
432      return FALSE;
433
434   stimg->texture = NULL;
435   pipe_resource_reference(&stimg->texture, img->texture);
436   switch (img->dri_components) {
437   case __DRI_IMAGE_COMPONENTS_Y_U_V:
438      stimg->format = PIPE_FORMAT_IYUV;
439      break;
440   case __DRI_IMAGE_COMPONENTS_Y_UV:
441      stimg->format = PIPE_FORMAT_NV12;
442      break;
443   default:
444      stimg->format = img->texture->format;
445      break;
446   }
447   stimg->level = img->level;
448   stimg->layer = img->layer;
449
450   return TRUE;
451}
452
453static int
454dri_get_param(struct st_manager *smapi,
455              enum st_manager_param param)
456{
457   struct dri_screen *screen = (struct dri_screen *)smapi;
458
459   switch(param) {
460   case ST_MANAGER_BROKEN_INVALIDATE:
461      return screen->broken_invalidate;
462   default:
463      return 0;
464   }
465}
466
467void
468dri_destroy_screen_helper(struct dri_screen * screen)
469{
470   if (screen->base.destroy)
471      screen->base.destroy(&screen->base);
472
473   if (screen->st_api && screen->st_api->destroy)
474      screen->st_api->destroy(screen->st_api);
475
476   if (screen->base.screen)
477      screen->base.screen->destroy(screen->base.screen);
478
479   mtx_destroy(&screen->opencl_func_mutex);
480}
481
482void
483dri_destroy_screen(__DRIscreen * sPriv)
484{
485   struct dri_screen *screen = dri_screen(sPriv);
486
487   dri_destroy_screen_helper(screen);
488
489   pipe_loader_release(&screen->dev, 1);
490
491   /* The caller in dri_util preserves the fd ownership */
492   free(screen);
493   sPriv->driverPrivate = NULL;
494   sPriv->extensions = NULL;
495}
496
497static void
498dri_postprocessing_init(struct dri_screen *screen)
499{
500   unsigned i;
501
502   for (i = 0; i < PP_FILTERS; i++) {
503      screen->pp_enabled[i] = driQueryOptioni(&screen->dev->option_cache,
504                                              pp_filters[i].name);
505   }
506}
507
508static void
509dri_set_background_context(struct st_context_iface *st,
510                           struct util_queue_monitoring *queue_info)
511{
512   struct dri_context *ctx = (struct dri_context *)st->st_manager_private;
513   const __DRIbackgroundCallableExtension *backgroundCallable =
514      ctx->sPriv->dri2.backgroundCallable;
515
516   /* Note: Mesa will only call this function if GL multithreading is enabled
517    * We only do that if the loader exposed the __DRI_BACKGROUND_CALLABLE
518    * extension. So we know that backgroundCallable is not NULL.
519    */
520   assert(backgroundCallable);
521   backgroundCallable->setBackgroundContext(ctx->cPriv->loaderPrivate);
522
523   if (ctx->hud)
524      hud_add_queue_for_monitoring(ctx->hud, queue_info);
525}
526
527void
528dri_init_options(struct dri_screen *screen)
529{
530   pipe_loader_load_options(screen->dev);
531
532   dri_fill_st_options(screen);
533}
534
535const __DRIconfig **
536dri_init_screen_helper(struct dri_screen *screen,
537                       struct pipe_screen *pscreen)
538{
539   screen->base.screen = pscreen;
540   screen->base.get_egl_image = dri_get_egl_image;
541   screen->base.get_param = dri_get_param;
542   screen->base.set_background_context = dri_set_background_context;
543
544   screen->st_api = st_gl_api_create();
545   if (!screen->st_api)
546      return NULL;
547
548   if(pscreen->get_param(pscreen, PIPE_CAP_NPOT_TEXTURES))
549      screen->target = PIPE_TEXTURE_2D;
550   else
551      screen->target = PIPE_TEXTURE_RECT;
552
553   dri_postprocessing_init(screen);
554
555   screen->st_api->query_versions(screen->st_api, &screen->base,
556                                  &screen->options,
557                                  &screen->sPriv->max_gl_core_version,
558                                  &screen->sPriv->max_gl_compat_version,
559                                  &screen->sPriv->max_gl_es1_version,
560                                  &screen->sPriv->max_gl_es2_version);
561
562   return dri_fill_in_modes(screen);
563}
564
565/* vim: set sw=3 ts=8 sts=3 expandtab: */
566