From c46b2ee2cace20f67b0c5e1121e1973a7678fd60 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Fri, 1 Aug 2014 20:02:02 +0100 Subject: freedreno: completely untested initial support v2: [Emil Velikov] - drmGetVersion returns the kernel module name. - Add it to the build :) - freedreno_map returns void * while gralloc::map expects int. Signed-off-by: Emil Velikov --- Android.mk | 9 +++ gralloc_drm.c | 4 + gralloc_drm_freedreno.c | 209 ++++++++++++++++++++++++++++++++++++++++++++++++ gralloc_drm_pipe.c | 10 +++ gralloc_drm_priv.h | 2 + 5 files changed, 234 insertions(+) create mode 100644 gralloc_drm_freedreno.c diff --git a/Android.mk b/Android.mk index c701b6e..116225a 100644 --- a/Android.mk +++ b/Android.mk @@ -23,6 +23,7 @@ DRM_GPU_DRIVERS := $(strip $(filter-out swrast, $(BOARD_GPU_DRIVERS))) +freedreno_drivers := freedreno intel_drivers := i915 i965 i915g ilo radeon_drivers := r300g r600g nouveau_drivers := nouveau @@ -30,6 +31,7 @@ vmwgfx_drivers := vmwgfx valid_drivers := \ prebuilt \ + $(freedreno_drivers) \ $(intel_drivers) \ $(radeon_drivers) \ $(nouveau_drivers) \ @@ -95,6 +97,13 @@ LOCAL_SHARED_LIBRARIES := \ libcutils \ libhardware_legacy \ +ifneq ($(filter $(freedreno_drivers), $(DRM_GPU_DRIVERS)),) +LOCAL_SRC_FILES += gralloc_drm_freedreno.c +LOCAL_C_INCLUDES += external/drm/freedreno +LOCAL_CFLAGS += -DENABLE_FREEDRENO +LOCAL_SHARED_LIBRARIES += libdrm_freedreno +endif + ifneq ($(filter $(intel_drivers), $(DRM_GPU_DRIVERS)),) LOCAL_SRC_FILES += gralloc_drm_intel.c LOCAL_C_INCLUDES += external/drm/intel diff --git a/gralloc_drm.c b/gralloc_drm.c index bd752cb..c53e556 100644 --- a/gralloc_drm.c +++ b/gralloc_drm.c @@ -73,6 +73,10 @@ init_drv_from_fd(int fd) ALOGI_IF(drv, "create pipe for driver %s", version->name); #endif +#ifdef ENABLE_FREEDRENO + if (!drv && !strcmp(version->name, "msm")) + drv = gralloc_drm_drv_create_for_freedreno(fd); +#endif #ifdef ENABLE_INTEL if (!drv && !strcmp(version->name, "i915")) { drv = gralloc_drm_drv_create_for_intel(fd); diff --git a/gralloc_drm_freedreno.c b/gralloc_drm_freedreno.c new file mode 100644 index 0000000..10b0939 --- /dev/null +++ b/gralloc_drm_freedreno.c @@ -0,0 +1,209 @@ +/* + * Copyright (C) 2011 Chia-I Wu + * Copyright (C) 2011 LunarG Inc. + * Copyright (C) 2014 Rob Clark + * + * Based on xf86-video-nouveau, which has + * + * Copyright © 2007 Red Hat, Inc. + * Copyright © 2008 Maarten Maathuis + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#define LOG_TAG "GRALLOC-FREEDRENO" + +#include +#include +#include +#include +#include + +#include "gralloc_drm.h" +#include "gralloc_drm_priv.h" + +#define MAX(a, b) (((a) > (b)) ? (a) : (b)) +#define ALIGN(val, align) (((val) + (align) - 1) & ~((align) - 1)) + +struct fd_info { + struct gralloc_drm_drv_t base; + + int fd; + struct fd_device *dev; +}; + +struct fd_buffer { + struct gralloc_drm_bo_t base; + + struct fd_bo *bo; +}; + +static struct fd_bo *alloc_bo(struct fd_info *info, + int width, int height, int cpp, int usage, int *pitch) +{ + struct fd_bo *bo = NULL; + int flags, size; + + /* TODO need a scanout flag if (usage & GRALLOC_USAGE_HW_FB).. */ + flags = DRM_FREEDRENO_GEM_CACHE_WCOMBINE; + + *pitch = ALIGN(width, 32) * cpp; + size = *pitch * height; + + return fd_bo_new(info->dev, size, flags); +} + +static struct gralloc_drm_bo_t * +fd_alloc(struct gralloc_drm_drv_t *drv, struct gralloc_drm_handle_t *handle) +{ + struct fd_info *info = (struct fd_info *) drv; + struct fd_buffer *fd_buf; + int cpp; + + cpp = gralloc_drm_get_bpp(handle->format); + if (!cpp) { + ALOGE("unrecognized format 0x%x", handle->format); + return NULL; + } + + fd_buf = calloc(1, sizeof(*fd_buf)); + if (!fd_buf) + return NULL; + + if (handle->name) { + fd_buf->bo = fd_bo_from_name(info->dev, handle->name); + if (!fd_buf->bo) { + ALOGE("failed to create fd bo from name %u", + handle->name); + free(fd_buf); + return NULL; + } + } + else { + int width, height, pitch; + + width = handle->width; + height = handle->height; + gralloc_drm_align_geometry(handle->format, &width, &height); + + fd_buf->bo = alloc_bo(info, width, height, + cpp, handle->usage, &pitch); + if (!fd_buf->bo) { + ALOGE("failed to allocate fd bo %dx%dx%d", + handle->width, handle->height, cpp); + free(fd_buf); + return NULL; + } + + if (fd_bo_get_name(fd_buf->bo, (uint32_t *) &handle->name)) { + ALOGE("failed to flink fd bo"); + fd_bo_del(fd_buf->bo); + free(fd_buf); + return NULL; + } + + handle->stride = pitch; + } + + if (handle->usage & GRALLOC_USAGE_HW_FB) + fd_buf->base.fb_handle = fd_bo_handle(fd_buf->bo); + + fd_buf->base.handle = handle; + + return &fd_buf->base; +} + +static void fd_free(struct gralloc_drm_drv_t *drv, + struct gralloc_drm_bo_t *bo) +{ + struct fd_buffer *fd_buf = (struct fd_buffer *) bo; + fd_bo_del(fd_buf->bo); + free(fd_buf); +} + +static int fd_map(struct gralloc_drm_drv_t *drv, + struct gralloc_drm_bo_t *bo, int x, int y, int w, int h, + int enable_write, void **addr) +{ + struct fd_buffer *fd_buf = (struct fd_buffer *) bo; + if (fd_bo_map(fd_buf->bo)) + return 0; + return -errno; +} + +static void fd_unmap(struct gralloc_drm_drv_t *drv, + struct gralloc_drm_bo_t *bo) +{ + // TODO should add fd_bo_unmap() to libdrm_freedreno someday.. +} + +static void fd_init_kms_features(struct gralloc_drm_drv_t *drv, + struct gralloc_drm_t *drm) +{ + struct fd_info *info = (struct fd_info *) drv; + + switch (drm->primary.fb_format) { + case HAL_PIXEL_FORMAT_BGRA_8888: + case HAL_PIXEL_FORMAT_RGB_565: + break; + default: + drm->primary.fb_format = HAL_PIXEL_FORMAT_BGRA_8888; + break; + } + + drm->mode_quirk_vmwgfx = 0; + drm->swap_mode = DRM_SWAP_FLIP; + drm->mode_sync_flip = 1; + drm->swap_interval = 1; + drm->vblank_secondary = 0; +} + +static void fd_destroy(struct gralloc_drm_drv_t *drv) +{ + struct fd_info *info = (struct fd_info *) drv; + fd_device_del(info->dev); + free(info); +} + +struct gralloc_drm_drv_t *gralloc_drm_drv_create_for_freedreno(int fd) +{ + struct fd_info *info; + int err; + + info = calloc(1, sizeof(*info)); + if (!info) + return NULL; + + info->fd = fd; + info->dev = fd_device_new_dup(info->fd); + if (!info->dev) { + ALOGE("failed to create fd device"); + free(info); + return NULL; + } + + info->base.destroy = fd_destroy; + info->base.init_kms_features = fd_init_kms_features; + info->base.alloc = fd_alloc; + info->base.free = fd_free; + info->base.map = fd_map; + info->base.unmap = fd_unmap; + + return &info->base; +} \ No newline at end of file diff --git a/gralloc_drm_pipe.c b/gralloc_drm_pipe.c index ec3e19d..1183ba1 100644 --- a/gralloc_drm_pipe.c +++ b/gralloc_drm_pipe.c @@ -368,6 +368,8 @@ static void pipe_destroy(struct gralloc_drm_drv_t *drv) FREE(pm); } +/* for freedreno */ +#include "freedreno/drm/freedreno_drm_public.h" /* for nouveau */ #include "nouveau/drm/nouveau_drm_public.h" /* for r300 */ @@ -387,6 +389,10 @@ static int pipe_init_screen(struct pipe_manager *pm) { struct pipe_screen *screen = NULL; +#ifdef ENABLE_PIPE_FREEDRENO + if (strcmp(pm->driver, "msm")) + screen = fd_drm_screen_create(pm->fd); +#endif #ifdef ENABLE_PIPE_NOUVEAU if (strcmp(pm->driver, "nouveau") == 0) screen = nouveau_drm_screen_create(pm->fd); @@ -520,6 +526,10 @@ static int pipe_find_driver(struct pipe_manager *pm, const char *name) driver = "vmwgfx"; err = 0; } + if (strcmp(name, "msm") == 0) { + driver = "msm"; + err = 0; + } } if (!err) diff --git a/gralloc_drm_priv.h b/gralloc_drm_priv.h index 1a36cc1..fd3b72e 100644 --- a/gralloc_drm_priv.h +++ b/gralloc_drm_priv.h @@ -197,6 +197,8 @@ struct gralloc_drm_bo_t { }; struct gralloc_drm_drv_t *gralloc_drm_drv_create_for_pipe(int fd, const char *name); + +struct gralloc_drm_drv_t *gralloc_drm_drv_create_for_freedreno(int fd); struct gralloc_drm_drv_t *gralloc_drm_drv_create_for_intel(int fd); struct gralloc_drm_drv_t *gralloc_drm_drv_create_for_radeon(int fd); struct gralloc_drm_drv_t *gralloc_drm_drv_create_for_nouveau(int fd); -- cgit v1.1