egl: Make display and surface hash tables local.
[mesa.git] / src / egl / main / eglscreen.c
index c3c1a47984735cab61507c4f9409c8f118e730d3..b6bde65e8b52a80c8611c8478a54b55775bb90a2 100644 (file)
  * 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;
 }
 
 
@@ -87,25 +160,19 @@ _eglCreateScreenSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
  * 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;
    }
 
@@ -125,8 +192,8 @@ _eglShowSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy, EGLint screen_number,
       }
 
       scrn->CurrentSurface = surf;
+      scrn->CurrentMode = mode;
    }
-
    return EGL_TRUE;
 }
 
@@ -139,10 +206,10 @@ _eglShowSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy, EGLint screen_number,
  * 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");
@@ -160,9 +227,9 @@ _eglScreenModeMESA(_EGLDriver *drv, EGLDisplay dpy, EGLint screen_number,
  */
 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;
@@ -175,31 +242,14 @@ _eglScreenPositionMESA(_EGLDriver *drv, EGLDisplay dpy,
 }
 
 
-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
@@ -212,10 +262,10 @@ _eglQueryScreenSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy,
  * 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
@@ -225,10 +275,10 @@ _eglQueryScreenModeMESA(_EGLDriver *drv, EGLDisplay dpy, EGLint screen_number,
 
 
 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");
@@ -240,6 +290,10 @@ _eglQueryScreenMESA(_EGLDriver *drv, EGLDisplay dpy, EGLint screen_number,
       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;
@@ -249,11 +303,31 @@ _eglQueryScreenMESA(_EGLDriver *drv, EGLDisplay dpy, EGLint screen_number,
 }
 
 
+/**
+ * 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);
 }