summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChia-I Wu <olvaffe@gmail.com>2010-01-04 12:01:38 +0800
committerChia-I Wu <olvaffe@gmail.com>2010-01-12 11:09:00 +0800
commit2dcdf19ee3a19fb41005d53f0dbc6e8a3970a8b6 (patch)
treebe78990741546a5891e381529e15258b02b5f3cc
parentc67ad0eee8f75e1fd65e8ab2fdd660dc132764ee (diff)
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>
-rw-r--r--src/gallium/state_trackers/egl_g3d/common/egl_g3d.c190
-rw-r--r--src/gallium/state_trackers/egl_g3d/common/egl_g3d.h13
2 files changed, 202 insertions, 1 deletions
diff --git a/src/gallium/state_trackers/egl_g3d/common/egl_g3d.c b/src/gallium/state_trackers/egl_g3d/common/egl_g3d.c
index f4a58f77ebe..8b2e3b5f85b 100644
--- a/src/gallium/state_trackers/egl_g3d/common/egl_g3d.c
+++ b/src/gallium/state_trackers/egl_g3d/common/egl_g3d.c
@@ -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;
diff --git a/src/gallium/state_trackers/egl_g3d/common/egl_g3d.h b/src/gallium/state_trackers/egl_g3d/common/egl_g3d.h
index 525bb488e2d..33894b614f9 100644
--- a/src/gallium/state_trackers/egl_g3d/common/egl_g3d.h
+++ b/src/gallium/state_trackers/egl_g3d/common/egl_g3d.h
@@ -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_ */