OSDN Git Service

freedreno: completely untested initial support
authorRob Clark <robdclark@gmail.com>
Fri, 1 Aug 2014 19:02:02 +0000 (20:02 +0100)
committerChih-Wei Huang <cwhuang@linux.org.tw>
Fri, 16 Jan 2015 12:22:22 +0000 (20:22 +0800)
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 <emil.l.velikov@gmail.com>
Android.mk
gralloc_drm.c
gralloc_drm_freedreno.c [new file with mode: 0644]
gralloc_drm_pipe.c
gralloc_drm_priv.h

index c701b6e..116225a 100644 (file)
@@ -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
index bd752cb..c53e556 100644 (file)
@@ -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 (file)
index 0000000..10b0939
--- /dev/null
@@ -0,0 +1,209 @@
+/*
+ * Copyright (C) 2011 Chia-I Wu <olvaffe@gmail.com>
+ * Copyright (C) 2011 LunarG Inc.
+ * Copyright (C) 2014 Rob Clark <robclark@freedesktop.org>
+ *
+ * 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 <cutils/log.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <drm.h>
+#include <freedreno_drmif.h>
+
+#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
index ec3e19d..1183ba1 100644 (file)
@@ -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)
index 1a36cc1..fd3b72e 100644 (file)
@@ -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);