0,0 → 1,235 |
/************************************************************************** |
* |
* 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 = 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 */ |