mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-25 21:18:26 +02:00
328 lines
7.3 KiB
C
328 lines
7.3 KiB
C
/*
|
|
* 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 "eglglobals.h"
|
|
#include "eglmode.h"
|
|
#include "eglconfig.h"
|
|
#include "eglsurface.h"
|
|
#include "eglscreen.h"
|
|
|
|
|
|
/**
|
|
* Return a new screen handle/ID.
|
|
* NOTE: we never reuse these!
|
|
*/
|
|
EGLScreenMESA
|
|
_eglAllocScreenHandle(void)
|
|
{
|
|
EGLScreenMESA s = _eglGlobal.FreeScreenHandle;
|
|
_eglGlobal.FreeScreenHandle++;
|
|
return s;
|
|
}
|
|
|
|
|
|
/**
|
|
* Initialize an _EGLScreen object to default values.
|
|
*/
|
|
void
|
|
_eglInitScreen(_EGLScreen *screen)
|
|
{
|
|
memset(screen, 0, sizeof(_EGLScreen));
|
|
screen->StepX = 1;
|
|
screen->StepY = 1;
|
|
}
|
|
|
|
|
|
/**
|
|
* Given a public screen handle, return the internal _EGLScreen object.
|
|
*/
|
|
_EGLScreen *
|
|
_eglLookupScreen(EGLDisplay dpy, EGLScreenMESA screen)
|
|
{
|
|
EGLint i;
|
|
_EGLDisplay *display = _eglLookupDisplay(dpy);
|
|
|
|
if (!display)
|
|
return NULL;
|
|
|
|
for (i = 0; i < display->NumScreens; i++) {
|
|
if (display->Screens[i]->Handle == screen)
|
|
return display->Screens[i];
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
|
|
/**
|
|
* Add the given _EGLScreen to the display's list of screens.
|
|
*/
|
|
void
|
|
_eglAddScreen(_EGLDisplay *display, _EGLScreen *screen)
|
|
{
|
|
EGLint n;
|
|
|
|
assert(display);
|
|
assert(screen);
|
|
|
|
screen->Handle = _eglAllocScreenHandle();
|
|
n = display->NumScreens;
|
|
display->Screens = realloc(display->Screens, (n+1) * sizeof(_EGLScreen *));
|
|
display->Screens[n] = screen;
|
|
display->NumScreens++;
|
|
}
|
|
|
|
|
|
|
|
EGLBoolean
|
|
_eglGetScreensMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA *screens,
|
|
EGLint max_screens, EGLint *num_screens)
|
|
{
|
|
_EGLDisplay *display = _eglLookupDisplay(dpy);
|
|
EGLint n;
|
|
|
|
if (!display) {
|
|
_eglError(EGL_BAD_DISPLAY, "eglGetScreensMESA");
|
|
return EGL_FALSE;
|
|
}
|
|
|
|
if (display->NumScreens > max_screens) {
|
|
n = max_screens;
|
|
}
|
|
else {
|
|
n = display->NumScreens;
|
|
}
|
|
|
|
if (screens) {
|
|
EGLint i;
|
|
for (i = 0; i < n; i++)
|
|
screens[i] = display->Screens[i]->Handle;
|
|
}
|
|
if (num_screens)
|
|
*num_screens = n;
|
|
|
|
return EGL_TRUE;
|
|
}
|
|
|
|
|
|
/**
|
|
* Example function - drivers should do a proper implementation.
|
|
*/
|
|
EGLSurface
|
|
_eglCreateScreenSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
|
|
const EGLint *attrib_list)
|
|
{
|
|
#if 0 /* THIS IS JUST EXAMPLE CODE */
|
|
_EGLSurface *surf;
|
|
|
|
surf = (_EGLSurface *) calloc(1, sizeof(_EGLSurface));
|
|
if (!surf)
|
|
return EGL_NO_SURFACE;
|
|
|
|
if (!_eglInitSurface(drv, dpy, surf, EGL_SCREEN_BIT_MESA,
|
|
config, attrib_list)) {
|
|
free(surf);
|
|
return EGL_NO_SURFACE;
|
|
}
|
|
|
|
_eglSaveSurface(surf);
|
|
|
|
return surf->Handle;
|
|
#endif
|
|
return EGL_NO_SURFACE;
|
|
}
|
|
|
|
|
|
/**
|
|
* Show the given surface on the named screen.
|
|
* If surface is EGL_NO_SURFACE, disable the screen's output.
|
|
*
|
|
* This is just a placeholder function; drivers will always override
|
|
* this with code that _really_ shows the surface.
|
|
*/
|
|
EGLBoolean
|
|
_eglShowScreenSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy,
|
|
EGLScreenMESA screen, EGLSurface surface,
|
|
EGLModeMESA m)
|
|
{
|
|
_EGLScreen *scrn = _eglLookupScreen(dpy, screen);
|
|
_EGLMode *mode = _eglLookupMode(dpy, m);
|
|
|
|
if (!scrn) {
|
|
_eglError(EGL_BAD_SCREEN_MESA, "eglShowSurfaceMESA");
|
|
return EGL_FALSE;
|
|
}
|
|
if (!mode && (m != EGL_NO_MODE_MESA )) {
|
|
_eglError(EGL_BAD_MODE_MESA, "eglShowSurfaceMESA");
|
|
return EGL_FALSE;
|
|
}
|
|
|
|
if (surface == EGL_NO_SURFACE) {
|
|
scrn->CurrentSurface = NULL;
|
|
}
|
|
else {
|
|
_EGLSurface *surf = _eglLookupSurface(surface);
|
|
if (!surf || surf->Type != EGL_SCREEN_BIT_MESA) {
|
|
_eglError(EGL_BAD_SURFACE, "eglShowSurfaceMESA");
|
|
return EGL_FALSE;
|
|
}
|
|
if (surf->Width < mode->Width || surf->Height < mode->Height) {
|
|
_eglError(EGL_BAD_SURFACE,
|
|
"eglShowSurfaceMESA(surface smaller than screen size)");
|
|
return EGL_FALSE;
|
|
}
|
|
|
|
scrn->CurrentSurface = surf;
|
|
scrn->CurrentMode = mode;
|
|
}
|
|
return EGL_TRUE;
|
|
}
|
|
|
|
|
|
/**
|
|
* Set a screen's current display mode.
|
|
* Note: mode = EGL_NO_MODE is valid (turns off the screen)
|
|
*
|
|
* This is just a placeholder function; drivers will always override
|
|
* this with code that _really_ sets the mode.
|
|
*/
|
|
EGLBoolean
|
|
_eglScreenModeMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen,
|
|
EGLModeMESA mode)
|
|
{
|
|
_EGLScreen *scrn = _eglLookupScreen(dpy, screen);
|
|
|
|
if (!scrn) {
|
|
_eglError(EGL_BAD_SCREEN_MESA, "eglScreenModeMESA");
|
|
return EGL_FALSE;
|
|
}
|
|
|
|
scrn->CurrentMode = _eglLookupMode(dpy, mode);
|
|
|
|
return EGL_TRUE;
|
|
}
|
|
|
|
|
|
/**
|
|
* Set a screen's surface origin.
|
|
*/
|
|
EGLBoolean
|
|
_eglScreenPositionMESA(_EGLDriver *drv, EGLDisplay dpy,
|
|
EGLScreenMESA screen, EGLint x, EGLint y)
|
|
{
|
|
_EGLScreen *scrn = _eglLookupScreen(dpy, screen);
|
|
if (!scrn) {
|
|
_eglError(EGL_BAD_SCREEN_MESA, "eglScreenPositionMESA");
|
|
return EGL_FALSE;
|
|
}
|
|
|
|
scrn->OriginX = x;
|
|
scrn->OriginY = y;
|
|
|
|
return EGL_TRUE;
|
|
}
|
|
|
|
|
|
/**
|
|
* Query a screen's current surface.
|
|
*/
|
|
EGLBoolean
|
|
_eglQueryScreenSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy,
|
|
EGLScreenMESA screen, EGLSurface *surface)
|
|
{
|
|
const _EGLScreen *scrn = _eglLookupScreen(dpy, screen);
|
|
if (scrn->CurrentSurface)
|
|
*surface = scrn->CurrentSurface->Handle;
|
|
else
|
|
*surface = EGL_NO_SURFACE;
|
|
return EGL_TRUE;
|
|
}
|
|
|
|
|
|
/**
|
|
* Query a screen's current mode.
|
|
*/
|
|
EGLBoolean
|
|
_eglQueryScreenModeMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen,
|
|
EGLModeMESA *mode)
|
|
{
|
|
const _EGLScreen *scrn = _eglLookupScreen(dpy, screen);
|
|
if (scrn->CurrentMode)
|
|
*mode = scrn->CurrentMode->Handle;
|
|
else
|
|
*mode = EGL_NO_MODE_MESA;
|
|
return EGL_TRUE;
|
|
}
|
|
|
|
|
|
EGLBoolean
|
|
_eglQueryScreenMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen,
|
|
EGLint attribute, EGLint *value)
|
|
{
|
|
const _EGLScreen *scrn = _eglLookupScreen(dpy, screen);
|
|
|
|
if (!scrn) {
|
|
_eglError(EGL_BAD_SCREEN_MESA, "eglQueryScreenMESA");
|
|
return EGL_FALSE;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
|
|
/**
|
|
* Delete the modes associated with given screen.
|
|
*/
|
|
void
|
|
_eglDestroyScreenModes(_EGLScreen *scrn)
|
|
{
|
|
EGLint i;
|
|
for (i = 0; i < scrn->NumModes; i++) {
|
|
if (scrn->Modes[i].Name)
|
|
free((char *) scrn->Modes[i].Name); /* cast away const */
|
|
}
|
|
if (scrn->Modes)
|
|
free(scrn->Modes);
|
|
scrn->Modes = NULL;
|
|
scrn->NumModes = 0;
|
|
}
|
|
|
|
|
|
/**
|
|
* Default fallback routine - drivers should usually override this.
|
|
*/
|
|
void
|
|
_eglDestroyScreen(_EGLScreen *scrn)
|
|
{
|
|
_eglDestroyScreenModes(scrn);
|
|
free(scrn);
|
|
}
|
|
|