1 /* RetroArch - A frontend for libretro.
2 * Copyright (c) 2011-2017 - Daniel De Matteis
3 *
4 * RetroArch is free software: you can redistribute it and/or modify it under the terms
5 * of the GNU General Public License as published by the Free Software Found-
6 * ation, either version 3 of the License, or (at your option) any later version.
7 *
8 * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
9 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
10 * PURPOSE. See the GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License along with RetroArch.
13 * If not, see <http://www.gnu.org/licenses/>.
14 */
15
16 #include <compat/strl.h>
17
18 #include <retro_miscellaneous.h>
19
20 #include "../../verbosity.h"
21
22 #include "drm_common.h"
23
24 /* TODO/FIXME - globals */
25 drmEventContext g_drm_evctx;
26 struct pollfd g_drm_fds;
27 uint32_t g_connector_id = 0;
28 int g_drm_fd = 0;
29 uint32_t g_crtc_id = 0;
30 drmModeCrtc *g_orig_crtc = NULL;
31 drmModeConnector *g_drm_connector = NULL;
32 drmModeModeInfo *g_drm_mode = NULL;
33
34 /* TODO/FIXME - static globals */
35 static drmModeRes *g_drm_resources = NULL;
36 static drmModeEncoder *g_drm_encoder = NULL;
37
38 /* Restore the original CRTC. */
drm_restore_crtc(void)39 void drm_restore_crtc(void)
40 {
41 if (!g_orig_crtc)
42 return;
43
44 drmModeSetCrtc(g_drm_fd, g_orig_crtc->crtc_id,
45 g_orig_crtc->buffer_id,
46 g_orig_crtc->x,
47 g_orig_crtc->y,
48 &g_connector_id, 1, &g_orig_crtc->mode);
49
50 drmModeFreeCrtc(g_orig_crtc);
51 g_orig_crtc = NULL;
52 }
53
drm_get_resources(int fd)54 bool drm_get_resources(int fd)
55 {
56 g_drm_resources = drmModeGetResources(fd);
57 if (!g_drm_resources)
58 {
59 RARCH_WARN("[DRM]: Couldn't get device resources.\n");
60 return false;
61 }
62
63 return true;
64 }
65
drm_get_connector(int fd,unsigned monitor_index)66 bool drm_get_connector(int fd, unsigned monitor_index)
67 {
68 unsigned i;
69 unsigned monitor_index_count = 0;
70 unsigned monitor = MAX(monitor_index, 1);
71
72 /* Enumerate all connectors. */
73
74 RARCH_LOG("[DRM]: Found %d connectors.\n", g_drm_resources->count_connectors);
75
76 for (i = 0; (int)i < g_drm_resources->count_connectors; i++)
77 {
78 drmModeConnectorPtr conn = drmModeGetConnector(
79 fd, g_drm_resources->connectors[i]);
80
81 if (conn)
82 {
83 bool connected = conn->connection == DRM_MODE_CONNECTED;
84 RARCH_LOG("[DRM]: Connector %d connected: %s\n", i, connected ? "yes" : "no");
85 RARCH_LOG("[DRM]: Connector %d has %d modes.\n", i, conn->count_modes);
86 if (connected && conn->count_modes > 0)
87 {
88 monitor_index_count++;
89 RARCH_LOG("[DRM]: Connector %d assigned to monitor index: #%u.\n", i, monitor_index_count);
90 }
91 drmModeFreeConnector(conn);
92 }
93 }
94
95 monitor_index_count = 0;
96
97 for (i = 0; (int)i < g_drm_resources->count_connectors; i++)
98 {
99 g_drm_connector = drmModeGetConnector(fd,
100 g_drm_resources->connectors[i]);
101
102 if (!g_drm_connector)
103 continue;
104 if (g_drm_connector->connection == DRM_MODE_CONNECTED
105 && g_drm_connector->count_modes > 0)
106 {
107 monitor_index_count++;
108 if (monitor_index_count == monitor)
109 break;
110 }
111
112 drmModeFreeConnector(g_drm_connector);
113 g_drm_connector = NULL;
114 }
115
116 if (!g_drm_connector)
117 {
118 RARCH_WARN("[DRM]: Couldn't get device connector.\n");
119 return false;
120 }
121 return true;
122 }
123
drm_calc_refresh_rate(drmModeModeInfo * mode)124 float drm_calc_refresh_rate(drmModeModeInfo *mode)
125 {
126 float refresh_rate = (mode->clock * 1000.0f) / (mode->htotal * mode->vtotal);
127 return refresh_rate;
128 }
129
drm_get_encoder(int fd)130 bool drm_get_encoder(int fd)
131 {
132 unsigned i;
133
134 for (i = 0; (int)i < g_drm_resources->count_encoders; i++)
135 {
136 g_drm_encoder = drmModeGetEncoder(fd, g_drm_resources->encoders[i]);
137
138 if (!g_drm_encoder)
139 continue;
140
141 if (g_drm_encoder->encoder_id == g_drm_connector->encoder_id)
142 break;
143
144 drmModeFreeEncoder(g_drm_encoder);
145 g_drm_encoder = NULL;
146 }
147
148 if (!g_drm_encoder)
149 {
150 RARCH_WARN("[DRM]: Couldn't find DRM encoder.\n");
151 return false;
152 }
153
154 for (i = 0; (int)i < g_drm_connector->count_modes; i++)
155 {
156 RARCH_LOG("[DRM]: Mode %d: (%s) %d x %d, %f Hz\n",
157 i,
158 g_drm_connector->modes[i].name,
159 g_drm_connector->modes[i].hdisplay,
160 g_drm_connector->modes[i].vdisplay,
161 drm_calc_refresh_rate(&g_drm_connector->modes[i]));
162 }
163
164 return true;
165 }
166
drm_setup(int fd)167 void drm_setup(int fd)
168 {
169 g_crtc_id = g_drm_encoder->crtc_id;
170 g_connector_id = g_drm_connector->connector_id;
171 g_orig_crtc = drmModeGetCrtc(fd, g_crtc_id);
172 if (!g_orig_crtc)
173 RARCH_WARN("[DRM]: Cannot find original CRTC.\n");
174 }
175
drm_get_refresh_rate(void * data)176 float drm_get_refresh_rate(void *data)
177 {
178 float refresh_rate = 0.0f;
179
180 if (g_drm_mode)
181 {
182 refresh_rate = drm_calc_refresh_rate(g_drm_mode);
183 }
184
185 return refresh_rate;
186 }
187
drm_free(void)188 void drm_free(void)
189 {
190 if (g_drm_encoder)
191 drmModeFreeEncoder(g_drm_encoder);
192 if (g_drm_connector)
193 drmModeFreeConnector(g_drm_connector);
194 if (g_drm_resources)
195 drmModeFreeResources(g_drm_resources);
196
197 memset(&g_drm_fds, 0, sizeof(struct pollfd));
198 memset(&g_drm_evctx, 0, sizeof(drmEventContext));
199
200 g_drm_encoder = NULL;
201 g_drm_connector = NULL;
202 g_drm_resources = NULL;
203 }
204