diff options
author | Benjamin Franzke <benjaminfranzke@googlemail.com> | 2011-05-03 13:33:42 +0200 |
---|---|---|
committer | Benjamin Franzke <benjaminfranzke@googlemail.com> | 2011-05-16 10:43:15 +0200 |
commit | 701d8889414fd4e0075990ba70629b90f56c0bab (patch) | |
tree | 5351468fcc9de646e4e8745a13b437c03d4cd679 | |
parent | 34e3dc461753cba213ef16a17c6d59d6fe9c0558 (diff) |
wip: gbm gallium backend
-rw-r--r-- | src/gallium/auxiliary/Makefile | 1 | ||||
-rw-r--r-- | src/gallium/state_trackers/egl/Makefile | 2 | ||||
-rw-r--r-- | src/gallium/state_trackers/egl/drm/modeset.c | 36 | ||||
-rw-r--r-- | src/gallium/state_trackers/egl/drm/native_drm.c | 42 | ||||
-rw-r--r-- | src/gallium/state_trackers/egl/drm/native_drm.h | 4 | ||||
-rw-r--r-- | src/gbm/Makefile | 19 | ||||
-rw-r--r-- | src/gbm/api.c | 3 | ||||
-rw-r--r-- | src/gbm/gallium_drm.c | 285 | ||||
-rw-r--r-- | src/gbm/gallium_drm_internal.h | 37 | ||||
-rw-r--r-- | src/gbm/internal.h | 2 | ||||
-rw-r--r-- | src/gbm/test.c | 4 |
11 files changed, 413 insertions, 22 deletions
diff --git a/src/gallium/auxiliary/Makefile b/src/gallium/auxiliary/Makefile index 2be4509b7a..dc77f75ca3 100644 --- a/src/gallium/auxiliary/Makefile +++ b/src/gallium/auxiliary/Makefile @@ -109,6 +109,7 @@ C_SOURCES = \ util/u_dl.c \ util/u_draw.c \ util/u_draw_quad.c \ + util/u_drm_screen.c \ util/u_format.c \ util/u_format_other.c \ util/u_format_latc.c \ diff --git a/src/gallium/state_trackers/egl/Makefile b/src/gallium/state_trackers/egl/Makefile index 763e7b58a4..7ced8d3c50 100644 --- a/src/gallium/state_trackers/egl/Makefile +++ b/src/gallium/state_trackers/egl/Makefile @@ -33,7 +33,7 @@ wayland_INCLUDES = \ wayland_SOURCES = $(wildcard wayland/*.c) wayland_OBJECTS = $(wayland_SOURCES:.c=.o) -drm_INCLUDES = -I$(TOP)/src/gallium/winsys $(shell pkg-config --cflags-only-I libdrm) +drm_INCLUDES = -I$(TOP)/src/gallium/winsys $(shell pkg-config --cflags-only-I libdrm) -I$(TOP)/src/ drm_SOURCES = $(wildcard drm/*.c) drm_OBJECTS = $(drm_SOURCES:.c=.o) diff --git a/src/gallium/state_trackers/egl/drm/modeset.c b/src/gallium/state_trackers/egl/drm/modeset.c index 3fff954090..73968d1343 100644 --- a/src/gallium/state_trackers/egl/drm/modeset.c +++ b/src/gallium/state_trackers/egl/drm/modeset.c @@ -290,6 +290,42 @@ drm_display_create_surface(struct native_display *ndpy, return drmsurf; } +struct native_surface * +drm_display_create_surface_from_resource(struct native_display *ndpy, + struct pipe_resource *resource) +{ + struct drm_display *drmdpy = drm_display(ndpy); + struct drm_surface *drmsurf; + enum native_attachment natt = NATIVE_ATTACHMENT_FRONT_LEFT; + + drmsurf = CALLOC_STRUCT(drm_surface); + if (!drmsurf) + return NULL; + + drmsurf->drmdpy = drmdpy; + drmsurf->color_format = resource->format; + drmsurf->width = resource->width0; + drmsurf->height = resource->height0; + drmsurf->have_pageflip = FALSE; + + drmsurf->rsurf = resource_surface_create(drmdpy->base.screen, + drmsurf->color_format, + PIPE_BIND_RENDER_TARGET | + PIPE_BIND_SAMPLER_VIEW | + PIPE_BIND_DISPLAY_TARGET | + PIPE_BIND_SCANOUT); + + resource_surface_import_resource(drmsurf->rsurf, natt, resource); + + drmsurf->base.destroy = drm_surface_destroy; + drmsurf->base.present = drm_surface_present; + drmsurf->base.validate = drm_surface_validate; + drmsurf->base.wait = drm_surface_wait; + + return &drmsurf->base; +} + + /** * Choose a CRTC that supports all given connectors. */ diff --git a/src/gallium/state_trackers/egl/drm/native_drm.c b/src/gallium/state_trackers/egl/drm/native_drm.c index c89a6d4767..7233370158 100644 --- a/src/gallium/state_trackers/egl/drm/native_drm.c +++ b/src/gallium/state_trackers/egl/drm/native_drm.c @@ -37,6 +37,8 @@ #include <radeon_drm.h> #include "radeon/drm/radeon_drm_public.h" +#include "gbm/gallium_drm_internal.h" + #ifdef HAVE_LIBUDEV #include <libudev.h> #endif @@ -140,6 +142,7 @@ drm_display_destroy(struct native_display *ndpy) FREE(drmdpy); } +#if 0 static const char * get_drm_screen_name(int fd, drmVersionPtr version) { @@ -191,6 +194,7 @@ drm_display_init_screen(struct native_display *ndpy) return TRUE; } +#endif static struct pipe_resource * drm_display_import_buffer(struct native_display *ndpy, @@ -310,9 +314,19 @@ static struct native_display_wayland_bufmgr drm_display_wayland_bufmgr = { #endif /* HAVE_WAYLAND_BACKEND */ +static struct native_surface * +drm_create_pixmap_surface(struct native_display *ndpy, + EGLNativePixmapType pix, + const struct native_config *nconf) +{ + struct gbm_gallium_drm_bo *bo = (void *) pix; + + return drm_display_create_surface_from_resource(ndpy, bo->resource); +} + static struct native_display * -drm_create_display(int fd, struct native_event_handler *event_handler, - void *user_data) +drm_create_display(struct gbm_gallium_drm_device *gbmdrm, + struct native_event_handler *event_handler, void *user_data) { struct drm_display *drmdpy; @@ -320,20 +334,20 @@ drm_create_display(int fd, struct native_event_handler *event_handler, if (!drmdpy) return NULL; - drmdpy->fd = fd; + drmdpy->fd = gbmdrm->base.base.fd; drmdpy->device_name = drm_get_device_name(fd); + drmdpy->event_handler = event_handler; drmdpy->base.user_data = user_data; - if (!drm_display_init_screen(&drmdpy->base)) { - drm_display_destroy(&drmdpy->base); - return NULL; - } + drmdpy->base.screen = gbmdrm->screen; drmdpy->base.destroy = drm_display_destroy; drmdpy->base.get_param = drm_display_get_param; drmdpy->base.get_configs = drm_display_get_configs; + drmdpy->base.create_pixmap_surface = drm_create_pixmap_surface; + drmdpy->base.buffer = &drm_display_buffer; #ifdef HAVE_WAYLAND_BACKEND if (drmdpy->device_name) @@ -355,18 +369,20 @@ native_set_event_handler(struct native_event_handler *event_handler) static struct native_display * native_create_display(void *dpy, boolean use_sw, void *user_data) { + struct gbm_gallium_drm_device *gbm; int fd; - if (dpy) { - fd = dup((int) pointer_to_intptr(dpy)); - } - else { + gbm = dpy; + + if (gbm == NULL) { fd = open("/dev/dri/card0", O_RDWR); + gbm = gbm_gallium_drm_device(gbm_device_create(fd)); } - if (fd < 0) + + if (gbm == NULL) return NULL; - return drm_create_display(fd, drm_event_handler, user_data); + return drm_create_display(gbm, drm_event_handler, user_data); } static const struct native_platform drm_platform = { diff --git a/src/gallium/state_trackers/egl/drm/native_drm.h b/src/gallium/state_trackers/egl/drm/native_drm.h index 41cdc4f9d0..f938edeada 100644 --- a/src/gallium/state_trackers/egl/drm/native_drm.h +++ b/src/gallium/state_trackers/egl/drm/native_drm.h @@ -154,4 +154,8 @@ drm_display_init_modeset(struct native_display *ndpy); void drm_display_fini_modeset(struct native_display *ndpy); +struct native_surface * +drm_display_create_surface_from_resource(struct native_display *ndpy, + struct pipe_resource *resource); + #endif /* _NATIVE_DRM_H_ */ diff --git a/src/gbm/Makefile b/src/gbm/Makefile index 78c60eb5ed..173374f82d 100644 --- a/src/gbm/Makefile +++ b/src/gbm/Makefile @@ -3,7 +3,11 @@ TOP = ../.. include $(TOP)/configs/current -INCLUDE_DIRS = -I$(TOP)/include +PIPE_PREFIX := pipe_ + +INCLUDE_DIRS = -I$(TOP)/include \ + -I$(TOP)/src/gallium/auxiliary \ + -I$(TOP)/src/gallium/include HEADERS = \ common.h \ @@ -15,18 +19,25 @@ SOURCES = \ api.c \ common.c \ common_drm.c \ - dri.c + dri.c \ + gallium_drm.c OBJECTS = $(SOURCES:.c=.o) # use dl*() to load drivers LOCAL_CFLAGS = -D_OS_UNIX=1 $(LIBDRM_CFLAGS) $(LIBUDEV_CFLAGS) $(DLOPEN_CFLAGS) -LOCAL_LIBS = +LOCAL_LIBS = \ + $(TOP)/src/gallium/drivers/identity/libidentity.a \ + $(TOP)/src/gallium/drivers/trace/libtrace.a \ + $(TOP)/src/gallium/drivers/rbug/librbug.a \ + $(GALLIUM_AUXILIARIES) GBM_LIB_DEPS += $(LIBDRM_LIB) $(LIBUDEV_LIBS) $(DLOPEN_LIBS) LOCAL_CFLAGS += \ - -DDEFAULT_DRIVER_DIR=\"$(DRI_DRIVER_SEARCH_DIR)\" + -DDEFAULT_DRIVER_DIR=\"$(DRI_DRIVER_SEARCH_DIR)\" \ + -D_EGL_GALLIUM_DRIVER_SEARCH_DIR=\"$(EGL_DRIVER_INSTALL_DIR)\" \ + -DPIPE_PREFIX=\"$(PIPE_PREFIX)\" .c.o: $(CC) -c $(INCLUDE_DIRS) $(CFLAGS) $(LOCAL_CFLAGS) $< -o $@ diff --git a/src/gbm/api.c b/src/gbm/api.c index fab261213a..b144cdace9 100644 --- a/src/gbm/api.c +++ b/src/gbm/api.c @@ -28,7 +28,8 @@ gbm_device_create(int fd) { struct gbm_device *gbm; - gbm = dri_device_create(fd); + //gbm = dri_device_create(fd); + gbm = gbm_gallium_drm_device_create(fd); if (gbm == NULL) return NULL; diff --git a/src/gbm/gallium_drm.c b/src/gbm/gallium_drm.c new file mode 100644 index 0000000000..71c8a5a567 --- /dev/null +++ b/src/gbm/gallium_drm.c @@ -0,0 +1,285 @@ +#include <limits.h> + +#include "util/u_memory.h" +#include "util/u_string.h" +#include "util/u_dl.h" +#include "util/u_inlines.h" + +#include "state_tracker/drm_driver.h" + +#include <unistd.h> +#include <sys/types.h> + +#include "gallium_drm_internal.h" + +static struct pipe_module { + boolean initialized; + char *name; + struct util_dl_library *lib; + const struct drm_driver_descriptor *drmdd; +} pipe_modules[16]; + +static char * +loader_strdup(const char *s) +{ + size_t len = (s) ? strlen(s) : 0; + char *t = MALLOC(len + 1); + if (t) { + memcpy(t, s, len); + t[len] = '\0'; + } + return t; +} + +static void +find_pipe_module(struct pipe_module *pmod, const char *name) +{ + char *search_paths, *end, *next, *p; + char path[PATH_MAX]; + int ret; + + search_paths = NULL; + if (geteuid() == getuid()) { + /* don't allow setuid apps to use gbm_gallium_drmVERS_PATH */ + search_paths = getenv("gbm_gallium_drmVERS_PATH"); + } + if (search_paths == NULL) + search_paths = _EGL_GALLIUM_DRIVER_SEARCH_DIR; + + end = search_paths + strlen(search_paths); + for (p = search_paths; p < end && pmod->lib == NULL; p = next + 1) { + int len; + next = strchr(p, ':'); + if (next == NULL) + next = end; + + len = next - p; + + if (len) { + ret = util_snprintf(path, sizeof(path), + "%.*s/" PIPE_PREFIX "%s" UTIL_DL_EXT, len, p, pmod->name); + } + else { + ret = util_snprintf(path, sizeof(path), + PIPE_PREFIX "%s" UTIL_DL_EXT, pmod->name); + } + if (ret > 0 && ret < sizeof(path)) { + pmod->lib = util_dl_open(path); +#if 0 + if (pmod->lib) + _eglLog(_EGL_DEBUG, "loaded %s", path); +#endif + } + + } +} + +static boolean +load_pipe_module(struct pipe_module *pmod, const char *name) +{ + pmod->name = loader_strdup(name); + if (!pmod->name) + return FALSE; + + //_eglSearchPathForEach(dlopen_pipe_module_cb, (void *) pmod); + + find_pipe_module(pmod, name); + + if (pmod->lib) { + pmod->drmdd = (const struct drm_driver_descriptor *) + util_dl_get_proc_address(pmod->lib, "driver_descriptor"); + + /* sanity check on the name */ + if (pmod->drmdd && strcmp(pmod->drmdd->name, pmod->name) != 0) + pmod->drmdd = NULL; + + if (!pmod->drmdd) { + util_dl_close(pmod->lib); + pmod->lib = NULL; + } + } + + return (pmod->drmdd != NULL); +} + +static struct pipe_module * +get_pipe_module(const char *name) +{ + struct pipe_module *pmod = NULL; + int i; + + if (!name) + return NULL; + + for (i = 0; i < Elements(pipe_modules); i++) { + if (!pipe_modules[i].initialized || + strcmp(pipe_modules[i].name, name) == 0) { + pmod = &pipe_modules[i]; + break; + } + } + if (!pmod) + return NULL; + + if (!pmod->initialized) { + load_pipe_module(pmod, name); + pmod->initialized = TRUE; + } + + return pmod; +} + +static struct pipe_screen * +create_drm_screen(const char *name, int fd) +{ + struct pipe_module *pmod = get_pipe_module(name); + + return (pmod && pmod->drmdd && pmod->drmdd->create_screen) ? + pmod->drmdd->create_screen(fd) : NULL; +} + + + + + + + + + + +static int +gallium_screen_create(struct gbm_gallium_drm_device *gdrm) +{ + gdrm->base.driver_name = drm_fd_get_driver(gdrm->base.base.fd); + printf("driver name. %s\n", gdrm->base.driver_name); + + gdrm->screen = create_drm_screen(gdrm->base.driver_name, gdrm->base.base.fd); + if (gdrm->screen == NULL) { + fprintf(stderr, "failed to load driver: %s\n", gdrm->base.driver_name); + return -1; + }; + + return 0; +} + +static void +gbm_gallium_drm_bo_destroy(struct gbm_bo *_bo) +{ + struct gbm_gallium_drm_bo *bo = gbm_gallium_drm_bo(_bo); + + pipe_resource_reference(&bo->resource, NULL); +} + +static struct gbm_bo * +gbm_gallium_drm_bo_create(struct gbm_device *gbm, + uint32_t width, uint32_t height, + enum gbm_bo_format format, uint32_t usage) +{ + struct gbm_gallium_drm_device *gdrm = gbm_gallium_drm_device(gbm); + struct gbm_gallium_drm_bo *bo; + struct pipe_resource templ; + struct winsys_handle whandle; + uint resource_usage = 0; + enum pipe_format pf; + + bo = CALLOC_STRUCT(gbm_gallium_drm_bo); + if (bo == NULL) + return NULL; + + bo->base.base.gbm = gbm; + bo->base.base.width = width; + bo->base.base.height = height; + + switch (format) { + case GBM_BO_FORMAT_XRGB8888: + pf = PIPE_FORMAT_B8G8R8X8_UNORM; + break; + case GBM_BO_FORMAT_ARGB8888: + pf = PIPE_FORMAT_B8G8R8A8_UNORM; + break; + default: + return NULL; + } + + if (usage & GBM_BO_USE_SCANOUT) + resource_usage |= PIPE_BIND_SCANOUT; + + if (usage & GBM_BO_USE_RENDERING) + resource_usage |= PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW; + +#if 0 + if (usage & GBM_BO_USE_CURSOR_64X64) + resource_usage |= PIPE_BIND_CURSOR; +#endif + + memset(&templ, 0, sizeof(templ)); + templ.bind = resource_usage; + templ.format = pf; + templ.target = PIPE_TEXTURE_2D; + templ.last_level = 0; + templ.width0 = width; + templ.height0 = height; + templ.depth0 = 1; + templ.array_size = 1; + + bo->resource = gdrm->screen->resource_create(gdrm->screen, &templ); + if (bo->resource == NULL) { + FREE(bo); + return NULL; + } + + memset(&whandle, 0, sizeof(whandle)); + whandle.type = DRM_API_HANDLE_TYPE_KMS; + gdrm->screen->resource_get_handle(gdrm->screen, bo->resource, &whandle); + + bo->base.base.handle.u32 = whandle.handle; + bo->base.base.pitch = whandle.stride; + + return &bo->base.base; +} + +static boolean +pipe_modules_destroy(void) +{ + //util_dl_close + + return TRUE; +} + +static void +gbm_gallium_drm_destroy(struct gbm_device *gbm) +{ + struct gbm_gallium_drm_device *gdrm = gbm_gallium_drm_device(gbm); + + gdrm->screen->destroy(gdrm->screen); + + pipe_modules_destroy(); + FREE(gdrm->base.driver_name); + + FREE(gdrm); +} + +struct gbm_device * +gbm_gallium_drm_device_create(int fd) +{ + struct gbm_gallium_drm_device *dri; + int ret; + + dri = calloc(1, sizeof *dri); + + dri->base.base.fd = fd; + dri->base.base.bo_create = gbm_gallium_drm_bo_create; + dri->base.base.bo_destroy = gbm_gallium_drm_bo_destroy; + dri->base.base.destroy = gbm_gallium_drm_destroy; + + dri->base.type = GBM_DRM_DRIVER_TYPE_GALLIUM; + dri->base.base.name = "drm"; + + ret = gallium_screen_create(dri); + if (ret) { + free(dri); + return NULL; + } + + return &dri->base.base; +} diff --git a/src/gbm/gallium_drm_internal.h b/src/gbm/gallium_drm_internal.h new file mode 100644 index 0000000000..7f9bc081ae --- /dev/null +++ b/src/gbm/gallium_drm_internal.h @@ -0,0 +1,37 @@ + +#ifndef _GBM_GALLIUM_DRM_INTERNAL_H_ +#define _GBM_GALLIUM_DRM_INTERNAL_H_ + +#include "pipe/p_state.h" + +#include "internal.h" + +#include "common.h" +#include "common_drm.h" + +struct gbm_gallium_drm_device { + struct gbm_drm_device base; + + struct pipe_screen *screen; + void *driver; +}; + +struct gbm_gallium_drm_bo { + struct gbm_drm_bo base; + + struct pipe_resource *resource; +}; + +static inline struct gbm_gallium_drm_device * +gbm_gallium_drm_device(struct gbm_device *gbm) +{ + return (struct gbm_gallium_drm_device *) gbm; +} + +static inline struct gbm_gallium_drm_bo * +gbm_gallium_drm_bo(struct gbm_bo *bo) +{ + return (struct gbm_gallium_drm_bo *) bo; +} + +#endif diff --git a/src/gbm/internal.h b/src/gbm/internal.h index d70aff9b1b..c0fcc48001 100644 --- a/src/gbm/internal.h +++ b/src/gbm/internal.h @@ -43,6 +43,6 @@ struct gbm_device * dri_device_create(int fd); struct gbm_device * -gallium_drm_device_create(int fd); +gbm_gallium_drm_device_create(int fd); #endif diff --git a/src/gbm/test.c b/src/gbm/test.c index d1b81199d2..83fa561208 100644 --- a/src/gbm/test.c +++ b/src/gbm/test.c @@ -18,7 +18,7 @@ int main(void) if (fd == -1) return 1; - gbm = gbm_create(fd); + gbm = gbm_device_create(fd); if (gbm == NULL) return 1; else @@ -27,7 +27,7 @@ int main(void) bo = gbm_bo_create(gbm, 250, 250, GBM_BO_FORMAT_XRGB8888, GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING); - gbm_destroy(gbm); + gbm_device_destroy(gbm); close(fd); |