xref: /third_party/libdrm/tests/tegra/drm-test.c (revision d722e3fb)
1d722e3fbSopenharmony_ci/*
2d722e3fbSopenharmony_ci * Copyright © 2014 NVIDIA Corporation
3d722e3fbSopenharmony_ci *
4d722e3fbSopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
5d722e3fbSopenharmony_ci * copy of this software and associated documentation files (the "Software"),
6d722e3fbSopenharmony_ci * to deal in the Software without restriction, including without limitation
7d722e3fbSopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8d722e3fbSopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
9d722e3fbSopenharmony_ci * Software is furnished to do so, subject to the following conditions:
10d722e3fbSopenharmony_ci *
11d722e3fbSopenharmony_ci * The above copyright notice and this permission notice shall be included in
12d722e3fbSopenharmony_ci * all copies or substantial portions of the Software.
13d722e3fbSopenharmony_ci *
14d722e3fbSopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15d722e3fbSopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16d722e3fbSopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17d722e3fbSopenharmony_ci * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18d722e3fbSopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19d722e3fbSopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20d722e3fbSopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE.
21d722e3fbSopenharmony_ci */
22d722e3fbSopenharmony_ci
23d722e3fbSopenharmony_ci#ifdef HAVE_CONFIG_H
24d722e3fbSopenharmony_ci#  include "config.h"
25d722e3fbSopenharmony_ci#endif
26d722e3fbSopenharmony_ci
27d722e3fbSopenharmony_ci#include <errno.h>
28d722e3fbSopenharmony_ci#include <fcntl.h>
29d722e3fbSopenharmony_ci#include <stdbool.h>
30d722e3fbSopenharmony_ci#include <stdint.h>
31d722e3fbSopenharmony_ci#include <stdio.h>
32d722e3fbSopenharmony_ci#include <stdlib.h>
33d722e3fbSopenharmony_ci#include <string.h>
34d722e3fbSopenharmony_ci#include <unistd.h>
35d722e3fbSopenharmony_ci
36d722e3fbSopenharmony_ci#include <sys/ioctl.h>
37d722e3fbSopenharmony_ci
38d722e3fbSopenharmony_ci#include "xf86drm.h"
39d722e3fbSopenharmony_ci#include "xf86drmMode.h"
40d722e3fbSopenharmony_ci#include "drm_fourcc.h"
41d722e3fbSopenharmony_ci
42d722e3fbSopenharmony_ci#include "drm-test.h"
43d722e3fbSopenharmony_ci
44d722e3fbSopenharmony_cistatic int drm_screen_probe_connector(struct drm_screen *screen,
45d722e3fbSopenharmony_ci                                      drmModeConnectorPtr connector)
46d722e3fbSopenharmony_ci{
47d722e3fbSopenharmony_ci    drmModeEncoderPtr encoder;
48d722e3fbSopenharmony_ci    drmModeCrtcPtr crtc;
49d722e3fbSopenharmony_ci    drmModeFBPtr fb;
50d722e3fbSopenharmony_ci
51d722e3fbSopenharmony_ci    encoder = drmModeGetEncoder(screen->fd, connector->encoder_id);
52d722e3fbSopenharmony_ci    if (!encoder)
53d722e3fbSopenharmony_ci        return -ENODEV;
54d722e3fbSopenharmony_ci
55d722e3fbSopenharmony_ci    crtc = drmModeGetCrtc(screen->fd, encoder->crtc_id);
56d722e3fbSopenharmony_ci    if (!crtc) {
57d722e3fbSopenharmony_ci        drmModeFreeEncoder(encoder);
58d722e3fbSopenharmony_ci        return -ENODEV;
59d722e3fbSopenharmony_ci    }
60d722e3fbSopenharmony_ci
61d722e3fbSopenharmony_ci    screen->old_fb = crtc->buffer_id;
62d722e3fbSopenharmony_ci
63d722e3fbSopenharmony_ci    fb = drmModeGetFB(screen->fd, crtc->buffer_id);
64d722e3fbSopenharmony_ci    if (!fb) {
65d722e3fbSopenharmony_ci        /* TODO: create new framebuffer */
66d722e3fbSopenharmony_ci        drmModeFreeEncoder(encoder);
67d722e3fbSopenharmony_ci        drmModeFreeCrtc(crtc);
68d722e3fbSopenharmony_ci        return -ENOSYS;
69d722e3fbSopenharmony_ci    }
70d722e3fbSopenharmony_ci
71d722e3fbSopenharmony_ci    screen->connector = connector->connector_id;
72d722e3fbSopenharmony_ci    screen->old_fb = crtc->buffer_id;
73d722e3fbSopenharmony_ci    screen->crtc = encoder->crtc_id;
74d722e3fbSopenharmony_ci    /* TODO: check crtc->mode_valid */
75d722e3fbSopenharmony_ci    screen->mode = crtc->mode;
76d722e3fbSopenharmony_ci
77d722e3fbSopenharmony_ci    screen->width = fb->width;
78d722e3fbSopenharmony_ci    screen->height = fb->height;
79d722e3fbSopenharmony_ci    screen->pitch = fb->pitch;
80d722e3fbSopenharmony_ci    screen->depth = fb->depth;
81d722e3fbSopenharmony_ci    screen->bpp = fb->bpp;
82d722e3fbSopenharmony_ci
83d722e3fbSopenharmony_ci    drmModeFreeEncoder(encoder);
84d722e3fbSopenharmony_ci    drmModeFreeCrtc(crtc);
85d722e3fbSopenharmony_ci    drmModeFreeFB(fb);
86d722e3fbSopenharmony_ci
87d722e3fbSopenharmony_ci    return 0;
88d722e3fbSopenharmony_ci}
89d722e3fbSopenharmony_ci
90d722e3fbSopenharmony_ciint drm_screen_open(struct drm_screen **screenp, int fd)
91d722e3fbSopenharmony_ci{
92d722e3fbSopenharmony_ci    drmModeConnectorPtr connector;
93d722e3fbSopenharmony_ci    struct drm_screen *screen;
94d722e3fbSopenharmony_ci    bool found = false;
95d722e3fbSopenharmony_ci    drmModeResPtr res;
96d722e3fbSopenharmony_ci    unsigned int i;
97d722e3fbSopenharmony_ci    int err;
98d722e3fbSopenharmony_ci
99d722e3fbSopenharmony_ci    if (!screenp || fd < 0)
100d722e3fbSopenharmony_ci        return -EINVAL;
101d722e3fbSopenharmony_ci
102d722e3fbSopenharmony_ci    screen = calloc(1, sizeof(*screen));
103d722e3fbSopenharmony_ci    if (!screen)
104d722e3fbSopenharmony_ci        return -ENOMEM;
105d722e3fbSopenharmony_ci
106d722e3fbSopenharmony_ci    screen->format = DRM_FORMAT_XRGB8888;
107d722e3fbSopenharmony_ci    screen->fd = fd;
108d722e3fbSopenharmony_ci
109d722e3fbSopenharmony_ci    res = drmModeGetResources(fd);
110d722e3fbSopenharmony_ci    if (!res) {
111d722e3fbSopenharmony_ci        free(screen);
112d722e3fbSopenharmony_ci        return -ENOMEM;
113d722e3fbSopenharmony_ci    }
114d722e3fbSopenharmony_ci
115d722e3fbSopenharmony_ci    for (i = 0; i < (unsigned int)res->count_connectors; i++) {
116d722e3fbSopenharmony_ci        connector = drmModeGetConnector(fd, res->connectors[i]);
117d722e3fbSopenharmony_ci        if (!connector)
118d722e3fbSopenharmony_ci            continue;
119d722e3fbSopenharmony_ci
120d722e3fbSopenharmony_ci        if (connector->connection != DRM_MODE_CONNECTED) {
121d722e3fbSopenharmony_ci            drmModeFreeConnector(connector);
122d722e3fbSopenharmony_ci            continue;
123d722e3fbSopenharmony_ci        }
124d722e3fbSopenharmony_ci
125d722e3fbSopenharmony_ci        err = drm_screen_probe_connector(screen, connector);
126d722e3fbSopenharmony_ci        if (err < 0) {
127d722e3fbSopenharmony_ci            drmModeFreeConnector(connector);
128d722e3fbSopenharmony_ci            continue;
129d722e3fbSopenharmony_ci        }
130d722e3fbSopenharmony_ci
131d722e3fbSopenharmony_ci        drmModeFreeConnector(connector);
132d722e3fbSopenharmony_ci        found = true;
133d722e3fbSopenharmony_ci        break;
134d722e3fbSopenharmony_ci    }
135d722e3fbSopenharmony_ci
136d722e3fbSopenharmony_ci    drmModeFreeResources(res);
137d722e3fbSopenharmony_ci
138d722e3fbSopenharmony_ci    if (!found) {
139d722e3fbSopenharmony_ci        free(screen);
140d722e3fbSopenharmony_ci        return -ENODEV;
141d722e3fbSopenharmony_ci    }
142d722e3fbSopenharmony_ci
143d722e3fbSopenharmony_ci    *screenp = screen;
144d722e3fbSopenharmony_ci
145d722e3fbSopenharmony_ci    return 0;
146d722e3fbSopenharmony_ci}
147d722e3fbSopenharmony_ci
148d722e3fbSopenharmony_ciint drm_screen_close(struct drm_screen *screen)
149d722e3fbSopenharmony_ci{
150d722e3fbSopenharmony_ci    int err;
151d722e3fbSopenharmony_ci
152d722e3fbSopenharmony_ci    err = drmModeSetCrtc(screen->fd, screen->crtc, screen->old_fb, 0, 0,
153d722e3fbSopenharmony_ci                         &screen->connector, 1, &screen->mode);
154d722e3fbSopenharmony_ci    if (err < 0) {
155d722e3fbSopenharmony_ci        fprintf(stderr, "drmModeSetCrtc() failed: %m\n");
156d722e3fbSopenharmony_ci        return -errno;
157d722e3fbSopenharmony_ci    }
158d722e3fbSopenharmony_ci
159d722e3fbSopenharmony_ci    free(screen);
160d722e3fbSopenharmony_ci
161d722e3fbSopenharmony_ci    return 0;
162d722e3fbSopenharmony_ci}
163d722e3fbSopenharmony_ci
164d722e3fbSopenharmony_ciint drm_framebuffer_new(struct drm_framebuffer **fbp,
165d722e3fbSopenharmony_ci                        struct drm_screen *screen, uint32_t handle,
166d722e3fbSopenharmony_ci                        unsigned int width, unsigned int height,
167d722e3fbSopenharmony_ci                        unsigned int pitch, uint32_t format,
168d722e3fbSopenharmony_ci                        void *data)
169d722e3fbSopenharmony_ci{
170d722e3fbSopenharmony_ci    struct drm_framebuffer *fb;
171d722e3fbSopenharmony_ci    uint32_t handles[4];
172d722e3fbSopenharmony_ci    uint32_t pitches[4];
173d722e3fbSopenharmony_ci    uint32_t offsets[4];
174d722e3fbSopenharmony_ci    int err;
175d722e3fbSopenharmony_ci
176d722e3fbSopenharmony_ci    fb = calloc(1, sizeof(*fb));
177d722e3fbSopenharmony_ci    if (!fb)
178d722e3fbSopenharmony_ci        return -ENOMEM;
179d722e3fbSopenharmony_ci
180d722e3fbSopenharmony_ci    fb->fd = screen->fd;
181d722e3fbSopenharmony_ci    fb->width = width;
182d722e3fbSopenharmony_ci    fb->height = height;
183d722e3fbSopenharmony_ci    fb->pitch = pitch;
184d722e3fbSopenharmony_ci    fb->format = format;
185d722e3fbSopenharmony_ci    fb->data = data;
186d722e3fbSopenharmony_ci
187d722e3fbSopenharmony_ci    handles[0] = handle;
188d722e3fbSopenharmony_ci    pitches[0] = pitch;
189d722e3fbSopenharmony_ci    offsets[0] = 0;
190d722e3fbSopenharmony_ci
191d722e3fbSopenharmony_ci    err = drmModeAddFB2(screen->fd, width, height, format, handles,
192d722e3fbSopenharmony_ci                        pitches, offsets, &fb->handle, 0);
193d722e3fbSopenharmony_ci    if (err < 0)
194d722e3fbSopenharmony_ci        return -errno;
195d722e3fbSopenharmony_ci
196d722e3fbSopenharmony_ci    *fbp = fb;
197d722e3fbSopenharmony_ci
198d722e3fbSopenharmony_ci    return 0;
199d722e3fbSopenharmony_ci}
200d722e3fbSopenharmony_ci
201d722e3fbSopenharmony_ciint drm_framebuffer_free(struct drm_framebuffer *fb)
202d722e3fbSopenharmony_ci{
203d722e3fbSopenharmony_ci    int err;
204d722e3fbSopenharmony_ci
205d722e3fbSopenharmony_ci    err = drmModeRmFB(fb->fd, fb->handle);
206d722e3fbSopenharmony_ci    if (err < 0)
207d722e3fbSopenharmony_ci        return -errno;
208d722e3fbSopenharmony_ci
209d722e3fbSopenharmony_ci    free(fb);
210d722e3fbSopenharmony_ci
211d722e3fbSopenharmony_ci    return 0;
212d722e3fbSopenharmony_ci}
213d722e3fbSopenharmony_ci
214d722e3fbSopenharmony_ciint drm_screen_set_framebuffer(struct drm_screen *screen,
215d722e3fbSopenharmony_ci                               struct drm_framebuffer *fb)
216d722e3fbSopenharmony_ci{
217d722e3fbSopenharmony_ci    int err;
218d722e3fbSopenharmony_ci
219d722e3fbSopenharmony_ci    err = drmModeSetCrtc(screen->fd, screen->crtc, fb->handle, 0, 0,
220d722e3fbSopenharmony_ci                         &screen->connector, 1, &screen->mode);
221d722e3fbSopenharmony_ci    if (err < 0)
222d722e3fbSopenharmony_ci        return -errno;
223d722e3fbSopenharmony_ci
224d722e3fbSopenharmony_ci    return 0;
225d722e3fbSopenharmony_ci}
226d722e3fbSopenharmony_ci
227d722e3fbSopenharmony_ciint drm_open(const char *path)
228d722e3fbSopenharmony_ci{
229d722e3fbSopenharmony_ci    int fd, err;
230d722e3fbSopenharmony_ci
231d722e3fbSopenharmony_ci    fd = open(path, O_RDWR);
232d722e3fbSopenharmony_ci    if (fd < 0)
233d722e3fbSopenharmony_ci        return -errno;
234d722e3fbSopenharmony_ci
235d722e3fbSopenharmony_ci    err = drmSetMaster(fd);
236d722e3fbSopenharmony_ci    if (err < 0) {
237d722e3fbSopenharmony_ci        close(fd);
238d722e3fbSopenharmony_ci        return -errno;
239d722e3fbSopenharmony_ci    }
240d722e3fbSopenharmony_ci
241d722e3fbSopenharmony_ci    return fd;
242d722e3fbSopenharmony_ci}
243d722e3fbSopenharmony_ci
244d722e3fbSopenharmony_civoid drm_close(int fd)
245d722e3fbSopenharmony_ci{
246d722e3fbSopenharmony_ci    drmDropMaster(fd);
247d722e3fbSopenharmony_ci    close(fd);
248d722e3fbSopenharmony_ci}
249