1bf215546Sopenharmony_ci/**************************************************************************
2bf215546Sopenharmony_ci *
3bf215546Sopenharmony_ci * Copyright 2012 Francisco Jerez
4bf215546Sopenharmony_ci * All Rights Reserved.
5bf215546Sopenharmony_ci *
6bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
7bf215546Sopenharmony_ci * copy of this software and associated documentation files (the
8bf215546Sopenharmony_ci * "Software"), to deal in the Software without restriction, including
9bf215546Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish,
10bf215546Sopenharmony_ci * distribute, sub license, and/or sell copies of the Software, and to
11bf215546Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to
12bf215546Sopenharmony_ci * the following conditions:
13bf215546Sopenharmony_ci *
14bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the
15bf215546Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions
16bf215546Sopenharmony_ci * of the Software.
17bf215546Sopenharmony_ci *
18bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20bf215546Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21bf215546Sopenharmony_ci * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22bf215546Sopenharmony_ci * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23bf215546Sopenharmony_ci * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24bf215546Sopenharmony_ci * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25bf215546Sopenharmony_ci *
26bf215546Sopenharmony_ci **************************************************************************/
27bf215546Sopenharmony_ci
28bf215546Sopenharmony_ci#include "pipe_loader_priv.h"
29bf215546Sopenharmony_ci
30bf215546Sopenharmony_ci#include "util/u_inlines.h"
31bf215546Sopenharmony_ci#include "util/u_memory.h"
32bf215546Sopenharmony_ci#include "util/u_string.h"
33bf215546Sopenharmony_ci#include "util/u_dl.h"
34bf215546Sopenharmony_ci#include "util/u_file.h"
35bf215546Sopenharmony_ci#include "util/xmlconfig.h"
36bf215546Sopenharmony_ci#include "util/driconf.h"
37bf215546Sopenharmony_ci
38bf215546Sopenharmony_ci#include <string.h>
39bf215546Sopenharmony_ci
40bf215546Sopenharmony_ci#ifdef _MSC_VER
41bf215546Sopenharmony_ci#include <stdlib.h>
42bf215546Sopenharmony_ci#define PATH_MAX _MAX_PATH
43bf215546Sopenharmony_ci#endif
44bf215546Sopenharmony_ci
45bf215546Sopenharmony_ci#define MODULE_PREFIX "pipe_"
46bf215546Sopenharmony_ci
47bf215546Sopenharmony_cistatic int (*backends[])(struct pipe_loader_device **, int) = {
48bf215546Sopenharmony_ci#ifdef HAVE_LIBDRM
49bf215546Sopenharmony_ci   &pipe_loader_drm_probe,
50bf215546Sopenharmony_ci#endif
51bf215546Sopenharmony_ci   &pipe_loader_sw_probe
52bf215546Sopenharmony_ci};
53bf215546Sopenharmony_ci
54bf215546Sopenharmony_ciconst driOptionDescription gallium_driconf[] = {
55bf215546Sopenharmony_ci#include "driinfo_gallium.h"
56bf215546Sopenharmony_ci};
57bf215546Sopenharmony_ci
58bf215546Sopenharmony_ciint
59bf215546Sopenharmony_cipipe_loader_probe(struct pipe_loader_device **devs, int ndev)
60bf215546Sopenharmony_ci{
61bf215546Sopenharmony_ci   int i, n = 0;
62bf215546Sopenharmony_ci
63bf215546Sopenharmony_ci   for (i = 0; i < ARRAY_SIZE(backends); i++)
64bf215546Sopenharmony_ci      n += backends[i](&devs[n], MAX2(0, ndev - n));
65bf215546Sopenharmony_ci
66bf215546Sopenharmony_ci   return n;
67bf215546Sopenharmony_ci}
68bf215546Sopenharmony_ci
69bf215546Sopenharmony_civoid
70bf215546Sopenharmony_cipipe_loader_release(struct pipe_loader_device **devs, int ndev)
71bf215546Sopenharmony_ci{
72bf215546Sopenharmony_ci   int i;
73bf215546Sopenharmony_ci
74bf215546Sopenharmony_ci   for (i = 0; i < ndev; i++)
75bf215546Sopenharmony_ci      devs[i]->ops->release(&devs[i]);
76bf215546Sopenharmony_ci}
77bf215546Sopenharmony_ci
78bf215546Sopenharmony_civoid
79bf215546Sopenharmony_cipipe_loader_base_release(struct pipe_loader_device **dev)
80bf215546Sopenharmony_ci{
81bf215546Sopenharmony_ci   driDestroyOptionCache(&(*dev)->option_cache);
82bf215546Sopenharmony_ci   driDestroyOptionInfo(&(*dev)->option_info);
83bf215546Sopenharmony_ci
84bf215546Sopenharmony_ci   FREE(*dev);
85bf215546Sopenharmony_ci   *dev = NULL;
86bf215546Sopenharmony_ci}
87bf215546Sopenharmony_ci
88bf215546Sopenharmony_cistatic driOptionDescription *
89bf215546Sopenharmony_cimerge_driconf(const driOptionDescription *driver_driconf, unsigned driver_count,
90bf215546Sopenharmony_ci              unsigned *merged_count)
91bf215546Sopenharmony_ci{
92bf215546Sopenharmony_ci   unsigned gallium_count = ARRAY_SIZE(gallium_driconf);
93bf215546Sopenharmony_ci   driOptionDescription *merged = malloc((driver_count + gallium_count) *
94bf215546Sopenharmony_ci                                         sizeof(*merged));
95bf215546Sopenharmony_ci   if (!merged) {
96bf215546Sopenharmony_ci      *merged_count = 0;
97bf215546Sopenharmony_ci      return NULL;
98bf215546Sopenharmony_ci   }
99bf215546Sopenharmony_ci
100bf215546Sopenharmony_ci   memcpy(merged, gallium_driconf, sizeof(*merged) * gallium_count);
101bf215546Sopenharmony_ci   memcpy(&merged[gallium_count], driver_driconf, sizeof(*merged) * driver_count);
102bf215546Sopenharmony_ci
103bf215546Sopenharmony_ci   *merged_count = driver_count + gallium_count;
104bf215546Sopenharmony_ci   return merged;
105bf215546Sopenharmony_ci}
106bf215546Sopenharmony_ci
107bf215546Sopenharmony_ci/**
108bf215546Sopenharmony_ci * Ensure that dev->option_cache is initialized appropriately for the driver.
109bf215546Sopenharmony_ci *
110bf215546Sopenharmony_ci * This function can be called multiple times.
111bf215546Sopenharmony_ci *
112bf215546Sopenharmony_ci * \param dev Device for which options should be loaded.
113bf215546Sopenharmony_ci */
114bf215546Sopenharmony_cistatic void
115bf215546Sopenharmony_cipipe_loader_load_options(struct pipe_loader_device *dev)
116bf215546Sopenharmony_ci{
117bf215546Sopenharmony_ci   if (dev->option_info.info)
118bf215546Sopenharmony_ci      return;
119bf215546Sopenharmony_ci
120bf215546Sopenharmony_ci   unsigned driver_count, merged_count;
121bf215546Sopenharmony_ci   const driOptionDescription *driver_driconf =
122bf215546Sopenharmony_ci      dev->ops->get_driconf(dev, &driver_count);
123bf215546Sopenharmony_ci
124bf215546Sopenharmony_ci   const driOptionDescription *merged_driconf =
125bf215546Sopenharmony_ci      merge_driconf(driver_driconf, driver_count, &merged_count);
126bf215546Sopenharmony_ci   driParseOptionInfo(&dev->option_info, merged_driconf, merged_count);
127bf215546Sopenharmony_ci   free((void *)merged_driconf);
128bf215546Sopenharmony_ci}
129bf215546Sopenharmony_ci
130bf215546Sopenharmony_civoid
131bf215546Sopenharmony_cipipe_loader_config_options(struct pipe_loader_device *dev)
132bf215546Sopenharmony_ci{
133bf215546Sopenharmony_ci   if (!dev->option_cache.info) {
134bf215546Sopenharmony_ci      driParseConfigFiles(&dev->option_cache, &dev->option_info, 0,
135bf215546Sopenharmony_ci                          dev->driver_name, NULL, NULL, NULL, 0, NULL, 0);
136bf215546Sopenharmony_ci   }
137bf215546Sopenharmony_ci}
138bf215546Sopenharmony_ci
139bf215546Sopenharmony_cichar *
140bf215546Sopenharmony_cipipe_loader_get_driinfo_xml(const char *driver_name)
141bf215546Sopenharmony_ci{
142bf215546Sopenharmony_ci   unsigned driver_count = 0;
143bf215546Sopenharmony_ci   const driOptionDescription *driver_driconf = NULL;
144bf215546Sopenharmony_ci
145bf215546Sopenharmony_ci#ifdef HAVE_LIBDRM
146bf215546Sopenharmony_ci   driver_driconf = pipe_loader_drm_get_driconf_by_name(driver_name,
147bf215546Sopenharmony_ci                                                        &driver_count);
148bf215546Sopenharmony_ci#endif
149bf215546Sopenharmony_ci
150bf215546Sopenharmony_ci   unsigned merged_count;
151bf215546Sopenharmony_ci   const driOptionDescription *merged_driconf =
152bf215546Sopenharmony_ci      merge_driconf(driver_driconf, driver_count, &merged_count);
153bf215546Sopenharmony_ci   free((void *)driver_driconf);
154bf215546Sopenharmony_ci
155bf215546Sopenharmony_ci   char *xml = driGetOptionsXml(merged_driconf, merged_count);
156bf215546Sopenharmony_ci
157bf215546Sopenharmony_ci   free((void *)merged_driconf);
158bf215546Sopenharmony_ci
159bf215546Sopenharmony_ci   return xml;
160bf215546Sopenharmony_ci}
161bf215546Sopenharmony_ci
162bf215546Sopenharmony_cistruct pipe_screen *
163bf215546Sopenharmony_cipipe_loader_create_screen_vk(struct pipe_loader_device *dev, bool sw_vk)
164bf215546Sopenharmony_ci{
165bf215546Sopenharmony_ci   struct pipe_screen_config config;
166bf215546Sopenharmony_ci
167bf215546Sopenharmony_ci   pipe_loader_load_options(dev);
168bf215546Sopenharmony_ci   config.options_info = &dev->option_info;
169bf215546Sopenharmony_ci   config.options = &dev->option_cache;
170bf215546Sopenharmony_ci
171bf215546Sopenharmony_ci   return dev->ops->create_screen(dev, &config, sw_vk);
172bf215546Sopenharmony_ci}
173bf215546Sopenharmony_ci
174bf215546Sopenharmony_cistruct pipe_screen *
175bf215546Sopenharmony_cipipe_loader_create_screen(struct pipe_loader_device *dev)
176bf215546Sopenharmony_ci{
177bf215546Sopenharmony_ci   return pipe_loader_create_screen_vk(dev, false);
178bf215546Sopenharmony_ci}
179bf215546Sopenharmony_ci
180bf215546Sopenharmony_cistruct util_dl_library *
181bf215546Sopenharmony_cipipe_loader_find_module(const char *driver_name,
182bf215546Sopenharmony_ci                        const char *library_paths)
183bf215546Sopenharmony_ci{
184bf215546Sopenharmony_ci   struct util_dl_library *lib;
185bf215546Sopenharmony_ci   const char *next;
186bf215546Sopenharmony_ci   char path[PATH_MAX];
187bf215546Sopenharmony_ci   int len, ret;
188bf215546Sopenharmony_ci
189bf215546Sopenharmony_ci   for (next = library_paths; *next; library_paths = next + 1) {
190bf215546Sopenharmony_ci      next = strchrnul(library_paths, ':');
191bf215546Sopenharmony_ci      len = next - library_paths;
192bf215546Sopenharmony_ci
193bf215546Sopenharmony_ci      if (len)
194bf215546Sopenharmony_ci         ret = snprintf(path, sizeof(path), "%.*s/%s%s%s",
195bf215546Sopenharmony_ci                        len, library_paths,
196bf215546Sopenharmony_ci                        MODULE_PREFIX, driver_name, UTIL_DL_EXT);
197bf215546Sopenharmony_ci      else
198bf215546Sopenharmony_ci         ret = snprintf(path, sizeof(path), "%s%s%s",
199bf215546Sopenharmony_ci                        MODULE_PREFIX, driver_name, UTIL_DL_EXT);
200bf215546Sopenharmony_ci
201bf215546Sopenharmony_ci      if (ret > 0 && ret < sizeof(path) && u_file_access(path, 0) != -1) {
202bf215546Sopenharmony_ci         lib = util_dl_open(path);
203bf215546Sopenharmony_ci         if (lib) {
204bf215546Sopenharmony_ci            return lib;
205bf215546Sopenharmony_ci         }
206bf215546Sopenharmony_ci         fprintf(stderr, "ERROR: Failed to load pipe driver at `%s': %s\n",
207bf215546Sopenharmony_ci                         path, util_dl_error());
208bf215546Sopenharmony_ci      }
209bf215546Sopenharmony_ci   }
210bf215546Sopenharmony_ci
211bf215546Sopenharmony_ci   return NULL;
212bf215546Sopenharmony_ci}
213