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