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