diff options
Diffstat (limited to 'src/gallium/state_trackers/egl/egl_tracker.c')
-rw-r--r-- | src/gallium/state_trackers/egl/egl_tracker.c | 271 |
1 files changed, 271 insertions, 0 deletions
diff --git a/src/gallium/state_trackers/egl/egl_tracker.c b/src/gallium/state_trackers/egl/egl_tracker.c new file mode 100644 index 0000000000..5140755001 --- /dev/null +++ b/src/gallium/state_trackers/egl/egl_tracker.c @@ -0,0 +1,271 @@ + +#include "utils.h" + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include "egl_tracker.h" + +#include <fcntl.h> + +#include "egllog.h" +#include "state_tracker/drm_api.h" + +#include "pipe/p_screen.h" +#include "pipe/internal/p_winsys_screen.h" + +/** HACK */ +void* driDriverAPI; +extern const struct dri_extension card_extensions[]; + + +/* + * Exported functions + */ + +static void +drm_unload(_EGLDriver *drv) +{ + free(drv); +} + +/** + * The bootstrap function. Return a new drm_driver object and + * plug in API functions. + */ +_EGLDriver * +_eglMain(const char *args) +{ + _EGLDriver *drv; + + drv = (_EGLDriver *) calloc(1, sizeof(_EGLDriver)); + if (!drv) { + return NULL; + } + + /* First fill in the dispatch table with defaults */ + _eglInitDriverFallbacks(drv); + /* then plug in our Drm-specific functions */ + drv->API.Initialize = drm_initialize; + drv->API.Terminate = drm_terminate; + drv->API.CreateContext = drm_create_context; + drv->API.MakeCurrent = drm_make_current; + drv->API.CreateWindowSurface = drm_create_window_surface; + drv->API.CreatePixmapSurface = drm_create_pixmap_surface; + drv->API.CreatePbufferSurface = drm_create_pbuffer_surface; + drv->API.DestroySurface = drm_destroy_surface; + drv->API.DestroyContext = drm_destroy_context; + drv->API.CreateScreenSurfaceMESA = drm_create_screen_surface_mesa; + drv->API.ShowScreenSurfaceMESA = drm_show_screen_surface_mesa; + drv->API.SwapBuffers = drm_swap_buffers; + + drv->Name = "DRM/Gallium/Win"; + drv->Unload = drm_unload; + + return drv; +} + +static void +drm_get_device_id(struct drm_device *device) +{ + char path[512]; + FILE *file; + char *ret; + + /* TODO get the real minor */ + int minor = 0; + + device->deviceID = 0; + + snprintf(path, sizeof(path), "/sys/class/drm/card%d/device/device", minor); + file = fopen(path, "r"); + if (!file) { + _eglLog(_EGL_WARNING, "Could not retrive device ID\n"); + return; + } + + ret = fgets(path, sizeof( path ), file); + if (!ret) + return; + + sscanf(path, "%x", &device->deviceID); + fclose(file); +} + +static void +drm_update_res(struct drm_device *dev) +{ + drmModeFreeResources(dev->res); + dev->res = drmModeGetResources(dev->drmFD); +} + +static void +drm_add_modes_from_connector(_EGLScreen *screen, drmModeConnectorPtr connector) +{ + drmModeModeInfoPtr m = NULL; + int i; + + for (i = 0; i < connector->count_modes; i++) { + m = &connector->modes[i]; + _eglAddNewMode(screen, m->hdisplay, m->vdisplay, m->vrefresh, m->name); + } +} + +static void +drm_find_dpms(struct drm_device *dev, struct drm_screen *screen) +{ + drmModeConnectorPtr c = screen->connector; + drmModePropertyPtr p; + int i; + + for (i = 0; i < c->count_props; i++) { + p = drmModeGetProperty(dev->drmFD, c->props[i]); + if (!strcmp(p->name, "DPMS")) + break; + + drmModeFreeProperty(p); + p = NULL; + } + + screen->dpms = p; +} + +static int drm_open_minor(int minor) +{ + char buf[64]; + + sprintf(buf, DRM_DEV_NAME, DRM_DIR_NAME, minor); + return open(buf, O_RDWR, 0); +} + +EGLBoolean +drm_initialize(_EGLDriver *drv, _EGLDisplay *disp, EGLint *major, EGLint *minor) +{ + struct drm_device *dev; + struct drm_screen *screen = NULL; + drmModeConnectorPtr connector = NULL; + drmModeResPtr res = NULL; + unsigned count_connectors = 0; + int num_screens = 0; + EGLint i; + int fd; + + dev = (struct drm_device *) calloc(1, sizeof(struct drm_device)); + if (!dev) + return EGL_FALSE; + dev->api = drm_api_create(); + + /* try the first node */ + fd = drm_open_minor(0); + if (fd < 0) + goto err_fd; + + dev->drmFD = fd; + drm_get_device_id(dev); + + dev->screen = dev->api->create_screen(dev->api, dev->drmFD, NULL); + if (!dev->screen) + goto err_screen; + dev->winsys = dev->screen->winsys; + + /* TODO HACK */ + driInitExtensions(NULL, card_extensions, GL_FALSE); + + drm_update_res(dev); + res = dev->res; + if (res) + count_connectors = res->count_connectors; + else + _eglLog(_EGL_WARNING, "Could not retrive kms information\n"); + + for(i = 0; i < count_connectors && i < MAX_SCREENS; i++) { + connector = drmModeGetConnector(fd, res->connectors[i]); + + if (!connector) + continue; + + if (connector->connection != DRM_MODE_CONNECTED) { + drmModeFreeConnector(connector); + continue; + } + + screen = malloc(sizeof(struct drm_screen)); + memset(screen, 0, sizeof(*screen)); + screen->connector = connector; + screen->connectorID = connector->connector_id; + _eglInitScreen(&screen->base); + _eglAddScreen(disp, &screen->base); + drm_add_modes_from_connector(&screen->base, connector); + drm_find_dpms(dev, screen); + dev->screens[num_screens++] = screen; + } + dev->count_screens = num_screens; + + disp->DriverData = dev; + + /* for now we only have one config */ + _EGLConfig *config = calloc(1, sizeof(*config)); + memset(config, 1, sizeof(*config)); + _eglInitConfig(config, 1); + _eglSetConfigAttrib(config, EGL_RED_SIZE, 8); + _eglSetConfigAttrib(config, EGL_GREEN_SIZE, 8); + _eglSetConfigAttrib(config, EGL_BLUE_SIZE, 8); + _eglSetConfigAttrib(config, EGL_ALPHA_SIZE, 8); + _eglSetConfigAttrib(config, EGL_BUFFER_SIZE, 32); + _eglSetConfigAttrib(config, EGL_DEPTH_SIZE, 24); + _eglSetConfigAttrib(config, EGL_STENCIL_SIZE, 8); + _eglSetConfigAttrib(config, EGL_SURFACE_TYPE, EGL_PBUFFER_BIT); + _eglAddConfig(disp, config); + + disp->ClientAPIsMask = EGL_OPENGL_BIT /*| EGL_OPENGL_ES_BIT*/; + /* enable supported extensions */ + disp->Extensions.MESA_screen_surface = EGL_TRUE; + disp->Extensions.MESA_copy_context = EGL_TRUE; + + *major = 1; + *minor = 4; + + return EGL_TRUE; + +err_screen: + drmClose(fd); +err_fd: + free(dev); + return EGL_FALSE; +} + +EGLBoolean +drm_terminate(_EGLDriver *drv, _EGLDisplay *dpy) +{ + struct drm_device *dev = lookup_drm_device(dpy); + struct drm_screen *screen; + int i = 0; + + _eglReleaseDisplayResources(drv, dpy); + _eglCleanupDisplay(dpy); + + drmFreeVersion(dev->version); + + for (i = 0; i < dev->count_screens; i++) { + screen = dev->screens[i]; + + if (screen->shown) + drm_takedown_shown_screen(dpy, screen); + + drmModeFreeProperty(screen->dpms); + drmModeFreeConnector(screen->connector); + _eglDestroyScreen(&screen->base); + dev->screens[i] = NULL; + } + + dev->screen->destroy(dev->screen); + dev->winsys = NULL; + + drmClose(dev->drmFD); + + dev->api->destroy(dev->api); + free(dev); + dpy->DriverData = NULL; + + return EGL_TRUE; +} |