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:
Chia-I Wu 2010-01-04 12:01:38 +08:00
parent c67ad0eee8
commit 2dcdf19ee3
2 changed files with 202 additions and 1 deletions

View File

@ -327,6 +327,69 @@ get_mode_api_mask(const __GLcontextModes *mode, EGLint 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.
*/
@ -365,8 +428,17 @@ egl_g3d_add_configs(_EGLDriver *drv, _EGLDisplay *dpy, EGLint id)
_eglInitConfig(&gconf->base, id);
valid = _eglConfigFromContextModesRec(&gconf->base,
&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);
}
if (!valid) {
_eglLog(_EGL_DEBUG, "skip invalid config 0x%x",
native_configs[i]->mode.visualID);
@ -403,10 +475,20 @@ static EGLBoolean
egl_g3d_terminate(_EGLDriver *drv, _EGLDisplay *dpy)
{
struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
EGLint i;
_eglReleaseDisplayResources(drv, 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)
gdpy->native->destroy(gdpy->native);
@ -444,6 +526,14 @@ egl_g3d_initialize(_EGLDriver *drv, _EGLDisplay *dpy,
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;
*minor = 4;
@ -863,6 +953,99 @@ egl_g3d_release_tex_image(_EGLDriver *drv, _EGLDisplay *dpy,
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
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.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.Unload = egl_g3d_unload;

View File

@ -34,6 +34,8 @@
#include "eglcontext.h"
#include "eglsurface.h"
#include "eglconfig.h"
#include "eglscreen.h"
#include "eglmode.h"
#include "native.h"
#include "egl_st.h"
@ -78,6 +80,11 @@ struct egl_g3d_config {
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 *
egl_g3d_driver(_EGLDriver *drv)
@ -110,4 +117,10 @@ egl_g3d_config(_EGLConfig *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_ */