• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2014 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 #ifdef HAVE_CONFIG_H
24 #  include "config.h"
25 #endif
26 
27 #include <errno.h>
28 #include <fcntl.h>
29 #include <stdbool.h>
30 #include <stdint.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <unistd.h>
35 
36 #include <sys/ioctl.h>
37 
38 #include "xf86drm.h"
39 #include "xf86drmMode.h"
40 #include "drm_fourcc.h"
41 
42 #include "drm-test.h"
43 
drm_screen_probe_connector(struct drm_screen * screen,drmModeConnectorPtr connector)44 static int drm_screen_probe_connector(struct drm_screen *screen,
45                                       drmModeConnectorPtr connector)
46 {
47     drmModeEncoderPtr encoder;
48     drmModeCrtcPtr crtc;
49     drmModeFBPtr fb;
50 
51     encoder = drmModeGetEncoder(screen->fd, connector->encoder_id);
52     if (!encoder)
53         return -ENODEV;
54 
55     crtc = drmModeGetCrtc(screen->fd, encoder->crtc_id);
56     if (!crtc) {
57         drmModeFreeEncoder(encoder);
58         return -ENODEV;
59     }
60 
61     screen->old_fb = crtc->buffer_id;
62 
63     fb = drmModeGetFB(screen->fd, crtc->buffer_id);
64     if (!fb) {
65         /* TODO: create new framebuffer */
66         drmModeFreeEncoder(encoder);
67         drmModeFreeCrtc(crtc);
68         return -ENOSYS;
69     }
70 
71     screen->connector = connector->connector_id;
72     screen->old_fb = crtc->buffer_id;
73     screen->crtc = encoder->crtc_id;
74     /* TODO: check crtc->mode_valid */
75     screen->mode = crtc->mode;
76 
77     screen->width = fb->width;
78     screen->height = fb->height;
79     screen->pitch = fb->pitch;
80     screen->depth = fb->depth;
81     screen->bpp = fb->bpp;
82 
83     drmModeFreeEncoder(encoder);
84     drmModeFreeCrtc(crtc);
85     drmModeFreeFB(fb);
86 
87     return 0;
88 }
89 
drm_screen_open(struct drm_screen ** screenp,int fd)90 int drm_screen_open(struct drm_screen **screenp, int fd)
91 {
92     drmModeConnectorPtr connector;
93     struct drm_screen *screen;
94     bool found = false;
95     drmModeResPtr res;
96     unsigned int i;
97     int err;
98 
99     if (!screenp || fd < 0)
100         return -EINVAL;
101 
102     screen = calloc(1, sizeof(*screen));
103     if (!screen)
104         return -ENOMEM;
105 
106     screen->format = DRM_FORMAT_XRGB8888;
107     screen->fd = fd;
108 
109     res = drmModeGetResources(fd);
110     if (!res) {
111         free(screen);
112         return -ENOMEM;
113     }
114 
115     for (i = 0; i < (unsigned int)res->count_connectors; i++) {
116         connector = drmModeGetConnector(fd, res->connectors[i]);
117         if (!connector)
118             continue;
119 
120         if (connector->connection != DRM_MODE_CONNECTED) {
121             drmModeFreeConnector(connector);
122             continue;
123         }
124 
125         err = drm_screen_probe_connector(screen, connector);
126         if (err < 0) {
127             drmModeFreeConnector(connector);
128             continue;
129         }
130 
131         drmModeFreeConnector(connector);
132         found = true;
133         break;
134     }
135 
136     drmModeFreeResources(res);
137 
138     if (!found) {
139         free(screen);
140         return -ENODEV;
141     }
142 
143     *screenp = screen;
144 
145     return 0;
146 }
147 
drm_screen_close(struct drm_screen * screen)148 int drm_screen_close(struct drm_screen *screen)
149 {
150     int err;
151 
152     err = drmModeSetCrtc(screen->fd, screen->crtc, screen->old_fb, 0, 0,
153                          &screen->connector, 1, &screen->mode);
154     if (err < 0) {
155         fprintf(stderr, "drmModeSetCrtc() failed: %m\n");
156         return -errno;
157     }
158 
159     free(screen);
160 
161     return 0;
162 }
163 
drm_framebuffer_new(struct drm_framebuffer ** fbp,struct drm_screen * screen,uint32_t handle,unsigned int width,unsigned int height,unsigned int pitch,uint32_t format,void * data)164 int drm_framebuffer_new(struct drm_framebuffer **fbp,
165                         struct drm_screen *screen, uint32_t handle,
166                         unsigned int width, unsigned int height,
167                         unsigned int pitch, uint32_t format,
168                         void *data)
169 {
170     struct drm_framebuffer *fb;
171     uint32_t handles[4];
172     uint32_t pitches[4];
173     uint32_t offsets[4];
174     int err;
175 
176     fb = calloc(1, sizeof(*fb));
177     if (!fb)
178         return -ENOMEM;
179 
180     fb->fd = screen->fd;
181     fb->width = width;
182     fb->height = height;
183     fb->pitch = pitch;
184     fb->format = format;
185     fb->data = data;
186 
187     handles[0] = handle;
188     pitches[0] = pitch;
189     offsets[0] = 0;
190 
191     err = drmModeAddFB2(screen->fd, width, height, format, handles,
192                         pitches, offsets, &fb->handle, 0);
193     if (err < 0)
194         return -errno;
195 
196     *fbp = fb;
197 
198     return 0;
199 }
200 
drm_framebuffer_free(struct drm_framebuffer * fb)201 int drm_framebuffer_free(struct drm_framebuffer *fb)
202 {
203     int err;
204 
205     err = drmModeRmFB(fb->fd, fb->handle);
206     if (err < 0)
207         return -errno;
208 
209     free(fb);
210 
211     return 0;
212 }
213 
drm_screen_set_framebuffer(struct drm_screen * screen,struct drm_framebuffer * fb)214 int drm_screen_set_framebuffer(struct drm_screen *screen,
215                                struct drm_framebuffer *fb)
216 {
217     int err;
218 
219     err = drmModeSetCrtc(screen->fd, screen->crtc, fb->handle, 0, 0,
220                          &screen->connector, 1, &screen->mode);
221     if (err < 0)
222         return -errno;
223 
224     return 0;
225 }
226 
drm_open(const char * path)227 int drm_open(const char *path)
228 {
229     int fd, err;
230 
231     fd = open(path, O_RDWR);
232     if (fd < 0)
233         return -errno;
234 
235     err = drmSetMaster(fd);
236     if (err < 0) {
237         close(fd);
238         return -errno;
239     }
240 
241     return fd;
242 }
243 
drm_close(int fd)244 void drm_close(int fd)
245 {
246     drmDropMaster(fd);
247     close(fd);
248 }
249