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