3867a0b83e9e8e8436b0c82c7fd8b7e31e3f9415
[platform/upstream/intel-gpu-tools.git] / tests / kms_render.c
1 /*
2  * Permission is hereby granted, free of charge, to any person obtaining a
3  * copy of this software and associated documentation files (the "Software"),
4  * to deal in the Software without restriction, including without limitation
5  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
6  * and/or sell copies of the Software, and to permit persons to whom the
7  * Software is furnished to do so, subject to the following conditions:
8  *
9  * The above copyright notice and this permission notice shall be included in
10  * all copies or substantial portions of the Software.
11  *
12  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
13  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
14  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
15  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
16  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
17  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
18  * IN THE SOFTWARE.
19  *
20  * Authors:
21  *    Imre Deak <imre.deak@intel.com>
22  */
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #include <assert.h>
28 #include <cairo.h>
29 #include <errno.h>
30 #include <stdint.h>
31 #include <unistd.h>
32 #include <sys/time.h>
33
34 #include "drmtest.h"
35 #include "testdisplay.h"
36 #include "intel_bufmgr.h"
37 #include "intel_batchbuffer.h"
38 #include "intel_gpu_tools.h"
39
40 drmModeRes *resources;
41 int drm_fd;
42 static drm_intel_bufmgr *bufmgr;
43 struct intel_batchbuffer *batch;
44 uint32_t devid;
45
46 enum test_flags {
47         TEST_DIRECT_RENDER      = 0x01,
48         TEST_GPU_BLIT           = 0x02,
49 };
50
51 static int paint_fb(struct kmstest_fb *fb, const char *test_name,
52                     const char *mode_format_str, const char *cconf_str)
53 {
54         cairo_t *cr;
55
56         cr = kmstest_get_cairo_ctx(drm_fd, fb);
57         if (!cr)
58                 return -1;
59
60         kmstest_paint_color_gradient(cr, 0, 0, fb->width, fb->height, 1, 1, 1);
61         kmstest_paint_test_pattern(cr, fb->width, fb->height);
62
63         cairo_select_font_face(cr, "Helvetica", CAIRO_FONT_SLANT_NORMAL,
64                                CAIRO_FONT_WEIGHT_NORMAL);
65         cairo_move_to(cr, fb->width / 2, fb->height / 2);
66         cairo_set_font_size(cr, 36);
67         kmstest_cairo_printf_line(cr, align_hcenter, 10, "%s", test_name);
68         kmstest_cairo_printf_line(cr, align_hcenter, 10, "%s", mode_format_str);
69         kmstest_cairo_printf_line(cr, align_hcenter, 10, "%s", cconf_str);
70
71         return 0;
72 }
73
74 static void gpu_blit(struct kmstest_fb *dst_fb, struct kmstest_fb *src_fb)
75 {
76         drm_intel_bo *dst_bo;
77         drm_intel_bo *src_bo;
78
79         dst_bo = gem_handle_to_libdrm_bo(bufmgr, drm_fd, "destination",
80                                          dst_fb->gem_handle);
81         assert(dst_bo);
82         src_bo = gem_handle_to_libdrm_bo(bufmgr, drm_fd, "source",
83                                          src_fb->gem_handle);
84         assert(src_bo);
85
86         intel_copy_bo(batch, dst_bo, src_bo, src_fb->width, src_fb->height);
87         intel_batchbuffer_flush(batch);
88         gem_quiescent_gpu(drm_fd);
89
90         drm_intel_bo_unreference(src_bo);
91         drm_intel_bo_unreference(dst_bo);
92 }
93
94 static int test_format(const char *test_name,
95                        struct kmstest_connector_config *cconf,
96                        drmModeModeInfo *mode, uint32_t format,
97                        enum test_flags flags)
98 {
99         int width;
100         int height;
101         struct kmstest_fb fb[2];
102         char *mode_format_str;
103         char *cconf_str;
104         int ret;
105
106         ret = asprintf(&mode_format_str, "%s @ %dHz / %s",
107                  mode->name, mode->vrefresh, kmstest_format_str(format));
108         assert(ret > 0);
109         ret = asprintf(&cconf_str, "pipe %s, encoder %s, connector %s",
110                        kmstest_pipe_str(cconf->pipe),
111                        kmstest_encoder_type_str(cconf->encoder->encoder_type),
112                        kmstest_connector_type_str(cconf->connector->connector_type));
113         assert(ret > 0);
114
115         printf("Beginning test %s with %s on %s\n",
116                 test_name, mode_format_str, cconf_str);
117
118         width = mode->hdisplay;
119         height = mode->vdisplay;
120
121         if (!kmstest_create_fb2(drm_fd, width, height, format, false, &fb[0]))
122                 goto err1;
123
124         if (!kmstest_create_fb2(drm_fd, width, height, format, false, &fb[1]))
125                 goto err2;
126
127         if (drmModeSetCrtc(drm_fd, cconf->crtc->crtc_id, fb[0].fb_id,
128                                  0, 0, &cconf->connector->connector_id, 1,
129                                  mode))
130                 goto err2;
131         do_or_die(drmModePageFlip(drm_fd, cconf->crtc->crtc_id, fb[0].fb_id,
132                                   0, NULL));
133         sleep(2);
134
135         if (flags & TEST_DIRECT_RENDER) {
136                 paint_fb(&fb[0], test_name, mode_format_str, cconf_str);
137         } else if (flags & TEST_GPU_BLIT) {
138                 paint_fb(&fb[1], test_name, mode_format_str, cconf_str);
139                 gpu_blit(&fb[0], &fb[1]);
140         }
141         sleep(5);
142
143         printf("Test %s with %s on %s: PASSED\n",
144                 test_name, mode_format_str, cconf_str);
145         free(mode_format_str);
146         free(cconf_str);
147
148         kmstest_remove_fb(drm_fd, &fb[1]);
149         kmstest_remove_fb(drm_fd, &fb[0]);
150
151         return 0;
152
153 err2:
154         kmstest_remove_fb(drm_fd, &fb[0]);
155 err1:
156         printf("Test %s with %s on %s: SKIPPED\n",
157                 test_name, mode_format_str, cconf_str);
158         free(mode_format_str);
159         free(cconf_str);
160
161         return -1;
162 }
163
164 static void test_connector(const char *test_name,
165                            struct kmstest_connector_config *cconf,
166                            enum test_flags flags)
167 {
168         const uint32_t *formats;
169         int format_count;
170         int i;
171
172         kmstest_get_all_formats(&formats, &format_count);
173         for (i = 0; i < cconf->connector->count_modes; i++) {
174                 int j;
175
176                 for (j = 0; j < format_count; j++)
177                         test_format(test_name,
178                                     cconf, &cconf->connector->modes[i],
179                                     formats[j], flags);
180         }
181 }
182
183 static int run_test(const char *test_name, enum test_flags flags)
184 {
185         int i;
186
187         resources = drmModeGetResources(drm_fd);
188         assert(resources);
189
190         /* Find any connected displays */
191         for (i = 0; i < resources->count_connectors; i++) {
192                 uint32_t connector_id;
193                 int j;
194
195                 connector_id = resources->connectors[i];
196                 for (j = 0; j < resources->count_crtcs; j++) {
197                         struct kmstest_connector_config cconf;
198                         int ret;
199
200                         ret = kmstest_get_connector_config(drm_fd, connector_id,
201                                                            1 << j, &cconf);
202                         if (ret < 0)
203                                 continue;
204
205                         test_connector(test_name, &cconf, flags);
206
207                         kmstest_free_connector_config(&cconf);
208                 }
209         }
210
211         drmModeFreeResources(resources);
212
213         return 1;
214 }
215
216 int main(int argc, char **argv)
217 {
218         struct {
219                 enum test_flags flags;
220                 const char *name;
221         } tests[] = {
222                 { TEST_DIRECT_RENDER,   "direct-render" },
223                 { TEST_GPU_BLIT,        "gpu-blit" },
224         };
225         int i;
226
227         drmtest_subtest_init(argc, argv);
228
229         if (!drmtest_only_list_subtests()) {
230                 drm_fd = drm_open_any();
231
232                 bufmgr = drm_intel_bufmgr_gem_init(drm_fd, 4096);
233                 devid = intel_get_drm_devid(drm_fd);
234                 batch = intel_batchbuffer_alloc(bufmgr, devid);
235
236                 do_or_die(drmtest_set_vt_graphics_mode());
237         }
238
239         for (i = 0; i < ARRAY_SIZE(tests); i++) {
240                 if (drmtest_run_subtest(tests[i].name))
241                         run_test(tests[i].name, tests[i].flags);
242         }
243
244         if (!drmtest_only_list_subtests())
245                 close(drm_fd);
246
247         return 0;
248 }