diff options
34 files changed, 277 insertions, 873 deletions
diff --git a/configure.ac b/configure.ac index 50feac4af3..af5a5fdc4b 100644 --- a/configure.ac +++ b/configure.ac @@ -911,13 +911,18 @@ if test "x$enable_egl" = xyes; then SRC_DIRS="$SRC_DIRS egl" EGL_LIB_DEPS="$DLOPEN_LIBS -lpthread" EGL_DRIVERS_DIRS="" - if test "$enable_static" != yes && test "$mesa_driver" != osmesa; then + if test "$enable_static" != yes; then # build egl_glx when libGL is built - EGL_DRIVERS_DIRS="glx" - fi - if test "$mesa_driver" == dri; then - # build egl_dri2 when dri is enabled - EGL_DRIVERS_DIRS="$EGL_DRIVERS_DIRS dri2" + if test "$mesa_driver" != osmesa; then + EGL_DRIVERS_DIRS="glx" + fi + + # build egl_dri2 when xcb-dri2 is available + PKG_CHECK_EXISTS([x11-xcb xcb-dri2 xcb-xfixes], + [have_xcb_dri2=yes],[have_xcb_dri2=no]) + if test "$have_xcb_dri2" = yes; then + EGL_DRIVERS_DIRS="$EGL_DRIVERS_DIRS dri2" + fi fi fi AC_SUBST([EGL_LIB_DEPS]) diff --git a/docs/egl.html b/docs/egl.html index 30cbe0eaed..9eba402411 100644 --- a/docs/egl.html +++ b/docs/egl.html @@ -206,25 +206,20 @@ It is accelerated when the GLX is. As such, it cannot provide functions that is not available in GLX or GLX extensions.</p> </li> -<li><code>egl_xdri</code> +<li><code>egl_dri2</code> <p>This driver supports the X Window System as its window system. It functions -as a DRI driver loader and can load DRI/DRI2/DRISW drivers. Unlike -<code>egl_glx</code>, it has no dependency on <code>libGL</code>. It talks to -the X server directly using DRI or DRI2 protocols. It also talks minimal GLX -protocol for things like available visuals or fbconfigs. With direct access to -the DRI drivers, it has the potential to support more EGL functions that are -not possible with <code>egl_glx</code>.</p> +as a DRI2 driver loader. Unlike <code>egl_glx</code>, it has no dependency on +<code>libGL</code>. It talks to the X server directly using DRI2 protocol.</p> </li> <li><code>egl_dri</code> <p>This driver lacks maintenance and does <em>not</em> build. It is similiar -to <code>egl_xdri</code> in that it functions as a DRI driver loader. But -unlike <code>egl_xdri</code>, it supports Linux framebuffer devices as its -window system and supports EGL_MESA_screen_surface extension. It loads only -DRI1 drivers. As DRI1 drivers is phasing out, it might be better to rewrite -the driver to support KMS and DRI2.</p> +to <code>egl_dri2</code> in that it functions as a DRI(1) driver loader. But +unlike <code>egl_dri2</code>, it supports Linux framebuffer devices as its +window system and supports EGL_MESA_screen_surface extension. As DRI1 drivers +are phasing out, it might eventually be replaced by <code>egl_dri2</code>.</p> </li> </ul> @@ -272,6 +267,41 @@ uninitialized display.</p> resources. The drivers are responsible to the correct behavior as defined by EGL.</p> +<h3><code>EGL_RENDER_BUFFER</code></h3> + +<p>In EGL, the color buffer a context should try to render to is decided by the +binding surface. It should try to render to the front buffer if the binding +surface has <code>EGL_RENDER_BUFFER</code> set to +<code>EGL_SINGLE_BUFFER</code>; If the same context is later bound to a +surface with <code>EGL_RENDER_BUFFER</code> set to +<code>EGL_BACK_BUFFER</code>, the context should try to render to the back +buffer. However, the context is allowed to make the final decision as to which +color buffer it wants to or is able to render to.</p> + +<p>For pbuffer surfaces, the render buffer is always +<code>EGL_BACK_BUFFER</code>. And for pixmap surfaces, the render buffer is +always <code>EGL_SINGLE_BUFFER</code>. Unlike window surfaces, EGL spec +requires their <code>EGL_RENDER_BUFFER</code> values to be honored. As a +result, a driver should never set <code>EGL_PIXMAP_BIT</code> or +<code>EGL_PBUFFER_BIT</code> bits of a config if the contexts created with the +config won't be able to honor the <code>EGL_RENDER_BUFFER</code> of pixmap or +pbuffer surfaces.</p> + +<p>It should also be noted that pixmap and pbuffer surfaces are assumed to be +single-buffered, in that <code>eglSwapBuffers</code> has no effect on them. It +is desirable that a driver allocates a private color buffer for each pbuffer +surface created. If the window system the driver supports has native pbuffers, +or if the native pixmaps have more than one color buffers, the driver should +carefully attach the native color buffers to the EGL surfaces, re-route them if +required.</p> + +<p>There is no defined behavior as to, for example, how +<code>glDrawBuffer</code> interacts with <code>EGL_RENDER_BUFFER</code>. Right +now, it is desired that the draw buffer in a client API be fixed for pixmap and +pbuffer surfaces. Therefore, the driver is responsible to guarantee that the +client API renders to the specified render buffer for pixmap and pbuffer +surfaces.</p> + <h3>TODOs</h3> <ul> diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c index 56d2b8bbe6..d53f137530 100644 --- a/src/egl/drivers/dri2/egl_dri2.c +++ b/src/egl/drivers/dri2/egl_dri2.c @@ -97,35 +97,8 @@ struct dri2_egl_config const __DRIconfig *dri_config; }; -static struct dri2_egl_driver * -dri2_egl_driver(_EGLDriver *drv) -{ - return (struct dri2_egl_driver *) drv; -} - -static struct dri2_egl_display * -dri2_egl_display(_EGLDisplay *dpy) -{ - return (struct dri2_egl_display *) dpy->DriverData; -} - -static struct dri2_egl_context * -dri2_egl_context(_EGLContext *ctx) -{ - return (struct dri2_egl_context *) ctx; -} - -static struct dri2_egl_surface * -dri2_egl_surface(_EGLSurface *surf) -{ - return (struct dri2_egl_surface *) surf; -} - -static struct dri2_egl_config * -dri2_egl_config(_EGLConfig *conf) -{ - return (struct dri2_egl_config *) conf; -} +/* standard typecasts */ +_EGL_DRIVER_STANDARD_TYPECASTS(dri2_egl) EGLint dri2_to_egl_attribute_map[] = { 0, @@ -171,8 +144,8 @@ EGLint dri2_to_egl_attribute_map[] = { 0, /* __DRI_ATTRIB_SWAP_METHOD */ EGL_MAX_SWAP_INTERVAL, /* __DRI_ATTRIB_MAX_SWAP_INTERVAL */ EGL_MIN_SWAP_INTERVAL, /* __DRI_ATTRIB_MIN_SWAP_INTERVAL */ - EGL_BIND_TO_TEXTURE_RGB, /* __DRI_ATTRIB_BIND_TO_TEXTURE_RGB */ - EGL_BIND_TO_TEXTURE_RGBA, /* __DRI_ATTRIB_BIND_TO_TEXTURE_RGBA */ + 0, /* __DRI_ATTRIB_BIND_TO_TEXTURE_RGB */ + 0, /* __DRI_ATTRIB_BIND_TO_TEXTURE_RGBA */ 0, /* __DRI_ATTRIB_BIND_TO_MIPMAP_TEXTURE */ 0, /* __DRI_ATTRIB_BIND_TO_TEXTURE_TARGETS */ 0, /* __DRI_ATTRIB_YINVERTED */ @@ -183,8 +156,8 @@ dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id) { struct dri2_egl_config *conf; struct dri2_egl_display *dri2_dpy; - unsigned int attrib, value, surface_type; - EGLint key; + unsigned int attrib, value, double_buffer; + EGLint key, bind_to_texture_rgb, bind_to_texture_rgba; int i; dri2_dpy = disp->DriverData; @@ -194,7 +167,6 @@ dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id) conf->dri_config = dri_config; _eglInitConfig(&conf->base, disp, id); - surface_type = EGL_PBUFFER_BIT | EGL_PIXMAP_BIT; i = 0; while (dri2_dpy->core->indexConfigAttrib(dri_config, i++, &attrib, &value)) { @@ -222,9 +194,16 @@ dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id) _eglSetConfigKey(&conf->base, EGL_CONFIG_CAVEAT, value); break; + case __DRI_ATTRIB_BIND_TO_TEXTURE_RGB: + bind_to_texture_rgb = value; + break; + + case __DRI_ATTRIB_BIND_TO_TEXTURE_RGBA: + bind_to_texture_rgba = value; + break; + case __DRI_ATTRIB_DOUBLE_BUFFER: - if (value) - surface_type |= EGL_WINDOW_BIT; + double_buffer = value; break; default: @@ -236,22 +215,28 @@ dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id) } /* EGL_SWAP_BEHAVIOR_PRESERVED_BIT */ - _eglSetConfigKey(&conf->base, EGL_SURFACE_TYPE, surface_type); + + if (double_buffer) { + /* FIXME: Figure out how to get the visual ID and types */ + _eglSetConfigKey(&conf->base, EGL_SURFACE_TYPE, EGL_WINDOW_BIT); + _eglSetConfigKey(&conf->base, EGL_NATIVE_VISUAL_ID, 0x21); + _eglSetConfigKey(&conf->base, EGL_NATIVE_VISUAL_TYPE, + XCB_VISUAL_CLASS_TRUE_COLOR); + } else { + _eglSetConfigKey(&conf->base, + EGL_SURFACE_TYPE, EGL_PIXMAP_BIT | EGL_PBUFFER_BIT); + _eglSetConfigKey(&conf->base, + EGL_BIND_TO_TEXTURE_RGB, bind_to_texture_rgb); + _eglSetConfigKey(&conf->base, + EGL_BIND_TO_TEXTURE_RGBA, bind_to_texture_rgba); + } /* EGL_OPENGL_ES_BIT, EGL_OPENVG_BIT, EGL_OPENGL_ES2_BIT */ _eglSetConfigKey(&conf->base, EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT); _eglSetConfigKey(&conf->base, EGL_CONFORMANT, EGL_OPENGL_BIT); - /* FIXME: Figure out how to get the visual ID and types */ - _eglSetConfigKey(&conf->base, EGL_NATIVE_VISUAL_ID, 0x21); - _eglSetConfigKey(&conf->base, EGL_NATIVE_VISUAL_TYPE, - XCB_VISUAL_CLASS_TRUE_COLOR); - - _eglSetConfigKey(&conf->base, EGL_BIND_TO_TEXTURE_RGB, EGL_TRUE); - _eglSetConfigKey(&conf->base, EGL_BIND_TO_TEXTURE_RGBA, EGL_TRUE); - if (!_eglValidateConfig(&conf->base, EGL_FALSE)) { - _eglLog(_EGL_DEBUG, "DRI2: failed to validate config %d", i); + _eglLog(_EGL_DEBUG, "DRI2: failed to validate config %d", id); free(conf); return; } @@ -484,13 +469,16 @@ dri2_initialize(_EGLDriver *drv, _EGLDisplay *disp, dri2_dpy->driver = NULL; end = search_paths + strlen(search_paths); for (p = search_paths; p < end && dri2_dpy->driver == NULL; p = next + 1) { + int path_len; + next = strchr(p, ':'); if (next == NULL) next = end; + path_len = next - p; snprintf(path, sizeof path, dri_driver_format, - next - p, p, + path_len, p, xcb_dri2_connect_driver_name_length (connect), xcb_dri2_connect_driver_name (connect)); @@ -583,6 +571,7 @@ dri2_initialize(_EGLDriver *drv, _EGLDisplay *disp, extensions = dri2_dpy->core->getExtensions(dri2_dpy->dri_screen); for (i = 0; extensions[i]; i++) { + _eglLog(_EGL_DEBUG, "DRI2: found extension `%s'", extensions[i]->name); if ((strcmp(extensions[i]->name, __DRI2_FLUSH) == 0)) dri2_dpy->flush = (__DRI2flushExtension *) extensions[i]; } @@ -719,11 +708,11 @@ dri2_make_current(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *dsurf, if ((cctx == NULL && ddraw == NULL && rdraw == NULL) || dri2_dpy->core->bindContext(cctx, ddraw, rdraw)) { - if (dsurf) + if (dsurf && !_eglIsSurfaceLinked(dsurf)) dri2_destroy_surface(drv, disp, dsurf); - if (rsurf && rsurf != dsurf) + if (rsurf && rsurf != dsurf && !_eglIsSurfaceLinked(dsurf)) dri2_destroy_surface(drv, disp, rsurf); - if (ctx != NULL) + if (ctx != NULL && !_eglIsContextLinked(ctx)) dri2_dpy->core->unbindContext(dri2_egl_context(ctx)->dri_context); return EGL_TRUE; @@ -835,8 +824,7 @@ dri2_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw) struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw); xcb_dri2_copy_region_cookie_t cookie; - if (dri2_dpy->flush) - (*dri2_dpy->flush->flush)(dri2_surf->dri_drawable); + (*dri2_dpy->flush->flush)(dri2_surf->dri_drawable); #if 0 /* FIXME: Add support for dri swapbuffers, that'll give us swap @@ -873,15 +861,21 @@ dri2_get_proc_address(_EGLDriver *drv, const char *procname) } static EGLBoolean -dri2_wait_client(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx) +dri2_wait_client(_EGLDriver *drv, _EGLDisplay *disp, _EGLContext *ctx) { - /* glXWaitGL(); */ + struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); + struct dri2_egl_surface *dri2_surf = dri2_egl_surface(ctx->DrawSurface); + + /* FIXME: If EGL allows frontbuffer rendering for window surfaces, + * we need to copy fake to real here.*/ + + (*dri2_dpy->flush->flush)(dri2_surf->dri_drawable); return EGL_TRUE; } static EGLBoolean -dri2_wait_native(_EGLDriver *drv, _EGLDisplay *dpy, EGLint engine) +dri2_wait_native(_EGLDriver *drv, _EGLDisplay *disp, EGLint engine) { if (engine != EGL_CORE_NATIVE_ENGINE) return _eglError(EGL_BAD_PARAMETER, "eglWaitNative"); @@ -897,6 +891,31 @@ dri2_unload(_EGLDriver *drv) free(dri2_drv); } +static EGLBoolean +dri2_copy_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf, + EGLNativePixmapType target) +{ + struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); + struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf); + xcb_gcontext_t gc; + + (*dri2_dpy->flush->flush)(dri2_surf->dri_drawable); + + gc = xcb_generate_id(dri2_dpy->conn); + xcb_create_gc(dri2_dpy->conn, gc, target, 0, NULL); + xcb_copy_area(dri2_dpy->conn, + dri2_surf->drawable, + target, + gc, + 0, 0, + 0, 0, + dri2_surf->base.Width, + dri2_surf->base.Height); + xcb_free_gc(dri2_dpy->conn, gc); + + return EGL_TRUE; +} + /** * This is the main entrypoint into the driver, called by libEGL. * Create a new _EGLDriver object and init its dispatch table. @@ -923,6 +942,7 @@ _eglMain(const char *args) dri2_drv->base.API.GetProcAddress = dri2_get_proc_address; dri2_drv->base.API.WaitClient = dri2_wait_client; dri2_drv->base.API.WaitNative = dri2_wait_native; + dri2_drv->base.API.CopyBuffers = dri2_copy_buffers; dri2_drv->base.Name = "DRI2"; dri2_drv->base.Unload = dri2_unload; diff --git a/src/egl/drivers/xdri/Makefile b/src/egl/drivers/xdri/Makefile deleted file mode 100644 index 9120620dc5..0000000000 --- a/src/egl/drivers/xdri/Makefile +++ /dev/null @@ -1,28 +0,0 @@ -# src/egl/drivers/xdri/Makefile - -TOP = ../../../.. -include $(TOP)/configs/current - -EGL_DRIVER = egl_xdri.so - -# steal sources from GLX -GLX_SOURCES = dri_common.c XF86dri.c dri2.c dri2_glx.c dri_glx.c drisw_glx.c -GLX_SOURCES := $(addprefix ../../../glx/x11/,$(GLX_SOURCES)) -GLX_INCLUDES = \ - $(shell pkg-config --cflags-only-I libdrm) \ - -I$(TOP)/include/GL/internal \ - -I$(TOP)/src/glx/x11 \ - -I$(TOP)/src/mesa/glapi \ - -I$(TOP)/src/mesa -GLX_CFLAGS = -DGLX_DIRECT_RENDERING - -EGL_SOURCES = egl_xdri.c glxinit.c driinit.c $(GLX_SOURCES) -EGL_INCLUDES = \ - -I$(TOP)/include \ - -I$(TOP)/src/egl/main \ - $(GLX_INCLUDES) - -EGL_CFLAGS = $(GLX_CFLAGS) -EGL_LIBS = -lX11 -lGL - -include ../Makefile.template diff --git a/src/egl/drivers/xdri/driinit.c b/src/egl/drivers/xdri/driinit.c deleted file mode 100644 index 3e54f0bd4d..0000000000 --- a/src/egl/drivers/xdri/driinit.c +++ /dev/null @@ -1,85 +0,0 @@ -/** - * DRI initialization. The DRI loaders are defined in src/glx/x11/. - */ - -#include <stdlib.h> -#include <sys/time.h> - -#include "glxclient.h" -#include "driinit.h" - -/* for __DRI_SYSTEM_TIME extension */ -_X_HIDDEN int -__glXGetUST(int64_t * ust) -{ - struct timeval tv; - - if (ust == NULL) { - return -EFAULT; - } - - if (gettimeofday(&tv, NULL) == 0) { - ust[0] = (tv.tv_sec * 1000000) + tv.tv_usec; - return 0; - } - else { - return -errno; - } -} - -_X_HIDDEN GLboolean -__driGetMscRateOML(__DRIdrawable * draw, - int32_t * numerator, int32_t * denominator, void *private) -{ - return GL_FALSE; -} - -/* ignore glx extensions */ -_X_HIDDEN void -__glXEnableDirectExtension(__GLXscreenConfigs * psc, const char *name) -{ -} - -_X_HIDDEN __GLXDRIdisplay * -__driCreateDisplay(__GLXdisplayPrivate *dpyPriv, int *version) -{ - __GLXDRIdisplay *driDisplay = NULL; - int ver = 0; - char *env; - int force_sw; - - env = getenv("EGL_SOFTWARE"); - force_sw = (env && *env != '0'); - - /* try DRI2 first */ - if (!force_sw) { - driDisplay = dri2CreateDisplay(dpyPriv->dpy); - if (driDisplay) { - /* fill in the required field */ - dpyPriv->dri2Display = driDisplay; - ver = 2; - } - } - - /* and then DRI */ - if (!force_sw && !driDisplay) { - driDisplay = driCreateDisplay(dpyPriv->dpy); - if (driDisplay) { - dpyPriv->driDisplay = driDisplay; - ver = 1; - } - } - - /* and then DRISW */ - if (!driDisplay) { - driDisplay = driswCreateDisplay(dpyPriv->dpy); - if (driDisplay) { - dpyPriv->driDisplay = driDisplay; - ver = 0; - } - } - - if (version) - *version = ver; - return driDisplay; -} diff --git a/src/egl/drivers/xdri/driinit.h b/src/egl/drivers/xdri/driinit.h deleted file mode 100644 index 6ea05cebef..0000000000 --- a/src/egl/drivers/xdri/driinit.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef DRIINIT_INCLUDED -#define DRIINIT_INCLUDED - -#include "glxclient.h" - -extern __GLXDRIdisplay * -__driCreateDisplay(__GLXdisplayPrivate *dpyPriv, int *version); - -#endif /* DRIINIT_INCLUDED */ diff --git a/src/egl/drivers/xdri/egl_xdri.c b/src/egl/drivers/xdri/egl_xdri.c deleted file mode 100644 index 555473c00a..0000000000 --- a/src/egl/drivers/xdri/egl_xdri.c +++ /dev/null @@ -1,625 +0,0 @@ -/************************************************************************** - * - * 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. - * - **************************************************************************/ - - -/** - * Code to interface a DRI driver to libEGL. - * Note that unlike previous DRI/EGL interfaces, this one is meant to - * be used _with_ X. Applications will use eglCreateWindowSurface() - * to render into X-created windows. - * - * This is an EGL driver that, in turn, loads a regular DRI driver. - * There are some dependencies on code in libGL, but those could be - * removed with some effort. - * - * Authors: Brian Paul - */ - -#include <assert.h> -#include <stdlib.h> -#include <X11/Xlib.h> - -#include "glxinit.h" -#include "driinit.h" -#include "glapi/glapi.h" /* for glapi functions */ - -#include "eglconfig.h" -#include "eglconfigutil.h" -#include "eglcontext.h" -#include "egldisplay.h" -#include "egldriver.h" -#include "eglcurrent.h" -#include "egllog.h" -#include "eglsurface.h" - -#define CALLOC_STRUCT(T) (struct T *) calloc(1, sizeof(struct T)) - -/** subclass of _EGLDriver */ -struct xdri_egl_driver -{ - _EGLDriver Base; /**< base class */ - void (*FlushCurrentContext)(void); -}; - - -/** driver data of _EGLDisplay */ -struct xdri_egl_display -{ - Display *dpy; - __GLXdisplayPrivate *dpyPriv; - __GLXDRIdisplay *driDisplay; - int driVersion; - - __GLXscreenConfigs *psc; - EGLint scr; -}; - - -/** subclass of _EGLContext */ -struct xdri_egl_context -{ - _EGLContext Base; /**< base class */ - - /* just enough info to create dri contexts */ - GLXContext dummy_gc; - - __GLXDRIcontext *driContext; -}; - - -/** subclass of _EGLSurface */ -struct xdri_egl_surface -{ - _EGLSurface Base; /**< base class */ - - Drawable drawable; - __GLXDRIdrawable *driDrawable; -}; - - -/** subclass of _EGLConfig */ -struct xdri_egl_config -{ - _EGLConfig Base; /**< base class */ - - const __GLcontextModes *mode; /**< corresponding GLX mode */ - EGLint window_render_buffer; -}; - - - -/* standard typecasts */ -_EGL_DRIVER_STANDARD_TYPECASTS(xdri_egl) - -#define lookup_display(dpy) xdri_egl_display(dpy) -#define lookup_context(ctx) xdri_egl_context(ctx) -#define lookup_surface(surf) xdri_egl_surface(surf) -#define lookup_config(conf) xdri_egl_config(conf) - - -/** Get size of given window */ -static Status -get_drawable_size(Display *dpy, Drawable d, uint *width, uint *height) -{ - Window root; - Status stat; - int xpos, ypos; - unsigned int w, h, bw, depth; - stat = XGetGeometry(dpy, d, &root, &xpos, &ypos, &w, &h, &bw, &depth); - *width = w; - *height = h; - return stat; -} - - -static EGLBoolean -convert_config(_EGLConfig *conf, EGLint id, const __GLcontextModes *m) -{ - EGLint val; - - if (!_eglConfigFromContextModesRec(conf, m, EGL_OPENGL_BIT, EGL_OPENGL_BIT)) - return EGL_FALSE; - - if (m->doubleBufferMode) { - /* pixmap and pbuffer surfaces are always single-buffered */ - val = GET_CONFIG_ATTRIB(conf, EGL_SURFACE_TYPE); - val &= ~(EGL_PIXMAP_BIT | EGL_PBUFFER_BIT); - SET_CONFIG_ATTRIB(conf, EGL_SURFACE_TYPE, val); - } - else { - /* EGL requires OpenGL ES context to be double-buffered */ - val = GET_CONFIG_ATTRIB(conf, EGL_RENDERABLE_TYPE); - val &= ~(EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT); - SET_CONFIG_ATTRIB(conf, EGL_RENDERABLE_TYPE, val); - } - /* skip "empty" config */ - if (!val) - return EGL_FALSE; - - val = GET_CONFIG_ATTRIB(conf, EGL_SURFACE_TYPE); - if (!(val & EGL_PBUFFER_BIT)) { - /* bind-to-texture cannot be EGL_TRUE without pbuffer bit */ - SET_CONFIG_ATTRIB(conf, EGL_BIND_TO_TEXTURE_RGB, EGL_FALSE); - SET_CONFIG_ATTRIB(conf, EGL_BIND_TO_TEXTURE_RGBA, EGL_FALSE); - } - - /* EGL_NATIVE_RENDERABLE is a boolean */ - val = GET_CONFIG_ATTRIB(conf, EGL_NATIVE_RENDERABLE); - if (val != EGL_TRUE) - SET_CONFIG_ATTRIB(conf, EGL_NATIVE_RENDERABLE, EGL_FALSE); - - return _eglValidateConfig(conf, EGL_FALSE); -} - - -/** - * Produce a set of EGL configs. - */ -static EGLint -create_configs(_EGLDisplay *disp, const __GLcontextModes *m, EGLint first_id) -{ - struct xdri_egl_display *xdri_dpy = lookup_display(disp); - int id = first_id; - - for (; m; m = m->next) { - struct xdri_egl_config *xdri_conf; - _EGLConfig conf; - EGLint rb; - - _eglInitConfig(&conf, disp, id); - if (!convert_config(&conf, id, m)) - continue; - if (m->doubleBufferMode) { - rb = EGL_BACK_BUFFER; - } - else { - /* ignore single-buffered mode for DRISW */ - if (xdri_dpy->driVersion == 0) - continue; - rb = EGL_SINGLE_BUFFER; - } - - xdri_conf = CALLOC_STRUCT(xdri_egl_config); - if (xdri_conf) { - memcpy(&xdri_conf->Base, &conf, sizeof(conf)); - xdri_conf->mode = m; - xdri_conf->window_render_buffer = rb; - _eglAddConfig(disp, &xdri_conf->Base); - id++; - } - } - - return id; -} - - -/** - * Called via eglInitialize(), xdri_dpy->API.Initialize(). - */ -static EGLBoolean -xdri_eglInitialize(_EGLDriver *drv, _EGLDisplay *dpy, - EGLint *minor, EGLint *major) -{ - struct xdri_egl_display *xdri_dpy; - __GLXdisplayPrivate *dpyPriv; - __GLXDRIdisplay *driDisplay; - __GLXscreenConfigs *psc; - EGLint first_id = 1; - int scr; - - xdri_dpy = CALLOC_STRUCT(xdri_egl_display); - if (!xdri_dpy) - return _eglError(EGL_BAD_ALLOC, "eglInitialize"); - - xdri_dpy->dpy = (Display *) dpy->NativeDisplay; - if (!xdri_dpy->dpy) { - xdri_dpy->dpy = XOpenDisplay(NULL); - if (!xdri_dpy->dpy) { - free(xdri_dpy); - return _eglError(EGL_NOT_INITIALIZED, "eglInitialize"); - } - } - - dpyPriv = __glXInitialize(xdri_dpy->dpy); - if (!dpyPriv) { - _eglLog(_EGL_WARNING, "failed to create GLX display"); - free(xdri_dpy); - return _eglError(EGL_NOT_INITIALIZED, "eglInitialize"); - } - - driDisplay = __driCreateDisplay(dpyPriv, &xdri_dpy->driVersion); - if (!driDisplay) { - _eglLog(_EGL_WARNING, "failed to create DRI display"); - free(xdri_dpy); - return _eglError(EGL_NOT_INITIALIZED, "eglInitialize"); - } - - scr = DefaultScreen(xdri_dpy->dpy); - psc = &dpyPriv->screenConfigs[scr]; - - xdri_dpy->dpyPriv = dpyPriv; - xdri_dpy->driDisplay = driDisplay; - xdri_dpy->psc = psc; - xdri_dpy->scr = scr; - - psc->driScreen = driDisplay->createScreen(psc, scr, dpyPriv); - if (!psc->driScreen) { - _eglLog(_EGL_WARNING, "failed to create DRI screen #%d", scr); - free(xdri_dpy); - return _eglError(EGL_NOT_INITIALIZED, "eglInitialize"); - } - - dpy->DriverData = xdri_dpy; - dpy->ClientAPIsMask = EGL_OPENGL_BIT; - - /* add visuals and fbconfigs */ - first_id = create_configs(dpy, psc->visuals, first_id); - create_configs(dpy, psc->configs, first_id); - - /* we're supporting EGL 1.4 */ - *minor = 1; - *major = 4; - - return EGL_TRUE; -} - - -/** - * Called via eglTerminate(), drv->API.Terminate(). - */ -static EGLBoolean -xdri_eglTerminate(_EGLDriver *drv, _EGLDisplay *dpy) -{ - struct xdri_egl_display *xdri_dpy = lookup_display(dpy); - __GLXscreenConfigs *psc; - - _eglReleaseDisplayResources(drv, dpy); - _eglCleanupDisplay(dpy); - - psc = xdri_dpy->psc; - if (psc->driver_configs) { - unsigned int i; - for (i = 0; psc->driver_configs[i]; i++) - free((__DRIconfig *) psc->driver_configs[i]); - free(psc->driver_configs); - psc->driver_configs = NULL; - } - if (psc->driScreen) { - psc->driScreen->destroyScreen(psc); - free(psc->driScreen); - psc->driScreen = NULL; - } - - xdri_dpy->driDisplay->destroyDisplay(xdri_dpy->driDisplay); - - free(xdri_dpy); - dpy->DriverData = NULL; - - return EGL_TRUE; -} - - -/* - * Called from eglGetProcAddress() via drv->API.GetProcAddress(). - */ -static _EGLProc -xdri_eglGetProcAddress(_EGLDriver *drv, const char *procname) -{ - /* the symbol is defined in libGL.so */ - return (_EGLProc) _glapi_get_proc_address(procname); -} - - -/** - * Called via eglCreateContext(), drv->API.CreateContext(). - */ -static _EGLContext * -xdri_eglCreateContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, - _EGLContext *share_list, const EGLint *attrib_list) -{ - struct xdri_egl_display *xdri_dpy = lookup_display(dpy); - struct xdri_egl_config *xdri_config = lookup_config(conf); - struct xdri_egl_context *shared = lookup_context(share_list); - __GLXscreenConfigs *psc = xdri_dpy->psc; - int renderType = GLX_RGBA_BIT; - struct xdri_egl_context *xdri_ctx; - - xdri_ctx = CALLOC_STRUCT(xdri_egl_context); - if (!xdri_ctx) { - _eglError(EGL_BAD_ALLOC, "eglCreateContext"); - return NULL; - } - - xdri_ctx->dummy_gc = CALLOC_STRUCT(__GLXcontextRec); - if (!xdri_ctx->dummy_gc) { - _eglError(EGL_BAD_ALLOC, "eglCreateContext"); - free(xdri_ctx); - return NULL; - } - - if (!_eglInitContext(&xdri_ctx->Base, dpy, &xdri_config->Base, attrib_list)) { - free(xdri_ctx->dummy_gc); - free(xdri_ctx); - return NULL; - } - - /* the config decides the render buffer for the context */ - xdri_ctx->Base.WindowRenderBuffer = xdri_config->window_render_buffer; - - xdri_ctx->driContext = - psc->driScreen->createContext(psc, - xdri_config->mode, - xdri_ctx->dummy_gc, - (shared) ? shared->dummy_gc : NULL, - renderType); - if (!xdri_ctx->driContext) { - free(xdri_ctx->dummy_gc); - free(xdri_ctx); - return NULL; - } - - /* fill in the required field */ - xdri_ctx->dummy_gc->driContext = xdri_ctx->driContext; - - return &xdri_ctx->Base; -} - - -/** - * Destroy a context. - */ -static void -destroy_context(_EGLDisplay *dpy, _EGLContext *ctx) -{ - struct xdri_egl_display *xdri_dpy = lookup_display(dpy); - struct xdri_egl_context *xdri_ctx = lookup_context(ctx); - - /* FIXME a context might live longer than its display */ - if (!dpy->Initialized) - _eglLog(_EGL_FATAL, "destroy a context with an unitialized display"); - - xdri_ctx->driContext->destroyContext(xdri_ctx->driContext, - xdri_dpy->psc, xdri_dpy->dpy); - free(xdri_ctx->dummy_gc); - free(xdri_ctx); -} - - -/** - * Destroy a surface. - */ -static void -destroy_surface(_EGLDisplay *dpy, _EGLSurface *surf) -{ - struct xdri_egl_surface *xdri_surf = lookup_surface(surf); - - if (!dpy->Initialized) - _eglLog(_EGL_FATAL, "destroy a surface with an unitialized display"); - - xdri_surf->driDrawable->destroyDrawable(xdri_surf->driDrawable); - free(xdri_surf); -} - - -static EGLBoolean -xdri_eglDestroyContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx) -{ - if (!_eglIsContextBound(ctx)) - destroy_context(dpy, ctx); - return EGL_TRUE; -} - - -/** - * Called via eglMakeCurrent(), drv->API.MakeCurrent(). - */ -static EGLBoolean -xdri_eglMakeCurrent(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *d, - _EGLSurface *r, _EGLContext *context) -{ - struct xdri_egl_driver *xdri_driver = xdri_egl_driver(drv); - struct xdri_egl_context *xdri_ctx = lookup_context(context); - struct xdri_egl_surface *draw = lookup_surface(d); - struct xdri_egl_surface *read = lookup_surface(r); - - /* bind the new context and return the "orphaned" one */ - if (!_eglBindContext(&context, &d, &r)) - return EGL_FALSE; - - /* flush before context switch */ - if (context && xdri_driver->FlushCurrentContext) - xdri_driver->FlushCurrentContext(); - - /* the symbol is defined in libGL.so */ - _glapi_check_multithread(); - - if (xdri_ctx) { - if (!xdri_ctx->driContext->bindContext(xdri_ctx->driContext, - draw->driDrawable, - read->driDrawable)) { - return EGL_FALSE; - } - } - else if (context) { - xdri_ctx = lookup_context(context); - xdri_ctx->driContext->unbindContext(xdri_ctx->driContext); - } - - if (context && !_eglIsContextLinked(context)) - destroy_context(dpy, context); - if (d && !_eglIsSurfaceLinked(d)) - destroy_surface(dpy, d); - if (r && r != d && !_eglIsSurfaceLinked(r)) - destroy_surface(dpy, r); - - return EGL_TRUE; -} - - -/** - * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface(). - */ -static _EGLSurface * -xdri_eglCreateWindowSurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, - EGLNativeWindowType window, - const EGLint *attrib_list) -{ - struct xdri_egl_display *xdri_dpy = lookup_display(dpy); - struct xdri_egl_config *xdri_config = lookup_config(conf); - struct xdri_egl_surface *xdri_surf; - uint width, height; - - xdri_surf = CALLOC_STRUCT(xdri_egl_surface); - if (!xdri_surf) { - _eglError(EGL_BAD_ALLOC, "eglCreateWindowSurface"); - return NULL; - } - - if (!_eglInitSurface(&xdri_surf->Base, dpy, EGL_WINDOW_BIT, - &xdri_config->Base, attrib_list)) { - free(xdri_surf); - return NULL; - } - - xdri_surf->driDrawable = - xdri_dpy->psc->driScreen->createDrawable(xdri_dpy->psc, - (XID) window, - (GLXDrawable) window, - xdri_config->mode); - if (!xdri_surf->driDrawable) { - free(xdri_surf); - return NULL; - } - - xdri_surf->drawable = (Drawable) window; - - get_drawable_size(xdri_dpy->dpy, window, &width, &height); - xdri_surf->Base.Width = width; - xdri_surf->Base.Height = height; - - return &xdri_surf->Base; -} - - -/** - * Called via eglCreatePbufferSurface(), drv->API.CreatePbufferSurface(). - */ -static _EGLSurface * -xdri_eglCreatePbufferSurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, - const EGLint *attrib_list) -{ - return NULL; -} - - - -static EGLBoolean -xdri_eglDestroySurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface) -{ - if (!_eglIsSurfaceBound(surface)) - destroy_surface(dpy, surface); - return EGL_TRUE; -} - - -static EGLBoolean -xdri_eglBindTexImage(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, - EGLint buffer) -{ - return EGL_FALSE; -} - - -static EGLBoolean -xdri_eglReleaseTexImage(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, - EGLint buffer) -{ - return EGL_FALSE; -} - - -static EGLBoolean -xdri_eglSwapBuffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *draw) -{ - struct xdri_egl_driver *xdri_driver = xdri_egl_driver(drv); - struct xdri_egl_display *xdri_dpy = lookup_display(dpy); - struct xdri_egl_surface *xdri_surf = lookup_surface(draw); - - /* swapBuffers does not flush commands */ - if (draw->CurrentContext && xdri_driver->FlushCurrentContext) - xdri_driver->FlushCurrentContext(); - - xdri_dpy->psc->driScreen->swapBuffers(xdri_surf->driDrawable, 0, 0, 0); - - return EGL_TRUE; -} - - -static void -xdri_Unload(_EGLDriver *drv) -{ - struct xdri_egl_driver *xdri_drv = xdri_egl_driver(drv); - free(xdri_drv); -} - - -/** - * This is the main entrypoint into the driver, called by libEGL. - * Create a new _EGLDriver object and init its dispatch table. - */ -_EGLDriver * -_eglMain(const char *args) -{ - struct xdri_egl_driver *xdri_drv = CALLOC_STRUCT(xdri_egl_driver); - if (!xdri_drv) - return NULL; - - _eglInitDriverFallbacks(&xdri_drv->Base); - xdri_drv->Base.API.Initialize = xdri_eglInitialize; - xdri_drv->Base.API.Terminate = xdri_eglTerminate; - - xdri_drv->Base.API.GetProcAddress = xdri_eglGetProcAddress; - - xdri_drv->Base.API.CreateContext = xdri_eglCreateContext; - xdri_drv->Base.API.DestroyContext = xdri_eglDestroyContext; - xdri_drv->Base.API.MakeCurrent = xdri_eglMakeCurrent; - xdri_drv->Base.API.CreateWindowSurface = xdri_eglCreateWindowSurface; - xdri_drv->Base.API.CreatePbufferSurface = xdri_eglCreatePbufferSurface; - xdri_drv->Base.API.DestroySurface = xdri_eglDestroySurface; - xdri_drv->Base.API.BindTexImage = xdri_eglBindTexImage; - xdri_drv->Base.API.ReleaseTexImage = xdri_eglReleaseTexImage; - xdri_drv->Base.API.SwapBuffers = xdri_eglSwapBuffers; - - xdri_drv->Base.Name = "X/DRI"; - xdri_drv->Base.Unload = xdri_Unload; - - /* we need a way to flush commands */ - xdri_drv->FlushCurrentContext = - (void (*)(void)) xdri_eglGetProcAddress(&xdri_drv->Base, "glFlush"); - - return &xdri_drv->Base; -} diff --git a/src/egl/main/eglconfig.c b/src/egl/main/eglconfig.c index 635ffee92b..1190f8cdd5 100644 --- a/src/egl/main/eglconfig.c +++ b/src/egl/main/eglconfig.c @@ -366,8 +366,11 @@ _eglValidateConfig(const _EGLConfig *conf, EGLBoolean for_matching) if (_eglValidationTable[i].criterion == ATTRIB_CRITERION_SPECIAL) valid = EGL_TRUE; } - if (!valid) + if (!valid) { + _eglLog(_EGL_DEBUG, + "attribute 0x%04x has an invalid value 0x%x", attr, val); break; + } } /* any invalid attribute value should have been catched */ @@ -390,10 +393,18 @@ _eglValidateConfig(const _EGLConfig *conf, EGLBoolean for_matching) valid = EGL_FALSE; break; } + if (!valid) { + _eglLog(_EGL_DEBUG, "conflicting color buffer type and channel sizes"); + return EGL_FALSE; + } val = GET_CONFIG_ATTRIB(conf, EGL_SAMPLE_BUFFERS); if (!val && GET_CONFIG_ATTRIB(conf, EGL_SAMPLES)) valid = EGL_FALSE; + if (!valid) { + _eglLog(_EGL_DEBUG, "conflicting samples and sample buffers"); + return EGL_FALSE; + } val = GET_CONFIG_ATTRIB(conf, EGL_SURFACE_TYPE); if (!(val & EGL_WINDOW_BIT)) { @@ -406,6 +417,10 @@ _eglValidateConfig(const _EGLConfig *conf, EGLBoolean for_matching) GET_CONFIG_ATTRIB(conf, EGL_BIND_TO_TEXTURE_RGBA)) valid = EGL_FALSE; } + if (!valid) { + _eglLog(_EGL_DEBUG, "conflicting surface type and native visual/texture binding"); + return EGL_FALSE; + } return valid; } @@ -457,8 +472,14 @@ _eglMatchConfig(const _EGLConfig *conf, const _EGLConfig *criteria) break; } - if (!matched) + if (!matched) { +#ifdef DEBUG + _eglLog(_EGL_DEBUG, + "the value (0x%x) of attribute 0x%04x did not meet the criteria (0x%x)", + val, attr, cmp); +#endif break; + } } return matched; diff --git a/src/egl/main/eglconfig.h b/src/egl/main/eglconfig.h index 09dc61f547..56ec95fe9a 100644 --- a/src/egl/main/eglconfig.h +++ b/src/egl/main/eglconfig.h @@ -21,6 +21,9 @@ struct _egl_config }; +/** + * Macros for source level compatibility. + */ #define SET_CONFIG_ATTRIB(CONF, ATTR, VAL) _eglSetConfigKey(CONF, ATTR, VAL) #define GET_CONFIG_ATTRIB(CONF, ATTR) _eglGetConfigKey(CONF, ATTR) @@ -55,6 +58,10 @@ _eglResetConfigKeys(_EGLConfig *conf, EGLint val) /** * Update a config for a given key. + * + * Note that a valid key is not necessarily a valid attribute. There are gaps + * in the attribute enums. The separation is to catch application errors. + * Drivers should never set a key that is an invalid attribute. */ static INLINE void _eglSetConfigKey(_EGLConfig *conf, EGLint key, EGLint val) @@ -77,20 +84,6 @@ _eglGetConfigKey(const _EGLConfig *conf, EGLint key) } -/** - * Set a given attribute. - * - * Because _eglGetConfigAttrib is already used as a fallback driver - * function, this function is not considered to have a good name. - * SET_CONFIG_ATTRIB is preferred over this function. - */ -static INLINE void -_eglSetConfigAttrib(_EGLConfig *conf, EGLint attr, EGLint val) -{ - SET_CONFIG_ATTRIB(conf, attr, val); -} - - PUBLIC void _eglInitConfig(_EGLConfig *config, _EGLDisplay *dpy, EGLint id); diff --git a/src/egl/main/eglcontext.h b/src/egl/main/eglcontext.h index 14fce02c11..cfe92dd9f5 100644 --- a/src/egl/main/eglcontext.h +++ b/src/egl/main/eglcontext.h @@ -60,6 +60,9 @@ _eglCopyContextMESA(_EGLDriver *drv, EGLDisplay dpy, EGLContext source, EGLConte /** * Return true if the context is bound to a thread. + * + * The binding is considered a reference to the context. Drivers should not + * destroy a context when it is bound. */ static INLINE EGLBoolean _eglIsContextBound(_EGLContext *ctx) @@ -119,6 +122,9 @@ _eglGetContextHandle(_EGLContext *ctx) /** * Return true if the context is linked to a display. + * + * The link is considered a reference to the context (the display is owning the + * context). Drivers should not destroy a context when it is linked. */ static INLINE EGLBoolean _eglIsContextLinked(_EGLContext *ctx) diff --git a/src/egl/main/egldriver.h b/src/egl/main/egldriver.h index c1e6fa2820..55686681dc 100644 --- a/src/egl/main/egldriver.h +++ b/src/egl/main/egldriver.h @@ -8,6 +8,9 @@ /** * Define an inline driver typecast function. + * + * Note that this macro defines a function and should not be ended with a + * semicolon when used. */ #define _EGL_DRIVER_TYPECAST(drvtype, egltype, code) \ static INLINE struct drvtype *drvtype(const egltype *obj) \ @@ -17,6 +20,9 @@ /** * Define the driver typecast functions for _EGLDriver, _EGLDisplay, * _EGLContext, _EGLSurface, and _EGLConfig. + * + * Note that this macro defines several functions and should not be ended with + * a semicolon when used. */ #define _EGL_DRIVER_STANDARD_TYPECASTS(drvname) \ _EGL_DRIVER_TYPECAST(drvname ## _driver, _EGLDriver, obj) \ diff --git a/src/egl/main/eglsurface.h b/src/egl/main/eglsurface.h index feba30d4f8..0a00035730 100644 --- a/src/egl/main/eglsurface.h +++ b/src/egl/main/eglsurface.h @@ -107,6 +107,9 @@ _eglCreatePbufferFromClientBuffer(_EGLDriver *drv, _EGLDisplay *dpy, /** * Return true if there is a context bound to the surface. + * + * The binding is considered a reference to the surface. Drivers should not + * destroy a surface when it is bound. */ static INLINE EGLBoolean _eglIsSurfaceBound(_EGLSurface *surf) @@ -166,6 +169,9 @@ _eglGetSurfaceHandle(_EGLSurface *surf) /** * Return true if the surface is linked to a display. + * + * The link is considered a reference to the surface (the display is owning the + * surface). Drivers should not destroy a surface when it is linked. */ static INLINE EGLBoolean _eglIsSurfaceLinked(_EGLSurface *surf) diff --git a/src/gallium/state_trackers/egl/Makefile b/src/gallium/state_trackers/egl/Makefile index b696f2fae9..2863320a48 100644 --- a/src/gallium/state_trackers/egl/Makefile +++ b/src/gallium/state_trackers/egl/Makefile @@ -15,13 +15,11 @@ 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 + $(TOP)/src/glx/x11/dri2.c x11_OBJECTS = $(x11_SOURCES:.c=.o) diff --git a/src/egl/drivers/xdri/glxinit.c b/src/gallium/state_trackers/egl/x11/glxinit.c index ba6132788a..ba6132788a 100644 --- a/src/egl/drivers/xdri/glxinit.c +++ b/src/gallium/state_trackers/egl/x11/glxinit.c diff --git a/src/egl/drivers/xdri/glxinit.h b/src/gallium/state_trackers/egl/x11/glxinit.h index 1cc7c460fe..1cc7c460fe 100644 --- a/src/egl/drivers/xdri/glxinit.h +++ b/src/gallium/state_trackers/egl/x11/glxinit.h diff --git a/src/gallium/state_trackers/egl/x11/x11_screen.c b/src/gallium/state_trackers/egl/x11/x11_screen.c index 76ce45ee57..d72bfc99d3 100644 --- a/src/gallium/state_trackers/egl/x11/x11_screen.c +++ b/src/gallium/state_trackers/egl/x11/x11_screen.c @@ -43,7 +43,7 @@ struct x11_screen { int number; /* - * This is used to fetch GLX visuals/fbconfigs. It uses code from egl_xdri. + * This is used to fetch GLX visuals/fbconfigs. It steals code from GLX. * It might be better to rewrite the part in Xlib or XCB. */ __GLXdisplayPrivate *glx_dpy; diff --git a/src/mesa/drivers/dri/i915/i915_fragprog.c b/src/mesa/drivers/dri/i915/i915_fragprog.c index a273bd28ea..15e3b87097 100644 --- a/src/mesa/drivers/dri/i915/i915_fragprog.c +++ b/src/mesa/drivers/dri/i915/i915_fragprog.c @@ -1205,7 +1205,7 @@ i915IsProgramNative(GLcontext * ctx, GLenum target, struct gl_program *prog) return GL_TRUE; } -static void +static GLboolean i915ProgramStringNotify(GLcontext * ctx, GLenum target, struct gl_program *prog) { @@ -1223,7 +1223,10 @@ i915ProgramStringNotify(GLcontext * ctx, } } - _tnl_program_string(ctx, target, prog); + (void) _tnl_program_string(ctx, target, prog); + + /* XXX check if program is legal, within limits */ + return GL_TRUE; } void diff --git a/src/mesa/drivers/dri/i965/brw_program.c b/src/mesa/drivers/dri/i965/brw_program.c index e3b6fccc49..c78f7b38ae 100644 --- a/src/mesa/drivers/dri/i965/brw_program.c +++ b/src/mesa/drivers/dri/i965/brw_program.c @@ -111,9 +111,10 @@ static GLboolean brwIsProgramNative( GLcontext *ctx, return GL_TRUE; } -static void brwProgramStringNotify( GLcontext *ctx, - GLenum target, - struct gl_program *prog ) + +static GLboolean brwProgramStringNotify( GLcontext *ctx, + GLenum target, + struct gl_program *prog ) { struct brw_context *brw = brw_context(ctx); @@ -150,6 +151,9 @@ static void brwProgramStringNotify( GLcontext *ctx, */ _tnl_program_string(ctx, target, prog); } + + /* XXX check if program is legal, within limits */ + return GL_TRUE; } void brwInitFragProgFuncs( struct dd_function_table *functions ) diff --git a/src/mesa/drivers/dri/r200/r200_cmdbuf.c b/src/mesa/drivers/dri/r200/r200_cmdbuf.c index 3135d5330d..2f2b8d94dc 100644 --- a/src/mesa/drivers/dri/r200/r200_cmdbuf.c +++ b/src/mesa/drivers/dri/r200/r200_cmdbuf.c @@ -88,6 +88,7 @@ void r200SetUpAtomList( r200ContextPtr rmesa ) insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.pix[i] ); insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.afs[0] ); insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.afs[1] ); + insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.stp ); for (i = 0; i < 8; ++i) insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.lit[i] ); for (i = 0; i < 3 + mtu; ++i) diff --git a/src/mesa/drivers/dri/r200/r200_state.c b/src/mesa/drivers/dri/r200/r200_state.c index d9bf31b611..d6964484bf 100644 --- a/src/mesa/drivers/dri/r200/r200_state.c +++ b/src/mesa/drivers/dri/r200/r200_state.c @@ -2464,6 +2464,12 @@ static void r200PolygonStipple( GLcontext *ctx, const GLubyte *mask ) radeon_firevertices(&r200->radeon); + radeon_print(RADEON_STATE, RADEON_TRACE, + "%s(%p) first 32 bits are %x.\n", + __func__, + ctx, + *(uint32_t*)mask); + R200_STATECHANGE(r200, stp); /* Must flip pattern upside down. diff --git a/src/mesa/drivers/dri/r200/r200_vertprog.c b/src/mesa/drivers/dri/r200/r200_vertprog.c index 4f225a233d..12f869d96f 100644 --- a/src/mesa/drivers/dri/r200/r200_vertprog.c +++ b/src/mesa/drivers/dri/r200/r200_vertprog.c @@ -1218,7 +1218,7 @@ r200DeleteProgram(GLcontext *ctx, struct gl_program *prog) _mesa_delete_program(ctx, prog); } -static void +static GLboolean r200ProgramStringNotify(GLcontext *ctx, GLenum target, struct gl_program *prog) { struct r200_vertex_program *vp = (void *)prog; @@ -1237,7 +1237,10 @@ r200ProgramStringNotify(GLcontext *ctx, GLenum target, struct gl_program *prog) break; } /* need this for tcl fallbacks */ - _tnl_program_string(ctx, target, prog); + (void) _tnl_program_string(ctx, target, prog); + + /* XXX check if program is legal, within limits */ + return GL_TRUE; } static GLboolean diff --git a/src/mesa/drivers/dri/r300/r300_shader.c b/src/mesa/drivers/dri/r300/r300_shader.c index a4f9db13ec..3638010e48 100644 --- a/src/mesa/drivers/dri/r300/r300_shader.c +++ b/src/mesa/drivers/dri/r300/r300_shader.c @@ -98,7 +98,7 @@ static void r300DeleteProgram(GLcontext * ctx, struct gl_program *prog) _mesa_delete_program(ctx, prog); } -static void +static GLboolean r300ProgramStringNotify(GLcontext * ctx, GLenum target, struct gl_program *prog) { struct r300_vertex_program_cont *vp = (struct r300_vertex_program_cont *)prog; @@ -116,7 +116,10 @@ r300ProgramStringNotify(GLcontext * ctx, GLenum target, struct gl_program *prog) } /* need this for tcl fallbacks */ - _tnl_program_string(ctx, target, prog); + (void) _tnl_program_string(ctx, target, prog); + + /* XXX check if program is legal, within limits */ + return GL_TRUE; } static GLboolean diff --git a/src/mesa/drivers/dri/r600/r700_oglprog.c b/src/mesa/drivers/dri/r600/r700_oglprog.c index 0d476fcd86..2a50361199 100644 --- a/src/mesa/drivers/dri/r600/r700_oglprog.c +++ b/src/mesa/drivers/dri/r600/r700_oglprog.c @@ -132,7 +132,7 @@ static void r700DeleteProgram(GLcontext * ctx, struct gl_program *prog) _mesa_delete_program(ctx, prog); } -static void +static GLboolean r700ProgramStringNotify(GLcontext * ctx, GLenum target, struct gl_program *prog) { struct r700_vertex_program_cont *vpc = (struct r700_vertex_program_cont *)prog; @@ -153,6 +153,8 @@ r700ProgramStringNotify(GLcontext * ctx, GLenum target, struct gl_program *prog) break; } + /* XXX check if program is legal, within limits */ + return GL_TRUE; } static GLboolean r700IsProgramNative(GLcontext * ctx, GLenum target, struct gl_program *prog) diff --git a/src/mesa/drivers/dri/radeon/radeon_debug.h b/src/mesa/drivers/dri/radeon/radeon_debug.h index 26da31c1c4..ef8b9671ac 100644 --- a/src/mesa/drivers/dri/radeon/radeon_debug.h +++ b/src/mesa/drivers/dri/radeon/radeon_debug.h @@ -47,7 +47,11 @@ typedef enum radeon_debug_levels { * errors. */ #ifndef RADEON_DEBUG_LEVEL -#define RADEON_DEBUG_LEVEL RADEON_VERBOSE +# ifdef DEBUG +# define RADEON_DEBUG_LEVEL RADEON_TRACE +# else +# define RADEON_DEBUG_LEVEL RADEON_VERBOSE +# endif #endif typedef enum radeon_debug_types { diff --git a/src/mesa/drivers/dri/radeon/radeon_ioctl.c b/src/mesa/drivers/dri/radeon/radeon_ioctl.c index 4fd60ac18e..db0e4f2f7a 100644 --- a/src/mesa/drivers/dri/radeon/radeon_ioctl.c +++ b/src/mesa/drivers/dri/radeon/radeon_ioctl.c @@ -92,6 +92,7 @@ void radeonSetUpAtomList( r100ContextPtr rmesa ) insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.lit[i]); for (i = 0; i < 6; ++i) insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.ucp[i]); + insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.stp); insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.eye); insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.grd); insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.fog); diff --git a/src/mesa/main/dd.h b/src/mesa/main/dd.h index 6705c901dd..d98a14e09c 100644 --- a/src/mesa/main/dd.h +++ b/src/mesa/main/dd.h @@ -581,9 +581,13 @@ struct dd_function_table { struct gl_program * (*NewProgram)(GLcontext *ctx, GLenum target, GLuint id); /** Delete a program */ void (*DeleteProgram)(GLcontext *ctx, struct gl_program *prog); - /** Notify driver that a program string has been specified. */ - void (*ProgramStringNotify)(GLcontext *ctx, GLenum target, - struct gl_program *prog); + /** + * Notify driver that a program string (and GPU code) has been specified + * or modified. Return GL_TRUE or GL_FALSE to indicate if the program is + * supported by the driver. + */ + GLboolean (*ProgramStringNotify)(GLcontext *ctx, GLenum target, + struct gl_program *prog); /** Query if program can be loaded onto hardware */ GLboolean (*IsProgramNative)(GLcontext *ctx, GLenum target, diff --git a/src/mesa/main/texenvprogram.c b/src/mesa/main/texenvprogram.c index 499b7330d0..414607e228 100644 --- a/src/mesa/main/texenvprogram.c +++ b/src/mesa/main/texenvprogram.c @@ -1535,8 +1535,15 @@ create_new_program(GLcontext *ctx, struct state_key *key, /* Notify driver the fragment program has (actually) changed. */ if (ctx->Driver.ProgramStringNotify) { - ctx->Driver.ProgramStringNotify( ctx, GL_FRAGMENT_PROGRAM_ARB, - &p.program->Base ); + GLboolean ok = ctx->Driver.ProgramStringNotify(ctx, + GL_FRAGMENT_PROGRAM_ARB, + &p.program->Base); + /* Driver should be able to handle any texenv programs as long as + * the driver correctly reported max number of texture units correctly, + * etc. + */ + ASSERT(ok); + (void) ok; /* silence unused var warning */ } if (DISASSEM) { diff --git a/src/mesa/shader/arbprogram.c b/src/mesa/shader/arbprogram.c index 746138071e..7e3040a6ef 100644 --- a/src/mesa/shader/arbprogram.c +++ b/src/mesa/shader/arbprogram.c @@ -489,8 +489,13 @@ _mesa_ProgramStringARB(GLenum target, GLenum format, GLsizei len, return; } - if (ctx->Program.ErrorPos == -1 && ctx->Driver.ProgramStringNotify) - ctx->Driver.ProgramStringNotify( ctx, target, base ); + if (ctx->Program.ErrorPos == -1) { + /* finally, give the program to the driver for translation/checking */ + if (!ctx->Driver.ProgramStringNotify(ctx, target, base)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glProgramStringARB(rejected by driver"); + } + } } diff --git a/src/mesa/shader/atifragshader.c b/src/mesa/shader/atifragshader.c index e04a05b22f..ab7b2030d1 100644 --- a/src/mesa/shader/atifragshader.c +++ b/src/mesa/shader/atifragshader.c @@ -378,8 +378,11 @@ _mesa_EndFragmentShaderATI(void) } if (ctx->ATIFragmentShader.Current->cur_pass > 1) ctx->ATIFragmentShader.Current->NumPasses = 2; - else ctx->ATIFragmentShader.Current->NumPasses = 1; - ctx->ATIFragmentShader.Current->cur_pass=0; + else + ctx->ATIFragmentShader.Current->NumPasses = 1; + + ctx->ATIFragmentShader.Current->cur_pass = 0; + #if MESA_DEBUG_ATI_FS for (j = 0; j < MAX_NUM_PASSES_ATI; j++) { for (i = 0; i < MAX_NUM_FRAGMENT_REGISTERS_ATI; i++) { @@ -402,8 +405,13 @@ _mesa_EndFragmentShaderATI(void) } } #endif - if (ctx->Driver.ProgramStringNotify) - ctx->Driver.ProgramStringNotify( ctx, GL_FRAGMENT_SHADER_ATI, NULL ); + + if (!ctx->Driver.ProgramStringNotify(ctx, GL_FRAGMENT_SHADER_ATI, NULL)) { + ctx->ATIFragmentShader.Current->isValid = GL_FALSE; + /* XXX is this the right error? */ + _mesa_error(ctx, GL_INVALID_OPERATION, + "glEndFragmentShaderATI(driver rejected shader)"); + } } void GLAPIENTRY diff --git a/src/mesa/shader/shader_api.c b/src/mesa/shader/shader_api.c index d53580f5f6..e8eaa9c103 100644 --- a/src/mesa/shader/shader_api.c +++ b/src/mesa/shader/shader_api.c @@ -1715,7 +1715,11 @@ set_program_uniform(GLcontext *ctx, struct gl_program *program, */ FLUSH_VERTICES(ctx, _NEW_TEXTURE | _NEW_PROGRAM); _mesa_update_shader_textures_used(program); - ctx->Driver.ProgramStringNotify(ctx, program->Target, program); + /* Do we need to care about the return value here? + * This should not be the first time the driver was notified of + * this program. + */ + (void) ctx->Driver.ProgramStringNotify(ctx, program->Target, program); } } else { diff --git a/src/mesa/shader/slang/slang_link.c b/src/mesa/shader/slang/slang_link.c index 21497b34e2..df524ce078 100644 --- a/src/mesa/shader/slang/slang_link.c +++ b/src/mesa/shader/slang/slang_link.c @@ -719,6 +719,7 @@ _slang_link(GLcontext *ctx, { const struct gl_vertex_program *vertProg = NULL; const struct gl_fragment_program *fragProg = NULL; + GLboolean vertNotify = GL_TRUE, fragNotify = GL_TRUE; GLuint numSamplers = 0; GLuint i; @@ -871,8 +872,8 @@ _slang_link(GLcontext *ctx, _mesa_update_shader_textures_used(&shProg->FragmentProgram->Base); /* notify driver that a new fragment program has been compiled/linked */ - ctx->Driver.ProgramStringNotify(ctx, GL_FRAGMENT_PROGRAM_ARB, - &shProg->FragmentProgram->Base); + vertNotify = ctx->Driver.ProgramStringNotify(ctx, GL_FRAGMENT_PROGRAM_ARB, + &shProg->FragmentProgram->Base); if (ctx->Shader.Flags & GLSL_DUMP) { _mesa_printf("Mesa pre-link fragment program:\n"); _mesa_print_program(&fragProg->Base); @@ -889,8 +890,8 @@ _slang_link(GLcontext *ctx, _mesa_update_shader_textures_used(&shProg->VertexProgram->Base); /* notify driver that a new vertex program has been compiled/linked */ - ctx->Driver.ProgramStringNotify(ctx, GL_VERTEX_PROGRAM_ARB, - &shProg->VertexProgram->Base); + fragNotify = ctx->Driver.ProgramStringNotify(ctx, GL_VERTEX_PROGRAM_ARB, + &shProg->VertexProgram->Base); if (ctx->Shader.Flags & GLSL_DUMP) { _mesa_printf("Mesa pre-link vertex program:\n"); _mesa_print_program(&vertProg->Base); @@ -918,6 +919,12 @@ _slang_link(GLcontext *ctx, } } - shProg->LinkStatus = (shProg->VertexProgram || shProg->FragmentProgram); + if (!vertNotify || !fragNotify) { + /* driver rejected one/both of the vertex/fragment programs */ + link_error(shProg, "Vertex and/or fragment program rejected by driver\n"); + } + else { + shProg->LinkStatus = (shProg->VertexProgram || shProg->FragmentProgram); + } } diff --git a/src/mesa/state_tracker/st_cb_program.c b/src/mesa/state_tracker/st_cb_program.c index 86c53b4e76..82ef5572e1 100644 --- a/src/mesa/state_tracker/st_cb_program.c +++ b/src/mesa/state_tracker/st_cb_program.c @@ -177,9 +177,9 @@ static GLboolean st_is_program_native( GLcontext *ctx, } -static void st_program_string_notify( GLcontext *ctx, - GLenum target, - struct gl_program *prog ) +static GLboolean st_program_string_notify( GLcontext *ctx, + GLenum target, + struct gl_program *prog ) { struct st_context *st = st_context(ctx); @@ -211,6 +211,9 @@ static void st_program_string_notify( GLcontext *ctx, if (st->vp == stvp) st->dirty.st |= ST_NEW_VERTEX_PROGRAM; } + + /* XXX check if program is legal, within limits */ + return GL_TRUE; } diff --git a/src/mesa/tnl/t_vb_program.c b/src/mesa/tnl/t_vb_program.c index 5396548666..44b64b17d1 100644 --- a/src/mesa/tnl/t_vb_program.c +++ b/src/mesa/tnl/t_vb_program.c @@ -203,13 +203,14 @@ vp_fetch_texel(GLcontext *ctx, const GLfloat texcoord[4], GLfloat lambda, * Called via ctx->Driver.ProgramStringNotify() after a new vertex program * string has been parsed. */ -void +GLboolean _tnl_program_string(GLcontext *ctx, GLenum target, struct gl_program *program) { /* No-op. * If we had derived anything from the program that was private to this * stage we'd recompute/validate it here. */ + return GL_TRUE; } diff --git a/src/mesa/tnl/tnl.h b/src/mesa/tnl/tnl.h index 9c66d3b019..2c0d1fef73 100644 --- a/src/mesa/tnl/tnl.h +++ b/src/mesa/tnl/tnl.h @@ -66,7 +66,7 @@ _tnl_allow_vertex_fog( GLcontext *ctx, GLboolean value ); extern void _tnl_allow_pixel_fog( GLcontext *ctx, GLboolean value ); -extern void +extern GLboolean _tnl_program_string(GLcontext *ctx, GLenum target, struct gl_program *program); struct _mesa_prim; |