Home | History | Annotate | Download | only in drm_gralloc
      1 #define LOG_TAG "GRALLOC-ROCKCHIP"
      2 
      3 #include <cutils/log.h>
      4 #include <stdlib.h>
      5 #include <errno.h>
      6 #include <drm.h>
      7 #include <rockchip/rockchip_drmif.h>
      8 
      9 #include "gralloc_drm.h"
     10 #include "gralloc_drm_priv.h"
     11 
     12 #define UNUSED(...) (void)(__VA_ARGS__)
     13 
     14 struct rockchip_info {
     15 	struct gralloc_drm_drv_t base;
     16 
     17 	struct rockchip_device *rockchip;
     18 	int fd;
     19 };
     20 
     21 struct rockchip_buffer {
     22 	struct gralloc_drm_bo_t base;
     23 
     24 	struct rockchip_bo *bo;
     25 };
     26 
     27 static void drm_gem_rockchip_destroy(struct gralloc_drm_drv_t *drv)
     28 {
     29 	struct rockchip_info *info = (struct rockchip_info *)drv;
     30 
     31 	if (info->rockchip)
     32 		rockchip_device_destroy(info->rockchip);
     33 	free(info);
     34 }
     35 
     36 static struct gralloc_drm_bo_t *drm_gem_rockchip_alloc(
     37 		struct gralloc_drm_drv_t *drv,
     38 		struct gralloc_drm_handle_t *handle)
     39 {
     40 	struct rockchip_info *info = (struct rockchip_info *)drv;
     41 	struct rockchip_buffer *buf;
     42 	struct drm_gem_close args;
     43 	int ret, cpp, pitch, aligned_width, aligned_height;
     44 	uint32_t size, gem_handle;
     45 
     46 	buf = calloc(1, sizeof(*buf));
     47 	if (!buf) {
     48 		ALOGE("Failed to allocate buffer wrapper\n");
     49 		return NULL;
     50 	}
     51 
     52 	cpp = gralloc_drm_get_bpp(handle->format);
     53 	if (!cpp) {
     54 		ALOGE("unrecognized format 0x%x", handle->format);
     55 		return NULL;
     56 	}
     57 
     58 	aligned_width = handle->width;
     59 	aligned_height = handle->height;
     60 	gralloc_drm_align_geometry(handle->format,
     61 			&aligned_width, &aligned_height);
     62 
     63 	/* TODO: We need to sort out alignment */
     64 	pitch = ALIGN(aligned_width * cpp, 64);
     65 	size = aligned_height * pitch;
     66 
     67 	if (handle->format == HAL_PIXEL_FORMAT_YCbCr_420_888) {
     68 		/*
     69 		 * WAR for H264 decoder requiring additional space
     70 		 * at the end of destination buffers.
     71 		 */
     72 		uint32_t w_mbs, h_mbs;
     73 
     74 		w_mbs = ALIGN(handle->width, 16) / 16;
     75 		h_mbs = ALIGN(handle->height, 16) / 16;
     76 		size += 64 * w_mbs * h_mbs;
     77 	}
     78 
     79 	if (handle->prime_fd >= 0) {
     80 		ret = drmPrimeFDToHandle(info->fd, handle->prime_fd,
     81 			&gem_handle);
     82 		if (ret) {
     83 			char *c = NULL;
     84 			ALOGE("failed to convert prime fd to handle %d ret=%d",
     85 				handle->prime_fd, ret);
     86 			*c = 0;
     87 			goto err;
     88 		}
     89 		ALOGV("Got handle %d for fd %d\n", gem_handle, handle->prime_fd);
     90 
     91 		buf->bo = rockchip_bo_from_handle(info->rockchip, gem_handle,
     92 			0, size);
     93 		if (!buf->bo) {
     94 			ALOGE("failed to wrap bo handle=%d size=%d\n",
     95 				gem_handle, size);
     96 
     97 			memset(&args, 0, sizeof(args));
     98 			args.handle = gem_handle;
     99 			drmIoctl(info->fd, DRM_IOCTL_GEM_CLOSE, &args);
    100 			return NULL;
    101 		}
    102 	} else {
    103 		buf->bo = rockchip_bo_create(info->rockchip, size, 0);
    104 		if (!buf->bo) {
    105 			ALOGE("failed to allocate bo %dx%dx%dx%d\n",
    106 				handle->height, pitch, cpp, size);
    107 			goto err;
    108 		}
    109 
    110 		gem_handle = rockchip_bo_handle(buf->bo);
    111 		ret = drmPrimeHandleToFD(info->fd, gem_handle, 0,
    112 			&handle->prime_fd);
    113 		ALOGV("Got fd %d for handle %d\n", handle->prime_fd, gem_handle);
    114 		if (ret) {
    115 			ALOGE("failed to get prime fd %d", ret);
    116 			goto err_unref;
    117 		}
    118 
    119 		buf->base.fb_handle = gem_handle;
    120 	}
    121 
    122 	handle->name = 0;
    123 	handle->stride = pitch;
    124 	buf->base.handle = handle;
    125 
    126 	return &buf->base;
    127 
    128 err_unref:
    129 	rockchip_bo_destroy(buf->bo);
    130 err:
    131 	free(buf);
    132 	return NULL;
    133 }
    134 
    135 static void drm_gem_rockchip_free(struct gralloc_drm_drv_t *drv,
    136 		struct gralloc_drm_bo_t *bo)
    137 {
    138 	struct rockchip_buffer *buf = (struct rockchip_buffer *)bo;
    139 
    140 	UNUSED(drv);
    141 
    142 	if (bo->handle && bo->handle->prime_fd)
    143 		close(bo->handle->prime_fd);
    144 
    145 	/* TODO: Is destroy correct here? */
    146 	rockchip_bo_destroy(buf->bo);
    147 	free(buf);
    148 }
    149 
    150 static int drm_gem_rockchip_map(struct gralloc_drm_drv_t *drv,
    151 		struct gralloc_drm_bo_t *bo, int x, int y, int w, int h,
    152 		int enable_write, void **addr)
    153 {
    154 	struct rockchip_buffer *buf = (struct rockchip_buffer *)bo;
    155 
    156 	UNUSED(drv, x, y, w, h, enable_write);
    157 
    158 	*addr = rockchip_bo_map(buf->bo);
    159 	if (!*addr) {
    160 		ALOGE("failed to map bo\n");
    161 		return -1;
    162 	}
    163 
    164 	return 0;
    165 }
    166 
    167 static void drm_gem_rockchip_unmap(struct gralloc_drm_drv_t *drv,
    168 		struct gralloc_drm_bo_t *bo)
    169 {
    170 	UNUSED(drv, bo);
    171 }
    172 
    173 struct gralloc_drm_drv_t *gralloc_drm_drv_create_for_rockchip(int fd)
    174 {
    175 	struct rockchip_info *info;
    176 	int ret;
    177 
    178 	info = calloc(1, sizeof(*info));
    179 	if (!info) {
    180 		ALOGE("Failed to allocate rockchip gralloc device\n");
    181 		return NULL;
    182 	}
    183 
    184 	info->rockchip = rockchip_device_create(fd);
    185 	if (!info->rockchip) {
    186 		ALOGE("Failed to create new rockchip instance\n");
    187 		free(info);
    188 		return NULL;
    189 	}
    190 
    191 	info->fd = fd;
    192 	info->base.destroy = drm_gem_rockchip_destroy;
    193 	info->base.alloc = drm_gem_rockchip_alloc;
    194 	info->base.free = drm_gem_rockchip_free;
    195 	info->base.map = drm_gem_rockchip_map;
    196 	info->base.unmap = drm_gem_rockchip_unmap;
    197 
    198 	return &info->base;
    199 }
    200