eglscreen.c revision 08a482e7a9d13db5d4e6fd974942f6699d7d49dc
1/* 2 * Ideas for screen management extension to EGL. 3 * 4 * Each EGLDisplay has one or more screens (CRTs, Flat Panels, etc). 5 * The screens' handles can be obtained with eglGetScreensMESA(). 6 * 7 * A new kind of EGLSurface is possible- one which can be directly scanned 8 * out on a screen. Such a surface is created with eglCreateScreenSurface(). 9 * 10 * To actually display a screen surface on a screen, the eglShowSurface() 11 * function is called. 12 */ 13 14#include <assert.h> 15#include <stdlib.h> 16#include <string.h> 17 18#include "egldisplay.h" 19#include "eglcurrent.h" 20#include "eglmode.h" 21#include "eglconfig.h" 22#include "eglsurface.h" 23#include "eglscreen.h" 24#include "eglmutex.h" 25 26 27#ifdef EGL_MESA_screen_surface 28 29 30/* ugh, no atomic op? */ 31static _EGL_DECLARE_MUTEX(_eglNextScreenHandleMutex); 32static EGLScreenMESA _eglNextScreenHandle = 1; 33 34 35/** 36 * Return a new screen handle/ID. 37 * NOTE: we never reuse these! 38 */ 39static EGLScreenMESA 40_eglAllocScreenHandle(void) 41{ 42 EGLScreenMESA s; 43 44 _eglLockMutex(&_eglNextScreenHandleMutex); 45 s = _eglNextScreenHandle++; 46 _eglUnlockMutex(&_eglNextScreenHandleMutex); 47 48 return s; 49} 50 51 52/** 53 * Initialize an _EGLScreen object to default values. 54 */ 55void 56_eglInitScreen(_EGLScreen *screen) 57{ 58 memset(screen, 0, sizeof(_EGLScreen)); 59 screen->StepX = 1; 60 screen->StepY = 1; 61} 62 63 64/** 65 * Given a public screen handle, return the internal _EGLScreen object. 66 */ 67_EGLScreen * 68_eglLookupScreen(EGLScreenMESA screen, _EGLDisplay *display) 69{ 70 EGLint i; 71 72 if (!display || !display->Screens) 73 return NULL; 74 75 for (i = 0; i < display->Screens->Size; i++) { 76 _EGLScreen *scr = (_EGLScreen *) display->Screens->Elements[i]; 77 if (scr->Handle == screen) 78 return scr; 79 } 80 return NULL; 81} 82 83 84/** 85 * Add the given _EGLScreen to the display's list of screens. 86 */ 87void 88_eglAddScreen(_EGLDisplay *display, _EGLScreen *screen) 89{ 90 assert(display); 91 assert(screen); 92 93 if (!display->Screens) { 94 display->Screens = _eglCreateArray("Screen", 4); 95 if (!display->Screens) 96 return; 97 } 98 screen->Handle = _eglAllocScreenHandle(); 99 _eglAppendArray(display->Screens, (void *) screen); 100} 101 102 103 104static EGLBoolean 105_eglFlattenScreen(void *elem, void *buffer) 106{ 107 _EGLScreen *scr = (_EGLScreen *) elem; 108 EGLScreenMESA *handle = (EGLScreenMESA *) buffer; 109 *handle = scr->Handle; 110 return EGL_TRUE; 111} 112 113 114EGLBoolean 115_eglGetScreensMESA(_EGLDriver *drv, _EGLDisplay *display, EGLScreenMESA *screens, 116 EGLint max_screens, EGLint *num_screens) 117{ 118 *num_screens = _eglFlattenArray(display->Screens, (void *) screens, 119 sizeof(screens[0]), max_screens, _eglFlattenScreen); 120 121 return EGL_TRUE; 122} 123 124 125/** 126 * Drivers should do a proper implementation. 127 */ 128_EGLSurface * 129_eglCreateScreenSurfaceMESA(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, 130 const EGLint *attrib_list) 131{ 132 return NULL; 133} 134 135 136/** 137 * Show the given surface on the named screen. 138 * If surface is EGL_NO_SURFACE, disable the screen's output. 139 * 140 * This is just a placeholder function; drivers will always override 141 * this with code that _really_ shows the surface. 142 */ 143EGLBoolean 144_eglShowScreenSurfaceMESA(_EGLDriver *drv, _EGLDisplay *dpy, 145 _EGLScreen *scrn, _EGLSurface *surf, 146 _EGLMode *mode) 147{ 148 if (!surf) { 149 scrn->CurrentSurface = NULL; 150 } 151 else { 152 if (surf->Type != EGL_SCREEN_BIT_MESA) { 153 _eglError(EGL_BAD_SURFACE, "eglShowSurfaceMESA"); 154 return EGL_FALSE; 155 } 156 if (surf->Width < mode->Width || surf->Height < mode->Height) { 157 _eglError(EGL_BAD_SURFACE, 158 "eglShowSurfaceMESA(surface smaller than screen size)"); 159 return EGL_FALSE; 160 } 161 162 scrn->CurrentSurface = surf; 163 scrn->CurrentMode = mode; 164 } 165 return EGL_TRUE; 166} 167 168 169/** 170 * Set a screen's current display mode. 171 * Note: mode = EGL_NO_MODE is valid (turns off the screen) 172 * 173 * This is just a placeholder function; drivers will always override 174 * this with code that _really_ sets the mode. 175 */ 176EGLBoolean 177_eglScreenModeMESA(_EGLDriver *drv, _EGLDisplay *dpy, _EGLScreen *scrn, 178 _EGLMode *m) 179{ 180 scrn->CurrentMode = m; 181 return EGL_TRUE; 182} 183 184 185/** 186 * Set a screen's surface origin. 187 */ 188EGLBoolean 189_eglScreenPositionMESA(_EGLDriver *drv, _EGLDisplay *dpy, 190 _EGLScreen *scrn, EGLint x, EGLint y) 191{ 192 scrn->OriginX = x; 193 scrn->OriginY = y; 194 195 return EGL_TRUE; 196} 197 198 199/** 200 * Query a screen's current surface. 201 */ 202EGLBoolean 203_eglQueryScreenSurfaceMESA(_EGLDriver *drv, _EGLDisplay *dpy, 204 _EGLScreen *scrn, _EGLSurface **surf) 205{ 206 *surf = scrn->CurrentSurface; 207 return EGL_TRUE; 208} 209 210 211/** 212 * Query a screen's current mode. 213 */ 214EGLBoolean 215_eglQueryScreenModeMESA(_EGLDriver *drv, _EGLDisplay *dpy, _EGLScreen *scrn, 216 _EGLMode **m) 217{ 218 *m = scrn->CurrentMode; 219 return EGL_TRUE; 220} 221 222 223EGLBoolean 224_eglQueryScreenMESA(_EGLDriver *drv, _EGLDisplay *dpy, _EGLScreen *scrn, 225 EGLint attribute, EGLint *value) 226{ 227 switch (attribute) { 228 case EGL_SCREEN_POSITION_MESA: 229 value[0] = scrn->OriginX; 230 value[1] = scrn->OriginY; 231 break; 232 case EGL_SCREEN_POSITION_GRANULARITY_MESA: 233 value[0] = scrn->StepX; 234 value[1] = scrn->StepY; 235 break; 236 default: 237 _eglError(EGL_BAD_ATTRIBUTE, "eglQueryScreenMESA"); 238 return EGL_FALSE; 239 } 240 241 return EGL_TRUE; 242} 243 244 245/** 246 * Delete the modes associated with given screen. 247 */ 248void 249_eglDestroyScreenModes(_EGLScreen *scrn) 250{ 251 EGLint i; 252 for (i = 0; i < scrn->NumModes; i++) { 253 if (scrn->Modes[i].Name) 254 free((char *) scrn->Modes[i].Name); /* cast away const */ 255 } 256 if (scrn->Modes) 257 free(scrn->Modes); 258 scrn->Modes = NULL; 259 scrn->NumModes = 0; 260} 261 262 263/** 264 * Default fallback routine - drivers should usually override this. 265 */ 266void 267_eglDestroyScreen(_EGLScreen *scrn) 268{ 269 _eglDestroyScreenModes(scrn); 270 free(scrn); 271} 272 273 274#endif /* EGL_MESA_screen_surface */ 275