/************************************************************************** * * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. * Copyright 2009-2010 Chia-I Wu <olvaffe@gmail.com> * Copyright 2010 LunarG, Inc. * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sub license, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice (including the * next paragraph) shall be included in all copies or substantial portions * of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. * **************************************************************************/ /* * Ideas for screen management extension to EGL. * * Each EGLDisplay has one or more screens (CRTs, Flat Panels, etc). * 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 "eglcurrent.h" #include "eglmode.h" #include "eglsurface.h" #include "eglscreen.h" #include "eglmutex.h" #ifdef EGL_MESA_screen_surface /* ugh, no atomic op? */ static _EGL_DECLARE_MUTEX(_eglNextScreenHandleMutex); static EGLScreenMESA _eglNextScreenHandle = 1; /** * Return a new screen handle/ID. * NOTE: we never reuse these! */ static EGLScreenMESA _eglAllocScreenHandle(void) { EGLScreenMESA s; _eglLockMutex(&_eglNextScreenHandleMutex); s = _eglNextScreenHandle; _eglNextScreenHandle += _EGL_SCREEN_MAX_MODES; _eglUnlockMutex(&_eglNextScreenHandleMutex); return s; } /** * Initialize an _EGLScreen object to default values. */ void _eglInitScreen(_EGLScreen *screen, _EGLDisplay *dpy, EGLint num_modes) { memset(screen, 0, sizeof(_EGLScreen)); screen->Display = dpy; screen->NumModes = num_modes; screen->StepX = 1; screen->StepY = 1; if (num_modes > _EGL_SCREEN_MAX_MODES) num_modes = _EGL_SCREEN_MAX_MODES; screen->Modes = (_EGLMode *) calloc(num_modes, sizeof(*screen->Modes)); screen->NumModes = (screen->Modes) ? num_modes : 0; } /** * Link a screen to its display and return the handle of the link. * The handle can be passed to client directly. */ EGLScreenMESA _eglLinkScreen(_EGLScreen *screen) { _EGLDisplay *display; EGLint i; assert(screen && screen->Display); display = screen->Display; if (!display->Screens) { display->Screens = _eglCreateArray("Screen", 4); if (!display->Screens) return (EGLScreenMESA) 0; } screen->Handle = _eglAllocScreenHandle(); for (i = 0; i < screen->NumModes; i++) screen->Modes[i].Handle = screen->Handle + i; _eglAppendArray(display->Screens, (void *) screen); return screen->Handle; } /** * Lookup a handle to find the linked config. * Return NULL if the handle has no corresponding linked config. */ _EGLScreen * _eglLookupScreen(EGLScreenMESA screen, _EGLDisplay *display) { EGLint i; if (!display || !display->Screens) return NULL; for (i = 0; i < display->Screens->Size; i++) { _EGLScreen *scr = (_EGLScreen *) display->Screens->Elements[i]; if (scr->Handle == screen) { assert(scr->Display == display); return scr; } } return NULL; } static EGLBoolean _eglFlattenScreen(void *elem, void *buffer) { _EGLScreen *scr = (_EGLScreen *) elem; EGLScreenMESA *handle = (EGLScreenMESA *) buffer; *handle = _eglGetScreenHandle(scr); return EGL_TRUE; } EGLBoolean _eglGetScreensMESA(_EGLDriver *drv, _EGLDisplay *display, EGLScreenMESA *screens, EGLint max_screens, EGLint *num_screens) { *num_screens = _eglFlattenArray(display->Screens, (void *) screens, sizeof(screens[0]), max_screens, _eglFlattenScreen); return EGL_TRUE; } /** * Set a screen's surface origin. */ EGLBoolean _eglScreenPositionMESA(_EGLDriver *drv, _EGLDisplay *dpy, _EGLScreen *scrn, EGLint x, EGLint y) { scrn->OriginX = x; scrn->OriginY = y; return EGL_TRUE; } /** * Query a screen's current surface. */ EGLBoolean _eglQueryScreenSurfaceMESA(_EGLDriver *drv, _EGLDisplay *dpy, _EGLScreen *scrn, _EGLSurface **surf) { *surf = scrn->CurrentSurface; return EGL_TRUE; } /** * Query a screen's current mode. */ EGLBoolean _eglQueryScreenModeMESA(_EGLDriver *drv, _EGLDisplay *dpy, _EGLScreen *scrn, _EGLMode **m) { *m = scrn->CurrentMode; return EGL_TRUE; } EGLBoolean _eglQueryScreenMESA(_EGLDriver *drv, _EGLDisplay *dpy, _EGLScreen *scrn, EGLint attribute, EGLint *value) { switch (attribute) { case EGL_SCREEN_POSITION_MESA: 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; } return EGL_TRUE; } #endif /* EGL_MESA_screen_surface */