Simply the name to egl.
WINDOW_SYSTEM = dri
GALLIUM_WINSYS_DIRS = drm
GALLIUM_WINSYS_DRM_DIRS = vmware intel i965
-GALLIUM_STATE_TRACKERS_DIRS = egl_g3d
+GALLIUM_STATE_TRACKERS_DIRS = egl
DRI_DIRS = i810 i915 i965 mach64 mga r128 r200 r300 radeon \
savage sis tdfx unichrome ffb swrast
SRC_DIRS = egl glsl mesa/es gallium gallium/winsys
PROGRAM_DIRS = es1/screen es1/xegl es2/xegl
-# egl_g3d needs this
+# egl st needs this
DEFINES += -DGLX_DIRECT_RENDERING
# no mesa or egl drivers
# build egl_x11_{swrast,i915}.so
GALLIUM_DRIVERS_DIRS += trace i915
-GALLIUM_STATE_TRACKERS_DIRS += egl_g3d
+GALLIUM_STATE_TRACKERS_DIRS += egl
GALLIUM_WINSYS_DIRS += drm
GALLIUM_WINSYS_DRM_DIRS += intel swrast
dri)
GALLIUM_STATE_TRACKERS_DIRS="dri"
if test "x$enable_egl" = xyes; then
- GALLIUM_STATE_TRACKERS_DIRS="$GALLIUM_STATE_TRACKERS_DIRS egl_g3d"
+ GALLIUM_STATE_TRACKERS_DIRS="$GALLIUM_STATE_TRACKERS_DIRS egl"
fi
# Have only tested st/xorg on 1.6.0 servers
PKG_CHECK_MODULES(XORG, [xorg-server >= 1.6.0],
AC_MSG_ERROR([state tracker '$tracker' doesn't exist])
case "$tracker" in
- egl_g3d)
+ egl)
if test "x$enable_egl" != xyes; then
- AC_MSG_ERROR([cannot build egl_g3d state tracker without EGL library])
+ AC_MSG_ERROR([cannot build egl state tracker without EGL library])
fi
;;
xorg)
# verify the requested driver directories exist
egl_displays=`IFS=', '; echo $with_egl_displays`
for dpy in $egl_displays; do
- test -d "$srcdir/src/gallium/state_trackers/egl_g3d/$dpy" || \
+ test -d "$srcdir/src/gallium/state_trackers/egl/$dpy" || \
AC_MSG_ERROR([EGL display '$dpy' does't exist])
done
EGL_DISPLAYS="$egl_displays"
the Gallium driver for your hardware. For example</p>
<pre>
- $ ./configure --with-state-trackers=egl_g3d,es,vega --enable-gallium-intel
+ $ ./configure --with-state-trackers=egl,es,vega --enable-gallium-intel
</pre>
-<p>The main library will be enabled by default. The <code>egl_g3d</code> state
+<p>The main library will be enabled by default. The <code>egl</code> state
tracker is needed by a number of EGL drivers. EGL drivers will be covered
later. The <a href="opengles.html">es state tracker</a> provides OpenGL ES 1.x
and 2.x and the <a href="openvg.html">vega state tracker</a> provides OpenVG
<p>The argument is a comma separated string. It is usually used to specify the
rendering APIs, like OpenGL ES or OpenVG, to build. But it should be noted
-that a number of EGL drivers depend on the <code>egl_g3d</code> state tracker.
-They will <em>not</em> be built without the <code>egl_g3d</code> state
-tracker.</p>
+that a number of EGL drivers depend on the <code>egl</code> state tracker.
+They will <em>not</em> be built without the <code>egl</code> state tracker.</p>
</li>
<p>Gallium EGL drivers supports all rendering APIs specified in EGL 1.4. The
support for optional EGL functions and EGL extensions is usually more complete
-than the classic ones. These drivers depend on the <code>egl_g3d</code> state
+than the classic ones. These drivers depend on the <code>egl</code> state
tracker to build. The available drivers are</p>
<ul>
<h2>Developers</h2>
The sources of the main library and the classic drivers can be found at
-<code>src/egl/</code>. The sources of the <code>egl_g3d</code> state tracker
-can be found at <code>src/gallium/state_trackers/egl_g3d/</code>.
+<code>src/egl/</code>. The sources of the <code>egl</code> state tracker can
+be found at <code>src/gallium/state_trackers/egl/</code>.
<h3>TODOs</h3>
<h2>Build the Libraries</h2>
<ol>
-<li>Run <code>configure</code> with <code>--with-state-trackers=egl_g3d,es</code> and enable the Gallium driver for your hardware.</li>
+<li>Run <code>configure</code> with <code>--with-state-trackers=egl,es</code> and enable the Gallium driver for your hardware.</li>
<li>Build and install Mesa as usual.</li>
</ol>
<h3>Sample build</h3>
A sample build looks as follows:
<pre>
- $ ./configure --with-state-trackers=egl_g3d,vega --enable-gallium-intel
+ $ ./configure --with-state-trackers=egl,vega --enable-gallium-intel
$ make
$ make install
</pre>
--- /dev/null
+TOP = ../../../..
+include $(TOP)/configs/current
+
+common_INCLUDES = \
+ -I. \
+ -I$(TOP)/src/gallium/include \
+ -I$(TOP)/src/gallium/auxiliary \
+ -I$(TOP)/src/egl/main \
+ -I$(TOP)/include
+
+common_SOURCES = $(wildcard common/*.c)
+common_OBJECTS = $(common_SOURCES:.c=.o)
+
+
+x11_INCLUDES = \
+ -I$(TOP)/src/gallium/drivers \
+ -I$(TOP)/src/glx/x11 \
+ -I$(TOP)/src/egl/drivers/xdri \
+ -I$(TOP)/src/mesa \
+ $(shell pkg-config --cflags-only-I libdrm)
+
+x11_SOURCES = $(wildcard x11/*.c) \
+ $(TOP)/src/glx/x11/dri2.c \
+ $(TOP)/src/egl/drivers/xdri/glxinit.c
+x11_OBJECTS = $(x11_SOURCES:.c=.o)
+
+
+kms_INCLUDES = $(shell pkg-config --cflags-only-I libdrm)
+kms_SOURCES = $(wildcard kms/*.c)
+kms_OBJECTS = $(kms_SOURCES:.c=.o)
+
+
+ALL_INCLUDES = $(common_INCLUDES) $(x11_INCLUDES) $(kms_INCLUDES)
+ALL_SOURCES = $(common_SOURCES) $(x11_SOURCES) $(kms_SOURCES)
+ALL_OBJECTS = $(common_OBJECTS) $(x11_OBJECTS) $(kms_OBJECTS)
+
+##### TARGETS #####
+
+EGL_DISPLAYS_MODS = $(foreach dpy, $(EGL_DISPLAYS), libegl$(dpy).a)
+
+default: depend $(EGL_DISPLAYS_MODS)
+
+
+libeglx11.a: $(x11_OBJECTS) $(common_OBJECTS) Makefile
+ $(MKLIB) -o eglx11 -static $(x11_OBJECTS) $(common_OBJECTS)
+
+libeglkms.a: $(kms_OBJECTS) $(common_OBJECTS) Makefile
+ $(MKLIB) -o eglkms -static $(kms_OBJECTS) $(common_OBJECTS)
+
+depend:
+ rm -f depend
+ touch depend
+ $(MKDEP) $(MKDEP_OPTIONS) $(ALL_INCLUDES) $(ALL_SOURCES) 2> /dev/null
+
+clean:
+ rm -f $(ALL_OBJECTS)
+ rm -f $(EGL_DISPLAYS_MODS)
+ rm -f depend depend.bak
+
+# Dummy target
+install:
+ @echo -n ""
+
+##### RULES #####
+
+$(common_OBJECTS): %.o: %.c
+ $(CC) -c $(common_INCLUDES) $(DEFINES) $(CFLAGS) $< -o $@
+
+$(x11_OBJECTS): %.o: %.c
+ $(CC) -c $(common_INCLUDES) $(x11_INCLUDES) $(DEFINES) $(CFLAGS) $< -o $@
+
+$(kms_OBJECTS): %.o: %.c
+ $(CC) -c $(common_INCLUDES) $(kms_INCLUDES) $(DEFINES) $(CFLAGS) $< -o $@
+
+sinclude depend
--- /dev/null
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.8
+ *
+ * Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org>
+ *
+ * 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
+ * BRIAN PAUL 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.
+ */
+
+#include <assert.h>
+#include <string.h>
+#include "pipe/p_screen.h"
+#include "util/u_memory.h"
+#include "util/u_rect.h"
+#include "egldriver.h"
+#include "eglcurrent.h"
+#include "eglconfigutil.h"
+#include "egllog.h"
+
+#include "native.h"
+#include "egl_g3d.h"
+#include "egl_st.h"
+
+/**
+ * Validate the draw/read surfaces of the context.
+ */
+static void
+egl_g3d_validate_context(_EGLDisplay *dpy, _EGLContext *ctx)
+{
+ struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
+ struct pipe_screen *screen = gdpy->native->screen;
+ struct egl_g3d_context *gctx = egl_g3d_context(ctx);
+ const uint st_att_map[NUM_NATIVE_ATTACHMENTS] = {
+ ST_SURFACE_FRONT_LEFT,
+ ST_SURFACE_BACK_LEFT,
+ ST_SURFACE_FRONT_RIGHT,
+ ST_SURFACE_BACK_RIGHT,
+ };
+ EGLint num_surfaces, s;
+
+ /* validate draw and/or read buffers */
+ num_surfaces = (gctx->base.ReadSurface == gctx->base.DrawSurface) ? 1 : 2;
+ for (s = 0; s < num_surfaces; s++) {
+ struct pipe_texture *textures[NUM_NATIVE_ATTACHMENTS];
+ struct egl_g3d_surface *gsurf;
+ struct egl_g3d_buffer *gbuf;
+ EGLint att;
+
+ if (s == 0) {
+ gsurf = egl_g3d_surface(gctx->base.DrawSurface);
+ gbuf = &gctx->draw;
+ }
+ else {
+ gsurf = egl_g3d_surface(gctx->base.ReadSurface);
+ gbuf = &gctx->read;
+ }
+
+ if (!gctx->force_validate) {
+ unsigned int seq_num;
+
+ gsurf->native->validate(gsurf->native, gbuf->attachment_mask,
+ &seq_num, NULL, NULL, NULL);
+ /* skip validation */
+ if (gsurf->sequence_number == seq_num)
+ continue;
+ }
+
+ pipe_surface_reference(&gsurf->render_surface, NULL);
+ memset(textures, 0, sizeof(textures));
+
+ gsurf->native->validate(gsurf->native, gbuf->attachment_mask,
+ &gsurf->sequence_number, textures,
+ &gsurf->base.Width, &gsurf->base.Height);
+ for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) {
+ struct pipe_texture *pt = textures[att];
+ struct pipe_surface *ps;
+
+ if (native_attachment_mask_test(gbuf->attachment_mask, att) && pt) {
+ ps = screen->get_tex_surface(screen, pt, 0, 0, 0,
+ PIPE_BUFFER_USAGE_GPU_READ |
+ PIPE_BUFFER_USAGE_GPU_WRITE);
+ gctx->stapi->st_set_framebuffer_surface(gbuf->st_fb,
+ st_att_map[att], ps);
+
+ if (gsurf->render_att == att)
+ pipe_surface_reference(&gsurf->render_surface, ps);
+
+ pipe_surface_reference(&ps, NULL);
+ pipe_texture_reference(&pt, NULL);
+ }
+ }
+
+ gctx->stapi->st_resize_framebuffer(gbuf->st_fb,
+ gsurf->base.Width, gsurf->base.Height);
+ }
+
+ gctx->force_validate = EGL_FALSE;
+
+}
+
+/**
+ * Create a st_framebuffer.
+ */
+static struct st_framebuffer *
+create_framebuffer(_EGLContext *ctx, _EGLSurface *surf)
+{
+ struct egl_g3d_context *gctx = egl_g3d_context(ctx);
+ struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
+ struct egl_g3d_config *gconf = egl_g3d_config(gsurf->base.Config);
+
+ return gctx->stapi->st_create_framebuffer(&gconf->native->mode,
+ gconf->native->color_format, gconf->native->depth_format,
+ gconf->native->stencil_format,
+ gsurf->base.Width, gsurf->base.Height, &gsurf->base);
+}
+
+/**
+ * Update the attachments of draw/read surfaces.
+ */
+static void
+egl_g3d_route_context(_EGLDisplay *dpy, _EGLContext *ctx)
+{
+ struct egl_g3d_context *gctx = egl_g3d_context(ctx);
+ EGLint s;
+
+ /* route draw and read buffers' attachments */
+ for (s = 0; s < 2; s++) {
+ struct egl_g3d_surface *gsurf;
+ struct egl_g3d_buffer *gbuf;
+
+ if (s == 0) {
+ gsurf = egl_g3d_surface(gctx->base.DrawSurface);
+ gbuf = &gctx->draw;
+ }
+ else {
+ gsurf = egl_g3d_surface(gctx->base.ReadSurface);
+ gbuf = &gctx->read;
+ }
+
+ gbuf->attachment_mask = (1 << gsurf->render_att);
+
+ /* FIXME OpenGL defaults to draw the front or back buffer when the
+ * context is single-buffered or double-buffered respectively. In EGL,
+ * however, the buffer to be drawn is determined by the surface, instead
+ * of the context. As a result, rendering to a pixmap surface with a
+ * double-buffered context does not work as expected.
+ *
+ * gctx->stapi->st_draw_front_buffer(gctx->st_ctx, natt ==
+ * NATIVE_ATTACHMENT_FRONT_LEFT);
+ */
+
+ /*
+ * FIXME If the back buffer is asked for here, and the front buffer is
+ * later needed by the client API (e.g. glDrawBuffer is called to draw
+ * the front buffer), it will create a new pipe texture and draw there.
+ * One fix is to ask for both buffers here, but it would be a waste if
+ * the front buffer is never used. A better fix is to add a callback to
+ * the pipe screen with context private (just like flush_frontbuffer).
+ */
+ }
+}
+
+/**
+ * Reallocate the context's framebuffers after draw/read surfaces change.
+ */
+static EGLBoolean
+egl_g3d_realloc_context(_EGLDisplay *dpy, _EGLContext *ctx)
+{
+ struct egl_g3d_context *gctx = egl_g3d_context(ctx);
+ struct egl_g3d_surface *gdraw = egl_g3d_surface(gctx->base.DrawSurface);
+ struct egl_g3d_surface *gread = egl_g3d_surface(gctx->base.ReadSurface);
+
+ /* unreference the old framebuffers */
+ if (gctx->draw.st_fb) {
+ EGLBoolean is_equal = (gctx->draw.st_fb == gctx->read.st_fb);
+ void *priv;
+
+ priv = gctx->stapi->st_framebuffer_private(gctx->draw.st_fb);
+ if (!gdraw || priv != (void *) &gdraw->base) {
+ gctx->stapi->st_unreference_framebuffer(gctx->draw.st_fb);
+ gctx->draw.st_fb = NULL;
+ gctx->draw.attachment_mask = 0x0;
+ }
+
+ if (is_equal) {
+ gctx->read.st_fb = NULL;
+ gctx->draw.attachment_mask = 0x0;
+ }
+ else {
+ priv = gctx->stapi->st_framebuffer_private(gctx->read.st_fb);
+ if (!gread || priv != (void *) &gread->base) {
+ gctx->stapi->st_unreference_framebuffer(gctx->read.st_fb);
+ gctx->read.st_fb = NULL;
+ gctx->draw.attachment_mask = 0x0;
+ }
+ }
+ }
+
+ if (!gdraw)
+ return EGL_TRUE;
+
+ /* create the draw fb */
+ if (!gctx->draw.st_fb) {
+ gctx->draw.st_fb = create_framebuffer(&gctx->base, &gdraw->base);
+ if (!gctx->draw.st_fb)
+ return EGL_FALSE;
+ }
+
+ /* create the read fb */
+ if (!gctx->read.st_fb) {
+ if (gread != gdraw) {
+ gctx->read.st_fb = create_framebuffer(&gctx->base, &gread->base);
+ if (!gctx->read.st_fb) {
+ gctx->stapi->st_unreference_framebuffer(gctx->draw.st_fb);
+ gctx->draw.st_fb = NULL;
+ return EGL_FALSE;
+ }
+ }
+ else {
+ /* there is no st_reference_framebuffer... */
+ gctx->read.st_fb = gctx->draw.st_fb;
+ }
+ }
+
+ egl_g3d_route_context(dpy, &gctx->base);
+ gctx->force_validate = EGL_TRUE;
+
+ return EGL_TRUE;
+}
+
+/**
+ * Return the current context of the given API.
+ */
+static struct egl_g3d_context *
+egl_g3d_get_current_context(EGLint api)
+{
+ _EGLThreadInfo *t = _eglGetCurrentThread();
+ EGLint api_index = _eglConvertApiToIndex(api);
+ return egl_g3d_context(t->CurrentContexts[api_index]);
+}
+
+/**
+ * Return the state tracker for the given context.
+ */
+static const struct egl_g3d_st *
+egl_g3d_choose_st(_EGLDriver *drv, _EGLContext *ctx)
+{
+ struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
+ const struct egl_g3d_st *stapi;
+ EGLint idx = -1;
+
+ switch (ctx->ClientAPI) {
+ case EGL_OPENGL_ES_API:
+ switch (ctx->ClientVersion) {
+ case 1:
+ idx = EGL_G3D_ST_OPENGL_ES;
+ break;
+ case 2:
+ idx = EGL_G3D_ST_OPENGL_ES2;
+ break;
+ default:
+ _eglLog(_EGL_WARNING, "unknown client version %d",
+ ctx->ClientVersion);
+ break;
+ }
+ break;
+ case EGL_OPENVG_API:
+ idx = EGL_G3D_ST_OPENVG;
+ break;
+ case EGL_OPENGL_API:
+ idx = EGL_G3D_ST_OPENGL;
+ break;
+ default:
+ _eglLog(_EGL_WARNING, "unknown client API 0x%04x", ctx->ClientAPI);
+ break;
+ }
+
+ stapi = (idx >= 0) ? gdrv->stapis[idx] : NULL;
+ return stapi;
+}
+
+/**
+ * Initialize the state trackers.
+ */
+static void
+egl_g3d_init_st(_EGLDriver *drv)
+{
+ struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
+ EGLint i;
+
+ /* already initialized */
+ if (gdrv->api_mask)
+ return;
+
+ for (i = 0; i < NUM_EGL_G3D_STS; i++) {
+ gdrv->stapis[i] = egl_g3d_get_st(i);
+ if (gdrv->stapis[i])
+ gdrv->api_mask |= gdrv->stapis[i]->api_bit;
+ }
+
+ if (gdrv->api_mask)
+ _eglLog(_EGL_DEBUG, "Driver API mask: 0x%x", gdrv->api_mask);
+ else
+ _eglLog(_EGL_WARNING, "No supported client API");
+}
+
+/**
+ * Get the probe object of the display.
+ *
+ * Note that this function may be called before the display is initialized.
+ */
+static struct native_probe *
+egl_g3d_get_probe(_EGLDriver *drv, _EGLDisplay *dpy)
+{
+ struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
+ struct native_probe *nprobe;
+
+ nprobe = (struct native_probe *) _eglGetProbeCache(gdrv->probe_key);
+ if (!nprobe || nprobe->display != dpy->NativeDisplay) {
+ if (nprobe)
+ nprobe->destroy(nprobe);
+ nprobe = native_create_probe(dpy->NativeDisplay);
+ _eglSetProbeCache(gdrv->probe_key, (void *) nprobe);
+ }
+
+ return nprobe;
+}
+
+/**
+ * Destroy the probe object of the display. The display may be NULL.
+ *
+ * Note that this function may be called before the display is initialized.
+ */
+static void
+egl_g3d_destroy_probe(_EGLDriver *drv, _EGLDisplay *dpy)
+{
+ struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
+ struct native_probe *nprobe;
+
+ nprobe = (struct native_probe *) _eglGetProbeCache(gdrv->probe_key);
+ if (nprobe && (!dpy || nprobe->display == dpy->NativeDisplay)) {
+ nprobe->destroy(nprobe);
+ _eglSetProbeCache(gdrv->probe_key, NULL);
+ }
+}
+
+/**
+ * Return an API mask that consists of the state trackers that supports the
+ * given mode.
+ *
+ * FIXME add st_is_mode_supported()?
+ */
+static EGLint
+get_mode_api_mask(const __GLcontextModes *mode, EGLint api_mask)
+{
+ EGLint check;
+
+ /* OpenGL ES 1.x and 2.x are checked together */
+ check = EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT;
+ if (api_mask & check) {
+ /* this is required by EGL, not by OpenGL ES */
+ if (mode->drawableType & GLX_WINDOW_BIT && !mode->doubleBufferMode)
+ api_mask &= ~check;
+ }
+
+ check = EGL_OPENVG_BIT;
+ if (api_mask & check) {
+ /* vega st needs the depth/stencil rb */
+ if (!mode->depthBits && !mode->stencilBits)
+ api_mask &= ~check;
+ }
+
+ 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.
+ */
+static EGLint
+egl_g3d_add_configs(_EGLDriver *drv, _EGLDisplay *dpy, EGLint id)
+{
+ struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
+ struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
+ const struct native_config **native_configs;
+ int num_configs, i;
+
+ native_configs = gdpy->native->get_configs(gdpy->native,
+ &num_configs);
+ if (!num_configs) {
+ if (native_configs)
+ free(native_configs);
+ return id;
+ }
+
+ for (i = 0; i < num_configs; i++) {
+ EGLint api_mask;
+ struct egl_g3d_config *gconf;
+ EGLBoolean valid;
+
+ api_mask = get_mode_api_mask(&native_configs[i]->mode, gdrv->api_mask);
+ if (!api_mask) {
+ _eglLog(_EGL_DEBUG, "no state tracker supports config 0x%x",
+ native_configs[i]->mode.visualID);
+ continue;
+ }
+
+ gconf = CALLOC_STRUCT(egl_g3d_config);
+ if (!gconf)
+ continue;
+
+ _eglInitConfig(&gconf->base, id);
+ valid = _eglConfigFromContextModesRec(&gconf->base,
+ &native_configs[i]->mode, api_mask, api_mask);
+ 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);
+ free(gconf);
+ continue;
+ }
+
+ gconf->native = native_configs[i];
+ _eglAddConfig(dpy, &gconf->base);
+ id++;
+ }
+
+ free(native_configs);
+ return id;
+}
+
+/**
+ * Flush the front buffer of the context's draw surface.
+ */
+static void
+egl_g3d_flush_frontbuffer(struct pipe_screen *screen,
+ struct pipe_surface *surf, void *context_private)
+{
+ struct egl_g3d_context *gctx = egl_g3d_context(context_private);
+ struct egl_g3d_surface *gsurf = egl_g3d_surface(gctx->base.DrawSurface);
+
+ if (gsurf)
+ gsurf->native->flush_frontbuffer(gsurf->native);
+}
+
+/**
+ * Re-validate the context.
+ */
+static void
+egl_g3d_update_buffer(struct pipe_screen *screen, void *context_private)
+{
+ struct egl_g3d_context *gctx = egl_g3d_context(context_private);
+
+ /**
+ * It is likely that the surface has changed when this function is called.
+ * Set force_validate to skip an unnecessary check.
+ */
+ gctx->force_validate = EGL_TRUE;
+ egl_g3d_validate_context(gctx->base.Display, &gctx->base);
+}
+
+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);
+
+ free(gdpy);
+ dpy->DriverData = NULL;
+
+ return EGL_TRUE;
+}
+
+static EGLBoolean
+egl_g3d_initialize(_EGLDriver *drv, _EGLDisplay *dpy,
+ EGLint *major, EGLint *minor)
+{
+ struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
+ struct egl_g3d_display *gdpy;
+
+ /* the probe object is unlikely to be needed again */
+ egl_g3d_destroy_probe(drv, dpy);
+
+ gdpy = CALLOC_STRUCT(egl_g3d_display);
+ if (!gdpy) {
+ _eglError(EGL_BAD_ALLOC, "eglInitialize");
+ goto fail;
+ }
+ dpy->DriverData = gdpy;
+
+ gdpy->native = native_create_display(dpy->NativeDisplay);
+ if (!gdpy->native) {
+ _eglError(EGL_NOT_INITIALIZED, "eglInitialize(no usable display)");
+ goto fail;
+ }
+
+ gdpy->native->screen->flush_frontbuffer = egl_g3d_flush_frontbuffer;
+ gdpy->native->screen->update_buffer = egl_g3d_update_buffer;
+
+ egl_g3d_init_st(&gdrv->base);
+ dpy->ClientAPIsMask = gdrv->api_mask;
+
+ if (egl_g3d_add_configs(drv, dpy, 1) == 1) {
+ _eglError(EGL_NOT_INITIALIZED, "eglInitialize(unable to add configs)");
+ 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;
+
+ return EGL_TRUE;
+
+fail:
+ if (gdpy)
+ egl_g3d_terminate(drv, dpy);
+ return EGL_FALSE;
+}
+
+static _EGLContext *
+egl_g3d_create_context(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
+ _EGLContext *share, const EGLint *attribs)
+{
+ struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
+ struct egl_g3d_context *gshare = egl_g3d_context(share);
+ struct egl_g3d_config *gconf = egl_g3d_config(conf);
+ struct egl_g3d_context *gctx;
+ const __GLcontextModes *mode;
+
+ gctx = CALLOC_STRUCT(egl_g3d_context);
+ if (!gctx) {
+ _eglError(EGL_BAD_ALLOC, "eglCreateContext");
+ return NULL;
+ }
+
+ if (!_eglInitContext(drv, &gctx->base, conf, attribs)) {
+ free(gctx);
+ return NULL;
+ }
+
+ gctx->stapi = egl_g3d_choose_st(drv, &gctx->base);
+ if (!gctx->stapi) {
+ free(gctx);
+ return NULL;
+ }
+
+ mode = &gconf->native->mode;
+ gctx->pipe =
+ gdpy->native->create_context(gdpy->native, (void *) &gctx->base);
+ if (!gctx->pipe) {
+ free(gctx);
+ return NULL;
+ }
+
+ gctx->st_ctx = gctx->stapi->st_create_context(gctx->pipe, mode,
+ (gshare) ? gshare->st_ctx : NULL);
+ if (!gctx->st_ctx) {
+ gctx->pipe->destroy(gctx->pipe);
+ free(gctx);
+ return NULL;
+ }
+
+ return &gctx->base;
+}
+
+static EGLBoolean
+egl_g3d_destroy_context(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx)
+{
+ struct egl_g3d_context *gctx = egl_g3d_context(ctx);
+
+ if (_eglIsContextBound(&gctx->base))
+ return EGL_TRUE;
+
+ egl_g3d_realloc_context(dpy, &gctx->base);
+
+ /* it will destroy pipe context */
+ gctx->stapi->st_destroy_context(gctx->st_ctx);
+
+ free(gctx);
+
+ return EGL_TRUE;
+}
+
+static EGLBoolean
+init_surface_geometry(_EGLSurface *surf)
+{
+ struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
+
+ return gsurf->native->validate(gsurf->native, 0x0,
+ &gsurf->sequence_number, NULL,
+ &gsurf->base.Width, &gsurf->base.Height);
+}
+
+static _EGLSurface *
+egl_g3d_create_window_surface(_EGLDriver *drv, _EGLDisplay *dpy,
+ _EGLConfig *conf, EGLNativeWindowType win,
+ 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, "eglCreateWindowSurface");
+ return NULL;
+ }
+
+ if (!_eglInitSurface(drv, &gsurf->base, EGL_WINDOW_BIT, conf, attribs)) {
+ free(gsurf);
+ return NULL;
+ }
+
+ gsurf->native =
+ gdpy->native->create_window_surface(gdpy->native, win, gconf->native);
+ if (!gsurf->native) {
+ free(gsurf);
+ return NULL;
+ }
+
+ if (!init_surface_geometry(&gsurf->base)) {
+ gsurf->native->destroy(gsurf->native);
+ free(gsurf);
+ return NULL;
+ }
+
+ gsurf->render_att = (gsurf->base.RenderBuffer == EGL_SINGLE_BUFFER ||
+ !gconf->native->mode.doubleBufferMode) ?
+ NATIVE_ATTACHMENT_FRONT_LEFT : NATIVE_ATTACHMENT_BACK_LEFT;
+
+ return &gsurf->base;
+}
+
+static _EGLSurface *
+egl_g3d_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *dpy,
+ _EGLConfig *conf, EGLNativePixmapType pix,
+ 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, "eglCreatePixmapSurface");
+ return NULL;
+ }
+
+ if (!_eglInitSurface(drv, &gsurf->base, EGL_PIXMAP_BIT, conf, attribs)) {
+ free(gsurf);
+ return NULL;
+ }
+
+ gsurf->native =
+ gdpy->native->create_pixmap_surface(gdpy->native, pix, gconf->native);
+ if (!gsurf->native) {
+ free(gsurf);
+ return NULL;
+ }
+
+ if (!init_surface_geometry(&gsurf->base)) {
+ gsurf->native->destroy(gsurf->native);
+ free(gsurf);
+ return NULL;
+ }
+
+ gsurf->render_att = NATIVE_ATTACHMENT_FRONT_LEFT;
+
+ return &gsurf->base;
+}
+
+static _EGLSurface *
+egl_g3d_create_pbuffer_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_PBUFFER_BIT, conf, attribs)) {
+ free(gsurf);
+ return NULL;
+ }
+
+ gsurf->native =
+ gdpy->native->create_pbuffer_surface(gdpy->native, gconf->native,
+ gsurf->base.Width, gsurf->base.Height);
+ if (!gsurf->native) {
+ free(gsurf);
+ return NULL;
+ }
+
+ if (!init_surface_geometry(&gsurf->base)) {
+ gsurf->native->destroy(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_destroy_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf)
+{
+ struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
+
+ if (_eglIsSurfaceBound(&gsurf->base))
+ return EGL_TRUE;
+
+ pipe_surface_reference(&gsurf->render_surface, NULL);
+ gsurf->native->destroy(gsurf->native);
+ free(gsurf);
+ return EGL_TRUE;
+}
+
+static EGLBoolean
+egl_g3d_make_current(_EGLDriver *drv, _EGLDisplay *dpy,
+ _EGLSurface *draw, _EGLSurface *read, _EGLContext *ctx)
+{
+ struct egl_g3d_context *gctx = egl_g3d_context(ctx);
+ struct egl_g3d_context *old_gctx;
+ EGLint api;
+ EGLBoolean ok = EGL_TRUE;
+
+ /* find the old context */
+ api = (gctx) ? gctx->base.ClientAPI : eglQueryAPI();
+ old_gctx = egl_g3d_get_current_context(api);
+ if (old_gctx && !_eglIsContextLinked(&old_gctx->base))
+ old_gctx = NULL;
+
+ if (!_eglMakeCurrent(drv, dpy, draw, read, ctx))
+ return EGL_FALSE;
+
+ if (old_gctx) {
+ /* flush old context */
+ old_gctx->stapi->st_flush(old_gctx->st_ctx,
+ PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL);
+
+ /*
+ * The old context is no longer current, and egl_g3d_realloc_context()
+ * should be called to destroy the framebuffers. However, it is possible
+ * that it will be made current again with the same draw/read surfaces.
+ * It might be better to keep it around.
+ */
+ }
+
+ if (gctx) {
+ struct egl_g3d_surface *gdraw = egl_g3d_surface(draw);
+
+ ok = egl_g3d_realloc_context(dpy, &gctx->base);
+ if (ok) {
+ ok = gctx->stapi->st_make_current(gctx->st_ctx,
+ gctx->draw.st_fb, gctx->read.st_fb);
+ if (ok) {
+ egl_g3d_validate_context(dpy, &gctx->base);
+ if (gdraw->base.Type == EGL_WINDOW_BIT) {
+ gctx->base.WindowRenderBuffer =
+ (gdraw->render_att == NATIVE_ATTACHMENT_FRONT_LEFT) ?
+ EGL_SINGLE_BUFFER : EGL_BACK_BUFFER;
+ }
+ }
+ }
+ }
+ else if (old_gctx) {
+ ok = old_gctx->stapi->st_make_current(NULL, NULL, NULL);
+ old_gctx->base.WindowRenderBuffer = EGL_NONE;
+ }
+
+ return ok;
+}
+
+static EGLBoolean
+egl_g3d_swap_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf)
+{
+ struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
+ _EGLContext *ctx = _eglGetCurrentContext();
+ struct egl_g3d_context *gctx = NULL;
+
+ /* no-op for pixmap or pbuffer surface */
+ if (gsurf->base.Type == EGL_PIXMAP_BIT ||
+ gsurf->base.Type == EGL_PBUFFER_BIT)
+ return EGL_TRUE;
+
+ /* or when the surface is single-buffered */
+ if (gsurf->render_att == NATIVE_ATTACHMENT_FRONT_LEFT)
+ return EGL_TRUE;
+
+ if (ctx && ctx->DrawSurface == surf)
+ gctx = egl_g3d_context(ctx);
+
+ /* flush if the surface is current */
+ if (gctx)
+ gctx->stapi->st_notify_swapbuffers(gctx->draw.st_fb);
+
+ /*
+ * We drew on the back buffer, unless there was no back buffer.
+ * In that case, we drew on the front buffer. Either case, we call
+ * swap_buffers.
+ */
+ if (!gsurf->native->swap_buffers(gsurf->native))
+ return EGL_FALSE;
+
+ if (gctx) {
+ struct egl_g3d_config *gconf = egl_g3d_config(gsurf->base.Config);
+
+ /* force validation if the swap method is not copy */
+ if (gconf->native->mode.swapMethod != GLX_SWAP_COPY_OML) {
+ gctx->force_validate = EGL_TRUE;
+ egl_g3d_validate_context(dpy, &gctx->base);
+ }
+ }
+
+ return EGL_TRUE;
+}
+
+/**
+ * Find a config that supports the pixmap.
+ */
+static _EGLConfig *
+find_pixmap_config(_EGLDisplay *dpy, EGLNativePixmapType pix)
+{
+ struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
+ struct egl_g3d_config *gconf;
+ EGLint i;
+
+ for (i = 0; i < dpy->NumConfigs; i++) {
+ gconf = egl_g3d_config(dpy->Configs[i]);
+ if (gdpy->native->is_pixmap_supported(gdpy->native, pix, gconf->native))
+ break;
+ }
+
+ return (i < dpy->NumConfigs) ? &gconf->base : NULL;
+}
+
+/**
+ * Get the pipe surface of the given attachment of the native surface.
+ */
+static struct pipe_surface *
+get_pipe_surface(struct native_display *ndpy, struct native_surface *nsurf,
+ enum native_attachment natt)
+{
+ struct pipe_texture *textures[NUM_NATIVE_ATTACHMENTS];
+ struct pipe_surface *psurf;
+
+ textures[natt] = NULL;
+ nsurf->validate(nsurf, 1 << natt, NULL, textures, NULL, NULL);
+ if (!textures[natt])
+ return NULL;
+
+ psurf = ndpy->screen->get_tex_surface(ndpy->screen, textures[natt],
+ 0, 0, 0, PIPE_BUFFER_USAGE_CPU_WRITE);
+ pipe_texture_reference(&textures[natt], NULL);
+
+ return psurf;
+}
+
+static EGLBoolean
+egl_g3d_copy_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
+ NativePixmapType target)
+{
+ struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
+ struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
+ _EGLContext *ctx = _eglGetCurrentContext();
+ struct egl_g3d_config *gconf;
+ struct native_surface *nsurf;
+ struct pipe_screen *screen = gdpy->native->screen;
+ struct pipe_surface *psurf;
+
+ if (!gsurf->render_surface)
+ return EGL_TRUE;
+
+ gconf = egl_g3d_config(find_pixmap_config(dpy, target));
+ if (!gconf)
+ return _eglError(EGL_BAD_NATIVE_PIXMAP, "eglCopyBuffers");
+
+ nsurf = gdpy->native->create_pixmap_surface(gdpy->native,
+ target, gconf->native);
+ if (!nsurf)
+ return _eglError(EGL_BAD_NATIVE_PIXMAP, "eglCopyBuffers");
+
+ /* flush if the surface is current */
+ if (ctx && ctx->DrawSurface == &gsurf->base) {
+ struct egl_g3d_context *gctx = egl_g3d_context(ctx);
+ gctx->stapi->st_flush(gctx->st_ctx,
+ PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL);
+ }
+
+ psurf = get_pipe_surface(gdpy->native, nsurf, NATIVE_ATTACHMENT_FRONT_LEFT);
+ if (psurf) {
+ struct pipe_context pipe;
+
+ /**
+ * XXX This is hacky. If we might allow the EGLDisplay to create a pipe
+ * context of its own and use the blitter context for this.
+ */
+ memset(&pipe, 0, sizeof(pipe));
+ pipe.screen = screen;
+
+ util_surface_copy(&pipe, FALSE, psurf, 0, 0,
+ gsurf->render_surface, 0, 0, psurf->width, psurf->height);
+
+ pipe_surface_reference(&psurf, NULL);
+ nsurf->flush_frontbuffer(nsurf);
+ }
+
+ nsurf->destroy(nsurf);
+
+ return EGL_TRUE;
+}
+
+static EGLBoolean
+egl_g3d_wait_client(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx)
+{
+ struct egl_g3d_context *gctx = egl_g3d_context(ctx);
+ gctx->stapi->st_finish(gctx->st_ctx);
+ return EGL_TRUE;
+}
+
+static EGLBoolean
+egl_g3d_wait_native(_EGLDriver *drv, _EGLDisplay *dpy, EGLint engine)
+{
+ _EGLSurface *surf = _eglGetCurrentSurface(EGL_DRAW);
+ struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
+
+ if (engine != EGL_CORE_NATIVE_ENGINE)
+ return _eglError(EGL_BAD_PARAMETER, "eglWaitNative");
+
+ if (gsurf)
+ gsurf->native->wait(gsurf->native);
+
+ return EGL_TRUE;
+}
+
+static _EGLProc
+egl_g3d_get_proc_address(_EGLDriver *drv, const char *procname)
+{
+ struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
+ _EGLProc proc;
+ EGLint i;
+
+ /* in case this is called before a display is initialized */
+ egl_g3d_init_st(&gdrv->base);
+
+ for (i = 0; i < NUM_EGL_G3D_STS; i++) {
+ const struct egl_g3d_st *stapi = gdrv->stapis[i];
+ if (stapi) {
+ proc = (_EGLProc) stapi->st_get_proc_address(procname);
+ if (proc)
+ return proc;
+ }
+ }
+
+ return (_EGLProc) NULL;
+}
+
+static EGLBoolean
+egl_g3d_bind_tex_image(_EGLDriver *drv, _EGLDisplay *dpy,
+ _EGLSurface *surf, EGLint buffer)
+{
+ struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
+ struct egl_g3d_context *gctx;
+ enum pipe_format target_format;
+ int target;
+
+ if (!gsurf || gsurf->base.Type != EGL_PBUFFER_BIT)
+ return _eglError(EGL_BAD_SURFACE, "eglBindTexImage");
+ if (buffer != EGL_BACK_BUFFER)
+ return _eglError(EGL_BAD_PARAMETER, "eglBindTexImage");
+ if (gsurf->base.BoundToTexture)
+ return _eglError(EGL_BAD_ACCESS, "eglBindTexImage");
+
+ switch (gsurf->base.TextureFormat) {
+ case EGL_TEXTURE_RGB:
+ target_format = PIPE_FORMAT_R8G8B8_UNORM;
+ break;
+ case EGL_TEXTURE_RGBA:
+ target_format = PIPE_FORMAT_A8R8G8B8_UNORM;
+ break;
+ default:
+ return _eglError(EGL_BAD_MATCH, "eglBindTexImage");
+ }
+
+ switch (gsurf->base.TextureTarget) {
+ case EGL_TEXTURE_2D:
+ target = ST_TEXTURE_2D;
+ break;
+ default:
+ return _eglError(EGL_BAD_MATCH, "eglBindTexImage");
+ }
+
+ /* flush properly if the surface is bound */
+ if (gsurf->base.Binding) {
+ gctx = egl_g3d_context(gsurf->base.Binding);
+ gctx->stapi->st_flush(gctx->st_ctx,
+ PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL);
+ }
+
+ /* XXX change to EGL_OPENGL_ES_API once OpenGL ES is merged */
+ gctx = egl_g3d_get_current_context(EGL_OPENGL_API);
+ if (gctx) {
+ if (!gsurf->render_surface)
+ return EGL_FALSE;
+
+ gctx->stapi->st_bind_texture_surface(gsurf->render_surface,
+ target, gsurf->base.MipmapLevel, target_format);
+ gsurf->base.BoundToTexture = EGL_TRUE;
+ }
+
+ return EGL_TRUE;
+}
+
+static EGLBoolean
+egl_g3d_release_tex_image(_EGLDriver *drv, _EGLDisplay *dpy,
+ _EGLSurface *surf, EGLint buffer)
+{
+ struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
+
+ if (!gsurf || gsurf->base.Type != EGL_PBUFFER_BIT ||
+ !gsurf->base.BoundToTexture)
+ return _eglError(EGL_BAD_SURFACE, "eglReleaseTexImage");
+ if (buffer != EGL_BACK_BUFFER)
+ return _eglError(EGL_BAD_PARAMETER, "eglReleaseTexImage");
+
+ if (gsurf->render_surface) {
+ _EGLThreadInfo *t = _eglGetCurrentThread();
+ /* XXX change to EGL_OPENGL_ES_API once OpenGL ES is merged */
+ struct egl_g3d_context *gctx = egl_g3d_context(
+ t->CurrentContexts[_eglConvertApiToIndex(EGL_OPENGL_API)]);
+
+ /* what if the context the surface binds to is no longer current? */
+ if (gctx)
+ gctx->stapi->st_unbind_texture_surface(gsurf->render_surface,
+ ST_TEXTURE_2D, gsurf->base.MipmapLevel);
+ }
+
+ gsurf->base.BoundToTexture = EGL_FALSE;
+
+ 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 EGLint
+egl_g3d_probe(_EGLDriver *drv, _EGLDisplay *dpy)
+{
+ struct native_probe *nprobe;
+ enum native_probe_result res;
+ EGLint score;
+
+ nprobe = egl_g3d_get_probe(drv, dpy);
+ res = native_get_probe_result(nprobe);
+
+ switch (res) {
+ case NATIVE_PROBE_UNKNOWN:
+ default:
+ score = 0;
+ break;
+ case NATIVE_PROBE_FALLBACK:
+ score = 40;
+ break;
+ case NATIVE_PROBE_SUPPORTED:
+ score = 50;
+ break;
+ case NATIVE_PROBE_EXACT:
+ score = 100;
+ break;
+ }
+
+ return score;
+}
+
+static void
+egl_g3d_unload(_EGLDriver *drv)
+{
+ struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
+
+ egl_g3d_destroy_probe(drv, NULL);
+ free(gdrv);
+}
+
+_EGLDriver *
+_eglMain(const char *args)
+{
+ static char driver_name[64];
+ struct egl_g3d_driver *gdrv;
+
+ snprintf(driver_name, sizeof(driver_name),
+ "Gallium/%s", native_get_name());
+
+ gdrv = CALLOC_STRUCT(egl_g3d_driver);
+ if (!gdrv)
+ return NULL;
+
+ _eglInitDriverFallbacks(&gdrv->base);
+
+ gdrv->base.API.Initialize = egl_g3d_initialize;
+ gdrv->base.API.Terminate = egl_g3d_terminate;
+ gdrv->base.API.CreateContext = egl_g3d_create_context;
+ gdrv->base.API.DestroyContext = egl_g3d_destroy_context;
+ gdrv->base.API.CreateWindowSurface = egl_g3d_create_window_surface;
+ gdrv->base.API.CreatePixmapSurface = egl_g3d_create_pixmap_surface;
+ gdrv->base.API.CreatePbufferSurface = egl_g3d_create_pbuffer_surface;
+ gdrv->base.API.DestroySurface = egl_g3d_destroy_surface;
+ gdrv->base.API.MakeCurrent = egl_g3d_make_current;
+ gdrv->base.API.SwapBuffers = egl_g3d_swap_buffers;
+ gdrv->base.API.CopyBuffers = egl_g3d_copy_buffers;
+ gdrv->base.API.WaitClient = egl_g3d_wait_client;
+ gdrv->base.API.WaitNative = egl_g3d_wait_native;
+ gdrv->base.API.GetProcAddress = egl_g3d_get_proc_address;
+
+ 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.Probe = egl_g3d_probe;
+ gdrv->base.Unload = egl_g3d_unload;
+
+ /* the key is " EGL G3D" */
+ gdrv->probe_key = 0x0E61063D;
+
+ return &gdrv->base;
+}
--- /dev/null
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.8
+ *
+ * Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org>
+ *
+ * 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
+ * BRIAN PAUL 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.
+ */
+
+#ifndef _EGL_G3D_H_
+#define _EGL_G3D_H_
+
+#include "pipe/p_compiler.h"
+#include "pipe/p_screen.h"
+#include "pipe/p_context.h"
+#include "pipe/p_format.h"
+#include "egldriver.h"
+#include "egldisplay.h"
+#include "eglcontext.h"
+#include "eglsurface.h"
+#include "eglconfig.h"
+#include "eglscreen.h"
+#include "eglmode.h"
+
+#include "native.h"
+#include "egl_st.h"
+
+struct egl_g3d_driver {
+ _EGLDriver base;
+ const struct egl_g3d_st *stapis[NUM_EGL_G3D_STS];
+ EGLint api_mask;
+
+ EGLint probe_key;
+};
+
+struct egl_g3d_display {
+ struct native_display *native;
+};
+
+struct egl_g3d_buffer {
+ struct st_framebuffer *st_fb;
+ uint attachment_mask;
+};
+
+struct egl_g3d_context {
+ _EGLContext base;
+
+ const struct egl_g3d_st *stapi;
+ struct pipe_context *pipe;
+
+ struct st_context *st_ctx;
+ EGLBoolean force_validate;
+ struct egl_g3d_buffer draw, read;
+};
+
+struct egl_g3d_surface {
+ _EGLSurface base;
+ struct native_surface *native;
+ enum native_attachment render_att;
+ struct pipe_surface *render_surface;
+ unsigned int sequence_number;
+};
+
+struct egl_g3d_config {
+ _EGLConfig base;
+ 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)
+{
+ return (struct egl_g3d_driver *) drv;
+}
+
+static INLINE struct egl_g3d_display *
+egl_g3d_display(_EGLDisplay *dpy)
+{
+ /* note that it is not direct casting */
+ return (struct egl_g3d_display *) dpy->DriverData;
+}
+
+static INLINE struct egl_g3d_context *
+egl_g3d_context(_EGLContext *ctx)
+{
+ return (struct egl_g3d_context *) ctx;
+}
+
+static INLINE struct egl_g3d_surface *
+egl_g3d_surface(_EGLSurface *surf)
+{
+ return (struct egl_g3d_surface *) surf;
+}
+
+static INLINE struct egl_g3d_config *
+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_ */
--- /dev/null
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.8
+ *
+ * Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org>
+ *
+ * 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
+ * BRIAN PAUL 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.
+ */
+
+#include <dlfcn.h>
+#include "pipe/p_compiler.h"
+#include "util/u_memory.h"
+#include "egllog.h"
+#include "EGL/egl.h" /* for EGL_api_BIT */
+
+#include "egl_st.h"
+
+#ifndef HAVE_DLADDR
+#define HAVE_DLADDR 1
+#endif
+
+#if HAVE_DLADDR
+
+static const char *
+egl_g3d_st_names[] = {
+#define ST_PUBLIC(name, ...) #name,
+#include "st_public_tmp.h"
+ NULL
+};
+
+static boolean
+egl_g3d_fill_st(struct egl_g3d_st *stapi, void *sym)
+{
+ st_proc *procs = (st_proc *) stapi;
+ void *handle;
+ Dl_info info;
+ const char **name;
+
+ if (!dladdr(sym, &info))
+ return FALSE;
+ handle = dlopen(info.dli_fname, RTLD_LAZY | RTLD_LOCAL | RTLD_NODELETE);
+ if (!handle)
+ return FALSE;
+
+ for (name = egl_g3d_st_names; *name; name++) {
+ st_proc proc = (st_proc) dlsym(handle, *name);
+ if (!proc) {
+ _eglLog(_EGL_WARNING, "%s is missing in %s", *name, info.dli_fname);
+ memset(stapi, 0, sizeof(*stapi));
+ dlclose(handle);
+ return FALSE;
+ }
+ *procs++ = proc;
+ }
+
+ dlclose(handle);
+ return TRUE;
+}
+
+#else /* HAVE_DLADDR */
+
+static boolean
+egl_g3d_fill_st(struct egl_g3d_st *stapi, void *sym)
+{
+#define ST_PUBLIC(name, ...) stapi->name = name;
+#include "st_public_tmp.h"
+ return TRUE;
+}
+
+#endif /* HAVE_DLADDR */
+
+static boolean
+egl_g3d_init_st(struct egl_g3d_st *stapi, const char *api)
+{
+ void *handle, *sym;
+ boolean res = FALSE;
+
+ /* already initialized */
+ if (stapi->st_notify_swapbuffers != NULL)
+ return TRUE;
+
+ handle = dlopen(NULL, RTLD_LAZY | RTLD_LOCAL);
+ if (!handle)
+ return FALSE;
+
+ sym = dlsym(handle, api);
+ if (sym && egl_g3d_fill_st(stapi, sym))
+ res = TRUE;
+
+ dlclose(handle);
+ return res;
+}
+
+static struct {
+ const char *symbol;
+ EGLint api_bit;
+} egl_g3d_st_info[NUM_EGL_G3D_STS] = {
+ { "st_api_OpenGL_ES1", EGL_OPENGL_ES_BIT },
+ { "st_api_OpenVG", EGL_OPENVG_BIT },
+ { "st_api_OpenGL_ES2", EGL_OPENGL_ES2_BIT },
+ { "st_api_OpenGL", EGL_OPENGL_BIT },
+};
+
+const struct egl_g3d_st *
+egl_g3d_get_st(enum egl_g3d_st_api api)
+{
+ static struct egl_g3d_st all_trackers[NUM_EGL_G3D_STS];
+
+ if (egl_g3d_init_st(&all_trackers[api], egl_g3d_st_info[api].symbol)) {
+ all_trackers[api].api_bit = egl_g3d_st_info[api].api_bit;
+ return &all_trackers[api];
+ }
+ else {
+ return NULL;
+ }
+}
--- /dev/null
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.8
+ *
+ * Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org>
+ *
+ * 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
+ * BRIAN PAUL 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.
+ */
+
+#ifndef _EGL_ST_H_
+#define _EGL_ST_H_
+
+#include "GL/gl.h" /* for GL types */
+#include "GL/internal/glcore.h" /* for __GLcontextModes */
+
+#include "pipe/p_compiler.h"
+#include "pipe/p_format.h"
+#include "pipe/p_context.h"
+
+/* avoid calling st functions directly */
+#if 1
+
+#define ST_SURFACE_FRONT_LEFT 0
+#define ST_SURFACE_BACK_LEFT 1
+#define ST_SURFACE_FRONT_RIGHT 2
+#define ST_SURFACE_BACK_RIGHT 3
+
+#define ST_TEXTURE_2D 0x2
+
+struct st_context;
+struct st_framebuffer;
+typedef void (*st_proc)();
+
+#else
+#include "state_tracker/st_public.h"
+#endif
+
+/* remember to update egl_g3d_get_st() when update the enums */
+enum egl_g3d_st_api {
+ EGL_G3D_ST_OPENGL_ES = 0,
+ EGL_G3D_ST_OPENVG,
+ EGL_G3D_ST_OPENGL_ES2,
+ EGL_G3D_ST_OPENGL,
+
+ NUM_EGL_G3D_STS
+};
+
+struct egl_g3d_st {
+#define ST_PUBLIC(name, ret, ...) ret (*name)(__VA_ARGS__);
+#include "st_public_tmp.h"
+ /* fields must be added here */
+ EGLint api_bit;
+};
+
+const struct egl_g3d_st *
+egl_g3d_get_st(enum egl_g3d_st_api api);
+
+#endif /* _EGL_ST_H_ */
--- /dev/null
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.8
+ *
+ * Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org>
+ *
+ * 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
+ * BRIAN PAUL 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.
+ */
+
+#ifndef _NATIVE_H_
+#define _NATIVE_H_
+
+#include "EGL/egl.h" /* for EGL native types */
+#include "GL/gl.h" /* for GL types needed by __GLcontextModes */
+#include "GL/internal/glcore.h" /* for __GLcontextModes */
+
+#include "pipe/p_compiler.h"
+#include "pipe/p_screen.h"
+#include "pipe/p_context.h"
+#include "pipe/p_state.h"
+
+/**
+ * Only color buffers are listed. The others are allocated privately through,
+ * for example, st_renderbuffer_alloc_storage().
+ */
+enum native_attachment {
+ NATIVE_ATTACHMENT_FRONT_LEFT,
+ NATIVE_ATTACHMENT_BACK_LEFT,
+ NATIVE_ATTACHMENT_FRONT_RIGHT,
+ NATIVE_ATTACHMENT_BACK_RIGHT,
+
+ NUM_NATIVE_ATTACHMENTS
+};
+
+/**
+ * Enumerations for probe results.
+ */
+enum native_probe_result {
+ NATIVE_PROBE_UNKNOWN,
+ NATIVE_PROBE_FALLBACK,
+ NATIVE_PROBE_SUPPORTED,
+ NATIVE_PROBE_EXACT,
+};
+
+/**
+ * A probe object for display probe.
+ */
+struct native_probe {
+ int magic;
+ EGLNativeDisplayType display;
+ void *data;
+
+ void (*destroy)(struct native_probe *nprobe);
+};
+
+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.
+ */
+ boolean (*flush_frontbuffer)(struct native_surface *nsurf);
+
+ /**
+ * Validate the buffers of the surface. textures, if not NULL, points to an
+ * array of size NUM_NATIVE_ATTACHMENTS and the returned textures are owned
+ * by the caller. A sequence number is also returned. The caller can use
+ * it to check if anything has changed since the last call. Any of the
+ * pointers may be NULL and it indicates the caller has no interest in those
+ * values.
+ *
+ * If this function is called multiple times with different attachment
+ * masks, those not listed in the latest call might be destroyed. This
+ * behavior might change in the future.
+ */
+ boolean (*validate)(struct native_surface *nsurf, uint attachment_mask,
+ unsigned int *seq_num, struct pipe_texture **textures,
+ int *width, int *height);
+
+ /**
+ * Wait until all native commands affecting the surface has been executed.
+ */
+ void (*wait)(struct native_surface *nsurf);
+};
+
+struct native_config {
+ /* __GLcontextModes should go away some day */
+ __GLcontextModes mode;
+ enum pipe_format color_format;
+ enum pipe_format depth_format;
+ enum pipe_format stencil_format;
+
+ /* treat it as an additional flag to mode.drawableType */
+ boolean scanout_bit;
+};
+
+struct native_connector {
+ int dummy;
+};
+
+struct native_mode {
+ const char *desc;
+ int width, height;
+ int refresh_rate;
+};
+
+struct native_display_modeset;
+
+/**
+ * A pipe winsys abstracts the OS. A pipe screen abstracts the graphcis
+ * hardware. A native display consists of a pipe winsys, a pipe screen, and
+ * the native display server.
+ */
+struct native_display {
+ /**
+ * The pipe screen of the native display.
+ *
+ * Note that the "flush_frontbuffer" and "update_buffer" callbacks will be
+ * overridden.
+ */
+ struct pipe_screen *screen;
+
+ void (*destroy)(struct native_display *ndpy);
+
+ /**
+ * Get the supported configs. The configs are owned by the display, but
+ * the returned array should be free()ed.
+ *
+ * The configs will be converted to EGL config by
+ * _eglConfigFromContextModesRec and validated by _eglValidateConfig.
+ * Those failing to pass the test will be skipped.
+ */
+ const struct native_config **(*get_configs)(struct native_display *ndpy,
+ int *num_configs);
+
+ /**
+ * Test if a pixmap is supported by the given config. Required unless no
+ * config has GLX_PIXMAP_BIT set.
+ *
+ * This function is usually called to find a config that supports a given
+ * pixmap. Thus, it is usually called with the same pixmap in a row.
+ */
+ boolean (*is_pixmap_supported)(struct native_display *ndpy,
+ EGLNativePixmapType pix,
+ const struct native_config *nconf);
+
+ /**
+ * Create a pipe context.
+ */
+ struct pipe_context *(*create_context)(struct native_display *ndpy,
+ void *context_private);
+
+ /**
+ * Create a window surface. Required unless no config has GLX_WINDOW_BIT
+ * set.
+ */
+ struct native_surface *(*create_window_surface)(struct native_display *ndpy,
+ EGLNativeWindowType win,
+ const struct native_config *nconf);
+
+ /**
+ * Create a pixmap surface. Required unless no config has GLX_PIXMAP_BIT
+ * set.
+ */
+ struct native_surface *(*create_pixmap_surface)(struct native_display *ndpy,
+ EGLNativePixmapType pix,
+ const struct native_config *nconf);
+
+ /**
+ * Create a pbuffer surface. Required unless no config has GLX_PBUFFER_BIT
+ * set.
+ */
+ struct native_surface *(*create_pbuffer_surface)(struct native_display *ndpy,
+ const struct native_config *nconf,
+ uint width, uint height);
+
+ const struct native_display_modeset *modeset;
+};
+
+/**
+ * Mode setting interface of the native display. It exposes the mode setting
+ * capabilities of the underlying graphics hardware.
+ */
+struct native_display_modeset {
+ /**
+ * Get the available physical connectors and the number of CRTCs.
+ */
+ const struct native_connector **(*get_connectors)(struct native_display *ndpy,
+ int *num_connectors,
+ int *num_crtcs);
+
+ /**
+ * Get the current supported modes of a connector. The returned modes may
+ * change every time this function is called and those from previous calls
+ * might become invalid.
+ */
+ const struct native_mode **(*get_modes)(struct native_display *ndpy,
+ const struct native_connector *nconn,
+ int *num_modes);
+
+ /**
+ * Create a scan-out surface. Required unless no config has
+ * GLX_SCREEN_BIT_MESA set.
+ */
+ struct native_surface *(*create_scanout_surface)(struct native_display *ndpy,
+ const struct native_config *nconf,
+ uint width, uint height);
+
+ /**
+ * Program the CRTC to output the surface to the given connectors with the
+ * given mode. When surface is not given, the CRTC is disabled.
+ *
+ * This interface does not export a way to query capabilities of the CRTCs.
+ * The native display usually needs to dynamically map the index to a CRTC
+ * that supports the given connectors.
+ */
+ boolean (*program)(struct native_display *ndpy, int crtc_idx,
+ struct native_surface *nsurf, uint x, uint y,
+ const struct native_connector **nconns, int num_nconns,
+ const struct native_mode *nmode);
+};
+
+/**
+ * Test whether an attachment is set in the mask.
+ */
+static INLINE boolean
+native_attachment_mask_test(uint mask, enum native_attachment att)
+{
+ return !!(mask & (1 << att));
+}
+
+/**
+ * Return a probe object for the given display.
+ *
+ * Note that the returned object may be cached and used by different native
+ * display modules. It allows fast probing when multiple modules probe the
+ * same display.
+ */
+struct native_probe *
+native_create_probe(EGLNativeDisplayType dpy);
+
+/**
+ * Probe the probe object.
+ */
+enum native_probe_result
+native_get_probe_result(struct native_probe *nprobe);
+
+const char *
+native_get_name(void);
+
+struct native_display *
+native_create_display(EGLNativeDisplayType dpy);
+
+#endif /* _NATIVE_H_ */
--- /dev/null
+ST_PUBLIC(st_create_context, struct st_context *, struct pipe_context *pipe, const __GLcontextModes *visual, struct st_context *share)
+ST_PUBLIC(st_destroy_context, void, struct st_context *st)
+ST_PUBLIC(st_copy_context_state, void, struct st_context *dst, struct st_context *src, uint mask)
+ST_PUBLIC(st_create_framebuffer, struct st_framebuffer *, const __GLcontextModes *visual, enum pipe_format colorFormat, enum pipe_format depthFormat, enum pipe_format stencilFormat, uint width, uint height, void *privateData)
+ST_PUBLIC(st_resize_framebuffer, void, struct st_framebuffer *stfb, uint width, uint height)
+ST_PUBLIC(st_set_framebuffer_surface, void, struct st_framebuffer *stfb, uint surfIndex, struct pipe_surface *surf)
+ST_PUBLIC(st_get_framebuffer_dimensions, void, struct st_framebuffer *stfb, uint *width, uint *height)
+ST_PUBLIC(st_get_framebuffer_surface, int, struct st_framebuffer *stfb, uint surfIndex, struct pipe_surface **surface)
+ST_PUBLIC(st_get_framebuffer_texture, int, struct st_framebuffer *stfb, uint surfIndex, struct pipe_texture **texture)
+ST_PUBLIC(st_framebuffer_private, void *, struct st_framebuffer *stfb)
+ST_PUBLIC(st_unreference_framebuffer, void, struct st_framebuffer *stfb)
+ST_PUBLIC(st_make_current, GLboolean, struct st_context *st, struct st_framebuffer *draw, struct st_framebuffer *read)
+ST_PUBLIC(st_get_current, struct st_context *, void)
+ST_PUBLIC(st_flush, void, struct st_context *st, uint pipeFlushFlags, struct pipe_fence_handle **fence)
+ST_PUBLIC(st_finish, void, struct st_context *st)
+ST_PUBLIC(st_notify_swapbuffers, void, struct st_framebuffer *stfb)
+ST_PUBLIC(st_bind_texture_surface, int, struct pipe_surface *ps, int target, int level, enum pipe_format format)
+ST_PUBLIC(st_unbind_texture_surface, int, struct pipe_surface *ps, int target, int level)
+ST_PUBLIC(st_get_proc_address, st_proc, const char *procname)
+#undef ST_PUBLIC
--- /dev/null
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.8
+ *
+ * Copyright (C) 2010 Chia-I Wu <olv@0xlab.org>
+ *
+ * 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
+ * BRIAN PAUL 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.
+ */
+
+#include <string.h>
+
+#include "pipe/p_screen.h"
+#include "pipe/p_context.h"
+#include "util/u_debug.h"
+#include "util/u_memory.h"
+#include "egllog.h"
+
+#include "native_kms.h"
+
+static boolean
+kms_surface_validate(struct native_surface *nsurf, uint attachment_mask,
+ unsigned int *seq_num, struct pipe_texture **textures,
+ int *width, int *height)
+{
+ struct kms_surface *ksurf = kms_surface(nsurf);
+ struct kms_display *kdpy = ksurf->kdpy;
+ struct pipe_screen *screen = kdpy->base.screen;
+ struct pipe_texture templ, *ptex;
+ int att;
+
+ if (attachment_mask) {
+ memset(&templ, 0, sizeof(templ));
+ templ.target = PIPE_TEXTURE_2D;
+ templ.last_level = 0;
+ templ.width0 = ksurf->width;
+ templ.height0 = ksurf->height;
+ templ.depth0 = 1;
+ templ.format = ksurf->color_format;
+ templ.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET;
+ if (ksurf->type == KMS_SURFACE_TYPE_SCANOUT)
+ templ.tex_usage |= PIPE_TEXTURE_USAGE_PRIMARY;
+ }
+
+ /* create textures */
+ for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) {
+ /* delay the allocation */
+ if (!native_attachment_mask_test(attachment_mask, att))
+ continue;
+
+ ptex = ksurf->textures[att];
+ if (!ptex) {
+ ptex = screen->texture_create(screen, &templ);
+ ksurf->textures[att] = ptex;
+ }
+
+ if (textures) {
+ textures[att] = NULL;
+ pipe_texture_reference(&textures[att], ptex);
+ }
+ }
+
+ if (seq_num)
+ *seq_num = ksurf->sequence_number;
+ if (width)
+ *width = ksurf->width;
+ if (height)
+ *height = ksurf->height;
+
+ return TRUE;
+}
+
+/**
+ * Add textures as DRM framebuffers.
+ */
+static boolean
+kms_surface_init_framebuffers(struct native_surface *nsurf, boolean need_back)
+{
+ struct kms_surface *ksurf = kms_surface(nsurf);
+ struct kms_display *kdpy = ksurf->kdpy;
+ int num_framebuffers = (need_back) ? 2 : 1;
+ int i, err;
+
+ for (i = 0; i < num_framebuffers; i++) {
+ struct kms_framebuffer *fb;
+ enum native_attachment natt;
+ unsigned int handle, stride;
+ uint block_bits;
+
+ if (i == 0) {
+ fb = &ksurf->front_fb;
+ natt = NATIVE_ATTACHMENT_FRONT_LEFT;
+ }
+ else {
+ fb = &ksurf->back_fb;
+ natt = NATIVE_ATTACHMENT_BACK_LEFT;
+ }
+
+ if (!fb->texture) {
+ /* make sure the texture has been allocated */
+ kms_surface_validate(&ksurf->base, 1 << natt, NULL, NULL, NULL, NULL);
+ if (!ksurf->textures[natt])
+ return FALSE;
+
+ pipe_texture_reference(&fb->texture, ksurf->textures[natt]);
+ }
+
+ /* already initialized */
+ if (fb->buffer_id)
+ continue;
+
+ /* TODO detect the real value */
+ fb->is_passive = TRUE;
+
+ if (!kdpy->api->local_handle_from_texture(kdpy->api,
+ kdpy->base.screen, fb->texture, &stride, &handle))
+ return FALSE;
+
+ block_bits = util_format_get_blocksizebits(ksurf->color_format);
+ err = drmModeAddFB(kdpy->fd, ksurf->width, ksurf->height,
+ block_bits, block_bits, stride, handle, &fb->buffer_id);
+ if (err) {
+ fb->buffer_id = 0;
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+static boolean
+kms_surface_flush_frontbuffer(struct native_surface *nsurf)
+{
+#ifdef DRM_MODE_FEATURE_DIRTYFB
+ struct kms_surface *ksurf = kms_surface(nsurf);
+ struct kms_display *kdpy = ksurf->kdpy;
+
+ /* pbuffer is private */
+ if (ksurf->type == KMS_SURFACE_TYPE_PBUFFER)
+ return TRUE;
+
+ if (ksurf->front_fb.is_passive)
+ drmModeDirtyFB(kdpy->fd, ksurf->front_fb.buffer_id, NULL, 0);
+#endif
+
+ return TRUE;
+}
+
+static boolean
+kms_surface_swap_buffers(struct native_surface *nsurf)
+{
+ struct kms_surface *ksurf = kms_surface(nsurf);
+ struct kms_crtc *kcrtc = &ksurf->current_crtc;
+ struct kms_display *kdpy = ksurf->kdpy;
+ struct kms_framebuffer tmp_fb;
+ struct pipe_texture *tmp_texture;
+ int err;
+
+ /* pbuffer is private */
+ if (ksurf->type == KMS_SURFACE_TYPE_PBUFFER)
+ return TRUE;
+
+ if (!ksurf->back_fb.buffer_id) {
+ if (!kms_surface_init_framebuffers(&ksurf->base, TRUE))
+ return FALSE;
+ }
+
+ if (ksurf->is_shown && kcrtc->crtc) {
+ err = drmModeSetCrtc(kdpy->fd, kcrtc->crtc->crtc_id,
+ ksurf->back_fb.buffer_id, kcrtc->crtc->x, kcrtc->crtc->y,
+ kcrtc->connectors, kcrtc->num_connectors, &kcrtc->crtc->mode);
+ if (err)
+ return FALSE;
+ }
+
+ /* swap the buffers */
+ tmp_fb = ksurf->front_fb;
+ ksurf->front_fb = ksurf->back_fb;
+ ksurf->back_fb = tmp_fb;
+
+ tmp_texture = ksurf->textures[NATIVE_ATTACHMENT_FRONT_LEFT];
+ ksurf->textures[NATIVE_ATTACHMENT_FRONT_LEFT] =
+ ksurf->textures[NATIVE_ATTACHMENT_BACK_LEFT];
+ ksurf->textures[NATIVE_ATTACHMENT_BACK_LEFT] = tmp_texture;
+
+ /* the front/back textures are swapped */
+ ksurf->sequence_number++;
+
+ return TRUE;
+}
+
+static void
+kms_surface_wait(struct native_surface *nsurf)
+{
+ /* no-op */
+}
+
+static void
+kms_surface_destroy(struct native_surface *nsurf)
+{
+ struct kms_surface *ksurf = kms_surface(nsurf);
+ int i;
+
+ if (ksurf->current_crtc.crtc)
+ drmModeFreeCrtc(ksurf->current_crtc.crtc);
+
+ if (ksurf->front_fb.buffer_id)
+ drmModeRmFB(ksurf->kdpy->fd, ksurf->front_fb.buffer_id);
+ pipe_texture_reference(&ksurf->front_fb.texture, NULL);
+
+ if (ksurf->back_fb.buffer_id)
+ drmModeRmFB(ksurf->kdpy->fd, ksurf->back_fb.buffer_id);
+ pipe_texture_reference(&ksurf->back_fb.texture, NULL);
+
+ for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) {
+ struct pipe_texture *ptex = ksurf->textures[i];
+ pipe_texture_reference(&ptex, NULL);
+ }
+
+ free(ksurf);
+}
+
+static struct kms_surface *
+kms_display_create_surface(struct native_display *ndpy,
+ enum kms_surface_type type,
+ const struct native_config *nconf,
+ uint width, uint height)
+{
+ struct kms_display *kdpy = kms_display(ndpy);
+ struct kms_config *kconf = kms_config(nconf);
+ struct kms_surface *ksurf;
+
+ ksurf = CALLOC_STRUCT(kms_surface);
+ if (!ksurf)
+ return NULL;
+
+ ksurf->kdpy = kdpy;
+ ksurf->type = type;
+ ksurf->color_format = kconf->base.color_format;
+ ksurf->width = width;
+ ksurf->height = height;
+
+ ksurf->base.destroy = kms_surface_destroy;
+ ksurf->base.swap_buffers = kms_surface_swap_buffers;
+ ksurf->base.flush_frontbuffer = kms_surface_flush_frontbuffer;
+ ksurf->base.validate = kms_surface_validate;
+ ksurf->base.wait = kms_surface_wait;
+
+ return ksurf;
+}
+
+/**
+ * Choose a CRTC that supports all given connectors.
+ */
+static uint32_t
+kms_display_choose_crtc(struct native_display *ndpy,
+ uint32_t *connectors, int num_connectors)
+{
+ struct kms_display *kdpy = kms_display(ndpy);
+ int idx;
+
+ for (idx = 0; idx < kdpy->resources->count_crtcs; idx++) {
+ boolean found_crtc = TRUE;
+ int i, j;
+
+ for (i = 0; i < num_connectors; i++) {
+ drmModeConnectorPtr connector;
+ int encoder_idx = -1;
+
+ connector = drmModeGetConnector(kdpy->fd, connectors[i]);
+ if (!connector) {
+ found_crtc = FALSE;
+ break;
+ }
+
+ /* find an encoder the CRTC supports */
+ for (j = 0; j < connector->count_encoders; j++) {
+ drmModeEncoderPtr encoder =
+ drmModeGetEncoder(kdpy->fd, connector->encoders[j]);
+ if (encoder->possible_crtcs & (1 << idx)) {
+ encoder_idx = j;
+ break;
+ }
+ drmModeFreeEncoder(encoder);
+ }
+
+ drmModeFreeConnector(connector);
+ if (encoder_idx < 0) {
+ found_crtc = FALSE;
+ break;
+ }
+ }
+
+ if (found_crtc)
+ break;
+ }
+
+ if (idx >= kdpy->resources->count_crtcs) {
+ _eglLog(_EGL_WARNING,
+ "failed to find a CRTC that supports the given %d connectors",
+ num_connectors);
+ return 0;
+ }
+
+ return kdpy->resources->crtcs[idx];
+}
+
+/**
+ * Remember the original CRTC status and set the CRTC
+ */
+static boolean
+kms_display_set_crtc(struct native_display *ndpy, int crtc_idx,
+ uint32_t buffer_id, uint32_t x, uint32_t y,
+ uint32_t *connectors, int num_connectors,
+ drmModeModeInfoPtr mode)
+{
+ struct kms_display *kdpy = kms_display(ndpy);
+ struct kms_crtc *kcrtc = &kdpy->saved_crtcs[crtc_idx];
+ uint32_t crtc_id;
+ int err;
+
+ if (kcrtc->crtc) {
+ crtc_id = kcrtc->crtc->crtc_id;
+ }
+ else {
+ int count = 0, i;
+
+ /*
+ * Choose the CRTC once. It could be more dynamic, but let's keep it
+ * simple for now.
+ */
+ crtc_id = kms_display_choose_crtc(&kdpy->base,
+ connectors, num_connectors);
+
+ /* save the original CRTC status */
+ kcrtc->crtc = drmModeGetCrtc(kdpy->fd, crtc_id);
+ if (!kcrtc->crtc)
+ return FALSE;
+
+ for (i = 0; i < kdpy->num_connectors; i++) {
+ struct kms_connector *kconn = &kdpy->connectors[i];
+ drmModeConnectorPtr connector = kconn->connector;
+ drmModeEncoderPtr encoder;
+
+ encoder = drmModeGetEncoder(kdpy->fd, connector->encoder_id);
+ if (encoder) {
+ if (encoder->crtc_id == crtc_id) {
+ kcrtc->connectors[count++] = connector->connector_id;
+ if (count >= Elements(kcrtc->connectors))
+ break;
+ }
+ drmModeFreeEncoder(encoder);
+ }
+ }
+
+ kcrtc->num_connectors = count;
+ }
+
+ err = drmModeSetCrtc(kdpy->fd, crtc_id, buffer_id, x, y,
+ connectors, num_connectors, mode);
+ if (err) {
+ drmModeFreeCrtc(kcrtc->crtc);
+ kcrtc->crtc = NULL;
+ kcrtc->num_connectors = 0;
+
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static boolean
+kms_display_program(struct native_display *ndpy, int crtc_idx,
+ struct native_surface *nsurf, uint x, uint y,
+ const struct native_connector **nconns, int num_nconns,
+ const struct native_mode *nmode)
+{
+ struct kms_display *kdpy = kms_display(ndpy);
+ struct kms_surface *ksurf = kms_surface(nsurf);
+ const struct kms_mode *kmode = kms_mode(nmode);
+ uint32_t connector_ids[32];
+ uint32_t buffer_id;
+ drmModeModeInfo mode_tmp, *mode;
+ int i;
+
+ if (num_nconns > Elements(connector_ids)) {
+ _eglLog(_EGL_WARNING, "too many connectors (%d)", num_nconns);
+ num_nconns = Elements(connector_ids);
+ }
+
+ if (ksurf) {
+ if (!kms_surface_init_framebuffers(&ksurf->base, FALSE))
+ return FALSE;
+
+ buffer_id = ksurf->front_fb.buffer_id;
+ /* the mode argument of drmModeSetCrtc is not constified */
+ mode_tmp = kmode->mode;
+ mode = &mode_tmp;
+ }
+ else {
+ /* disable the CRTC */
+ buffer_id = 0;
+ mode = NULL;
+ num_nconns = 0;
+ }
+
+ for (i = 0; i < num_nconns; i++) {
+ struct kms_connector *kconn = kms_connector(nconns[i]);
+ connector_ids[i] = kconn->connector->connector_id;
+ }
+
+ if (!kms_display_set_crtc(&kdpy->base, crtc_idx, buffer_id, x, y,
+ connector_ids, num_nconns, mode)) {
+ _eglLog(_EGL_WARNING, "failed to set CRTC %d", crtc_idx);
+
+ return FALSE;
+ }
+
+ if (kdpy->shown_surfaces[crtc_idx])
+ kdpy->shown_surfaces[crtc_idx]->is_shown = FALSE;
+ kdpy->shown_surfaces[crtc_idx] = ksurf;
+
+ /* remember the settings for buffer swapping */
+ if (ksurf) {
+ uint32_t crtc_id = kdpy->saved_crtcs[crtc_idx].crtc->crtc_id;
+ struct kms_crtc *kcrtc = &ksurf->current_crtc;
+
+ if (kcrtc->crtc)
+ drmModeFreeCrtc(kcrtc->crtc);
+ kcrtc->crtc = drmModeGetCrtc(kdpy->fd, crtc_id);
+
+ assert(num_nconns < Elements(kcrtc->connectors));
+ memcpy(kcrtc->connectors, connector_ids,
+ sizeof(*connector_ids) * num_nconns);
+ kcrtc->num_connectors = num_nconns;
+
+ ksurf->is_shown = TRUE;
+ }
+
+ return TRUE;
+}
+
+static const struct native_mode **
+kms_display_get_modes(struct native_display *ndpy,
+ const struct native_connector *nconn,
+ int *num_modes)
+{
+ struct kms_display *kdpy = kms_display(ndpy);
+ struct kms_connector *kconn = kms_connector(nconn);
+ const struct native_mode **nmodes_return;
+ int count, i;
+
+ /* delete old data */
+ if (kconn->connector) {
+ drmModeFreeConnector(kconn->connector);
+ free(kconn->kms_modes);
+
+ kconn->connector = NULL;
+ kconn->kms_modes = NULL;
+ kconn->num_modes = 0;
+ }
+
+ /* detect again */
+ kconn->connector = drmModeGetConnector(kdpy->fd, kconn->connector_id);
+ if (!kconn->connector)
+ return NULL;
+
+ count = kconn->connector->count_modes;
+ kconn->kms_modes = calloc(count, sizeof(*kconn->kms_modes));
+ if (!kconn->kms_modes) {
+ drmModeFreeConnector(kconn->connector);
+ kconn->connector = NULL;
+
+ return NULL;
+ }
+
+ for (i = 0; i < count; i++) {
+ struct kms_mode *kmode = &kconn->kms_modes[i];
+ drmModeModeInfoPtr mode = &kconn->connector->modes[i];
+
+ kmode->mode = *mode;
+
+ kmode->base.desc = kmode->mode.name;
+ kmode->base.width = kmode->mode.hdisplay;
+ kmode->base.height = kmode->mode.vdisplay;
+ kmode->base.refresh_rate = kmode->mode.vrefresh / 1000;
+ }
+
+ nmodes_return = malloc(count * sizeof(*nmodes_return));
+ if (nmodes_return) {
+ for (i = 0; i < count; i++)
+ nmodes_return[i] = &kconn->kms_modes[i].base;
+ if (num_modes)
+ *num_modes = count;
+ }
+
+ return nmodes_return;
+}
+
+static const struct native_connector **
+kms_display_get_connectors(struct native_display *ndpy, int *num_connectors,
+ int *num_crtc)
+{
+ struct kms_display *kdpy = kms_display(ndpy);
+ const struct native_connector **connectors;
+ int i;
+
+ if (!kdpy->connectors) {
+ kdpy->connectors =
+ calloc(kdpy->resources->count_connectors, sizeof(*kdpy->connectors));
+ if (!kdpy->connectors)
+ return NULL;
+
+ for (i = 0; i < kdpy->resources->count_connectors; i++) {
+ struct kms_connector *kconn = &kdpy->connectors[i];
+
+ kconn->connector_id = kdpy->resources->connectors[i];
+ /* kconn->connector is allocated when the modes are asked */
+ }
+
+ kdpy->num_connectors = kdpy->resources->count_connectors;
+ }
+
+ connectors = malloc(kdpy->num_connectors * sizeof(*connectors));
+ if (connectors) {
+ for (i = 0; i < kdpy->num_connectors; i++)
+ connectors[i] = &kdpy->connectors[i].base;
+ if (num_connectors)
+ *num_connectors = kdpy->num_connectors;
+ }
+
+ if (num_crtc)
+ *num_crtc = kdpy->resources->count_crtcs;
+
+ return connectors;
+}
+
+static struct native_surface *
+kms_display_create_scanout_surface(struct native_display *ndpy,
+ const struct native_config *nconf,
+ uint width, uint height)
+{
+ struct kms_surface *ksurf;
+
+ ksurf = kms_display_create_surface(ndpy,
+ KMS_SURFACE_TYPE_SCANOUT, nconf, width, height);
+ return &ksurf->base;
+}
+
+static struct native_surface *
+kms_display_create_pbuffer_surface(struct native_display *ndpy,
+ const struct native_config *nconf,
+ uint width, uint height)
+{
+ struct kms_surface *ksurf;
+
+ ksurf = kms_display_create_surface(ndpy,
+ KMS_SURFACE_TYPE_PBUFFER, nconf, width, height);
+ return &ksurf->base;
+}
+
+static struct pipe_context *
+kms_display_create_context(struct native_display *ndpy, void *context_private)
+{
+ struct kms_display *kdpy = kms_display(ndpy);
+ struct pipe_context *pctx;
+
+ pctx = kdpy->api->create_context(kdpy->api, kdpy->base.screen);
+ if (pctx)
+ pctx->priv = context_private;
+ return pctx;
+}
+
+static boolean
+kms_display_is_format_supported(struct native_display *ndpy,
+ enum pipe_format fmt, boolean is_color)
+{
+ return ndpy->screen->is_format_supported(ndpy->screen,
+ fmt, PIPE_TEXTURE_2D,
+ (is_color) ? PIPE_TEXTURE_USAGE_RENDER_TARGET :
+ PIPE_TEXTURE_USAGE_DEPTH_STENCIL, 0);
+}
+
+static const struct native_config **
+kms_display_get_configs(struct native_display *ndpy, int *num_configs)
+{
+ struct kms_display *kdpy = kms_display(ndpy);
+ const struct native_config **configs;
+
+ /* first time */
+ if (!kdpy->config) {
+ struct native_config *nconf;
+ enum pipe_format format;
+
+ kdpy->config = calloc(1, sizeof(*kdpy->config));
+ if (!kdpy->config)
+ return NULL;
+
+ nconf = &kdpy->config->base;
+
+ /* always double-buffered */
+ nconf->mode.doubleBufferMode = TRUE;
+
+ format = PIPE_FORMAT_A8R8G8B8_UNORM;
+ if (!kms_display_is_format_supported(&kdpy->base, format, TRUE)) {
+ format = PIPE_FORMAT_B8G8R8A8_UNORM;
+ if (!kms_display_is_format_supported(&kdpy->base, format, TRUE))
+ format = PIPE_FORMAT_NONE;
+ }
+ if (format == PIPE_FORMAT_NONE)
+ return NULL;
+
+ nconf->color_format = format;
+ nconf->mode.redBits = 8;
+ nconf->mode.greenBits = 8;
+ nconf->mode.blueBits = 8;
+ nconf->mode.alphaBits = 8;
+ nconf->mode.rgbBits = 32;
+
+ format = PIPE_FORMAT_S8Z24_UNORM;
+ if (!kms_display_is_format_supported(&kdpy->base, format, FALSE)) {
+ format = PIPE_FORMAT_Z24S8_UNORM;
+ if (!kms_display_is_format_supported(&kdpy->base, format, FALSE))
+ format = PIPE_FORMAT_NONE;
+ }
+ if (format != PIPE_FORMAT_NONE) {
+ nconf->depth_format = format;
+ nconf->stencil_format = format;
+
+ nconf->mode.depthBits = 24;
+ nconf->mode.stencilBits = 8;
+ nconf->mode.haveDepthBuffer = TRUE;
+ nconf->mode.haveStencilBuffer = TRUE;
+ }
+
+ nconf->scanout_bit = TRUE;
+ nconf->mode.drawableType = GLX_PBUFFER_BIT;
+ nconf->mode.swapMethod = GLX_SWAP_EXCHANGE_OML;
+
+ nconf->mode.visualID = 0;
+ nconf->mode.visualType = EGL_NONE;
+
+ nconf->mode.renderType = GLX_RGBA_BIT;
+ nconf->mode.rgbMode = TRUE;
+ nconf->mode.xRenderable = FALSE;
+ }
+
+ configs = malloc(sizeof(*configs));
+ if (configs) {
+ configs[0] = &kdpy->config->base;
+ if (num_configs)
+ *num_configs = 1;
+ }
+
+ return configs;
+}
+
+static void
+kms_display_destroy(struct native_display *ndpy)
+{
+ struct kms_display *kdpy = kms_display(ndpy);
+ int i;
+
+ if (kdpy->config)
+ free(kdpy->config);
+
+ if (kdpy->connectors) {
+ for (i = 0; i < kdpy->num_connectors; i++) {
+ struct kms_connector *kconn = &kdpy->connectors[i];
+ if (kconn->connector) {
+ drmModeFreeConnector(kconn->connector);
+ free(kconn->kms_modes);
+ }
+ }
+ free(kdpy->connectors);
+ }
+
+ if (kdpy->shown_surfaces)
+ free(kdpy->shown_surfaces);
+
+ if (kdpy->saved_crtcs) {
+ for (i = 0; i < kdpy->resources->count_crtcs; i++) {
+ struct kms_crtc *kcrtc = &kdpy->saved_crtcs[i];
+
+ if (kcrtc->crtc) {
+ /* restore crtc */
+ drmModeSetCrtc(kdpy->fd, kcrtc->crtc->crtc_id,
+ kcrtc->crtc->buffer_id, kcrtc->crtc->x, kcrtc->crtc->y,
+ kcrtc->connectors, kcrtc->num_connectors,
+ &kcrtc->crtc->mode);
+
+ drmModeFreeCrtc(kcrtc->crtc);
+ }
+ }
+ free(kdpy->saved_crtcs);
+ }
+
+ if (kdpy->resources)
+ drmModeFreeResources(kdpy->resources);
+
+ if (kdpy->base.screen)
+ kdpy->base.screen->destroy(kdpy->base.screen);
+
+ if (kdpy->fd >= 0)
+ drmClose(kdpy->fd);
+
+ if (kdpy->api)
+ kdpy->api->destroy(kdpy->api);
+ free(kdpy);
+}
+
+/**
+ * Initialize KMS and pipe screen.
+ */
+static boolean
+kms_display_init_screen(struct native_display *ndpy)
+{
+ struct kms_display *kdpy = kms_display(ndpy);
+ struct drm_create_screen_arg arg;
+ int fd;
+
+ fd = drmOpen(kdpy->api->name, NULL);
+ if (fd < 0) {
+ _eglLog(_EGL_WARNING, "failed to open DRM device");
+ return FALSE;
+ }
+
+#if 0
+ if (drmSetMaster(fd)) {
+ _eglLog(_EGL_WARNING, "failed to become DRM master");
+ return FALSE;
+ }
+#endif
+
+ memset(&arg, 0, sizeof(arg));
+ arg.mode = DRM_CREATE_NORMAL;
+ kdpy->base.screen = kdpy->api->create_screen(kdpy->api, fd, &arg);
+ if (!kdpy->base.screen) {
+ _eglLog(_EGL_WARNING, "failed to create DRM screen");
+ drmClose(fd);
+ return FALSE;
+ }
+
+ kdpy->fd = fd;
+
+ return TRUE;
+}
+
+static struct native_display_modeset kms_display_modeset = {
+ .get_connectors = kms_display_get_connectors,
+ .get_modes = kms_display_get_modes,
+ .create_scanout_surface = kms_display_create_scanout_surface,
+ .program = kms_display_program
+};
+
+static struct native_display *
+kms_create_display(EGLNativeDisplayType dpy, struct drm_api *api)
+{
+ struct kms_display *kdpy;
+
+ kdpy = CALLOC_STRUCT(kms_display);
+ if (!kdpy)
+ return NULL;
+
+ kdpy->api = api;
+ if (!kdpy->api) {
+ _eglLog(_EGL_WARNING, "failed to create DRM API");
+ free(kdpy);
+ return NULL;
+ }
+
+ kdpy->fd = -1;
+ if (!kms_display_init_screen(&kdpy->base)) {
+ kms_display_destroy(&kdpy->base);
+ return NULL;
+ }
+
+ /* resources are fixed, unlike crtc, connector, or encoder */
+ kdpy->resources = drmModeGetResources(kdpy->fd);
+ if (!kdpy->resources) {
+ kms_display_destroy(&kdpy->base);
+ return NULL;
+ }
+
+ kdpy->saved_crtcs =
+ calloc(kdpy->resources->count_crtcs, sizeof(*kdpy->saved_crtcs));
+ if (!kdpy->saved_crtcs) {
+ kms_display_destroy(&kdpy->base);
+ return NULL;
+ }
+
+ kdpy->shown_surfaces =
+ calloc(kdpy->resources->count_crtcs, sizeof(*kdpy->shown_surfaces));
+ if (!kdpy->shown_surfaces) {
+ kms_display_destroy(&kdpy->base);
+ return NULL;
+ }
+
+ kdpy->base.destroy = kms_display_destroy;
+ kdpy->base.get_configs = kms_display_get_configs;
+ kdpy->base.create_context = kms_display_create_context;
+ kdpy->base.create_pbuffer_surface = kms_display_create_pbuffer_surface;
+
+ kdpy->base.modeset = &kms_display_modeset;
+
+ return &kdpy->base;
+}
+
+struct native_probe *
+native_create_probe(EGLNativeDisplayType dpy)
+{
+ return NULL;
+}
+
+enum native_probe_result
+native_get_probe_result(struct native_probe *nprobe)
+{
+ return NATIVE_PROBE_UNKNOWN;
+}
+
+/* the api is destroyed with the native display */
+static struct drm_api *drm_api;
+
+const char *
+native_get_name(void)
+{
+ static char kms_name[32];
+
+ if (!drm_api)
+ drm_api = drm_api_create();
+
+ if (drm_api)
+ snprintf(kms_name, sizeof(kms_name), "KMS/%s", drm_api->name);
+ else
+ snprintf(kms_name, sizeof(kms_name), "KMS");
+
+ return kms_name;
+}
+
+struct native_display *
+native_create_display(EGLNativeDisplayType dpy)
+{
+ struct native_display *ndpy = NULL;
+
+ if (!drm_api)
+ drm_api = drm_api_create();
+
+ if (drm_api)
+ ndpy = kms_create_display(dpy, drm_api);
+
+ return ndpy;
+}
--- /dev/null
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.8
+ *
+ * Copyright (C) 2010 Chia-I Wu <olv@0xlab.org>
+ *
+ * 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
+ * BRIAN PAUL 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.
+ */
+
+#ifndef _NATIVE_KMS_H_
+#define _NATIVE_KMS_H_
+
+#include <xf86drm.h>
+#include <xf86drmMode.h>
+
+#include "pipe/p_compiler.h"
+#include "util/u_format.h"
+#include "pipe/p_state.h"
+#include "state_tracker/drm_api.h"
+
+#include "common/native.h"
+
+enum kms_surface_type {
+ KMS_SURFACE_TYPE_PBUFFER,
+ KMS_SURFACE_TYPE_SCANOUT
+};
+
+struct kms_config;
+struct kms_connector;
+struct kms_mode;
+
+struct kms_crtc {
+ drmModeCrtcPtr crtc;
+ uint32_t connectors[32];
+ int num_connectors;
+};
+
+struct kms_display {
+ struct native_display base;
+
+ int fd;
+ struct drm_api *api;
+ drmModeResPtr resources;
+ struct kms_config *config;
+
+ struct kms_connector *connectors;
+ int num_connectors;
+
+ struct kms_surface **shown_surfaces;
+ /* save the original settings of the CRTCs */
+ struct kms_crtc *saved_crtcs;
+};
+
+struct kms_framebuffer {
+ struct pipe_texture *texture;
+ boolean is_passive;
+
+ uint32_t buffer_id;
+};
+
+struct kms_surface {
+ struct native_surface base;
+ enum kms_surface_type type;
+ enum pipe_format color_format;
+ struct kms_display *kdpy;
+ int width, height;
+
+ struct pipe_texture *textures[NUM_NATIVE_ATTACHMENTS];
+ unsigned int sequence_number;
+ struct kms_framebuffer front_fb, back_fb;
+
+ boolean is_shown;
+ struct kms_crtc current_crtc;
+};
+
+struct kms_config {
+ struct native_config base;
+};
+
+struct kms_connector {
+ struct native_connector base;
+
+ uint32_t connector_id;
+ drmModeConnectorPtr connector;
+ struct kms_mode *kms_modes;
+ int num_modes;
+};
+
+struct kms_mode {
+ struct native_mode base;
+ drmModeModeInfo mode;
+};
+
+static INLINE struct kms_display *
+kms_display(const struct native_display *ndpy)
+{
+ return (struct kms_display *) ndpy;
+}
+
+static INLINE struct kms_surface *
+kms_surface(const struct native_surface *nsurf)
+{
+ return (struct kms_surface *) nsurf;
+}
+
+static INLINE struct kms_config *
+kms_config(const struct native_config *nconf)
+{
+ return (struct kms_config *) nconf;
+}
+
+static INLINE struct kms_connector *
+kms_connector(const struct native_connector *nconn)
+{
+ return (struct kms_connector *) nconn;
+}
+
+static INLINE struct kms_mode *
+kms_mode(const struct native_mode *nmode)
+{
+ return (struct kms_mode *) nmode;
+}
+
+#endif /* _NATIVE_KMS_H_ */
--- /dev/null
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.8
+ *
+ * Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org>
+ *
+ * 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
+ * BRIAN PAUL 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.
+ */
+
+#include "util/u_memory.h"
+#include "util/u_math.h"
+#include "util/u_format.h"
+#include "pipe/p_compiler.h"
+#include "pipe/p_screen.h"
+#include "pipe/p_context.h"
+#include "pipe/p_state.h"
+#include "state_tracker/drm_api.h"
+#include "egllog.h"
+
+#include "native_x11.h"
+#include "x11_screen.h"
+
+enum dri2_surface_type {
+ DRI2_SURFACE_TYPE_WINDOW,
+ DRI2_SURFACE_TYPE_PIXMAP,
+ DRI2_SURFACE_TYPE_PBUFFER
+};
+
+struct dri2_display {
+ struct native_display base;
+ Display *dpy;
+ boolean own_dpy;
+
+ struct drm_api *api;
+ struct x11_screen *xscr;
+ int xscr_number;
+
+ struct dri2_config *configs;
+ int num_configs;
+};
+
+struct dri2_surface {
+ struct native_surface base;
+ Drawable drawable;
+ enum dri2_surface_type type;
+ enum pipe_format color_format;
+ struct dri2_display *dri2dpy;
+
+ struct pipe_texture *pbuffer_textures[NUM_NATIVE_ATTACHMENTS];
+ boolean have_back, have_fake;
+ int width, height;
+ unsigned int sequence_number;
+};
+
+struct dri2_config {
+ struct native_config base;
+};
+
+static INLINE struct dri2_display *
+dri2_display(const struct native_display *ndpy)
+{
+ return (struct dri2_display *) ndpy;
+}
+
+static INLINE struct dri2_surface *
+dri2_surface(const struct native_surface *nsurf)
+{
+ return (struct dri2_surface *) nsurf;
+}
+
+static INLINE struct dri2_config *
+dri2_config(const struct native_config *nconf)
+{
+ return (struct dri2_config *) nconf;
+}
+
+static boolean
+dri2_surface_flush_frontbuffer(struct native_surface *nsurf)
+{
+ struct dri2_surface *dri2surf = dri2_surface(nsurf);
+ struct dri2_display *dri2dpy = dri2surf->dri2dpy;
+
+ /* pbuffer is private */
+ if (dri2surf->type == DRI2_SURFACE_TYPE_PBUFFER)
+ return TRUE;
+
+ /* copy to real front buffer */
+ if (dri2surf->have_fake)
+ x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable,
+ 0, 0, dri2surf->width, dri2surf->height,
+ DRI2BufferFakeFrontLeft, DRI2BufferFrontLeft);
+
+ return TRUE;
+}
+
+static boolean
+dri2_surface_swap_buffers(struct native_surface *nsurf)
+{
+ struct dri2_surface *dri2surf = dri2_surface(nsurf);
+ struct dri2_display *dri2dpy = dri2surf->dri2dpy;
+
+ /* pbuffer is private */
+ if (dri2surf->type == DRI2_SURFACE_TYPE_PBUFFER)
+ return TRUE;
+
+ /* copy to front buffer */
+ if (dri2surf->have_back)
+ x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable,
+ 0, 0, dri2surf->width, dri2surf->height,
+ DRI2BufferBackLeft, DRI2BufferFrontLeft);
+
+ /* and update fake front buffer */
+ if (dri2surf->have_fake)
+ x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable,
+ 0, 0, dri2surf->width, dri2surf->height,
+ DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft);
+
+ return TRUE;
+}
+
+static boolean
+dri2_surface_validate(struct native_surface *nsurf, uint attachment_mask,
+ unsigned int *seq_num, struct pipe_texture **textures,
+ int *width, int *height)
+{
+ struct dri2_surface *dri2surf = dri2_surface(nsurf);
+ struct dri2_display *dri2dpy = dri2surf->dri2dpy;
+ unsigned int dri2atts[NUM_NATIVE_ATTACHMENTS];
+ struct pipe_texture templ;
+ struct x11_drawable_buffer *xbufs;
+ int num_ins, num_outs, att, i;
+
+ if (attachment_mask) {
+ memset(&templ, 0, sizeof(templ));
+ templ.target = PIPE_TEXTURE_2D;
+ templ.last_level = 0;
+ templ.width0 = dri2surf->width;
+ templ.height0 = dri2surf->height;
+ templ.depth0 = 1;
+ templ.format = dri2surf->color_format;
+ templ.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET;
+
+ if (textures)
+ memset(textures, 0, sizeof(*textures) * NUM_NATIVE_ATTACHMENTS);
+ }
+
+ /* create textures for pbuffer */
+ if (dri2surf->type == DRI2_SURFACE_TYPE_PBUFFER) {
+ struct pipe_screen *screen = dri2dpy->base.screen;
+
+ for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) {
+ struct pipe_texture *ptex = dri2surf->pbuffer_textures[att];
+
+ /* delay the allocation */
+ if (!native_attachment_mask_test(attachment_mask, att))
+ continue;
+
+ if (!ptex) {
+ ptex = screen->texture_create(screen, &templ);
+ dri2surf->pbuffer_textures[att] = ptex;
+ }
+
+ if (textures)
+ pipe_texture_reference(&textures[att], ptex);
+ }
+
+ if (seq_num)
+ *seq_num = dri2surf->sequence_number;
+ if (width)
+ *width = dri2surf->width;
+ if (height)
+ *height = dri2surf->height;
+
+ return TRUE;
+ }
+
+ /* prepare the attachments */
+ num_ins = 0;
+ for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) {
+ if (native_attachment_mask_test(attachment_mask, att)) {
+ unsigned int dri2att;
+
+ switch (att) {
+ case NATIVE_ATTACHMENT_FRONT_LEFT:
+ dri2att = DRI2BufferFrontLeft;
+ break;
+ case NATIVE_ATTACHMENT_BACK_LEFT:
+ dri2att = DRI2BufferBackLeft;
+ break;
+ case NATIVE_ATTACHMENT_FRONT_RIGHT:
+ dri2att = DRI2BufferFrontRight;
+ break;
+ case NATIVE_ATTACHMENT_BACK_RIGHT:
+ dri2att = DRI2BufferBackRight;
+ break;
+ default:
+ assert(0);
+ dri2att = 0;
+ break;
+ }
+
+ dri2atts[num_ins] = dri2att;
+ num_ins++;
+ }
+ }
+
+ dri2surf->have_back = FALSE;
+ dri2surf->have_fake = FALSE;
+
+ /* remember old geometry */
+ templ.width0 = dri2surf->width;
+ templ.height0 = dri2surf->height;
+
+ xbufs = x11_drawable_get_buffers(dri2dpy->xscr, dri2surf->drawable,
+ &dri2surf->width, &dri2surf->height,
+ dri2atts, FALSE, num_ins, &num_outs);
+ if (!xbufs)
+ return FALSE;
+
+ if (templ.width0 != dri2surf->width || templ.height0 != dri2surf->height) {
+ /* are there cases where the buffers change and the geometry doesn't? */
+ dri2surf->sequence_number++;
+
+ templ.width0 = dri2surf->width;
+ templ.height0 = dri2surf->height;
+ }
+
+ for (i = 0; i < num_outs; i++) {
+ struct x11_drawable_buffer *xbuf = &xbufs[i];
+ const char *desc;
+ enum native_attachment natt;
+
+ switch (xbuf->attachment) {
+ case DRI2BufferFrontLeft:
+ natt = NATIVE_ATTACHMENT_FRONT_LEFT;
+ desc = "DRI2 Front Buffer";
+ break;
+ case DRI2BufferFakeFrontLeft:
+ natt = NATIVE_ATTACHMENT_FRONT_LEFT;
+ desc = "DRI2 Fake Front Buffer";
+ dri2surf->have_fake = TRUE;
+ break;
+ case DRI2BufferBackLeft:
+ natt = NATIVE_ATTACHMENT_BACK_LEFT;
+ desc = "DRI2 Back Buffer";
+ dri2surf->have_back = TRUE;
+ break;
+ default:
+ desc = NULL;
+ break;
+ }
+
+ if (!desc || !native_attachment_mask_test(attachment_mask, natt) ||
+ (textures && textures[natt])) {
+ if (!desc)
+ _eglLog(_EGL_WARNING, "unknown buffer %d", xbuf->attachment);
+ else if (!native_attachment_mask_test(attachment_mask, natt))
+ _eglLog(_EGL_WARNING, "unexpected buffer %d", xbuf->attachment);
+ else
+ _eglLog(_EGL_WARNING, "both real and fake front buffers are listed");
+ continue;
+ }
+
+ if (textures) {
+ struct pipe_texture *ptex =
+ dri2dpy->api->texture_from_shared_handle(dri2dpy->api,
+ dri2dpy->base.screen, &templ,
+ desc, xbuf->pitch, xbuf->name);
+ if (ptex) {
+ /* the caller owns the textures */
+ textures[natt] = ptex;
+ }
+ }
+ }
+
+ free(xbufs);
+
+ if (seq_num)
+ *seq_num = dri2surf->sequence_number;
+ if (width)
+ *width = dri2surf->width;
+ if (height)
+ *height = dri2surf->height;
+
+ return TRUE;
+}
+
+static void
+dri2_surface_wait(struct native_surface *nsurf)
+{
+ struct dri2_surface *dri2surf = dri2_surface(nsurf);
+ struct dri2_display *dri2dpy = dri2surf->dri2dpy;
+
+ if (dri2surf->have_fake) {
+ x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable,
+ 0, 0, dri2surf->width, dri2surf->height,
+ DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft);
+ }
+}
+
+static void
+dri2_surface_destroy(struct native_surface *nsurf)
+{
+ struct dri2_surface *dri2surf = dri2_surface(nsurf);
+ int i;
+
+ for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) {
+ struct pipe_texture *ptex = dri2surf->pbuffer_textures[i];
+ pipe_texture_reference(&ptex, NULL);
+ }
+
+ if (dri2surf->drawable)
+ x11_drawable_enable_dri2(dri2surf->dri2dpy->xscr,
+ dri2surf->drawable, FALSE);
+ free(dri2surf);
+}
+
+static struct dri2_surface *
+dri2_display_create_surface(struct native_display *ndpy,
+ enum dri2_surface_type type,
+ Drawable drawable,
+ const struct native_config *nconf)
+{
+ struct dri2_display *dri2dpy = dri2_display(ndpy);
+ struct dri2_config *dri2conf = dri2_config(nconf);
+ struct dri2_surface *dri2surf;
+
+ dri2surf = CALLOC_STRUCT(dri2_surface);
+ if (!dri2surf)
+ return NULL;
+
+ if (drawable)
+ x11_drawable_enable_dri2(dri2dpy->xscr, drawable, TRUE);
+
+ dri2surf->dri2dpy = dri2dpy;
+ dri2surf->type = type;
+ dri2surf->drawable = drawable;
+ dri2surf->color_format = dri2conf->base.color_format;
+
+ dri2surf->base.destroy = dri2_surface_destroy;
+ dri2surf->base.swap_buffers = dri2_surface_swap_buffers;
+ dri2surf->base.flush_frontbuffer = dri2_surface_flush_frontbuffer;
+ dri2surf->base.validate = dri2_surface_validate;
+ dri2surf->base.wait = dri2_surface_wait;
+
+ return dri2surf;
+}
+
+static struct native_surface *
+dri2_display_create_window_surface(struct native_display *ndpy,
+ EGLNativeWindowType win,
+ const struct native_config *nconf)
+{
+ struct dri2_surface *dri2surf;
+
+ dri2surf = dri2_display_create_surface(ndpy, DRI2_SURFACE_TYPE_WINDOW,
+ (Drawable) win, nconf);
+ return (dri2surf) ? &dri2surf->base : NULL;
+}
+
+static struct native_surface *
+dri2_display_create_pixmap_surface(struct native_display *ndpy,
+ EGLNativePixmapType pix,
+ const struct native_config *nconf)
+{
+ struct dri2_surface *dri2surf;
+
+ dri2surf = dri2_display_create_surface(ndpy, DRI2_SURFACE_TYPE_PIXMAP,
+ (Drawable) pix, nconf);
+ return (dri2surf) ? &dri2surf->base : NULL;
+}
+
+static struct native_surface *
+dri2_display_create_pbuffer_surface(struct native_display *ndpy,
+ const struct native_config *nconf,
+ uint width, uint height)
+{
+ struct dri2_surface *dri2surf;
+
+ dri2surf = dri2_display_create_surface(ndpy, DRI2_SURFACE_TYPE_PBUFFER,
+ (Drawable) None, nconf);
+ if (dri2surf) {
+ dri2surf->width = width;
+ dri2surf->height = height;
+ }
+ return (dri2surf) ? &dri2surf->base : NULL;
+}
+
+static struct pipe_context *
+dri2_display_create_context(struct native_display *ndpy, void *context_private)
+{
+ struct dri2_display *dri2dpy = dri2_display(ndpy);
+ struct pipe_context *pctx;
+
+ pctx = dri2dpy->api->create_context(dri2dpy->api, dri2dpy->base.screen);
+ if (pctx)
+ pctx->priv = context_private;
+ return pctx;
+}
+
+static int
+choose_color_format(const __GLcontextModes *mode, enum pipe_format formats[32])
+{
+ int count = 0;
+
+ switch (mode->rgbBits) {
+ case 32:
+ formats[count++] = PIPE_FORMAT_A8R8G8B8_UNORM;
+ formats[count++] = PIPE_FORMAT_B8G8R8A8_UNORM;
+ break;
+ case 24:
+ formats[count++] = PIPE_FORMAT_X8R8G8B8_UNORM;
+ formats[count++] = PIPE_FORMAT_B8G8R8X8_UNORM;
+ formats[count++] = PIPE_FORMAT_A8R8G8B8_UNORM;
+ formats[count++] = PIPE_FORMAT_B8G8R8A8_UNORM;
+ break;
+ case 16:
+ formats[count++] = PIPE_FORMAT_R5G6B5_UNORM;
+ break;
+ default:
+ break;
+ }
+
+ return count;
+}
+
+static int
+choose_depth_stencil_format(const __GLcontextModes *mode,
+ enum pipe_format formats[32])
+{
+ int count = 0;
+
+ switch (mode->depthBits) {
+ case 32:
+ formats[count++] = PIPE_FORMAT_Z32_UNORM;
+ break;
+ case 24:
+ if (mode->stencilBits) {
+ formats[count++] = PIPE_FORMAT_S8Z24_UNORM;
+ formats[count++] = PIPE_FORMAT_Z24S8_UNORM;
+ }
+ else {
+ formats[count++] = PIPE_FORMAT_X8Z24_UNORM;
+ formats[count++] = PIPE_FORMAT_Z24X8_UNORM;
+ }
+ break;
+ case 16:
+ formats[count++] = PIPE_FORMAT_Z16_UNORM;
+ break;
+ default:
+ break;
+ }
+
+ return count;
+}
+
+static boolean
+is_format_supported(struct pipe_screen *screen,
+ enum pipe_format fmt, boolean is_color)
+{
+ return screen->is_format_supported(screen, fmt, PIPE_TEXTURE_2D,
+ (is_color) ? PIPE_TEXTURE_USAGE_RENDER_TARGET :
+ PIPE_TEXTURE_USAGE_DEPTH_STENCIL, 0);
+}
+
+static boolean
+dri2_display_convert_config(struct native_display *ndpy,
+ const __GLcontextModes *mode,
+ struct native_config *nconf)
+{
+ enum pipe_format formats[32];
+ int num_formats, i;
+
+ if (!(mode->renderType & GLX_RGBA_BIT) || !mode->rgbMode)
+ return FALSE;
+
+ /* skip single-buffered configs */
+ if (!mode->doubleBufferMode)
+ return FALSE;
+
+ nconf->mode = *mode;
+ nconf->mode.renderType = GLX_RGBA_BIT;
+ nconf->mode.rgbMode = TRUE;
+ /* pbuffer is allocated locally and is always supported */
+ nconf->mode.drawableType |= GLX_PBUFFER_BIT;
+ /* the swap method is always copy */
+ nconf->mode.swapMethod = GLX_SWAP_COPY_OML;
+
+ /* fix up */
+ nconf->mode.rgbBits =
+ nconf->mode.redBits + nconf->mode.greenBits +
+ nconf->mode.blueBits + nconf->mode.alphaBits;
+ if (!(nconf->mode.drawableType & GLX_WINDOW_BIT)) {
+ nconf->mode.visualID = 0;
+ nconf->mode.visualType = GLX_NONE;
+ }
+ if (!(nconf->mode.drawableType & GLX_PBUFFER_BIT)) {
+ nconf->mode.bindToTextureRgb = FALSE;
+ nconf->mode.bindToTextureRgba = FALSE;
+ }
+
+ nconf->color_format = PIPE_FORMAT_NONE;
+ nconf->depth_format = PIPE_FORMAT_NONE;
+ nconf->stencil_format = PIPE_FORMAT_NONE;
+
+ /* choose color format */
+ num_formats = choose_color_format(mode, formats);
+ for (i = 0; i < num_formats; i++) {
+ if (is_format_supported(ndpy->screen, formats[i], TRUE)) {
+ nconf->color_format = formats[i];
+ break;
+ }
+ }
+ if (nconf->color_format == PIPE_FORMAT_NONE)
+ return FALSE;
+
+ /* choose depth/stencil format */
+ num_formats = choose_depth_stencil_format(mode, formats);
+ for (i = 0; i < num_formats; i++) {
+ if (is_format_supported(ndpy->screen, formats[i], FALSE)) {
+ nconf->depth_format = formats[i];
+ nconf->stencil_format = formats[i];
+ break;
+ }
+ }
+ if ((nconf->mode.depthBits && nconf->depth_format == PIPE_FORMAT_NONE) ||
+ (nconf->mode.stencilBits && nconf->stencil_format == PIPE_FORMAT_NONE))
+ return FALSE;
+
+ return TRUE;
+}
+
+static const struct native_config **
+dri2_display_get_configs(struct native_display *ndpy, int *num_configs)
+{
+ struct dri2_display *dri2dpy = dri2_display(ndpy);
+ const struct native_config **configs;
+ int i;
+
+ /* first time */
+ if (!dri2dpy->configs) {
+ const __GLcontextModes *modes;
+ int num_modes, count;
+
+ modes = x11_screen_get_glx_configs(dri2dpy->xscr);
+ if (!modes)
+ return NULL;
+ num_modes = x11_context_modes_count(modes);
+
+ dri2dpy->configs = calloc(num_modes, sizeof(*dri2dpy->configs));
+ if (!dri2dpy->configs)
+ return NULL;
+
+ count = 0;
+ for (i = 0; i < num_modes; i++) {
+ struct native_config *nconf = &dri2dpy->configs[count].base;
+ if (dri2_display_convert_config(&dri2dpy->base, modes, nconf))
+ count++;
+ modes = modes->next;
+ }
+
+ dri2dpy->num_configs = count;
+ }
+
+ configs = malloc(dri2dpy->num_configs * sizeof(*configs));
+ if (configs) {
+ for (i = 0; i < dri2dpy->num_configs; i++)
+ configs[i] = (const struct native_config *) &dri2dpy->configs[i];
+ if (num_configs)
+ *num_configs = dri2dpy->num_configs;
+ }
+
+ return configs;
+}
+
+static boolean
+dri2_display_is_pixmap_supported(struct native_display *ndpy,
+ EGLNativePixmapType pix,
+ const struct native_config *nconf)
+{
+ struct dri2_display *dri2dpy = dri2_display(ndpy);
+ uint depth, nconf_depth;
+
+ depth = x11_drawable_get_depth(dri2dpy->xscr, (Drawable) pix);
+ nconf_depth = util_format_get_blocksizebits(nconf->color_format);
+
+ /* simple depth match for now */
+ return (depth == nconf_depth || (depth == 24 && depth + 8 == nconf_depth));
+}
+
+static void
+dri2_display_destroy(struct native_display *ndpy)
+{
+ struct dri2_display *dri2dpy = dri2_display(ndpy);
+
+ if (dri2dpy->configs)
+ free(dri2dpy->configs);
+
+ if (dri2dpy->base.screen)
+ dri2dpy->base.screen->destroy(dri2dpy->base.screen);
+
+ if (dri2dpy->xscr)
+ x11_screen_destroy(dri2dpy->xscr);
+ if (dri2dpy->own_dpy)
+ XCloseDisplay(dri2dpy->dpy);
+ if (dri2dpy->api && dri2dpy->api->destroy)
+ dri2dpy->api->destroy(dri2dpy->api);
+ free(dri2dpy);
+}
+
+/**
+ * Initialize DRI2 and pipe screen.
+ */
+static boolean
+dri2_display_init_screen(struct native_display *ndpy)
+{
+ struct dri2_display *dri2dpy = dri2_display(ndpy);
+ const char *driver = dri2dpy->api->name;
+ struct drm_create_screen_arg arg;
+ int fd;
+
+ if (!x11_screen_support(dri2dpy->xscr, X11_SCREEN_EXTENSION_DRI2) ||
+ !x11_screen_support(dri2dpy->xscr, X11_SCREEN_EXTENSION_GLX)) {
+ _eglLog(_EGL_WARNING, "GLX/DRI2 is not supported");
+ return FALSE;
+ }
+
+ fd = x11_screen_enable_dri2(dri2dpy->xscr, driver);
+ if (fd < 0)
+ return FALSE;
+
+ memset(&arg, 0, sizeof(arg));
+ arg.mode = DRM_CREATE_NORMAL;
+ dri2dpy->base.screen = dri2dpy->api->create_screen(dri2dpy->api, fd, &arg);
+ if (!dri2dpy->base.screen) {
+ _eglLog(_EGL_WARNING, "failed to create DRM screen");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+struct native_display *
+x11_create_dri2_display(EGLNativeDisplayType dpy, struct drm_api *api)
+{
+ struct dri2_display *dri2dpy;
+
+ dri2dpy = CALLOC_STRUCT(dri2_display);
+ if (!dri2dpy)
+ return NULL;
+
+ dri2dpy->api = api;
+ if (!dri2dpy->api) {
+ _eglLog(_EGL_WARNING, "failed to create DRM API");
+ free(dri2dpy);
+ return NULL;
+ }
+
+ dri2dpy->dpy = dpy;
+ if (!dri2dpy->dpy) {
+ dri2dpy->dpy = XOpenDisplay(NULL);
+ if (!dri2dpy->dpy) {
+ dri2_display_destroy(&dri2dpy->base);
+ return NULL;
+ }
+ dri2dpy->own_dpy = TRUE;
+ }
+
+ dri2dpy->xscr_number = DefaultScreen(dri2dpy->dpy);
+ dri2dpy->xscr = x11_screen_create(dri2dpy->dpy, dri2dpy->xscr_number);
+ if (!dri2dpy->xscr) {
+ dri2_display_destroy(&dri2dpy->base);
+ return NULL;
+ }
+
+ if (!dri2_display_init_screen(&dri2dpy->base)) {
+ dri2_display_destroy(&dri2dpy->base);
+ return NULL;
+ }
+
+ dri2dpy->base.destroy = dri2_display_destroy;
+ dri2dpy->base.get_configs = dri2_display_get_configs;
+ dri2dpy->base.is_pixmap_supported = dri2_display_is_pixmap_supported;
+ dri2dpy->base.create_context = dri2_display_create_context;
+ dri2dpy->base.create_window_surface = dri2_display_create_window_surface;
+ dri2dpy->base.create_pixmap_surface = dri2_display_create_pixmap_surface;
+ dri2dpy->base.create_pbuffer_surface = dri2_display_create_pbuffer_surface;
+
+ return &dri2dpy->base;
+}
--- /dev/null
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.8
+ *
+ * Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org>
+ *
+ * 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
+ * BRIAN PAUL 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.
+ */
+
+#include <string.h>
+#include "util/u_debug.h"
+#include "util/u_memory.h"
+#include "state_tracker/drm_api.h"
+#include "egllog.h"
+
+#include "native_x11.h"
+#include "x11_screen.h"
+
+#define X11_PROBE_MAGIC 0x11980BE /* "X11PROBE" */
+
+static struct drm_api *api;
+
+static void
+x11_probe_destroy(struct native_probe *nprobe)
+{
+ if (nprobe->data)
+ free(nprobe->data);
+ free(nprobe);
+}
+
+struct native_probe *
+native_create_probe(EGLNativeDisplayType dpy)
+{
+ struct native_probe *nprobe;
+ struct x11_screen *xscr;
+ int scr;
+ const char *driver_name = NULL;
+ Display *xdpy;
+
+ nprobe = CALLOC_STRUCT(native_probe);
+ if (!nprobe)
+ return NULL;
+
+ xdpy = dpy;
+ if (!xdpy) {
+ xdpy = XOpenDisplay(NULL);
+ if (!xdpy) {
+ free(nprobe);
+ return NULL;
+ }
+ }
+
+ scr = DefaultScreen(xdpy);
+ xscr = x11_screen_create(xdpy, scr);
+ if (xscr) {
+ if (x11_screen_support(xscr, X11_SCREEN_EXTENSION_DRI2)) {
+ driver_name = x11_screen_probe_dri2(xscr);
+ nprobe->data = strdup(driver_name);
+ }
+
+ x11_screen_destroy(xscr);
+ }
+
+ if (xdpy != dpy)
+ XCloseDisplay(xdpy);
+
+ nprobe->magic = X11_PROBE_MAGIC;
+ nprobe->display = dpy;
+
+ nprobe->destroy = x11_probe_destroy;
+
+ return nprobe;
+}
+
+enum native_probe_result
+native_get_probe_result(struct native_probe *nprobe)
+{
+ if (!nprobe || nprobe->magic != X11_PROBE_MAGIC)
+ return NATIVE_PROBE_UNKNOWN;
+
+ if (!api)
+ api = drm_api_create();
+
+ /* this is a software driver */
+ if (!api)
+ return NATIVE_PROBE_SUPPORTED;
+
+ /* the display does not support DRI2 or the driver mismatches */
+ if (!nprobe->data || strcmp(api->name, (const char *) nprobe->data) != 0)
+ return NATIVE_PROBE_FALLBACK;
+
+ return NATIVE_PROBE_EXACT;
+}
+
+const char *
+native_get_name(void)
+{
+ static char x11_name[32];
+
+ if (!api)
+ api = drm_api_create();
+
+ if (api)
+ snprintf(x11_name, sizeof(x11_name), "X11/%s", api->name);
+ else
+ snprintf(x11_name, sizeof(x11_name), "X11");
+
+ return x11_name;
+}
+
+struct native_display *
+native_create_display(EGLNativeDisplayType dpy)
+{
+ struct native_display *ndpy = NULL;
+ boolean force_sw;
+
+ if (!api)
+ api = drm_api_create();
+
+ force_sw = debug_get_bool_option("EGL_SOFTWARE", FALSE);
+ if (api && !force_sw) {
+ ndpy = x11_create_dri2_display(dpy, api);
+ }
+
+ if (!ndpy) {
+ EGLint level = (force_sw) ? _EGL_INFO : _EGL_WARNING;
+
+ _eglLog(level, "use software fallback");
+ ndpy = x11_create_ximage_display(dpy, TRUE);
+ }
+
+ return ndpy;
+}
--- /dev/null
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.8
+ *
+ * Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org>
+ *
+ * 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
+ * BRIAN PAUL 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.
+ */
+
+#ifndef _NATIVE_X11_H_
+#define _NATIVE_X11_H_
+
+#include "state_tracker/drm_api.h"
+#include "common/native.h"
+
+struct native_display *
+x11_create_ximage_display(EGLNativeDisplayType dpy, boolean use_xshm);
+
+struct native_display *
+x11_create_dri2_display(EGLNativeDisplayType dpy, struct drm_api *api);
+
+#endif /* _NATIVE_X11_H_ */
--- /dev/null
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.8
+ *
+ * Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org>
+ *
+ * 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
+ * BRIAN PAUL 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.
+ */
+
+#include <assert.h>
+#include <sys/ipc.h>
+#include <sys/types.h>
+#include <sys/shm.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/extensions/XShm.h>
+#include "util/u_memory.h"
+#include "util/u_math.h"
+#include "util/u_format.h"
+#include "pipe/p_compiler.h"
+#include "pipe/internal/p_winsys_screen.h"
+#include "softpipe/sp_winsys.h"
+#include "egllog.h"
+
+#include "sw_winsys.h"
+#include "native_x11.h"
+#include "x11_screen.h"
+
+enum ximage_surface_type {
+ XIMAGE_SURFACE_TYPE_WINDOW,
+ XIMAGE_SURFACE_TYPE_PIXMAP,
+ XIMAGE_SURFACE_TYPE_PBUFFER
+};
+
+struct ximage_display {
+ struct native_display base;
+ Display *dpy;
+ boolean own_dpy;
+
+ struct x11_screen *xscr;
+ int xscr_number;
+
+ boolean use_xshm;
+
+ struct pipe_winsys *winsys;
+ struct ximage_config *configs;
+ int num_configs;
+};
+
+struct ximage_buffer {
+ XImage *ximage;
+
+ struct pipe_texture *texture;
+ XShmSegmentInfo *shm_info;
+ boolean xshm_attached;
+};
+
+struct ximage_surface {
+ struct native_surface base;
+ Drawable drawable;
+ enum ximage_surface_type type;
+ enum pipe_format color_format;
+ XVisualInfo visual;
+ struct ximage_display *xdpy;
+
+ int width, height;
+ GC gc;
+
+ struct ximage_buffer buffers[NUM_NATIVE_ATTACHMENTS];
+ unsigned int sequence_number;
+};
+
+struct ximage_config {
+ struct native_config base;
+ const XVisualInfo *visual;
+};
+
+static INLINE struct ximage_display *
+ximage_display(const struct native_display *ndpy)
+{
+ return (struct ximage_display *) ndpy;
+}
+
+static INLINE struct ximage_surface *
+ximage_surface(const struct native_surface *nsurf)
+{
+ return (struct ximage_surface *) nsurf;
+}
+
+static INLINE struct ximage_config *
+ximage_config(const struct native_config *nconf)
+{
+ return (struct ximage_config *) nconf;
+}
+
+static void
+ximage_surface_free_buffer(struct native_surface *nsurf,
+ enum native_attachment which)
+{
+ struct ximage_surface *xsurf = ximage_surface(nsurf);
+ struct ximage_buffer *xbuf = &xsurf->buffers[which];
+
+ pipe_texture_reference(&xbuf->texture, NULL);
+
+ if (xbuf->shm_info) {
+ if (xbuf->xshm_attached)
+ XShmDetach(xsurf->xdpy->dpy, xbuf->shm_info);
+ if (xbuf->shm_info->shmaddr != (void *) -1)
+ shmdt(xbuf->shm_info->shmaddr);
+ if (xbuf->shm_info->shmid != -1)
+ shmctl(xbuf->shm_info->shmid, IPC_RMID, 0);
+
+ xbuf->shm_info->shmaddr = (void *) -1;
+ xbuf->shm_info->shmid = -1;
+ }
+}
+
+static boolean
+ximage_surface_alloc_buffer(struct native_surface *nsurf,
+ enum native_attachment which)
+{
+ struct ximage_surface *xsurf = ximage_surface(nsurf);
+ struct ximage_buffer *xbuf = &xsurf->buffers[which];
+ struct pipe_screen *screen = xsurf->xdpy->base.screen;
+ struct pipe_texture templ;
+
+ /* free old data */
+ if (xbuf->texture)
+ ximage_surface_free_buffer(&xsurf->base, which);
+
+ memset(&templ, 0, sizeof(templ));
+ templ.target = PIPE_TEXTURE_2D;
+ templ.format = xsurf->color_format;
+ templ.width0 = xsurf->width;
+ templ.height0 = xsurf->height;
+ templ.depth0 = 1;
+ templ.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET;
+
+ if (xbuf->shm_info) {
+ struct pipe_buffer *pbuf;
+ unsigned stride, size;
+ void *addr = NULL;
+
+ stride = util_format_get_stride(xsurf->color_format, xsurf->width);
+ /* alignment should depend on visual? */
+ stride = align(stride, 4);
+ size = stride * xsurf->height;
+
+ /* create and attach shm object */
+ xbuf->shm_info->shmid = shmget(IPC_PRIVATE, size, 0755);
+ if (xbuf->shm_info->shmid != -1) {
+ xbuf->shm_info->shmaddr =
+ shmat(xbuf->shm_info->shmid, NULL, 0);
+ if (xbuf->shm_info->shmaddr != (void *) -1) {
+ if (XShmAttach(xsurf->xdpy->dpy, xbuf->shm_info)) {
+ addr = xbuf->shm_info->shmaddr;
+ xbuf->xshm_attached = TRUE;
+ }
+ }
+ }
+
+ if (addr) {
+ pbuf = screen->user_buffer_create(screen, addr, size);
+ if (pbuf) {
+ xbuf->texture =
+ screen->texture_blanket(screen, &templ, &stride, pbuf);
+ pipe_buffer_reference(&pbuf, NULL);
+ }
+ }
+ }
+ else {
+ xbuf->texture = screen->texture_create(screen, &templ);
+ }
+
+ /* clean up the buffer if allocation failed */
+ if (!xbuf->texture)
+ ximage_surface_free_buffer(&xsurf->base, which);
+
+ return (xbuf->texture != NULL);
+}
+
+static boolean
+ximage_surface_draw_buffer(struct native_surface *nsurf,
+ enum native_attachment which)
+{
+ struct ximage_surface *xsurf = ximage_surface(nsurf);
+ struct ximage_buffer *xbuf = &xsurf->buffers[which];
+ struct pipe_screen *screen = xsurf->xdpy->base.screen;
+ struct pipe_transfer *transfer;
+
+ if (xsurf->type == XIMAGE_SURFACE_TYPE_PBUFFER)
+ return TRUE;
+
+ assert(xsurf->drawable && xbuf->ximage && xbuf->texture);
+
+ transfer = screen->get_tex_transfer(screen, xbuf->texture,
+ 0, 0, 0, PIPE_TRANSFER_READ, 0, 0, xsurf->width, xsurf->height);
+ if (!transfer)
+ return FALSE;
+
+ xbuf->ximage->bytes_per_line = transfer->stride;
+ xbuf->ximage->data = screen->transfer_map(screen, transfer);
+ if (!xbuf->ximage->data) {
+ screen->tex_transfer_destroy(transfer);
+ return FALSE;
+ }
+
+
+ if (xbuf->shm_info)
+ XShmPutImage(xsurf->xdpy->dpy, xsurf->drawable, xsurf->gc,
+ xbuf->ximage, 0, 0, 0, 0, xsurf->width, xsurf->height, False);
+ else
+ XPutImage(xsurf->xdpy->dpy, xsurf->drawable, xsurf->gc,
+ xbuf->ximage, 0, 0, 0, 0, xsurf->width, xsurf->height);
+
+ xbuf->ximage->data = NULL;
+ screen->transfer_unmap(screen, transfer);
+
+ /*
+ * softpipe allows the pipe transfer to be re-used, but we don't want to
+ * rely on that behavior.
+ */
+ screen->tex_transfer_destroy(transfer);
+
+ XSync(xsurf->xdpy->dpy, FALSE);
+
+ return TRUE;
+}
+
+static boolean
+ximage_surface_flush_frontbuffer(struct native_surface *nsurf)
+{
+ return ximage_surface_draw_buffer(nsurf, NATIVE_ATTACHMENT_FRONT_LEFT);
+}
+
+static boolean
+ximage_surface_swap_buffers(struct native_surface *nsurf)
+{
+ struct ximage_surface *xsurf = ximage_surface(nsurf);
+ struct ximage_buffer *xfront, *xback, xtmp;
+
+ xfront = &xsurf->buffers[NATIVE_ATTACHMENT_FRONT_LEFT];
+ xback = &xsurf->buffers[NATIVE_ATTACHMENT_BACK_LEFT];
+
+ /* draw the back buffer directly if there is no front buffer */
+ if (!xfront->texture)
+ return ximage_surface_draw_buffer(nsurf, NATIVE_ATTACHMENT_BACK_LEFT);
+
+ /* swap the buffers */
+ xtmp = *xfront;
+ *xfront = *xback;
+ *xback = xtmp;
+
+ /* the front/back textures are swapped */
+ xsurf->sequence_number++;
+
+ return ximage_surface_draw_buffer(nsurf, NATIVE_ATTACHMENT_FRONT_LEFT);
+}
+
+static void
+ximage_surface_update_geometry(struct native_surface *nsurf)
+{
+ struct ximage_surface *xsurf = ximage_surface(nsurf);
+ Status ok;
+ Window root;
+ int x, y;
+ unsigned int w, h, border, depth;
+
+ /* pbuffer has fixed geometry */
+ if (xsurf->type == XIMAGE_SURFACE_TYPE_PBUFFER)
+ return;
+
+ ok = XGetGeometry(xsurf->xdpy->dpy, xsurf->drawable,
+ &root, &x, &y, &w, &h, &border, &depth);
+ if (ok) {
+ xsurf->width = w;
+ xsurf->height = h;
+ }
+}
+
+static boolean
+ximage_surface_validate(struct native_surface *nsurf, uint attachment_mask,
+ unsigned int *seq_num, struct pipe_texture **textures,
+ int *width, int *height)
+{
+ struct ximage_surface *xsurf = ximage_surface(nsurf);
+ boolean new_buffers = FALSE;
+ int att;
+
+ ximage_surface_update_geometry(&xsurf->base);
+
+ for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) {
+ struct ximage_buffer *xbuf = &xsurf->buffers[att];
+
+ /* delay the allocation */
+ if (!native_attachment_mask_test(attachment_mask, att))
+ continue;
+
+ /* reallocate the texture */
+ if (!xbuf->texture ||
+ xsurf->width != xbuf->texture->width0 ||
+ xsurf->height != xbuf->texture->height0) {
+ new_buffers = TRUE;
+ if (ximage_surface_alloc_buffer(&xsurf->base, att)) {
+ /* update ximage */
+ if (xbuf->ximage) {
+ xbuf->ximage->width = xsurf->width;
+ xbuf->ximage->height = xsurf->height;
+ }
+ }
+ }
+
+ if (textures) {
+ textures[att] = NULL;
+ pipe_texture_reference(&textures[att], xbuf->texture);
+ }
+ }
+
+ /* increase the sequence number so that caller knows */
+ if (new_buffers)
+ xsurf->sequence_number++;
+
+ if (seq_num)
+ *seq_num = xsurf->sequence_number;
+ if (width)
+ *width = xsurf->width;
+ if (height)
+ *height = xsurf->height;
+
+ return TRUE;
+}
+
+static void
+ximage_surface_wait(struct native_surface *nsurf)
+{
+ struct ximage_surface *xsurf = ximage_surface(nsurf);
+ XSync(xsurf->xdpy->dpy, FALSE);
+ /* TODO XGetImage and update the front texture */
+}
+
+static void
+ximage_surface_destroy(struct native_surface *nsurf)
+{
+ struct ximage_surface *xsurf = ximage_surface(nsurf);
+ int i;
+
+ for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) {
+ struct ximage_buffer *xbuf = &xsurf->buffers[i];
+ ximage_surface_free_buffer(&xsurf->base, i);
+ /* xbuf->shm_info is owned by xbuf->ximage? */
+ if (xbuf->ximage) {
+ XDestroyImage(xbuf->ximage);
+ xbuf->ximage = NULL;
+ }
+ }
+
+ if (xsurf->type != XIMAGE_SURFACE_TYPE_PBUFFER)
+ XFreeGC(xsurf->xdpy->dpy, xsurf->gc);
+ free(xsurf);
+}
+
+static struct ximage_surface *
+ximage_display_create_surface(struct native_display *ndpy,
+ enum ximage_surface_type type,
+ Drawable drawable,
+ const struct native_config *nconf)
+{
+ struct ximage_display *xdpy = ximage_display(ndpy);
+ struct ximage_config *xconf = ximage_config(nconf);
+ struct ximage_surface *xsurf;
+ int i;
+
+ xsurf = CALLOC_STRUCT(ximage_surface);
+ if (!xsurf)
+ return NULL;
+
+ xsurf->xdpy = xdpy;
+ xsurf->type = type;
+ xsurf->color_format = xconf->base.color_format;
+ xsurf->drawable = drawable;
+
+ if (xsurf->type != XIMAGE_SURFACE_TYPE_PBUFFER) {
+ xsurf->drawable = drawable;
+ xsurf->visual = *xconf->visual;
+
+ xsurf->gc = XCreateGC(xdpy->dpy, xsurf->drawable, 0, NULL);
+ if (!xsurf->gc) {
+ free(xsurf);
+ return NULL;
+ }
+
+ for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) {
+ struct ximage_buffer *xbuf = &xsurf->buffers[i];
+
+ if (xdpy->use_xshm) {
+ xbuf->shm_info = calloc(1, sizeof(*xbuf->shm_info));
+ if (xbuf->shm_info) {
+ /* initialize shm info */
+ xbuf->shm_info->shmid = -1;
+ xbuf->shm_info->shmaddr = (void *) -1;
+ xbuf->shm_info->readOnly = TRUE;
+
+ xbuf->ximage = XShmCreateImage(xsurf->xdpy->dpy,
+ xsurf->visual.visual,
+ xsurf->visual.depth,
+ ZPixmap, NULL,
+ xbuf->shm_info,
+ 0, 0);
+ }
+ }
+ else {
+ xbuf->ximage = XCreateImage(xsurf->xdpy->dpy,
+ xsurf->visual.visual,
+ xsurf->visual.depth,
+ ZPixmap, 0, /* format, offset */
+ NULL, /* data */
+ 0, 0, /* size */
+ 8, /* bitmap_pad */
+ 0); /* bytes_per_line */
+ }
+
+ if (!xbuf->ximage) {
+ XFreeGC(xdpy->dpy, xsurf->gc);
+ free(xsurf);
+ return NULL;
+ }
+ }
+ }
+
+ xsurf->base.destroy = ximage_surface_destroy;
+ xsurf->base.swap_buffers = ximage_surface_swap_buffers;
+ xsurf->base.flush_frontbuffer = ximage_surface_flush_frontbuffer;
+ xsurf->base.validate = ximage_surface_validate;
+ xsurf->base.wait = ximage_surface_wait;
+
+ return xsurf;
+}
+
+static struct native_surface *
+ximage_display_create_window_surface(struct native_display *ndpy,
+ EGLNativeWindowType win,
+ const struct native_config *nconf)
+{
+ struct ximage_surface *xsurf;
+
+ xsurf = ximage_display_create_surface(ndpy, XIMAGE_SURFACE_TYPE_WINDOW,
+ (Drawable) win, nconf);
+ return (xsurf) ? &xsurf->base : NULL;
+}
+
+static struct native_surface *
+ximage_display_create_pixmap_surface(struct native_display *ndpy,
+ EGLNativePixmapType pix,
+ const struct native_config *nconf)
+{
+ struct ximage_surface *xsurf;
+
+ xsurf = ximage_display_create_surface(ndpy, XIMAGE_SURFACE_TYPE_PIXMAP,
+ (Drawable) pix, nconf);
+ return (xsurf) ? &xsurf->base : NULL;
+}
+
+static struct native_surface *
+ximage_display_create_pbuffer_surface(struct native_display *ndpy,
+ const struct native_config *nconf,
+ uint width, uint height)
+{
+ struct ximage_surface *xsurf;
+
+ xsurf = ximage_display_create_surface(ndpy, XIMAGE_SURFACE_TYPE_PBUFFER,
+ (Drawable) None, nconf);
+ if (xsurf) {
+ xsurf->width = width;
+ xsurf->height = height;
+ }
+ return (xsurf) ? &xsurf->base : NULL;
+}
+
+static struct pipe_context *
+ximage_display_create_context(struct native_display *ndpy,
+ void *context_private)
+{
+ struct pipe_context *pctx = softpipe_create(ndpy->screen);
+ if (pctx)
+ pctx->priv = context_private;
+ return pctx;
+}
+
+static enum pipe_format
+choose_format(const XVisualInfo *vinfo)
+{
+ enum pipe_format fmt;
+ /* TODO elaborate the formats */
+ switch (vinfo->depth) {
+ case 32:
+ fmt = PIPE_FORMAT_A8R8G8B8_UNORM;
+ break;
+ case 24:
+ fmt = PIPE_FORMAT_X8R8G8B8_UNORM;
+ break;
+ case 16:
+ fmt = PIPE_FORMAT_R5G6B5_UNORM;
+ break;
+ default:
+ fmt = PIPE_FORMAT_NONE;
+ break;
+ }
+
+ return fmt;
+}
+
+static const struct native_config **
+ximage_display_get_configs(struct native_display *ndpy, int *num_configs)
+{
+ struct ximage_display *xdpy = ximage_display(ndpy);
+ const struct native_config **configs;
+ int i;
+
+ /* first time */
+ if (!xdpy->configs) {
+ const XVisualInfo *visuals;
+ int num_visuals, count, j;
+
+ visuals = x11_screen_get_visuals(xdpy->xscr, &num_visuals);
+ if (!visuals)
+ return NULL;
+
+ /*
+ * Create two configs for each visual.
+ * One with depth/stencil buffer; one without
+ */
+ xdpy->configs = calloc(num_visuals * 2, sizeof(*xdpy->configs));
+ if (!xdpy->configs)
+ return NULL;
+
+ count = 0;
+ for (i = 0; i < num_visuals; i++) {
+ for (j = 0; j < 2; j++) {
+ struct ximage_config *xconf = &xdpy->configs[count];
+ __GLcontextModes *mode = &xconf->base.mode;
+
+ xconf->visual = &visuals[i];
+ xconf->base.color_format = choose_format(xconf->visual);
+ if (xconf->base.color_format == PIPE_FORMAT_NONE)
+ continue;
+
+ x11_screen_convert_visual(xdpy->xscr, xconf->visual, mode);
+ /* support double buffer mode */
+ mode->doubleBufferMode = TRUE;
+
+ xconf->base.depth_format = PIPE_FORMAT_NONE;
+ xconf->base.stencil_format = PIPE_FORMAT_NONE;
+ /* create the second config with depth/stencil buffer */
+ if (j == 1) {
+ xconf->base.depth_format = PIPE_FORMAT_S8Z24_UNORM;
+ xconf->base.stencil_format = PIPE_FORMAT_S8Z24_UNORM;
+ mode->depthBits = 24;
+ mode->stencilBits = 8;
+ mode->haveDepthBuffer = TRUE;
+ mode->haveStencilBuffer = TRUE;
+ }
+
+ mode->maxPbufferWidth = 4096;
+ mode->maxPbufferHeight = 4096;
+ mode->maxPbufferPixels = 4096 * 4096;
+ mode->drawableType =
+ GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT;
+ mode->swapMethod = GLX_SWAP_EXCHANGE_OML;
+
+ if (mode->alphaBits)
+ mode->bindToTextureRgba = TRUE;
+ else
+ mode->bindToTextureRgb = TRUE;
+
+ count++;
+ }
+ }
+
+ xdpy->num_configs = count;
+ }
+
+ configs = malloc(xdpy->num_configs * sizeof(*configs));
+ if (configs) {
+ for (i = 0; i < xdpy->num_configs; i++)
+ configs[i] = (const struct native_config *) &xdpy->configs[i];
+ if (num_configs)
+ *num_configs = xdpy->num_configs;
+ }
+ return configs;
+}
+
+static boolean
+ximage_display_is_pixmap_supported(struct native_display *ndpy,
+ EGLNativePixmapType pix,
+ const struct native_config *nconf)
+{
+ struct ximage_display *xdpy = ximage_display(ndpy);
+ enum pipe_format fmt;
+ uint depth;
+
+ depth = x11_drawable_get_depth(xdpy->xscr, (Drawable) pix);
+ switch (depth) {
+ case 32:
+ fmt = PIPE_FORMAT_A8R8G8B8_UNORM;
+ break;
+ case 24:
+ fmt = PIPE_FORMAT_X8R8G8B8_UNORM;
+ break;
+ case 16:
+ fmt = PIPE_FORMAT_R5G6B5_UNORM;
+ break;
+ default:
+ fmt = PIPE_FORMAT_NONE;
+ break;
+ }
+
+ return (fmt == nconf->color_format);
+}
+
+static void
+ximage_display_destroy(struct native_display *ndpy)
+{
+ struct ximage_display *xdpy = ximage_display(ndpy);
+
+ if (xdpy->configs)
+ free(xdpy->configs);
+
+ xdpy->base.screen->destroy(xdpy->base.screen);
+ free(xdpy->winsys);
+
+ x11_screen_destroy(xdpy->xscr);
+ if (xdpy->own_dpy)
+ XCloseDisplay(xdpy->dpy);
+ free(xdpy);
+}
+
+struct native_display *
+x11_create_ximage_display(EGLNativeDisplayType dpy, boolean use_xshm)
+{
+ struct ximage_display *xdpy;
+
+ xdpy = CALLOC_STRUCT(ximage_display);
+ if (!xdpy)
+ return NULL;
+
+ xdpy->dpy = dpy;
+ if (!xdpy->dpy) {
+ xdpy->dpy = XOpenDisplay(NULL);
+ if (!xdpy->dpy) {
+ free(xdpy);
+ return NULL;
+ }
+ xdpy->own_dpy = TRUE;
+ }
+
+ xdpy->xscr_number = DefaultScreen(xdpy->dpy);
+ xdpy->xscr = x11_screen_create(xdpy->dpy, xdpy->xscr_number);
+ if (!xdpy->xscr) {
+ free(xdpy);
+ return NULL;
+ }
+
+ xdpy->use_xshm =
+ (use_xshm && x11_screen_support(xdpy->xscr, X11_SCREEN_EXTENSION_XSHM));
+
+ xdpy->winsys = create_sw_winsys();
+ xdpy->base.screen = softpipe_create_screen(xdpy->winsys);
+
+ xdpy->base.destroy = ximage_display_destroy;
+
+ xdpy->base.get_configs = ximage_display_get_configs;
+ xdpy->base.is_pixmap_supported = ximage_display_is_pixmap_supported;
+ xdpy->base.create_context = ximage_display_create_context;
+ xdpy->base.create_window_surface = ximage_display_create_window_surface;
+ xdpy->base.create_pixmap_surface = ximage_display_create_pixmap_surface;
+ xdpy->base.create_pbuffer_surface = ximage_display_create_pbuffer_surface;
+
+ return &xdpy->base;
+}
--- /dev/null
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * 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, sub license, 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 (including the
+ * next paragraph) 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 NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS 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.
+ *
+ **************************************************************************/
+
+/**
+ * Totally software-based winsys layer.
+ * Note that the one winsys function that we can't implement here
+ * is flush_frontbuffer().
+ * Whoever uses this code will have to provide that.
+ *
+ * Authors: Brian Paul
+ */
+
+
+#include "pipe/internal/p_winsys_screen.h"
+#include "pipe/p_state.h"
+#include "pipe/p_inlines.h"
+#include "util/u_format.h"
+#include "util/u_math.h"
+#include "util/u_memory.h"
+
+#include "sw_winsys.h"
+
+
+
+/** Subclass of pipe_winsys */
+struct sw_pipe_winsys
+{
+ struct pipe_winsys Base;
+ /* no extra fields for now */
+};
+
+
+/** subclass of pipe_buffer */
+struct sw_pipe_buffer
+{
+ struct pipe_buffer Base;
+ boolean UserBuffer; /** Is this a user-space buffer? */
+ void *Data;
+ void *Mapped;
+};
+
+
+/** cast wrapper */
+static INLINE struct sw_pipe_buffer *
+sw_pipe_buffer(struct pipe_buffer *b)
+{
+ return (struct sw_pipe_buffer *) b;
+}
+
+
+static const char *
+get_name(struct pipe_winsys *pws)
+{
+ return "software";
+}
+
+
+/** Create new pipe_buffer and allocate storage of given size */
+static struct pipe_buffer *
+buffer_create(struct pipe_winsys *pws,
+ unsigned alignment,
+ unsigned usage,
+ unsigned size)
+{
+ struct sw_pipe_buffer *buffer = CALLOC_STRUCT(sw_pipe_buffer);
+ if (!buffer)
+ return NULL;
+
+ pipe_reference_init(&buffer->Base.reference, 1);
+ buffer->Base.alignment = alignment;
+ buffer->Base.usage = usage;
+ buffer->Base.size = size;
+
+ /* align to 16-byte multiple for Cell */
+ buffer->Data = align_malloc(size, MAX2(alignment, 16));
+
+ return &buffer->Base;
+}
+
+
+/**
+ * Create buffer which wraps user-space data.
+ */
+static struct pipe_buffer *
+user_buffer_create(struct pipe_winsys *pws, void *ptr, unsigned bytes)
+{
+ struct sw_pipe_buffer *buffer = CALLOC_STRUCT(sw_pipe_buffer);
+ if (!buffer)
+ return NULL;
+
+ pipe_reference_init(&buffer->Base.reference, 1);
+ buffer->Base.size = bytes;
+ buffer->UserBuffer = TRUE;
+ buffer->Data = ptr;
+
+ return &buffer->Base;
+}
+
+
+static void *
+buffer_map(struct pipe_winsys *pws, struct pipe_buffer *buf, unsigned flags)
+{
+ struct sw_pipe_buffer *buffer = sw_pipe_buffer(buf);
+ buffer->Mapped = buffer->Data;
+ return buffer->Mapped;
+}
+
+
+static void
+buffer_unmap(struct pipe_winsys *pws, struct pipe_buffer *buf)
+{
+ struct sw_pipe_buffer *buffer = sw_pipe_buffer(buf);
+ buffer->Mapped = NULL;
+}
+
+
+static void
+buffer_destroy(struct pipe_buffer *buf)
+{
+ struct sw_pipe_buffer *buffer = sw_pipe_buffer(buf);
+
+ if (buffer->Data && !buffer->UserBuffer) {
+ align_free(buffer->Data);
+ buffer->Data = NULL;
+ }
+
+ free(buffer);
+}
+
+
+static struct pipe_buffer *
+surface_buffer_create(struct pipe_winsys *winsys,
+ unsigned width, unsigned height,
+ enum pipe_format format,
+ unsigned usage,
+ unsigned tex_usage,
+ unsigned *stride)
+{
+ const unsigned alignment = 64;
+ unsigned nblocksy;
+
+ nblocksy = util_format_get_nblocksy(format, height);
+ *stride = align(util_format_get_stride(format, width), alignment);
+
+ return winsys->buffer_create(winsys, alignment,
+ usage,
+ *stride * nblocksy);
+}
+
+
+static void
+fence_reference(struct pipe_winsys *sws, struct pipe_fence_handle **ptr,
+ struct pipe_fence_handle *fence)
+{
+ /* no-op */
+}
+
+
+static int
+fence_signalled(struct pipe_winsys *sws, struct pipe_fence_handle *fence,
+ unsigned flag)
+{
+ /* no-op */
+ return 0;
+}
+
+
+static int
+fence_finish(struct pipe_winsys *sws, struct pipe_fence_handle *fence,
+ unsigned flag)
+{
+ /* no-op */
+ return 0;
+}
+
+
+/**
+ * Create/return a new pipe_winsys object.
+ */
+struct pipe_winsys *
+create_sw_winsys(void)
+{
+ struct sw_pipe_winsys *ws = CALLOC_STRUCT(sw_pipe_winsys);
+ if (!ws)
+ return NULL;
+
+ /* Fill in this struct with callbacks that pipe will need to
+ * communicate with the window system, buffer manager, etc.
+ */
+ ws->Base.buffer_create = buffer_create;
+ ws->Base.user_buffer_create = user_buffer_create;
+ ws->Base.buffer_map = buffer_map;
+ ws->Base.buffer_unmap = buffer_unmap;
+ ws->Base.buffer_destroy = buffer_destroy;
+
+ ws->Base.surface_buffer_create = surface_buffer_create;
+
+ ws->Base.fence_reference = fence_reference;
+ ws->Base.fence_signalled = fence_signalled;
+ ws->Base.fence_finish = fence_finish;
+
+ ws->Base.flush_frontbuffer = NULL; /* not implemented here! */
+
+ ws->Base.get_name = get_name;
+
+ return &ws->Base;
+}
--- /dev/null
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * 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, sub license, 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 (including the
+ * next paragraph) 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 NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS 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.
+ *
+ **************************************************************************/
+
+
+#ifndef SW_WINSYS_H
+#define SW_WINSYS_H
+
+
+struct pipe_winsys;
+
+
+extern struct pipe_winsys *
+create_sw_winsys(void);
+
+
+#endif /* SW_WINSYS_H */
--- /dev/null
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.8
+ *
+ * Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org>
+ *
+ * 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
+ * BRIAN PAUL 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.
+ */
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <X11/Xlibint.h>
+#include <X11/extensions/XShm.h>
+#include "util/u_memory.h"
+#include "util/u_math.h"
+#include "util/u_format.h"
+#include "xf86drm.h"
+#include "egllog.h"
+
+#include "x11_screen.h"
+#include "dri2.h"
+#include "glxinit.h"
+
+struct x11_screen {
+ Display *dpy;
+ int number;
+
+ /*
+ * This is used to fetch GLX visuals/fbconfigs. It uses code from egl_xdri.
+ * It might be better to rewrite the part in Xlib or XCB.
+ */
+ __GLXdisplayPrivate *glx_dpy;
+
+ int dri_major, dri_minor;
+ char *dri_driver;
+ char *dri_device;
+ int dri_fd;
+
+ XVisualInfo *visuals;
+ int num_visuals;
+
+ /* cached values for x11_drawable_get_depth */
+ Drawable last_drawable;
+ unsigned int last_depth;
+};
+
+
+/**
+ * Create a X11 screen.
+ */
+struct x11_screen *
+x11_screen_create(Display *dpy, int screen)
+{
+ struct x11_screen *xscr;
+
+ if (screen >= ScreenCount(dpy))
+ return NULL;
+
+ xscr = CALLOC_STRUCT(x11_screen);
+ if (xscr) {
+ xscr->dpy = dpy;
+ xscr->number = screen;
+
+ xscr->dri_major = -1;
+ xscr->dri_fd = -1;
+ }
+ return xscr;
+}
+
+/**
+ * Destroy a X11 screen.
+ */
+void
+x11_screen_destroy(struct x11_screen *xscr)
+{
+ if (xscr->dri_fd >= 0)
+ close(xscr->dri_fd);
+ if (xscr->dri_driver)
+ Xfree(xscr->dri_driver);
+ if (xscr->dri_device)
+ Xfree(xscr->dri_device);
+
+ /* xscr->glx_dpy will be destroyed with the X display */
+
+ if (xscr->visuals)
+ XFree(xscr->visuals);
+ free(xscr);
+}
+
+static boolean
+x11_screen_init_dri2(struct x11_screen *xscr)
+{
+ if (xscr->dri_major < 0) {
+ int eventBase, errorBase;
+
+ if (!DRI2QueryExtension(xscr->dpy, &eventBase, &errorBase) ||
+ !DRI2QueryVersion(xscr->dpy, &xscr->dri_major, &xscr->dri_minor))
+ xscr->dri_major = -1;
+ }
+ return (xscr->dri_major >= 0);
+}
+
+static boolean
+x11_screen_init_glx(struct x11_screen *xscr)
+{
+ if (!xscr->glx_dpy)
+ xscr->glx_dpy = __glXInitialize(xscr->dpy);
+ return (xscr->glx_dpy != NULL);
+}
+
+/**
+ * Return true if the screen supports the extension.
+ */
+boolean
+x11_screen_support(struct x11_screen *xscr, enum x11_screen_extension ext)
+{
+ boolean supported = FALSE;
+
+ switch (ext) {
+ case X11_SCREEN_EXTENSION_XSHM:
+ supported = XShmQueryExtension(xscr->dpy);
+ break;
+ case X11_SCREEN_EXTENSION_GLX:
+ supported = x11_screen_init_glx(xscr);
+ break;
+ case X11_SCREEN_EXTENSION_DRI2:
+ supported = x11_screen_init_dri2(xscr);
+ break;
+ default:
+ break;
+ }
+
+ return supported;
+}
+
+/**
+ * Return the X visuals.
+ */
+const XVisualInfo *
+x11_screen_get_visuals(struct x11_screen *xscr, int *num_visuals)
+{
+ if (!xscr->visuals) {
+ XVisualInfo vinfo_template;
+ vinfo_template.screen = xscr->number;
+ xscr->visuals = XGetVisualInfo(xscr->dpy, VisualScreenMask,
+ &vinfo_template, &xscr->num_visuals);
+ }
+
+ if (num_visuals)
+ *num_visuals = xscr->num_visuals;
+ return xscr->visuals;
+}
+
+void
+x11_screen_convert_visual(struct x11_screen *xscr, const XVisualInfo *visual,
+ __GLcontextModes *mode)
+{
+ int r, g, b, a;
+ int visual_type;
+
+ r = util_bitcount(visual->red_mask);
+ g = util_bitcount(visual->green_mask);
+ b = util_bitcount(visual->blue_mask);
+ a = visual->depth - (r + g + b);
+#if defined(__cplusplus) || defined(c_plusplus)
+ visual_type = visual->c_class;
+#else
+ visual_type = visual->class;
+#endif
+
+ /* convert to GLX visual type */
+ switch (visual_type) {
+ case TrueColor:
+ visual_type = GLX_TRUE_COLOR;
+ break;
+ case DirectColor:
+ visual_type = GLX_DIRECT_COLOR;
+ break;
+ case PseudoColor:
+ visual_type = GLX_PSEUDO_COLOR;
+ break;
+ case StaticColor:
+ visual_type = GLX_STATIC_COLOR;
+ break;
+ case GrayScale:
+ visual_type = GLX_GRAY_SCALE;
+ break;
+ case StaticGray:
+ visual_type = GLX_STATIC_GRAY;
+ break;
+ default:
+ visual_type = GLX_NONE;
+ break;
+ }
+
+ mode->rgbBits = r + g + b + a;
+ mode->redBits = r;
+ mode->greenBits = g;
+ mode->blueBits = b;
+ mode->alphaBits = a;
+ mode->visualID = visual->visualid;
+ mode->visualType = visual_type;
+
+ /* sane defaults */
+ mode->renderType = GLX_RGBA_BIT;
+ mode->rgbMode = TRUE;
+ mode->visualRating = GLX_SLOW_CONFIG;
+ mode->xRenderable = TRUE;
+}
+
+/**
+ * Return the GLX fbconfigs.
+ */
+const __GLcontextModes *
+x11_screen_get_glx_configs(struct x11_screen *xscr)
+{
+ return (x11_screen_init_glx(xscr))
+ ? xscr->glx_dpy->screenConfigs[xscr->number].configs
+ : NULL;
+}
+
+/**
+ * Return the GLX visuals.
+ */
+const __GLcontextModes *
+x11_screen_get_glx_visuals(struct x11_screen *xscr)
+{
+ return (x11_screen_init_glx(xscr))
+ ? xscr->glx_dpy->screenConfigs[xscr->number].visuals
+ : NULL;
+}
+
+static boolean
+x11_screen_is_driver_equal(struct x11_screen *xscr, const char *driver)
+{
+ return (strcmp(xscr->dri_driver, driver) == 0);
+}
+
+/**
+ * Probe the screen for the DRI2 driver name.
+ */
+const char *
+x11_screen_probe_dri2(struct x11_screen *xscr)
+{
+ /* get the driver name and the device name */
+ if (!xscr->dri_driver) {
+ if (!DRI2Connect(xscr->dpy, RootWindow(xscr->dpy, xscr->number),
+ &xscr->dri_driver, &xscr->dri_device))
+ xscr->dri_driver = xscr->dri_device = NULL;
+ }
+
+ return xscr->dri_driver;
+}
+
+/**
+ * Enable DRI2 and returns the file descriptor of the DRM device. The file
+ * descriptor will be closed automatically when the screen is destoryed.
+ */
+int
+x11_screen_enable_dri2(struct x11_screen *xscr, const char *driver)
+{
+ if (xscr->dri_fd < 0) {
+ int fd;
+ drm_magic_t magic;
+
+ /* get the driver name and the device name first */
+ if (!x11_screen_probe_dri2(xscr))
+ return -1;
+
+ if (!x11_screen_is_driver_equal(xscr, driver)) {
+ _eglLog(_EGL_WARNING, "Driver mismatch: %s != %s",
+ xscr->dri_driver, driver);
+ return -1;
+ }
+
+ fd = open(xscr->dri_device, O_RDWR);
+ if (fd < 0) {
+ _eglLog(_EGL_WARNING, "failed to open %s", xscr->dri_device);
+ return -1;
+ }
+
+ memset(&magic, 0, sizeof(magic));
+ if (drmGetMagic(fd, &magic)) {
+ _eglLog(_EGL_WARNING, "failed to get magic");
+ close(fd);
+ return -1;
+ }
+
+ if (!DRI2Authenticate(xscr->dpy,
+ RootWindow(xscr->dpy, xscr->number), magic)) {
+ _eglLog(_EGL_WARNING, "failed to authenticate magic");
+ close(fd);
+ return -1;
+ }
+
+ xscr->dri_fd = fd;
+ }
+
+ return xscr->dri_fd;
+}
+
+/**
+ * Create/Destroy the DRI drawable.
+ */
+void
+x11_drawable_enable_dri2(struct x11_screen *xscr,
+ Drawable drawable, boolean on)
+{
+ if (on)
+ DRI2CreateDrawable(xscr->dpy, drawable);
+ else
+ DRI2DestroyDrawable(xscr->dpy, drawable);
+}
+
+/**
+ * Copy between buffers of the DRI2 drawable.
+ */
+void
+x11_drawable_copy_buffers(struct x11_screen *xscr, Drawable drawable,
+ int x, int y, int width, int height,
+ int src_buf, int dst_buf)
+{
+ XRectangle rect;
+ XserverRegion region;
+
+ rect.x = x;
+ rect.y = y;
+ rect.width = width;
+ rect.height = height;
+
+ region = XFixesCreateRegion(xscr->dpy, &rect, 1);
+ DRI2CopyRegion(xscr->dpy, drawable, region, dst_buf, src_buf);
+ XFixesDestroyRegion(xscr->dpy, region);
+}
+
+/**
+ * Get the buffers of the DRI2 drawable. The returned array should be freed.
+ */
+struct x11_drawable_buffer *
+x11_drawable_get_buffers(struct x11_screen *xscr, Drawable drawable,
+ int *width, int *height, unsigned int *attachments,
+ boolean with_format, int num_ins, int *num_outs)
+{
+ DRI2Buffer *dri2bufs;
+
+ if (with_format)
+ dri2bufs = DRI2GetBuffersWithFormat(xscr->dpy, drawable, width, height,
+ attachments, num_ins, num_outs);
+ else
+ dri2bufs = DRI2GetBuffers(xscr->dpy, drawable, width, height,
+ attachments, num_ins, num_outs);
+
+ return (struct x11_drawable_buffer *) dri2bufs;
+}
+
+/**
+ * Return the depth of a drawable.
+ *
+ * Unlike other drawable functions, the drawable needs not be a DRI2 drawable.
+ */
+uint
+x11_drawable_get_depth(struct x11_screen *xscr, Drawable drawable)
+{
+ unsigned int depth;
+
+ if (drawable != xscr->last_drawable) {
+ Window root;
+ int x, y;
+ unsigned int w, h, border;
+ Status ok;
+
+ ok = XGetGeometry(xscr->dpy, drawable, &root,
+ &x, &y, &w, &h, &border, &depth);
+ if (!ok)
+ depth = 0;
+
+ xscr->last_drawable = drawable;
+ xscr->last_depth = depth;
+ }
+ else {
+ depth = xscr->last_depth;
+ }
+
+ return depth;
+}
+
+/**
+ * Create a mode list of the given size.
+ */
+__GLcontextModes *
+x11_context_modes_create(unsigned count)
+{
+ const size_t size = sizeof(__GLcontextModes);
+ __GLcontextModes *base = NULL;
+ __GLcontextModes **next;
+ unsigned i;
+
+ next = &base;
+ for (i = 0; i < count; i++) {
+ *next = (__GLcontextModes *) calloc(1, size);
+ if (*next == NULL) {
+ x11_context_modes_destroy(base);
+ base = NULL;
+ break;
+ }
+ next = &((*next)->next);
+ }
+
+ return base;
+}
+
+/**
+ * Destroy a mode list.
+ */
+void
+x11_context_modes_destroy(__GLcontextModes *modes)
+{
+ while (modes != NULL) {
+ __GLcontextModes *next = modes->next;
+ free(modes);
+ modes = next;
+ }
+}
+
+/**
+ * Return the number of the modes in the mode list.
+ */
+unsigned
+x11_context_modes_count(const __GLcontextModes *modes)
+{
+ const __GLcontextModes *mode;
+ int count = 0;
+ for (mode = modes; mode; mode = mode->next)
+ count++;
+ return count;
+}
--- /dev/null
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.8
+ *
+ * Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org>
+ *
+ * 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
+ * BRIAN PAUL 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.
+ */
+
+#ifndef _X11_SCREEN_H_
+#define _X11_SCREEN_H_
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/extensions/dri2tokens.h>
+#include "pipe/p_compiler.h"
+#include "common/native.h"
+
+enum x11_screen_extension {
+ X11_SCREEN_EXTENSION_XSHM,
+ X11_SCREEN_EXTENSION_GLX,
+ X11_SCREEN_EXTENSION_DRI2,
+};
+
+/* the same as DRI2Buffer */
+struct x11_drawable_buffer {
+ unsigned int attachment;
+ unsigned int name;
+ unsigned int pitch;
+ unsigned int cpp;
+ unsigned int flags;
+};
+
+struct x11_screen;
+
+struct x11_screen *
+x11_screen_create(Display *dpy, int screen);
+
+void
+x11_screen_destroy(struct x11_screen *xscr);
+
+boolean
+x11_screen_support(struct x11_screen *xscr, enum x11_screen_extension ext);
+
+const XVisualInfo *
+x11_screen_get_visuals(struct x11_screen *xscr, int *num_visuals);
+
+void
+x11_screen_convert_visual(struct x11_screen *xscr, const XVisualInfo *visual,
+ __GLcontextModes *mode);
+
+const __GLcontextModes *
+x11_screen_get_glx_configs(struct x11_screen *xscr);
+
+const __GLcontextModes *
+x11_screen_get_glx_visuals(struct x11_screen *xscr);
+
+const char *
+x11_screen_probe_dri2(struct x11_screen *xscr);
+
+int
+x11_screen_enable_dri2(struct x11_screen *xscr, const char *driver);
+
+__GLcontextModes *
+x11_context_modes_create(unsigned count);
+
+void
+x11_context_modes_destroy(__GLcontextModes *modes);
+
+unsigned
+x11_context_modes_count(const __GLcontextModes *modes);
+
+void
+x11_drawable_enable_dri2(struct x11_screen *xscr,
+ Drawable drawable, boolean on);
+
+void
+x11_drawable_copy_buffers(struct x11_screen *xscr, Drawable drawable,
+ int x, int y, int width, int height,
+ int src_buf, int dst_buf);
+
+struct x11_drawable_buffer *
+x11_drawable_get_buffers(struct x11_screen *xscr, Drawable drawable,
+ int *width, int *height, unsigned int *attachments,
+ boolean with_format, int num_ins, int *num_outs);
+
+uint
+x11_drawable_get_depth(struct x11_screen *xscr, Drawable drawable);
+
+#endif /* _X11_SCREEN_H_ */
+++ /dev/null
-TOP = ../../../..
-include $(TOP)/configs/current
-
-common_INCLUDES = \
- -I. \
- -I$(TOP)/src/gallium/include \
- -I$(TOP)/src/gallium/auxiliary \
- -I$(TOP)/src/egl/main \
- -I$(TOP)/include
-
-common_SOURCES = $(wildcard common/*.c)
-common_OBJECTS = $(common_SOURCES:.c=.o)
-
-
-x11_INCLUDES = \
- -I$(TOP)/src/gallium/drivers \
- -I$(TOP)/src/glx/x11 \
- -I$(TOP)/src/egl/drivers/xdri \
- -I$(TOP)/src/mesa \
- $(shell pkg-config --cflags-only-I libdrm)
-
-x11_SOURCES = $(wildcard x11/*.c) \
- $(TOP)/src/glx/x11/dri2.c \
- $(TOP)/src/egl/drivers/xdri/glxinit.c
-x11_OBJECTS = $(x11_SOURCES:.c=.o)
-
-
-kms_INCLUDES = $(shell pkg-config --cflags-only-I libdrm)
-kms_SOURCES = $(wildcard kms/*.c)
-kms_OBJECTS = $(kms_SOURCES:.c=.o)
-
-
-ALL_INCLUDES = $(common_INCLUDES) $(x11_INCLUDES) $(kms_INCLUDES)
-ALL_SOURCES = $(common_SOURCES) $(x11_SOURCES) $(kms_SOURCES)
-ALL_OBJECTS = $(common_OBJECTS) $(x11_OBJECTS) $(kms_OBJECTS)
-
-##### TARGETS #####
-
-EGL_DISPLAYS_MODS = $(foreach dpy, $(EGL_DISPLAYS), libegl$(dpy).a)
-
-default: depend $(EGL_DISPLAYS_MODS)
-
-
-libeglx11.a: $(x11_OBJECTS) $(common_OBJECTS) Makefile
- $(MKLIB) -o eglx11 -static $(x11_OBJECTS) $(common_OBJECTS)
-
-libeglkms.a: $(kms_OBJECTS) $(common_OBJECTS) Makefile
- $(MKLIB) -o eglkms -static $(kms_OBJECTS) $(common_OBJECTS)
-
-depend:
- rm -f depend
- touch depend
- $(MKDEP) $(MKDEP_OPTIONS) $(ALL_INCLUDES) $(ALL_SOURCES) 2> /dev/null
-
-clean:
- rm -f $(ALL_OBJECTS)
- rm -f $(EGL_DISPLAYS_MODS)
- rm -f depend depend.bak
-
-# Dummy target
-install:
- @echo -n ""
-
-##### RULES #####
-
-$(common_OBJECTS): %.o: %.c
- $(CC) -c $(common_INCLUDES) $(DEFINES) $(CFLAGS) $< -o $@
-
-$(x11_OBJECTS): %.o: %.c
- $(CC) -c $(common_INCLUDES) $(x11_INCLUDES) $(DEFINES) $(CFLAGS) $< -o $@
-
-$(kms_OBJECTS): %.o: %.c
- $(CC) -c $(common_INCLUDES) $(kms_INCLUDES) $(DEFINES) $(CFLAGS) $< -o $@
-
-sinclude depend
+++ /dev/null
-/*
- * Mesa 3-D graphics library
- * Version: 7.8
- *
- * Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org>
- *
- * 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
- * BRIAN PAUL 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.
- */
-
-#include <assert.h>
-#include <string.h>
-#include "pipe/p_screen.h"
-#include "util/u_memory.h"
-#include "util/u_rect.h"
-#include "egldriver.h"
-#include "eglcurrent.h"
-#include "eglconfigutil.h"
-#include "egllog.h"
-
-#include "native.h"
-#include "egl_g3d.h"
-#include "egl_st.h"
-
-/**
- * Validate the draw/read surfaces of the context.
- */
-static void
-egl_g3d_validate_context(_EGLDisplay *dpy, _EGLContext *ctx)
-{
- struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
- struct pipe_screen *screen = gdpy->native->screen;
- struct egl_g3d_context *gctx = egl_g3d_context(ctx);
- const uint st_att_map[NUM_NATIVE_ATTACHMENTS] = {
- ST_SURFACE_FRONT_LEFT,
- ST_SURFACE_BACK_LEFT,
- ST_SURFACE_FRONT_RIGHT,
- ST_SURFACE_BACK_RIGHT,
- };
- EGLint num_surfaces, s;
-
- /* validate draw and/or read buffers */
- num_surfaces = (gctx->base.ReadSurface == gctx->base.DrawSurface) ? 1 : 2;
- for (s = 0; s < num_surfaces; s++) {
- struct pipe_texture *textures[NUM_NATIVE_ATTACHMENTS];
- struct egl_g3d_surface *gsurf;
- struct egl_g3d_buffer *gbuf;
- EGLint att;
-
- if (s == 0) {
- gsurf = egl_g3d_surface(gctx->base.DrawSurface);
- gbuf = &gctx->draw;
- }
- else {
- gsurf = egl_g3d_surface(gctx->base.ReadSurface);
- gbuf = &gctx->read;
- }
-
- if (!gctx->force_validate) {
- unsigned int seq_num;
-
- gsurf->native->validate(gsurf->native, gbuf->attachment_mask,
- &seq_num, NULL, NULL, NULL);
- /* skip validation */
- if (gsurf->sequence_number == seq_num)
- continue;
- }
-
- pipe_surface_reference(&gsurf->render_surface, NULL);
- memset(textures, 0, sizeof(textures));
-
- gsurf->native->validate(gsurf->native, gbuf->attachment_mask,
- &gsurf->sequence_number, textures,
- &gsurf->base.Width, &gsurf->base.Height);
- for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) {
- struct pipe_texture *pt = textures[att];
- struct pipe_surface *ps;
-
- if (native_attachment_mask_test(gbuf->attachment_mask, att) && pt) {
- ps = screen->get_tex_surface(screen, pt, 0, 0, 0,
- PIPE_BUFFER_USAGE_GPU_READ |
- PIPE_BUFFER_USAGE_GPU_WRITE);
- gctx->stapi->st_set_framebuffer_surface(gbuf->st_fb,
- st_att_map[att], ps);
-
- if (gsurf->render_att == att)
- pipe_surface_reference(&gsurf->render_surface, ps);
-
- pipe_surface_reference(&ps, NULL);
- pipe_texture_reference(&pt, NULL);
- }
- }
-
- gctx->stapi->st_resize_framebuffer(gbuf->st_fb,
- gsurf->base.Width, gsurf->base.Height);
- }
-
- gctx->force_validate = EGL_FALSE;
-
-}
-
-/**
- * Create a st_framebuffer.
- */
-static struct st_framebuffer *
-create_framebuffer(_EGLContext *ctx, _EGLSurface *surf)
-{
- struct egl_g3d_context *gctx = egl_g3d_context(ctx);
- struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
- struct egl_g3d_config *gconf = egl_g3d_config(gsurf->base.Config);
-
- return gctx->stapi->st_create_framebuffer(&gconf->native->mode,
- gconf->native->color_format, gconf->native->depth_format,
- gconf->native->stencil_format,
- gsurf->base.Width, gsurf->base.Height, &gsurf->base);
-}
-
-/**
- * Update the attachments of draw/read surfaces.
- */
-static void
-egl_g3d_route_context(_EGLDisplay *dpy, _EGLContext *ctx)
-{
- struct egl_g3d_context *gctx = egl_g3d_context(ctx);
- EGLint s;
-
- /* route draw and read buffers' attachments */
- for (s = 0; s < 2; s++) {
- struct egl_g3d_surface *gsurf;
- struct egl_g3d_buffer *gbuf;
-
- if (s == 0) {
- gsurf = egl_g3d_surface(gctx->base.DrawSurface);
- gbuf = &gctx->draw;
- }
- else {
- gsurf = egl_g3d_surface(gctx->base.ReadSurface);
- gbuf = &gctx->read;
- }
-
- gbuf->attachment_mask = (1 << gsurf->render_att);
-
- /* FIXME OpenGL defaults to draw the front or back buffer when the
- * context is single-buffered or double-buffered respectively. In EGL,
- * however, the buffer to be drawn is determined by the surface, instead
- * of the context. As a result, rendering to a pixmap surface with a
- * double-buffered context does not work as expected.
- *
- * gctx->stapi->st_draw_front_buffer(gctx->st_ctx, natt ==
- * NATIVE_ATTACHMENT_FRONT_LEFT);
- */
-
- /*
- * FIXME If the back buffer is asked for here, and the front buffer is
- * later needed by the client API (e.g. glDrawBuffer is called to draw
- * the front buffer), it will create a new pipe texture and draw there.
- * One fix is to ask for both buffers here, but it would be a waste if
- * the front buffer is never used. A better fix is to add a callback to
- * the pipe screen with context private (just like flush_frontbuffer).
- */
- }
-}
-
-/**
- * Reallocate the context's framebuffers after draw/read surfaces change.
- */
-static EGLBoolean
-egl_g3d_realloc_context(_EGLDisplay *dpy, _EGLContext *ctx)
-{
- struct egl_g3d_context *gctx = egl_g3d_context(ctx);
- struct egl_g3d_surface *gdraw = egl_g3d_surface(gctx->base.DrawSurface);
- struct egl_g3d_surface *gread = egl_g3d_surface(gctx->base.ReadSurface);
-
- /* unreference the old framebuffers */
- if (gctx->draw.st_fb) {
- EGLBoolean is_equal = (gctx->draw.st_fb == gctx->read.st_fb);
- void *priv;
-
- priv = gctx->stapi->st_framebuffer_private(gctx->draw.st_fb);
- if (!gdraw || priv != (void *) &gdraw->base) {
- gctx->stapi->st_unreference_framebuffer(gctx->draw.st_fb);
- gctx->draw.st_fb = NULL;
- gctx->draw.attachment_mask = 0x0;
- }
-
- if (is_equal) {
- gctx->read.st_fb = NULL;
- gctx->draw.attachment_mask = 0x0;
- }
- else {
- priv = gctx->stapi->st_framebuffer_private(gctx->read.st_fb);
- if (!gread || priv != (void *) &gread->base) {
- gctx->stapi->st_unreference_framebuffer(gctx->read.st_fb);
- gctx->read.st_fb = NULL;
- gctx->draw.attachment_mask = 0x0;
- }
- }
- }
-
- if (!gdraw)
- return EGL_TRUE;
-
- /* create the draw fb */
- if (!gctx->draw.st_fb) {
- gctx->draw.st_fb = create_framebuffer(&gctx->base, &gdraw->base);
- if (!gctx->draw.st_fb)
- return EGL_FALSE;
- }
-
- /* create the read fb */
- if (!gctx->read.st_fb) {
- if (gread != gdraw) {
- gctx->read.st_fb = create_framebuffer(&gctx->base, &gread->base);
- if (!gctx->read.st_fb) {
- gctx->stapi->st_unreference_framebuffer(gctx->draw.st_fb);
- gctx->draw.st_fb = NULL;
- return EGL_FALSE;
- }
- }
- else {
- /* there is no st_reference_framebuffer... */
- gctx->read.st_fb = gctx->draw.st_fb;
- }
- }
-
- egl_g3d_route_context(dpy, &gctx->base);
- gctx->force_validate = EGL_TRUE;
-
- return EGL_TRUE;
-}
-
-/**
- * Return the current context of the given API.
- */
-static struct egl_g3d_context *
-egl_g3d_get_current_context(EGLint api)
-{
- _EGLThreadInfo *t = _eglGetCurrentThread();
- EGLint api_index = _eglConvertApiToIndex(api);
- return egl_g3d_context(t->CurrentContexts[api_index]);
-}
-
-/**
- * Return the state tracker for the given context.
- */
-static const struct egl_g3d_st *
-egl_g3d_choose_st(_EGLDriver *drv, _EGLContext *ctx)
-{
- struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
- const struct egl_g3d_st *stapi;
- EGLint idx = -1;
-
- switch (ctx->ClientAPI) {
- case EGL_OPENGL_ES_API:
- switch (ctx->ClientVersion) {
- case 1:
- idx = EGL_G3D_ST_OPENGL_ES;
- break;
- case 2:
- idx = EGL_G3D_ST_OPENGL_ES2;
- break;
- default:
- _eglLog(_EGL_WARNING, "unknown client version %d",
- ctx->ClientVersion);
- break;
- }
- break;
- case EGL_OPENVG_API:
- idx = EGL_G3D_ST_OPENVG;
- break;
- case EGL_OPENGL_API:
- idx = EGL_G3D_ST_OPENGL;
- break;
- default:
- _eglLog(_EGL_WARNING, "unknown client API 0x%04x", ctx->ClientAPI);
- break;
- }
-
- stapi = (idx >= 0) ? gdrv->stapis[idx] : NULL;
- return stapi;
-}
-
-/**
- * Initialize the state trackers.
- */
-static void
-egl_g3d_init_st(_EGLDriver *drv)
-{
- struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
- EGLint i;
-
- /* already initialized */
- if (gdrv->api_mask)
- return;
-
- for (i = 0; i < NUM_EGL_G3D_STS; i++) {
- gdrv->stapis[i] = egl_g3d_get_st(i);
- if (gdrv->stapis[i])
- gdrv->api_mask |= gdrv->stapis[i]->api_bit;
- }
-
- if (gdrv->api_mask)
- _eglLog(_EGL_DEBUG, "Driver API mask: 0x%x", gdrv->api_mask);
- else
- _eglLog(_EGL_WARNING, "No supported client API");
-}
-
-/**
- * Get the probe object of the display.
- *
- * Note that this function may be called before the display is initialized.
- */
-static struct native_probe *
-egl_g3d_get_probe(_EGLDriver *drv, _EGLDisplay *dpy)
-{
- struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
- struct native_probe *nprobe;
-
- nprobe = (struct native_probe *) _eglGetProbeCache(gdrv->probe_key);
- if (!nprobe || nprobe->display != dpy->NativeDisplay) {
- if (nprobe)
- nprobe->destroy(nprobe);
- nprobe = native_create_probe(dpy->NativeDisplay);
- _eglSetProbeCache(gdrv->probe_key, (void *) nprobe);
- }
-
- return nprobe;
-}
-
-/**
- * Destroy the probe object of the display. The display may be NULL.
- *
- * Note that this function may be called before the display is initialized.
- */
-static void
-egl_g3d_destroy_probe(_EGLDriver *drv, _EGLDisplay *dpy)
-{
- struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
- struct native_probe *nprobe;
-
- nprobe = (struct native_probe *) _eglGetProbeCache(gdrv->probe_key);
- if (nprobe && (!dpy || nprobe->display == dpy->NativeDisplay)) {
- nprobe->destroy(nprobe);
- _eglSetProbeCache(gdrv->probe_key, NULL);
- }
-}
-
-/**
- * Return an API mask that consists of the state trackers that supports the
- * given mode.
- *
- * FIXME add st_is_mode_supported()?
- */
-static EGLint
-get_mode_api_mask(const __GLcontextModes *mode, EGLint api_mask)
-{
- EGLint check;
-
- /* OpenGL ES 1.x and 2.x are checked together */
- check = EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT;
- if (api_mask & check) {
- /* this is required by EGL, not by OpenGL ES */
- if (mode->drawableType & GLX_WINDOW_BIT && !mode->doubleBufferMode)
- api_mask &= ~check;
- }
-
- check = EGL_OPENVG_BIT;
- if (api_mask & check) {
- /* vega st needs the depth/stencil rb */
- if (!mode->depthBits && !mode->stencilBits)
- api_mask &= ~check;
- }
-
- 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.
- */
-static EGLint
-egl_g3d_add_configs(_EGLDriver *drv, _EGLDisplay *dpy, EGLint id)
-{
- struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
- struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
- const struct native_config **native_configs;
- int num_configs, i;
-
- native_configs = gdpy->native->get_configs(gdpy->native,
- &num_configs);
- if (!num_configs) {
- if (native_configs)
- free(native_configs);
- return id;
- }
-
- for (i = 0; i < num_configs; i++) {
- EGLint api_mask;
- struct egl_g3d_config *gconf;
- EGLBoolean valid;
-
- api_mask = get_mode_api_mask(&native_configs[i]->mode, gdrv->api_mask);
- if (!api_mask) {
- _eglLog(_EGL_DEBUG, "no state tracker supports config 0x%x",
- native_configs[i]->mode.visualID);
- continue;
- }
-
- gconf = CALLOC_STRUCT(egl_g3d_config);
- if (!gconf)
- continue;
-
- _eglInitConfig(&gconf->base, id);
- valid = _eglConfigFromContextModesRec(&gconf->base,
- &native_configs[i]->mode, api_mask, api_mask);
- 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);
- free(gconf);
- continue;
- }
-
- gconf->native = native_configs[i];
- _eglAddConfig(dpy, &gconf->base);
- id++;
- }
-
- free(native_configs);
- return id;
-}
-
-/**
- * Flush the front buffer of the context's draw surface.
- */
-static void
-egl_g3d_flush_frontbuffer(struct pipe_screen *screen,
- struct pipe_surface *surf, void *context_private)
-{
- struct egl_g3d_context *gctx = egl_g3d_context(context_private);
- struct egl_g3d_surface *gsurf = egl_g3d_surface(gctx->base.DrawSurface);
-
- if (gsurf)
- gsurf->native->flush_frontbuffer(gsurf->native);
-}
-
-/**
- * Re-validate the context.
- */
-static void
-egl_g3d_update_buffer(struct pipe_screen *screen, void *context_private)
-{
- struct egl_g3d_context *gctx = egl_g3d_context(context_private);
-
- /**
- * It is likely that the surface has changed when this function is called.
- * Set force_validate to skip an unnecessary check.
- */
- gctx->force_validate = EGL_TRUE;
- egl_g3d_validate_context(gctx->base.Display, &gctx->base);
-}
-
-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);
-
- free(gdpy);
- dpy->DriverData = NULL;
-
- return EGL_TRUE;
-}
-
-static EGLBoolean
-egl_g3d_initialize(_EGLDriver *drv, _EGLDisplay *dpy,
- EGLint *major, EGLint *minor)
-{
- struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
- struct egl_g3d_display *gdpy;
-
- /* the probe object is unlikely to be needed again */
- egl_g3d_destroy_probe(drv, dpy);
-
- gdpy = CALLOC_STRUCT(egl_g3d_display);
- if (!gdpy) {
- _eglError(EGL_BAD_ALLOC, "eglInitialize");
- goto fail;
- }
- dpy->DriverData = gdpy;
-
- gdpy->native = native_create_display(dpy->NativeDisplay);
- if (!gdpy->native) {
- _eglError(EGL_NOT_INITIALIZED, "eglInitialize(no usable display)");
- goto fail;
- }
-
- gdpy->native->screen->flush_frontbuffer = egl_g3d_flush_frontbuffer;
- gdpy->native->screen->update_buffer = egl_g3d_update_buffer;
-
- egl_g3d_init_st(&gdrv->base);
- dpy->ClientAPIsMask = gdrv->api_mask;
-
- if (egl_g3d_add_configs(drv, dpy, 1) == 1) {
- _eglError(EGL_NOT_INITIALIZED, "eglInitialize(unable to add configs)");
- 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;
-
- return EGL_TRUE;
-
-fail:
- if (gdpy)
- egl_g3d_terminate(drv, dpy);
- return EGL_FALSE;
-}
-
-static _EGLContext *
-egl_g3d_create_context(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
- _EGLContext *share, const EGLint *attribs)
-{
- struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
- struct egl_g3d_context *gshare = egl_g3d_context(share);
- struct egl_g3d_config *gconf = egl_g3d_config(conf);
- struct egl_g3d_context *gctx;
- const __GLcontextModes *mode;
-
- gctx = CALLOC_STRUCT(egl_g3d_context);
- if (!gctx) {
- _eglError(EGL_BAD_ALLOC, "eglCreateContext");
- return NULL;
- }
-
- if (!_eglInitContext(drv, &gctx->base, conf, attribs)) {
- free(gctx);
- return NULL;
- }
-
- gctx->stapi = egl_g3d_choose_st(drv, &gctx->base);
- if (!gctx->stapi) {
- free(gctx);
- return NULL;
- }
-
- mode = &gconf->native->mode;
- gctx->pipe =
- gdpy->native->create_context(gdpy->native, (void *) &gctx->base);
- if (!gctx->pipe) {
- free(gctx);
- return NULL;
- }
-
- gctx->st_ctx = gctx->stapi->st_create_context(gctx->pipe, mode,
- (gshare) ? gshare->st_ctx : NULL);
- if (!gctx->st_ctx) {
- gctx->pipe->destroy(gctx->pipe);
- free(gctx);
- return NULL;
- }
-
- return &gctx->base;
-}
-
-static EGLBoolean
-egl_g3d_destroy_context(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx)
-{
- struct egl_g3d_context *gctx = egl_g3d_context(ctx);
-
- if (_eglIsContextBound(&gctx->base))
- return EGL_TRUE;
-
- egl_g3d_realloc_context(dpy, &gctx->base);
-
- /* it will destroy pipe context */
- gctx->stapi->st_destroy_context(gctx->st_ctx);
-
- free(gctx);
-
- return EGL_TRUE;
-}
-
-static EGLBoolean
-init_surface_geometry(_EGLSurface *surf)
-{
- struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
-
- return gsurf->native->validate(gsurf->native, 0x0,
- &gsurf->sequence_number, NULL,
- &gsurf->base.Width, &gsurf->base.Height);
-}
-
-static _EGLSurface *
-egl_g3d_create_window_surface(_EGLDriver *drv, _EGLDisplay *dpy,
- _EGLConfig *conf, EGLNativeWindowType win,
- 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, "eglCreateWindowSurface");
- return NULL;
- }
-
- if (!_eglInitSurface(drv, &gsurf->base, EGL_WINDOW_BIT, conf, attribs)) {
- free(gsurf);
- return NULL;
- }
-
- gsurf->native =
- gdpy->native->create_window_surface(gdpy->native, win, gconf->native);
- if (!gsurf->native) {
- free(gsurf);
- return NULL;
- }
-
- if (!init_surface_geometry(&gsurf->base)) {
- gsurf->native->destroy(gsurf->native);
- free(gsurf);
- return NULL;
- }
-
- gsurf->render_att = (gsurf->base.RenderBuffer == EGL_SINGLE_BUFFER ||
- !gconf->native->mode.doubleBufferMode) ?
- NATIVE_ATTACHMENT_FRONT_LEFT : NATIVE_ATTACHMENT_BACK_LEFT;
-
- return &gsurf->base;
-}
-
-static _EGLSurface *
-egl_g3d_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *dpy,
- _EGLConfig *conf, EGLNativePixmapType pix,
- 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, "eglCreatePixmapSurface");
- return NULL;
- }
-
- if (!_eglInitSurface(drv, &gsurf->base, EGL_PIXMAP_BIT, conf, attribs)) {
- free(gsurf);
- return NULL;
- }
-
- gsurf->native =
- gdpy->native->create_pixmap_surface(gdpy->native, pix, gconf->native);
- if (!gsurf->native) {
- free(gsurf);
- return NULL;
- }
-
- if (!init_surface_geometry(&gsurf->base)) {
- gsurf->native->destroy(gsurf->native);
- free(gsurf);
- return NULL;
- }
-
- gsurf->render_att = NATIVE_ATTACHMENT_FRONT_LEFT;
-
- return &gsurf->base;
-}
-
-static _EGLSurface *
-egl_g3d_create_pbuffer_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_PBUFFER_BIT, conf, attribs)) {
- free(gsurf);
- return NULL;
- }
-
- gsurf->native =
- gdpy->native->create_pbuffer_surface(gdpy->native, gconf->native,
- gsurf->base.Width, gsurf->base.Height);
- if (!gsurf->native) {
- free(gsurf);
- return NULL;
- }
-
- if (!init_surface_geometry(&gsurf->base)) {
- gsurf->native->destroy(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_destroy_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf)
-{
- struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
-
- if (_eglIsSurfaceBound(&gsurf->base))
- return EGL_TRUE;
-
- pipe_surface_reference(&gsurf->render_surface, NULL);
- gsurf->native->destroy(gsurf->native);
- free(gsurf);
- return EGL_TRUE;
-}
-
-static EGLBoolean
-egl_g3d_make_current(_EGLDriver *drv, _EGLDisplay *dpy,
- _EGLSurface *draw, _EGLSurface *read, _EGLContext *ctx)
-{
- struct egl_g3d_context *gctx = egl_g3d_context(ctx);
- struct egl_g3d_context *old_gctx;
- EGLint api;
- EGLBoolean ok = EGL_TRUE;
-
- /* find the old context */
- api = (gctx) ? gctx->base.ClientAPI : eglQueryAPI();
- old_gctx = egl_g3d_get_current_context(api);
- if (old_gctx && !_eglIsContextLinked(&old_gctx->base))
- old_gctx = NULL;
-
- if (!_eglMakeCurrent(drv, dpy, draw, read, ctx))
- return EGL_FALSE;
-
- if (old_gctx) {
- /* flush old context */
- old_gctx->stapi->st_flush(old_gctx->st_ctx,
- PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL);
-
- /*
- * The old context is no longer current, and egl_g3d_realloc_context()
- * should be called to destroy the framebuffers. However, it is possible
- * that it will be made current again with the same draw/read surfaces.
- * It might be better to keep it around.
- */
- }
-
- if (gctx) {
- struct egl_g3d_surface *gdraw = egl_g3d_surface(draw);
-
- ok = egl_g3d_realloc_context(dpy, &gctx->base);
- if (ok) {
- ok = gctx->stapi->st_make_current(gctx->st_ctx,
- gctx->draw.st_fb, gctx->read.st_fb);
- if (ok) {
- egl_g3d_validate_context(dpy, &gctx->base);
- if (gdraw->base.Type == EGL_WINDOW_BIT) {
- gctx->base.WindowRenderBuffer =
- (gdraw->render_att == NATIVE_ATTACHMENT_FRONT_LEFT) ?
- EGL_SINGLE_BUFFER : EGL_BACK_BUFFER;
- }
- }
- }
- }
- else if (old_gctx) {
- ok = old_gctx->stapi->st_make_current(NULL, NULL, NULL);
- old_gctx->base.WindowRenderBuffer = EGL_NONE;
- }
-
- return ok;
-}
-
-static EGLBoolean
-egl_g3d_swap_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf)
-{
- struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
- _EGLContext *ctx = _eglGetCurrentContext();
- struct egl_g3d_context *gctx = NULL;
-
- /* no-op for pixmap or pbuffer surface */
- if (gsurf->base.Type == EGL_PIXMAP_BIT ||
- gsurf->base.Type == EGL_PBUFFER_BIT)
- return EGL_TRUE;
-
- /* or when the surface is single-buffered */
- if (gsurf->render_att == NATIVE_ATTACHMENT_FRONT_LEFT)
- return EGL_TRUE;
-
- if (ctx && ctx->DrawSurface == surf)
- gctx = egl_g3d_context(ctx);
-
- /* flush if the surface is current */
- if (gctx)
- gctx->stapi->st_notify_swapbuffers(gctx->draw.st_fb);
-
- /*
- * We drew on the back buffer, unless there was no back buffer.
- * In that case, we drew on the front buffer. Either case, we call
- * swap_buffers.
- */
- if (!gsurf->native->swap_buffers(gsurf->native))
- return EGL_FALSE;
-
- if (gctx) {
- struct egl_g3d_config *gconf = egl_g3d_config(gsurf->base.Config);
-
- /* force validation if the swap method is not copy */
- if (gconf->native->mode.swapMethod != GLX_SWAP_COPY_OML) {
- gctx->force_validate = EGL_TRUE;
- egl_g3d_validate_context(dpy, &gctx->base);
- }
- }
-
- return EGL_TRUE;
-}
-
-/**
- * Find a config that supports the pixmap.
- */
-static _EGLConfig *
-find_pixmap_config(_EGLDisplay *dpy, EGLNativePixmapType pix)
-{
- struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
- struct egl_g3d_config *gconf;
- EGLint i;
-
- for (i = 0; i < dpy->NumConfigs; i++) {
- gconf = egl_g3d_config(dpy->Configs[i]);
- if (gdpy->native->is_pixmap_supported(gdpy->native, pix, gconf->native))
- break;
- }
-
- return (i < dpy->NumConfigs) ? &gconf->base : NULL;
-}
-
-/**
- * Get the pipe surface of the given attachment of the native surface.
- */
-static struct pipe_surface *
-get_pipe_surface(struct native_display *ndpy, struct native_surface *nsurf,
- enum native_attachment natt)
-{
- struct pipe_texture *textures[NUM_NATIVE_ATTACHMENTS];
- struct pipe_surface *psurf;
-
- textures[natt] = NULL;
- nsurf->validate(nsurf, 1 << natt, NULL, textures, NULL, NULL);
- if (!textures[natt])
- return NULL;
-
- psurf = ndpy->screen->get_tex_surface(ndpy->screen, textures[natt],
- 0, 0, 0, PIPE_BUFFER_USAGE_CPU_WRITE);
- pipe_texture_reference(&textures[natt], NULL);
-
- return psurf;
-}
-
-static EGLBoolean
-egl_g3d_copy_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
- NativePixmapType target)
-{
- struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
- struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
- _EGLContext *ctx = _eglGetCurrentContext();
- struct egl_g3d_config *gconf;
- struct native_surface *nsurf;
- struct pipe_screen *screen = gdpy->native->screen;
- struct pipe_surface *psurf;
-
- if (!gsurf->render_surface)
- return EGL_TRUE;
-
- gconf = egl_g3d_config(find_pixmap_config(dpy, target));
- if (!gconf)
- return _eglError(EGL_BAD_NATIVE_PIXMAP, "eglCopyBuffers");
-
- nsurf = gdpy->native->create_pixmap_surface(gdpy->native,
- target, gconf->native);
- if (!nsurf)
- return _eglError(EGL_BAD_NATIVE_PIXMAP, "eglCopyBuffers");
-
- /* flush if the surface is current */
- if (ctx && ctx->DrawSurface == &gsurf->base) {
- struct egl_g3d_context *gctx = egl_g3d_context(ctx);
- gctx->stapi->st_flush(gctx->st_ctx,
- PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL);
- }
-
- psurf = get_pipe_surface(gdpy->native, nsurf, NATIVE_ATTACHMENT_FRONT_LEFT);
- if (psurf) {
- struct pipe_context pipe;
-
- /**
- * XXX This is hacky. If we might allow the EGLDisplay to create a pipe
- * context of its own and use the blitter context for this.
- */
- memset(&pipe, 0, sizeof(pipe));
- pipe.screen = screen;
-
- util_surface_copy(&pipe, FALSE, psurf, 0, 0,
- gsurf->render_surface, 0, 0, psurf->width, psurf->height);
-
- pipe_surface_reference(&psurf, NULL);
- nsurf->flush_frontbuffer(nsurf);
- }
-
- nsurf->destroy(nsurf);
-
- return EGL_TRUE;
-}
-
-static EGLBoolean
-egl_g3d_wait_client(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx)
-{
- struct egl_g3d_context *gctx = egl_g3d_context(ctx);
- gctx->stapi->st_finish(gctx->st_ctx);
- return EGL_TRUE;
-}
-
-static EGLBoolean
-egl_g3d_wait_native(_EGLDriver *drv, _EGLDisplay *dpy, EGLint engine)
-{
- _EGLSurface *surf = _eglGetCurrentSurface(EGL_DRAW);
- struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
-
- if (engine != EGL_CORE_NATIVE_ENGINE)
- return _eglError(EGL_BAD_PARAMETER, "eglWaitNative");
-
- if (gsurf)
- gsurf->native->wait(gsurf->native);
-
- return EGL_TRUE;
-}
-
-static _EGLProc
-egl_g3d_get_proc_address(_EGLDriver *drv, const char *procname)
-{
- struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
- _EGLProc proc;
- EGLint i;
-
- /* in case this is called before a display is initialized */
- egl_g3d_init_st(&gdrv->base);
-
- for (i = 0; i < NUM_EGL_G3D_STS; i++) {
- const struct egl_g3d_st *stapi = gdrv->stapis[i];
- if (stapi) {
- proc = (_EGLProc) stapi->st_get_proc_address(procname);
- if (proc)
- return proc;
- }
- }
-
- return (_EGLProc) NULL;
-}
-
-static EGLBoolean
-egl_g3d_bind_tex_image(_EGLDriver *drv, _EGLDisplay *dpy,
- _EGLSurface *surf, EGLint buffer)
-{
- struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
- struct egl_g3d_context *gctx;
- enum pipe_format target_format;
- int target;
-
- if (!gsurf || gsurf->base.Type != EGL_PBUFFER_BIT)
- return _eglError(EGL_BAD_SURFACE, "eglBindTexImage");
- if (buffer != EGL_BACK_BUFFER)
- return _eglError(EGL_BAD_PARAMETER, "eglBindTexImage");
- if (gsurf->base.BoundToTexture)
- return _eglError(EGL_BAD_ACCESS, "eglBindTexImage");
-
- switch (gsurf->base.TextureFormat) {
- case EGL_TEXTURE_RGB:
- target_format = PIPE_FORMAT_R8G8B8_UNORM;
- break;
- case EGL_TEXTURE_RGBA:
- target_format = PIPE_FORMAT_A8R8G8B8_UNORM;
- break;
- default:
- return _eglError(EGL_BAD_MATCH, "eglBindTexImage");
- }
-
- switch (gsurf->base.TextureTarget) {
- case EGL_TEXTURE_2D:
- target = ST_TEXTURE_2D;
- break;
- default:
- return _eglError(EGL_BAD_MATCH, "eglBindTexImage");
- }
-
- /* flush properly if the surface is bound */
- if (gsurf->base.Binding) {
- gctx = egl_g3d_context(gsurf->base.Binding);
- gctx->stapi->st_flush(gctx->st_ctx,
- PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL);
- }
-
- /* XXX change to EGL_OPENGL_ES_API once OpenGL ES is merged */
- gctx = egl_g3d_get_current_context(EGL_OPENGL_API);
- if (gctx) {
- if (!gsurf->render_surface)
- return EGL_FALSE;
-
- gctx->stapi->st_bind_texture_surface(gsurf->render_surface,
- target, gsurf->base.MipmapLevel, target_format);
- gsurf->base.BoundToTexture = EGL_TRUE;
- }
-
- return EGL_TRUE;
-}
-
-static EGLBoolean
-egl_g3d_release_tex_image(_EGLDriver *drv, _EGLDisplay *dpy,
- _EGLSurface *surf, EGLint buffer)
-{
- struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
-
- if (!gsurf || gsurf->base.Type != EGL_PBUFFER_BIT ||
- !gsurf->base.BoundToTexture)
- return _eglError(EGL_BAD_SURFACE, "eglReleaseTexImage");
- if (buffer != EGL_BACK_BUFFER)
- return _eglError(EGL_BAD_PARAMETER, "eglReleaseTexImage");
-
- if (gsurf->render_surface) {
- _EGLThreadInfo *t = _eglGetCurrentThread();
- /* XXX change to EGL_OPENGL_ES_API once OpenGL ES is merged */
- struct egl_g3d_context *gctx = egl_g3d_context(
- t->CurrentContexts[_eglConvertApiToIndex(EGL_OPENGL_API)]);
-
- /* what if the context the surface binds to is no longer current? */
- if (gctx)
- gctx->stapi->st_unbind_texture_surface(gsurf->render_surface,
- ST_TEXTURE_2D, gsurf->base.MipmapLevel);
- }
-
- gsurf->base.BoundToTexture = EGL_FALSE;
-
- 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 EGLint
-egl_g3d_probe(_EGLDriver *drv, _EGLDisplay *dpy)
-{
- struct native_probe *nprobe;
- enum native_probe_result res;
- EGLint score;
-
- nprobe = egl_g3d_get_probe(drv, dpy);
- res = native_get_probe_result(nprobe);
-
- switch (res) {
- case NATIVE_PROBE_UNKNOWN:
- default:
- score = 0;
- break;
- case NATIVE_PROBE_FALLBACK:
- score = 40;
- break;
- case NATIVE_PROBE_SUPPORTED:
- score = 50;
- break;
- case NATIVE_PROBE_EXACT:
- score = 100;
- break;
- }
-
- return score;
-}
-
-static void
-egl_g3d_unload(_EGLDriver *drv)
-{
- struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
-
- egl_g3d_destroy_probe(drv, NULL);
- free(gdrv);
-}
-
-_EGLDriver *
-_eglMain(const char *args)
-{
- static char driver_name[64];
- struct egl_g3d_driver *gdrv;
-
- snprintf(driver_name, sizeof(driver_name),
- "Gallium/%s", native_get_name());
-
- gdrv = CALLOC_STRUCT(egl_g3d_driver);
- if (!gdrv)
- return NULL;
-
- _eglInitDriverFallbacks(&gdrv->base);
-
- gdrv->base.API.Initialize = egl_g3d_initialize;
- gdrv->base.API.Terminate = egl_g3d_terminate;
- gdrv->base.API.CreateContext = egl_g3d_create_context;
- gdrv->base.API.DestroyContext = egl_g3d_destroy_context;
- gdrv->base.API.CreateWindowSurface = egl_g3d_create_window_surface;
- gdrv->base.API.CreatePixmapSurface = egl_g3d_create_pixmap_surface;
- gdrv->base.API.CreatePbufferSurface = egl_g3d_create_pbuffer_surface;
- gdrv->base.API.DestroySurface = egl_g3d_destroy_surface;
- gdrv->base.API.MakeCurrent = egl_g3d_make_current;
- gdrv->base.API.SwapBuffers = egl_g3d_swap_buffers;
- gdrv->base.API.CopyBuffers = egl_g3d_copy_buffers;
- gdrv->base.API.WaitClient = egl_g3d_wait_client;
- gdrv->base.API.WaitNative = egl_g3d_wait_native;
- gdrv->base.API.GetProcAddress = egl_g3d_get_proc_address;
-
- 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.Probe = egl_g3d_probe;
- gdrv->base.Unload = egl_g3d_unload;
-
- /* the key is " EGL G3D" */
- gdrv->probe_key = 0x0E61063D;
-
- return &gdrv->base;
-}
+++ /dev/null
-/*
- * Mesa 3-D graphics library
- * Version: 7.8
- *
- * Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org>
- *
- * 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
- * BRIAN PAUL 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.
- */
-
-#ifndef _EGL_G3D_H_
-#define _EGL_G3D_H_
-
-#include "pipe/p_compiler.h"
-#include "pipe/p_screen.h"
-#include "pipe/p_context.h"
-#include "pipe/p_format.h"
-#include "egldriver.h"
-#include "egldisplay.h"
-#include "eglcontext.h"
-#include "eglsurface.h"
-#include "eglconfig.h"
-#include "eglscreen.h"
-#include "eglmode.h"
-
-#include "native.h"
-#include "egl_st.h"
-
-struct egl_g3d_driver {
- _EGLDriver base;
- const struct egl_g3d_st *stapis[NUM_EGL_G3D_STS];
- EGLint api_mask;
-
- EGLint probe_key;
-};
-
-struct egl_g3d_display {
- struct native_display *native;
-};
-
-struct egl_g3d_buffer {
- struct st_framebuffer *st_fb;
- uint attachment_mask;
-};
-
-struct egl_g3d_context {
- _EGLContext base;
-
- const struct egl_g3d_st *stapi;
- struct pipe_context *pipe;
-
- struct st_context *st_ctx;
- EGLBoolean force_validate;
- struct egl_g3d_buffer draw, read;
-};
-
-struct egl_g3d_surface {
- _EGLSurface base;
- struct native_surface *native;
- enum native_attachment render_att;
- struct pipe_surface *render_surface;
- unsigned int sequence_number;
-};
-
-struct egl_g3d_config {
- _EGLConfig base;
- 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)
-{
- return (struct egl_g3d_driver *) drv;
-}
-
-static INLINE struct egl_g3d_display *
-egl_g3d_display(_EGLDisplay *dpy)
-{
- /* note that it is not direct casting */
- return (struct egl_g3d_display *) dpy->DriverData;
-}
-
-static INLINE struct egl_g3d_context *
-egl_g3d_context(_EGLContext *ctx)
-{
- return (struct egl_g3d_context *) ctx;
-}
-
-static INLINE struct egl_g3d_surface *
-egl_g3d_surface(_EGLSurface *surf)
-{
- return (struct egl_g3d_surface *) surf;
-}
-
-static INLINE struct egl_g3d_config *
-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_ */
+++ /dev/null
-/*
- * Mesa 3-D graphics library
- * Version: 7.8
- *
- * Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org>
- *
- * 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
- * BRIAN PAUL 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.
- */
-
-#include <dlfcn.h>
-#include "pipe/p_compiler.h"
-#include "util/u_memory.h"
-#include "egllog.h"
-#include "EGL/egl.h" /* for EGL_api_BIT */
-
-#include "egl_st.h"
-
-#ifndef HAVE_DLADDR
-#define HAVE_DLADDR 1
-#endif
-
-#if HAVE_DLADDR
-
-static const char *
-egl_g3d_st_names[] = {
-#define ST_PUBLIC(name, ...) #name,
-#include "st_public_tmp.h"
- NULL
-};
-
-static boolean
-egl_g3d_fill_st(struct egl_g3d_st *stapi, void *sym)
-{
- st_proc *procs = (st_proc *) stapi;
- void *handle;
- Dl_info info;
- const char **name;
-
- if (!dladdr(sym, &info))
- return FALSE;
- handle = dlopen(info.dli_fname, RTLD_LAZY | RTLD_LOCAL | RTLD_NODELETE);
- if (!handle)
- return FALSE;
-
- for (name = egl_g3d_st_names; *name; name++) {
- st_proc proc = (st_proc) dlsym(handle, *name);
- if (!proc) {
- _eglLog(_EGL_WARNING, "%s is missing in %s", *name, info.dli_fname);
- memset(stapi, 0, sizeof(*stapi));
- dlclose(handle);
- return FALSE;
- }
- *procs++ = proc;
- }
-
- dlclose(handle);
- return TRUE;
-}
-
-#else /* HAVE_DLADDR */
-
-static boolean
-egl_g3d_fill_st(struct egl_g3d_st *stapi, void *sym)
-{
-#define ST_PUBLIC(name, ...) stapi->name = name;
-#include "st_public_tmp.h"
- return TRUE;
-}
-
-#endif /* HAVE_DLADDR */
-
-static boolean
-egl_g3d_init_st(struct egl_g3d_st *stapi, const char *api)
-{
- void *handle, *sym;
- boolean res = FALSE;
-
- /* already initialized */
- if (stapi->st_notify_swapbuffers != NULL)
- return TRUE;
-
- handle = dlopen(NULL, RTLD_LAZY | RTLD_LOCAL);
- if (!handle)
- return FALSE;
-
- sym = dlsym(handle, api);
- if (sym && egl_g3d_fill_st(stapi, sym))
- res = TRUE;
-
- dlclose(handle);
- return res;
-}
-
-static struct {
- const char *symbol;
- EGLint api_bit;
-} egl_g3d_st_info[NUM_EGL_G3D_STS] = {
- { "st_api_OpenGL_ES1", EGL_OPENGL_ES_BIT },
- { "st_api_OpenVG", EGL_OPENVG_BIT },
- { "st_api_OpenGL_ES2", EGL_OPENGL_ES2_BIT },
- { "st_api_OpenGL", EGL_OPENGL_BIT },
-};
-
-const struct egl_g3d_st *
-egl_g3d_get_st(enum egl_g3d_st_api api)
-{
- static struct egl_g3d_st all_trackers[NUM_EGL_G3D_STS];
-
- if (egl_g3d_init_st(&all_trackers[api], egl_g3d_st_info[api].symbol)) {
- all_trackers[api].api_bit = egl_g3d_st_info[api].api_bit;
- return &all_trackers[api];
- }
- else {
- return NULL;
- }
-}
+++ /dev/null
-/*
- * Mesa 3-D graphics library
- * Version: 7.8
- *
- * Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org>
- *
- * 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
- * BRIAN PAUL 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.
- */
-
-#ifndef _EGL_ST_H_
-#define _EGL_ST_H_
-
-#include "GL/gl.h" /* for GL types */
-#include "GL/internal/glcore.h" /* for __GLcontextModes */
-
-#include "pipe/p_compiler.h"
-#include "pipe/p_format.h"
-#include "pipe/p_context.h"
-
-/* avoid calling st functions directly */
-#if 1
-
-#define ST_SURFACE_FRONT_LEFT 0
-#define ST_SURFACE_BACK_LEFT 1
-#define ST_SURFACE_FRONT_RIGHT 2
-#define ST_SURFACE_BACK_RIGHT 3
-
-#define ST_TEXTURE_2D 0x2
-
-struct st_context;
-struct st_framebuffer;
-typedef void (*st_proc)();
-
-#else
-#include "state_tracker/st_public.h"
-#endif
-
-/* remember to update egl_g3d_get_st() when update the enums */
-enum egl_g3d_st_api {
- EGL_G3D_ST_OPENGL_ES = 0,
- EGL_G3D_ST_OPENVG,
- EGL_G3D_ST_OPENGL_ES2,
- EGL_G3D_ST_OPENGL,
-
- NUM_EGL_G3D_STS
-};
-
-struct egl_g3d_st {
-#define ST_PUBLIC(name, ret, ...) ret (*name)(__VA_ARGS__);
-#include "st_public_tmp.h"
- /* fields must be added here */
- EGLint api_bit;
-};
-
-const struct egl_g3d_st *
-egl_g3d_get_st(enum egl_g3d_st_api api);
-
-#endif /* _EGL_ST_H_ */
+++ /dev/null
-/*
- * Mesa 3-D graphics library
- * Version: 7.8
- *
- * Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org>
- *
- * 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
- * BRIAN PAUL 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.
- */
-
-#ifndef _NATIVE_H_
-#define _NATIVE_H_
-
-#include "EGL/egl.h" /* for EGL native types */
-#include "GL/gl.h" /* for GL types needed by __GLcontextModes */
-#include "GL/internal/glcore.h" /* for __GLcontextModes */
-
-#include "pipe/p_compiler.h"
-#include "pipe/p_screen.h"
-#include "pipe/p_context.h"
-#include "pipe/p_state.h"
-
-/**
- * Only color buffers are listed. The others are allocated privately through,
- * for example, st_renderbuffer_alloc_storage().
- */
-enum native_attachment {
- NATIVE_ATTACHMENT_FRONT_LEFT,
- NATIVE_ATTACHMENT_BACK_LEFT,
- NATIVE_ATTACHMENT_FRONT_RIGHT,
- NATIVE_ATTACHMENT_BACK_RIGHT,
-
- NUM_NATIVE_ATTACHMENTS
-};
-
-/**
- * Enumerations for probe results.
- */
-enum native_probe_result {
- NATIVE_PROBE_UNKNOWN,
- NATIVE_PROBE_FALLBACK,
- NATIVE_PROBE_SUPPORTED,
- NATIVE_PROBE_EXACT,
-};
-
-/**
- * A probe object for display probe.
- */
-struct native_probe {
- int magic;
- EGLNativeDisplayType display;
- void *data;
-
- void (*destroy)(struct native_probe *nprobe);
-};
-
-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.
- */
- boolean (*flush_frontbuffer)(struct native_surface *nsurf);
-
- /**
- * Validate the buffers of the surface. textures, if not NULL, points to an
- * array of size NUM_NATIVE_ATTACHMENTS and the returned textures are owned
- * by the caller. A sequence number is also returned. The caller can use
- * it to check if anything has changed since the last call. Any of the
- * pointers may be NULL and it indicates the caller has no interest in those
- * values.
- *
- * If this function is called multiple times with different attachment
- * masks, those not listed in the latest call might be destroyed. This
- * behavior might change in the future.
- */
- boolean (*validate)(struct native_surface *nsurf, uint attachment_mask,
- unsigned int *seq_num, struct pipe_texture **textures,
- int *width, int *height);
-
- /**
- * Wait until all native commands affecting the surface has been executed.
- */
- void (*wait)(struct native_surface *nsurf);
-};
-
-struct native_config {
- /* __GLcontextModes should go away some day */
- __GLcontextModes mode;
- enum pipe_format color_format;
- enum pipe_format depth_format;
- enum pipe_format stencil_format;
-
- /* treat it as an additional flag to mode.drawableType */
- boolean scanout_bit;
-};
-
-struct native_connector {
- int dummy;
-};
-
-struct native_mode {
- const char *desc;
- int width, height;
- int refresh_rate;
-};
-
-struct native_display_modeset;
-
-/**
- * A pipe winsys abstracts the OS. A pipe screen abstracts the graphcis
- * hardware. A native display consists of a pipe winsys, a pipe screen, and
- * the native display server.
- */
-struct native_display {
- /**
- * The pipe screen of the native display.
- *
- * Note that the "flush_frontbuffer" and "update_buffer" callbacks will be
- * overridden.
- */
- struct pipe_screen *screen;
-
- void (*destroy)(struct native_display *ndpy);
-
- /**
- * Get the supported configs. The configs are owned by the display, but
- * the returned array should be free()ed.
- *
- * The configs will be converted to EGL config by
- * _eglConfigFromContextModesRec and validated by _eglValidateConfig.
- * Those failing to pass the test will be skipped.
- */
- const struct native_config **(*get_configs)(struct native_display *ndpy,
- int *num_configs);
-
- /**
- * Test if a pixmap is supported by the given config. Required unless no
- * config has GLX_PIXMAP_BIT set.
- *
- * This function is usually called to find a config that supports a given
- * pixmap. Thus, it is usually called with the same pixmap in a row.
- */
- boolean (*is_pixmap_supported)(struct native_display *ndpy,
- EGLNativePixmapType pix,
- const struct native_config *nconf);
-
- /**
- * Create a pipe context.
- */
- struct pipe_context *(*create_context)(struct native_display *ndpy,
- void *context_private);
-
- /**
- * Create a window surface. Required unless no config has GLX_WINDOW_BIT
- * set.
- */
- struct native_surface *(*create_window_surface)(struct native_display *ndpy,
- EGLNativeWindowType win,
- const struct native_config *nconf);
-
- /**
- * Create a pixmap surface. Required unless no config has GLX_PIXMAP_BIT
- * set.
- */
- struct native_surface *(*create_pixmap_surface)(struct native_display *ndpy,
- EGLNativePixmapType pix,
- const struct native_config *nconf);
-
- /**
- * Create a pbuffer surface. Required unless no config has GLX_PBUFFER_BIT
- * set.
- */
- struct native_surface *(*create_pbuffer_surface)(struct native_display *ndpy,
- const struct native_config *nconf,
- uint width, uint height);
-
- const struct native_display_modeset *modeset;
-};
-
-/**
- * Mode setting interface of the native display. It exposes the mode setting
- * capabilities of the underlying graphics hardware.
- */
-struct native_display_modeset {
- /**
- * Get the available physical connectors and the number of CRTCs.
- */
- const struct native_connector **(*get_connectors)(struct native_display *ndpy,
- int *num_connectors,
- int *num_crtcs);
-
- /**
- * Get the current supported modes of a connector. The returned modes may
- * change every time this function is called and those from previous calls
- * might become invalid.
- */
- const struct native_mode **(*get_modes)(struct native_display *ndpy,
- const struct native_connector *nconn,
- int *num_modes);
-
- /**
- * Create a scan-out surface. Required unless no config has
- * GLX_SCREEN_BIT_MESA set.
- */
- struct native_surface *(*create_scanout_surface)(struct native_display *ndpy,
- const struct native_config *nconf,
- uint width, uint height);
-
- /**
- * Program the CRTC to output the surface to the given connectors with the
- * given mode. When surface is not given, the CRTC is disabled.
- *
- * This interface does not export a way to query capabilities of the CRTCs.
- * The native display usually needs to dynamically map the index to a CRTC
- * that supports the given connectors.
- */
- boolean (*program)(struct native_display *ndpy, int crtc_idx,
- struct native_surface *nsurf, uint x, uint y,
- const struct native_connector **nconns, int num_nconns,
- const struct native_mode *nmode);
-};
-
-/**
- * Test whether an attachment is set in the mask.
- */
-static INLINE boolean
-native_attachment_mask_test(uint mask, enum native_attachment att)
-{
- return !!(mask & (1 << att));
-}
-
-/**
- * Return a probe object for the given display.
- *
- * Note that the returned object may be cached and used by different native
- * display modules. It allows fast probing when multiple modules probe the
- * same display.
- */
-struct native_probe *
-native_create_probe(EGLNativeDisplayType dpy);
-
-/**
- * Probe the probe object.
- */
-enum native_probe_result
-native_get_probe_result(struct native_probe *nprobe);
-
-const char *
-native_get_name(void);
-
-struct native_display *
-native_create_display(EGLNativeDisplayType dpy);
-
-#endif /* _NATIVE_H_ */
+++ /dev/null
-ST_PUBLIC(st_create_context, struct st_context *, struct pipe_context *pipe, const __GLcontextModes *visual, struct st_context *share)
-ST_PUBLIC(st_destroy_context, void, struct st_context *st)
-ST_PUBLIC(st_copy_context_state, void, struct st_context *dst, struct st_context *src, uint mask)
-ST_PUBLIC(st_create_framebuffer, struct st_framebuffer *, const __GLcontextModes *visual, enum pipe_format colorFormat, enum pipe_format depthFormat, enum pipe_format stencilFormat, uint width, uint height, void *privateData)
-ST_PUBLIC(st_resize_framebuffer, void, struct st_framebuffer *stfb, uint width, uint height)
-ST_PUBLIC(st_set_framebuffer_surface, void, struct st_framebuffer *stfb, uint surfIndex, struct pipe_surface *surf)
-ST_PUBLIC(st_get_framebuffer_dimensions, void, struct st_framebuffer *stfb, uint *width, uint *height)
-ST_PUBLIC(st_get_framebuffer_surface, int, struct st_framebuffer *stfb, uint surfIndex, struct pipe_surface **surface)
-ST_PUBLIC(st_get_framebuffer_texture, int, struct st_framebuffer *stfb, uint surfIndex, struct pipe_texture **texture)
-ST_PUBLIC(st_framebuffer_private, void *, struct st_framebuffer *stfb)
-ST_PUBLIC(st_unreference_framebuffer, void, struct st_framebuffer *stfb)
-ST_PUBLIC(st_make_current, GLboolean, struct st_context *st, struct st_framebuffer *draw, struct st_framebuffer *read)
-ST_PUBLIC(st_get_current, struct st_context *, void)
-ST_PUBLIC(st_flush, void, struct st_context *st, uint pipeFlushFlags, struct pipe_fence_handle **fence)
-ST_PUBLIC(st_finish, void, struct st_context *st)
-ST_PUBLIC(st_notify_swapbuffers, void, struct st_framebuffer *stfb)
-ST_PUBLIC(st_bind_texture_surface, int, struct pipe_surface *ps, int target, int level, enum pipe_format format)
-ST_PUBLIC(st_unbind_texture_surface, int, struct pipe_surface *ps, int target, int level)
-ST_PUBLIC(st_get_proc_address, st_proc, const char *procname)
-#undef ST_PUBLIC
+++ /dev/null
-/*
- * Mesa 3-D graphics library
- * Version: 7.8
- *
- * Copyright (C) 2010 Chia-I Wu <olv@0xlab.org>
- *
- * 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
- * BRIAN PAUL 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.
- */
-
-#include <string.h>
-
-#include "pipe/p_screen.h"
-#include "pipe/p_context.h"
-#include "util/u_debug.h"
-#include "util/u_memory.h"
-#include "egllog.h"
-
-#include "native_kms.h"
-
-static boolean
-kms_surface_validate(struct native_surface *nsurf, uint attachment_mask,
- unsigned int *seq_num, struct pipe_texture **textures,
- int *width, int *height)
-{
- struct kms_surface *ksurf = kms_surface(nsurf);
- struct kms_display *kdpy = ksurf->kdpy;
- struct pipe_screen *screen = kdpy->base.screen;
- struct pipe_texture templ, *ptex;
- int att;
-
- if (attachment_mask) {
- memset(&templ, 0, sizeof(templ));
- templ.target = PIPE_TEXTURE_2D;
- templ.last_level = 0;
- templ.width0 = ksurf->width;
- templ.height0 = ksurf->height;
- templ.depth0 = 1;
- templ.format = ksurf->color_format;
- templ.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET;
- if (ksurf->type == KMS_SURFACE_TYPE_SCANOUT)
- templ.tex_usage |= PIPE_TEXTURE_USAGE_PRIMARY;
- }
-
- /* create textures */
- for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) {
- /* delay the allocation */
- if (!native_attachment_mask_test(attachment_mask, att))
- continue;
-
- ptex = ksurf->textures[att];
- if (!ptex) {
- ptex = screen->texture_create(screen, &templ);
- ksurf->textures[att] = ptex;
- }
-
- if (textures) {
- textures[att] = NULL;
- pipe_texture_reference(&textures[att], ptex);
- }
- }
-
- if (seq_num)
- *seq_num = ksurf->sequence_number;
- if (width)
- *width = ksurf->width;
- if (height)
- *height = ksurf->height;
-
- return TRUE;
-}
-
-/**
- * Add textures as DRM framebuffers.
- */
-static boolean
-kms_surface_init_framebuffers(struct native_surface *nsurf, boolean need_back)
-{
- struct kms_surface *ksurf = kms_surface(nsurf);
- struct kms_display *kdpy = ksurf->kdpy;
- int num_framebuffers = (need_back) ? 2 : 1;
- int i, err;
-
- for (i = 0; i < num_framebuffers; i++) {
- struct kms_framebuffer *fb;
- enum native_attachment natt;
- unsigned int handle, stride;
- uint block_bits;
-
- if (i == 0) {
- fb = &ksurf->front_fb;
- natt = NATIVE_ATTACHMENT_FRONT_LEFT;
- }
- else {
- fb = &ksurf->back_fb;
- natt = NATIVE_ATTACHMENT_BACK_LEFT;
- }
-
- if (!fb->texture) {
- /* make sure the texture has been allocated */
- kms_surface_validate(&ksurf->base, 1 << natt, NULL, NULL, NULL, NULL);
- if (!ksurf->textures[natt])
- return FALSE;
-
- pipe_texture_reference(&fb->texture, ksurf->textures[natt]);
- }
-
- /* already initialized */
- if (fb->buffer_id)
- continue;
-
- /* TODO detect the real value */
- fb->is_passive = TRUE;
-
- if (!kdpy->api->local_handle_from_texture(kdpy->api,
- kdpy->base.screen, fb->texture, &stride, &handle))
- return FALSE;
-
- block_bits = util_format_get_blocksizebits(ksurf->color_format);
- err = drmModeAddFB(kdpy->fd, ksurf->width, ksurf->height,
- block_bits, block_bits, stride, handle, &fb->buffer_id);
- if (err) {
- fb->buffer_id = 0;
- return FALSE;
- }
- }
-
- return TRUE;
-}
-
-static boolean
-kms_surface_flush_frontbuffer(struct native_surface *nsurf)
-{
-#ifdef DRM_MODE_FEATURE_DIRTYFB
- struct kms_surface *ksurf = kms_surface(nsurf);
- struct kms_display *kdpy = ksurf->kdpy;
-
- /* pbuffer is private */
- if (ksurf->type == KMS_SURFACE_TYPE_PBUFFER)
- return TRUE;
-
- if (ksurf->front_fb.is_passive)
- drmModeDirtyFB(kdpy->fd, ksurf->front_fb.buffer_id, NULL, 0);
-#endif
-
- return TRUE;
-}
-
-static boolean
-kms_surface_swap_buffers(struct native_surface *nsurf)
-{
- struct kms_surface *ksurf = kms_surface(nsurf);
- struct kms_crtc *kcrtc = &ksurf->current_crtc;
- struct kms_display *kdpy = ksurf->kdpy;
- struct kms_framebuffer tmp_fb;
- struct pipe_texture *tmp_texture;
- int err;
-
- /* pbuffer is private */
- if (ksurf->type == KMS_SURFACE_TYPE_PBUFFER)
- return TRUE;
-
- if (!ksurf->back_fb.buffer_id) {
- if (!kms_surface_init_framebuffers(&ksurf->base, TRUE))
- return FALSE;
- }
-
- if (ksurf->is_shown && kcrtc->crtc) {
- err = drmModeSetCrtc(kdpy->fd, kcrtc->crtc->crtc_id,
- ksurf->back_fb.buffer_id, kcrtc->crtc->x, kcrtc->crtc->y,
- kcrtc->connectors, kcrtc->num_connectors, &kcrtc->crtc->mode);
- if (err)
- return FALSE;
- }
-
- /* swap the buffers */
- tmp_fb = ksurf->front_fb;
- ksurf->front_fb = ksurf->back_fb;
- ksurf->back_fb = tmp_fb;
-
- tmp_texture = ksurf->textures[NATIVE_ATTACHMENT_FRONT_LEFT];
- ksurf->textures[NATIVE_ATTACHMENT_FRONT_LEFT] =
- ksurf->textures[NATIVE_ATTACHMENT_BACK_LEFT];
- ksurf->textures[NATIVE_ATTACHMENT_BACK_LEFT] = tmp_texture;
-
- /* the front/back textures are swapped */
- ksurf->sequence_number++;
-
- return TRUE;
-}
-
-static void
-kms_surface_wait(struct native_surface *nsurf)
-{
- /* no-op */
-}
-
-static void
-kms_surface_destroy(struct native_surface *nsurf)
-{
- struct kms_surface *ksurf = kms_surface(nsurf);
- int i;
-
- if (ksurf->current_crtc.crtc)
- drmModeFreeCrtc(ksurf->current_crtc.crtc);
-
- if (ksurf->front_fb.buffer_id)
- drmModeRmFB(ksurf->kdpy->fd, ksurf->front_fb.buffer_id);
- pipe_texture_reference(&ksurf->front_fb.texture, NULL);
-
- if (ksurf->back_fb.buffer_id)
- drmModeRmFB(ksurf->kdpy->fd, ksurf->back_fb.buffer_id);
- pipe_texture_reference(&ksurf->back_fb.texture, NULL);
-
- for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) {
- struct pipe_texture *ptex = ksurf->textures[i];
- pipe_texture_reference(&ptex, NULL);
- }
-
- free(ksurf);
-}
-
-static struct kms_surface *
-kms_display_create_surface(struct native_display *ndpy,
- enum kms_surface_type type,
- const struct native_config *nconf,
- uint width, uint height)
-{
- struct kms_display *kdpy = kms_display(ndpy);
- struct kms_config *kconf = kms_config(nconf);
- struct kms_surface *ksurf;
-
- ksurf = CALLOC_STRUCT(kms_surface);
- if (!ksurf)
- return NULL;
-
- ksurf->kdpy = kdpy;
- ksurf->type = type;
- ksurf->color_format = kconf->base.color_format;
- ksurf->width = width;
- ksurf->height = height;
-
- ksurf->base.destroy = kms_surface_destroy;
- ksurf->base.swap_buffers = kms_surface_swap_buffers;
- ksurf->base.flush_frontbuffer = kms_surface_flush_frontbuffer;
- ksurf->base.validate = kms_surface_validate;
- ksurf->base.wait = kms_surface_wait;
-
- return ksurf;
-}
-
-/**
- * Choose a CRTC that supports all given connectors.
- */
-static uint32_t
-kms_display_choose_crtc(struct native_display *ndpy,
- uint32_t *connectors, int num_connectors)
-{
- struct kms_display *kdpy = kms_display(ndpy);
- int idx;
-
- for (idx = 0; idx < kdpy->resources->count_crtcs; idx++) {
- boolean found_crtc = TRUE;
- int i, j;
-
- for (i = 0; i < num_connectors; i++) {
- drmModeConnectorPtr connector;
- int encoder_idx = -1;
-
- connector = drmModeGetConnector(kdpy->fd, connectors[i]);
- if (!connector) {
- found_crtc = FALSE;
- break;
- }
-
- /* find an encoder the CRTC supports */
- for (j = 0; j < connector->count_encoders; j++) {
- drmModeEncoderPtr encoder =
- drmModeGetEncoder(kdpy->fd, connector->encoders[j]);
- if (encoder->possible_crtcs & (1 << idx)) {
- encoder_idx = j;
- break;
- }
- drmModeFreeEncoder(encoder);
- }
-
- drmModeFreeConnector(connector);
- if (encoder_idx < 0) {
- found_crtc = FALSE;
- break;
- }
- }
-
- if (found_crtc)
- break;
- }
-
- if (idx >= kdpy->resources->count_crtcs) {
- _eglLog(_EGL_WARNING,
- "failed to find a CRTC that supports the given %d connectors",
- num_connectors);
- return 0;
- }
-
- return kdpy->resources->crtcs[idx];
-}
-
-/**
- * Remember the original CRTC status and set the CRTC
- */
-static boolean
-kms_display_set_crtc(struct native_display *ndpy, int crtc_idx,
- uint32_t buffer_id, uint32_t x, uint32_t y,
- uint32_t *connectors, int num_connectors,
- drmModeModeInfoPtr mode)
-{
- struct kms_display *kdpy = kms_display(ndpy);
- struct kms_crtc *kcrtc = &kdpy->saved_crtcs[crtc_idx];
- uint32_t crtc_id;
- int err;
-
- if (kcrtc->crtc) {
- crtc_id = kcrtc->crtc->crtc_id;
- }
- else {
- int count = 0, i;
-
- /*
- * Choose the CRTC once. It could be more dynamic, but let's keep it
- * simple for now.
- */
- crtc_id = kms_display_choose_crtc(&kdpy->base,
- connectors, num_connectors);
-
- /* save the original CRTC status */
- kcrtc->crtc = drmModeGetCrtc(kdpy->fd, crtc_id);
- if (!kcrtc->crtc)
- return FALSE;
-
- for (i = 0; i < kdpy->num_connectors; i++) {
- struct kms_connector *kconn = &kdpy->connectors[i];
- drmModeConnectorPtr connector = kconn->connector;
- drmModeEncoderPtr encoder;
-
- encoder = drmModeGetEncoder(kdpy->fd, connector->encoder_id);
- if (encoder) {
- if (encoder->crtc_id == crtc_id) {
- kcrtc->connectors[count++] = connector->connector_id;
- if (count >= Elements(kcrtc->connectors))
- break;
- }
- drmModeFreeEncoder(encoder);
- }
- }
-
- kcrtc->num_connectors = count;
- }
-
- err = drmModeSetCrtc(kdpy->fd, crtc_id, buffer_id, x, y,
- connectors, num_connectors, mode);
- if (err) {
- drmModeFreeCrtc(kcrtc->crtc);
- kcrtc->crtc = NULL;
- kcrtc->num_connectors = 0;
-
- return FALSE;
- }
-
- return TRUE;
-}
-
-static boolean
-kms_display_program(struct native_display *ndpy, int crtc_idx,
- struct native_surface *nsurf, uint x, uint y,
- const struct native_connector **nconns, int num_nconns,
- const struct native_mode *nmode)
-{
- struct kms_display *kdpy = kms_display(ndpy);
- struct kms_surface *ksurf = kms_surface(nsurf);
- const struct kms_mode *kmode = kms_mode(nmode);
- uint32_t connector_ids[32];
- uint32_t buffer_id;
- drmModeModeInfo mode_tmp, *mode;
- int i;
-
- if (num_nconns > Elements(connector_ids)) {
- _eglLog(_EGL_WARNING, "too many connectors (%d)", num_nconns);
- num_nconns = Elements(connector_ids);
- }
-
- if (ksurf) {
- if (!kms_surface_init_framebuffers(&ksurf->base, FALSE))
- return FALSE;
-
- buffer_id = ksurf->front_fb.buffer_id;
- /* the mode argument of drmModeSetCrtc is not constified */
- mode_tmp = kmode->mode;
- mode = &mode_tmp;
- }
- else {
- /* disable the CRTC */
- buffer_id = 0;
- mode = NULL;
- num_nconns = 0;
- }
-
- for (i = 0; i < num_nconns; i++) {
- struct kms_connector *kconn = kms_connector(nconns[i]);
- connector_ids[i] = kconn->connector->connector_id;
- }
-
- if (!kms_display_set_crtc(&kdpy->base, crtc_idx, buffer_id, x, y,
- connector_ids, num_nconns, mode)) {
- _eglLog(_EGL_WARNING, "failed to set CRTC %d", crtc_idx);
-
- return FALSE;
- }
-
- if (kdpy->shown_surfaces[crtc_idx])
- kdpy->shown_surfaces[crtc_idx]->is_shown = FALSE;
- kdpy->shown_surfaces[crtc_idx] = ksurf;
-
- /* remember the settings for buffer swapping */
- if (ksurf) {
- uint32_t crtc_id = kdpy->saved_crtcs[crtc_idx].crtc->crtc_id;
- struct kms_crtc *kcrtc = &ksurf->current_crtc;
-
- if (kcrtc->crtc)
- drmModeFreeCrtc(kcrtc->crtc);
- kcrtc->crtc = drmModeGetCrtc(kdpy->fd, crtc_id);
-
- assert(num_nconns < Elements(kcrtc->connectors));
- memcpy(kcrtc->connectors, connector_ids,
- sizeof(*connector_ids) * num_nconns);
- kcrtc->num_connectors = num_nconns;
-
- ksurf->is_shown = TRUE;
- }
-
- return TRUE;
-}
-
-static const struct native_mode **
-kms_display_get_modes(struct native_display *ndpy,
- const struct native_connector *nconn,
- int *num_modes)
-{
- struct kms_display *kdpy = kms_display(ndpy);
- struct kms_connector *kconn = kms_connector(nconn);
- const struct native_mode **nmodes_return;
- int count, i;
-
- /* delete old data */
- if (kconn->connector) {
- drmModeFreeConnector(kconn->connector);
- free(kconn->kms_modes);
-
- kconn->connector = NULL;
- kconn->kms_modes = NULL;
- kconn->num_modes = 0;
- }
-
- /* detect again */
- kconn->connector = drmModeGetConnector(kdpy->fd, kconn->connector_id);
- if (!kconn->connector)
- return NULL;
-
- count = kconn->connector->count_modes;
- kconn->kms_modes = calloc(count, sizeof(*kconn->kms_modes));
- if (!kconn->kms_modes) {
- drmModeFreeConnector(kconn->connector);
- kconn->connector = NULL;
-
- return NULL;
- }
-
- for (i = 0; i < count; i++) {
- struct kms_mode *kmode = &kconn->kms_modes[i];
- drmModeModeInfoPtr mode = &kconn->connector->modes[i];
-
- kmode->mode = *mode;
-
- kmode->base.desc = kmode->mode.name;
- kmode->base.width = kmode->mode.hdisplay;
- kmode->base.height = kmode->mode.vdisplay;
- kmode->base.refresh_rate = kmode->mode.vrefresh / 1000;
- }
-
- nmodes_return = malloc(count * sizeof(*nmodes_return));
- if (nmodes_return) {
- for (i = 0; i < count; i++)
- nmodes_return[i] = &kconn->kms_modes[i].base;
- if (num_modes)
- *num_modes = count;
- }
-
- return nmodes_return;
-}
-
-static const struct native_connector **
-kms_display_get_connectors(struct native_display *ndpy, int *num_connectors,
- int *num_crtc)
-{
- struct kms_display *kdpy = kms_display(ndpy);
- const struct native_connector **connectors;
- int i;
-
- if (!kdpy->connectors) {
- kdpy->connectors =
- calloc(kdpy->resources->count_connectors, sizeof(*kdpy->connectors));
- if (!kdpy->connectors)
- return NULL;
-
- for (i = 0; i < kdpy->resources->count_connectors; i++) {
- struct kms_connector *kconn = &kdpy->connectors[i];
-
- kconn->connector_id = kdpy->resources->connectors[i];
- /* kconn->connector is allocated when the modes are asked */
- }
-
- kdpy->num_connectors = kdpy->resources->count_connectors;
- }
-
- connectors = malloc(kdpy->num_connectors * sizeof(*connectors));
- if (connectors) {
- for (i = 0; i < kdpy->num_connectors; i++)
- connectors[i] = &kdpy->connectors[i].base;
- if (num_connectors)
- *num_connectors = kdpy->num_connectors;
- }
-
- if (num_crtc)
- *num_crtc = kdpy->resources->count_crtcs;
-
- return connectors;
-}
-
-static struct native_surface *
-kms_display_create_scanout_surface(struct native_display *ndpy,
- const struct native_config *nconf,
- uint width, uint height)
-{
- struct kms_surface *ksurf;
-
- ksurf = kms_display_create_surface(ndpy,
- KMS_SURFACE_TYPE_SCANOUT, nconf, width, height);
- return &ksurf->base;
-}
-
-static struct native_surface *
-kms_display_create_pbuffer_surface(struct native_display *ndpy,
- const struct native_config *nconf,
- uint width, uint height)
-{
- struct kms_surface *ksurf;
-
- ksurf = kms_display_create_surface(ndpy,
- KMS_SURFACE_TYPE_PBUFFER, nconf, width, height);
- return &ksurf->base;
-}
-
-static struct pipe_context *
-kms_display_create_context(struct native_display *ndpy, void *context_private)
-{
- struct kms_display *kdpy = kms_display(ndpy);
- struct pipe_context *pctx;
-
- pctx = kdpy->api->create_context(kdpy->api, kdpy->base.screen);
- if (pctx)
- pctx->priv = context_private;
- return pctx;
-}
-
-static boolean
-kms_display_is_format_supported(struct native_display *ndpy,
- enum pipe_format fmt, boolean is_color)
-{
- return ndpy->screen->is_format_supported(ndpy->screen,
- fmt, PIPE_TEXTURE_2D,
- (is_color) ? PIPE_TEXTURE_USAGE_RENDER_TARGET :
- PIPE_TEXTURE_USAGE_DEPTH_STENCIL, 0);
-}
-
-static const struct native_config **
-kms_display_get_configs(struct native_display *ndpy, int *num_configs)
-{
- struct kms_display *kdpy = kms_display(ndpy);
- const struct native_config **configs;
-
- /* first time */
- if (!kdpy->config) {
- struct native_config *nconf;
- enum pipe_format format;
-
- kdpy->config = calloc(1, sizeof(*kdpy->config));
- if (!kdpy->config)
- return NULL;
-
- nconf = &kdpy->config->base;
-
- /* always double-buffered */
- nconf->mode.doubleBufferMode = TRUE;
-
- format = PIPE_FORMAT_A8R8G8B8_UNORM;
- if (!kms_display_is_format_supported(&kdpy->base, format, TRUE)) {
- format = PIPE_FORMAT_B8G8R8A8_UNORM;
- if (!kms_display_is_format_supported(&kdpy->base, format, TRUE))
- format = PIPE_FORMAT_NONE;
- }
- if (format == PIPE_FORMAT_NONE)
- return NULL;
-
- nconf->color_format = format;
- nconf->mode.redBits = 8;
- nconf->mode.greenBits = 8;
- nconf->mode.blueBits = 8;
- nconf->mode.alphaBits = 8;
- nconf->mode.rgbBits = 32;
-
- format = PIPE_FORMAT_S8Z24_UNORM;
- if (!kms_display_is_format_supported(&kdpy->base, format, FALSE)) {
- format = PIPE_FORMAT_Z24S8_UNORM;
- if (!kms_display_is_format_supported(&kdpy->base, format, FALSE))
- format = PIPE_FORMAT_NONE;
- }
- if (format != PIPE_FORMAT_NONE) {
- nconf->depth_format = format;
- nconf->stencil_format = format;
-
- nconf->mode.depthBits = 24;
- nconf->mode.stencilBits = 8;
- nconf->mode.haveDepthBuffer = TRUE;
- nconf->mode.haveStencilBuffer = TRUE;
- }
-
- nconf->scanout_bit = TRUE;
- nconf->mode.drawableType = GLX_PBUFFER_BIT;
- nconf->mode.swapMethod = GLX_SWAP_EXCHANGE_OML;
-
- nconf->mode.visualID = 0;
- nconf->mode.visualType = EGL_NONE;
-
- nconf->mode.renderType = GLX_RGBA_BIT;
- nconf->mode.rgbMode = TRUE;
- nconf->mode.xRenderable = FALSE;
- }
-
- configs = malloc(sizeof(*configs));
- if (configs) {
- configs[0] = &kdpy->config->base;
- if (num_configs)
- *num_configs = 1;
- }
-
- return configs;
-}
-
-static void
-kms_display_destroy(struct native_display *ndpy)
-{
- struct kms_display *kdpy = kms_display(ndpy);
- int i;
-
- if (kdpy->config)
- free(kdpy->config);
-
- if (kdpy->connectors) {
- for (i = 0; i < kdpy->num_connectors; i++) {
- struct kms_connector *kconn = &kdpy->connectors[i];
- if (kconn->connector) {
- drmModeFreeConnector(kconn->connector);
- free(kconn->kms_modes);
- }
- }
- free(kdpy->connectors);
- }
-
- if (kdpy->shown_surfaces)
- free(kdpy->shown_surfaces);
-
- if (kdpy->saved_crtcs) {
- for (i = 0; i < kdpy->resources->count_crtcs; i++) {
- struct kms_crtc *kcrtc = &kdpy->saved_crtcs[i];
-
- if (kcrtc->crtc) {
- /* restore crtc */
- drmModeSetCrtc(kdpy->fd, kcrtc->crtc->crtc_id,
- kcrtc->crtc->buffer_id, kcrtc->crtc->x, kcrtc->crtc->y,
- kcrtc->connectors, kcrtc->num_connectors,
- &kcrtc->crtc->mode);
-
- drmModeFreeCrtc(kcrtc->crtc);
- }
- }
- free(kdpy->saved_crtcs);
- }
-
- if (kdpy->resources)
- drmModeFreeResources(kdpy->resources);
-
- if (kdpy->base.screen)
- kdpy->base.screen->destroy(kdpy->base.screen);
-
- if (kdpy->fd >= 0)
- drmClose(kdpy->fd);
-
- if (kdpy->api)
- kdpy->api->destroy(kdpy->api);
- free(kdpy);
-}
-
-/**
- * Initialize KMS and pipe screen.
- */
-static boolean
-kms_display_init_screen(struct native_display *ndpy)
-{
- struct kms_display *kdpy = kms_display(ndpy);
- struct drm_create_screen_arg arg;
- int fd;
-
- fd = drmOpen(kdpy->api->name, NULL);
- if (fd < 0) {
- _eglLog(_EGL_WARNING, "failed to open DRM device");
- return FALSE;
- }
-
-#if 0
- if (drmSetMaster(fd)) {
- _eglLog(_EGL_WARNING, "failed to become DRM master");
- return FALSE;
- }
-#endif
-
- memset(&arg, 0, sizeof(arg));
- arg.mode = DRM_CREATE_NORMAL;
- kdpy->base.screen = kdpy->api->create_screen(kdpy->api, fd, &arg);
- if (!kdpy->base.screen) {
- _eglLog(_EGL_WARNING, "failed to create DRM screen");
- drmClose(fd);
- return FALSE;
- }
-
- kdpy->fd = fd;
-
- return TRUE;
-}
-
-static struct native_display_modeset kms_display_modeset = {
- .get_connectors = kms_display_get_connectors,
- .get_modes = kms_display_get_modes,
- .create_scanout_surface = kms_display_create_scanout_surface,
- .program = kms_display_program
-};
-
-static struct native_display *
-kms_create_display(EGLNativeDisplayType dpy, struct drm_api *api)
-{
- struct kms_display *kdpy;
-
- kdpy = CALLOC_STRUCT(kms_display);
- if (!kdpy)
- return NULL;
-
- kdpy->api = api;
- if (!kdpy->api) {
- _eglLog(_EGL_WARNING, "failed to create DRM API");
- free(kdpy);
- return NULL;
- }
-
- kdpy->fd = -1;
- if (!kms_display_init_screen(&kdpy->base)) {
- kms_display_destroy(&kdpy->base);
- return NULL;
- }
-
- /* resources are fixed, unlike crtc, connector, or encoder */
- kdpy->resources = drmModeGetResources(kdpy->fd);
- if (!kdpy->resources) {
- kms_display_destroy(&kdpy->base);
- return NULL;
- }
-
- kdpy->saved_crtcs =
- calloc(kdpy->resources->count_crtcs, sizeof(*kdpy->saved_crtcs));
- if (!kdpy->saved_crtcs) {
- kms_display_destroy(&kdpy->base);
- return NULL;
- }
-
- kdpy->shown_surfaces =
- calloc(kdpy->resources->count_crtcs, sizeof(*kdpy->shown_surfaces));
- if (!kdpy->shown_surfaces) {
- kms_display_destroy(&kdpy->base);
- return NULL;
- }
-
- kdpy->base.destroy = kms_display_destroy;
- kdpy->base.get_configs = kms_display_get_configs;
- kdpy->base.create_context = kms_display_create_context;
- kdpy->base.create_pbuffer_surface = kms_display_create_pbuffer_surface;
-
- kdpy->base.modeset = &kms_display_modeset;
-
- return &kdpy->base;
-}
-
-struct native_probe *
-native_create_probe(EGLNativeDisplayType dpy)
-{
- return NULL;
-}
-
-enum native_probe_result
-native_get_probe_result(struct native_probe *nprobe)
-{
- return NATIVE_PROBE_UNKNOWN;
-}
-
-/* the api is destroyed with the native display */
-static struct drm_api *drm_api;
-
-const char *
-native_get_name(void)
-{
- static char kms_name[32];
-
- if (!drm_api)
- drm_api = drm_api_create();
-
- if (drm_api)
- snprintf(kms_name, sizeof(kms_name), "KMS/%s", drm_api->name);
- else
- snprintf(kms_name, sizeof(kms_name), "KMS");
-
- return kms_name;
-}
-
-struct native_display *
-native_create_display(EGLNativeDisplayType dpy)
-{
- struct native_display *ndpy = NULL;
-
- if (!drm_api)
- drm_api = drm_api_create();
-
- if (drm_api)
- ndpy = kms_create_display(dpy, drm_api);
-
- return ndpy;
-}
+++ /dev/null
-/*
- * Mesa 3-D graphics library
- * Version: 7.8
- *
- * Copyright (C) 2010 Chia-I Wu <olv@0xlab.org>
- *
- * 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
- * BRIAN PAUL 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.
- */
-
-#ifndef _NATIVE_KMS_H_
-#define _NATIVE_KMS_H_
-
-#include <xf86drm.h>
-#include <xf86drmMode.h>
-
-#include "pipe/p_compiler.h"
-#include "util/u_format.h"
-#include "pipe/p_state.h"
-#include "state_tracker/drm_api.h"
-
-#include "common/native.h"
-
-enum kms_surface_type {
- KMS_SURFACE_TYPE_PBUFFER,
- KMS_SURFACE_TYPE_SCANOUT
-};
-
-struct kms_config;
-struct kms_connector;
-struct kms_mode;
-
-struct kms_crtc {
- drmModeCrtcPtr crtc;
- uint32_t connectors[32];
- int num_connectors;
-};
-
-struct kms_display {
- struct native_display base;
-
- int fd;
- struct drm_api *api;
- drmModeResPtr resources;
- struct kms_config *config;
-
- struct kms_connector *connectors;
- int num_connectors;
-
- struct kms_surface **shown_surfaces;
- /* save the original settings of the CRTCs */
- struct kms_crtc *saved_crtcs;
-};
-
-struct kms_framebuffer {
- struct pipe_texture *texture;
- boolean is_passive;
-
- uint32_t buffer_id;
-};
-
-struct kms_surface {
- struct native_surface base;
- enum kms_surface_type type;
- enum pipe_format color_format;
- struct kms_display *kdpy;
- int width, height;
-
- struct pipe_texture *textures[NUM_NATIVE_ATTACHMENTS];
- unsigned int sequence_number;
- struct kms_framebuffer front_fb, back_fb;
-
- boolean is_shown;
- struct kms_crtc current_crtc;
-};
-
-struct kms_config {
- struct native_config base;
-};
-
-struct kms_connector {
- struct native_connector base;
-
- uint32_t connector_id;
- drmModeConnectorPtr connector;
- struct kms_mode *kms_modes;
- int num_modes;
-};
-
-struct kms_mode {
- struct native_mode base;
- drmModeModeInfo mode;
-};
-
-static INLINE struct kms_display *
-kms_display(const struct native_display *ndpy)
-{
- return (struct kms_display *) ndpy;
-}
-
-static INLINE struct kms_surface *
-kms_surface(const struct native_surface *nsurf)
-{
- return (struct kms_surface *) nsurf;
-}
-
-static INLINE struct kms_config *
-kms_config(const struct native_config *nconf)
-{
- return (struct kms_config *) nconf;
-}
-
-static INLINE struct kms_connector *
-kms_connector(const struct native_connector *nconn)
-{
- return (struct kms_connector *) nconn;
-}
-
-static INLINE struct kms_mode *
-kms_mode(const struct native_mode *nmode)
-{
- return (struct kms_mode *) nmode;
-}
-
-#endif /* _NATIVE_KMS_H_ */
+++ /dev/null
-/*
- * Mesa 3-D graphics library
- * Version: 7.8
- *
- * Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org>
- *
- * 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
- * BRIAN PAUL 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.
- */
-
-#include "util/u_memory.h"
-#include "util/u_math.h"
-#include "util/u_format.h"
-#include "pipe/p_compiler.h"
-#include "pipe/p_screen.h"
-#include "pipe/p_context.h"
-#include "pipe/p_state.h"
-#include "state_tracker/drm_api.h"
-#include "egllog.h"
-
-#include "native_x11.h"
-#include "x11_screen.h"
-
-enum dri2_surface_type {
- DRI2_SURFACE_TYPE_WINDOW,
- DRI2_SURFACE_TYPE_PIXMAP,
- DRI2_SURFACE_TYPE_PBUFFER
-};
-
-struct dri2_display {
- struct native_display base;
- Display *dpy;
- boolean own_dpy;
-
- struct drm_api *api;
- struct x11_screen *xscr;
- int xscr_number;
-
- struct dri2_config *configs;
- int num_configs;
-};
-
-struct dri2_surface {
- struct native_surface base;
- Drawable drawable;
- enum dri2_surface_type type;
- enum pipe_format color_format;
- struct dri2_display *dri2dpy;
-
- struct pipe_texture *pbuffer_textures[NUM_NATIVE_ATTACHMENTS];
- boolean have_back, have_fake;
- int width, height;
- unsigned int sequence_number;
-};
-
-struct dri2_config {
- struct native_config base;
-};
-
-static INLINE struct dri2_display *
-dri2_display(const struct native_display *ndpy)
-{
- return (struct dri2_display *) ndpy;
-}
-
-static INLINE struct dri2_surface *
-dri2_surface(const struct native_surface *nsurf)
-{
- return (struct dri2_surface *) nsurf;
-}
-
-static INLINE struct dri2_config *
-dri2_config(const struct native_config *nconf)
-{
- return (struct dri2_config *) nconf;
-}
-
-static boolean
-dri2_surface_flush_frontbuffer(struct native_surface *nsurf)
-{
- struct dri2_surface *dri2surf = dri2_surface(nsurf);
- struct dri2_display *dri2dpy = dri2surf->dri2dpy;
-
- /* pbuffer is private */
- if (dri2surf->type == DRI2_SURFACE_TYPE_PBUFFER)
- return TRUE;
-
- /* copy to real front buffer */
- if (dri2surf->have_fake)
- x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable,
- 0, 0, dri2surf->width, dri2surf->height,
- DRI2BufferFakeFrontLeft, DRI2BufferFrontLeft);
-
- return TRUE;
-}
-
-static boolean
-dri2_surface_swap_buffers(struct native_surface *nsurf)
-{
- struct dri2_surface *dri2surf = dri2_surface(nsurf);
- struct dri2_display *dri2dpy = dri2surf->dri2dpy;
-
- /* pbuffer is private */
- if (dri2surf->type == DRI2_SURFACE_TYPE_PBUFFER)
- return TRUE;
-
- /* copy to front buffer */
- if (dri2surf->have_back)
- x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable,
- 0, 0, dri2surf->width, dri2surf->height,
- DRI2BufferBackLeft, DRI2BufferFrontLeft);
-
- /* and update fake front buffer */
- if (dri2surf->have_fake)
- x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable,
- 0, 0, dri2surf->width, dri2surf->height,
- DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft);
-
- return TRUE;
-}
-
-static boolean
-dri2_surface_validate(struct native_surface *nsurf, uint attachment_mask,
- unsigned int *seq_num, struct pipe_texture **textures,
- int *width, int *height)
-{
- struct dri2_surface *dri2surf = dri2_surface(nsurf);
- struct dri2_display *dri2dpy = dri2surf->dri2dpy;
- unsigned int dri2atts[NUM_NATIVE_ATTACHMENTS];
- struct pipe_texture templ;
- struct x11_drawable_buffer *xbufs;
- int num_ins, num_outs, att, i;
-
- if (attachment_mask) {
- memset(&templ, 0, sizeof(templ));
- templ.target = PIPE_TEXTURE_2D;
- templ.last_level = 0;
- templ.width0 = dri2surf->width;
- templ.height0 = dri2surf->height;
- templ.depth0 = 1;
- templ.format = dri2surf->color_format;
- templ.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET;
-
- if (textures)
- memset(textures, 0, sizeof(*textures) * NUM_NATIVE_ATTACHMENTS);
- }
-
- /* create textures for pbuffer */
- if (dri2surf->type == DRI2_SURFACE_TYPE_PBUFFER) {
- struct pipe_screen *screen = dri2dpy->base.screen;
-
- for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) {
- struct pipe_texture *ptex = dri2surf->pbuffer_textures[att];
-
- /* delay the allocation */
- if (!native_attachment_mask_test(attachment_mask, att))
- continue;
-
- if (!ptex) {
- ptex = screen->texture_create(screen, &templ);
- dri2surf->pbuffer_textures[att] = ptex;
- }
-
- if (textures)
- pipe_texture_reference(&textures[att], ptex);
- }
-
- if (seq_num)
- *seq_num = dri2surf->sequence_number;
- if (width)
- *width = dri2surf->width;
- if (height)
- *height = dri2surf->height;
-
- return TRUE;
- }
-
- /* prepare the attachments */
- num_ins = 0;
- for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) {
- if (native_attachment_mask_test(attachment_mask, att)) {
- unsigned int dri2att;
-
- switch (att) {
- case NATIVE_ATTACHMENT_FRONT_LEFT:
- dri2att = DRI2BufferFrontLeft;
- break;
- case NATIVE_ATTACHMENT_BACK_LEFT:
- dri2att = DRI2BufferBackLeft;
- break;
- case NATIVE_ATTACHMENT_FRONT_RIGHT:
- dri2att = DRI2BufferFrontRight;
- break;
- case NATIVE_ATTACHMENT_BACK_RIGHT:
- dri2att = DRI2BufferBackRight;
- break;
- default:
- assert(0);
- dri2att = 0;
- break;
- }
-
- dri2atts[num_ins] = dri2att;
- num_ins++;
- }
- }
-
- dri2surf->have_back = FALSE;
- dri2surf->have_fake = FALSE;
-
- /* remember old geometry */
- templ.width0 = dri2surf->width;
- templ.height0 = dri2surf->height;
-
- xbufs = x11_drawable_get_buffers(dri2dpy->xscr, dri2surf->drawable,
- &dri2surf->width, &dri2surf->height,
- dri2atts, FALSE, num_ins, &num_outs);
- if (!xbufs)
- return FALSE;
-
- if (templ.width0 != dri2surf->width || templ.height0 != dri2surf->height) {
- /* are there cases where the buffers change and the geometry doesn't? */
- dri2surf->sequence_number++;
-
- templ.width0 = dri2surf->width;
- templ.height0 = dri2surf->height;
- }
-
- for (i = 0; i < num_outs; i++) {
- struct x11_drawable_buffer *xbuf = &xbufs[i];
- const char *desc;
- enum native_attachment natt;
-
- switch (xbuf->attachment) {
- case DRI2BufferFrontLeft:
- natt = NATIVE_ATTACHMENT_FRONT_LEFT;
- desc = "DRI2 Front Buffer";
- break;
- case DRI2BufferFakeFrontLeft:
- natt = NATIVE_ATTACHMENT_FRONT_LEFT;
- desc = "DRI2 Fake Front Buffer";
- dri2surf->have_fake = TRUE;
- break;
- case DRI2BufferBackLeft:
- natt = NATIVE_ATTACHMENT_BACK_LEFT;
- desc = "DRI2 Back Buffer";
- dri2surf->have_back = TRUE;
- break;
- default:
- desc = NULL;
- break;
- }
-
- if (!desc || !native_attachment_mask_test(attachment_mask, natt) ||
- (textures && textures[natt])) {
- if (!desc)
- _eglLog(_EGL_WARNING, "unknown buffer %d", xbuf->attachment);
- else if (!native_attachment_mask_test(attachment_mask, natt))
- _eglLog(_EGL_WARNING, "unexpected buffer %d", xbuf->attachment);
- else
- _eglLog(_EGL_WARNING, "both real and fake front buffers are listed");
- continue;
- }
-
- if (textures) {
- struct pipe_texture *ptex =
- dri2dpy->api->texture_from_shared_handle(dri2dpy->api,
- dri2dpy->base.screen, &templ,
- desc, xbuf->pitch, xbuf->name);
- if (ptex) {
- /* the caller owns the textures */
- textures[natt] = ptex;
- }
- }
- }
-
- free(xbufs);
-
- if (seq_num)
- *seq_num = dri2surf->sequence_number;
- if (width)
- *width = dri2surf->width;
- if (height)
- *height = dri2surf->height;
-
- return TRUE;
-}
-
-static void
-dri2_surface_wait(struct native_surface *nsurf)
-{
- struct dri2_surface *dri2surf = dri2_surface(nsurf);
- struct dri2_display *dri2dpy = dri2surf->dri2dpy;
-
- if (dri2surf->have_fake) {
- x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable,
- 0, 0, dri2surf->width, dri2surf->height,
- DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft);
- }
-}
-
-static void
-dri2_surface_destroy(struct native_surface *nsurf)
-{
- struct dri2_surface *dri2surf = dri2_surface(nsurf);
- int i;
-
- for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) {
- struct pipe_texture *ptex = dri2surf->pbuffer_textures[i];
- pipe_texture_reference(&ptex, NULL);
- }
-
- if (dri2surf->drawable)
- x11_drawable_enable_dri2(dri2surf->dri2dpy->xscr,
- dri2surf->drawable, FALSE);
- free(dri2surf);
-}
-
-static struct dri2_surface *
-dri2_display_create_surface(struct native_display *ndpy,
- enum dri2_surface_type type,
- Drawable drawable,
- const struct native_config *nconf)
-{
- struct dri2_display *dri2dpy = dri2_display(ndpy);
- struct dri2_config *dri2conf = dri2_config(nconf);
- struct dri2_surface *dri2surf;
-
- dri2surf = CALLOC_STRUCT(dri2_surface);
- if (!dri2surf)
- return NULL;
-
- if (drawable)
- x11_drawable_enable_dri2(dri2dpy->xscr, drawable, TRUE);
-
- dri2surf->dri2dpy = dri2dpy;
- dri2surf->type = type;
- dri2surf->drawable = drawable;
- dri2surf->color_format = dri2conf->base.color_format;
-
- dri2surf->base.destroy = dri2_surface_destroy;
- dri2surf->base.swap_buffers = dri2_surface_swap_buffers;
- dri2surf->base.flush_frontbuffer = dri2_surface_flush_frontbuffer;
- dri2surf->base.validate = dri2_surface_validate;
- dri2surf->base.wait = dri2_surface_wait;
-
- return dri2surf;
-}
-
-static struct native_surface *
-dri2_display_create_window_surface(struct native_display *ndpy,
- EGLNativeWindowType win,
- const struct native_config *nconf)
-{
- struct dri2_surface *dri2surf;
-
- dri2surf = dri2_display_create_surface(ndpy, DRI2_SURFACE_TYPE_WINDOW,
- (Drawable) win, nconf);
- return (dri2surf) ? &dri2surf->base : NULL;
-}
-
-static struct native_surface *
-dri2_display_create_pixmap_surface(struct native_display *ndpy,
- EGLNativePixmapType pix,
- const struct native_config *nconf)
-{
- struct dri2_surface *dri2surf;
-
- dri2surf = dri2_display_create_surface(ndpy, DRI2_SURFACE_TYPE_PIXMAP,
- (Drawable) pix, nconf);
- return (dri2surf) ? &dri2surf->base : NULL;
-}
-
-static struct native_surface *
-dri2_display_create_pbuffer_surface(struct native_display *ndpy,
- const struct native_config *nconf,
- uint width, uint height)
-{
- struct dri2_surface *dri2surf;
-
- dri2surf = dri2_display_create_surface(ndpy, DRI2_SURFACE_TYPE_PBUFFER,
- (Drawable) None, nconf);
- if (dri2surf) {
- dri2surf->width = width;
- dri2surf->height = height;
- }
- return (dri2surf) ? &dri2surf->base : NULL;
-}
-
-static struct pipe_context *
-dri2_display_create_context(struct native_display *ndpy, void *context_private)
-{
- struct dri2_display *dri2dpy = dri2_display(ndpy);
- struct pipe_context *pctx;
-
- pctx = dri2dpy->api->create_context(dri2dpy->api, dri2dpy->base.screen);
- if (pctx)
- pctx->priv = context_private;
- return pctx;
-}
-
-static int
-choose_color_format(const __GLcontextModes *mode, enum pipe_format formats[32])
-{
- int count = 0;
-
- switch (mode->rgbBits) {
- case 32:
- formats[count++] = PIPE_FORMAT_A8R8G8B8_UNORM;
- formats[count++] = PIPE_FORMAT_B8G8R8A8_UNORM;
- break;
- case 24:
- formats[count++] = PIPE_FORMAT_X8R8G8B8_UNORM;
- formats[count++] = PIPE_FORMAT_B8G8R8X8_UNORM;
- formats[count++] = PIPE_FORMAT_A8R8G8B8_UNORM;
- formats[count++] = PIPE_FORMAT_B8G8R8A8_UNORM;
- break;
- case 16:
- formats[count++] = PIPE_FORMAT_R5G6B5_UNORM;
- break;
- default:
- break;
- }
-
- return count;
-}
-
-static int
-choose_depth_stencil_format(const __GLcontextModes *mode,
- enum pipe_format formats[32])
-{
- int count = 0;
-
- switch (mode->depthBits) {
- case 32:
- formats[count++] = PIPE_FORMAT_Z32_UNORM;
- break;
- case 24:
- if (mode->stencilBits) {
- formats[count++] = PIPE_FORMAT_S8Z24_UNORM;
- formats[count++] = PIPE_FORMAT_Z24S8_UNORM;
- }
- else {
- formats[count++] = PIPE_FORMAT_X8Z24_UNORM;
- formats[count++] = PIPE_FORMAT_Z24X8_UNORM;
- }
- break;
- case 16:
- formats[count++] = PIPE_FORMAT_Z16_UNORM;
- break;
- default:
- break;
- }
-
- return count;
-}
-
-static boolean
-is_format_supported(struct pipe_screen *screen,
- enum pipe_format fmt, boolean is_color)
-{
- return screen->is_format_supported(screen, fmt, PIPE_TEXTURE_2D,
- (is_color) ? PIPE_TEXTURE_USAGE_RENDER_TARGET :
- PIPE_TEXTURE_USAGE_DEPTH_STENCIL, 0);
-}
-
-static boolean
-dri2_display_convert_config(struct native_display *ndpy,
- const __GLcontextModes *mode,
- struct native_config *nconf)
-{
- enum pipe_format formats[32];
- int num_formats, i;
-
- if (!(mode->renderType & GLX_RGBA_BIT) || !mode->rgbMode)
- return FALSE;
-
- /* skip single-buffered configs */
- if (!mode->doubleBufferMode)
- return FALSE;
-
- nconf->mode = *mode;
- nconf->mode.renderType = GLX_RGBA_BIT;
- nconf->mode.rgbMode = TRUE;
- /* pbuffer is allocated locally and is always supported */
- nconf->mode.drawableType |= GLX_PBUFFER_BIT;
- /* the swap method is always copy */
- nconf->mode.swapMethod = GLX_SWAP_COPY_OML;
-
- /* fix up */
- nconf->mode.rgbBits =
- nconf->mode.redBits + nconf->mode.greenBits +
- nconf->mode.blueBits + nconf->mode.alphaBits;
- if (!(nconf->mode.drawableType & GLX_WINDOW_BIT)) {
- nconf->mode.visualID = 0;
- nconf->mode.visualType = GLX_NONE;
- }
- if (!(nconf->mode.drawableType & GLX_PBUFFER_BIT)) {
- nconf->mode.bindToTextureRgb = FALSE;
- nconf->mode.bindToTextureRgba = FALSE;
- }
-
- nconf->color_format = PIPE_FORMAT_NONE;
- nconf->depth_format = PIPE_FORMAT_NONE;
- nconf->stencil_format = PIPE_FORMAT_NONE;
-
- /* choose color format */
- num_formats = choose_color_format(mode, formats);
- for (i = 0; i < num_formats; i++) {
- if (is_format_supported(ndpy->screen, formats[i], TRUE)) {
- nconf->color_format = formats[i];
- break;
- }
- }
- if (nconf->color_format == PIPE_FORMAT_NONE)
- return FALSE;
-
- /* choose depth/stencil format */
- num_formats = choose_depth_stencil_format(mode, formats);
- for (i = 0; i < num_formats; i++) {
- if (is_format_supported(ndpy->screen, formats[i], FALSE)) {
- nconf->depth_format = formats[i];
- nconf->stencil_format = formats[i];
- break;
- }
- }
- if ((nconf->mode.depthBits && nconf->depth_format == PIPE_FORMAT_NONE) ||
- (nconf->mode.stencilBits && nconf->stencil_format == PIPE_FORMAT_NONE))
- return FALSE;
-
- return TRUE;
-}
-
-static const struct native_config **
-dri2_display_get_configs(struct native_display *ndpy, int *num_configs)
-{
- struct dri2_display *dri2dpy = dri2_display(ndpy);
- const struct native_config **configs;
- int i;
-
- /* first time */
- if (!dri2dpy->configs) {
- const __GLcontextModes *modes;
- int num_modes, count;
-
- modes = x11_screen_get_glx_configs(dri2dpy->xscr);
- if (!modes)
- return NULL;
- num_modes = x11_context_modes_count(modes);
-
- dri2dpy->configs = calloc(num_modes, sizeof(*dri2dpy->configs));
- if (!dri2dpy->configs)
- return NULL;
-
- count = 0;
- for (i = 0; i < num_modes; i++) {
- struct native_config *nconf = &dri2dpy->configs[count].base;
- if (dri2_display_convert_config(&dri2dpy->base, modes, nconf))
- count++;
- modes = modes->next;
- }
-
- dri2dpy->num_configs = count;
- }
-
- configs = malloc(dri2dpy->num_configs * sizeof(*configs));
- if (configs) {
- for (i = 0; i < dri2dpy->num_configs; i++)
- configs[i] = (const struct native_config *) &dri2dpy->configs[i];
- if (num_configs)
- *num_configs = dri2dpy->num_configs;
- }
-
- return configs;
-}
-
-static boolean
-dri2_display_is_pixmap_supported(struct native_display *ndpy,
- EGLNativePixmapType pix,
- const struct native_config *nconf)
-{
- struct dri2_display *dri2dpy = dri2_display(ndpy);
- uint depth, nconf_depth;
-
- depth = x11_drawable_get_depth(dri2dpy->xscr, (Drawable) pix);
- nconf_depth = util_format_get_blocksizebits(nconf->color_format);
-
- /* simple depth match for now */
- return (depth == nconf_depth || (depth == 24 && depth + 8 == nconf_depth));
-}
-
-static void
-dri2_display_destroy(struct native_display *ndpy)
-{
- struct dri2_display *dri2dpy = dri2_display(ndpy);
-
- if (dri2dpy->configs)
- free(dri2dpy->configs);
-
- if (dri2dpy->base.screen)
- dri2dpy->base.screen->destroy(dri2dpy->base.screen);
-
- if (dri2dpy->xscr)
- x11_screen_destroy(dri2dpy->xscr);
- if (dri2dpy->own_dpy)
- XCloseDisplay(dri2dpy->dpy);
- if (dri2dpy->api && dri2dpy->api->destroy)
- dri2dpy->api->destroy(dri2dpy->api);
- free(dri2dpy);
-}
-
-/**
- * Initialize DRI2 and pipe screen.
- */
-static boolean
-dri2_display_init_screen(struct native_display *ndpy)
-{
- struct dri2_display *dri2dpy = dri2_display(ndpy);
- const char *driver = dri2dpy->api->name;
- struct drm_create_screen_arg arg;
- int fd;
-
- if (!x11_screen_support(dri2dpy->xscr, X11_SCREEN_EXTENSION_DRI2) ||
- !x11_screen_support(dri2dpy->xscr, X11_SCREEN_EXTENSION_GLX)) {
- _eglLog(_EGL_WARNING, "GLX/DRI2 is not supported");
- return FALSE;
- }
-
- fd = x11_screen_enable_dri2(dri2dpy->xscr, driver);
- if (fd < 0)
- return FALSE;
-
- memset(&arg, 0, sizeof(arg));
- arg.mode = DRM_CREATE_NORMAL;
- dri2dpy->base.screen = dri2dpy->api->create_screen(dri2dpy->api, fd, &arg);
- if (!dri2dpy->base.screen) {
- _eglLog(_EGL_WARNING, "failed to create DRM screen");
- return FALSE;
- }
-
- return TRUE;
-}
-
-struct native_display *
-x11_create_dri2_display(EGLNativeDisplayType dpy, struct drm_api *api)
-{
- struct dri2_display *dri2dpy;
-
- dri2dpy = CALLOC_STRUCT(dri2_display);
- if (!dri2dpy)
- return NULL;
-
- dri2dpy->api = api;
- if (!dri2dpy->api) {
- _eglLog(_EGL_WARNING, "failed to create DRM API");
- free(dri2dpy);
- return NULL;
- }
-
- dri2dpy->dpy = dpy;
- if (!dri2dpy->dpy) {
- dri2dpy->dpy = XOpenDisplay(NULL);
- if (!dri2dpy->dpy) {
- dri2_display_destroy(&dri2dpy->base);
- return NULL;
- }
- dri2dpy->own_dpy = TRUE;
- }
-
- dri2dpy->xscr_number = DefaultScreen(dri2dpy->dpy);
- dri2dpy->xscr = x11_screen_create(dri2dpy->dpy, dri2dpy->xscr_number);
- if (!dri2dpy->xscr) {
- dri2_display_destroy(&dri2dpy->base);
- return NULL;
- }
-
- if (!dri2_display_init_screen(&dri2dpy->base)) {
- dri2_display_destroy(&dri2dpy->base);
- return NULL;
- }
-
- dri2dpy->base.destroy = dri2_display_destroy;
- dri2dpy->base.get_configs = dri2_display_get_configs;
- dri2dpy->base.is_pixmap_supported = dri2_display_is_pixmap_supported;
- dri2dpy->base.create_context = dri2_display_create_context;
- dri2dpy->base.create_window_surface = dri2_display_create_window_surface;
- dri2dpy->base.create_pixmap_surface = dri2_display_create_pixmap_surface;
- dri2dpy->base.create_pbuffer_surface = dri2_display_create_pbuffer_surface;
-
- return &dri2dpy->base;
-}
+++ /dev/null
-/*
- * Mesa 3-D graphics library
- * Version: 7.8
- *
- * Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org>
- *
- * 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
- * BRIAN PAUL 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.
- */
-
-#include <string.h>
-#include "util/u_debug.h"
-#include "util/u_memory.h"
-#include "state_tracker/drm_api.h"
-#include "egllog.h"
-
-#include "native_x11.h"
-#include "x11_screen.h"
-
-#define X11_PROBE_MAGIC 0x11980BE /* "X11PROBE" */
-
-static struct drm_api *api;
-
-static void
-x11_probe_destroy(struct native_probe *nprobe)
-{
- if (nprobe->data)
- free(nprobe->data);
- free(nprobe);
-}
-
-struct native_probe *
-native_create_probe(EGLNativeDisplayType dpy)
-{
- struct native_probe *nprobe;
- struct x11_screen *xscr;
- int scr;
- const char *driver_name = NULL;
- Display *xdpy;
-
- nprobe = CALLOC_STRUCT(native_probe);
- if (!nprobe)
- return NULL;
-
- xdpy = dpy;
- if (!xdpy) {
- xdpy = XOpenDisplay(NULL);
- if (!xdpy) {
- free(nprobe);
- return NULL;
- }
- }
-
- scr = DefaultScreen(xdpy);
- xscr = x11_screen_create(xdpy, scr);
- if (xscr) {
- if (x11_screen_support(xscr, X11_SCREEN_EXTENSION_DRI2)) {
- driver_name = x11_screen_probe_dri2(xscr);
- nprobe->data = strdup(driver_name);
- }
-
- x11_screen_destroy(xscr);
- }
-
- if (xdpy != dpy)
- XCloseDisplay(xdpy);
-
- nprobe->magic = X11_PROBE_MAGIC;
- nprobe->display = dpy;
-
- nprobe->destroy = x11_probe_destroy;
-
- return nprobe;
-}
-
-enum native_probe_result
-native_get_probe_result(struct native_probe *nprobe)
-{
- if (!nprobe || nprobe->magic != X11_PROBE_MAGIC)
- return NATIVE_PROBE_UNKNOWN;
-
- if (!api)
- api = drm_api_create();
-
- /* this is a software driver */
- if (!api)
- return NATIVE_PROBE_SUPPORTED;
-
- /* the display does not support DRI2 or the driver mismatches */
- if (!nprobe->data || strcmp(api->name, (const char *) nprobe->data) != 0)
- return NATIVE_PROBE_FALLBACK;
-
- return NATIVE_PROBE_EXACT;
-}
-
-const char *
-native_get_name(void)
-{
- static char x11_name[32];
-
- if (!api)
- api = drm_api_create();
-
- if (api)
- snprintf(x11_name, sizeof(x11_name), "X11/%s", api->name);
- else
- snprintf(x11_name, sizeof(x11_name), "X11");
-
- return x11_name;
-}
-
-struct native_display *
-native_create_display(EGLNativeDisplayType dpy)
-{
- struct native_display *ndpy = NULL;
- boolean force_sw;
-
- if (!api)
- api = drm_api_create();
-
- force_sw = debug_get_bool_option("EGL_SOFTWARE", FALSE);
- if (api && !force_sw) {
- ndpy = x11_create_dri2_display(dpy, api);
- }
-
- if (!ndpy) {
- EGLint level = (force_sw) ? _EGL_INFO : _EGL_WARNING;
-
- _eglLog(level, "use software fallback");
- ndpy = x11_create_ximage_display(dpy, TRUE);
- }
-
- return ndpy;
-}
+++ /dev/null
-/*
- * Mesa 3-D graphics library
- * Version: 7.8
- *
- * Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org>
- *
- * 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
- * BRIAN PAUL 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.
- */
-
-#ifndef _NATIVE_X11_H_
-#define _NATIVE_X11_H_
-
-#include "state_tracker/drm_api.h"
-#include "common/native.h"
-
-struct native_display *
-x11_create_ximage_display(EGLNativeDisplayType dpy, boolean use_xshm);
-
-struct native_display *
-x11_create_dri2_display(EGLNativeDisplayType dpy, struct drm_api *api);
-
-#endif /* _NATIVE_X11_H_ */
+++ /dev/null
-/*
- * Mesa 3-D graphics library
- * Version: 7.8
- *
- * Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org>
- *
- * 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
- * BRIAN PAUL 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.
- */
-
-#include <assert.h>
-#include <sys/ipc.h>
-#include <sys/types.h>
-#include <sys/shm.h>
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-#include <X11/extensions/XShm.h>
-#include "util/u_memory.h"
-#include "util/u_math.h"
-#include "util/u_format.h"
-#include "pipe/p_compiler.h"
-#include "pipe/internal/p_winsys_screen.h"
-#include "softpipe/sp_winsys.h"
-#include "egllog.h"
-
-#include "sw_winsys.h"
-#include "native_x11.h"
-#include "x11_screen.h"
-
-enum ximage_surface_type {
- XIMAGE_SURFACE_TYPE_WINDOW,
- XIMAGE_SURFACE_TYPE_PIXMAP,
- XIMAGE_SURFACE_TYPE_PBUFFER
-};
-
-struct ximage_display {
- struct native_display base;
- Display *dpy;
- boolean own_dpy;
-
- struct x11_screen *xscr;
- int xscr_number;
-
- boolean use_xshm;
-
- struct pipe_winsys *winsys;
- struct ximage_config *configs;
- int num_configs;
-};
-
-struct ximage_buffer {
- XImage *ximage;
-
- struct pipe_texture *texture;
- XShmSegmentInfo *shm_info;
- boolean xshm_attached;
-};
-
-struct ximage_surface {
- struct native_surface base;
- Drawable drawable;
- enum ximage_surface_type type;
- enum pipe_format color_format;
- XVisualInfo visual;
- struct ximage_display *xdpy;
-
- int width, height;
- GC gc;
-
- struct ximage_buffer buffers[NUM_NATIVE_ATTACHMENTS];
- unsigned int sequence_number;
-};
-
-struct ximage_config {
- struct native_config base;
- const XVisualInfo *visual;
-};
-
-static INLINE struct ximage_display *
-ximage_display(const struct native_display *ndpy)
-{
- return (struct ximage_display *) ndpy;
-}
-
-static INLINE struct ximage_surface *
-ximage_surface(const struct native_surface *nsurf)
-{
- return (struct ximage_surface *) nsurf;
-}
-
-static INLINE struct ximage_config *
-ximage_config(const struct native_config *nconf)
-{
- return (struct ximage_config *) nconf;
-}
-
-static void
-ximage_surface_free_buffer(struct native_surface *nsurf,
- enum native_attachment which)
-{
- struct ximage_surface *xsurf = ximage_surface(nsurf);
- struct ximage_buffer *xbuf = &xsurf->buffers[which];
-
- pipe_texture_reference(&xbuf->texture, NULL);
-
- if (xbuf->shm_info) {
- if (xbuf->xshm_attached)
- XShmDetach(xsurf->xdpy->dpy, xbuf->shm_info);
- if (xbuf->shm_info->shmaddr != (void *) -1)
- shmdt(xbuf->shm_info->shmaddr);
- if (xbuf->shm_info->shmid != -1)
- shmctl(xbuf->shm_info->shmid, IPC_RMID, 0);
-
- xbuf->shm_info->shmaddr = (void *) -1;
- xbuf->shm_info->shmid = -1;
- }
-}
-
-static boolean
-ximage_surface_alloc_buffer(struct native_surface *nsurf,
- enum native_attachment which)
-{
- struct ximage_surface *xsurf = ximage_surface(nsurf);
- struct ximage_buffer *xbuf = &xsurf->buffers[which];
- struct pipe_screen *screen = xsurf->xdpy->base.screen;
- struct pipe_texture templ;
-
- /* free old data */
- if (xbuf->texture)
- ximage_surface_free_buffer(&xsurf->base, which);
-
- memset(&templ, 0, sizeof(templ));
- templ.target = PIPE_TEXTURE_2D;
- templ.format = xsurf->color_format;
- templ.width0 = xsurf->width;
- templ.height0 = xsurf->height;
- templ.depth0 = 1;
- templ.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET;
-
- if (xbuf->shm_info) {
- struct pipe_buffer *pbuf;
- unsigned stride, size;
- void *addr = NULL;
-
- stride = util_format_get_stride(xsurf->color_format, xsurf->width);
- /* alignment should depend on visual? */
- stride = align(stride, 4);
- size = stride * xsurf->height;
-
- /* create and attach shm object */
- xbuf->shm_info->shmid = shmget(IPC_PRIVATE, size, 0755);
- if (xbuf->shm_info->shmid != -1) {
- xbuf->shm_info->shmaddr =
- shmat(xbuf->shm_info->shmid, NULL, 0);
- if (xbuf->shm_info->shmaddr != (void *) -1) {
- if (XShmAttach(xsurf->xdpy->dpy, xbuf->shm_info)) {
- addr = xbuf->shm_info->shmaddr;
- xbuf->xshm_attached = TRUE;
- }
- }
- }
-
- if (addr) {
- pbuf = screen->user_buffer_create(screen, addr, size);
- if (pbuf) {
- xbuf->texture =
- screen->texture_blanket(screen, &templ, &stride, pbuf);
- pipe_buffer_reference(&pbuf, NULL);
- }
- }
- }
- else {
- xbuf->texture = screen->texture_create(screen, &templ);
- }
-
- /* clean up the buffer if allocation failed */
- if (!xbuf->texture)
- ximage_surface_free_buffer(&xsurf->base, which);
-
- return (xbuf->texture != NULL);
-}
-
-static boolean
-ximage_surface_draw_buffer(struct native_surface *nsurf,
- enum native_attachment which)
-{
- struct ximage_surface *xsurf = ximage_surface(nsurf);
- struct ximage_buffer *xbuf = &xsurf->buffers[which];
- struct pipe_screen *screen = xsurf->xdpy->base.screen;
- struct pipe_transfer *transfer;
-
- if (xsurf->type == XIMAGE_SURFACE_TYPE_PBUFFER)
- return TRUE;
-
- assert(xsurf->drawable && xbuf->ximage && xbuf->texture);
-
- transfer = screen->get_tex_transfer(screen, xbuf->texture,
- 0, 0, 0, PIPE_TRANSFER_READ, 0, 0, xsurf->width, xsurf->height);
- if (!transfer)
- return FALSE;
-
- xbuf->ximage->bytes_per_line = transfer->stride;
- xbuf->ximage->data = screen->transfer_map(screen, transfer);
- if (!xbuf->ximage->data) {
- screen->tex_transfer_destroy(transfer);
- return FALSE;
- }
-
-
- if (xbuf->shm_info)
- XShmPutImage(xsurf->xdpy->dpy, xsurf->drawable, xsurf->gc,
- xbuf->ximage, 0, 0, 0, 0, xsurf->width, xsurf->height, False);
- else
- XPutImage(xsurf->xdpy->dpy, xsurf->drawable, xsurf->gc,
- xbuf->ximage, 0, 0, 0, 0, xsurf->width, xsurf->height);
-
- xbuf->ximage->data = NULL;
- screen->transfer_unmap(screen, transfer);
-
- /*
- * softpipe allows the pipe transfer to be re-used, but we don't want to
- * rely on that behavior.
- */
- screen->tex_transfer_destroy(transfer);
-
- XSync(xsurf->xdpy->dpy, FALSE);
-
- return TRUE;
-}
-
-static boolean
-ximage_surface_flush_frontbuffer(struct native_surface *nsurf)
-{
- return ximage_surface_draw_buffer(nsurf, NATIVE_ATTACHMENT_FRONT_LEFT);
-}
-
-static boolean
-ximage_surface_swap_buffers(struct native_surface *nsurf)
-{
- struct ximage_surface *xsurf = ximage_surface(nsurf);
- struct ximage_buffer *xfront, *xback, xtmp;
-
- xfront = &xsurf->buffers[NATIVE_ATTACHMENT_FRONT_LEFT];
- xback = &xsurf->buffers[NATIVE_ATTACHMENT_BACK_LEFT];
-
- /* draw the back buffer directly if there is no front buffer */
- if (!xfront->texture)
- return ximage_surface_draw_buffer(nsurf, NATIVE_ATTACHMENT_BACK_LEFT);
-
- /* swap the buffers */
- xtmp = *xfront;
- *xfront = *xback;
- *xback = xtmp;
-
- /* the front/back textures are swapped */
- xsurf->sequence_number++;
-
- return ximage_surface_draw_buffer(nsurf, NATIVE_ATTACHMENT_FRONT_LEFT);
-}
-
-static void
-ximage_surface_update_geometry(struct native_surface *nsurf)
-{
- struct ximage_surface *xsurf = ximage_surface(nsurf);
- Status ok;
- Window root;
- int x, y;
- unsigned int w, h, border, depth;
-
- /* pbuffer has fixed geometry */
- if (xsurf->type == XIMAGE_SURFACE_TYPE_PBUFFER)
- return;
-
- ok = XGetGeometry(xsurf->xdpy->dpy, xsurf->drawable,
- &root, &x, &y, &w, &h, &border, &depth);
- if (ok) {
- xsurf->width = w;
- xsurf->height = h;
- }
-}
-
-static boolean
-ximage_surface_validate(struct native_surface *nsurf, uint attachment_mask,
- unsigned int *seq_num, struct pipe_texture **textures,
- int *width, int *height)
-{
- struct ximage_surface *xsurf = ximage_surface(nsurf);
- boolean new_buffers = FALSE;
- int att;
-
- ximage_surface_update_geometry(&xsurf->base);
-
- for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) {
- struct ximage_buffer *xbuf = &xsurf->buffers[att];
-
- /* delay the allocation */
- if (!native_attachment_mask_test(attachment_mask, att))
- continue;
-
- /* reallocate the texture */
- if (!xbuf->texture ||
- xsurf->width != xbuf->texture->width0 ||
- xsurf->height != xbuf->texture->height0) {
- new_buffers = TRUE;
- if (ximage_surface_alloc_buffer(&xsurf->base, att)) {
- /* update ximage */
- if (xbuf->ximage) {
- xbuf->ximage->width = xsurf->width;
- xbuf->ximage->height = xsurf->height;
- }
- }
- }
-
- if (textures) {
- textures[att] = NULL;
- pipe_texture_reference(&textures[att], xbuf->texture);
- }
- }
-
- /* increase the sequence number so that caller knows */
- if (new_buffers)
- xsurf->sequence_number++;
-
- if (seq_num)
- *seq_num = xsurf->sequence_number;
- if (width)
- *width = xsurf->width;
- if (height)
- *height = xsurf->height;
-
- return TRUE;
-}
-
-static void
-ximage_surface_wait(struct native_surface *nsurf)
-{
- struct ximage_surface *xsurf = ximage_surface(nsurf);
- XSync(xsurf->xdpy->dpy, FALSE);
- /* TODO XGetImage and update the front texture */
-}
-
-static void
-ximage_surface_destroy(struct native_surface *nsurf)
-{
- struct ximage_surface *xsurf = ximage_surface(nsurf);
- int i;
-
- for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) {
- struct ximage_buffer *xbuf = &xsurf->buffers[i];
- ximage_surface_free_buffer(&xsurf->base, i);
- /* xbuf->shm_info is owned by xbuf->ximage? */
- if (xbuf->ximage) {
- XDestroyImage(xbuf->ximage);
- xbuf->ximage = NULL;
- }
- }
-
- if (xsurf->type != XIMAGE_SURFACE_TYPE_PBUFFER)
- XFreeGC(xsurf->xdpy->dpy, xsurf->gc);
- free(xsurf);
-}
-
-static struct ximage_surface *
-ximage_display_create_surface(struct native_display *ndpy,
- enum ximage_surface_type type,
- Drawable drawable,
- const struct native_config *nconf)
-{
- struct ximage_display *xdpy = ximage_display(ndpy);
- struct ximage_config *xconf = ximage_config(nconf);
- struct ximage_surface *xsurf;
- int i;
-
- xsurf = CALLOC_STRUCT(ximage_surface);
- if (!xsurf)
- return NULL;
-
- xsurf->xdpy = xdpy;
- xsurf->type = type;
- xsurf->color_format = xconf->base.color_format;
- xsurf->drawable = drawable;
-
- if (xsurf->type != XIMAGE_SURFACE_TYPE_PBUFFER) {
- xsurf->drawable = drawable;
- xsurf->visual = *xconf->visual;
-
- xsurf->gc = XCreateGC(xdpy->dpy, xsurf->drawable, 0, NULL);
- if (!xsurf->gc) {
- free(xsurf);
- return NULL;
- }
-
- for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) {
- struct ximage_buffer *xbuf = &xsurf->buffers[i];
-
- if (xdpy->use_xshm) {
- xbuf->shm_info = calloc(1, sizeof(*xbuf->shm_info));
- if (xbuf->shm_info) {
- /* initialize shm info */
- xbuf->shm_info->shmid = -1;
- xbuf->shm_info->shmaddr = (void *) -1;
- xbuf->shm_info->readOnly = TRUE;
-
- xbuf->ximage = XShmCreateImage(xsurf->xdpy->dpy,
- xsurf->visual.visual,
- xsurf->visual.depth,
- ZPixmap, NULL,
- xbuf->shm_info,
- 0, 0);
- }
- }
- else {
- xbuf->ximage = XCreateImage(xsurf->xdpy->dpy,
- xsurf->visual.visual,
- xsurf->visual.depth,
- ZPixmap, 0, /* format, offset */
- NULL, /* data */
- 0, 0, /* size */
- 8, /* bitmap_pad */
- 0); /* bytes_per_line */
- }
-
- if (!xbuf->ximage) {
- XFreeGC(xdpy->dpy, xsurf->gc);
- free(xsurf);
- return NULL;
- }
- }
- }
-
- xsurf->base.destroy = ximage_surface_destroy;
- xsurf->base.swap_buffers = ximage_surface_swap_buffers;
- xsurf->base.flush_frontbuffer = ximage_surface_flush_frontbuffer;
- xsurf->base.validate = ximage_surface_validate;
- xsurf->base.wait = ximage_surface_wait;
-
- return xsurf;
-}
-
-static struct native_surface *
-ximage_display_create_window_surface(struct native_display *ndpy,
- EGLNativeWindowType win,
- const struct native_config *nconf)
-{
- struct ximage_surface *xsurf;
-
- xsurf = ximage_display_create_surface(ndpy, XIMAGE_SURFACE_TYPE_WINDOW,
- (Drawable) win, nconf);
- return (xsurf) ? &xsurf->base : NULL;
-}
-
-static struct native_surface *
-ximage_display_create_pixmap_surface(struct native_display *ndpy,
- EGLNativePixmapType pix,
- const struct native_config *nconf)
-{
- struct ximage_surface *xsurf;
-
- xsurf = ximage_display_create_surface(ndpy, XIMAGE_SURFACE_TYPE_PIXMAP,
- (Drawable) pix, nconf);
- return (xsurf) ? &xsurf->base : NULL;
-}
-
-static struct native_surface *
-ximage_display_create_pbuffer_surface(struct native_display *ndpy,
- const struct native_config *nconf,
- uint width, uint height)
-{
- struct ximage_surface *xsurf;
-
- xsurf = ximage_display_create_surface(ndpy, XIMAGE_SURFACE_TYPE_PBUFFER,
- (Drawable) None, nconf);
- if (xsurf) {
- xsurf->width = width;
- xsurf->height = height;
- }
- return (xsurf) ? &xsurf->base : NULL;
-}
-
-static struct pipe_context *
-ximage_display_create_context(struct native_display *ndpy,
- void *context_private)
-{
- struct pipe_context *pctx = softpipe_create(ndpy->screen);
- if (pctx)
- pctx->priv = context_private;
- return pctx;
-}
-
-static enum pipe_format
-choose_format(const XVisualInfo *vinfo)
-{
- enum pipe_format fmt;
- /* TODO elaborate the formats */
- switch (vinfo->depth) {
- case 32:
- fmt = PIPE_FORMAT_A8R8G8B8_UNORM;
- break;
- case 24:
- fmt = PIPE_FORMAT_X8R8G8B8_UNORM;
- break;
- case 16:
- fmt = PIPE_FORMAT_R5G6B5_UNORM;
- break;
- default:
- fmt = PIPE_FORMAT_NONE;
- break;
- }
-
- return fmt;
-}
-
-static const struct native_config **
-ximage_display_get_configs(struct native_display *ndpy, int *num_configs)
-{
- struct ximage_display *xdpy = ximage_display(ndpy);
- const struct native_config **configs;
- int i;
-
- /* first time */
- if (!xdpy->configs) {
- const XVisualInfo *visuals;
- int num_visuals, count, j;
-
- visuals = x11_screen_get_visuals(xdpy->xscr, &num_visuals);
- if (!visuals)
- return NULL;
-
- /*
- * Create two configs for each visual.
- * One with depth/stencil buffer; one without
- */
- xdpy->configs = calloc(num_visuals * 2, sizeof(*xdpy->configs));
- if (!xdpy->configs)
- return NULL;
-
- count = 0;
- for (i = 0; i < num_visuals; i++) {
- for (j = 0; j < 2; j++) {
- struct ximage_config *xconf = &xdpy->configs[count];
- __GLcontextModes *mode = &xconf->base.mode;
-
- xconf->visual = &visuals[i];
- xconf->base.color_format = choose_format(xconf->visual);
- if (xconf->base.color_format == PIPE_FORMAT_NONE)
- continue;
-
- x11_screen_convert_visual(xdpy->xscr, xconf->visual, mode);
- /* support double buffer mode */
- mode->doubleBufferMode = TRUE;
-
- xconf->base.depth_format = PIPE_FORMAT_NONE;
- xconf->base.stencil_format = PIPE_FORMAT_NONE;
- /* create the second config with depth/stencil buffer */
- if (j == 1) {
- xconf->base.depth_format = PIPE_FORMAT_S8Z24_UNORM;
- xconf->base.stencil_format = PIPE_FORMAT_S8Z24_UNORM;
- mode->depthBits = 24;
- mode->stencilBits = 8;
- mode->haveDepthBuffer = TRUE;
- mode->haveStencilBuffer = TRUE;
- }
-
- mode->maxPbufferWidth = 4096;
- mode->maxPbufferHeight = 4096;
- mode->maxPbufferPixels = 4096 * 4096;
- mode->drawableType =
- GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT;
- mode->swapMethod = GLX_SWAP_EXCHANGE_OML;
-
- if (mode->alphaBits)
- mode->bindToTextureRgba = TRUE;
- else
- mode->bindToTextureRgb = TRUE;
-
- count++;
- }
- }
-
- xdpy->num_configs = count;
- }
-
- configs = malloc(xdpy->num_configs * sizeof(*configs));
- if (configs) {
- for (i = 0; i < xdpy->num_configs; i++)
- configs[i] = (const struct native_config *) &xdpy->configs[i];
- if (num_configs)
- *num_configs = xdpy->num_configs;
- }
- return configs;
-}
-
-static boolean
-ximage_display_is_pixmap_supported(struct native_display *ndpy,
- EGLNativePixmapType pix,
- const struct native_config *nconf)
-{
- struct ximage_display *xdpy = ximage_display(ndpy);
- enum pipe_format fmt;
- uint depth;
-
- depth = x11_drawable_get_depth(xdpy->xscr, (Drawable) pix);
- switch (depth) {
- case 32:
- fmt = PIPE_FORMAT_A8R8G8B8_UNORM;
- break;
- case 24:
- fmt = PIPE_FORMAT_X8R8G8B8_UNORM;
- break;
- case 16:
- fmt = PIPE_FORMAT_R5G6B5_UNORM;
- break;
- default:
- fmt = PIPE_FORMAT_NONE;
- break;
- }
-
- return (fmt == nconf->color_format);
-}
-
-static void
-ximage_display_destroy(struct native_display *ndpy)
-{
- struct ximage_display *xdpy = ximage_display(ndpy);
-
- if (xdpy->configs)
- free(xdpy->configs);
-
- xdpy->base.screen->destroy(xdpy->base.screen);
- free(xdpy->winsys);
-
- x11_screen_destroy(xdpy->xscr);
- if (xdpy->own_dpy)
- XCloseDisplay(xdpy->dpy);
- free(xdpy);
-}
-
-struct native_display *
-x11_create_ximage_display(EGLNativeDisplayType dpy, boolean use_xshm)
-{
- struct ximage_display *xdpy;
-
- xdpy = CALLOC_STRUCT(ximage_display);
- if (!xdpy)
- return NULL;
-
- xdpy->dpy = dpy;
- if (!xdpy->dpy) {
- xdpy->dpy = XOpenDisplay(NULL);
- if (!xdpy->dpy) {
- free(xdpy);
- return NULL;
- }
- xdpy->own_dpy = TRUE;
- }
-
- xdpy->xscr_number = DefaultScreen(xdpy->dpy);
- xdpy->xscr = x11_screen_create(xdpy->dpy, xdpy->xscr_number);
- if (!xdpy->xscr) {
- free(xdpy);
- return NULL;
- }
-
- xdpy->use_xshm =
- (use_xshm && x11_screen_support(xdpy->xscr, X11_SCREEN_EXTENSION_XSHM));
-
- xdpy->winsys = create_sw_winsys();
- xdpy->base.screen = softpipe_create_screen(xdpy->winsys);
-
- xdpy->base.destroy = ximage_display_destroy;
-
- xdpy->base.get_configs = ximage_display_get_configs;
- xdpy->base.is_pixmap_supported = ximage_display_is_pixmap_supported;
- xdpy->base.create_context = ximage_display_create_context;
- xdpy->base.create_window_surface = ximage_display_create_window_surface;
- xdpy->base.create_pixmap_surface = ximage_display_create_pixmap_surface;
- xdpy->base.create_pbuffer_surface = ximage_display_create_pbuffer_surface;
-
- return &xdpy->base;
-}
+++ /dev/null
-/**************************************************************************
- *
- * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
- * All Rights Reserved.
- *
- * 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, sub license, 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 (including the
- * next paragraph) 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 NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS 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.
- *
- **************************************************************************/
-
-/**
- * Totally software-based winsys layer.
- * Note that the one winsys function that we can't implement here
- * is flush_frontbuffer().
- * Whoever uses this code will have to provide that.
- *
- * Authors: Brian Paul
- */
-
-
-#include "pipe/internal/p_winsys_screen.h"
-#include "pipe/p_state.h"
-#include "pipe/p_inlines.h"
-#include "util/u_format.h"
-#include "util/u_math.h"
-#include "util/u_memory.h"
-
-#include "sw_winsys.h"
-
-
-
-/** Subclass of pipe_winsys */
-struct sw_pipe_winsys
-{
- struct pipe_winsys Base;
- /* no extra fields for now */
-};
-
-
-/** subclass of pipe_buffer */
-struct sw_pipe_buffer
-{
- struct pipe_buffer Base;
- boolean UserBuffer; /** Is this a user-space buffer? */
- void *Data;
- void *Mapped;
-};
-
-
-/** cast wrapper */
-static INLINE struct sw_pipe_buffer *
-sw_pipe_buffer(struct pipe_buffer *b)
-{
- return (struct sw_pipe_buffer *) b;
-}
-
-
-static const char *
-get_name(struct pipe_winsys *pws)
-{
- return "software";
-}
-
-
-/** Create new pipe_buffer and allocate storage of given size */
-static struct pipe_buffer *
-buffer_create(struct pipe_winsys *pws,
- unsigned alignment,
- unsigned usage,
- unsigned size)
-{
- struct sw_pipe_buffer *buffer = CALLOC_STRUCT(sw_pipe_buffer);
- if (!buffer)
- return NULL;
-
- pipe_reference_init(&buffer->Base.reference, 1);
- buffer->Base.alignment = alignment;
- buffer->Base.usage = usage;
- buffer->Base.size = size;
-
- /* align to 16-byte multiple for Cell */
- buffer->Data = align_malloc(size, MAX2(alignment, 16));
-
- return &buffer->Base;
-}
-
-
-/**
- * Create buffer which wraps user-space data.
- */
-static struct pipe_buffer *
-user_buffer_create(struct pipe_winsys *pws, void *ptr, unsigned bytes)
-{
- struct sw_pipe_buffer *buffer = CALLOC_STRUCT(sw_pipe_buffer);
- if (!buffer)
- return NULL;
-
- pipe_reference_init(&buffer->Base.reference, 1);
- buffer->Base.size = bytes;
- buffer->UserBuffer = TRUE;
- buffer->Data = ptr;
-
- return &buffer->Base;
-}
-
-
-static void *
-buffer_map(struct pipe_winsys *pws, struct pipe_buffer *buf, unsigned flags)
-{
- struct sw_pipe_buffer *buffer = sw_pipe_buffer(buf);
- buffer->Mapped = buffer->Data;
- return buffer->Mapped;
-}
-
-
-static void
-buffer_unmap(struct pipe_winsys *pws, struct pipe_buffer *buf)
-{
- struct sw_pipe_buffer *buffer = sw_pipe_buffer(buf);
- buffer->Mapped = NULL;
-}
-
-
-static void
-buffer_destroy(struct pipe_buffer *buf)
-{
- struct sw_pipe_buffer *buffer = sw_pipe_buffer(buf);
-
- if (buffer->Data && !buffer->UserBuffer) {
- align_free(buffer->Data);
- buffer->Data = NULL;
- }
-
- free(buffer);
-}
-
-
-static struct pipe_buffer *
-surface_buffer_create(struct pipe_winsys *winsys,
- unsigned width, unsigned height,
- enum pipe_format format,
- unsigned usage,
- unsigned tex_usage,
- unsigned *stride)
-{
- const unsigned alignment = 64;
- unsigned nblocksy;
-
- nblocksy = util_format_get_nblocksy(format, height);
- *stride = align(util_format_get_stride(format, width), alignment);
-
- return winsys->buffer_create(winsys, alignment,
- usage,
- *stride * nblocksy);
-}
-
-
-static void
-fence_reference(struct pipe_winsys *sws, struct pipe_fence_handle **ptr,
- struct pipe_fence_handle *fence)
-{
- /* no-op */
-}
-
-
-static int
-fence_signalled(struct pipe_winsys *sws, struct pipe_fence_handle *fence,
- unsigned flag)
-{
- /* no-op */
- return 0;
-}
-
-
-static int
-fence_finish(struct pipe_winsys *sws, struct pipe_fence_handle *fence,
- unsigned flag)
-{
- /* no-op */
- return 0;
-}
-
-
-/**
- * Create/return a new pipe_winsys object.
- */
-struct pipe_winsys *
-create_sw_winsys(void)
-{
- struct sw_pipe_winsys *ws = CALLOC_STRUCT(sw_pipe_winsys);
- if (!ws)
- return NULL;
-
- /* Fill in this struct with callbacks that pipe will need to
- * communicate with the window system, buffer manager, etc.
- */
- ws->Base.buffer_create = buffer_create;
- ws->Base.user_buffer_create = user_buffer_create;
- ws->Base.buffer_map = buffer_map;
- ws->Base.buffer_unmap = buffer_unmap;
- ws->Base.buffer_destroy = buffer_destroy;
-
- ws->Base.surface_buffer_create = surface_buffer_create;
-
- ws->Base.fence_reference = fence_reference;
- ws->Base.fence_signalled = fence_signalled;
- ws->Base.fence_finish = fence_finish;
-
- ws->Base.flush_frontbuffer = NULL; /* not implemented here! */
-
- ws->Base.get_name = get_name;
-
- return &ws->Base;
-}
+++ /dev/null
-/**************************************************************************
- *
- * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
- * All Rights Reserved.
- *
- * 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, sub license, 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 (including the
- * next paragraph) 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 NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS 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.
- *
- **************************************************************************/
-
-
-#ifndef SW_WINSYS_H
-#define SW_WINSYS_H
-
-
-struct pipe_winsys;
-
-
-extern struct pipe_winsys *
-create_sw_winsys(void);
-
-
-#endif /* SW_WINSYS_H */
+++ /dev/null
-/*
- * Mesa 3-D graphics library
- * Version: 7.8
- *
- * Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org>
- *
- * 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
- * BRIAN PAUL 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.
- */
-
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <X11/Xlibint.h>
-#include <X11/extensions/XShm.h>
-#include "util/u_memory.h"
-#include "util/u_math.h"
-#include "util/u_format.h"
-#include "xf86drm.h"
-#include "egllog.h"
-
-#include "x11_screen.h"
-#include "dri2.h"
-#include "glxinit.h"
-
-struct x11_screen {
- Display *dpy;
- int number;
-
- /*
- * This is used to fetch GLX visuals/fbconfigs. It uses code from egl_xdri.
- * It might be better to rewrite the part in Xlib or XCB.
- */
- __GLXdisplayPrivate *glx_dpy;
-
- int dri_major, dri_minor;
- char *dri_driver;
- char *dri_device;
- int dri_fd;
-
- XVisualInfo *visuals;
- int num_visuals;
-
- /* cached values for x11_drawable_get_depth */
- Drawable last_drawable;
- unsigned int last_depth;
-};
-
-
-/**
- * Create a X11 screen.
- */
-struct x11_screen *
-x11_screen_create(Display *dpy, int screen)
-{
- struct x11_screen *xscr;
-
- if (screen >= ScreenCount(dpy))
- return NULL;
-
- xscr = CALLOC_STRUCT(x11_screen);
- if (xscr) {
- xscr->dpy = dpy;
- xscr->number = screen;
-
- xscr->dri_major = -1;
- xscr->dri_fd = -1;
- }
- return xscr;
-}
-
-/**
- * Destroy a X11 screen.
- */
-void
-x11_screen_destroy(struct x11_screen *xscr)
-{
- if (xscr->dri_fd >= 0)
- close(xscr->dri_fd);
- if (xscr->dri_driver)
- Xfree(xscr->dri_driver);
- if (xscr->dri_device)
- Xfree(xscr->dri_device);
-
- /* xscr->glx_dpy will be destroyed with the X display */
-
- if (xscr->visuals)
- XFree(xscr->visuals);
- free(xscr);
-}
-
-static boolean
-x11_screen_init_dri2(struct x11_screen *xscr)
-{
- if (xscr->dri_major < 0) {
- int eventBase, errorBase;
-
- if (!DRI2QueryExtension(xscr->dpy, &eventBase, &errorBase) ||
- !DRI2QueryVersion(xscr->dpy, &xscr->dri_major, &xscr->dri_minor))
- xscr->dri_major = -1;
- }
- return (xscr->dri_major >= 0);
-}
-
-static boolean
-x11_screen_init_glx(struct x11_screen *xscr)
-{
- if (!xscr->glx_dpy)
- xscr->glx_dpy = __glXInitialize(xscr->dpy);
- return (xscr->glx_dpy != NULL);
-}
-
-/**
- * Return true if the screen supports the extension.
- */
-boolean
-x11_screen_support(struct x11_screen *xscr, enum x11_screen_extension ext)
-{
- boolean supported = FALSE;
-
- switch (ext) {
- case X11_SCREEN_EXTENSION_XSHM:
- supported = XShmQueryExtension(xscr->dpy);
- break;
- case X11_SCREEN_EXTENSION_GLX:
- supported = x11_screen_init_glx(xscr);
- break;
- case X11_SCREEN_EXTENSION_DRI2:
- supported = x11_screen_init_dri2(xscr);
- break;
- default:
- break;
- }
-
- return supported;
-}
-
-/**
- * Return the X visuals.
- */
-const XVisualInfo *
-x11_screen_get_visuals(struct x11_screen *xscr, int *num_visuals)
-{
- if (!xscr->visuals) {
- XVisualInfo vinfo_template;
- vinfo_template.screen = xscr->number;
- xscr->visuals = XGetVisualInfo(xscr->dpy, VisualScreenMask,
- &vinfo_template, &xscr->num_visuals);
- }
-
- if (num_visuals)
- *num_visuals = xscr->num_visuals;
- return xscr->visuals;
-}
-
-void
-x11_screen_convert_visual(struct x11_screen *xscr, const XVisualInfo *visual,
- __GLcontextModes *mode)
-{
- int r, g, b, a;
- int visual_type;
-
- r = util_bitcount(visual->red_mask);
- g = util_bitcount(visual->green_mask);
- b = util_bitcount(visual->blue_mask);
- a = visual->depth - (r + g + b);
-#if defined(__cplusplus) || defined(c_plusplus)
- visual_type = visual->c_class;
-#else
- visual_type = visual->class;
-#endif
-
- /* convert to GLX visual type */
- switch (visual_type) {
- case TrueColor:
- visual_type = GLX_TRUE_COLOR;
- break;
- case DirectColor:
- visual_type = GLX_DIRECT_COLOR;
- break;
- case PseudoColor:
- visual_type = GLX_PSEUDO_COLOR;
- break;
- case StaticColor:
- visual_type = GLX_STATIC_COLOR;
- break;
- case GrayScale:
- visual_type = GLX_GRAY_SCALE;
- break;
- case StaticGray:
- visual_type = GLX_STATIC_GRAY;
- break;
- default:
- visual_type = GLX_NONE;
- break;
- }
-
- mode->rgbBits = r + g + b + a;
- mode->redBits = r;
- mode->greenBits = g;
- mode->blueBits = b;
- mode->alphaBits = a;
- mode->visualID = visual->visualid;
- mode->visualType = visual_type;
-
- /* sane defaults */
- mode->renderType = GLX_RGBA_BIT;
- mode->rgbMode = TRUE;
- mode->visualRating = GLX_SLOW_CONFIG;
- mode->xRenderable = TRUE;
-}
-
-/**
- * Return the GLX fbconfigs.
- */
-const __GLcontextModes *
-x11_screen_get_glx_configs(struct x11_screen *xscr)
-{
- return (x11_screen_init_glx(xscr))
- ? xscr->glx_dpy->screenConfigs[xscr->number].configs
- : NULL;
-}
-
-/**
- * Return the GLX visuals.
- */
-const __GLcontextModes *
-x11_screen_get_glx_visuals(struct x11_screen *xscr)
-{
- return (x11_screen_init_glx(xscr))
- ? xscr->glx_dpy->screenConfigs[xscr->number].visuals
- : NULL;
-}
-
-static boolean
-x11_screen_is_driver_equal(struct x11_screen *xscr, const char *driver)
-{
- return (strcmp(xscr->dri_driver, driver) == 0);
-}
-
-/**
- * Probe the screen for the DRI2 driver name.
- */
-const char *
-x11_screen_probe_dri2(struct x11_screen *xscr)
-{
- /* get the driver name and the device name */
- if (!xscr->dri_driver) {
- if (!DRI2Connect(xscr->dpy, RootWindow(xscr->dpy, xscr->number),
- &xscr->dri_driver, &xscr->dri_device))
- xscr->dri_driver = xscr->dri_device = NULL;
- }
-
- return xscr->dri_driver;
-}
-
-/**
- * Enable DRI2 and returns the file descriptor of the DRM device. The file
- * descriptor will be closed automatically when the screen is destoryed.
- */
-int
-x11_screen_enable_dri2(struct x11_screen *xscr, const char *driver)
-{
- if (xscr->dri_fd < 0) {
- int fd;
- drm_magic_t magic;
-
- /* get the driver name and the device name first */
- if (!x11_screen_probe_dri2(xscr))
- return -1;
-
- if (!x11_screen_is_driver_equal(xscr, driver)) {
- _eglLog(_EGL_WARNING, "Driver mismatch: %s != %s",
- xscr->dri_driver, driver);
- return -1;
- }
-
- fd = open(xscr->dri_device, O_RDWR);
- if (fd < 0) {
- _eglLog(_EGL_WARNING, "failed to open %s", xscr->dri_device);
- return -1;
- }
-
- memset(&magic, 0, sizeof(magic));
- if (drmGetMagic(fd, &magic)) {
- _eglLog(_EGL_WARNING, "failed to get magic");
- close(fd);
- return -1;
- }
-
- if (!DRI2Authenticate(xscr->dpy,
- RootWindow(xscr->dpy, xscr->number), magic)) {
- _eglLog(_EGL_WARNING, "failed to authenticate magic");
- close(fd);
- return -1;
- }
-
- xscr->dri_fd = fd;
- }
-
- return xscr->dri_fd;
-}
-
-/**
- * Create/Destroy the DRI drawable.
- */
-void
-x11_drawable_enable_dri2(struct x11_screen *xscr,
- Drawable drawable, boolean on)
-{
- if (on)
- DRI2CreateDrawable(xscr->dpy, drawable);
- else
- DRI2DestroyDrawable(xscr->dpy, drawable);
-}
-
-/**
- * Copy between buffers of the DRI2 drawable.
- */
-void
-x11_drawable_copy_buffers(struct x11_screen *xscr, Drawable drawable,
- int x, int y, int width, int height,
- int src_buf, int dst_buf)
-{
- XRectangle rect;
- XserverRegion region;
-
- rect.x = x;
- rect.y = y;
- rect.width = width;
- rect.height = height;
-
- region = XFixesCreateRegion(xscr->dpy, &rect, 1);
- DRI2CopyRegion(xscr->dpy, drawable, region, dst_buf, src_buf);
- XFixesDestroyRegion(xscr->dpy, region);
-}
-
-/**
- * Get the buffers of the DRI2 drawable. The returned array should be freed.
- */
-struct x11_drawable_buffer *
-x11_drawable_get_buffers(struct x11_screen *xscr, Drawable drawable,
- int *width, int *height, unsigned int *attachments,
- boolean with_format, int num_ins, int *num_outs)
-{
- DRI2Buffer *dri2bufs;
-
- if (with_format)
- dri2bufs = DRI2GetBuffersWithFormat(xscr->dpy, drawable, width, height,
- attachments, num_ins, num_outs);
- else
- dri2bufs = DRI2GetBuffers(xscr->dpy, drawable, width, height,
- attachments, num_ins, num_outs);
-
- return (struct x11_drawable_buffer *) dri2bufs;
-}
-
-/**
- * Return the depth of a drawable.
- *
- * Unlike other drawable functions, the drawable needs not be a DRI2 drawable.
- */
-uint
-x11_drawable_get_depth(struct x11_screen *xscr, Drawable drawable)
-{
- unsigned int depth;
-
- if (drawable != xscr->last_drawable) {
- Window root;
- int x, y;
- unsigned int w, h, border;
- Status ok;
-
- ok = XGetGeometry(xscr->dpy, drawable, &root,
- &x, &y, &w, &h, &border, &depth);
- if (!ok)
- depth = 0;
-
- xscr->last_drawable = drawable;
- xscr->last_depth = depth;
- }
- else {
- depth = xscr->last_depth;
- }
-
- return depth;
-}
-
-/**
- * Create a mode list of the given size.
- */
-__GLcontextModes *
-x11_context_modes_create(unsigned count)
-{
- const size_t size = sizeof(__GLcontextModes);
- __GLcontextModes *base = NULL;
- __GLcontextModes **next;
- unsigned i;
-
- next = &base;
- for (i = 0; i < count; i++) {
- *next = (__GLcontextModes *) calloc(1, size);
- if (*next == NULL) {
- x11_context_modes_destroy(base);
- base = NULL;
- break;
- }
- next = &((*next)->next);
- }
-
- return base;
-}
-
-/**
- * Destroy a mode list.
- */
-void
-x11_context_modes_destroy(__GLcontextModes *modes)
-{
- while (modes != NULL) {
- __GLcontextModes *next = modes->next;
- free(modes);
- modes = next;
- }
-}
-
-/**
- * Return the number of the modes in the mode list.
- */
-unsigned
-x11_context_modes_count(const __GLcontextModes *modes)
-{
- const __GLcontextModes *mode;
- int count = 0;
- for (mode = modes; mode; mode = mode->next)
- count++;
- return count;
-}
+++ /dev/null
-/*
- * Mesa 3-D graphics library
- * Version: 7.8
- *
- * Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org>
- *
- * 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
- * BRIAN PAUL 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.
- */
-
-#ifndef _X11_SCREEN_H_
-#define _X11_SCREEN_H_
-
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-#include <X11/extensions/dri2tokens.h>
-#include "pipe/p_compiler.h"
-#include "common/native.h"
-
-enum x11_screen_extension {
- X11_SCREEN_EXTENSION_XSHM,
- X11_SCREEN_EXTENSION_GLX,
- X11_SCREEN_EXTENSION_DRI2,
-};
-
-/* the same as DRI2Buffer */
-struct x11_drawable_buffer {
- unsigned int attachment;
- unsigned int name;
- unsigned int pitch;
- unsigned int cpp;
- unsigned int flags;
-};
-
-struct x11_screen;
-
-struct x11_screen *
-x11_screen_create(Display *dpy, int screen);
-
-void
-x11_screen_destroy(struct x11_screen *xscr);
-
-boolean
-x11_screen_support(struct x11_screen *xscr, enum x11_screen_extension ext);
-
-const XVisualInfo *
-x11_screen_get_visuals(struct x11_screen *xscr, int *num_visuals);
-
-void
-x11_screen_convert_visual(struct x11_screen *xscr, const XVisualInfo *visual,
- __GLcontextModes *mode);
-
-const __GLcontextModes *
-x11_screen_get_glx_configs(struct x11_screen *xscr);
-
-const __GLcontextModes *
-x11_screen_get_glx_visuals(struct x11_screen *xscr);
-
-const char *
-x11_screen_probe_dri2(struct x11_screen *xscr);
-
-int
-x11_screen_enable_dri2(struct x11_screen *xscr, const char *driver);
-
-__GLcontextModes *
-x11_context_modes_create(unsigned count);
-
-void
-x11_context_modes_destroy(__GLcontextModes *modes);
-
-unsigned
-x11_context_modes_count(const __GLcontextModes *modes);
-
-void
-x11_drawable_enable_dri2(struct x11_screen *xscr,
- Drawable drawable, boolean on);
-
-void
-x11_drawable_copy_buffers(struct x11_screen *xscr, Drawable drawable,
- int x, int y, int width, int height,
- int src_buf, int dst_buf);
-
-struct x11_drawable_buffer *
-x11_drawable_get_buffers(struct x11_screen *xscr, Drawable drawable,
- int *width, int *height, unsigned int *attachments,
- boolean with_format, int num_ins, int *num_outs);
-
-uint
-x11_drawable_get_depth(struct x11_screen *xscr, Drawable drawable);
-
-#endif /* _X11_SCREEN_H_ */
--- /dev/null
+# src/gallium/winsys/drm/Makefile.egl
+
+# The driver Makefile should define
+#
+# EGL_DRIVER_NAME, the name of the driver
+# EGL_DRIVER_SOURCES, the sources of the driver
+# EGL_DRIVER_LIBS, extra libraries needed by the driver
+# EGL_DRIVER_PIPES, the pipe drivers of the driver
+#
+# before including this file.
+
+EGL_DRIVER_OBJECTS = $(EGL_DRIVER_SOURCES:.c=.o)
+
+common_LIBS = -ldrm -lm -ldl
+
+x11_ST = $(TOP)/src/gallium/state_trackers/egl/libeglx11.a
+x11_LIBS = $(common_LIBS) -lX11 -lXext -lXfixes
+
+kms_ST = $(TOP)/src/gallium/state_trackers/egl/libeglkms.a
+kms_LIBS = $(common_LIBS)
+
+##### RULES #####
+
+.c.o:
+ $(CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@
+
+
+##### TARGETS #####
+
+EGL_DISPLAY_DRIVERS = $(foreach dpy, $(EGL_DISPLAYS), egl_$(dpy)_$(EGL_DRIVER_NAME).so)
+
+LIB_GALLIUM_DIR = $(TOP)/$(LIB_DIR)/gallium
+EGL_DISPLAY_LIBS = $(foreach drv, $(EGL_DISPLAY_DRIVERS), $(LIB_GALLIUM_DIR)/$(drv))
+
+default: $(EGL_DISPLAY_LIBS)
+
+$(EGL_DISPLAY_LIBS): $(LIB_GALLIUM_DIR)/%.so: %.so
+ @mkdir -p $(LIB_GALLIUM_DIR)
+ $(INSTALL) $^ $(LIB_GALLIUM_DIR)
+
+define mklib-egl
+$(MKLIB) -o $@ -noprefix -linker '$(CC)' -ldflags '$(LDFLAGS)' \
+ $(MKLIB_OPTIONS) $(EGL_DRIVER_OBJECTS) \
+ -Wl,--whole-archive $($(1)_ST) -Wl,--no-whole-archive \
+ $(EGL_DRIVER_PIPES) $(GALLIUM_AUXILIARIES) $($(1)_LIBS) $(EGL_DRIVER_LIBS)
+endef
+
+egl_x11_$(EGL_DRIVER_NAME).so: $(EGL_DRIVER_OBJECTS) $(x11_ST) $(EGL_DRIVER_PIPES) $(GALLIUM_AUXILIARIES) Makefile
+ $(call mklib-egl,x11)
+
+egl_kms_$(EGL_DRIVER_NAME).so: $(EGL_DRIVER_OBJECTS) $(kms_ST) $(EGL_DRIVER_PIPES) $(GALLIUM_AUXILIARIES) Makefile
+ $(call mklib-egl,kms)
+
+clean:
+ -rm -f $(EGL_DRIVER_OBJECTS)
+ -rm -f $(EGL_DISPLAY_DRIVERS)
+
+install: $(EGL_DISPLAY_LIBS)
+ @$(INSTALL) -d $(DESTDIR)$(DRI_DRIVER_INSTALL_DIR)
+ @echo "Install $(EGL_DISPLAY_DRIVERS)"
+ @for lib in "$(EGL_DISPLAY_LIBS)"; do \
+ $(MINSTALL) -m 755 "$$lib" $(DESTDIR)$(DRI_DRIVER_INSTALL_DIR); \
+ done
+
+depend:
+++ /dev/null
-# src/gallium/winsys/drm/Makefile.egl_g3d
-
-# The driver Makefile should define
-#
-# EGL_DRIVER_NAME, the name of the driver
-# EGL_DRIVER_SOURCES, the sources of the driver
-# EGL_DRIVER_LIBS, extra libraries needed by the driver
-# EGL_DRIVER_PIPES, the pipe drivers of the driver
-#
-# before including this file.
-
-EGL_DRIVER_OBJECTS = $(EGL_DRIVER_SOURCES:.c=.o)
-
-common_LIBS = -ldrm -lm -ldl
-
-x11_ST = $(TOP)/src/gallium/state_trackers/egl_g3d/libeglx11.a
-x11_LIBS = $(common_LIBS) -lX11 -lXext -lXfixes
-
-kms_ST = $(TOP)/src/gallium/state_trackers/egl_g3d/libeglkms.a
-kms_LIBS = $(common_LIBS)
-
-##### RULES #####
-
-.c.o:
- $(CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@
-
-
-##### TARGETS #####
-
-EGL_DISPLAY_DRIVERS = $(foreach dpy, $(EGL_DISPLAYS), egl_$(dpy)_$(EGL_DRIVER_NAME).so)
-
-LIB_GALLIUM_DIR = $(TOP)/$(LIB_DIR)/gallium
-EGL_DISPLAY_LIBS = $(foreach drv, $(EGL_DISPLAY_DRIVERS), $(LIB_GALLIUM_DIR)/$(drv))
-
-default: $(EGL_DISPLAY_LIBS)
-
-$(EGL_DISPLAY_LIBS): $(LIB_GALLIUM_DIR)/%.so: %.so
- @mkdir -p $(LIB_GALLIUM_DIR)
- $(INSTALL) $^ $(LIB_GALLIUM_DIR)
-
-define mklib-egl
-$(MKLIB) -o $@ -noprefix -linker '$(CC)' -ldflags '$(LDFLAGS)' \
- $(MKLIB_OPTIONS) $(EGL_DRIVER_OBJECTS) \
- -Wl,--whole-archive $($(1)_ST) -Wl,--no-whole-archive \
- $(EGL_DRIVER_PIPES) $(GALLIUM_AUXILIARIES) $($(1)_LIBS) $(EGL_DRIVER_LIBS)
-endef
-
-egl_x11_$(EGL_DRIVER_NAME).so: $(EGL_DRIVER_OBJECTS) $(x11_ST) $(EGL_DRIVER_PIPES) $(GALLIUM_AUXILIARIES) Makefile
- $(call mklib-egl,x11)
-
-egl_kms_$(EGL_DRIVER_NAME).so: $(EGL_DRIVER_OBJECTS) $(kms_ST) $(EGL_DRIVER_PIPES) $(GALLIUM_AUXILIARIES) Makefile
- $(call mklib-egl,kms)
-
-clean:
- -rm -f $(EGL_DRIVER_OBJECTS)
- -rm -f $(EGL_DISPLAY_DRIVERS)
-
-install: $(EGL_DISPLAY_LIBS)
- @$(INSTALL) -d $(DESTDIR)$(DRI_DRIVER_INSTALL_DIR)
- @echo "Install $(EGL_DISPLAY_DRIVERS)"
- @for lib in "$(EGL_DISPLAY_LIBS)"; do \
- $(MINSTALL) -m 755 "$$lib" $(DESTDIR)$(DRI_DRIVER_INSTALL_DIR); \
- done
-
-depend:
--- /dev/null
+TOP = ../../../../../..
+include $(TOP)/configs/current
+
+EGL_DRIVER_NAME = i965
+EGL_DRIVER_SOURCES = dummy.c
+EGL_DRIVER_LIBS = -ldrm_intel
+
+EGL_DRIVER_PIPES = \
+ $(TOP)/src/gallium/winsys/drm/i965/gem/libi965drm.a \
+ $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a \
+ $(TOP)/src/gallium/drivers/trace/libtrace.a \
+ $(TOP)/src/gallium/drivers/i965/libi965.a
+
+include ../../Makefile.egl
--- /dev/null
+/* mklib expects at least one object file */
+++ /dev/null
-TOP = ../../../../../..
-include $(TOP)/configs/current
-
-EGL_DRIVER_NAME = i965
-EGL_DRIVER_SOURCES = dummy.c
-EGL_DRIVER_LIBS = -ldrm_intel
-
-EGL_DRIVER_PIPES = \
- $(TOP)/src/gallium/winsys/drm/i965/gem/libi965drm.a \
- $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a \
- $(TOP)/src/gallium/drivers/trace/libtrace.a \
- $(TOP)/src/gallium/drivers/i965/libi965.a
-
-include ../../Makefile.egl_g3d
+++ /dev/null
-/* mklib expects at least one object file */
--- /dev/null
+TOP = ../../../../../..
+include $(TOP)/configs/current
+
+EGL_DRIVER_NAME = i915
+EGL_DRIVER_SOURCES = dummy.c
+EGL_DRIVER_LIBS = -ldrm_intel
+
+EGL_DRIVER_PIPES = \
+ $(TOP)/src/gallium/winsys/drm/intel/gem/libinteldrm.a \
+ $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a \
+ $(TOP)/src/gallium/drivers/trace/libtrace.a \
+ $(TOP)/src/gallium/drivers/i915/libi915.a
+
+include ../../Makefile.egl
--- /dev/null
+/* mklib expects at least one object file */
+++ /dev/null
-TOP = ../../../../../..
-include $(TOP)/configs/current
-
-EGL_DRIVER_NAME = i915
-EGL_DRIVER_SOURCES = dummy.c
-EGL_DRIVER_LIBS = -ldrm_intel
-
-EGL_DRIVER_PIPES = \
- $(TOP)/src/gallium/winsys/drm/intel/gem/libinteldrm.a \
- $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a \
- $(TOP)/src/gallium/drivers/trace/libtrace.a \
- $(TOP)/src/gallium/drivers/i915/libi915.a
-
-include ../../Makefile.egl_g3d
+++ /dev/null
-/* mklib expects at least one object file */
--- /dev/null
+TOP = ../../../../../..
+include $(TOP)/configs/current
+
+EGL_DRIVER_NAME = nouveau
+EGL_DRIVER_SOURCES = dummy.c
+EGL_DRIVER_LIBS = -ldrm_nouveau
+
+EGL_DRIVER_PIPES = \
+ $(TOP)/src/gallium/winsys/drm/nouveau/drm/libnouveaudrm.a \
+ $(TOP)/src/gallium/drivers/nv04/libnv04.a \
+ $(TOP)/src/gallium/drivers/nv10/libnv10.a \
+ $(TOP)/src/gallium/drivers/nv20/libnv20.a \
+ $(TOP)/src/gallium/drivers/nv30/libnv30.a \
+ $(TOP)/src/gallium/drivers/nv40/libnv40.a \
+ $(TOP)/src/gallium/drivers/nv50/libnv50.a \
+ $(TOP)/src/gallium/drivers/nouveau/libnouveau.a \
+ $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a
+
+include ../../Makefile.egl
--- /dev/null
+/* mklib expects at least one object file */
+++ /dev/null
-TOP = ../../../../../..
-include $(TOP)/configs/current
-
-EGL_DRIVER_NAME = nouveau
-EGL_DRIVER_SOURCES = dummy.c
-EGL_DRIVER_LIBS = -ldrm_nouveau
-
-EGL_DRIVER_PIPES = \
- $(TOP)/src/gallium/winsys/drm/nouveau/drm/libnouveaudrm.a \
- $(TOP)/src/gallium/drivers/nv04/libnv04.a \
- $(TOP)/src/gallium/drivers/nv10/libnv10.a \
- $(TOP)/src/gallium/drivers/nv20/libnv20.a \
- $(TOP)/src/gallium/drivers/nv30/libnv30.a \
- $(TOP)/src/gallium/drivers/nv40/libnv40.a \
- $(TOP)/src/gallium/drivers/nv50/libnv50.a \
- $(TOP)/src/gallium/drivers/nouveau/libnouveau.a \
- $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a
-
-include ../../Makefile.egl_g3d
+++ /dev/null
-/* mklib expects at least one object file */
--- /dev/null
+TOP = ../../../../../..
+include $(TOP)/configs/current
+
+EGL_DRIVER_NAME = radeon
+EGL_DRIVER_SOURCES = dummy.c
+EGL_DRIVER_LIBS = -ldrm_radeon
+
+EGL_DRIVER_PIPES = \
+ $(TOP)/src/gallium/winsys/drm/radeon/core/libradeonwinsys.a \
+ $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a \
+ $(TOP)/src/gallium/drivers/trace/libtrace.a \
+ $(TOP)/src/gallium/drivers/r300/libr300.a
+
+include ../../Makefile.egl
--- /dev/null
+/* mklib expects at least one object file */
+++ /dev/null
-TOP = ../../../../../..
-include $(TOP)/configs/current
-
-EGL_DRIVER_NAME = radeon
-EGL_DRIVER_SOURCES = dummy.c
-EGL_DRIVER_LIBS = -ldrm_radeon
-
-EGL_DRIVER_PIPES = \
- $(TOP)/src/gallium/winsys/drm/radeon/core/libradeonwinsys.a \
- $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a \
- $(TOP)/src/gallium/drivers/trace/libtrace.a \
- $(TOP)/src/gallium/drivers/r300/libr300.a
-
-include ../../Makefile.egl_g3d
+++ /dev/null
-/* mklib expects at least one object file */
--- /dev/null
+TOP = ../../../../../..
+include $(TOP)/configs/current
+
+EGL_DRIVER_NAME = swrast
+EGL_DRIVER_SOURCES = dummy.c
+EGL_DRIVER_LIBS =
+
+EGL_DRIVER_PIPES = \
+ $(TOP)/src/gallium/winsys/drm/swrast/core/libswrastdrm.a \
+ $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a
+
+include ../../Makefile.egl
--- /dev/null
+/* mklib expects at least one object file */
+++ /dev/null
-TOP = ../../../../../..
-include $(TOP)/configs/current
-
-EGL_DRIVER_NAME = swrast
-EGL_DRIVER_SOURCES = dummy.c
-EGL_DRIVER_LIBS =
-
-EGL_DRIVER_PIPES = \
- $(TOP)/src/gallium/winsys/drm/swrast/core/libswrastdrm.a \
- $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a
-
-include ../../Makefile.egl_g3d
+++ /dev/null
-/* mklib expects at least one object file */
--- /dev/null
+TOP = ../../../../../..
+include $(TOP)/configs/current
+
+EGL_DRIVER_NAME = vmwgfx
+EGL_DRIVER_SOURCES = dummy.c
+EGL_DRIVER_LIBS =
+
+EGL_DRIVER_PIPES = \
+ $(TOP)/src/gallium/winsys/drm/vmware/core/libsvgadrm.a \
+ $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a \
+ $(TOP)/src/gallium/drivers/trace/libtrace.a \
+ $(TOP)/src/gallium/drivers/svga/libsvga.a
+
+include ../../Makefile.egl
--- /dev/null
+/* mklib expects at least one object file */
+++ /dev/null
-TOP = ../../../../../..
-include $(TOP)/configs/current
-
-EGL_DRIVER_NAME = vmwgfx
-EGL_DRIVER_SOURCES = dummy.c
-EGL_DRIVER_LIBS =
-
-EGL_DRIVER_PIPES = \
- $(TOP)/src/gallium/winsys/drm/vmware/core/libsvgadrm.a \
- $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a \
- $(TOP)/src/gallium/drivers/trace/libtrace.a \
- $(TOP)/src/gallium/drivers/svga/libsvga.a
-
-include ../../Makefile.egl_g3d
+++ /dev/null
-/* mklib expects at least one object file */