Some initial per-thread support.
[mesa.git] / src / egl / main / eglscreen.c
1 /*
2 * Ideas for screen management extension to EGL.
3 *
4 * Each EGLDisplay has one or more screens (CRTs, Flat Panels, etc).
5 * The screens' handles can be obtained with eglGetScreensMESA().
6 *
7 * A new kind of EGLSurface is possible- one which can be directly scanned
8 * out on a screen. Such a surface is created with eglCreateScreenSurface().
9 *
10 * To actually display a screen surface on a screen, the eglShowSurface()
11 * function is called.
12 */
13
14 #include <assert.h>
15 #include <stdlib.h>
16 #include <string.h>
17
18 #include "egldisplay.h"
19 #include "eglglobals.h"
20 #include "eglmode.h"
21 #include "eglconfig.h"
22 #include "eglsurface.h"
23 #include "eglscreen.h"
24
25
26 /**
27 * Initialize an _EGLScreen object to default values.
28 */
29 void
30 _eglInitScreen(_EGLScreen *screen)
31 {
32 memset(screen, 0, sizeof(_EGLScreen));
33 screen->StepX = 1;
34 screen->StepY = 1;
35 }
36
37
38 /**
39 * Given a public screen handle, return the internal _EGLScreen object.
40 */
41 _EGLScreen *
42 _eglLookupScreen(EGLDisplay dpy, EGLScreenMESA screen)
43 {
44 EGLint i;
45 _EGLDisplay *display = _eglLookupDisplay(dpy);
46
47 if (!display)
48 return NULL;
49
50 for (i = 0; i < display->NumScreens; i++) {
51 if (display->Screens[i]->Handle == screen)
52 return display->Screens[i];
53 }
54 return NULL;
55 }
56
57
58 /**
59 * Add the given _EGLScreen to the display's list of screens.
60 */
61 void
62 _eglAddScreen(_EGLDisplay *display, _EGLScreen *screen)
63 {
64 EGLint n;
65
66 assert(display);
67 assert(screen);
68
69 screen->Handle = _eglAllocScreenHandle();
70 n = display->NumScreens;
71 display->Screens = realloc(display->Screens, (n+1) * sizeof(_EGLScreen *));
72 display->Screens[n] = screen;
73 display->NumScreens++;
74 }
75
76
77
78 EGLBoolean
79 _eglGetScreensMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA *screens,
80 EGLint max_screens, EGLint *num_screens)
81 {
82 _EGLDisplay *display = _eglLookupDisplay(dpy);
83 EGLint n;
84
85 if (!display) {
86 _eglError(EGL_BAD_DISPLAY, "eglGetScreensMESA");
87 return EGL_FALSE;
88 }
89
90 if (display->NumScreens > max_screens) {
91 n = max_screens;
92 }
93 else {
94 n = display->NumScreens;
95 }
96
97 if (screens) {
98 EGLint i;
99 for (i = 0; i < n; i++)
100 screens[i] = display->Screens[i]->Handle;
101 }
102 if (num_screens)
103 *num_screens = n;
104
105 return EGL_TRUE;
106 }
107
108
109 /**
110 * Example function - drivers should do a proper implementation.
111 */
112 EGLSurface
113 _eglCreateScreenSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
114 const EGLint *attrib_list)
115 {
116 #if 0 /* THIS IS JUST EXAMPLE CODE */
117 _EGLSurface *surf;
118
119 surf = (_EGLSurface *) calloc(1, sizeof(_EGLSurface));
120 if (!surf)
121 return EGL_NO_SURFACE;
122
123 if (!_eglInitSurface(drv, dpy, surf, EGL_SCREEN_BIT_MESA,
124 config, attrib_list)) {
125 free(surf);
126 return EGL_NO_SURFACE;
127 }
128
129 _eglSaveSurface(surf);
130
131 return surf->Handle;
132 #endif
133 return EGL_NO_SURFACE;
134 }
135
136
137 /**
138 * Show the given surface on the named screen.
139 * If surface is EGL_NO_SURFACE, disable the screen's output.
140 *
141 * This is just a placeholder function; drivers will always override
142 * this with code that _really_ shows the surface.
143 */
144 EGLBoolean
145 _eglShowScreenSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy,
146 EGLScreenMESA screen, EGLSurface surface,
147 EGLModeMESA m)
148 {
149 _EGLScreen *scrn = _eglLookupScreen(dpy, screen);
150 _EGLMode *mode = _eglLookupMode(dpy, m);
151
152 if (!scrn) {
153 _eglError(EGL_BAD_SCREEN_MESA, "eglShowSurfaceMESA");
154 return EGL_FALSE;
155 }
156 if (!mode && (m != EGL_NO_MODE_MESA )) {
157 _eglError(EGL_BAD_MODE_MESA, "eglShowSurfaceMESA");
158 return EGL_FALSE;
159 }
160
161 if (surface == EGL_NO_SURFACE) {
162 scrn->CurrentSurface = NULL;
163 }
164 else {
165 _EGLSurface *surf = _eglLookupSurface(surface);
166 if (!surf || surf->Type != EGL_SCREEN_BIT_MESA) {
167 _eglError(EGL_BAD_SURFACE, "eglShowSurfaceMESA");
168 return EGL_FALSE;
169 }
170 if (surf->Width < mode->Width || surf->Height < mode->Height) {
171 _eglError(EGL_BAD_SURFACE,
172 "eglShowSurfaceMESA(surface smaller than screen size)");
173 return EGL_FALSE;
174 }
175
176 scrn->CurrentSurface = surf;
177 scrn->CurrentMode = mode;
178 }
179 return EGL_TRUE;
180 }
181
182
183 /**
184 * Set a screen's current display mode.
185 * Note: mode = EGL_NO_MODE is valid (turns off the screen)
186 *
187 * This is just a placeholder function; drivers will always override
188 * this with code that _really_ sets the mode.
189 */
190 EGLBoolean
191 _eglScreenModeMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen,
192 EGLModeMESA mode)
193 {
194 _EGLScreen *scrn = _eglLookupScreen(dpy, screen);
195
196 if (!scrn) {
197 _eglError(EGL_BAD_SCREEN_MESA, "eglScreenModeMESA");
198 return EGL_FALSE;
199 }
200
201 scrn->CurrentMode = _eglLookupMode(dpy, mode);
202
203 return EGL_TRUE;
204 }
205
206
207 /**
208 * Set a screen's surface origin.
209 */
210 EGLBoolean
211 _eglScreenPositionMESA(_EGLDriver *drv, EGLDisplay dpy,
212 EGLScreenMESA screen, EGLint x, EGLint y)
213 {
214 _EGLScreen *scrn = _eglLookupScreen(dpy, screen);
215 if (!scrn) {
216 _eglError(EGL_BAD_SCREEN_MESA, "eglScreenPositionMESA");
217 return EGL_FALSE;
218 }
219
220 scrn->OriginX = x;
221 scrn->OriginY = y;
222
223 return EGL_TRUE;
224 }
225
226
227 /**
228 * Query a screen's current surface.
229 */
230 EGLBoolean
231 _eglQueryScreenSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy,
232 EGLScreenMESA screen, EGLSurface *surface)
233 {
234 const _EGLScreen *scrn = _eglLookupScreen(dpy, screen);
235 if (scrn->CurrentSurface)
236 *surface = scrn->CurrentSurface->Handle;
237 else
238 *surface = EGL_NO_SURFACE;
239 return EGL_TRUE;
240 }
241
242
243 /**
244 * Query a screen's current mode.
245 */
246 EGLBoolean
247 _eglQueryScreenModeMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen,
248 EGLModeMESA *mode)
249 {
250 const _EGLScreen *scrn = _eglLookupScreen(dpy, screen);
251 if (scrn->CurrentMode)
252 *mode = scrn->CurrentMode->Handle;
253 else
254 *mode = EGL_NO_MODE_MESA;
255 return EGL_TRUE;
256 }
257
258
259 EGLBoolean
260 _eglQueryScreenMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen,
261 EGLint attribute, EGLint *value)
262 {
263 const _EGLScreen *scrn = _eglLookupScreen(dpy, screen);
264
265 if (!scrn) {
266 _eglError(EGL_BAD_SCREEN_MESA, "eglQueryScreenMESA");
267 return EGL_FALSE;
268 }
269
270 switch (attribute) {
271 case EGL_SCREEN_POSITION_MESA:
272 value[0] = scrn->OriginX;
273 value[1] = scrn->OriginY;
274 break;
275 case EGL_SCREEN_POSITION_GRANULARITY_MESA:
276 value[0] = scrn->StepX;
277 value[1] = scrn->StepY;
278 break;
279 default:
280 _eglError(EGL_BAD_ATTRIBUTE, "eglQueryScreenMESA");
281 return EGL_FALSE;
282 }
283
284 return EGL_TRUE;
285 }
286
287
288 /**
289 * Delete the modes associated with given screen.
290 */
291 void
292 _eglDestroyScreenModes(_EGLScreen *scrn)
293 {
294 EGLint i;
295 for (i = 0; i < scrn->NumModes; i++) {
296 if (scrn->Modes[i].Name)
297 free((char *) scrn->Modes[i].Name); /* cast away const */
298 }
299 if (scrn->Modes)
300 free(scrn->Modes);
301 scrn->Modes = NULL;
302 scrn->NumModes = 0;
303 }
304
305
306 /**
307 * Default fallback routine - drivers should usually override this.
308 */
309 void
310 _eglDestroyScreen(_EGLScreen *scrn)
311 {
312 _eglDestroyScreenModes(scrn);
313 free(scrn);
314 }
315