xref: /OK3568_Linux_fs/external/camera_engine_rkaiq/rkisp_demo/demo/drmDsp/bo.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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