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