* Ideas for screen management extension to EGL.
*
* Each EGLDisplay has one or more screens (CRTs, Flat Panels, etc).
- * The number of screens can be queried with eglQueryDisplay(EGL_SCREEN_COUNT).
+ * The screens' handles can be obtained with eglGetScreensMESA().
*
* A new kind of EGLSurface is possible- one which can be directly scanned
* out on a screen. Such a surface is created with eglCreateScreenSurface().
*
* To actually display a screen surface on a screen, the eglShowSurface()
* function is called.
- *
*/
#include <assert.h>
#include <stdlib.h>
+#include <string.h>
+
#include "egldisplay.h"
#include "eglglobals.h"
#include "eglmode.h"
+#include "eglconfig.h"
#include "eglsurface.h"
#include "eglscreen.h"
+/**
+ * Return a new screen handle/ID.
+ * NOTE: we never reuse these!
+ */
+EGLScreenMESA
+_eglAllocScreenHandle(void)
+{
+ EGLScreenMESA s = _eglGlobal.FreeScreenHandle;
+ _eglGlobal.FreeScreenHandle++;
+ return s;
+}
+
+
+/**
+ * Initialize an _EGLScreen object to default values.
+ */
+void
+_eglInitScreen(_EGLScreen *screen)
+{
+ memset(screen, 0, sizeof(_EGLScreen));
+ screen->StepX = 1;
+ screen->StepY = 1;
+}
+
+
+/**
+ * Given a public screen handle, return the internal _EGLScreen object.
+ */
_EGLScreen *
-_eglLookupScreen(EGLDisplay dpy, GLint screenNumber)
+_eglLookupScreen(EGLDisplay dpy, EGLScreenMESA screen)
{
- _EGLDisplay *disp = _eglLookupDisplay(dpy);
- if (!disp || screenNumber < 0 || screenNumber >= disp->NumScreens) {
+ EGLint i;
+ _EGLDisplay *display = _eglLookupDisplay(dpy);
+
+ if (!display)
return NULL;
+
+ for (i = 0; i < display->NumScreens; i++) {
+ if (display->Screens[i]->Handle == screen)
+ return display->Screens[i];
+ }
+ return NULL;
+}
+
+
+/**
+ * Add the given _EGLScreen to the display's list of screens.
+ */
+void
+_eglAddScreen(_EGLDisplay *display, _EGLScreen *screen)
+{
+ EGLint n;
+
+ assert(display);
+ assert(screen);
+
+ screen->Handle = _eglAllocScreenHandle();
+ n = display->NumScreens;
+ display->Screens = realloc(display->Screens, (n+1) * sizeof(_EGLScreen *));
+ display->Screens[n] = screen;
+ display->NumScreens++;
+}
+
+
+
+EGLBoolean
+_eglGetScreensMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA *screens,
+ EGLint max_screens, EGLint *num_screens)
+{
+ _EGLDisplay *display = _eglLookupDisplay(dpy);
+ EGLint n;
+
+ if (!display) {
+ _eglError(EGL_BAD_DISPLAY, "eglGetScreensMESA");
+ return EGL_FALSE;
+ }
+
+ if (display->NumScreens > max_screens) {
+ n = max_screens;
}
else {
- return disp->Screens + screenNumber;
+ n = display->NumScreens;
}
+
+ if (screens) {
+ EGLint i;
+ for (i = 0; i < n; i++)
+ screens[i] = display->Screens[i]->Handle;
+ }
+ if (num_screens)
+ *num_screens = n;
+
+ return EGL_TRUE;
}
/**
- * Create a drawing surface which can be directly displayed on a screen.
+ * Example function - drivers should do a proper implementation.
*/
EGLSurface
_eglCreateScreenSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
const EGLint *attrib_list)
{
+#if 0 /* THIS IS JUST EXAMPLE CODE */
_EGLSurface *surf;
- EGLint width = 0, height = 0;
- EGLint i;
-
- for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) {
- switch (attrib_list[i]) {
- case EGL_WIDTH:
- width = attrib_list[++i];
- break;
- case EGL_HEIGHT:
- height = attrib_list[++i];
- break;
- default:
- _eglError(EGL_BAD_ATTRIBUTE, "eglCreateScreenSurfaceMESA");
- return EGL_NO_SURFACE;
- }
- }
+ _EGLConfig *conf;
- if (width <= 0 || height <= 0) {
- _eglError(EGL_BAD_ATTRIBUTE,
- "eglCreateScreenSurfaceMESA(width or height)");
+ conf = _eglLookupConfig(drv, dpy, config);
+ if (!conf) {
+ _eglError(EGL_BAD_CONFIG, "eglCreateScreenSurfaceMESA");
return EGL_NO_SURFACE;
}
- surf = (_EGLSurface *) malloc(sizeof(_EGLSurface));
- _eglInitSurface(surf);
- surf->Width = width;
- surf->Height = height;
- surf->Type = EGL_SCREEN_BIT_MESA;
+ surf = (_EGLSurface *) calloc(1, sizeof(_EGLSurface));
+ if (!surf)
+ return EGL_NO_SURFACE;
- /* insert into hash table */
- _eglSaveSurface(surf);
- assert(surf->Handle);
+ if (!_eglInitSurface(drv, surf, EGL_SCREEN_BIT_MESA,
+ conf, attrib_list)) {
+ free(surf);
+ return EGL_NO_SURFACE;
+ }
- return surf->Handle;
+ return _eglLinkSurface(surf, _eglLookupDisplay(dpy));
+#endif
+ return EGL_NO_SURFACE;
}
* this with code that _really_ shows the surface.
*/
EGLBoolean
-_eglShowSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy, EGLint screen_number,
- EGLSurface surface)
+_eglShowScreenSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy,
+ EGLScreenMESA screen, EGLSurface surface,
+ EGLModeMESA m)
{
- _EGLScreen *scrn = _eglLookupScreen(dpy, screen_number);
- _EGLMode *mode;
+ _EGLScreen *scrn = _eglLookupScreen(dpy, screen);
+ _EGLMode *mode = _eglLookupMode(dpy, m);
if (!scrn) {
_eglError(EGL_BAD_SCREEN_MESA, "eglShowSurfaceMESA");
return EGL_FALSE;
}
-
- /*
- * XXX: Check if the surface's configuration is compatible with the
- * current screen mode.
- */
-
- mode = scrn->CurrentMode;
- if (mode == EGL_NO_MODE_MESA) {
- _eglError(EGL_BAD_MODE_MESA, "eglShowSurfaceMESA(no current mode)");
+ if (!mode && (m != EGL_NO_MODE_MESA )) {
+ _eglError(EGL_BAD_MODE_MESA, "eglShowSurfaceMESA");
return EGL_FALSE;
}
}
scrn->CurrentSurface = surf;
+ scrn->CurrentMode = mode;
}
-
return EGL_TRUE;
}
* this with code that _really_ sets the mode.
*/
EGLBoolean
-_eglScreenModeMESA(_EGLDriver *drv, EGLDisplay dpy, EGLint screen_number,
+_eglScreenModeMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen,
EGLModeMESA mode)
{
- _EGLScreen *scrn = _eglLookupScreen(dpy, screen_number);
+ _EGLScreen *scrn = _eglLookupScreen(dpy, screen);
if (!scrn) {
_eglError(EGL_BAD_SCREEN_MESA, "eglScreenModeMESA");
*/
EGLBoolean
_eglScreenPositionMESA(_EGLDriver *drv, EGLDisplay dpy,
- EGLint screen_number, EGLint x, EGLint y)
+ EGLScreenMESA screen, EGLint x, EGLint y)
{
- _EGLScreen *scrn = _eglLookupScreen(dpy, screen_number);
+ _EGLScreen *scrn = _eglLookupScreen(dpy, screen);
if (!scrn) {
_eglError(EGL_BAD_SCREEN_MESA, "eglScreenPositionMESA");
return EGL_FALSE;
}
-EGLBoolean
-_eglQueryDisplayMESA(_EGLDriver *drv, EGLDisplay dpy,
- EGLint attribute, EGLint *value)
-{
- const _EGLDisplay *display = _eglLookupDisplay(dpy);
- switch (attribute) {
- case EGL_SCREEN_COUNT_MESA:
- *value = display->NumScreens;
- break;
- default:
- _eglError(EGL_BAD_ATTRIBUTE, "eglQueryDisplayMESA");
- return EGL_FALSE;
- }
- return EGL_TRUE;
-}
-
-
/**
* Query a screen's current surface.
*/
EGLBoolean
_eglQueryScreenSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy,
- EGLint screen_number, EGLSurface *surface)
+ EGLScreenMESA screen, EGLSurface *surface)
{
- const _EGLScreen *scrn = _eglLookupScreen(dpy, screen_number);
+ const _EGLScreen *scrn = _eglLookupScreen(dpy, screen);
if (scrn->CurrentSurface)
*surface = scrn->CurrentSurface->Handle;
else
* Query a screen's current mode.
*/
EGLBoolean
-_eglQueryScreenModeMESA(_EGLDriver *drv, EGLDisplay dpy, EGLint screen_number,
+_eglQueryScreenModeMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen,
EGLModeMESA *mode)
{
- const _EGLScreen *scrn = _eglLookupScreen(dpy, screen_number);
+ const _EGLScreen *scrn = _eglLookupScreen(dpy, screen);
if (scrn->CurrentMode)
*mode = scrn->CurrentMode->Handle;
else
EGLBoolean
-_eglQueryScreenMESA(_EGLDriver *drv, EGLDisplay dpy, EGLint screen_number,
+_eglQueryScreenMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen,
EGLint attribute, EGLint *value)
{
- const _EGLScreen *scrn = _eglLookupScreen(dpy, screen_number);
+ const _EGLScreen *scrn = _eglLookupScreen(dpy, screen);
if (!scrn) {
_eglError(EGL_BAD_SCREEN_MESA, "eglQueryScreenMESA");
value[0] = scrn->OriginX;
value[1] = scrn->OriginY;
break;
+ case EGL_SCREEN_POSITION_GRANULARITY_MESA:
+ value[0] = scrn->StepX;
+ value[1] = scrn->StepY;
+ break;
default:
_eglError(EGL_BAD_ATTRIBUTE, "eglQueryScreenMESA");
return EGL_FALSE;
}
+/**
+ * Delete the modes associated with given screen.
+ */
+void
+_eglDestroyScreenModes(_EGLScreen *scrn)
+{
+ EGLint i;
+ for (i = 0; i < scrn->NumModes; i++) {
+ if (scrn->Modes[i].Name)
+ free((char *) scrn->Modes[i].Name); /* cast away const */
+ }
+ if (scrn->Modes)
+ free(scrn->Modes);
+ scrn->Modes = NULL;
+ scrn->NumModes = 0;
+}
+
+/**
+ * Default fallback routine - drivers should usually override this.
+ */
void
-_eglDeleteScreen(_EGLScreen *scrn)
+_eglDestroyScreen(_EGLScreen *scrn)
{
- free(scrn->Modes);
+ _eglDestroyScreenModes(scrn);
free(scrn);
}