main drm.c
  1/* wld: drm.c
  2 *
  3 * Copyright (c) 2013, 2014 Michael Forney
  4 *
  5 * Permission is hereby granted, free of charge, to any person obtaining a copy
  6 * of this software and associated documentation files (the "Software"), to deal
  7 * in the Software without restriction, including without limitation the rights
  8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9 * copies of the Software, and to permit persons to whom the Software is
 10 * furnished to do so, subject to the following conditions:
 11 *
 12 * The above copyright notice and this permission notice shall be included in
 13 * all copies or substantial portions of the Software.
 14 *
 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 21 * SOFTWARE.
 22 */
 23
 24#include "drm.h"
 25#include "drm-private.h"
 26
 27#include <sys/types.h>
 28#ifndef major
 29
 30#ifdef __linux__
 31#include <sys/sysmacros.h>
 32#elif defined(__sun)
 33#include <sys/mkdev.h>
 34#endif
 35
 36#endif
 37
 38const static struct drm_driver *drivers[] = {
 39#if WITH_DRM_INTEL
 40	&intel_drm_driver,
 41#endif
 42#if WITH_DRM_NOUVEAU
 43	&nouveau_drm_driver,
 44#endif
 45	&dumb_drm_driver
 46};
 47
 48static const struct drm_driver *
 49find_driver(int fd)
 50{
 51	#ifdef __sun
 52	(void)fd;
 53	return NULL;
 54	#else
 55	char path[64], id[32];
 56	uint32_t vendor_id, device_id;
 57	char *path_part;
 58	struct stat st;
 59	FILE *file;
 60	uint32_t index;
 61	int n;
 62
 63	if (fstat(fd, &st) == -1)
 64		return NULL;
 65
 66	n = snprintf(path, sizeof(path), "/sys/dev/char/%u:%u/device/", major(st.st_rdev), minor(st.st_rdev));
 67	if (n + 6 >= sizeof(path))
 68		return NULL;
 69	path_part = path + n;
 70
 71	strcpy(path_part, "vendor");
 72	file = fopen(path, "r");
 73	if (!file)
 74		return NULL;
 75	fgets(id, sizeof id, file);
 76	fclose(file);
 77	vendor_id = strtoul(id, NULL, 0);
 78
 79	strcpy(path_part, "device");
 80	file = fopen(path, "r");
 81	if (!file)
 82		return NULL;
 83	fgets(id, sizeof id, file);
 84	fclose(file);
 85	device_id = strtoul(id, NULL, 0);
 86
 87	for (index = 0; index < ARRAY_LENGTH(drivers); ++index) {
 88		DEBUG("Trying DRM driver `%s'\n", drivers[index]->name);
 89		if (drivers[index]->device_supported(vendor_id, device_id))
 90			return drivers[index];
 91	}
 92
 93	return NULL;
 94	#endif
 95}
 96
 97EXPORT
 98struct wld_context *
 99wld_drm_create_context(int fd)
100{
101	const struct drm_driver *driver;
102	struct wld_context *context;
103
104	if (!getenv("WLD_DRM_DUMB")) {
105		driver = find_driver(fd);
106		if (driver) {
107			context = driver->create_context(fd);
108			if (context)
109				return context;
110		}
111	}
112
113	DEBUG("Falling back to dumb DRM driver\n");
114	return dumb_drm_driver.create_context(fd);
115}
116
117EXPORT
118bool
119wld_drm_is_dumb(struct wld_context *context)
120{
121	return context->impl == dumb_context_impl;
122}