egl: Add checks for EGL_MESA_screen_surface.
[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 "eglcurrent.h"
20 #include "eglmode.h"
21 #include "eglconfig.h"
22 #include "eglsurface.h"
23 #include "eglscreen.h"
24 #include "eglmutex.h"
25
26
27 #ifdef EGL_MESA_screen_surface
28
29
30 /* ugh, no atomic op? */
31 static _EGL_DECLARE_MUTEX(_eglNextScreenHandleMutex);
32 static EGLScreenMESA _eglNextScreenHandle = 1;
33
34
35 /**
36 * Return a new screen handle/ID.
37 * NOTE: we never reuse these!
38 */
39 static EGLScreenMESA
40 _eglAllocScreenHandle(void)
41 {
42 EGLScreenMESA s;
43
44 _eglLockMutex(&_eglNextScreenHandleMutex);
45 s = _eglNextScreenHandle++;
46 _eglUnlockMutex(&_eglNextScreenHandleMutex);
47
48 return s;
49 }
50
51
52 /**
53 * Initialize an _EGLScreen object to default values.
54 */
55 void
56 _eglInitScreen(_EGLScreen *screen)
57 {
58 memset(screen, 0, sizeof(_EGLScreen));
59 screen->StepX = 1;
60 screen->StepY = 1;
61 }
62
63
64 /**
65 * Given a public screen handle, return the internal _EGLScreen object.
66 */
67 _EGLScreen *
68 _eglLookupScreen(EGLScreenMESA screen, _EGLDisplay *display)
69 {
70 EGLint i;
71
72 if (!display->Screens)
73 return NULL;
74
75 for (i = 0; i < display->Screens->Size; i++) {
76 _EGLScreen *scr = (_EGLScreen *) display->Screens->Elements[i];
77 if (scr->Handle == screen)
78 return scr;
79 }
80 return NULL;
81 }
82
83
84 /**
85 * Add the given _EGLScreen to the display's list of screens.
86 */
87 void
88 _eglAddScreen(_EGLDisplay *display, _EGLScreen *screen)
89 {
90 assert(display);
91 assert(screen);
92
93 if (!display->Screens) {
94 display->Screens = _eglCreateArray("Screen", 4);
95 if (!display->Screens)
96 return;
97 }
98 screen->Handle = _eglAllocScreenHandle();
99 _eglAppendArray(display->Screens, (void *) screen);
100 }
101
102
103
104 static EGLBoolean
105 _eglFlattenScreen(void *elem, void *buffer)
106 {
107 _EGLScreen *scr = (_EGLScreen *) elem;
108 EGLScreenMESA *handle = (EGLScreenMESA *) buffer;
109 *handle = scr->Handle;
110 return EGL_TRUE;
111 }
112
113
114 EGLBoolean
115 _eglGetScreensMESA(_EGLDriver *drv, _EGLDisplay *display, EGLScreenMESA *screens,
116 EGLint max_screens, EGLint *num_screens)
117 {
118 *num_screens = _eglFlattenArray(display->Screens, (void *) screens,
119 sizeof(screens[0]), max_screens, _eglFlattenScreen);
120
121 return EGL_TRUE;
122 }
123
124
125 /**
126 * Drivers should do a proper implementation.
127 */
128 _EGLSurface *
129 _eglCreateScreenSurfaceMESA(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
130 const EGLint *attrib_list)
131 {
132 return NULL;
133 }
134
135
136 /**
137 * Show the given surface on the named screen.
138 * If surface is EGL_NO_SURFACE, disable the screen's output.
139 *
140 * This is just a placeholder function; drivers will always override
141 * this with code that _really_ shows the surface.
142 */
143 EGLBoolean
144 _eglShowScreenSurfaceMESA(_EGLDriver *drv, _EGLDisplay *dpy,
145 _EGLScreen *scrn, _EGLSurface *surf,
146 _EGLMode *mode)
147 {
148 if (!surf) {
149 scrn->CurrentSurface = NULL;
150 }
151 else {
152 if (surf->Type != EGL_SCREEN_BIT_MESA) {
153 _eglError(EGL_BAD_SURFACE, "eglShowSurfaceMESA");
154 return EGL_FALSE;
155 }
156 if (surf->Width < mode->Width || surf->Height < mode->Height) {
157 _eglError(EGL_BAD_SURFACE,
158 "eglShowSurfaceMESA(surface smaller than screen size)");
159 return EGL_FALSE;
160 }
161
162 scrn->CurrentSurface = surf;
163 scrn->CurrentMode = mode;
164 }
165 return EGL_TRUE;
166 }
167
168
169 /**
170 * Set a screen's current display mode.
171 * Note: mode = EGL_NO_MODE is valid (turns off the screen)
172 *
173 * This is just a placeholder function; drivers will always override
174 * this with code that _really_ sets the mode.
175 */
176 EGLBoolean
177 _eglScreenModeMESA(_EGLDriver *drv, _EGLDisplay *dpy, _EGLScreen *scrn,
178 _EGLMode *m)
179 {
180 scrn->CurrentMode = m;
181 return EGL_TRUE;
182 }
183
184
185 /**
186 * Set a screen's surface origin.
187 */
188 EGLBoolean
189 _eglScreenPositionMESA(_EGLDriver *drv, _EGLDisplay *dpy,
190 _EGLScreen *scrn, EGLint x, EGLint y)
191 {
192 scrn->OriginX = x;
193 scrn->OriginY = y;
194
195 return EGL_TRUE;
196 }
197
198
199 /**
200 * Query a screen's current surface.
201 */
202 EGLBoolean
203 _eglQueryScreenSurfaceMESA(_EGLDriver *drv, _EGLDisplay *dpy,
204 _EGLScreen *scrn, _EGLSurface **surf)
205 {
206 *surf = scrn->CurrentSurface;
207 return EGL_TRUE;
208 }
209
210
211 /**
212 * Query a screen's current mode.
213 */
214 EGLBoolean
215 _eglQueryScreenModeMESA(_EGLDriver *drv, _EGLDisplay *dpy, _EGLScreen *scrn,
216 _EGLMode **m)
217 {
218 *m = scrn->CurrentMode;
219 return EGL_TRUE;
220 }
221
222
223 EGLBoolean
224 _eglQueryScreenMESA(_EGLDriver *drv, _EGLDisplay *dpy, _EGLScreen *scrn,
225 EGLint attribute, EGLint *value)
226 {
227 switch (attribute) {
228 case EGL_SCREEN_POSITION_MESA:
229 value[0] = scrn->OriginX;
230 value[1] = scrn->OriginY;
231 break;
232 case EGL_SCREEN_POSITION_GRANULARITY_MESA:
233 value[0] = scrn->StepX;
234 value[1] = scrn->StepY;
235 break;
236 default:
237 _eglError(EGL_BAD_ATTRIBUTE, "eglQueryScreenMESA");
238 return EGL_FALSE;
239 }
240
241 return EGL_TRUE;
242 }
243
244
245 /**
246 * Delete the modes associated with given screen.
247 */
248 void
249 _eglDestroyScreenModes(_EGLScreen *scrn)
250 {
251 EGLint i;
252 for (i = 0; i < scrn->NumModes; i++) {
253 if (scrn->Modes[i].Name)
254 free((char *) scrn->Modes[i].Name); /* cast away const */
255 }
256 if (scrn->Modes)
257 free(scrn->Modes);
258 scrn->Modes = NULL;
259 scrn->NumModes = 0;
260 }
261
262
263 /**
264 * Default fallback routine - drivers should usually override this.
265 */
266 void
267 _eglDestroyScreen(_EGLScreen *scrn)
268 {
269 _eglDestroyScreenModes(scrn);
270 free(scrn);
271 }
272
273
274 #endif /* EGL_MESA_screen_surface */