st/egl_g3d: Add support for EGL_MESA_screen_surface.
This is implemented through the modeset interface. Signed-off-by: Chia-I Wu <olvaffe@gmail.com>
This commit is contained in:
parent
c67ad0eee8
commit
2dcdf19ee3
|
@ -327,6 +327,69 @@ get_mode_api_mask(const __GLcontextModes *mode, EGLint api_mask)
|
||||||
return api_mask;
|
return api_mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef EGL_MESA_screen_surface
|
||||||
|
|
||||||
|
static void
|
||||||
|
egl_g3d_add_screens(_EGLDriver *drv, _EGLDisplay *dpy)
|
||||||
|
{
|
||||||
|
struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
|
||||||
|
const struct native_connector **native_connectors;
|
||||||
|
EGLint num_connectors, i;
|
||||||
|
|
||||||
|
native_connectors =
|
||||||
|
gdpy->native->modeset->get_connectors(gdpy->native, &num_connectors, NULL);
|
||||||
|
if (!num_connectors) {
|
||||||
|
if (native_connectors)
|
||||||
|
free(native_connectors);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < num_connectors; i++) {
|
||||||
|
const struct native_connector *nconn = native_connectors[i];
|
||||||
|
struct egl_g3d_screen *gscr;
|
||||||
|
const struct native_mode **native_modes;
|
||||||
|
EGLint num_modes, j;
|
||||||
|
|
||||||
|
/* TODO support for hotplug */
|
||||||
|
native_modes =
|
||||||
|
gdpy->native->modeset->get_modes(gdpy->native, nconn, &num_modes);
|
||||||
|
if (!num_modes) {
|
||||||
|
if (native_modes)
|
||||||
|
free(native_modes);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
gscr = CALLOC_STRUCT(egl_g3d_screen);
|
||||||
|
if (!gscr) {
|
||||||
|
free(native_modes);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
_eglInitScreen(&gscr->base);
|
||||||
|
|
||||||
|
for (j = 0; j < num_modes; j++) {
|
||||||
|
const struct native_mode *nmode = native_modes[j];
|
||||||
|
_EGLMode *mode;
|
||||||
|
|
||||||
|
mode = _eglAddNewMode(&gscr->base, nmode->width, nmode->height,
|
||||||
|
nmode->refresh_rate, nmode->desc);
|
||||||
|
if (!mode)
|
||||||
|
break;
|
||||||
|
/* gscr->native_modes and gscr->base.Modes should be consistent */
|
||||||
|
assert(mode == &gscr->base.Modes[j]);
|
||||||
|
}
|
||||||
|
|
||||||
|
gscr->native = nconn;
|
||||||
|
gscr->native_modes = native_modes;
|
||||||
|
|
||||||
|
_eglAddScreen(dpy, &gscr->base);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(native_connectors);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* EGL_MESA_screen_surface */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add configs to display and return the next config ID.
|
* Add configs to display and return the next config ID.
|
||||||
*/
|
*/
|
||||||
|
@ -365,8 +428,17 @@ egl_g3d_add_configs(_EGLDriver *drv, _EGLDisplay *dpy, EGLint id)
|
||||||
_eglInitConfig(&gconf->base, id);
|
_eglInitConfig(&gconf->base, id);
|
||||||
valid = _eglConfigFromContextModesRec(&gconf->base,
|
valid = _eglConfigFromContextModesRec(&gconf->base,
|
||||||
&native_configs[i]->mode, api_mask, api_mask);
|
&native_configs[i]->mode, api_mask, api_mask);
|
||||||
if (valid)
|
if (valid) {
|
||||||
|
#ifdef EGL_MESA_screen_surface
|
||||||
|
/* check if scanout surface bit is set */
|
||||||
|
if (native_configs[i]->scanout_bit) {
|
||||||
|
EGLint val = GET_CONFIG_ATTRIB(&gconf->base, EGL_SURFACE_TYPE);
|
||||||
|
val |= EGL_SCREEN_BIT_MESA;
|
||||||
|
SET_CONFIG_ATTRIB(&gconf->base, EGL_SURFACE_TYPE, val);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
valid = _eglValidateConfig(&gconf->base, EGL_FALSE);
|
valid = _eglValidateConfig(&gconf->base, EGL_FALSE);
|
||||||
|
}
|
||||||
if (!valid) {
|
if (!valid) {
|
||||||
_eglLog(_EGL_DEBUG, "skip invalid config 0x%x",
|
_eglLog(_EGL_DEBUG, "skip invalid config 0x%x",
|
||||||
native_configs[i]->mode.visualID);
|
native_configs[i]->mode.visualID);
|
||||||
|
@ -403,10 +475,20 @@ static EGLBoolean
|
||||||
egl_g3d_terminate(_EGLDriver *drv, _EGLDisplay *dpy)
|
egl_g3d_terminate(_EGLDriver *drv, _EGLDisplay *dpy)
|
||||||
{
|
{
|
||||||
struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
|
struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
|
||||||
|
EGLint i;
|
||||||
|
|
||||||
_eglReleaseDisplayResources(drv, dpy);
|
_eglReleaseDisplayResources(drv, dpy);
|
||||||
_eglCleanupDisplay(dpy);
|
_eglCleanupDisplay(dpy);
|
||||||
|
|
||||||
|
if (dpy->Screens) {
|
||||||
|
for (i = 0; i < dpy->NumScreens; i++) {
|
||||||
|
struct egl_g3d_screen *gscr = egl_g3d_screen(dpy->Screens[i]);
|
||||||
|
free(gscr->native_modes);
|
||||||
|
free(gscr);
|
||||||
|
}
|
||||||
|
free(dpy->Screens);
|
||||||
|
}
|
||||||
|
|
||||||
if (gdpy->native)
|
if (gdpy->native)
|
||||||
gdpy->native->destroy(gdpy->native);
|
gdpy->native->destroy(gdpy->native);
|
||||||
|
|
||||||
|
@ -444,6 +526,14 @@ egl_g3d_initialize(_EGLDriver *drv, _EGLDisplay *dpy,
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef EGL_MESA_screen_surface
|
||||||
|
/* enable MESA_screen_surface */
|
||||||
|
if (gdpy->native->modeset) {
|
||||||
|
dpy->Extensions.MESA_screen_surface = EGL_TRUE;
|
||||||
|
egl_g3d_add_screens(drv, dpy);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
*major = 1;
|
*major = 1;
|
||||||
*minor = 4;
|
*minor = 4;
|
||||||
|
|
||||||
|
@ -863,6 +953,99 @@ egl_g3d_release_tex_image(_EGLDriver *drv, _EGLDisplay *dpy,
|
||||||
return EGL_TRUE;
|
return EGL_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef EGL_MESA_screen_surface
|
||||||
|
|
||||||
|
static _EGLSurface *
|
||||||
|
egl_g3d_create_screen_surface(_EGLDriver *drv, _EGLDisplay *dpy,
|
||||||
|
_EGLConfig *conf, const EGLint *attribs)
|
||||||
|
{
|
||||||
|
struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
|
||||||
|
struct egl_g3d_config *gconf = egl_g3d_config(conf);
|
||||||
|
struct egl_g3d_surface *gsurf;
|
||||||
|
|
||||||
|
gsurf = CALLOC_STRUCT(egl_g3d_surface);
|
||||||
|
if (!gsurf) {
|
||||||
|
_eglError(EGL_BAD_ALLOC, "eglCreatePbufferSurface");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_eglInitSurface(drv, &gsurf->base,
|
||||||
|
EGL_SCREEN_BIT_MESA, conf, attribs)) {
|
||||||
|
free(gsurf);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
gsurf->native =
|
||||||
|
gdpy->native->modeset->create_scanout_surface(gdpy->native,
|
||||||
|
gconf->native, gsurf->base.Width, gsurf->base.Height);
|
||||||
|
if (!gsurf->native) {
|
||||||
|
free(gsurf);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
gsurf->render_att = (!gconf->native->mode.doubleBufferMode) ?
|
||||||
|
NATIVE_ATTACHMENT_FRONT_LEFT : NATIVE_ATTACHMENT_BACK_LEFT;
|
||||||
|
|
||||||
|
return &gsurf->base;
|
||||||
|
}
|
||||||
|
|
||||||
|
static EGLBoolean
|
||||||
|
egl_g3d_show_screen_surface(_EGLDriver *drv, _EGLDisplay *dpy,
|
||||||
|
_EGLScreen *scr, _EGLSurface *surf,
|
||||||
|
_EGLMode *mode)
|
||||||
|
{
|
||||||
|
struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
|
||||||
|
struct egl_g3d_screen *gscr = egl_g3d_screen(scr);
|
||||||
|
struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
|
||||||
|
struct native_surface *nsurf;
|
||||||
|
const struct native_mode *nmode;
|
||||||
|
EGLBoolean changed;
|
||||||
|
|
||||||
|
if (gsurf) {
|
||||||
|
EGLint idx;
|
||||||
|
|
||||||
|
if (!mode)
|
||||||
|
return _eglError(EGL_BAD_MATCH, "eglShowSurfaceMESA");
|
||||||
|
if (gsurf->base.Type != EGL_SCREEN_BIT_MESA)
|
||||||
|
return _eglError(EGL_BAD_SURFACE, "eglShowScreenSurfaceMESA");
|
||||||
|
if (gsurf->base.Width < mode->Width || gsurf->base.Height < mode->Height)
|
||||||
|
return _eglError(EGL_BAD_MATCH,
|
||||||
|
"eglShowSurfaceMESA(surface smaller than mode size)");
|
||||||
|
|
||||||
|
/* find the index of the mode */
|
||||||
|
for (idx = 0; idx < gscr->base.NumModes; idx++)
|
||||||
|
if (mode == &gscr->base.Modes[idx])
|
||||||
|
break;
|
||||||
|
if (idx >= gscr->base.NumModes) {
|
||||||
|
return _eglError(EGL_BAD_MODE_MESA,
|
||||||
|
"eglShowSurfaceMESA(unknown mode)");
|
||||||
|
}
|
||||||
|
|
||||||
|
nsurf = gsurf->native;
|
||||||
|
nmode = gscr->native_modes[idx];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (mode)
|
||||||
|
return _eglError(EGL_BAD_MATCH, "eglShowSurfaceMESA");
|
||||||
|
|
||||||
|
/* disable the screen */
|
||||||
|
nsurf = NULL;
|
||||||
|
nmode = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO surface panning by CRTC choosing */
|
||||||
|
changed = gdpy->native->modeset->program(gdpy->native, 0, nsurf,
|
||||||
|
gscr->base.OriginX, gscr->base.OriginY, &gscr->native, 1, nmode);
|
||||||
|
if (changed) {
|
||||||
|
gscr->base.CurrentSurface = &gsurf->base;
|
||||||
|
gscr->base.CurrentMode = mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* EGL_MESA_screen_surface */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
egl_g3d_unload(_EGLDriver *drv)
|
egl_g3d_unload(_EGLDriver *drv)
|
||||||
{
|
{
|
||||||
|
@ -903,6 +1086,11 @@ _eglMain(const char *args)
|
||||||
gdrv->base.API.BindTexImage = egl_g3d_bind_tex_image;
|
gdrv->base.API.BindTexImage = egl_g3d_bind_tex_image;
|
||||||
gdrv->base.API.ReleaseTexImage = egl_g3d_release_tex_image;
|
gdrv->base.API.ReleaseTexImage = egl_g3d_release_tex_image;
|
||||||
|
|
||||||
|
#ifdef EGL_MESA_screen_surface
|
||||||
|
gdrv->base.API.CreateScreenSurfaceMESA = egl_g3d_create_screen_surface;
|
||||||
|
gdrv->base.API.ShowScreenSurfaceMESA = egl_g3d_show_screen_surface;
|
||||||
|
#endif
|
||||||
|
|
||||||
gdrv->base.Name = driver_name;
|
gdrv->base.Name = driver_name;
|
||||||
gdrv->base.Unload = egl_g3d_unload;
|
gdrv->base.Unload = egl_g3d_unload;
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,8 @@
|
||||||
#include "eglcontext.h"
|
#include "eglcontext.h"
|
||||||
#include "eglsurface.h"
|
#include "eglsurface.h"
|
||||||
#include "eglconfig.h"
|
#include "eglconfig.h"
|
||||||
|
#include "eglscreen.h"
|
||||||
|
#include "eglmode.h"
|
||||||
|
|
||||||
#include "native.h"
|
#include "native.h"
|
||||||
#include "egl_st.h"
|
#include "egl_st.h"
|
||||||
|
@ -78,6 +80,11 @@ struct egl_g3d_config {
|
||||||
const struct native_config *native;
|
const struct native_config *native;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct egl_g3d_screen {
|
||||||
|
_EGLScreen base;
|
||||||
|
const struct native_connector *native;
|
||||||
|
const struct native_mode **native_modes;
|
||||||
|
};
|
||||||
|
|
||||||
static INLINE struct egl_g3d_driver *
|
static INLINE struct egl_g3d_driver *
|
||||||
egl_g3d_driver(_EGLDriver *drv)
|
egl_g3d_driver(_EGLDriver *drv)
|
||||||
|
@ -110,4 +117,10 @@ egl_g3d_config(_EGLConfig *conf)
|
||||||
return (struct egl_g3d_config *) conf;
|
return (struct egl_g3d_config *) conf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static INLINE struct egl_g3d_screen *
|
||||||
|
egl_g3d_screen(_EGLScreen *scr)
|
||||||
|
{
|
||||||
|
return (struct egl_g3d_screen *) scr;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* _EGL_G3D_H_ */
|
#endif /* _EGL_G3D_H_ */
|
||||||
|
|
Loading…
Reference in New Issue