Git init
[framework/uifw/xorg/lib/libdrm.git] / tests / planetest / planetest.c
1 #include "config.h"
2
3 #include <assert.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <stdint.h>
7 #include <string.h>
8 #include <errno.h>
9 #include <getopt.h>
10
11 #include "xf86drm.h"
12 #include "xf86drmMode.h"
13 #include "libkms.h"
14 #include "exynos_drm.h"
15
16 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
17
18 drmModeRes *resources;
19 int fd;
20
21 struct connector {
22         uint32_t id;
23         char mode_str[64];
24         drmModeModeInfo *mode;
25         drmModeEncoder *encoder;
26         int crtc;
27         unsigned int fb_id[2], current_fb_id;
28         struct timeval start;
29
30         int swap_count;
31 };
32
33 struct fb_data {
34         struct kms_driver *kms;
35         struct kms_bo *bo;
36         unsigned int fb_id;
37 };
38
39 static void
40 connector_find_mode(struct connector *c)
41 {
42         drmModeConnector *connector;
43         int i, j;
44
45         /* First, find the connector & mode */
46         c->mode = NULL;
47         for (i = 0; i < resources->count_connectors; i++) {
48                 connector = drmModeGetConnector(fd, resources->connectors[i]);
49
50                 if (!connector) {
51                         fprintf(stderr, "could not get connector %i: %s\n",
52                                 resources->connectors[i], strerror(errno));
53                         drmModeFreeConnector(connector);
54                         continue;
55                 }
56
57                 if (!connector->count_modes) {
58                         drmModeFreeConnector(connector);
59                         continue;
60                 }
61
62                 if (connector->connector_id != c->id) {
63                         drmModeFreeConnector(connector);
64                         continue;
65                 }
66
67                 for (j = 0; j < connector->count_modes; j++) {
68                         c->mode = &connector->modes[j];
69                         if (!strcmp(c->mode->name, c->mode_str))
70                                 break;
71                 }
72
73                 /* Found it, break out */
74                 if (c->mode)
75                         break;
76
77                 drmModeFreeConnector(connector);
78         }
79
80         if (!c->mode) {
81                 fprintf(stderr, "failed to find mode \"%s\"\n", c->mode_str);
82                 return;
83         }
84
85         /* Now get the encoder */
86         for (i = 0; i < resources->count_encoders; i++) {
87                 c->encoder = drmModeGetEncoder(fd, resources->encoders[i]);
88
89                 if (!c->encoder) {
90                         fprintf(stderr, "could not get encoder %i: %s\n",
91                                 resources->encoders[i], strerror(errno));
92                         drmModeFreeEncoder(c->encoder);
93                         continue;
94                 }
95
96                 if (c->encoder->encoder_id  == connector->encoder_id)
97                         break;
98
99                 drmModeFreeEncoder(c->encoder);
100         }
101
102         if (c->crtc == -1)
103                 c->crtc = c->encoder->crtc_id;
104 }
105
106 static struct kms_bo *
107 allocate_buffer(struct kms_driver *kms,
108                 int width, int height, unsigned *stride)
109 {
110         struct kms_bo *bo;
111         unsigned bo_attribs[] = {
112                 KMS_WIDTH,   0,
113                 KMS_HEIGHT,  0,
114                 KMS_BO_TYPE, KMS_BO_TYPE_SCANOUT_X8R8G8B8,
115                 KMS_TERMINATE_PROP_LIST
116         };
117         int ret;
118
119         bo_attribs[1] = width;
120         bo_attribs[3] = height;
121
122         ret = kms_bo_create(kms, bo_attribs, &bo);
123         if (ret) {
124                 fprintf(stderr, "failed to alloc buffer: %s\n",
125                         strerror(-ret));
126                 return NULL;
127         }
128
129         ret = kms_bo_get_prop(bo, KMS_PITCH, stride);
130         if (ret) {
131                 fprintf(stderr, "failed to retreive buffer stride: %s\n",
132                         strerror(-ret));
133                 kms_bo_destroy(&bo);
134                 return NULL;
135         }
136
137         return bo;
138 }
139
140 static int
141 create_grey_buffer(struct kms_driver *kms,
142                    int width, int height, int *stride_out,
143                    struct kms_bo **bo_out, int color)
144 {
145         struct kms_bo *bo;
146         int size, ret;
147         unsigned stride;
148         void *virtual;
149
150         bo = allocate_buffer(kms, width, height, &stride);
151         if (!bo)
152                 return -1;
153
154         ret = kms_bo_map(bo, &virtual);
155         if (ret) {
156                 fprintf(stderr, "failed to map buffer: %s\n",
157                         strerror(-ret));
158                 kms_bo_destroy(&bo);
159                 return -1;
160         }
161
162         size = stride * height;
163         memset(virtual, color, size);
164         kms_bo_unmap(bo);
165
166         *bo_out = bo;
167         *stride_out = stride;
168
169         return 0;
170 }
171
172 static int
173 connector_find_plane(struct connector *c)
174 {
175         drmModePlaneRes *plane_resources;
176         drmModePlane *ovr;
177         uint32_t id = 0;
178         int i;
179
180         plane_resources = drmModeGetPlaneResources(fd);
181         if (!plane_resources) {
182                 fprintf(stderr, "drmModeGetPlaneResources failed: %s\n",
183                         strerror(errno));
184                 return 0;
185         }
186
187         for (i = 0; i < plane_resources->count_planes; i++) {
188                 ovr = drmModeGetPlane(fd, plane_resources->planes[i]);
189                 if (!ovr) {
190                         fprintf(stderr, "drmModeGetPlane failed: %s\n",
191                                 strerror(errno));
192                         continue;
193                 }
194
195                 if (ovr->possible_crtcs & (1<<i)) {
196                         id = ovr->plane_id;
197                         drmModeFreePlane(ovr);
198                         break;
199                 }
200                 drmModeFreePlane(ovr);
201         }
202
203         return id;
204 }
205
206 static int
207 connector_find_plane2(struct connector *c, unsigned int *plane_id)
208 {
209         drmModePlaneRes *plane_resources;
210         drmModePlane *ovr;
211         int i;
212
213         plane_resources = drmModeGetPlaneResources(fd);
214         if (!plane_resources) {
215                 fprintf(stderr, "drmModeGetPlaneResources failed: %s\n",
216                         strerror(errno));
217                 return -1;
218         }
219
220         for (i = 0; i < plane_resources->count_planes; i++) {
221                 plane_id[i] = 0;
222
223                 ovr = drmModeGetPlane(fd, plane_resources->planes[i]);
224                 if (!ovr) {
225                         fprintf(stderr, "drmModeGetPlane failed: %s\n",
226                                 strerror(errno));
227                         continue;
228                 }
229
230                 if (ovr->possible_crtcs & (1 << 0))
231                         plane_id[i] = ovr->plane_id;
232                 drmModeFreePlane(ovr);
233         }
234
235         return 0;
236 }
237
238 static struct fb_data *make_fb(int w, int h, int color)
239 {
240         struct fb_data *fb_data;
241         struct kms_driver *kms;
242         struct kms_bo *bo;
243         unsigned int fb_id;
244         unsigned handle;
245         int stride;
246         int err;
247
248         fb_data = malloc(sizeof(struct fb_data));
249         if (!fb_data)
250                 return NULL;
251
252         memset(fb_data, 0, sizeof(struct fb_data));
253
254         err = kms_create(fd, &kms);
255         if (err) {
256                 fprintf(stderr, "failed to create kms driver: %s\n",
257                         strerror(-err));
258                 goto err_alloc;
259         }
260
261         if (create_grey_buffer(kms, w, h, &stride, &bo, color))
262                 goto err_alloc;
263
264         kms_bo_get_prop(bo, KMS_HANDLE, &handle);
265         err = drmModeAddFB(fd, w, h, 32, 32, stride, handle, &fb_id);
266         if (err) {
267                 fprintf(stderr, "failed to add fb: %s\n", strerror(errno));
268                 goto err_alloc;
269         }
270
271         fb_data->fb_id = fb_id;
272         fb_data->kms = kms;
273         fb_data->bo = bo;
274
275         return fb_data;
276
277 err_alloc:
278         free(fb_data);
279         return NULL;
280 }
281
282 static int exynos_plane_set_zpos(int fd, unsigned int plane_id, int zpos)
283 {
284         struct drm_exynos_plane_set_zpos zpos_req;
285         int ret;
286
287         zpos_req.plane_id = plane_id;
288         zpos_req.zpos = zpos;
289
290         ret = ioctl(fd, DRM_IOCTL_EXYNOS_PLANE_SET_ZPOS, &zpos_req);
291         if (ret < 0) {
292                 fprintf(stderr, "failed to set plane zpos: %s\n",
293                                 strerror(-ret));
294                 return ret;
295         }
296
297         return 0;
298 }
299
300 #define PLANE_NR        5
301 static void planetest_start(int nr, int start_plane, int crtc, int connector)
302 {
303         struct connector c;
304         struct fb_data *fb_data[PLANE_NR];
305         unsigned int plane_id[PLANE_NR];
306         int height;
307         int width;
308         int x;
309         int y;
310         int i;
311         int ret;
312
313         c.id = connector;
314         c.crtc = crtc;
315
316         if (nr < 1 || nr > PLANE_NR) {
317                 fprintf(stderr, "wrong plane count\n");
318                 return;
319         }
320
321         if (start_plane < 0 || start_plane > (nr -1) ) {
322                 fprintf(stderr, "Wrong start plane\n");
323                 return;
324         }
325
326         connector_find_mode(&c);
327
328         if (c.mode == NULL) {
329                 fprintf(stderr, "mode is NULL\n");
330                 return;
331         }
332
333         width = c.mode->hdisplay;
334         height = c.mode->vdisplay;
335
336         width /= 8;
337         height /= 8;
338         x = width;
339         y = height;
340
341         ret = connector_find_plane2(&c, plane_id);
342         if (ret < 0)
343                 goto err;
344
345         for (i = start_plane; i < nr; i++) {
346                 if (!plane_id[i])
347                         continue;
348
349                 fb_data[i] = make_fb(width, height, 0x30 + 0x20 * i);
350                 if (!fb_data[i])
351                         return;
352
353                 if (exynos_plane_set_zpos(fd, plane_id[i], i))
354                         goto err;
355
356                 if (drmModeSetPlane(fd, plane_id[i], c.crtc, fb_data[i]->fb_id,
357                                         x, y, width, height,
358                                         0, 0, width, height)) {
359                         fprintf(stderr, "failed to enable plane: %s\n",
360                                         strerror(errno));
361                         goto err;
362                 }
363
364                 x += width - 30;
365                 y += height - 30;
366                 width += 40;
367                 height += 40;
368         }
369
370         getchar();
371
372 err:
373         for (i = start_plane; i < nr; i++) {
374                 if (fb_data[i]) {
375                         kms_bo_destroy(&fb_data[i]->bo);
376                         kms_destroy(&fb_data[i]->kms);
377                         free(fb_data[i]);
378                 }
379
380                 if (!plane_id[i])
381                         continue;
382
383                 if (drmModeSetPlane(fd, plane_id[i], c.crtc,
384                                 0, 0, 0, /* bufferId, crtc_x, crtc_y */
385                                 0, 0, /* crtc_w, crtc_h */
386                                 0, 0, 0, 0 /* src_XXX */)) {
387                         fprintf(stderr, "failed to enable plane: %s\n",
388                                         strerror(errno));
389                         goto err;
390                 }
391         }
392 }
393
394 static void help(void)
395 {
396         printf("Usage: ./planetest [OPTION]\n"
397                " [OPTION]\n"
398                " -s <connector_id>@<crtc_id>/<plane count>/<start_plane>\n"
399                " -h Usage\n"
400                "\n"
401                "Default: connector 11, crtc 3, plane_count 5, start_plane 1\n");
402         exit(0);
403 }
404
405 static char optstr[] = "hs:";
406
407 int main(int argc, char **argv)
408 {
409         char *modules[] = { "exynos-drm" };
410         int opt;
411         int i, connector_id, nr, start_plane;
412         uint32_t crtc_id;
413
414         // default option (LCD)
415         crtc_id = 3;
416         connector_id = 11;
417         nr = 5;
418         start_plane = 1;
419
420         /* parse args */
421         opterr = 0;
422         while ((opt = getopt(argc, argv, optstr)) != -1) {
423                 switch (opt) {
424                 case 's':
425                         if (sscanf(optarg, "%d@%d/%d/%d",
426                                    &connector_id,
427                                    &crtc_id,
428                                    &nr,
429                                    &start_plane) != 4) {
430                                 help();
431                                 break;
432                         }
433                         break;
434                 case 'h':
435                 default:
436                         help();
437                         break;
438                 }
439                 break;
440         }
441
442         for (i = 0; i < ARRAY_SIZE(modules); i++) {
443                 printf("trying to load module %s...", modules[i]);
444                 fd = drmOpen(modules[i], NULL);
445                 if (fd < 0) {
446                         printf("failed.\n");
447                 } else {
448                         printf("success.\n");
449                         break;
450                 }
451         }
452
453         resources = drmModeGetResources(fd);
454         if (!resources) {
455                 fprintf(stderr, "drmModeGetResources failed: %s\n",
456                         strerror(errno));
457                 drmClose(fd);
458                 return 1;
459         }
460
461         planetest_start(nr, start_plane, crtc_id, connector_id);
462
463         /* TODO */
464
465         drmModeFreeResources(resources);
466
467         return 0;
468 }