Home | History | Annotate | Download | only in planetest
      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 #include <sys/types.h>
      4 #include <sys/stat.h>
      5 #include <sys/mman.h>
      6 #include <fcntl.h>
      7 #include <errno.h>
      8 
      9 #include <xf86drm.h>
     10 #include <xf86drmMode.h>
     11 #include <drm_fourcc.h>
     12 
     13 #include "bo.h"
     14 #include "dev.h"
     15 
     16 void fill_bo(struct sp_bo *bo, uint8_t a, uint8_t r, uint8_t g, uint8_t b)
     17 {
     18 	draw_rect(bo, 0, 0, bo->width, bo->height, a, r, g, b);
     19 }
     20 
     21 void draw_rect(struct sp_bo *bo, uint32_t x, uint32_t y, uint32_t width,
     22 		uint32_t height, uint8_t a, uint8_t r, uint8_t g, uint8_t b)
     23 {
     24 	uint32_t i, j, xmax = x + width, ymax = y + height;
     25 
     26 	if (xmax > bo->width)
     27 		xmax = bo->width;
     28 	if (ymax > bo->height)
     29 		ymax = bo->height;
     30 
     31 	for (i = y; i < ymax; i++) {
     32 		uint8_t *row = bo->map_addr + i * bo->pitch;
     33 
     34 		for (j = x; j < xmax; j++) {
     35 			uint8_t *pixel = row + j * 4;
     36 
     37 			if (bo->format == DRM_FORMAT_ARGB8888 ||
     38 			    bo->format == DRM_FORMAT_XRGB8888)
     39 			{
     40 				pixel[0] = b;
     41 				pixel[1] = g;
     42 				pixel[2] = r;
     43 				pixel[3] = a;
     44 			} else if (bo->format == DRM_FORMAT_RGBA8888) {
     45 				pixel[0] = r;
     46 				pixel[1] = g;
     47 				pixel[2] = b;
     48 				pixel[3] = a;
     49 			}
     50 		}
     51 	}
     52 }
     53 
     54 static int add_fb_sp_bo(struct sp_bo *bo, uint32_t format)
     55 {
     56 	int ret;
     57 	uint32_t handles[4], pitches[4], offsets[4];
     58 
     59 	handles[0] = bo->handle;
     60 	pitches[0] = bo->pitch;
     61 	offsets[0] = 0;
     62 
     63 	ret = drmModeAddFB2(bo->dev->fd, bo->width, bo->height,
     64 			format, handles, pitches, offsets,
     65 			&bo->fb_id, bo->flags);
     66 	if (ret) {
     67 		printf("failed to create fb ret=%d\n", ret);
     68 		return ret;
     69 	}
     70 	return 0;
     71 }
     72 
     73 static int map_sp_bo(struct sp_bo *bo)
     74 {
     75 	int ret;
     76 	struct drm_mode_map_dumb md;
     77 
     78 	if (bo->map_addr)
     79 		return 0;
     80 
     81 	md.handle = bo->handle;
     82 	ret = drmIoctl(bo->dev->fd, DRM_IOCTL_MODE_MAP_DUMB, &md);
     83 	if (ret) {
     84 		printf("failed to map sp_bo ret=%d\n", ret);
     85 		return ret;
     86 	}
     87 
     88 	bo->map_addr = mmap(NULL, bo->size, PROT_READ | PROT_WRITE, MAP_SHARED,
     89 				bo->dev->fd, md.offset);
     90 	if (bo->map_addr == MAP_FAILED) {
     91 		printf("failed to map bo ret=%d\n", -errno);
     92 		return -errno;
     93 	}
     94 	return 0;
     95 }
     96 
     97 struct sp_bo *create_sp_bo(struct sp_dev *dev, uint32_t width, uint32_t height,
     98 		uint32_t depth, uint32_t bpp, uint32_t format, uint32_t flags)
     99 {
    100 	int ret;
    101 	struct drm_mode_create_dumb cd;
    102 	struct sp_bo *bo;
    103 
    104 	bo = calloc(1, sizeof(*bo));
    105 	if (!bo)
    106 		return NULL;
    107 
    108 	cd.height = height;
    109 	cd.width = width;
    110 	cd.bpp = bpp;
    111 	cd.flags = flags;
    112 
    113 	ret = drmIoctl(dev->fd, DRM_IOCTL_MODE_CREATE_DUMB, &cd);
    114 	if (ret) {
    115 		printf("failed to create sp_bo %d\n", ret);
    116 		goto err;
    117 	}
    118 
    119 	bo->dev = dev;
    120 	bo->width = width;
    121 	bo->height = height;
    122 	bo->depth = depth;
    123 	bo->bpp = bpp;
    124 	bo->format = format;
    125 	bo->flags = flags;
    126 
    127 	bo->handle = cd.handle;
    128 	bo->pitch = cd.pitch;
    129 	bo->size = cd.size;
    130 
    131 	ret = add_fb_sp_bo(bo, format);
    132 	if (ret) {
    133 		printf("failed to add fb ret=%d\n", ret);
    134 		goto err;
    135 	}
    136 
    137 	ret = map_sp_bo(bo);
    138 	if (ret) {
    139 		printf("failed to map bo ret=%d\n", ret);
    140 		goto err;
    141 	}
    142 
    143 	return bo;
    144 
    145 err:
    146 	free_sp_bo(bo);
    147 	return NULL;
    148 }
    149 
    150 void free_sp_bo(struct sp_bo *bo)
    151 {
    152 	int ret;
    153 	struct drm_mode_destroy_dumb dd;
    154 
    155 	if (!bo)
    156 		return;
    157 
    158 	if (bo->map_addr)
    159 		munmap(bo->map_addr, bo->size);
    160 
    161 	if (bo->fb_id) {
    162 		ret = drmModeRmFB(bo->dev->fd, bo->fb_id);
    163 		if (ret)
    164 			printf("Failed to rmfb ret=%d!\n", ret);
    165 	}
    166 
    167 	if (bo->handle) {
    168 		dd.handle = bo->handle;
    169 		ret = drmIoctl(bo->dev->fd, DRM_IOCTL_MODE_DESTROY_DUMB, &dd);
    170 		if (ret)
    171 			printf("Failed to destroy buffer ret=%d\n", ret);
    172 	}
    173 
    174 	free(bo);
    175 }
    176