• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2018 NVIDIA Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20  * OTHER DEALINGS IN THE SOFTWARE.
21  */
22 
23 #include <errno.h>
24 #include <fcntl.h>
25 #include <stdio.h>
26 #include <string.h>
27 #include <unistd.h>
28 
29 #include "tegra.h"
30 
31 #include "host1x.h"
32 #include "vic.h"
33 
34 /* clear output image to red */
clear(struct vic * vic,struct drm_tegra_channel * channel,struct vic_image * output)35 static int clear(struct vic *vic, struct drm_tegra_channel *channel,
36                  struct vic_image *output)
37 {
38     struct drm_tegra_pushbuf *pushbuf;
39     struct drm_tegra_job *job;
40     uint32_t *ptr;
41     int err;
42 
43     err = drm_tegra_job_new(channel, &job);
44     if (err < 0) {
45         fprintf(stderr, "failed to create job: %s\n", strerror(-err));
46         return 1;
47     }
48 
49     err = drm_tegra_job_get_pushbuf(job, &pushbuf);
50     if (err < 0) {
51         fprintf(stderr, "failed to create push buffer: %s\n", strerror(-err));
52         return 1;
53     }
54 
55     err = vic_clear(vic, output, 1023, 1023, 0, 0);
56     if (err < 0) {
57         fprintf(stderr, "failed to clear surface: %s\n", strerror(-err));
58         return err;
59     }
60 
61     err = drm_tegra_pushbuf_begin(pushbuf, 32, &ptr);
62     if (err < 0) {
63         fprintf(stderr, "failed to prepare push buffer: %s\n", strerror(-err));
64         return err;
65     }
66 
67     err = vic->ops->execute(vic, pushbuf, &ptr, output, NULL, 0);
68     if (err < 0) {
69         fprintf(stderr, "failed to execute operation: %s\n", strerror(-err));
70         return err;
71     }
72 
73     err = drm_tegra_pushbuf_sync_cond(pushbuf, &ptr, vic->syncpt,
74                                       DRM_TEGRA_SYNC_COND_OP_DONE);
75     if (err < 0) {
76         fprintf(stderr, "failed to push syncpoint: %s\n", strerror(-err));
77         return err;
78     }
79 
80     err = drm_tegra_pushbuf_end(pushbuf, ptr);
81     if (err < 0) {
82         fprintf(stderr, "failed to update push buffer: %s\n", strerror(-err));
83         return err;
84     }
85 
86     err = drm_tegra_job_submit(job, NULL);
87     if (err < 0) {
88         fprintf(stderr, "failed to submit job: %s\n", strerror(-err));
89         return err;
90     }
91 
92     err = drm_tegra_job_wait(job, 1000000000);
93     if (err < 0) {
94         fprintf(stderr, "failed to wait for job: %s\n", strerror(-err));
95         return err;
96     }
97 
98     drm_tegra_job_free(job);
99 
100     return 0;
101 }
102 
103 /* fill bottom half of image to blue */
fill(struct vic * vic,struct drm_tegra_channel * channel,struct vic_image * output)104 static int fill(struct vic *vic, struct drm_tegra_channel *channel,
105                 struct vic_image *output)
106 {
107     struct drm_tegra_pushbuf *pushbuf;
108     struct drm_tegra_job *job;
109     uint32_t *ptr;
110     int err;
111 
112     err = drm_tegra_job_new(channel, &job);
113     if (err < 0) {
114         fprintf(stderr, "failed to create job: %s\n", strerror(-err));
115         return 1;
116     }
117 
118     err = drm_tegra_job_get_pushbuf(job, &pushbuf);
119     if (err < 0) {
120         fprintf(stderr, "failed to create push buffer: %s\n", strerror(-err));
121         return 1;
122     }
123 
124     err = drm_tegra_pushbuf_begin(pushbuf, 32, &ptr);
125     if (err < 0) {
126         fprintf(stderr, "failed to prepare push buffer: %s\n", strerror(-err));
127         return err;
128     }
129 
130     err = vic->ops->fill(vic, output, 0, output->height / 2, output->width - 1,
131                          output->height -1, 1023, 0, 0, 1023);
132     if (err < 0) {
133         fprintf(stderr, "failed to fill surface: %s\n", strerror(-err));
134         return err;
135     }
136 
137     err = vic->ops->execute(vic, pushbuf, &ptr, output, NULL, 0);
138     if (err < 0) {
139         fprintf(stderr, "failed to execute operation: %s\n", strerror(-err));
140         return err;
141     }
142 
143     err = drm_tegra_pushbuf_sync_cond(pushbuf, &ptr, vic->syncpt,
144                                       DRM_TEGRA_SYNC_COND_OP_DONE);
145     if (err < 0) {
146         fprintf(stderr, "failed to push syncpoint: %s\n", strerror(-err));
147         return err;
148     }
149 
150     err = drm_tegra_pushbuf_end(pushbuf, ptr);
151     if (err < 0) {
152         fprintf(stderr, "failed to update push buffer: %s\n", strerror(-err));
153         return err;
154     }
155 
156     err = drm_tegra_job_submit(job, NULL);
157     if (err < 0) {
158         fprintf(stderr, "failed to submit job: %s\n", strerror(-err));
159         return err;
160     }
161 
162     err = drm_tegra_job_wait(job, 1000000000);
163     if (err < 0) {
164         fprintf(stderr, "failed to wait for job: %s\n", strerror(-err));
165         return err;
166     }
167 
168     drm_tegra_job_free(job);
169 
170     return 0;
171 }
172 
173 /* blit image */
blit(struct vic * vic,struct drm_tegra_channel * channel,struct vic_image * output,struct vic_image * input)174 static int blit(struct vic *vic, struct drm_tegra_channel *channel,
175                 struct vic_image *output, struct vic_image *input)
176 {
177     struct drm_tegra_pushbuf *pushbuf;
178     struct drm_tegra_job *job;
179     uint32_t *ptr;
180     int err;
181 
182     err = drm_tegra_job_new(channel, &job);
183     if (err < 0) {
184         fprintf(stderr, "failed to create job: %s\n", strerror(-err));
185         return 1;
186     }
187 
188     err = drm_tegra_job_get_pushbuf(job, &pushbuf);
189     if (err < 0) {
190         fprintf(stderr, "failed to create push buffer: %s\n", strerror(-err));
191         return 1;
192     }
193 
194     err = drm_tegra_pushbuf_begin(pushbuf, 32, &ptr);
195     if (err < 0) {
196         fprintf(stderr, "failed to prepare push buffer: %s\n", strerror(-err));
197         return err;
198     }
199 
200     err = vic->ops->blit(vic, output, input);
201     if (err < 0) {
202         fprintf(stderr, "failed to blit surface: %s\n", strerror(-err));
203         return err;
204     }
205 
206     err = vic->ops->execute(vic, pushbuf, &ptr, output, &input, 1);
207     if (err < 0) {
208         fprintf(stderr, "failed to execute operation: %s\n", strerror(-err));
209         return err;
210     }
211 
212     err = drm_tegra_pushbuf_sync_cond(pushbuf, &ptr, vic->syncpt,
213                                       DRM_TEGRA_SYNC_COND_OP_DONE);
214     if (err < 0) {
215         fprintf(stderr, "failed to push syncpoint: %s\n", strerror(-err));
216         return err;
217     }
218 
219     err = drm_tegra_pushbuf_end(pushbuf, ptr);
220     if (err < 0) {
221         fprintf(stderr, "failed to update push buffer: %s\n", strerror(-err));
222         return err;
223     }
224 
225     err = drm_tegra_job_submit(job, NULL);
226     if (err < 0) {
227         fprintf(stderr, "failed to submit job: %s\n", strerror(-err));
228         return err;
229     }
230 
231     err = drm_tegra_job_wait(job, 1000000000);
232     if (err < 0) {
233         fprintf(stderr, "failed to wait for job: %s\n", strerror(-err));
234         return err;
235     }
236 
237     drm_tegra_job_free(job);
238 
239     return 0;
240 }
241 
main(int argc,char * argv[])242 int main(int argc, char *argv[])
243 {
244     const unsigned int format = VIC_PIXEL_FORMAT_A8R8G8B8;
245     const unsigned int kind = VIC_BLK_KIND_PITCH;
246     const unsigned int width = 16, height = 16;
247     const char *device = "/dev/dri/renderD128";
248     struct drm_tegra_channel *channel;
249     struct vic_image *input, *output;
250     struct drm_tegra *drm;
251     unsigned int version;
252     struct vic *vic;
253     int fd, err;
254 
255     if (argc > 1)
256         device = argv[1];
257 
258     fd = open(device, O_RDWR);
259     if (fd < 0) {
260         fprintf(stderr, "open() failed: %s\n", strerror(errno));
261         return 1;
262     }
263 
264     err = drm_tegra_new(fd, &drm);
265     if (err < 0) {
266         fprintf(stderr, "failed to open Tegra device: %s\n", strerror(-err));
267         close(fd);
268         return 1;
269     }
270 
271     err = drm_tegra_channel_open(drm, DRM_TEGRA_VIC, &channel);
272     if (err < 0) {
273         fprintf(stderr, "failed to open channel to VIC: %s\n", strerror(-err));
274         return 1;
275     }
276 
277     version = drm_tegra_channel_get_version(channel);
278     printf("version: %08x\n", version);
279 
280     err = vic_new(drm, channel, &vic);
281     if (err < 0) {
282         fprintf(stderr, "failed to create VIC: %s\n", strerror(-err));
283         return 1;
284     }
285 
286     err = vic_image_new(vic, width, height, format, kind, DRM_TEGRA_CHANNEL_MAP_READ_WRITE,
287                         &input);
288     if (err < 0) {
289         fprintf(stderr, "failed to create input image: %d\n", err);
290         return 1;
291     }
292 
293     err = vic_image_new(vic, width, height, format, kind, DRM_TEGRA_CHANNEL_MAP_READ_WRITE,
294                         &output);
295     if (err < 0) {
296         fprintf(stderr, "failed to create output image: %d\n", err);
297         return 1;
298     }
299 
300     err = clear(vic, channel, input);
301     if (err < 0) {
302         fprintf(stderr, "failed to clear image: %s\n", strerror(-err));
303         return 1;
304     }
305 
306     err = fill(vic, channel, input);
307     if (err < 0) {
308         fprintf(stderr, "failed to fill rectangle: %s\n", strerror(-err));
309         return 1;
310     }
311 
312     err = blit(vic, channel, output, input);
313     if (err < 0) {
314         fprintf(stderr, "failed to blit image: %s\n", strerror(-err));
315         return 1;
316     }
317 
318     printf("input: %ux%u\n", input->width, input->height);
319     vic_image_dump(input, stdout);
320 
321     printf("output: %ux%u\n", output->width, output->height);
322     vic_image_dump(output, stdout);
323 
324     vic_image_free(output);
325     vic_image_free(input);
326 
327     vic_free(vic);
328     drm_tegra_channel_close(channel);
329     drm_tegra_close(drm);
330     close(fd);
331 
332     return 0;
333 }
334