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