Home | History | Annotate | Download | only in main
      1 /**************************************************************************
      2  *
      3  * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
      4  * Copyright 2009-2010 Chia-I Wu <olvaffe (at) gmail.com>
      5  * Copyright 2010 LunarG, Inc.
      6  * All Rights Reserved.
      7  *
      8  * Permission is hereby granted, free of charge, to any person obtaining a
      9  * copy of this software and associated documentation files (the
     10  * "Software"), to deal in the Software without restriction, including
     11  * without limitation the rights to use, copy, modify, merge, publish,
     12  * distribute, sub license, and/or sell copies of the Software, and to
     13  * permit persons to whom the Software is furnished to do so, subject to
     14  * the following conditions:
     15  *
     16  * The above copyright notice and this permission notice (including the
     17  * next paragraph) shall be included in all copies or substantial portions
     18  * of the Software.
     19  *
     20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     21  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     22  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     23  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     24  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     25  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     26  * DEALINGS IN THE SOFTWARE.
     27  *
     28  **************************************************************************/
     29 
     30 
     31 /*
     32  * Ideas for screen management extension to EGL.
     33  *
     34  * Each EGLDisplay has one or more screens (CRTs, Flat Panels, etc).
     35  * The screens' handles can be obtained with eglGetScreensMESA().
     36  *
     37  * A new kind of EGLSurface is possible- one which can be directly scanned
     38  * out on a screen.  Such a surface is created with eglCreateScreenSurface().
     39  *
     40  * To actually display a screen surface on a screen, the eglShowSurface()
     41  * function is called.
     42  */
     43 
     44 #include <assert.h>
     45 #include <stdlib.h>
     46 #include <string.h>
     47 
     48 #include "egldisplay.h"
     49 #include "eglcurrent.h"
     50 #include "eglmode.h"
     51 #include "eglsurface.h"
     52 #include "eglscreen.h"
     53 #include "eglmutex.h"
     54 
     55 
     56 #ifdef EGL_MESA_screen_surface
     57 
     58 
     59 /* ugh, no atomic op? */
     60 static _EGL_DECLARE_MUTEX(_eglNextScreenHandleMutex);
     61 static EGLScreenMESA _eglNextScreenHandle = 1;
     62 
     63 
     64 /**
     65  * Return a new screen handle/ID.
     66  * NOTE: we never reuse these!
     67  */
     68 static EGLScreenMESA
     69 _eglAllocScreenHandle(void)
     70 {
     71    EGLScreenMESA s;
     72 
     73    _eglLockMutex(&_eglNextScreenHandleMutex);
     74    s = _eglNextScreenHandle;
     75    _eglNextScreenHandle += _EGL_SCREEN_MAX_MODES;
     76    _eglUnlockMutex(&_eglNextScreenHandleMutex);
     77 
     78    return s;
     79 }
     80 
     81 
     82 /**
     83  * Initialize an _EGLScreen object to default values.
     84  */
     85 void
     86 _eglInitScreen(_EGLScreen *screen, _EGLDisplay *dpy, EGLint num_modes)
     87 {
     88    memset(screen, 0, sizeof(_EGLScreen));
     89 
     90    screen->Display = dpy;
     91    screen->NumModes = num_modes;
     92    screen->StepX = 1;
     93    screen->StepY = 1;
     94 
     95    if (num_modes > _EGL_SCREEN_MAX_MODES)
     96       num_modes = _EGL_SCREEN_MAX_MODES;
     97    screen->Modes = (_EGLMode *) calloc(num_modes, sizeof(*screen->Modes));
     98    screen->NumModes = (screen->Modes) ? num_modes : 0;
     99 }
    100 
    101 
    102 /**
    103  * Link a screen to its display and return the handle of the link.
    104  * The handle can be passed to client directly.
    105  */
    106 EGLScreenMESA
    107 _eglLinkScreen(_EGLScreen *screen)
    108 {
    109    _EGLDisplay *display;
    110    EGLint i;
    111 
    112    assert(screen && screen->Display);
    113    display = screen->Display;
    114 
    115    if (!display->Screens) {
    116       display->Screens = _eglCreateArray("Screen", 4);
    117       if (!display->Screens)
    118          return (EGLScreenMESA) 0;
    119    }
    120 
    121    screen->Handle = _eglAllocScreenHandle();
    122    for (i = 0; i < screen->NumModes; i++)
    123       screen->Modes[i].Handle = screen->Handle + i;
    124 
    125    _eglAppendArray(display->Screens, (void *) screen);
    126 
    127    return screen->Handle;
    128 }
    129 
    130 
    131 /**
    132  * Lookup a handle to find the linked config.
    133  * Return NULL if the handle has no corresponding linked config.
    134  */
    135 _EGLScreen *
    136 _eglLookupScreen(EGLScreenMESA screen, _EGLDisplay *display)
    137 {
    138    EGLint i;
    139 
    140    if (!display || !display->Screens)
    141       return NULL;
    142 
    143    for (i = 0; i < display->Screens->Size; i++) {
    144       _EGLScreen *scr = (_EGLScreen *) display->Screens->Elements[i];
    145       if (scr->Handle == screen) {
    146          assert(scr->Display == display);
    147          return scr;
    148       }
    149    }
    150    return NULL;
    151 }
    152 
    153 
    154 static EGLBoolean
    155 _eglFlattenScreen(void *elem, void *buffer)
    156 {
    157    _EGLScreen *scr = (_EGLScreen *) elem;
    158    EGLScreenMESA *handle = (EGLScreenMESA *) buffer;
    159    *handle = _eglGetScreenHandle(scr);
    160    return EGL_TRUE;
    161 }
    162 
    163 
    164 EGLBoolean
    165 _eglGetScreensMESA(_EGLDriver *drv, _EGLDisplay *display, EGLScreenMESA *screens,
    166                    EGLint max_screens, EGLint *num_screens)
    167 {
    168    *num_screens = _eglFlattenArray(display->Screens, (void *) screens,
    169          sizeof(screens[0]), max_screens, _eglFlattenScreen);
    170 
    171    return EGL_TRUE;
    172 }
    173 
    174 
    175 /**
    176  * Set a screen's surface origin.
    177  */
    178 EGLBoolean
    179 _eglScreenPositionMESA(_EGLDriver *drv, _EGLDisplay *dpy,
    180                        _EGLScreen *scrn, EGLint x, EGLint y)
    181 {
    182    scrn->OriginX = x;
    183    scrn->OriginY = y;
    184 
    185    return EGL_TRUE;
    186 }
    187 
    188 
    189 /**
    190  * Query a screen's current surface.
    191  */
    192 EGLBoolean
    193 _eglQueryScreenSurfaceMESA(_EGLDriver *drv, _EGLDisplay *dpy,
    194                            _EGLScreen *scrn, _EGLSurface **surf)
    195 {
    196    *surf = scrn->CurrentSurface;
    197    return EGL_TRUE;
    198 }
    199 
    200 
    201 /**
    202  * Query a screen's current mode.
    203  */
    204 EGLBoolean
    205 _eglQueryScreenModeMESA(_EGLDriver *drv, _EGLDisplay *dpy, _EGLScreen *scrn,
    206                         _EGLMode **m)
    207 {
    208    *m = scrn->CurrentMode;
    209    return EGL_TRUE;
    210 }
    211 
    212 
    213 EGLBoolean
    214 _eglQueryScreenMESA(_EGLDriver *drv, _EGLDisplay *dpy, _EGLScreen *scrn,
    215                     EGLint attribute, EGLint *value)
    216 {
    217    switch (attribute) {
    218    case EGL_SCREEN_POSITION_MESA:
    219       value[0] = scrn->OriginX;
    220       value[1] = scrn->OriginY;
    221       break;
    222    case EGL_SCREEN_POSITION_GRANULARITY_MESA:
    223       value[0] = scrn->StepX;
    224       value[1] = scrn->StepY;
    225       break;
    226    default:
    227       _eglError(EGL_BAD_ATTRIBUTE, "eglQueryScreenMESA");
    228       return EGL_FALSE;
    229    }
    230 
    231    return EGL_TRUE;
    232 }
    233 
    234 
    235 #endif /* EGL_MESA_screen_surface */
    236