aboutsummaryrefslogtreecommitdiffstats
path: root/src/gallium/state_trackers/egl/common
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/state_trackers/egl/common')
-rw-r--r--src/gallium/state_trackers/egl/common/egl_g3d.c26
-rw-r--r--src/gallium/state_trackers/egl/common/egl_g3d_api.c74
-rw-r--r--src/gallium/state_trackers/egl/common/egl_g3d_image.c18
-rw-r--r--src/gallium/state_trackers/egl/common/egl_g3d_st.c3
-rw-r--r--src/gallium/state_trackers/egl/common/native.h37
-rw-r--r--src/gallium/state_trackers/egl/common/native_buffer.h59
6 files changed, 187 insertions, 30 deletions
diff --git a/src/gallium/state_trackers/egl/common/egl_g3d.c b/src/gallium/state_trackers/egl/common/egl_g3d.c
index 30ddcd5bc14..a3750ac56fb 100644
--- a/src/gallium/state_trackers/egl/common/egl_g3d.c
+++ b/src/gallium/state_trackers/egl/common/egl_g3d.c
@@ -156,7 +156,8 @@ egl_g3d_add_screens(_EGLDriver *drv, _EGLDisplay *dpy)
*/
static EGLBoolean
init_config_attributes(_EGLConfig *conf, const struct native_config *nconf,
- EGLint api_mask, enum pipe_format depth_stencil_format)
+ EGLint api_mask, enum pipe_format depth_stencil_format,
+ EGLBoolean preserve_buffer, EGLint max_swap_interval)
{
uint rgba[4], depth_stencil[2], buffer_size;
EGLint surface_type;
@@ -238,6 +239,11 @@ init_config_attributes(_EGLConfig *conf, const struct native_config *nconf,
conf->TransparentBlueValue = nconf->transparent_rgb_values[2];
}
+ conf->MinSwapInterval = 0;
+ conf->MaxSwapInterval = max_swap_interval;
+ if (preserve_buffer)
+ conf->SurfaceType |= EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
+
return _eglValidateConfig(conf, EGL_FALSE);
}
@@ -247,7 +253,8 @@ init_config_attributes(_EGLConfig *conf, const struct native_config *nconf,
static EGLBoolean
egl_g3d_init_config(_EGLDriver *drv, _EGLDisplay *dpy,
_EGLConfig *conf, const struct native_config *nconf,
- enum pipe_format depth_stencil_format)
+ enum pipe_format depth_stencil_format,
+ int preserve_buffer, int max_swap_interval)
{
struct egl_g3d_config *gconf = egl_g3d_config(conf);
EGLint buffer_mask, api_mask;
@@ -288,7 +295,8 @@ egl_g3d_init_config(_EGLDriver *drv, _EGLDisplay *dpy,
}
valid = init_config_attributes(&gconf->base,
- nconf, api_mask, depth_stencil_format);
+ nconf, api_mask, depth_stencil_format,
+ preserve_buffer, max_swap_interval);
if (!valid) {
_eglLog(_EGL_DEBUG, "skip invalid config 0x%x", nconf->native_visual_id);
return EGL_FALSE;
@@ -349,6 +357,7 @@ egl_g3d_add_configs(_EGLDriver *drv, _EGLDisplay *dpy, EGLint id)
const struct native_config **native_configs;
enum pipe_format depth_stencil_formats[8];
int num_formats, num_configs, i, j;
+ int preserve_buffer, max_swap_interval;
native_configs = gdpy->native->get_configs(gdpy->native, &num_configs);
if (!num_configs) {
@@ -357,6 +366,11 @@ egl_g3d_add_configs(_EGLDriver *drv, _EGLDisplay *dpy, EGLint id)
return id;
}
+ preserve_buffer =
+ gdpy->native->get_param(gdpy->native, NATIVE_PARAM_PRESERVE_BUFFER);
+ max_swap_interval =
+ gdpy->native->get_param(gdpy->native, NATIVE_PARAM_MAX_SWAP_INTERVAL);
+
num_formats = egl_g3d_fill_depth_stencil_formats(dpy,
depth_stencil_formats);
@@ -368,7 +382,8 @@ egl_g3d_add_configs(_EGLDriver *drv, _EGLDisplay *dpy, EGLint id)
if (gconf) {
_eglInitConfig(&gconf->base, dpy, id);
if (!egl_g3d_init_config(drv, dpy, &gconf->base,
- native_configs[i], depth_stencil_formats[j])) {
+ native_configs[i], depth_stencil_formats[j],
+ preserve_buffer, max_swap_interval)) {
FREE(gconf);
break;
}
@@ -538,7 +553,8 @@ egl_g3d_initialize(_EGLDriver *drv, _EGLDisplay *dpy,
if (dpy->Platform == _EGL_PLATFORM_DRM) {
dpy->Extensions.MESA_drm_display = EGL_TRUE;
- dpy->Extensions.MESA_drm_image = EGL_TRUE;
+ if (gdpy->native->buffer)
+ dpy->Extensions.MESA_drm_image = EGL_TRUE;
}
if (egl_g3d_add_configs(drv, dpy, 1) == 1) {
diff --git a/src/gallium/state_trackers/egl/common/egl_g3d_api.c b/src/gallium/state_trackers/egl/common/egl_g3d_api.c
index c10245bb067..fd7dc8f8149 100644
--- a/src/gallium/state_trackers/egl/common/egl_g3d_api.c
+++ b/src/gallium/state_trackers/egl/common/egl_g3d_api.c
@@ -97,6 +97,70 @@ egl_g3d_choose_st(_EGLDriver *drv, _EGLContext *ctx,
return stapi;
}
+static int
+egl_g3d_compare_config(const _EGLConfig *conf1, const _EGLConfig *conf2,
+ void *priv_data)
+{
+ const _EGLConfig *criteria = (const _EGLConfig *) priv_data;
+
+ /* EGL_NATIVE_VISUAL_TYPE ignored? */
+ return _eglCompareConfigs(conf1, conf2, criteria, EGL_TRUE);
+}
+
+static EGLBoolean
+egl_g3d_match_config(const _EGLConfig *conf, const _EGLConfig *criteria)
+{
+ if (!_eglMatchConfig(conf, criteria))
+ return EGL_FALSE;
+
+ if (criteria->MatchNativePixmap != EGL_NONE &&
+ criteria->MatchNativePixmap != EGL_DONT_CARE) {
+ struct egl_g3d_display *gdpy = egl_g3d_display(conf->Display);
+ struct egl_g3d_config *gconf = egl_g3d_config(conf);
+ EGLNativePixmapType pix =
+ (EGLNativePixmapType) criteria->MatchNativePixmap;
+
+ if (!gdpy->native->is_pixmap_supported(gdpy->native, pix, gconf->native))
+ return EGL_FALSE;
+ }
+
+ return EGL_TRUE;
+}
+
+static EGLBoolean
+egl_g3d_choose_config(_EGLDriver *drv, _EGLDisplay *dpy, const EGLint *attribs,
+ EGLConfig *configs, EGLint size, EGLint *num_configs)
+{
+ _EGLConfig **tmp_configs, criteria;
+ EGLint tmp_size, i;
+
+ if (!num_configs)
+ return _eglError(EGL_BAD_PARAMETER, "eglChooseConfigs");
+
+ if (!_eglParseConfigAttribList(&criteria, dpy, attribs))
+ return _eglError(EGL_BAD_ATTRIBUTE, "eglChooseConfig");
+
+ tmp_configs = (_EGLConfig **) _eglFilterArray(dpy->Configs, &tmp_size,
+ (_EGLArrayForEach) egl_g3d_match_config, (void *) &criteria);
+ if (!tmp_configs)
+ return _eglError(EGL_BAD_ALLOC, "eglChooseConfig(out of memory)");
+
+ /* perform sorting of configs */
+ if (tmp_configs && tmp_size) {
+ _eglSortConfigs((const _EGLConfig **) tmp_configs, tmp_size,
+ egl_g3d_compare_config, (void *) &criteria);
+ size = MIN2(tmp_size, size);
+ for (i = 0; i < size; i++)
+ configs[i] = _eglGetConfigHandle(tmp_configs[i]);
+ }
+
+ free(tmp_configs);
+
+ *num_configs = size;
+
+ return EGL_TRUE;
+}
+
static _EGLContext *
egl_g3d_create_context(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
_EGLContext *share, const EGLint *attribs)
@@ -539,7 +603,10 @@ egl_g3d_swap_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf)
PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL);
}
- return gsurf->native->swap_buffers(gsurf->native);
+ return gsurf->native->present(gsurf->native,
+ NATIVE_ATTACHMENT_BACK_LEFT,
+ gsurf->base.SwapBehavior == EGL_BUFFER_PRESERVED,
+ gsurf->base.SwapInterval);
}
/**
@@ -607,8 +674,7 @@ egl_g3d_copy_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
if (psrc) {
gdpy->pipe->resource_copy_region(gdpy->pipe, ptex, subdst, 0, 0, 0,
gsurf->render_texture, subsrc, 0, 0, 0, ptex->width0, ptex->height0);
-
- nsurf->flush_frontbuffer(nsurf);
+ nsurf->present(nsurf, NATIVE_ATTACHMENT_FRONT_LEFT, FALSE, 0);
}
pipe_resource_reference(&ptex, NULL);
@@ -838,6 +904,8 @@ egl_g3d_init_driver_api(_EGLDriver *drv)
{
_eglInitDriverFallbacks(drv);
+ drv->API.ChooseConfig = egl_g3d_choose_config;
+
drv->API.CreateContext = egl_g3d_create_context;
drv->API.DestroyContext = egl_g3d_destroy_context;
drv->API.CreateWindowSurface = egl_g3d_create_window_surface;
diff --git a/src/gallium/state_trackers/egl/common/egl_g3d_image.c b/src/gallium/state_trackers/egl/common/egl_g3d_image.c
index be9c88e5e47..6a1f8cc697b 100644
--- a/src/gallium/state_trackers/egl/common/egl_g3d_image.c
+++ b/src/gallium/state_trackers/egl/common/egl_g3d_image.c
@@ -38,7 +38,7 @@
#include "egl_g3d_api.h"
#include "egl_g3d_image.h"
-/* move this to native display? */
+/* for struct winsys_handle */
#include "state_tracker/drm_driver.h"
/**
@@ -137,13 +137,11 @@ egl_g3d_reference_drm_buffer(_EGLDisplay *dpy, EGLint name,
_EGLImage *img, const EGLint *attribs)
{
struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
- struct pipe_screen *screen = gdpy->native->screen;
struct pipe_resource templ;
struct winsys_handle wsh;
_EGLImageAttribs attrs;
EGLint format;
- /* winsys_handle is in theory platform-specific */
if (dpy->Platform != _EGL_PLATFORM_DRM)
return NULL;
@@ -178,9 +176,10 @@ egl_g3d_reference_drm_buffer(_EGLDisplay *dpy, EGLint name,
memset(&wsh, 0, sizeof(wsh));
wsh.handle = (unsigned) name;
- wsh.stride = attrs.DRMBufferStrideMESA;
+ wsh.stride =
+ attrs.DRMBufferStrideMESA * util_format_get_blocksize(templ.format);
- return screen->resource_from_handle(screen, &templ, &wsh);
+ return gdpy->native->buffer->import_buffer(gdpy->native, &templ, &wsh);
}
#endif /* EGL_MESA_drm_image */
@@ -302,10 +301,8 @@ egl_g3d_export_drm_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLImage *img,
{
struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
struct egl_g3d_image *gimg = egl_g3d_image(img);
- struct pipe_screen *screen = gdpy->native->screen;
struct winsys_handle wsh;
- /* winsys_handle is in theory platform-specific */
if (dpy->Platform != _EGL_PLATFORM_DRM)
return EGL_FALSE;
@@ -313,9 +310,9 @@ egl_g3d_export_drm_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLImage *img,
if (name) {
memset(&handle, 0, sizeof(handle));
wsh.type = DRM_API_HANDLE_TYPE_SHARED;
- if (!screen->resource_get_handle(screen, gimg->texture, &wsh)) {
+ if (!gdpy->native->buffer->export_buffer(gdpy->native,
+ gimg->texture, &wsh))
return EGL_FALSE;
- }
*name = wsh.handle;
}
@@ -324,7 +321,8 @@ egl_g3d_export_drm_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLImage *img,
if (handle || stride) {
memset(&wsh, 0, sizeof(wsh));
wsh.type = DRM_API_HANDLE_TYPE_KMS;
- if (!screen->resource_get_handle(screen, gimg->texture, &wsh))
+ if (!gdpy->native->buffer->export_buffer(gdpy->native,
+ gimg->texture, &wsh))
return EGL_FALSE;
if (handle)
diff --git a/src/gallium/state_trackers/egl/common/egl_g3d_st.c b/src/gallium/state_trackers/egl/common/egl_g3d_st.c
index 0affe632cfe..25e2999590c 100644
--- a/src/gallium/state_trackers/egl/common/egl_g3d_st.c
+++ b/src/gallium/state_trackers/egl/common/egl_g3d_st.c
@@ -192,7 +192,8 @@ egl_g3d_st_framebuffer_flush_front(struct st_framebuffer_iface *stfbi,
_EGLSurface *surf = (_EGLSurface *) stfbi->st_manager_private;
struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
- return gsurf->native->flush_frontbuffer(gsurf->native);
+ return gsurf->native->present(gsurf->native,
+ NATIVE_ATTACHMENT_FRONT_LEFT, FALSE, 0);
}
static boolean
diff --git a/src/gallium/state_trackers/egl/common/native.h b/src/gallium/state_trackers/egl/common/native.h
index 3c3f57e2670..3886ca20562 100644
--- a/src/gallium/state_trackers/egl/common/native.h
+++ b/src/gallium/state_trackers/egl/common/native.h
@@ -34,6 +34,11 @@
#include "pipe/p_state.h"
#include "state_tracker/sw_winsys.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "native_buffer.h"
#include "native_modeset.h"
/**
@@ -54,7 +59,17 @@ enum native_param_type {
* Return TRUE if window/pixmap surfaces use the buffers of the native
* types.
*/
- NATIVE_PARAM_USE_NATIVE_BUFFER
+ NATIVE_PARAM_USE_NATIVE_BUFFER,
+
+ /**
+ * Return TRUE if native_surface::present can preserve the buffer.
+ */
+ NATIVE_PARAM_PRESERVE_BUFFER,
+
+ /**
+ * Return the maximum supported swap interval.
+ */
+ NATIVE_PARAM_MAX_SWAP_INTERVAL
};
struct native_surface {
@@ -66,17 +81,12 @@ struct native_surface {
void (*destroy)(struct native_surface *nsurf);
/**
- * Swap the front and back buffers so that the back buffer is visible. It
- * is no-op if the surface is single-buffered. The contents of the back
- * buffer after swapping may or may not be preserved.
- */
- boolean (*swap_buffers)(struct native_surface *nsurf);
-
- /**
- * Make the front buffer visible. In some native displays, changes to the
- * front buffer might not be visible immediately and require manual flush.
+ * Present the given buffer to the native engine.
*/
- boolean (*flush_frontbuffer)(struct native_surface *nsurf);
+ boolean (*present)(struct native_surface *nsurf,
+ enum native_attachment natt,
+ boolean preserve,
+ uint swap_interval);
/**
* Validate the buffers of the surface. textures, if not NULL, points to an
@@ -181,6 +191,7 @@ struct native_display {
EGLNativePixmapType pix,
const struct native_config *nconf);
+ const struct native_display_buffer *buffer;
const struct native_display_modeset *modeset;
};
@@ -232,4 +243,8 @@ native_get_drm_platform(void);
const struct native_platform *
native_get_fbdev_platform(void);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* _NATIVE_H_ */
diff --git a/src/gallium/state_trackers/egl/common/native_buffer.h b/src/gallium/state_trackers/egl/common/native_buffer.h
new file mode 100644
index 00000000000..5c29ab97411
--- /dev/null
+++ b/src/gallium/state_trackers/egl/common/native_buffer.h
@@ -0,0 +1,59 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.9
+ *
+ * Copyright (C) 2010 LunarG Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Chia-I Wu <[email protected]>
+ */
+
+#ifndef _NATIVE_BUFFER_H_
+#define _NATIVE_BUFFER_H_
+
+#include "pipe/p_compiler.h"
+
+struct native_display;
+struct pipe_resource;
+
+/**
+ * Buffer interface of the native display. It allows native buffers to be
+ * imported and exported.
+ *
+ * Just like a native window or a native pixmap, a native buffer is another
+ * native type. Its definition depends on the native display.
+ *
+ * For DRM platform, the type of a native buffer is struct winsys_handle.
+ */
+struct native_display_buffer {
+ struct pipe_resource *(*import_buffer)(struct native_display *ndpy,
+ const struct pipe_resource *templ,
+ void *buf);
+
+ /**
+ * The resource must be creatred with PIPE_BIND_SHARED.
+ */
+ boolean (*export_buffer)(struct native_display *ndpy,
+ struct pipe_resource *res,
+ void *buf);
+};
+
+#endif /* _NATIVE_BUFFER_H_ */