mesa/src/egl/main/egldisplay.c

381 lines
7.9 KiB
C
Raw Normal View History

/**
* Functions related to EGLDisplay.
*/
#include <assert.h>
2005-04-22 22:09:39 +01:00
#include <stdlib.h>
#include <string.h>
#include "eglcontext.h"
#include "eglsurface.h"
2005-04-22 22:09:39 +01:00
#include "egldisplay.h"
#include "egldriver.h"
2005-04-22 22:09:39 +01:00
#include "eglglobals.h"
#include "eglhash.h"
2008-05-28 19:56:36 +01:00
#include "eglstring.h"
#include "eglmutex.h"
static _EGL_DECLARE_MUTEX(_eglDisplayInitMutex);
static _EGLHashtable *_eglDisplayHash;
/* TODO surface hash table should be per-display */
static _EGLHashtable *_eglSurfaceHash;
/**
* Finish display management.
*/
static void
_eglFiniDisplay(void)
{
_eglLockMutex(&_eglDisplayInitMutex);
if (_eglDisplayHash) {
/* XXX TODO walk over table entries, deleting each */
_eglDeleteHashTable(_eglDisplayHash);
_eglDisplayHash = NULL;
_eglDeleteHashTable(_eglSurfaceHash);
_eglSurfaceHash = NULL;
}
_eglUnlockMutex(&_eglDisplayInitMutex);
}
/* This can be avoided if hash table can be statically initialized */
static INLINE void
_eglInitDisplay(void)
{
if (!_eglDisplayHash) {
_eglLockMutex(&_eglDisplayInitMutex);
/* check again after acquiring lock */
if (!_eglDisplayHash) {
_eglDisplayHash = _eglNewHashTable();
_eglSurfaceHash = _eglNewHashTable();
(void) _eglFiniDisplay;
}
_eglUnlockMutex(&_eglDisplayInitMutex);
}
}
2005-04-22 22:09:39 +01:00
/**
* Allocate a new _EGLDisplay object for the given nativeDisplay handle.
* We'll also try to determine the device driver name at this time.
2008-05-28 19:56:36 +01:00
*
* Note that nativeDisplay may be an X Display ptr, or a string.
2005-04-22 22:09:39 +01:00
*/
_EGLDisplay *
_eglNewDisplay(NativeDisplayType nativeDisplay)
2005-04-22 22:09:39 +01:00
{
2005-12-23 08:17:44 +00:00
_EGLDisplay *dpy = (_EGLDisplay *) calloc(1, sizeof(_EGLDisplay));
2005-04-22 22:09:39 +01:00
if (dpy) {
dpy->NativeDisplay = nativeDisplay;
#if defined(_EGL_PLATFORM_X)
dpy->Xdpy = (Display *) nativeDisplay;
#endif
_eglInitDisplay();
dpy->SurfaceHash = _eglSurfaceHash;
dpy->DriverName = _eglChooseDriver(dpy);
if (!dpy->DriverName) {
free(dpy);
return NULL;
}
2005-04-22 22:09:39 +01:00
}
return dpy;
}
/**
* Link a display to itself and return the handle of the link.
* The handle can be passed to client directly.
*/
EGLDisplay
_eglLinkDisplay(_EGLDisplay *dpy)
{
EGLuint key;
_eglInitDisplay();
key = _eglHashGenKey(_eglDisplayHash);
assert(key);
/* "link" the display to the hash table */
_eglHashInsert(_eglDisplayHash, key, dpy);
dpy->Handle = (EGLDisplay) _eglUIntToPointer(key);
return dpy->Handle;
}
/**
* Unlink a linked display from itself.
* Accessing an unlinked display should generate EGL_BAD_DISPLAY error.
*/
void
_eglUnlinkDisplay(_EGLDisplay *dpy)
{
EGLuint key = _eglPointerToUInt((void *) dpy->Handle);
_eglInitDisplay();
_eglHashRemove(_eglDisplayHash, key);
dpy->Handle = EGL_NO_DISPLAY;
}
/**
* Return the handle of a linked display, or EGL_NO_DISPLAY.
*/
EGLDisplay
_eglGetDisplayHandle(_EGLDisplay *display)
{
if (display)
return display->Handle;
else
return EGL_NO_DISPLAY;
}
2005-04-22 22:09:39 +01:00
/**
* Lookup a handle to find the linked display.
* Return NULL if the handle has no corresponding linked display.
2005-04-22 22:09:39 +01:00
*/
_EGLDisplay *
_eglLookupDisplay(EGLDisplay dpy)
{
EGLuint key = _eglPointerToUInt((void *) dpy);
_eglInitDisplay();
return (_EGLDisplay *) _eglHashLookup(_eglDisplayHash, key);
2005-04-22 22:09:39 +01:00
}
/**
* Find the display corresponding to the specified native display id in all
* linked displays.
*/
_EGLDisplay *
_eglFindDisplay(NativeDisplayType nativeDisplay)
{
EGLuint key;
_eglInitDisplay();
/* Walk the hash table. Should switch to list if it is a problem. */
key = _eglHashFirstEntry(_eglDisplayHash);
while (key) {
_EGLDisplay *dpy = (_EGLDisplay *)
_eglHashLookup(_eglDisplayHash, key);
assert(dpy);
if (dpy->NativeDisplay == nativeDisplay)
return dpy;
key = _eglHashNextEntry(_eglDisplayHash, key);
}
return NULL;
}
/**
* Destroy the contexts and surfaces that are linked to the display.
*/
void
_eglReleaseDisplayResources(_EGLDriver *drv, EGLDisplay dpy)
{
_EGLDisplay *display;
_EGLContext *contexts;
_EGLSurface *surfaces;
display = _eglLookupDisplay(dpy);
if (!display)
return;
contexts = display->ContextList;
surfaces = display->SurfaceList;
while (contexts) {
EGLContext handle = _eglGetContextHandle(contexts);
contexts = contexts->Next;
drv->API.DestroyContext(drv, dpy, handle);
}
assert(!display->ContextList);
while (surfaces) {
EGLSurface handle = _eglGetSurfaceHandle(surfaces);
surfaces = surfaces->Next;
drv->API.DestroySurface(drv, dpy, handle);
}
assert(!display->SurfaceList);
}
/**
* Free all the data hanging of an _EGLDisplay object, but not
* the object itself.
*/
2005-04-22 22:09:39 +01:00
void
_eglCleanupDisplay(_EGLDisplay *disp)
2005-04-22 22:09:39 +01:00
{
EGLint i;
for (i = 0; i < disp->NumConfigs; i++) {
free(disp->Configs[i]);
}
2005-04-22 22:09:39 +01:00
free(disp->Configs);
disp->Configs = NULL;
/* XXX incomplete */
free((void *) disp->DriverName);
disp->DriverName = NULL;
/* driver deletes the _EGLDisplay object */
2005-04-22 22:09:39 +01:00
}
/**
* Link a context to a display and return the handle of the link.
* The handle can be passed to client directly.
*/
EGLContext
_eglLinkContext(_EGLContext *ctx, _EGLDisplay *dpy)
{
ctx->Display = dpy;
ctx->Next = dpy->ContextList;
dpy->ContextList = ctx;
return (EGLContext) ctx;
}
/**
* Unlink a linked context from its display.
* Accessing an unlinked context should generate EGL_BAD_CONTEXT error.
*/
void
_eglUnlinkContext(_EGLContext *ctx)
{
_EGLContext *prev;
prev = ctx->Display->ContextList;
if (prev != ctx) {
while (prev) {
if (prev->Next == ctx)
break;
prev = prev->Next;
}
assert(prev);
prev->Next = ctx->Next;
}
else {
ctx->Display->ContextList = ctx->Next;
}
ctx->Next = NULL;
ctx->Display = NULL;
}
/**
* Return the handle of a linked context, or EGL_NO_CONTEXT.
*/
EGLContext
_eglGetContextHandle(_EGLContext *ctx)
{
return (EGLContext) ((ctx && ctx->Display) ? ctx : EGL_NO_CONTEXT);
}
/**
* Lookup a handle to find the linked context.
* Return NULL if the handle has no corresponding linked context.
*/
_EGLContext *
_eglLookupContext(EGLContext ctx)
{
_EGLContext *context = (_EGLContext *) ctx;
return (context && context->Display) ? context : NULL;
}
/**
* Link a surface to a display and return the handle of the link.
* The handle can be passed to client directly.
*/
EGLSurface
_eglLinkSurface(_EGLSurface *surf, _EGLDisplay *dpy)
{
EGLuint key;
surf->Display = dpy;
surf->Next = dpy->SurfaceList;
dpy->SurfaceList = surf;
key = _eglHashGenKey(dpy->SurfaceHash);
assert(key);
_eglHashInsert(dpy->SurfaceHash, key, surf);
surf->Handle = (EGLSurface) _eglUIntToPointer(key);
return surf->Handle;
}
/**
* Unlink a linked surface from its display.
* Accessing an unlinked surface should generate EGL_BAD_SURFACE error.
*/
void
_eglUnlinkSurface(_EGLSurface *surf)
{
_EGLSurface *prev;
EGLuint key = _eglPointerToUInt((void *) surf->Handle);
_eglHashRemove(surf->Display->SurfaceHash, key);
surf->Handle = EGL_NO_SURFACE;
prev = surf->Display->SurfaceList;
if (prev != surf) {
while (prev) {
if (prev->Next == surf)
break;
prev = prev->Next;
}
assert(prev);
prev->Next = surf->Next;
}
else {
prev = NULL;
surf->Display->SurfaceList = surf->Next;
}
surf->Next = NULL;
surf->Display = NULL;
}
/**
* Return the handle of a linked surface, or EGL_NO_SURFACE.
*/
EGLSurface
_eglGetSurfaceHandle(_EGLSurface *surface)
{
if (surface)
return surface->Handle;
else
return EGL_NO_SURFACE;
}
/**
* Lookup a handle to find the linked surface.
* Return NULL if the handle has no corresponding linked surface.
*/
_EGLSurface *
_eglLookupSurface(EGLSurface surf)
{
EGLuint key = _eglPointerToUInt((void *) surf);
return (_EGLSurface *) _eglHashLookup(_eglSurfaceHash, key);
}