From cfc5bafcb2db8c6e05d7be6bb7315960be08c0d8 Mon Sep 17 00:00:00 2001 From: marha Date: Tue, 1 Jul 2014 08:46:12 +0200 Subject: fontconfig mesa pixman git update 1 July 2014 pixman commit 5a2edb3f2c2cfde6b25ac614e2004a9f78583d74 fontconfig commit dab60e4476ada4ad4639599ea24dd012d4a79584 mesa commit 1bfc0a11027449ae7ab7c28eb695f26de530eccf --- mesalib/configure.ac | 24 +-- mesalib/docs/GL3.txt | 16 +- mesalib/docs/relnotes/10.3.html | 2 + mesalib/include/GL/glx.h | 2 +- mesalib/include/GL/internal/dri_interface.h | 31 ++- mesalib/src/Makefile.am | 4 +- mesalib/src/gallium/Automake.inc | 23 +-- mesalib/src/glsl/ast.h | 5 + mesalib/src/glsl/ast_to_hir.cpp | 19 ++ mesalib/src/glsl/ast_type.cpp | 39 +++- mesalib/src/glsl/builtin_functions.cpp | 64 ++++++- mesalib/src/glsl/builtin_variables.cpp | 12 -- mesalib/src/glsl/glsl_parser.yy | 53 ++++++ mesalib/src/glsl/glsl_parser_extras.h | 18 ++ mesalib/src/glsl/glsl_types.h | 6 + mesalib/src/glsl/ir.h | 39 +++- mesalib/src/glsl/ir_hierarchical_visitor.cpp | 50 +++-- mesalib/src/glsl/ir_hierarchical_visitor.h | 6 +- mesalib/src/glsl/ir_hv_accept.cpp | 20 +- mesalib/src/glsl/ir_print_visitor.cpp | 20 +- mesalib/src/glsl/ir_reader.cpp | 28 ++- mesalib/src/glsl/ir_rvalue_visitor.cpp | 37 ++++ mesalib/src/glsl/ir_rvalue_visitor.h | 6 + mesalib/src/glsl/link_atomics.cpp | 13 +- mesalib/src/glsl/link_uniform_blocks.cpp | 6 + mesalib/src/glsl/link_varyings.cpp | 41 +++- mesalib/src/glsl/link_varyings.h | 17 ++ mesalib/src/glsl/linker.cpp | 150 +++++++++++++-- mesalib/src/glsl/lower_output_reads.cpp | 4 +- mesalib/src/glsl/lower_packed_varyings.cpp | 4 +- mesalib/src/glsl/opt_dead_code_local.cpp | 2 +- mesalib/src/loader/Makefile.am | 23 ++- mesalib/src/loader/loader.c | 212 +++++++++++++++++++++ mesalib/src/loader/loader.h | 7 + mesalib/src/mapi/glapi/gen/gl_API.xml | 8 +- mesalib/src/mesa/drivers/common/meta.c | 53 ++---- mesalib/src/mesa/drivers/dri/common/dri_util.c | 6 +- mesalib/src/mesa/drivers/dri/common/xmlconfig.c | 207 +++++++++++--------- mesalib/src/mesa/drivers/dri/common/xmlconfig.h | 29 +-- .../mesa/drivers/dri/common/xmlpool/t_options.h | 14 ++ mesalib/src/mesa/main/context.c | 3 - mesalib/src/mesa/main/dlist.c | 46 ----- mesalib/src/mesa/main/extensions.c | 3 +- mesalib/src/mesa/main/ff_fragment_shader.cpp | 80 -------- mesalib/src/mesa/main/format_pack.c | 25 --- mesalib/src/mesa/main/format_unpack.c | 14 -- mesalib/src/mesa/main/formats.c | 20 +- mesalib/src/mesa/main/formats.h | 2 - mesalib/src/mesa/main/glformats.c | 35 ---- mesalib/src/mesa/main/glformats.h | 3 - mesalib/src/mesa/main/mtypes.h | 14 +- mesalib/src/mesa/main/pack.c | 137 ------------- mesalib/src/mesa/main/pack.h | 8 - mesalib/src/mesa/main/queryobj.c | 18 +- mesalib/src/mesa/main/shaderapi.c | 1 + mesalib/src/mesa/main/shaderobj.c | 1 + mesalib/src/mesa/main/texenv.c | 198 ------------------- mesalib/src/mesa/main/texenv.h | 12 -- mesalib/src/mesa/main/texformat.c | 5 - mesalib/src/mesa/main/texgetimage.c | 5 - mesalib/src/mesa/main/teximage.c | 13 +- mesalib/src/mesa/main/texstate.c | 15 -- mesalib/src/mesa/main/texstore.c | 78 -------- mesalib/src/mesa/main/vdpau.c | 11 ++ mesalib/src/mesa/program/prog_statevars.c | 30 --- mesalib/src/mesa/program/prog_statevars.h | 2 - mesalib/src/mesa/program/program.c | 1 + mesalib/src/mesa/swrast/s_texcombine.c | 77 +------- mesalib/src/mesa/swrast/s_texfetch.c | 1 - mesalib/src/mesa/swrast/s_texfetch_tmp.h | 16 -- 70 files changed, 1080 insertions(+), 1114 deletions(-) (limited to 'mesalib') diff --git a/mesalib/configure.ac b/mesalib/configure.ac index e4cfb07ee..0d4fb0518 100644 --- a/mesalib/configure.ac +++ b/mesalib/configure.ac @@ -1317,6 +1317,7 @@ if test "x$enable_gallium_egl" = xyes; then GALLIUM_STATE_TRACKERS_DIRS="egl $GALLIUM_STATE_TRACKERS_DIRS" GALLIUM_TARGET_DIRS="$GALLIUM_TARGET_DIRS egl-static" +# enable_gallium_loader=yes fi AM_CONDITIONAL(HAVE_GALLIUM_EGL, test "x$enable_gallium_egl" = xyes) @@ -1425,6 +1426,7 @@ AM_CONDITIONAL(HAVE_ST_VDPAU, test "x$enable_vdpau" = xyes) if test "x$enable_omx" = xyes; then PKG_CHECK_MODULES([OMX], [libomxil-bellagio >= $LIBOMXIL_BELLAGIO_REQUIRED x11-xcb xcb-dri2 >= $XCBDRI2_REQUIRED]) GALLIUM_STATE_TRACKERS_DIRS="$GALLIUM_STATE_TRACKERS_DIRS omx" + enable_gallium_loader=yes fi AM_CONDITIONAL(HAVE_ST_OMX, test "x$enable_omx" = xyes) @@ -1602,7 +1604,7 @@ fi AC_ARG_WITH([egl-driver-dir], [AS_HELP_STRING([--with-egl-driver-dir=DIR], - [directory for EGL drivers [[default=${libdir}/egl]]])], + [directory for EGL drivers @<:@default=${libdir}/egl@:>@])], [EGL_DRIVER_INSTALL_DIR="$withval"], [EGL_DRIVER_INSTALL_DIR='${libdir}/egl']) AC_SUBST([EGL_DRIVER_INSTALL_DIR]) @@ -1909,14 +1911,14 @@ if test -n "$with_gallium_drivers"; then HAVE_GALLIUM_SVGA=yes GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS svga softpipe" gallium_require_drm_loader - gallium_check_st "svga/drm" "dri-vmwgfx" "" + gallium_check_st "svga/drm" "dri-vmwgfx" "xa/vmwgfx" ;; xi915) HAVE_GALLIUM_I915=yes PKG_CHECK_MODULES([INTEL], [libdrm_intel >= $LIBDRM_INTEL_REQUIRED]) gallium_require_drm_loader GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS i915" - gallium_check_st "i915/drm" "dri-i915" + gallium_check_st "i915/drm" "dri-i915" "xa/i915" DRICOMMON_NEED_LIBDRM=yes ;; xilo) @@ -1924,7 +1926,7 @@ if test -n "$with_gallium_drivers"; then PKG_CHECK_MODULES([INTEL], [libdrm_intel >= $LIBDRM_INTEL_REQUIRED]) gallium_require_drm_loader GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS ilo" - gallium_check_st "intel/drm" "dri-ilo" + gallium_check_st "intel/drm" "dri-ilo" "xa/ilo" DRICOMMON_NEED_LIBDRM=yes ;; xr300) @@ -1933,7 +1935,7 @@ if test -n "$with_gallium_drivers"; then gallium_require_drm_loader gallium_require_llvm "Gallium R300" GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS r300" - gallium_check_st "radeon/drm" "r300/dri" "" "" "" + gallium_check_st "radeon/drm" "r300/dri" "xa/r300" "" "" DRICOMMON_NEED_LIBDRM=yes ;; xr600) @@ -1951,7 +1953,7 @@ if test -n "$with_gallium_drivers"; then if test "x$enable_opencl" = xyes; then LLVM_COMPONENTS="${LLVM_COMPONENTS} bitreader asmparser" fi - gallium_check_st "radeon/drm" "r600/dri" "" "xvmc/r600" "vdpau/r600" "r600/omx" + gallium_check_st "radeon/drm" "r600/dri" "xa/r600" "xvmc/r600" "vdpau/r600" "omx/r600" DRICOMMON_NEED_LIBDRM=yes ;; xradeonsi) @@ -1961,7 +1963,7 @@ if test -n "$with_gallium_drivers"; then GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS radeonsi" radeon_llvm_check "radeonsi" require_egl_drm "radeonsi" - gallium_check_st "radeon/drm" "radeonsi/dri" "" "" "vdpau/radeonsi" "radeonsi/omx" + gallium_check_st "radeon/drm" "radeonsi/dri" "xa/radeonsi" "" "vdpau/radeonsi" "omx/radeonsi" DRICOMMON_NEED_LIBDRM=yes ;; xnouveau) @@ -1969,7 +1971,7 @@ if test -n "$with_gallium_drivers"; then PKG_CHECK_MODULES([NOUVEAU], [libdrm_nouveau >= $LIBDRM_NOUVEAU_REQUIRED]) gallium_require_drm_loader GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS nouveau" - gallium_check_st "nouveau/drm" "dri-nouveau" "" "xvmc/nouveau" "vdpau/nouveau" "omx-nouveau" + gallium_check_st "nouveau/drm" "dri-nouveau" "xa/nouveau" "xvmc/nouveau" "vdpau/nouveau" "omx/nouveau" DRICOMMON_NEED_LIBDRM=yes ;; xfreedreno) @@ -1977,7 +1979,7 @@ if test -n "$with_gallium_drivers"; then PKG_CHECK_MODULES([FREEDRENO], [libdrm_freedreno >= $LIBDRM_FREEDRENO_REQUIRED]) gallium_require_drm_loader GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS freedreno" - gallium_check_st "freedreno/drm" "dri-freedreno" "" "" "" + gallium_check_st "freedreno/drm" "dri-freedreno" "xa/freedreno" "" "" DRICOMMON_NEED_LIBDRM=yes ;; xswrast) @@ -2214,16 +2216,14 @@ AC_CONFIG_FILES([Makefile src/gallium/targets/egl-static/Makefile src/gallium/targets/gbm/Makefile src/gallium/targets/libgl-xlib/Makefile - src/gallium/targets/omx-nouveau/Makefile + src/gallium/targets/omx/Makefile src/gallium/targets/opencl/Makefile src/gallium/targets/osmesa/Makefile src/gallium/targets/osmesa/osmesa.pc src/gallium/targets/pipe-loader/Makefile src/gallium/targets/r300/dri/Makefile src/gallium/targets/r600/dri/Makefile - src/gallium/targets/r600/omx/Makefile src/gallium/targets/radeonsi/dri/Makefile - src/gallium/targets/radeonsi/omx/Makefile src/gallium/targets/vdpau/Makefile src/gallium/targets/xa/Makefile src/gallium/targets/xa/xatracker.pc diff --git a/mesalib/docs/GL3.txt b/mesalib/docs/GL3.txt index 47165fe1e..bc418a908 100644 --- a/mesalib/docs/GL3.txt +++ b/mesalib/docs/GL3.txt @@ -101,21 +101,21 @@ GL 4.0: GL_ARB_draw_indirect DONE (i965) GL_ARB_gpu_shader5 started - 'precise' qualifier DONE - - Dynamically uniform sampler array indices not started - - Dynamically uniform UBO array indices not started + - Dynamically uniform sampler array indices started (Chris) + - Dynamically uniform UBO array indices started (Chris) - Implicit signed -> unsigned conversions DONE - Fused multiply-add DONE - Packing/bitfield/conversion functions DONE - Enhanced textureGather DONE - Geometry shader instancing DONE - - Geometry shader multiple streams not started + - Geometry shader multiple streams DONE (i965) - Enhanced per-sample shading DONE - - Interpolation functions started + - Interpolation functions started (Chris) - New overload resolution rules DONE - GL_ARB_gpu_shader_fp64 not started + GL_ARB_gpu_shader_fp64 started (Dave) GL_ARB_sample_shading DONE (i965, nv50, nvc0, radeonsi) GL_ARB_shader_subroutine not started - GL_ARB_tessellation_shader not started + GL_ARB_tessellation_shader started (Fabian) GL_ARB_texture_buffer_object_rgb32 DONE (i965, nvc0, r600, radeonsi, softpipe) GL_ARB_texture_cube_map_array DONE (i965, nv50, nvc0, r600, radeonsi, softpipe) GL_ARB_texture_gather DONE (i965, nv50, nvc0, radeonsi) @@ -130,7 +130,7 @@ GL 4.1: GL_ARB_ES2_compatibility DONE (i965, nv50, nvc0, r300, r600, radeonsi) GL_ARB_get_program_binary DONE (0 binary formats) GL_ARB_separate_shader_objects DONE (all drivers) - GL_ARB_shader_precision not started + GL_ARB_shader_precision started (Micah) GL_ARB_vertex_attrib_64bit not started GL_ARB_viewport_array DONE (i965, nv50, nvc0, r600) @@ -154,7 +154,7 @@ GL 4.2: GL 4.3: GLSL 4.3 not started - GL_ARB_arrays_of_arrays started + GL_ARB_arrays_of_arrays started (Timothy) GL_ARB_ES3_compatibility DONE (i965) GL_ARB_clear_buffer_object DONE (all drivers) GL_ARB_compute_shader started (Paul Berry) diff --git a/mesalib/docs/relnotes/10.3.html b/mesalib/docs/relnotes/10.3.html index ecc8580f4..47d2c5fff 100644 --- a/mesalib/docs/relnotes/10.3.html +++ b/mesalib/docs/relnotes/10.3.html @@ -53,6 +53,7 @@ Note: some of the new features are only available with certain drivers.
  • GL_ARB_texture_query_levels on nv50, nvc0, llvmpipe, r600, radeonsi, softpipe
  • GL_ARB_texture_query_lod on radeonsi
  • GL_ARB_viewport_array on nvc0
  • +
  • GL_ARB_seamless_cubemap_per_texture on i965, llvmpipe, nvc0, r600, radeonsi, softpipe
  • @@ -63,6 +64,7 @@ TBD.

    Changes

    diff --git a/mesalib/include/GL/glx.h b/mesalib/include/GL/glx.h index 234abc050..78f5052b2 100644 --- a/mesalib/include/GL/glx.h +++ b/mesalib/include/GL/glx.h @@ -518,7 +518,7 @@ typedef struct { unsigned long serial; /* # of last request processed by server */ Bool send_event; /* true if this came from a SendEvent request */ Display *display; /* Display the event was read from */ - GLXDrawable drawable; /* drawable on which event was requested in event mask */ + Drawable drawable; /* drawable on which event was requested in event mask */ int event_type; int64_t ust; int64_t msc; diff --git a/mesalib/include/GL/internal/dri_interface.h b/mesalib/include/GL/internal/dri_interface.h index 4d57d0b82..725d622a1 100644 --- a/mesalib/include/GL/internal/dri_interface.h +++ b/mesalib/include/GL/internal/dri_interface.h @@ -40,6 +40,7 @@ #ifndef DRI_INTERFACE_H #define DRI_INTERFACE_H +#include /* For archs with no drm.h */ #if defined(__APPLE__) || defined(__CYGWIN__) || defined(__GNU__) #ifndef __NOT_HAVE_DRM_H @@ -1005,7 +1006,7 @@ struct __DRIdri2ExtensionRec { * extensions. */ #define __DRI_IMAGE "DRI_IMAGE" -#define __DRI_IMAGE_VERSION 8 +#define __DRI_IMAGE_VERSION 9 /** * These formats correspond to the similarly named MESA_FORMAT_* @@ -1133,6 +1134,13 @@ enum __DRIChromaSiting { #define __DRI_IMAGE_ERROR_BAD_PARAMETER 3 /*@}*/ +/** + * blitImage flags + */ + +#define __BLIT_FLAG_FLUSH 0x0001 +#define __BLIT_FLAG_FINISH 0x0002 + typedef struct __DRIimageRec __DRIimage; typedef struct __DRIimageExtensionRec __DRIimageExtension; struct __DRIimageExtensionRec { @@ -1239,6 +1247,21 @@ struct __DRIimageExtensionRec { enum __DRIChromaSiting vert_siting, unsigned *error, void *loaderPrivate); + + /** + * Blit a part of a __DRIimage to another and flushes + * + * flush_flag: + * 0: no flush + * __BLIT_FLAG_FLUSH: flush after the blit operation + * __BLIT_FLAG_FINISH: flush and wait the blit finished + * + * \since 9 + */ + void (*blitImage)(__DRIcontext *context, __DRIimage *dst, __DRIimage *src, + int dstx0, int dsty0, int dstwidth, int dstheight, + int srcx0, int srcy0, int srcwidth, int srcheight, + int flush_flag); }; @@ -1272,9 +1295,9 @@ typedef struct __DRI2configQueryExtensionRec __DRI2configQueryExtension; struct __DRI2configQueryExtensionRec { __DRIextension base; - int (*configQueryb)(__DRIscreen *screen, const char *var, GLboolean *val); - int (*configQueryi)(__DRIscreen *screen, const char *var, GLint *val); - int (*configQueryf)(__DRIscreen *screen, const char *var, GLfloat *val); + int (*configQueryb)(__DRIscreen *screen, const char *var, bool *val); + int (*configQueryi)(__DRIscreen *screen, const char *var, int *val); + int (*configQueryf)(__DRIscreen *screen, const char *var, float *val); }; /** diff --git a/mesalib/src/Makefile.am b/mesalib/src/Makefile.am index 9d1580f90..d4a7090dc 100644 --- a/mesalib/src/Makefile.am +++ b/mesalib/src/Makefile.am @@ -19,12 +19,14 @@ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. -SUBDIRS = gtest loader mapi +SUBDIRS = gtest mapi if NEED_OPENGL_COMMON SUBDIRS += glsl mesa endif +SUBDIRS += loader + if HAVE_DRI_GLX SUBDIRS += glx endif diff --git a/mesalib/src/gallium/Automake.inc b/mesalib/src/gallium/Automake.inc index 8bf2a12e8..4600b9c5b 100644 --- a/mesalib/src/gallium/Automake.inc +++ b/mesalib/src/gallium/Automake.inc @@ -39,7 +39,7 @@ GALLIUM_DRI_CFLAGS = \ $(LIBDRM_CFLAGS) \ $(VISIBILITY_CFLAGS) -GALLIUM_VIDEO_CFLAGS = \ +GALLIUM_TARGET_CFLAGS = \ -I$(top_srcdir)/include \ -I$(top_srcdir)/src/loader \ -I$(top_srcdir)/src/gallium/include \ @@ -59,20 +59,10 @@ GALLIUM_DRI_LINKER_FLAGS = \ -avoid-version \ $(GC_SECTIONS) -GALLIUM_OMX_LINKER_FLAGS = \ - -shared \ - -module \ - -no-undefined \ - -avoid-version \ - $(GC_SECTIONS) \ - $(LD_NO_UNDEFINED) - if HAVE_LD_VERSION_SCRIPT GALLIUM_DRI_LINKER_FLAGS += \ -Wl,--version-script=$(top_srcdir)/src/gallium/targets/dri.sym -GALLIUM_OMX_LINKER_FLAGS += \ - -Wl,--version-script=$(top_srcdir)/src/gallium/targets/omx.sym endif @@ -90,12 +80,6 @@ GALLIUM_DRI_LIB_DEPS = \ $(EXPAT_LIBS) \ $(GALLIUM_COMMON_LIB_DEPS) -GALLIUM_OMX_LIB_DEPS = \ - $(top_builddir)/src/gallium/auxiliary/libgallium.la \ - $(top_builddir)/src/gallium/state_trackers/omx/libomxtracker.la \ - $(OMX_LIBS) \ - $(GALLIUM_COMMON_LIB_DEPS) - GALLIUM_WINSYS_CFLAGS = \ -I$(top_srcdir)/include \ -I$(top_srcdir)/src/gallium/include \ @@ -104,13 +88,8 @@ GALLIUM_WINSYS_CFLAGS = \ $(VISIBILITY_CFLAGS) if HAVE_MESA_LLVM - GALLIUM_DRI_LINKER_FLAGS += $(LLVM_LDFLAGS) -GALLIUM_OMX_LINKER_FLAGS += $(LLVM_LDFLAGS) - GALLIUM_DRI_LIB_DEPS += $(LLVM_LIBS) -GALLIUM_OMX_LIB_DEPS += $(LLVM_LIBS) - endif diff --git a/mesalib/src/glsl/ast.h b/mesalib/src/glsl/ast.h index 56e7bd86f..15bf086a1 100644 --- a/mesalib/src/glsl/ast.h +++ b/mesalib/src/glsl/ast.h @@ -509,6 +509,8 @@ struct ast_type_qualifier { /** \name Layout qualifiers for GL_ARB_gpu_shader5 */ /** \{ */ unsigned invocations:1; + unsigned stream:1; /**< Has stream value assigned */ + unsigned explicit_stream:1; /**< stream value assigned explicitly by shader code */ /** \} */ } /** \brief Set of flags, accessed by name. */ @@ -542,6 +544,9 @@ struct ast_type_qualifier { /** Maximum output vertices in GLSL 1.50 geometry shaders. */ int max_vertices; + /** Stream in GLSL 1.50 geometry shaders. */ + unsigned stream; + /** Input or output primitive type in GLSL 1.50 geometry shaders */ GLenum prim_type; diff --git a/mesalib/src/glsl/ast_to_hir.cpp b/mesalib/src/glsl/ast_to_hir.cpp index 7ba04a808..042ef243b 100644 --- a/mesalib/src/glsl/ast_to_hir.cpp +++ b/mesalib/src/glsl/ast_to_hir.cpp @@ -2461,6 +2461,11 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual, if (qual->flags.q.sample) var->data.sample = 1; + if (state->stage == MESA_SHADER_GEOMETRY && + qual->flags.q.out && qual->flags.q.stream) { + var->data.stream = qual->stream; + } + if (qual->flags.q.attribute && state->stage != MESA_SHADER_VERTEX) { var->type = glsl_type::error_type; _mesa_glsl_error(loc, state, @@ -5100,6 +5105,9 @@ ast_process_structure_or_interface_block(exec_list *instructions, fields[i].centroid = qual->flags.q.centroid ? 1 : 0; fields[i].sample = qual->flags.q.sample ? 1 : 0; + /* Only save explicitly defined streams in block's field */ + fields[i].stream = qual->flags.q.explicit_stream ? qual->stream : -1; + if (qual->flags.q.row_major || qual->flags.q.column_major) { if (!qual->flags.q.uniform) { _mesa_glsl_error(&loc, state, @@ -5548,6 +5556,17 @@ ast_interface_block::hir(exec_list *instructions, var->data.sample = fields[i].sample; var->init_interface_type(block_type); + if (fields[i].stream != -1 && + ((unsigned)fields[i].stream) != this->layout.stream) { + _mesa_glsl_error(&loc, state, + "stream layout qualifier on " + "interface block member `%s' does not match " + "the interface block (%d vs %d)", + var->name, fields[i].stream, this->layout.stream); + } + + var->data.stream = this->layout.stream; + if (redeclaring_per_vertex) { ir_variable *earlier = get_variable_being_redeclared(var, loc, state, diff --git a/mesalib/src/glsl/ast_type.cpp b/mesalib/src/glsl/ast_type.cpp index 77053d5b1..017f23d0e 100644 --- a/mesalib/src/glsl/ast_type.cpp +++ b/mesalib/src/glsl/ast_type.cpp @@ -125,9 +125,13 @@ ast_type_qualifier::merge_qualifier(YYLTYPE *loc, /* Uniform block layout qualifiers get to overwrite each * other (rightmost having priority), while all other * qualifiers currently don't allow duplicates. + * + * Geometry shaders can have several layout qualifiers + * assigning different stream values. */ - if ((this->flags.i & q.flags.i & ~(ubo_mat_mask.flags.i | + if ((state->stage != MESA_SHADER_GEOMETRY) && + (this->flags.i & q.flags.i & ~(ubo_mat_mask.flags.i | ubo_layout_mask.flags.i | ubo_binding_mask.flags.i)) != 0) { _mesa_glsl_error(loc, state, @@ -154,6 +158,39 @@ ast_type_qualifier::merge_qualifier(YYLTYPE *loc, this->max_vertices = q.max_vertices; } + if (state->stage == MESA_SHADER_GEOMETRY && + state->has_explicit_attrib_stream()) { + if (q.flags.q.stream && q.stream >= state->ctx->Const.MaxVertexStreams) { + _mesa_glsl_error(loc, state, + "`stream' value is larger than MAX_VERTEX_STREAMS - 1 " + "(%d > %d)", + q.stream, state->ctx->Const.MaxVertexStreams - 1); + } + if (this->flags.q.explicit_stream && + this->stream >= state->ctx->Const.MaxVertexStreams) { + _mesa_glsl_error(loc, state, + "`stream' value is larger than MAX_VERTEX_STREAMS - 1 " + "(%d > %d)", + this->stream, state->ctx->Const.MaxVertexStreams - 1); + } + + if (!this->flags.q.explicit_stream) { + if (q.flags.q.stream) { + this->flags.q.stream = 1; + this->stream = q.stream; + } else if (!this->flags.q.stream && this->flags.q.out) { + /* Assign default global stream value */ + this->flags.q.stream = 1; + this->stream = state->out_qualifier->stream; + } + } else { + if (q.flags.q.explicit_stream) { + _mesa_glsl_error(loc, state, + "duplicate layout `stream' qualifier"); + } + } + } + if ((q.flags.i & ubo_mat_mask.flags.i) != 0) this->flags.i &= ~ubo_mat_mask.flags.i; if ((q.flags.i & ubo_layout_mask.flags.i) != 0) diff --git a/mesalib/src/glsl/builtin_functions.cpp b/mesalib/src/glsl/builtin_functions.cpp index f9f06862e..94b578107 100644 --- a/mesalib/src/glsl/builtin_functions.cpp +++ b/mesalib/src/glsl/builtin_functions.cpp @@ -359,6 +359,12 @@ shader_image_load_store(const _mesa_glsl_parse_state *state) state->ARB_shader_image_load_store_enable); } +static bool +gs_streams(const _mesa_glsl_parse_state *state) +{ + return gpu_shader5(state) && gs_only(state); +} + /** @} */ /******************************************************************************/ @@ -594,6 +600,10 @@ private: B0(EmitVertex) B0(EndPrimitive) + ir_function_signature *_EmitStreamVertex(builtin_available_predicate avail, + const glsl_type *stream_type); + ir_function_signature *_EndStreamPrimitive(builtin_available_predicate avail, + const glsl_type *stream_type); B2(textureQueryLod); B1(textureQueryLevels); @@ -1708,6 +1718,14 @@ builtin_builder::create_builtins() add_function("EmitVertex", _EmitVertex(), NULL); add_function("EndPrimitive", _EndPrimitive(), NULL); + add_function("EmitStreamVertex", + _EmitStreamVertex(gs_streams, glsl_type::uint_type), + _EmitStreamVertex(gs_streams, glsl_type::int_type), + NULL); + add_function("EndStreamPrimitive", + _EndStreamPrimitive(gs_streams, glsl_type::uint_type), + _EndStreamPrimitive(gs_streams, glsl_type::int_type), + NULL); add_function("textureQueryLOD", _textureQueryLod(glsl_type::sampler1D_type, glsl_type::float_type), @@ -3872,7 +3890,28 @@ builtin_builder::_EmitVertex() { MAKE_SIG(glsl_type::void_type, gs_only, 0); - body.emit(new(mem_ctx) ir_emit_vertex()); + ir_rvalue *stream = new(mem_ctx) ir_constant(0, 1); + body.emit(new(mem_ctx) ir_emit_vertex(stream)); + + return sig; +} + +ir_function_signature * +builtin_builder::_EmitStreamVertex(builtin_available_predicate avail, + const glsl_type *stream_type) +{ + /* Section 8.12 (Geometry Shader Functions) of the GLSL 4.0 spec says: + * + * "Emit the current values of output variables to the current output + * primitive on stream stream. The argument to stream must be a constant + * integral expression." + */ + ir_variable *stream = + new(mem_ctx) ir_variable(stream_type, "stream", ir_var_const_in); + + MAKE_SIG(glsl_type::void_type, avail, 1, stream); + + body.emit(new(mem_ctx) ir_emit_vertex(var_ref(stream))); return sig; } @@ -3882,7 +3921,28 @@ builtin_builder::_EndPrimitive() { MAKE_SIG(glsl_type::void_type, gs_only, 0); - body.emit(new(mem_ctx) ir_end_primitive()); + ir_rvalue *stream = new(mem_ctx) ir_constant(0, 1); + body.emit(new(mem_ctx) ir_end_primitive(stream)); + + return sig; +} + +ir_function_signature * +builtin_builder::_EndStreamPrimitive(builtin_available_predicate avail, + const glsl_type *stream_type) +{ + /* Section 8.12 (Geometry Shader Functions) of the GLSL 4.0 spec says: + * + * "Completes the current output primitive on stream stream and starts + * a new one. The argument to stream must be a constant integral + * expression." + */ + ir_variable *stream = + new(mem_ctx) ir_variable(stream_type, "stream", ir_var_const_in); + + MAKE_SIG(glsl_type::void_type, avail, 1, stream); + + body.emit(new(mem_ctx) ir_end_primitive(var_ref(stream))); return sig; } diff --git a/mesalib/src/glsl/builtin_variables.cpp b/mesalib/src/glsl/builtin_variables.cpp index b9c69d23c..9f9571619 100644 --- a/mesalib/src/glsl/builtin_variables.cpp +++ b/mesalib/src/glsl/builtin_variables.cpp @@ -160,14 +160,6 @@ static const struct gl_builtin_uniform_element gl_NormalScale_elements[] = { {NULL, {STATE_NORMAL_SCALE}, SWIZZLE_XXXX}, }; -static const struct gl_builtin_uniform_element gl_BumpRotMatrix0MESA_elements[] = { - {NULL, {STATE_INTERNAL, STATE_ROT_MATRIX_0}, SWIZZLE_XYZW}, -}; - -static const struct gl_builtin_uniform_element gl_BumpRotMatrix1MESA_elements[] = { - {NULL, {STATE_INTERNAL, STATE_ROT_MATRIX_1}, SWIZZLE_XYZW}, -}; - static const struct gl_builtin_uniform_element gl_FogParamsOptimizedMESA_elements[] = { {NULL, {STATE_INTERNAL, STATE_FOG_PARAMS_OPTIMIZED}, SWIZZLE_XYZW}, }; @@ -284,8 +276,6 @@ static const struct gl_builtin_uniform_desc _mesa_builtin_uniform_desc[] = { STATEVAR(gl_NormalMatrix), STATEVAR(gl_NormalScale), - STATEVAR(gl_BumpRotMatrix0MESA), - STATEVAR(gl_BumpRotMatrix1MESA), STATEVAR(gl_FogParamsOptimizedMESA), STATEVAR(gl_CurrentAttribVertMESA), STATEVAR(gl_CurrentAttribFragMESA), @@ -761,8 +751,6 @@ builtin_variable_generator::generate_uniforms() add_uniform(mat4_t, "gl_ModelViewProjectionMatrixInverseTranspose"); add_uniform(float_t, "gl_NormalScale"); add_uniform(type("gl_LightModelParameters"), "gl_LightModel"); - add_uniform(vec2_t, "gl_BumpRotMatrix0MESA"); - add_uniform(vec2_t, "gl_BumpRotMatrix1MESA"); add_uniform(vec4_t, "gl_FogParamsOptimizedMESA"); const glsl_type *const mat4_array_type = diff --git a/mesalib/src/glsl/glsl_parser.yy b/mesalib/src/glsl/glsl_parser.yy index 240995901..b9897498f 100644 --- a/mesalib/src/glsl/glsl_parser.yy +++ b/mesalib/src/glsl/glsl_parser.yy @@ -1395,6 +1395,22 @@ layout_qualifier_id: } } + if (state->stage == MESA_SHADER_GEOMETRY) { + if (match_layout_qualifier("stream", $1, state) == 0 && + state->check_explicit_attrib_stream_allowed(& @3)) { + $$.flags.q.stream = 1; + + if ($3 < 0) { + _mesa_glsl_error(& @3, state, + "invalid stream %d specified", $3); + YYERROR; + } else { + $$.flags.q.explicit_stream = 1; + $$.stream = $3; + } + } + } + static const char * const local_size_qualifiers[3] = { "local_size_x", "local_size_y", @@ -1693,6 +1709,20 @@ storage_qualifier: { memset(& $$, 0, sizeof($$)); $$.flags.q.out = 1; + + if (state->stage == MESA_SHADER_GEOMETRY && + state->has_explicit_attrib_stream()) { + /* Section 4.3.8.2 (Output Layout Qualifiers) of the GLSL 4.00 + * spec says: + * + * "If the block or variable is declared with the stream + * identifier, it is associated with the specified stream; + * otherwise, it is associated with the current default stream." + */ + $$.flags.q.stream = 1; + $$.flags.q.explicit_stream = 0; + $$.stream = state->out_qualifier->stream; + } } | UNIFORM { @@ -2361,6 +2391,18 @@ interface_block: if (!block->layout.merge_qualifier(& @1, state, $1)) { YYERROR; } + + foreach_list_typed (ast_declarator_list, member, link, &block->declarations) { + ast_type_qualifier& qualifier = member->type->qualifier; + if (qualifier.flags.q.stream && qualifier.stream != block->layout.stream) { + _mesa_glsl_error(& @1, state, + "stream layout qualifier on " + "interface block member does not match " + "the interface block (%d vs %d)", + qualifier.stream, block->layout.stream); + YYERROR; + } + } $$ = block; } ; @@ -2434,6 +2476,14 @@ basic_interface_block: block->layout.flags.i |= block_interface_qualifier; + if (state->stage == MESA_SHADER_GEOMETRY && + state->has_explicit_attrib_stream()) { + /* Assign global layout's stream value. */ + block->layout.flags.q.stream = 1; + block->layout.flags.q.explicit_stream = 0; + block->layout.stream = state->out_qualifier->stream; + } + foreach_list_typed (ast_declarator_list, member, link, &block->declarations) { ast_type_qualifier& qualifier = member->type->qualifier; if ((qualifier.flags.i & interface_type_mask) == 0) { @@ -2576,6 +2626,9 @@ layout_defaults: } if (!state->out_qualifier->merge_qualifier(& @1, state, $1)) YYERROR; + + /* Allow future assigments of global out's stream id value */ + state->out_qualifier->flags.q.explicit_stream = 0; } $$ = NULL; } diff --git a/mesalib/src/glsl/glsl_parser_extras.h b/mesalib/src/glsl/glsl_parser_extras.h index aa4a114e4..a0af965fd 100644 --- a/mesalib/src/glsl/glsl_parser_extras.h +++ b/mesalib/src/glsl/glsl_parser_extras.h @@ -119,6 +119,19 @@ struct _mesa_glsl_parse_state { return check_version(130, 300, locp, "bit-wise operations are forbidden"); } + bool check_explicit_attrib_stream_allowed(YYLTYPE *locp) + { + if (!this->has_explicit_attrib_stream()) { + const char *const requirement = "GL_ARB_gpu_shader5 extension or GLSL 400"; + + _mesa_glsl_error(locp, this, "explicit stream requires %s", + requirement); + return false; + } + + return true; + } + bool check_explicit_attrib_location_allowed(YYLTYPE *locp, const ir_variable *var) { @@ -166,6 +179,11 @@ struct _mesa_glsl_parse_state { return true; } + bool has_explicit_attrib_stream() const + { + return ARB_gpu_shader5_enable || is_version(400, 0); + } + bool has_explicit_attrib_location() const { return ARB_explicit_attrib_location_enable || is_version(330, 300); diff --git a/mesalib/src/glsl/glsl_types.h b/mesalib/src/glsl/glsl_types.h index f6d4a02ab..0b63d4850 100644 --- a/mesalib/src/glsl/glsl_types.h +++ b/mesalib/src/glsl/glsl_types.h @@ -671,6 +671,12 @@ struct glsl_struct_field { * in ir_variable::sample). 0 otherwise. */ unsigned sample:1; + + /** + * For interface blocks, it has a value if this variable uses multiple vertex + * streams (as in ir_variable::stream). -1 otherwise. + */ + int stream; }; static inline unsigned int diff --git a/mesalib/src/glsl/ir.h b/mesalib/src/glsl/ir.h index b4e52d3d0..d5239d4de 100644 --- a/mesalib/src/glsl/ir.h +++ b/mesalib/src/glsl/ir.h @@ -705,6 +705,11 @@ public: */ int location; + /** + * Vertex stream output identifier. + */ + unsigned stream; + /** * output index for dual source blending. */ @@ -2154,9 +2159,11 @@ private: */ class ir_emit_vertex : public ir_instruction { public: - ir_emit_vertex() - : ir_instruction(ir_type_emit_vertex) + ir_emit_vertex(ir_rvalue *stream) + : ir_instruction(ir_type_emit_vertex), + stream(stream) { + assert(stream); } virtual void accept(ir_visitor *v) @@ -2164,12 +2171,19 @@ public: v->visit(this); } - virtual ir_emit_vertex *clone(void *mem_ctx, struct hash_table *) const + virtual ir_emit_vertex *clone(void *mem_ctx, struct hash_table *ht) const { - return new(mem_ctx) ir_emit_vertex(); + return new(mem_ctx) ir_emit_vertex(this->stream->clone(mem_ctx, ht)); } virtual ir_visitor_status accept(ir_hierarchical_visitor *); + + int stream_id() const + { + return stream->as_constant()->value.i[0]; + } + + ir_rvalue *stream; }; /** @@ -2178,9 +2192,11 @@ public: */ class ir_end_primitive : public ir_instruction { public: - ir_end_primitive() - : ir_instruction(ir_type_end_primitive) + ir_end_primitive(ir_rvalue *stream) + : ir_instruction(ir_type_end_primitive), + stream(stream) { + assert(stream); } virtual void accept(ir_visitor *v) @@ -2188,12 +2204,19 @@ public: v->visit(this); } - virtual ir_end_primitive *clone(void *mem_ctx, struct hash_table *) const + virtual ir_end_primitive *clone(void *mem_ctx, struct hash_table *ht) const { - return new(mem_ctx) ir_end_primitive(); + return new(mem_ctx) ir_end_primitive(this->stream->clone(mem_ctx, ht)); } virtual ir_visitor_status accept(ir_hierarchical_visitor *); + + int stream_id() const + { + return stream->as_constant()->value.i[0]; + } + + ir_rvalue *stream; }; /*@}*/ diff --git a/mesalib/src/glsl/ir_hierarchical_visitor.cpp b/mesalib/src/glsl/ir_hierarchical_visitor.cpp index 2e606dda4..d3c00ecdb 100644 --- a/mesalib/src/glsl/ir_hierarchical_visitor.cpp +++ b/mesalib/src/glsl/ir_hierarchical_visitor.cpp @@ -68,24 +68,6 @@ ir_hierarchical_visitor::visit(ir_loop_jump *ir) return visit_continue; } -ir_visitor_status -ir_hierarchical_visitor::visit(ir_emit_vertex *ir) -{ - if (this->callback != NULL) - this->callback(ir, this->data); - - return visit_continue; -} - -ir_visitor_status -ir_hierarchical_visitor::visit(ir_end_primitive *ir) -{ - if (this->callback != NULL) - this->callback(ir, this->data); - - return visit_continue; -} - ir_visitor_status ir_hierarchical_visitor::visit(ir_dereference_variable *ir) { @@ -303,6 +285,38 @@ ir_hierarchical_visitor::visit_leave(ir_if *ir) return visit_continue; } +ir_visitor_status +ir_hierarchical_visitor::visit_enter(ir_emit_vertex *ir) +{ + if (this->callback != NULL) + this->callback(ir, this->data); + + return visit_continue; +} + +ir_visitor_status +ir_hierarchical_visitor::visit_leave(ir_emit_vertex *ir) +{ + (void) ir; + return visit_continue; +} + +ir_visitor_status +ir_hierarchical_visitor::visit_enter(ir_end_primitive *ir) +{ + if (this->callback != NULL) + this->callback(ir, this->data); + + return visit_continue; +} + +ir_visitor_status +ir_hierarchical_visitor::visit_leave(ir_end_primitive *ir) +{ + (void) ir; + return visit_continue; +} + void ir_hierarchical_visitor::run(exec_list *instructions) { diff --git a/mesalib/src/glsl/ir_hierarchical_visitor.h b/mesalib/src/glsl/ir_hierarchical_visitor.h index 647d2e002..bc89a04d8 100644 --- a/mesalib/src/glsl/ir_hierarchical_visitor.h +++ b/mesalib/src/glsl/ir_hierarchical_visitor.h @@ -87,8 +87,6 @@ public: virtual ir_visitor_status visit(class ir_variable *); virtual ir_visitor_status visit(class ir_constant *); virtual ir_visitor_status visit(class ir_loop_jump *); - virtual ir_visitor_status visit(class ir_emit_vertex *); - virtual ir_visitor_status visit(class ir_end_primitive *); /** * ir_dereference_variable isn't technically a leaf, but it is treated as a @@ -137,6 +135,10 @@ public: virtual ir_visitor_status visit_leave(class ir_discard *); virtual ir_visitor_status visit_enter(class ir_if *); virtual ir_visitor_status visit_leave(class ir_if *); + virtual ir_visitor_status visit_enter(class ir_emit_vertex *); + virtual ir_visitor_status visit_leave(class ir_emit_vertex *); + virtual ir_visitor_status visit_enter(class ir_end_primitive *); + virtual ir_visitor_status visit_leave(class ir_end_primitive *); /*@}*/ diff --git a/mesalib/src/glsl/ir_hv_accept.cpp b/mesalib/src/glsl/ir_hv_accept.cpp index 2a1f70e5b..3ca7a5887 100644 --- a/mesalib/src/glsl/ir_hv_accept.cpp +++ b/mesalib/src/glsl/ir_hv_accept.cpp @@ -405,12 +405,28 @@ ir_if::accept(ir_hierarchical_visitor *v) ir_visitor_status ir_emit_vertex::accept(ir_hierarchical_visitor *v) { - return v->visit(this); + ir_visitor_status s = v->visit_enter(this); + if (s != visit_continue) + return (s == visit_continue_with_parent) ? visit_continue : s; + + s = this->stream->accept(v); + if (s != visit_continue) + return (s == visit_continue_with_parent) ? visit_continue : s; + + return (s == visit_stop) ? s : v->visit_leave(this); } ir_visitor_status ir_end_primitive::accept(ir_hierarchical_visitor *v) { - return v->visit(this); + ir_visitor_status s = v->visit_enter(this); + if (s != visit_continue) + return (s == visit_continue_with_parent) ? visit_continue : s; + + s = this->stream->accept(v); + if (s != visit_continue) + return (s == visit_continue_with_parent) ? visit_continue : s; + + return (s == visit_stop) ? s : v->visit_leave(this); } diff --git a/mesalib/src/glsl/ir_print_visitor.cpp b/mesalib/src/glsl/ir_print_visitor.cpp index c4a6f9c9f..72ad4223f 100644 --- a/mesalib/src/glsl/ir_print_visitor.cpp +++ b/mesalib/src/glsl/ir_print_visitor.cpp @@ -169,11 +169,14 @@ void ir_print_visitor::visit(ir_variable *ir) "in ", "out ", "inout ", "const_in ", "sys ", "temporary " }; STATIC_ASSERT(ARRAY_SIZE(mode) == ir_var_mode_count); + const char *const stream [] = {"", "stream1 ", "stream2 ", "stream3 "}; const char *const interp[] = { "", "smooth", "flat", "noperspective" }; STATIC_ASSERT(ARRAY_SIZE(interp) == INTERP_QUALIFIER_COUNT); - fprintf(f, "(%s%s%s%s%s) ", - cent, samp, inv, mode[ir->data.mode], interp[ir->data.interpolation]); + fprintf(f, "(%s%s%s%s%s%s) ", + cent, samp, inv, mode[ir->data.mode], + stream[ir->data.stream], + interp[ir->data.interpolation]); print_type(f, ir->type); fprintf(f, " %s)", unique_name(ir)); @@ -560,13 +563,18 @@ ir_print_visitor::visit(ir_loop_jump *ir) } void -ir_print_visitor::visit(ir_emit_vertex *) +ir_print_visitor::visit(ir_emit_vertex *ir) { - fprintf(f, "(emit-vertex)"); + fprintf(f, "(emit-vertex "); + ir->stream->accept(this); + fprintf(f, ")\n"); } void -ir_print_visitor::visit(ir_end_primitive *) +ir_print_visitor::visit(ir_end_primitive *ir) { - fprintf(f, "(end-primitive)"); + fprintf(f, "(end-primitive "); + ir->stream->accept(this); + fprintf(f, ")\n"); + } diff --git a/mesalib/src/glsl/ir_reader.cpp b/mesalib/src/glsl/ir_reader.cpp index 28923f3b8..a178c82b5 100644 --- a/mesalib/src/glsl/ir_reader.cpp +++ b/mesalib/src/glsl/ir_reader.cpp @@ -437,6 +437,12 @@ ir_reader::read_declaration(s_expression *expr) var->data.mode = ir_var_function_inout; } else if (strcmp(qualifier->value(), "temporary") == 0) { var->data.mode = ir_var_temporary; + } else if (strcmp(qualifier->value(), "stream1") == 0) { + var->data.stream = 1; + } else if (strcmp(qualifier->value(), "stream2") == 0) { + var->data.stream = 2; + } else if (strcmp(qualifier->value(), "stream3") == 0) { + var->data.stream = 3; } else if (strcmp(qualifier->value(), "smooth") == 0) { var->data.interpolation = INTERP_QUALIFIER_SMOOTH; } else if (strcmp(qualifier->value(), "flat") == 0) { @@ -1109,10 +1115,17 @@ ir_reader::read_texture(s_expression *expr) ir_emit_vertex * ir_reader::read_emit_vertex(s_expression *expr) { - s_pattern pat[] = { "emit-vertex" }; + s_expression *s_stream = NULL; + + s_pattern pat[] = { "emit-vertex", s_stream }; if (MATCH(expr, pat)) { - return new(mem_ctx) ir_emit_vertex(); + ir_rvalue *stream = read_dereference(s_stream); + if (stream == NULL) { + ir_read_error(NULL, "when reading stream info in emit-vertex"); + return NULL; + } + return new(mem_ctx) ir_emit_vertex(stream); } ir_read_error(NULL, "when reading emit-vertex"); return NULL; @@ -1121,10 +1134,17 @@ ir_reader::read_emit_vertex(s_expression *expr) ir_end_primitive * ir_reader::read_end_primitive(s_expression *expr) { - s_pattern pat[] = { "end-primitive" }; + s_expression *s_stream = NULL; + + s_pattern pat[] = { "end-primitive", s_stream }; if (MATCH(expr, pat)) { - return new(mem_ctx) ir_end_primitive(); + ir_rvalue *stream = read_dereference(s_stream); + if (stream == NULL) { + ir_read_error(NULL, "when reading stream info in end-primitive"); + return NULL; + } + return new(mem_ctx) ir_end_primitive(stream); } ir_read_error(NULL, "when reading end-primitive"); return NULL; diff --git a/mesalib/src/glsl/ir_rvalue_visitor.cpp b/mesalib/src/glsl/ir_rvalue_visitor.cpp index fcbe9448d..0370170b3 100644 --- a/mesalib/src/glsl/ir_rvalue_visitor.cpp +++ b/mesalib/src/glsl/ir_rvalue_visitor.cpp @@ -149,6 +149,19 @@ ir_rvalue_base_visitor::rvalue_visit(ir_if *ir) return visit_continue; } +ir_visitor_status +ir_rvalue_base_visitor::rvalue_visit(ir_emit_vertex *ir) +{ + handle_rvalue(&ir->stream); + return visit_continue; +} + +ir_visitor_status +ir_rvalue_base_visitor::rvalue_visit(ir_end_primitive *ir) +{ + handle_rvalue(&ir->stream); + return visit_continue; +} ir_visitor_status ir_rvalue_visitor::visit_leave(ir_expression *ir) @@ -204,6 +217,18 @@ ir_rvalue_visitor::visit_leave(ir_if *ir) return rvalue_visit(ir); } +ir_visitor_status +ir_rvalue_visitor::visit_leave(ir_emit_vertex *ir) +{ + return rvalue_visit(ir); +} + +ir_visitor_status +ir_rvalue_visitor::visit_leave(ir_end_primitive *ir) +{ + return rvalue_visit(ir); +} + ir_visitor_status ir_rvalue_enter_visitor::visit_enter(ir_expression *ir) { @@ -257,3 +282,15 @@ ir_rvalue_enter_visitor::visit_enter(ir_if *ir) { return rvalue_visit(ir); } + +ir_visitor_status +ir_rvalue_enter_visitor::visit_enter(ir_emit_vertex *ir) +{ + return rvalue_visit(ir); +} + +ir_visitor_status +ir_rvalue_enter_visitor::visit_enter(ir_end_primitive *ir) +{ + return rvalue_visit(ir); +} diff --git a/mesalib/src/glsl/ir_rvalue_visitor.h b/mesalib/src/glsl/ir_rvalue_visitor.h index 2179fa5a8..04ec0fa39 100644 --- a/mesalib/src/glsl/ir_rvalue_visitor.h +++ b/mesalib/src/glsl/ir_rvalue_visitor.h @@ -41,6 +41,8 @@ public: ir_visitor_status rvalue_visit(ir_return *); ir_visitor_status rvalue_visit(ir_swizzle *); ir_visitor_status rvalue_visit(ir_texture *); + ir_visitor_status rvalue_visit(ir_emit_vertex *); + ir_visitor_status rvalue_visit(ir_end_primitive *); virtual void handle_rvalue(ir_rvalue **rvalue) = 0; }; @@ -57,6 +59,8 @@ public: virtual ir_visitor_status visit_leave(ir_return *); virtual ir_visitor_status visit_leave(ir_swizzle *); virtual ir_visitor_status visit_leave(ir_texture *); + virtual ir_visitor_status visit_leave(ir_emit_vertex *); + virtual ir_visitor_status visit_leave(ir_end_primitive *); }; class ir_rvalue_enter_visitor : public ir_rvalue_base_visitor { @@ -71,4 +75,6 @@ public: virtual ir_visitor_status visit_enter(ir_return *); virtual ir_visitor_status visit_enter(ir_swizzle *); virtual ir_visitor_status visit_enter(ir_texture *); + virtual ir_visitor_status visit_enter(ir_emit_vertex *); + virtual ir_visitor_status visit_enter(ir_end_primitive *); }; diff --git a/mesalib/src/glsl/link_atomics.cpp b/mesalib/src/glsl/link_atomics.cpp index d92cdb117..fbe4e7364 100644 --- a/mesalib/src/glsl/link_atomics.cpp +++ b/mesalib/src/glsl/link_atomics.cpp @@ -54,9 +54,18 @@ namespace { void push_back(unsigned id, ir_variable *var) { - counters = (active_atomic_counter *) - realloc(counters, sizeof(active_atomic_counter) * (num_counters + 1)); + active_atomic_counter *new_counters; + new_counters = (active_atomic_counter *) + realloc(counters, sizeof(active_atomic_counter) * + (num_counters + 1)); + + if (new_counters == NULL) { + _mesa_error_no_memory(__func__); + return; + } + + counters = new_counters; counters[num_counters].id = id; counters[num_counters].var = var; num_counters++; diff --git a/mesalib/src/glsl/link_uniform_blocks.cpp b/mesalib/src/glsl/link_uniform_blocks.cpp index 1a0e64318..53a18c934 100644 --- a/mesalib/src/glsl/link_uniform_blocks.cpp +++ b/mesalib/src/glsl/link_uniform_blocks.cpp @@ -170,6 +170,12 @@ link_uniform_blocks(void *mem_ctx, struct hash_table *block_hash = _mesa_hash_table_create(mem_ctx, _mesa_key_string_equal); + if (block_hash == NULL) { + _mesa_error_no_memory(__func__); + linker_error(prog, "out of memory\n"); + return 0; + } + /* Determine which uniform blocks are active. */ link_uniform_block_active_visitor v(mem_ctx, block_hash, prog); diff --git a/mesalib/src/glsl/link_varyings.cpp b/mesalib/src/glsl/link_varyings.cpp index 686329857..520a51a27 100644 --- a/mesalib/src/glsl/link_varyings.cpp +++ b/mesalib/src/glsl/link_varyings.cpp @@ -291,6 +291,7 @@ tfeedback_decl::init(struct gl_context *ctx, const void *mem_ctx, this->skip_components = 0; this->next_buffer_separator = false; this->matched_candidate = NULL; + this->stream_id = 0; if (ctx->Extensions.ARB_transform_feedback3) { /* Parse gl_NextBuffer. */ @@ -355,8 +356,8 @@ tfeedback_decl::is_same(const tfeedback_decl &x, const tfeedback_decl &y) /** - * Assign a location for this tfeedback_decl object based on the transform - * feedback candidate found by find_candidate. + * Assign a location and stream ID for this tfeedback_decl object based on the + * transform feedback candidate found by find_candidate. * * If an error occurs, the error is reported through linker_error() and false * is returned. @@ -437,6 +438,11 @@ tfeedback_decl::assign_location(struct gl_context *ctx, return false; } + /* Only transform feedback varyings can be assigned to non-zero streams, + * so assign the stream id here. + */ + this->stream_id = this->matched_candidate->toplevel_var->data.stream; + return true; } @@ -495,6 +501,7 @@ tfeedback_decl::store(struct gl_context *ctx, struct gl_shader_program *prog, info->Outputs[info->NumOutputs].ComponentOffset = location_frac; info->Outputs[info->NumOutputs].OutputRegister = location; info->Outputs[info->NumOutputs].NumComponents = output_size; + info->Outputs[info->NumOutputs].StreamId = stream_id; info->Outputs[info->NumOutputs].OutputBuffer = buffer; info->Outputs[info->NumOutputs].DstOffset = info->BufferStride[buffer]; ++info->NumOutputs; @@ -628,10 +635,27 @@ store_tfeedback_info(struct gl_context *ctx, struct gl_shader_program *prog, } else { /* GL_INVERLEAVED_ATTRIBS */ + int buffer_stream_id = -1; for (unsigned i = 0; i < num_tfeedback_decls; ++i) { if (tfeedback_decls[i].is_next_buffer_separator()) { num_buffers++; + buffer_stream_id = -1; continue; + } else if (buffer_stream_id == -1) { + /* First varying writing to this buffer: remember its stream */ + buffer_stream_id = (int) tfeedback_decls[i].get_stream_id(); + } else if (buffer_stream_id != + (int) tfeedback_decls[i].get_stream_id()) { + /* Varying writes to the same buffer from a different stream */ + linker_error(prog, + "Transform feedback can't capture varyings belonging " + "to different vertex streams in a single buffer. " + "Varying %s writes to buffer from stream %u, other " + "varyings in the same buffer write from stream %u.", + tfeedback_decls[i].name(), + tfeedback_decls[i].get_stream_id(), + buffer_stream_id); + return false; } if (!tfeedback_decls[i].store(ctx, prog, @@ -1323,6 +1347,11 @@ assign_varying_locations(struct gl_context *ctx, (output_var->data.mode != ir_var_shader_out)) continue; + /* Only geometry shaders can use non-zero streams */ + assert(output_var->data.stream == 0 || + (output_var->data.stream < MAX_VERTEX_STREAMS && + producer->Stage == MESA_SHADER_GEOMETRY)); + tfeedback_candidate_generator g(mem_ctx, tfeedback_candidates); g.process(output_var); @@ -1338,6 +1367,14 @@ assign_varying_locations(struct gl_context *ctx, if (input_var || (prog->SeparateShader && consumer == NULL)) { matches.record(output_var, input_var); } + + /* Only stream 0 outputs can be consumed in the next stage */ + if (input_var && output_var->data.stream != 0) { + linker_error(prog, "output %s is assigned to stream=%d but " + "is linked to an input, which requires stream=0", + output_var->name, output_var->data.stream); + return false; + } } } else { /* If there's no producer stage, then this must be a separable program. diff --git a/mesalib/src/glsl/link_varyings.h b/mesalib/src/glsl/link_varyings.h index 6fa268176..afc16a8ba 100644 --- a/mesalib/src/glsl/link_varyings.h +++ b/mesalib/src/glsl/link_varyings.h @@ -112,6 +112,16 @@ public: return !this->next_buffer_separator && !this->skip_components; } + const char *name() const + { + return this->orig_name; + } + + unsigned get_stream_id() const + { + return this->stream_id; + } + /** * The total number of varying components taken up by this variable. Only * valid if assign_location() has been called. @@ -210,6 +220,13 @@ private: * data structure that was found. Otherwise NULL. */ const tfeedback_candidate *matched_candidate; + + /** + * StreamId assigned to this varying (defaults to 0). Can only be set to + * values other than 0 in geometry shaders that use the stream layout + * modifier. Accepted values must be in the range [0, MAX_VERTEX_STREAMS-1]. + */ + unsigned stream_id; }; diff --git a/mesalib/src/glsl/linker.cpp b/mesalib/src/glsl/linker.cpp index 0b6a71679..3036ebcb3 100644 --- a/mesalib/src/glsl/linker.cpp +++ b/mesalib/src/glsl/linker.cpp @@ -250,31 +250,100 @@ public: } }; - /** - * Visitor that determines whether or not a shader uses ir_end_primitive. + * Visitor that determines the highest stream id to which a (geometry) shader + * emits vertices. It also checks whether End{Stream}Primitive is ever called. */ -class find_end_primitive_visitor : public ir_hierarchical_visitor { +class find_emit_vertex_visitor : public ir_hierarchical_visitor { public: - find_end_primitive_visitor() - : found(false) + find_emit_vertex_visitor(int max_allowed) + : max_stream_allowed(max_allowed), + invalid_stream_id(0), + invalid_stream_id_from_emit_vertex(false), + end_primitive_found(false), + uses_non_zero_stream(false) { /* empty */ } - virtual ir_visitor_status visit(ir_end_primitive *) + virtual ir_visitor_status visit_leave(ir_emit_vertex *ir) { - found = true; - return visit_stop; + int stream_id = ir->stream_id(); + + if (stream_id < 0) { + invalid_stream_id = stream_id; + invalid_stream_id_from_emit_vertex = true; + return visit_stop; + } + + if (stream_id > max_stream_allowed) { + invalid_stream_id = stream_id; + invalid_stream_id_from_emit_vertex = true; + return visit_stop; + } + + if (stream_id != 0) + uses_non_zero_stream = true; + + return visit_continue; } - bool end_primitive_found() + virtual ir_visitor_status visit_leave(ir_end_primitive *ir) { - return found; + end_primitive_found = true; + + int stream_id = ir->stream_id(); + + if (stream_id < 0) { + invalid_stream_id = stream_id; + invalid_stream_id_from_emit_vertex = false; + return visit_stop; + } + + if (stream_id > max_stream_allowed) { + invalid_stream_id = stream_id; + invalid_stream_id_from_emit_vertex = false; + return visit_stop; + } + + if (stream_id != 0) + uses_non_zero_stream = true; + + return visit_continue; + } + + bool error() + { + return invalid_stream_id != 0; + } + + const char *error_func() + { + return invalid_stream_id_from_emit_vertex ? + "EmitStreamVertex" : "EndStreamPrimitive"; + } + + int error_stream() + { + return invalid_stream_id; + } + + bool uses_streams() + { + return uses_non_zero_stream; + } + + bool uses_end_primitive() + { + return end_primitive_found; } private: - bool found; + int max_stream_allowed; + int invalid_stream_id; + bool invalid_stream_id_from_emit_vertex; + bool end_primitive_found; + bool uses_non_zero_stream; }; } /* anonymous namespace */ @@ -551,10 +620,58 @@ validate_geometry_shader_executable(struct gl_shader_program *prog, analyze_clip_usage(prog, shader, &prog->Geom.UsesClipDistance, &prog->Geom.ClipDistanceArraySize); +} + +/** + * Check if geometry shaders emit to non-zero streams and do corresponding + * validations. + */ +static void +validate_geometry_shader_emissions(struct gl_context *ctx, + struct gl_shader_program *prog) +{ + if (prog->_LinkedShaders[MESA_SHADER_GEOMETRY] != NULL) { + find_emit_vertex_visitor emit_vertex(ctx->Const.MaxVertexStreams - 1); + emit_vertex.run(prog->_LinkedShaders[MESA_SHADER_GEOMETRY]->ir); + if (emit_vertex.error()) { + linker_error(prog, "Invalid call %s(%d). Accepted values for the " + "stream parameter are in the range [0, %d].", + emit_vertex.error_func(), + emit_vertex.error_stream(), + ctx->Const.MaxVertexStreams - 1); + } + prog->Geom.UsesStreams = emit_vertex.uses_streams(); + prog->Geom.UsesEndPrimitive = emit_vertex.uses_end_primitive(); - find_end_primitive_visitor end_primitive; - end_primitive.run(shader->ir); - prog->Geom.UsesEndPrimitive = end_primitive.end_primitive_found(); + /* From the ARB_gpu_shader5 spec: + * + * "Multiple vertex streams are supported only if the output primitive + * type is declared to be "points". A program will fail to link if it + * contains a geometry shader calling EmitStreamVertex() or + * EndStreamPrimitive() if its output primitive type is not "points". + * + * However, in the same spec: + * + * "The function EmitVertex() is equivalent to calling EmitStreamVertex() + * with set to zero." + * + * And: + * + * "The function EndPrimitive() is equivalent to calling + * EndStreamPrimitive() with set to zero." + * + * Since we can call EmitVertex() and EndPrimitive() when we output + * primitives other than points, calling EmitStreamVertex(0) or + * EmitEndPrimitive(0) should not produce errors. This it also what Nvidia + * does. Currently we only set prog->Geom.UsesStreams to TRUE when + * EmitStreamVertex() or EmitEndPrimitive() are called with a non-zero + * stream. + */ + if (prog->Geom.UsesStreams && prog->Geom.OutputType != GL_POINTS) { + linker_error(prog, "EmitStreamVertex(n) and EndStreamPrimitive(n) " + "with n>0 requires point output"); + } + } } @@ -1479,6 +1596,8 @@ link_intrastage_shaders(void *mem_ctx, const unsigned num_uniform_blocks = link_uniform_blocks(mem_ctx, prog, shader_list, num_shaders, &uniform_blocks); + if (!prog->LinkStatus) + return NULL; /* Check that there is only a single definition of each function signature * across all shaders. @@ -2556,6 +2675,9 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) ; } + /* Check and validate stream emissions in geometry shaders */ + validate_geometry_shader_emissions(ctx, prog); + /* Mark all generic shader inputs and outputs as unpaired. */ for (unsigned i = MESA_SHADER_VERTEX; i <= MESA_SHADER_FRAGMENT; i++) { if (prog->_LinkedShaders[i] != NULL) { diff --git a/mesalib/src/glsl/lower_output_reads.cpp b/mesalib/src/glsl/lower_output_reads.cpp index afe17766b..1ee815d5e 100644 --- a/mesalib/src/glsl/lower_output_reads.cpp +++ b/mesalib/src/glsl/lower_output_reads.cpp @@ -52,7 +52,7 @@ public: output_read_remover(); ~output_read_remover(); virtual ir_visitor_status visit(class ir_dereference_variable *); - virtual ir_visitor_status visit(class ir_emit_vertex *); + virtual ir_visitor_status visit_leave(class ir_emit_vertex *); virtual ir_visitor_status visit_leave(class ir_return *); virtual ir_visitor_status visit_leave(class ir_function_signature *); }; @@ -148,7 +148,7 @@ output_read_remover::visit_leave(ir_return *ir) } ir_visitor_status -output_read_remover::visit(ir_emit_vertex *ir) +output_read_remover::visit_leave(ir_emit_vertex *ir) { hash_table_call_foreach(replacements, emit_return_copy, ir); hash_table_clear(replacements); diff --git a/mesalib/src/glsl/lower_packed_varyings.cpp b/mesalib/src/glsl/lower_packed_varyings.cpp index e8654748f..eda56a97b 100644 --- a/mesalib/src/glsl/lower_packed_varyings.cpp +++ b/mesalib/src/glsl/lower_packed_varyings.cpp @@ -613,7 +613,7 @@ public: explicit lower_packed_varyings_gs_splicer(void *mem_ctx, const exec_list *instructions); - virtual ir_visitor_status visit(ir_emit_vertex *ev); + virtual ir_visitor_status visit_leave(ir_emit_vertex *ev); private: /** @@ -637,7 +637,7 @@ lower_packed_varyings_gs_splicer::lower_packed_varyings_gs_splicer( ir_visitor_status -lower_packed_varyings_gs_splicer::visit(ir_emit_vertex *ev) +lower_packed_varyings_gs_splicer::visit_leave(ir_emit_vertex *ev) { foreach_list(node, this->instructions) { ir_instruction *ir = (ir_instruction *) node; diff --git a/mesalib/src/glsl/opt_dead_code_local.cpp b/mesalib/src/glsl/opt_dead_code_local.cpp index c27c526f9..88895fb0e 100644 --- a/mesalib/src/glsl/opt_dead_code_local.cpp +++ b/mesalib/src/glsl/opt_dead_code_local.cpp @@ -114,7 +114,7 @@ public: return visit_continue_with_parent; } - virtual ir_visitor_status visit(ir_emit_vertex *) + virtual ir_visitor_status visit_leave(ir_emit_vertex *) { /* For the purpose of dead code elimination, emitting a vertex counts as * "reading" all of the currently assigned output variables. diff --git a/mesalib/src/loader/Makefile.am b/mesalib/src/loader/Makefile.am index bddf7ac35..ae8a84492 100644 --- a/mesalib/src/loader/Makefile.am +++ b/mesalib/src/loader/Makefile.am @@ -29,6 +29,25 @@ libloader_la_CPPFLAGS = \ $(VISIBILITY_CFLAGS) \ $(LIBUDEV_CFLAGS) +libloader_la_SOURCES = $(LOADER_C_FILES) +libloader_la_LIBADD = + +if NEED_OPENGL_COMMON +libloader_la_CPPFLAGS += \ + -I$(top_srcdir)/src/mesa/drivers/dri/common/ \ + -I$(top_builddir)/src/mesa/drivers/dri/common/ \ + -I$(top_srcdir)/src/mesa/ \ + -I$(top_srcdir)/src/mapi/ \ + -DUSE_DRICONF + +libloader_la_SOURCES += \ + $(top_srcdir)/src/mesa/drivers/dri/common/xmlconfig.c + +libloader_la_LIBADD += \ + -lm \ + $(EXPAT_LIBS) +endif + if !HAVE_LIBDRM libloader_la_CPPFLAGS += \ -D__NOT_HAVE_DRM_H @@ -36,8 +55,6 @@ else libloader_la_CPPFLAGS += \ $(LIBDRM_CFLAGS) -libloader_la_LIBADD = \ +libloader_la_LIBADD += \ $(LIBDRM_LIBS) endif - -libloader_la_SOURCES = $(LOADER_C_FILES) diff --git a/mesalib/src/loader/loader.c b/mesalib/src/loader/loader.c index 0f262653b..47e1f5874 100644 --- a/mesalib/src/loader/loader.c +++ b/mesalib/src/loader/loader.c @@ -70,6 +70,14 @@ #ifdef HAVE_LIBUDEV #include #include +#include +#include +#include +#include +#ifdef USE_DRICONF +#include "xmlconfig.h" +#include "xmlpool.h" +#endif #endif #ifdef HAVE_SYSFS #include @@ -214,6 +222,210 @@ out: return (*chip_id >= 0); } + +static char * +get_render_node_from_id_path_tag(struct udev *udev, + char *id_path_tag, + char another_tag) +{ + struct udev_device *device; + struct udev_enumerate *e; + struct udev_list_entry *entry; + const char *path, *id_path_tag_tmp; + char *path_res; + char found = 0; + UDEV_SYMBOL(struct udev_enumerate *, udev_enumerate_new, + (struct udev *)); + UDEV_SYMBOL(int, udev_enumerate_add_match_subsystem, + (struct udev_enumerate *, const char *)); + UDEV_SYMBOL(int, udev_enumerate_add_match_sysname, + (struct udev_enumerate *, const char *)); + UDEV_SYMBOL(int, udev_enumerate_scan_devices, + (struct udev_enumerate *)); + UDEV_SYMBOL(struct udev_list_entry *, udev_enumerate_get_list_entry, + (struct udev_enumerate *)); + UDEV_SYMBOL(struct udev_list_entry *, udev_list_entry_get_next, + (struct udev_list_entry *)); + UDEV_SYMBOL(const char *, udev_list_entry_get_name, + (struct udev_list_entry *)); + UDEV_SYMBOL(struct udev_device *, udev_device_new_from_syspath, + (struct udev *, const char *)); + UDEV_SYMBOL(const char *, udev_device_get_property_value, + (struct udev_device *, const char *)); + UDEV_SYMBOL(const char *, udev_device_get_devnode, + (struct udev_device *)); + UDEV_SYMBOL(struct udev_device *, udev_device_unref, + (struct udev_device *)); + + e = udev_enumerate_new(udev); + udev_enumerate_add_match_subsystem(e, "drm"); + udev_enumerate_add_match_sysname(e, "render*"); + + udev_enumerate_scan_devices(e); + udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(e)) { + path = udev_list_entry_get_name(entry); + device = udev_device_new_from_syspath(udev, path); + if (!device) + continue; + id_path_tag_tmp = udev_device_get_property_value(device, "ID_PATH_TAG"); + if (id_path_tag_tmp) { + if ((!another_tag && !strcmp(id_path_tag, id_path_tag_tmp)) || + (another_tag && strcmp(id_path_tag, id_path_tag_tmp))) { + found = 1; + break; + } + } + udev_device_unref(device); + } + + if (found) { + path_res = strdup(udev_device_get_devnode(device)); + udev_device_unref(device); + return path_res; + } + return NULL; +} + +static char * +get_id_path_tag_from_fd(struct udev *udev, int fd) +{ + struct udev_device *device; + const char *id_path_tag_tmp; + char *id_path_tag; + UDEV_SYMBOL(const char *, udev_device_get_property_value, + (struct udev_device *, const char *)); + UDEV_SYMBOL(struct udev_device *, udev_device_unref, + (struct udev_device *)); + + device = udev_device_new_from_fd(udev, fd); + if (!device) + return NULL; + + id_path_tag_tmp = udev_device_get_property_value(device, "ID_PATH_TAG"); + if (!id_path_tag_tmp) + return NULL; + + id_path_tag = strdup(id_path_tag_tmp); + + udev_device_unref(device); + return id_path_tag; +} + +static int +drm_open_device(const char *device_name) +{ + int fd; +#ifdef O_CLOEXEC + fd = open(device_name, O_RDWR | O_CLOEXEC); + if (fd == -1 && errno == EINVAL) +#endif + { + fd = open(device_name, O_RDWR); + if (fd != -1) + fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC); + } + return fd; +} + +#ifdef USE_DRICONF +const char __driConfigOptionsLoader[] = +DRI_CONF_BEGIN + DRI_CONF_SECTION_INITIALIZATION + DRI_CONF_DEVICE_ID_PATH_TAG() + DRI_CONF_SECTION_END +DRI_CONF_END; +#endif + +int loader_get_user_preferred_fd(int default_fd, int *different_device) +{ + struct udev *udev; +#ifdef USE_DRICONF + driOptionCache defaultInitOptions; + driOptionCache userInitOptions; +#endif + const char *dri_prime = getenv("DRI_PRIME"); + char *prime = NULL; + int is_different_device = 0, fd = default_fd; + char *default_device_id_path_tag; + char *device_name = NULL; + char another_tag = 0; + UDEV_SYMBOL(struct udev *, udev_new, (void)); + UDEV_SYMBOL(struct udev *, udev_unref, (struct udev *)); + + if (dri_prime) + prime = strdup(dri_prime); +#ifdef USE_DRICONF + else { + driParseOptionInfo(&defaultInitOptions, __driConfigOptionsLoader); + driParseConfigFiles(&userInitOptions, &defaultInitOptions, 0, "loader"); + if (driCheckOption(&userInitOptions, "device_id", DRI_STRING)) + prime = strdup(driQueryOptionstr(&userInitOptions, "device_id")); + driDestroyOptionCache(&userInitOptions); + driDestroyOptionInfo(&defaultInitOptions); + } +#endif + + if (prime == NULL) { + *different_device = 0; + return default_fd; + } + + udev = udev_new(); + if (!udev) + goto prime_clean; + + default_device_id_path_tag = get_id_path_tag_from_fd(udev, default_fd); + if (!default_device_id_path_tag) + goto udev_clean; + + is_different_device = 1; + /* two format are supported: + * "1": choose any other card than the card used by default. + * id_path_tag: (for example "pci-0000_02_00_0") choose the card + * with this id_path_tag. + */ + if (!strcmp(prime,"1")) { + free(prime); + prime = strdup(default_device_id_path_tag); + /* request a card with a different card than the default card */ + another_tag = 1; + } else if (!strcmp(default_device_id_path_tag, prime)) + /* we are to get a new fd (render-node) of the same device */ + is_different_device = 0; + + device_name = get_render_node_from_id_path_tag(udev, + prime, + another_tag); + if (device_name == NULL) { + is_different_device = 0; + goto default_device_clean; + } + + fd = drm_open_device(device_name); + if (fd > 0) { + close(default_fd); + } else { + fd = default_fd; + is_different_device = 0; + } + free(device_name); + + default_device_clean: + free(default_device_id_path_tag); + udev_clean: + udev_unref(udev); + prime_clean: + free(prime); + + *different_device = is_different_device; + return fd; +} +#else +int loader_get_user_preferred_fd(int default_fd, int *different_device) +{ + *different_device = 0; + return default_fd; +} #endif #if defined(HAVE_SYSFS) diff --git a/mesalib/src/loader/loader.h b/mesalib/src/loader/loader.h index dfd77baad..fa57950de 100644 --- a/mesalib/src/loader/loader.h +++ b/mesalib/src/loader/loader.h @@ -41,6 +41,13 @@ loader_get_driver_for_fd(int fd, unsigned driver_types); char * loader_get_device_name_for_fd(int fd); +/* Function to get a different device than the one we are to use by default, + * if the user requests so and it is possible. The initial fd will be closed + * if neccessary. The returned fd is potentially a render-node. + */ + +int +loader_get_user_preferred_fd(int default_fd, int *different_device); /* for logging.. keep this aligned with egllog.h so we can just use * _eglLog directly. diff --git a/mesalib/src/mapi/glapi/gen/gl_API.xml b/mesalib/src/mapi/glapi/gen/gl_API.xml index 0a486f070..882e66e0b 100644 --- a/mesalib/src/mapi/glapi/gen/gl_API.xml +++ b/mesalib/src/mapi/glapi/gen/gl_API.xml @@ -12157,22 +12157,22 @@ - + - + - + - + diff --git a/mesalib/src/mesa/drivers/common/meta.c b/mesalib/src/mesa/drivers/common/meta.c index 1a2e45320..f313f5645 100644 --- a/mesalib/src/mesa/drivers/common/meta.c +++ b/mesalib/src/mesa/drivers/common/meta.c @@ -1515,23 +1515,15 @@ static void meta_glsl_clear_init(struct gl_context *ctx, struct clear_state *clear) { const char *vs_source = + "#extension GL_AMD_vertex_shader_layer : enable\n" "attribute vec4 position;\n" - "void main()\n" - "{\n" - " gl_Position = position;\n" - "}\n"; - const char *gs_source = - "#version 150\n" - "layout(triangles) in;\n" - "layout(triangle_strip, max_vertices = 4) out;\n" "uniform int layer;\n" "void main()\n" "{\n" - " for (int i = 0; i < 3; i++) {\n" - " gl_Layer = layer;\n" - " gl_Position = gl_in[i].gl_Position;\n" - " EmitVertex();\n" - " }\n" + "#ifdef GL_AMD_vertex_shader_layer\n" + " gl_Layer = layer;\n" + "#endif\n" + " gl_Position = position;\n" "}\n"; const char *fs_source = "uniform vec4 color;\n" @@ -1539,7 +1531,7 @@ meta_glsl_clear_init(struct gl_context *ctx, struct clear_state *clear) "{\n" " gl_FragColor = color;\n" "}\n"; - GLuint vs, gs = 0, fs; + GLuint vs, fs; bool has_integer_textures; _mesa_meta_setup_vertex_objects(&clear->VAO, &clear->VBO, true, 3, 0, 0); @@ -1551,12 +1543,6 @@ meta_glsl_clear_init(struct gl_context *ctx, struct clear_state *clear) _mesa_ShaderSource(vs, 1, &vs_source, NULL); _mesa_CompileShader(vs); - if (_mesa_has_geometry_shaders(ctx)) { - gs = _mesa_CreateShader(GL_GEOMETRY_SHADER); - _mesa_ShaderSource(gs, 1, &gs_source, NULL); - _mesa_CompileShader(gs); - } - fs = _mesa_CreateShader(GL_FRAGMENT_SHADER); _mesa_ShaderSource(fs, 1, &fs_source, NULL); _mesa_CompileShader(fs); @@ -1564,20 +1550,14 @@ meta_glsl_clear_init(struct gl_context *ctx, struct clear_state *clear) clear->ShaderProg = _mesa_CreateProgram(); _mesa_AttachShader(clear->ShaderProg, fs); _mesa_DeleteShader(fs); - if (gs != 0) - _mesa_AttachShader(clear->ShaderProg, gs); _mesa_AttachShader(clear->ShaderProg, vs); _mesa_DeleteShader(vs); _mesa_BindAttribLocation(clear->ShaderProg, 0, "position"); _mesa_ObjectLabel(GL_PROGRAM, clear->ShaderProg, -1, "meta clear"); _mesa_LinkProgram(clear->ShaderProg); - clear->ColorLocation = _mesa_GetUniformLocation(clear->ShaderProg, - "color"); - if (gs != 0) { - clear->LayerLocation = _mesa_GetUniformLocation(clear->ShaderProg, - "layer"); - } + clear->ColorLocation = _mesa_GetUniformLocation(clear->ShaderProg, "color"); + clear->LayerLocation = _mesa_GetUniformLocation(clear->ShaderProg, "layer"); has_integer_textures = _mesa_is_gles3(ctx) || (_mesa_is_desktop_gl(ctx) && ctx->Const.GLSLVersion >= 130); @@ -1587,9 +1567,14 @@ meta_glsl_clear_init(struct gl_context *ctx, struct clear_state *clear) const char *vs_int_source = ralloc_asprintf(shader_source_mem_ctx, "#version 130\n" + "#extension GL_AMD_vertex_shader_layer : enable\n" "in vec4 position;\n" + "uniform int layer;\n" "void main()\n" "{\n" + "#ifdef GL_AMD_vertex_shader_layer\n" + " gl_Layer = layer;\n" + "#endif\n" " gl_Position = position;\n" "}\n"); const char *fs_int_source = @@ -1612,8 +1597,6 @@ meta_glsl_clear_init(struct gl_context *ctx, struct clear_state *clear) clear->IntegerShaderProg = _mesa_CreateProgram(); _mesa_AttachShader(clear->IntegerShaderProg, fs); _mesa_DeleteShader(fs); - if (gs != 0) - _mesa_AttachShader(clear->IntegerShaderProg, gs); _mesa_AttachShader(clear->IntegerShaderProg, vs); _mesa_DeleteShader(vs); _mesa_BindAttribLocation(clear->IntegerShaderProg, 0, "position"); @@ -1629,13 +1612,9 @@ meta_glsl_clear_init(struct gl_context *ctx, struct clear_state *clear) clear->IntegerColorLocation = _mesa_GetUniformLocation(clear->IntegerShaderProg, "color"); - if (gs != 0) { - clear->IntegerLayerLocation = - _mesa_GetUniformLocation(clear->IntegerShaderProg, "layer"); - } + clear->IntegerLayerLocation = + _mesa_GetUniformLocation(clear->IntegerShaderProg, "layer"); } - if (gs != 0) - _mesa_DeleteShader(gs); } static void @@ -1843,7 +1822,7 @@ meta_clear(struct gl_context *ctx, GLbitfield buffers, bool glsl) /* draw quad(s) */ if (fb->MaxNumLayers > 0) { unsigned layer; - assert(glsl); + assert(glsl && clear->LayerLocation != -1); for (layer = 0; layer < fb->MaxNumLayers; layer++) { if (fb->_IntegerColor) _mesa_Uniform1i(clear->IntegerLayerLocation, layer); diff --git a/mesalib/src/mesa/drivers/dri/common/dri_util.c b/mesalib/src/mesa/drivers/dri/common/dri_util.c index 471287909..8506f5356 100644 --- a/mesalib/src/mesa/drivers/dri/common/dri_util.c +++ b/mesalib/src/mesa/drivers/dri/common/dri_util.c @@ -677,7 +677,7 @@ dri2ReleaseBuffer(__DRIscreen *screen, __DRIbuffer *buffer) static int -dri2ConfigQueryb(__DRIscreen *screen, const char *var, GLboolean *val) +dri2ConfigQueryb(__DRIscreen *screen, const char *var, bool *val) { if (!driCheckOption(&screen->optionCache, var, DRI_BOOL)) return -1; @@ -688,7 +688,7 @@ dri2ConfigQueryb(__DRIscreen *screen, const char *var, GLboolean *val) } static int -dri2ConfigQueryi(__DRIscreen *screen, const char *var, GLint *val) +dri2ConfigQueryi(__DRIscreen *screen, const char *var, int *val) { if (!driCheckOption(&screen->optionCache, var, DRI_INT) && !driCheckOption(&screen->optionCache, var, DRI_ENUM)) @@ -700,7 +700,7 @@ dri2ConfigQueryi(__DRIscreen *screen, const char *var, GLint *val) } static int -dri2ConfigQueryf(__DRIscreen *screen, const char *var, GLfloat *val) +dri2ConfigQueryf(__DRIscreen *screen, const char *var, float *val) { if (!driCheckOption(&screen->optionCache, var, DRI_FLOAT)) return -1; diff --git a/mesalib/src/mesa/drivers/dri/common/xmlconfig.c b/mesalib/src/mesa/drivers/dri/common/xmlconfig.c index b95e452f1..5091c115b 100644 --- a/mesalib/src/mesa/drivers/dri/common/xmlconfig.c +++ b/mesalib/src/mesa/drivers/dri/common/xmlconfig.c @@ -27,8 +27,6 @@ * \author Felix Kuehling */ -#include "main/glheader.h" - #include #include #include @@ -106,15 +104,15 @@ static const char *__getProgramName () { #endif /** \brief Find an option in an option cache with the name as key */ -static GLuint findOption (const driOptionCache *cache, const char *name) { - GLuint len = strlen (name); - GLuint size = 1 << cache->tableSize, mask = size - 1; - GLuint hash = 0; - GLuint i, shift; +static uint32_t findOption (const driOptionCache *cache, const char *name) { + uint32_t len = strlen (name); + uint32_t size = 1 << cache->tableSize, mask = size - 1; + uint32_t hash = 0; + uint32_t i, shift; /* compute a hash from the variable length name */ for (i = 0, shift = 0; i < len; ++i, shift = (shift+8) & 31) - hash += (GLuint)name[i] << shift; + hash += (uint32_t)name[i] << shift; hash *= hash; hash = (hash >> (16-cache->tableSize/2)) & mask; @@ -134,7 +132,7 @@ static GLuint findOption (const driOptionCache *cache, const char *name) { /** \brief Like strdup but using malloc and with error checking. */ #define XSTRDUP(dest,source) do { \ - GLuint len = strlen (source); \ + uint32_t len = strlen (source); \ if (!(dest = malloc(len+1))) { \ fprintf (stderr, "%s: %d: out of memory.\n", __FILE__, __LINE__); \ abort(); \ @@ -146,8 +144,8 @@ static int compare (const void *a, const void *b) { return strcmp (*(char *const*)a, *(char *const*)b); } /** \brief Binary search in a string array. */ -static GLuint bsearchStr (const XML_Char *name, - const XML_Char *elems[], GLuint count) { +static uint32_t bsearchStr (const XML_Char *name, + const XML_Char *elems[], uint32_t count) { const XML_Char **found; found = bsearch (&name, elems, count, sizeof (XML_Char *), compare); if (found) @@ -165,11 +163,11 @@ static GLuint bsearchStr (const XML_Char *name, * returning tail points to the first character that is not part of * the integer number. If no number was found then tail points to the * start of the input string. */ -static GLint strToI (const XML_Char *string, const XML_Char **tail, int base) { - GLint radix = base == 0 ? 10 : base; - GLint result = 0; - GLint sign = 1; - GLboolean numberFound = GL_FALSE; +static int strToI (const XML_Char *string, const XML_Char **tail, int base) { + int radix = base == 0 ? 10 : base; + int result = 0; + int sign = 1; + bool numberFound = false; const XML_Char *start = string; assert (radix >= 2 && radix <= 36); @@ -180,7 +178,7 @@ static GLint strToI (const XML_Char *string, const XML_Char **tail, int base) { } else if (*string == '+') string++; if (base == 0 && *string == '0') { - numberFound = GL_TRUE; + numberFound = true; if (*(string+1) == 'x' || *(string+1) == 'X') { radix = 16; string += 2; @@ -190,7 +188,7 @@ static GLint strToI (const XML_Char *string, const XML_Char **tail, int base) { } } do { - GLint digit = -1; + int digit = -1; if (radix <= 10) { if (*string >= '0' && *string < '0' + radix) digit = *string - '0'; @@ -203,12 +201,12 @@ static GLint strToI (const XML_Char *string, const XML_Char **tail, int base) { digit = *string - 'A' + 10; } if (digit != -1) { - numberFound = GL_TRUE; + numberFound = true; result = radix*result + digit; string++; } else break; - } while (GL_TRUE); + } while (true); *tail = numberFound ? string : start; return sign * result; } @@ -225,9 +223,9 @@ static GLint strToI (const XML_Char *string, const XML_Char **tail, int base) { * to the start of the input string. * * Uses two passes for maximum accuracy. */ -static GLfloat strToF (const XML_Char *string, const XML_Char **tail) { - GLint nDigits = 0, pointPos, exponent; - GLfloat sign = 1.0f, result = 0.0f, scale; +static float strToF (const XML_Char *string, const XML_Char **tail) { + int nDigits = 0, pointPos, exponent; + float sign = 1.0f, result = 0.0f, scale; const XML_Char *start = string, *numStart; /* sign */ @@ -270,13 +268,13 @@ static GLfloat strToF (const XML_Char *string, const XML_Char **tail) { string = numStart; /* scale of the first digit */ - scale = sign * (GLfloat)pow (10.0, (GLdouble)(pointPos-1 + exponent)); + scale = sign * (float)pow (10.0, (double)(pointPos-1 + exponent)); /* second pass: parse digits */ do { if (*string != '.') { assert (*string >= '0' && *string <= '9'); - result += scale * (GLfloat)(*string - '0'); + result += scale * (float)(*string - '0'); scale *= 0.1f; nDigits--; } @@ -287,7 +285,7 @@ static GLfloat strToF (const XML_Char *string, const XML_Char **tail) { } /** \brief Parse a value of a given type. */ -static GLboolean parseValue (driOptionValue *v, driOptionType type, +static bool parseValue (driOptionValue *v, driOptionType type, const XML_Char *string) { const XML_Char *tail = NULL; /* skip leading white-space */ @@ -295,14 +293,14 @@ static GLboolean parseValue (driOptionValue *v, driOptionType type, switch (type) { case DRI_BOOL: if (!strcmp (string, "false")) { - v->_bool = GL_FALSE; + v->_bool = false; tail = string + 5; } else if (!strcmp (string, "true")) { - v->_bool = GL_TRUE; + v->_bool = true; tail = string + 4; } else - return GL_FALSE; + return false; break; case DRI_ENUM: /* enum is just a special integer */ case DRI_INT: @@ -311,23 +309,28 @@ static GLboolean parseValue (driOptionValue *v, driOptionType type, case DRI_FLOAT: v->_float = strToF (string, &tail); break; + case DRI_STRING: + if (v->_string) + free (v->_string); + v->_string = strndup(string, STRING_CONF_MAXLEN); + return GL_TRUE; } if (tail == string) - return GL_FALSE; /* empty string (or containing only white-space) */ + return false; /* empty string (or containing only white-space) */ /* skip trailing white space */ if (*tail) tail += strspn (tail, " \f\n\r\t\v"); if (*tail) - return GL_FALSE; /* something left over that is not part of value */ + return false; /* something left over that is not part of value */ - return GL_TRUE; + return true; } /** \brief Parse a list of ranges of type info->type. */ -static GLboolean parseRanges (driOptionInfo *info, const XML_Char *string) { +static bool parseRanges (driOptionInfo *info, const XML_Char *string) { XML_Char *cp, *range; - GLuint nRanges, i; + uint32_t nRanges, i; driOptionRange *ranges; XSTRDUP (cp, string); @@ -375,39 +378,41 @@ static GLboolean parseRanges (driOptionInfo *info, const XML_Char *string) { free(cp); if (i < nRanges) { free(ranges); - return GL_FALSE; + return false; } else assert (range == NULL); info->nRanges = nRanges; info->ranges = ranges; - return GL_TRUE; + return true; } /** \brief Check if a value is in one of info->ranges. */ -static GLboolean checkValue (const driOptionValue *v, const driOptionInfo *info) { - GLuint i; +static bool checkValue (const driOptionValue *v, const driOptionInfo *info) { + uint32_t i; assert (info->type != DRI_BOOL); /* should be caught by the parser */ if (info->nRanges == 0) - return GL_TRUE; + return true; switch (info->type) { case DRI_ENUM: /* enum is just a special integer */ case DRI_INT: for (i = 0; i < info->nRanges; ++i) if (v->_int >= info->ranges[i].start._int && v->_int <= info->ranges[i].end._int) - return GL_TRUE; + return true; break; case DRI_FLOAT: for (i = 0; i < info->nRanges; ++i) if (v->_float >= info->ranges[i].start._float && v->_float <= info->ranges[i].end._float) - return GL_TRUE; + return true; + break; + case DRI_STRING: break; default: assert (0); /* should never happen */ } - return GL_FALSE; + return false; } /** @@ -478,11 +483,11 @@ struct OptInfoData { const char *name; XML_Parser parser; driOptionCache *cache; - GLboolean inDriInfo; - GLboolean inSection; - GLboolean inDesc; - GLboolean inOption; - GLboolean inEnum; + bool inDriInfo; + bool inSection; + bool inDesc; + bool inOption; + bool inEnum; int curOption; }; @@ -500,10 +505,10 @@ static const XML_Char *OptInfoElems[] = { * for external configuration tools. */ static void parseEnumAttr (struct OptInfoData *data, const XML_Char **attr) { - GLuint i; + uint32_t i; const XML_Char *value = NULL, *text = NULL; driOptionValue v; - GLuint opt = data->curOption; + uint32_t opt = data->curOption; for (i = 0; attr[i]; i += 2) { if (!strcmp (attr[i], "value")) value = attr[i+1]; else if (!strcmp (attr[i], "text")) text = attr[i+1]; @@ -523,7 +528,7 @@ static void parseEnumAttr (struct OptInfoData *data, const XML_Char **attr) { * for external configuration tools. */ static void parseDescAttr (struct OptInfoData *data, const XML_Char **attr) { - GLuint i; + uint32_t i; const XML_Char *lang = NULL, *text = NULL; for (i = 0; attr[i]; i += 2) { if (!strcmp (attr[i], "lang")) lang = attr[i+1]; @@ -541,9 +546,9 @@ static void parseOptInfoAttr (struct OptInfoData *data, const XML_Char **attr) { const XML_Char *attrVal[OA_COUNT] = {NULL, NULL, NULL, NULL}; const char *defaultVal; driOptionCache *cache = data->cache; - GLuint opt, i; + uint32_t opt, i; for (i = 0; attr[i]; i += 2) { - GLuint attrName = bsearchStr (attr[i], optAttr, OA_COUNT); + uint32_t attrName = bsearchStr (attr[i], optAttr, OA_COUNT); if (attrName >= OA_COUNT) XML_FATAL ("illegal option attribute: %s", attr[i]); attrVal[attrName] = attr[i+1]; @@ -567,6 +572,8 @@ static void parseOptInfoAttr (struct OptInfoData *data, const XML_Char **attr) { cache->info[opt].type = DRI_INT; else if (!strcmp (attrVal[OA_TYPE], "float")) cache->info[opt].type = DRI_FLOAT; + else if (!strcmp (attrVal[OA_TYPE], "string")) + cache->info[opt].type = DRI_STRING; else XML_FATAL ("illegal type in option: %s.", attrVal[OA_TYPE]); @@ -608,7 +615,7 @@ static void optInfoStartElem (void *userData, const XML_Char *name, XML_FATAL1 ("nested elements."); if (attr[0]) XML_FATAL1 ("attributes specified on element."); - data->inDriInfo = GL_TRUE; + data->inDriInfo = true; break; case OI_SECTION: if (!data->inDriInfo) @@ -617,14 +624,14 @@ static void optInfoStartElem (void *userData, const XML_Char *name, XML_FATAL1 ("nested
    elements."); if (attr[0]) XML_FATAL1 ("attributes specified on
    element."); - data->inSection = GL_TRUE; + data->inSection = true; break; case OI_DESCRIPTION: if (!data->inSection && !data->inOption) XML_FATAL1 (" must be inside or inDesc) XML_FATAL1 ("nested elements."); - data->inDesc = GL_TRUE; + data->inDesc = true; parseDescAttr (data, attr); break; case OI_OPTION: @@ -634,7 +641,7 @@ static void optInfoStartElem (void *userData, const XML_Char *name, XML_FATAL1 ("