aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormarha <marha@users.sourceforge.net>2012-07-13 10:11:58 +0200
committermarha <marha@users.sourceforge.net>2012-07-13 10:11:58 +0200
commitf0a7d1d88be0c31bd471f4428c4493a93f2d9321 (patch)
tree15b5078011dc751f9c1a1bb21e51dc2e600ee205
parent165450290d6c26756ede118f52ba2164abce7c9a (diff)
downloadvcxsrv-f0a7d1d88be0c31bd471f4428c4493a93f2d9321.tar.gz
vcxsrv-f0a7d1d88be0c31bd471f4428c4493a93f2d9321.tar.bz2
vcxsrv-f0a7d1d88be0c31bd471f4428c4493a93f2d9321.zip
xserver mesa git update 13 Jul 2012
-rw-r--r--X11/extensions/randrproto.txt36
-rw-r--r--gl/configure.ac2
-rw-r--r--mesalib/configure.ac21
-rw-r--r--mesalib/docs/GL3.txt4
-rw-r--r--mesalib/docs/relnotes-8.1.html2
-rw-r--r--mesalib/scons/gallium.py4
-rw-r--r--mesalib/src/gallium/auxiliary/util/u_blit.c337
-rw-r--r--mesalib/src/gallium/auxiliary/util/u_blit.h20
-rw-r--r--mesalib/src/gallium/auxiliary/util/u_blitter.c153
-rw-r--r--mesalib/src/gallium/auxiliary/util/u_blitter.h4
-rw-r--r--mesalib/src/gallium/auxiliary/util/u_format.h29
-rw-r--r--mesalib/src/gallium/auxiliary/util/u_gen_mipmap.c84
-rw-r--r--mesalib/src/gallium/auxiliary/util/u_inlines.h26
-rw-r--r--mesalib/src/gallium/auxiliary/util/u_simple_shaders.c100
-rw-r--r--mesalib/src/gallium/auxiliary/util/u_simple_shaders.h12
-rw-r--r--mesalib/src/glsl/ir.h3
-rw-r--r--mesalib/src/glsl/ir_builder.cpp23
-rw-r--r--mesalib/src/glsl/ir_builder.h6
-rw-r--r--mesalib/src/glsl/linker.cpp119
-rw-r--r--mesalib/src/mapi/glapi/gen/gl_API.xml50
-rw-r--r--mesalib/src/mesa/main/api_validate.c26
-rw-r--r--mesalib/src/mesa/main/api_validate.h4
-rw-r--r--mesalib/src/mesa/main/context.c1
-rw-r--r--mesalib/src/mesa/main/dd.h8
-rw-r--r--mesalib/src/mesa/main/dlist.c126
-rw-r--r--mesalib/src/mesa/main/extensions.c2
-rw-r--r--mesalib/src/mesa/main/fbobject.c3
-rw-r--r--mesalib/src/mesa/main/formats.c6
-rw-r--r--mesalib/src/mesa/main/get.c9
-rw-r--r--mesalib/src/mesa/main/image.c1
-rw-r--r--mesalib/src/mesa/main/mtypes.h3
-rw-r--r--mesalib/src/mesa/main/queryobj.c82
-rw-r--r--mesalib/src/mesa/main/texformat.c10
-rw-r--r--mesalib/src/mesa/main/teximage.c9
-rw-r--r--mesalib/src/mesa/main/transformfeedback.c32
-rw-r--r--mesalib/src/mesa/main/vtxfmt.c5
-rw-r--r--mesalib/src/mesa/state_tracker/st_cb_blit.c37
-rw-r--r--mesalib/src/mesa/state_tracker/st_cb_drawpixels.c25
-rw-r--r--mesalib/src/mesa/state_tracker/st_cb_texture.c32
-rw-r--r--mesalib/src/mesa/state_tracker/st_context.c2
-rw-r--r--mesalib/src/mesa/state_tracker/st_context.h2
-rw-r--r--mesalib/src/mesa/state_tracker/st_extensions.c6
-rw-r--r--mesalib/src/mesa/state_tracker/st_format.c4
-rw-r--r--mesalib/src/mesa/vbo/vbo_exec_array.c62
-rw-r--r--mesalib/src/mesa/vbo/vbo_save_api.c45
-rw-r--r--xorg-server/glx/glxdri2.c23
-rw-r--r--xorg-server/glx/glxext.c3
-rw-r--r--xorg-server/glx/glxserver.h2
-rw-r--r--xorg-server/hw/xfree86/common/xf86AutoConfig.c1
-rw-r--r--xorg-server/hw/xfree86/dri2/dri2.c15
-rw-r--r--xorg-server/hw/xfree86/dri2/dri2.h7
-rw-r--r--xorg-server/hw/xfree86/sdksyms.sh2
-rw-r--r--xorg-server/hw/xquartz/pseudoramiX.c4
-rw-r--r--xorg-server/hw/xquartz/xpr/dri.h3
-rw-r--r--xorg-server/hw/xwin/InitOutput.c23
-rw-r--r--xorg-server/test/xtest.c1
56 files changed, 1323 insertions, 338 deletions
diff --git a/X11/extensions/randrproto.txt b/X11/extensions/randrproto.txt
index 6526b977d..2b17cee58 100644
--- a/X11/extensions/randrproto.txt
+++ b/X11/extensions/randrproto.txt
@@ -162,6 +162,7 @@ David Dawes for XFree86 DDX integration work
Thomas Winischhofer for the hardware-accelerated SiS rotation implementation
Matthew Tippett and Kevin Martin for splitting outputs and CRTCs to more
fully expose what video hardware can do
+Dave Airlie for the 1.4.0 protocol changes.
❧❧❧❧❧❧❧❧❧❧❧
@@ -277,7 +278,10 @@ ROTATION { Rotate_0
RRSELECTMASK { RRScreenChangeNotifyMask
RRCrtcChangeNotifyMask (New in version 1.2)
RROutputChangeNotifyMask (New in version 1.2)
- RROutputPropertyNotifyMask (New in version 1.2) }
+ RROutputPropertyNotifyMask (New in version 1.2)
+ RRProviderChangeNotifyMask (New in version 1.4)
+ RRProviderPropertyNotifyMask (New in version 1.4)
+ RRResourceChangeNotifyMask (New in version 1.4) }
SIZEID { CARD16 }
@@ -401,6 +405,20 @@ The name of this extension is "RANDR".
RROutputPropertyNotify events will be sent when properties change on
this output.
+ New for version 1.4:
+
+ If 'enable' contains RRProviderChangeNotifyMask,
+ RRProviderChangeNotify events will be sent whenever the role for a
+ provider object has changed.
+
+ If 'enable' contains RRProviderPropertyNotifyMask,
+ RRProviderPropertyNotify events will be sent when properties change
+ on a provider object.
+
+ If 'enable' contains RRResourceChangeNotifyMask,
+ RRResourceChangeNotify events will be sent whenever the set of
+ available RandR resources associated with the screen has changed.
+
┌───
RRSetScreenConfig
window: WINDOW
@@ -661,7 +679,7 @@ dynamic changes in the display environment.
RRListOutputProperties
output:OUTPUT
- atoms: LISTof ATOM
+ atoms: LISTofATOM
└───
Errors: Output
@@ -1345,7 +1363,7 @@ dynamic changes in the display environment.
RRListProviderProperties
provider:PROVIDERS
- atoms: LISTof ATOM
+ atoms: LISTofATOM
└───
Errors: Provider
@@ -1967,7 +1985,7 @@ The RandR extension was developed in parallel with the implementation
to ensure the feasibility of various portions of the design. As
portions of the extension are implemented, the version number of the
extension has changed to reflect the portions of the standard provided.
-This document describes the version 1.2 of the specification, the
+This document describes the version 1.4 of the specification, the
partial implementations have version numbers less than that. Here's a
list of what each version provided:
@@ -1993,6 +2011,8 @@ list of what each version provided:
transformations. Added panning. Added primary outputs.
Added standard properties.
+ 1.4: Added provider objects for handling multi-GPU systems.
+
Compatibility between 0.0 and 1.0 was *NOT* preserved, and 0.0 clients
will fail against 1.0 servers. The wire encoding op-codes were
changed for GetScreenInfo to ensure this failure in a relatively
@@ -2001,8 +2021,8 @@ graceful way. Version 1.1 servers and clients are cross compatible with
compatibility from this point. Version 1.2 offers an extended model of the
system with multiple output support. Version 1.3 adds a cheap version of
GetScreenResources to avoid expensive DDC operations, CRTC transformations,
-panning, and the primary output concept. 1.2 and 1.3 are backward-compatible
-with 1.1.
+panning, and the primary output concept. Versions 1.2 through 1.4 are
+backward-compatible with 1.1.
❧❧❧❧❧❧❧❧❧❧❧
@@ -2070,6 +2090,10 @@ A.1 Common Types
0x0002 CrtcChangeNotifyMask Added in version 1.2
0x0004 OutputChangeNotifyMask Added in version 1.2
0x0008 OutputPropertyNotifyMask Added in version 1.2
+ 0x0010 ProviderChangeNotifyMask Added in version 1.4
+ 0x0020 ProviderPropertyNotifyMask Added in version 1.4
+ 0x0040 ResourceChangeNotifyMask Added in version 1.4
+
└───
Event select mask for RRSelectInput
diff --git a/gl/configure.ac b/gl/configure.ac
index 9907db05c..58d60fa34 100644
--- a/gl/configure.ac
+++ b/gl/configure.ac
@@ -1,5 +1,5 @@
AC_PREREQ([2.60])
-AC_INIT([GLProto], [1.4.15], [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg])
+AC_INIT([GLProto], [1.4.16], [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg])
AM_INIT_AUTOMAKE([foreign dist-bzip2])
AM_MAINTAINER_MODE
diff --git a/mesalib/configure.ac b/mesalib/configure.ac
index b5250f321..08ea5beb4 100644
--- a/mesalib/configure.ac
+++ b/mesalib/configure.ac
@@ -1030,29 +1030,12 @@ xyesno)
GL_PC_CFLAGS="$X11_INCLUDES"
# XCB can only be used from pkg-config
- PKG_CHECK_MODULES([XCB],[x11-xcb xcb-glx])
+ PKG_CHECK_MODULES([XCB],[x11-xcb xcb-glx >= 1.8.1])
GL_PC_REQ_PRIV="$GL_PC_REQ_PRIV x11-xcb xcb-glx"
X11_INCLUDES="$X11_INCLUDES $XCB_CFLAGS"
GL_LIB_DEPS="$GL_LIB_DEPS $XCB_LIBS"
fi
- # Check to see if the xcb-glx library is new enough to support
- # GLX_ARB_create_context. This bit of hackery is necessary until XCB 1.8
- # is released.
- save_CPPFLAGS="$CPPFLAGS"
- save_LDFLAGS="$LDFLAGS"
- CPPFLAGS="$CPPFLAGS $X11_INCLUDES"
- LDFLAGS="$LDFLAGS $GL_LIB_DEPS"
- AC_CHECK_LIB(xcb-glx, xcb_glx_create_context_attribs_arb_checked,
- [HAVE_XCB_GLX_CREATE_CONTEXT=yes],
- [HAVE_XCB_GLX_CREATE_CONTEXT=no])
- CPPFLAGS="$save_CPPFLAGS"
- LDFLAGS="$save_LDFLAGS"
-
- if test x$HAVE_XCB_GLX_CREATE_CONTEXT = xyes; then
- X11_INCLUDES="$X11_INCLUDES -DHAVE_XCB_GLX_CREATE_CONTEXT"
- fi
-
# need DRM libs, -lpthread, etc.
GL_LIB_DEPS="$GL_LIB_DEPS $LIBDRM_LIBS -lm -lpthread $DLOPEN_LIBS"
GL_PC_LIB_PRIV="-lm -lpthread $DLOPEN_LIBS"
@@ -1061,8 +1044,6 @@ esac
# This is outside the case (above) so that it is invoked even for non-GLX
# builds.
-AM_CONDITIONAL(HAVE_XCB_GLX_CREATE_CONTEXT,
- test x$HAVE_XCB_GLX_CREATE_CONTEXT = xyes)
AM_CONDITIONAL(HAVE_XF86VIDMODE, test "x$HAVE_XF86VIDMODE" = xyes)
GLESv1_CM_LIB_DEPS="$LIBDRM_LIBS -lm -lpthread $DLOPEN_LIBS"
diff --git a/mesalib/docs/GL3.txt b/mesalib/docs/GL3.txt
index 8357289ea..7c6874568 100644
--- a/mesalib/docs/GL3.txt
+++ b/mesalib/docs/GL3.txt
@@ -100,7 +100,7 @@ GL_ARB_texture_buffer_object_rgb32 not started
GL_ARB_texture_cube_map_array not started
GL_ARB_texture_gather not started
GL_ARB_transform_feedback2 DONE
-GL_ARB_transform_feedback3 not started
+GL_ARB_transform_feedback3 DONE
GL 4.1:
@@ -121,7 +121,7 @@ GL_ARB_texture_compression_bptc not started
GL_ARB_compressed_texture_pixel_storage not started
GL_ARB_shader_atomic_counters not started
GL_ARB_texture_storage DONE (r300, r600, swrast)
-GL_ARB_transform_feedback_instanced not started
+GL_ARB_transform_feedback_instanced DONE
GL_ARB_base_instance DONE (nv50, nvc0, r600, radeonsi)
GL_ARB_shader_image_load_store not started
GL_ARB_conservative_depth DONE (softpipe)
diff --git a/mesalib/docs/relnotes-8.1.html b/mesalib/docs/relnotes-8.1.html
index c6980b688..45770d392 100644
--- a/mesalib/docs/relnotes-8.1.html
+++ b/mesalib/docs/relnotes-8.1.html
@@ -37,6 +37,8 @@ Note: some of the new features are only available with certain drivers.
<li>GL_ARB_debug_output</li>
<li>GL_ARB_shader_bit_encoding</li>
<li>GL_ARB_timer_query</li>
+<li>GL_ARB_transform_feedback3</li>
+<li>GL_ARB_transform_feedback_instanced</li>
<li>GL_EXT_unpack_subimage for ES 2.0</li>
<li>GL_EXT_read_format_bgra for ES 1.1 and 2.0</li>
<li>GL_EXT_texture_rg for ES 2.x</li>
diff --git a/mesalib/scons/gallium.py b/mesalib/scons/gallium.py
index 75c713d1c..001a5def1 100644
--- a/mesalib/scons/gallium.py
+++ b/mesalib/scons/gallium.py
@@ -368,7 +368,6 @@ def generate(env):
ccflags += [
'-Wall',
'-Wno-long-long',
- '-ffast-math',
'-fmessage-length=0', # be nice to Eclipse
]
cflags += [
@@ -405,7 +404,6 @@ def generate(env):
'/GL-', # disable whole program optimization
]
ccflags += [
- '/fp:fast', # fast floating point
'/W3', # warning level
#'/Wp64', # enable 64 bit porting warnings
'/wd4996', # disable deprecated POSIX name warnings
@@ -516,7 +514,7 @@ def generate(env):
createInstallMethods(env)
env.PkgCheckModules('X11', ['x11', 'xext', 'xdamage', 'xfixes'])
- env.PkgCheckModules('XCB', ['x11-xcb', 'xcb-glx'])
+ env.PkgCheckModules('XCB', ['x11-xcb', 'xcb-glx >= 1.8.1'])
env.PkgCheckModules('XF86VIDMODE', ['xxf86vm'])
env.PkgCheckModules('DRM', ['libdrm >= 2.4.24'])
env.PkgCheckModules('DRM_INTEL', ['libdrm_intel >= 2.4.30'])
diff --git a/mesalib/src/gallium/auxiliary/util/u_blit.c b/mesalib/src/gallium/auxiliary/util/u_blit.c
index 9bd2ef52d..b52f4c092 100644
--- a/mesalib/src/gallium/auxiliary/util/u_blit.c
+++ b/mesalib/src/gallium/auxiliary/util/u_blit.c
@@ -56,9 +56,11 @@ struct blit_state
struct pipe_context *pipe;
struct cso_context *cso;
- struct pipe_blend_state blend;
- struct pipe_depth_stencil_alpha_state depthstencil_keep;
- struct pipe_depth_stencil_alpha_state depthstencil_write;
+ struct pipe_blend_state blend_write_color, blend_keep_color;
+ struct pipe_depth_stencil_alpha_state dsa_keep_depthstencil;
+ struct pipe_depth_stencil_alpha_state dsa_write_depthstencil;
+ struct pipe_depth_stencil_alpha_state dsa_write_depth;
+ struct pipe_depth_stencil_alpha_state dsa_write_stencil;
struct pipe_rasterizer_state rasterizer;
struct pipe_sampler_state sampler;
struct pipe_viewport_state viewport;
@@ -66,13 +68,17 @@ struct blit_state
enum pipe_texture_target internal_target;
void *vs;
- void *fs[TGSI_WRITEMASK_XYZW + 1];
- void *fs_depth;
+ void *fs[PIPE_MAX_TEXTURE_TYPES][TGSI_WRITEMASK_XYZW + 1];
+ void *fs_depthstencil[PIPE_MAX_TEXTURE_TYPES];
+ void *fs_depth[PIPE_MAX_TEXTURE_TYPES];
+ void *fs_stencil[PIPE_MAX_TEXTURE_TYPES];
struct pipe_resource *vbuf; /**< quad vertices */
unsigned vbuf_slot;
float vertices[4][2][4]; /**< vertex/texcoords for quad */
+
+ boolean has_stencil_export;
};
@@ -94,24 +100,28 @@ util_create_blit(struct pipe_context *pipe, struct cso_context *cso)
ctx->cso = cso;
/* disabled blending/masking */
- memset(&ctx->blend, 0, sizeof(ctx->blend));
- ctx->blend.rt[0].colormask = PIPE_MASK_RGBA;
-
- /* no-op depth/stencil/alpha */
- memset(&ctx->depthstencil_keep, 0, sizeof(ctx->depthstencil_keep));
- memset(&ctx->depthstencil_write, 0, sizeof(ctx->depthstencil_write));
- ctx->depthstencil_write.depth.enabled = 1;
- ctx->depthstencil_write.depth.writemask = 1;
- ctx->depthstencil_write.depth.func = PIPE_FUNC_ALWAYS;
+ ctx->blend_write_color.rt[0].colormask = PIPE_MASK_RGBA;
+
+ /* depth stencil states */
+ ctx->dsa_write_depth.depth.enabled = 1;
+ ctx->dsa_write_depth.depth.writemask = 1;
+ ctx->dsa_write_depth.depth.func = PIPE_FUNC_ALWAYS;
+ ctx->dsa_write_stencil.stencil[0].enabled = 1;
+ ctx->dsa_write_stencil.stencil[0].func = PIPE_FUNC_ALWAYS;
+ ctx->dsa_write_stencil.stencil[0].fail_op = PIPE_STENCIL_OP_REPLACE;
+ ctx->dsa_write_stencil.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE;
+ ctx->dsa_write_stencil.stencil[0].zfail_op = PIPE_STENCIL_OP_REPLACE;
+ ctx->dsa_write_stencil.stencil[0].valuemask = 0xff;
+ ctx->dsa_write_stencil.stencil[0].writemask = 0xff;
+ ctx->dsa_write_depthstencil.depth = ctx->dsa_write_depth.depth;
+ ctx->dsa_write_depthstencil.stencil[0] = ctx->dsa_write_stencil.stencil[0];
/* rasterizer */
- memset(&ctx->rasterizer, 0, sizeof(ctx->rasterizer));
ctx->rasterizer.cull_face = PIPE_FACE_NONE;
ctx->rasterizer.gl_rasterization_rules = 1;
ctx->rasterizer.depth_clip = 1;
/* samplers */
- memset(&ctx->sampler, 0, sizeof(ctx->sampler));
ctx->sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
ctx->sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
ctx->sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
@@ -120,7 +130,6 @@ util_create_blit(struct pipe_context *pipe, struct cso_context *cso)
ctx->sampler.mag_img_filter = 0; /* set later */
/* vertex elements state */
- memset(&ctx->velem[0], 0, sizeof(ctx->velem[0]) * 2);
for (i = 0; i < 2; i++) {
ctx->velem[i].src_offset = i * 4 * sizeof(float);
ctx->velem[i].instance_divisor = 0;
@@ -142,6 +151,9 @@ util_create_blit(struct pipe_context *pipe, struct cso_context *cso)
else
ctx->internal_target = PIPE_TEXTURE_RECT;
+ ctx->has_stencil_export =
+ pipe->screen->get_param(pipe->screen, PIPE_CAP_SHADER_STENCIL_EXPORT);
+
return ctx;
}
@@ -153,17 +165,29 @@ void
util_destroy_blit(struct blit_state *ctx)
{
struct pipe_context *pipe = ctx->pipe;
- unsigned i;
+ unsigned i, j;
if (ctx->vs)
pipe->delete_vs_state(pipe, ctx->vs);
- for (i = 0; i < Elements(ctx->fs); i++)
- if (ctx->fs[i])
- pipe->delete_fs_state(pipe, ctx->fs[i]);
+ for (i = 0; i < Elements(ctx->fs); i++) {
+ for (j = 0; j < Elements(ctx->fs[i]); j++) {
+ if (ctx->fs[i][j])
+ pipe->delete_fs_state(pipe, ctx->fs[i][j]);
+ }
+ }
- if (ctx->fs_depth)
- pipe->delete_fs_state(pipe, ctx->fs_depth);
+ for (i = 0; i < PIPE_MAX_TEXTURE_TYPES; i++) {
+ if (ctx->fs_depthstencil[i]) {
+ pipe->delete_fs_state(pipe, ctx->fs_depthstencil[i]);
+ }
+ if (ctx->fs_depth[i]) {
+ pipe->delete_fs_state(pipe, ctx->fs_depth[i]);
+ }
+ if (ctx->fs_stencil[i]) {
+ pipe->delete_fs_state(pipe, ctx->fs_stencil[i]);
+ }
+ }
pipe_resource_reference(&ctx->vbuf, NULL);
@@ -175,30 +199,76 @@ util_destroy_blit(struct blit_state *ctx)
* Helper function to set the fragment shaders.
*/
static INLINE void
-set_fragment_shader(struct blit_state *ctx, uint writemask)
+set_fragment_shader(struct blit_state *ctx, uint writemask,
+ enum pipe_texture_target pipe_tex)
{
- if (!ctx->fs[writemask])
- ctx->fs[writemask] =
- util_make_fragment_tex_shader_writemask(ctx->pipe, TGSI_TEXTURE_2D,
+ if (!ctx->fs[pipe_tex][writemask]) {
+ unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(pipe_tex);
+
+ ctx->fs[pipe_tex][writemask] =
+ util_make_fragment_tex_shader_writemask(ctx->pipe, tgsi_tex,
TGSI_INTERPOLATE_LINEAR,
writemask);
+ }
- cso_set_fragment_shader_handle(ctx->cso, ctx->fs[writemask]);
+ cso_set_fragment_shader_handle(ctx->cso, ctx->fs[pipe_tex][writemask]);
}
/**
- * Helper function to set the depthwrite shader.
+ * Helper function to set the shader which writes depth and stencil.
*/
static INLINE void
-set_depth_fragment_shader(struct blit_state *ctx)
+set_depthstencil_fragment_shader(struct blit_state *ctx,
+ enum pipe_texture_target pipe_tex)
{
- if (!ctx->fs_depth)
- ctx->fs_depth =
- util_make_fragment_tex_shader_writedepth(ctx->pipe, TGSI_TEXTURE_2D,
+ if (!ctx->fs_depthstencil[pipe_tex]) {
+ unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(pipe_tex);
+
+ ctx->fs_depthstencil[pipe_tex] =
+ util_make_fragment_tex_shader_writedepthstencil(ctx->pipe, tgsi_tex,
TGSI_INTERPOLATE_LINEAR);
+ }
- cso_set_fragment_shader_handle(ctx->cso, ctx->fs_depth);
+ cso_set_fragment_shader_handle(ctx->cso, ctx->fs_depthstencil[pipe_tex]);
+}
+
+
+/**
+ * Helper function to set the shader which writes depth.
+ */
+static INLINE void
+set_depth_fragment_shader(struct blit_state *ctx,
+ enum pipe_texture_target pipe_tex)
+{
+ if (!ctx->fs_depth[pipe_tex]) {
+ unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(pipe_tex);
+
+ ctx->fs_depth[pipe_tex] =
+ util_make_fragment_tex_shader_writedepth(ctx->pipe, tgsi_tex,
+ TGSI_INTERPOLATE_LINEAR);
+ }
+
+ cso_set_fragment_shader_handle(ctx->cso, ctx->fs_depth[pipe_tex]);
+}
+
+
+/**
+ * Helper function to set the shader which writes stencil.
+ */
+static INLINE void
+set_stencil_fragment_shader(struct blit_state *ctx,
+ enum pipe_texture_target pipe_tex)
+{
+ if (!ctx->fs_stencil[pipe_tex]) {
+ unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(pipe_tex);
+
+ ctx->fs_stencil[pipe_tex] =
+ util_make_fragment_tex_shader_writestencil(ctx->pipe, tgsi_tex,
+ TGSI_INTERPOLATE_LINEAR);
+ }
+
+ cso_set_fragment_shader_handle(ctx->cso, ctx->fs_stencil[pipe_tex]);
}
@@ -350,20 +420,19 @@ formats_compatible(enum pipe_format src_format,
* \param writemask controls which channels in the dest surface are sourced
* from the src surface. Disabled channels are sourced
* from (0,0,0,1).
- * XXX need some control over blitting stencil.
*/
void
-util_blit_pixels_writemask(struct blit_state *ctx,
- struct pipe_resource *src_tex,
- unsigned src_level,
- int srcX0, int srcY0,
- int srcX1, int srcY1,
- int srcZ0,
- struct pipe_surface *dst,
- int dstX0, int dstY0,
- int dstX1, int dstY1,
- float z, uint filter,
- uint writemask)
+util_blit_pixels(struct blit_state *ctx,
+ struct pipe_resource *src_tex,
+ unsigned src_level,
+ int srcX0, int srcY0,
+ int srcX1, int srcY1,
+ int srcZ0,
+ struct pipe_surface *dst,
+ int dstX0, int dstY0,
+ int dstX1, int dstY1,
+ float z, uint filter,
+ uint writemask, uint zs_writemask)
{
struct pipe_context *pipe = ctx->pipe;
struct pipe_screen *screen = pipe->screen;
@@ -375,9 +444,12 @@ util_blit_pixels_writemask(struct blit_state *ctx,
const int srcW = abs(srcX1 - srcX0);
const int srcH = abs(srcY1 - srcY0);
unsigned offset;
- boolean overlap, dst_is_depth;
+ boolean overlap;
float s0, t0, s1, t1;
boolean normalized;
+ boolean is_stencil, is_depth, blit_depth, blit_stencil;
+ const struct util_format_description *src_desc =
+ util_format_description(src_tex->format);
assert(filter == PIPE_TEX_MIPFILTER_NEAREST ||
filter == PIPE_TEX_MIPFILTER_LINEAR);
@@ -394,12 +466,24 @@ util_blit_pixels_writemask(struct blit_state *ctx,
src_format = util_format_linear(src_tex->format);
dst_format = util_format_linear(dst->format);
+ /* See whether we will blit depth or stencil. */
+ is_depth = util_format_has_depth(src_desc);
+ is_stencil = util_format_has_stencil(src_desc);
+
+ blit_depth = is_depth && (zs_writemask & BLIT_WRITEMASK_Z);
+ blit_stencil = is_stencil && (zs_writemask & BLIT_WRITEMASK_STENCIL);
+
+ assert((writemask && !zs_writemask && !is_depth && !is_stencil) ||
+ (!writemask && (blit_depth || blit_stencil)));
+
/*
* Check for simple case: no format conversion, no flipping, no stretching,
* no overlapping.
* Filter mode should not matter since there's no stretching.
*/
if (formats_compatible(src_format, dst_format) &&
+ is_stencil == blit_stencil &&
+ is_depth == blit_depth &&
srcX0 < srcX1 &&
dstX0 < dstX1 &&
srcY0 < srcY1 &&
@@ -422,6 +506,17 @@ util_blit_pixels_writemask(struct blit_state *ctx,
return;
}
+ /* It's a mistake to call this function with a stencil format and
+ * without shader stencil export. We don't do software fallbacks here.
+ * Ignore stencil and only copy depth.
+ */
+ if (blit_stencil && !ctx->has_stencil_export) {
+ blit_stencil = FALSE;
+
+ if (!blit_depth)
+ return;
+ }
+
if (dst_format == dst->format) {
dst_surface = dst;
} else {
@@ -430,20 +525,11 @@ util_blit_pixels_writemask(struct blit_state *ctx,
dst_surface = pipe->create_surface(pipe, dst->texture, &templ);
}
- /* Create a temporary texture when src and dest alias or when src
- * is anything other than a 2d texture.
- * XXX should just use appropriate shader to access 1d / 3d slice / cube face,
- * much like the u_blitter code does (should be pretty trivial).
- *
- * This can still be improved upon.
+ /* Create a temporary texture when src and dest alias.
*/
- if ((src_tex == dst_surface->texture &&
+ if (src_tex == dst_surface->texture &&
dst_surface->u.tex.level == src_level &&
- dst_surface->u.tex.first_layer == srcZ0) ||
- (src_tex->target != PIPE_TEXTURE_2D &&
- src_tex->target != PIPE_TEXTURE_2D &&
- src_tex->target != PIPE_TEXTURE_RECT))
- {
+ dst_surface->u.tex.first_layer == srcZ0) {
/* Make a temporary texture which contains a copy of the source pixels.
* Then we'll sample from the temporary texture.
*/
@@ -509,6 +595,11 @@ util_blit_pixels_writemask(struct blit_state *ctx,
}
u_sampler_view_default_template(&sv_templ, tex, tex->format);
+ if (!blit_depth && blit_stencil) {
+ /* set a stencil-only format, e.g. Z24S8 --> X24S8 */
+ sv_templ.format = util_format_stencil_only(tex->format);
+ assert(sv_templ.format != PIPE_FORMAT_NONE);
+ }
sampler_view = pipe->create_sampler_view(pipe, tex, &sv_templ);
if (!sampler_view) {
@@ -520,6 +611,11 @@ util_blit_pixels_writemask(struct blit_state *ctx,
else {
/* Directly sample from the source resource/texture */
u_sampler_view_default_template(&sv_templ, src_tex, src_format);
+ if (!blit_depth && blit_stencil) {
+ /* set a stencil-only format, e.g. Z24S8 --> X24S8 */
+ sv_templ.format = util_format_stencil_only(src_format);
+ assert(sv_templ.format != PIPE_FORMAT_NONE);
+ }
sampler_view = pipe->create_sampler_view(pipe, src_tex, &sv_templ);
if (!sampler_view) {
@@ -540,15 +636,14 @@ util_blit_pixels_writemask(struct blit_state *ctx,
}
}
- dst_is_depth = util_format_is_depth_or_stencil(dst_format);
-
- assert(screen->is_format_supported(screen, sampler_view->format, ctx->internal_target,
- sampler_view->texture->nr_samples,
- PIPE_BIND_SAMPLER_VIEW));
+ assert(screen->is_format_supported(screen, sampler_view->format,
+ ctx->internal_target, sampler_view->texture->nr_samples,
+ PIPE_BIND_SAMPLER_VIEW));
assert(screen->is_format_supported(screen, dst_format, ctx->internal_target,
- dst_surface->texture->nr_samples,
- dst_is_depth ? PIPE_BIND_DEPTH_STENCIL :
- PIPE_BIND_RENDER_TARGET));
+ dst_surface->texture->nr_samples,
+ is_depth || is_stencil ? PIPE_BIND_DEPTH_STENCIL :
+ PIPE_BIND_RENDER_TARGET));
+
/* save state (restored below) */
cso_save_blend(ctx->cso);
cso_save_depth_stencil_alpha(ctx->cso);
@@ -565,23 +660,76 @@ util_blit_pixels_writemask(struct blit_state *ctx,
cso_save_vertex_buffers(ctx->cso);
/* set misc state we care about */
- cso_set_blend(ctx->cso, &ctx->blend);
- cso_set_depth_stencil_alpha(ctx->cso,
- dst_is_depth ? &ctx->depthstencil_write :
- &ctx->depthstencil_keep);
+ if (writemask)
+ cso_set_blend(ctx->cso, &ctx->blend_write_color);
+ else
+ cso_set_blend(ctx->cso, &ctx->blend_keep_color);
+
cso_set_rasterizer(ctx->cso, &ctx->rasterizer);
cso_set_vertex_elements(ctx->cso, 2, ctx->velem);
cso_set_stream_outputs(ctx->cso, 0, NULL, 0);
- /* sampler */
+ /* default sampler state */
ctx->sampler.normalized_coords = normalized;
ctx->sampler.min_img_filter = filter;
ctx->sampler.mag_img_filter = filter;
ctx->sampler.min_lod = src_level;
ctx->sampler.max_lod = src_level;
- cso_single_sampler(ctx->cso, 0, &ctx->sampler);
+
+ /* Depth stencil state, fragment shader and sampler setup depending on what
+ * we blit.
+ */
+ if (blit_depth && blit_stencil) {
+ cso_single_sampler(ctx->cso, 0, &ctx->sampler);
+ /* don't filter stencil */
+ ctx->sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
+ ctx->sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
+ cso_single_sampler(ctx->cso, 1, &ctx->sampler);
+
+ cso_set_depth_stencil_alpha(ctx->cso, &ctx->dsa_write_depthstencil);
+ set_depthstencil_fragment_shader(ctx, sampler_view->texture->target);
+ }
+ else if (blit_depth) {
+ cso_single_sampler(ctx->cso, 0, &ctx->sampler);
+ cso_set_depth_stencil_alpha(ctx->cso, &ctx->dsa_write_depth);
+ set_depth_fragment_shader(ctx, sampler_view->texture->target);
+ }
+ else if (blit_stencil) {
+ /* don't filter stencil */
+ ctx->sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
+ ctx->sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
+ cso_single_sampler(ctx->cso, 0, &ctx->sampler);
+
+ cso_set_depth_stencil_alpha(ctx->cso, &ctx->dsa_write_stencil);
+ set_stencil_fragment_shader(ctx, sampler_view->texture->target);
+ }
+ else { /* color */
+ cso_single_sampler(ctx->cso, 0, &ctx->sampler);
+ cso_set_depth_stencil_alpha(ctx->cso, &ctx->dsa_keep_depthstencil);
+ set_fragment_shader(ctx, writemask, sampler_view->texture->target);
+ }
cso_single_sampler_done(ctx->cso);
+ /* textures */
+ if (blit_depth && blit_stencil) {
+ /* Setup two samplers, one for depth and the other one for stencil. */
+ struct pipe_sampler_view templ;
+ struct pipe_sampler_view *views[2];
+
+ templ = *sampler_view;
+ templ.format = util_format_stencil_only(templ.format);
+ assert(templ.format != PIPE_FORMAT_NONE);
+
+ views[0] = sampler_view;
+ views[1] = pipe->create_sampler_view(pipe, views[0]->texture, &templ);
+ cso_set_fragment_sampler_views(ctx->cso, 2, views);
+
+ pipe_sampler_view_reference(&views[1], NULL);
+ }
+ else {
+ cso_set_fragment_sampler_views(ctx->cso, 1, &sampler_view);
+ }
+
/* viewport */
ctx->viewport.scale[0] = 0.5f * dst_surface->width;
ctx->viewport.scale[1] = 0.5f * dst_surface->height;
@@ -593,15 +741,6 @@ util_blit_pixels_writemask(struct blit_state *ctx,
ctx->viewport.translate[3] = 0.0f;
cso_set_viewport(ctx->cso, &ctx->viewport);
- /* texture */
- cso_set_fragment_sampler_views(ctx->cso, 1, &sampler_view);
-
- /* shaders */
- if (dst_is_depth) {
- set_depth_fragment_shader(ctx);
- } else {
- set_fragment_shader(ctx, writemask);
- }
set_vertex_shader(ctx);
cso_set_geometry_shader_handle(ctx->cso, NULL);
@@ -609,7 +748,7 @@ util_blit_pixels_writemask(struct blit_state *ctx,
memset(&fb, 0, sizeof(fb));
fb.width = dst_surface->width;
fb.height = dst_surface->height;
- if (dst_is_depth) {
+ if (blit_depth || blit_stencil) {
fb.zsbuf = dst_surface;
} else {
fb.nr_cbufs = 1;
@@ -655,31 +794,6 @@ util_blit_pixels_writemask(struct blit_state *ctx,
}
-void
-util_blit_pixels(struct blit_state *ctx,
- struct pipe_resource *src_tex,
- unsigned src_level,
- int srcX0, int srcY0,
- int srcX1, int srcY1,
- int srcZ,
- struct pipe_surface *dst,
- int dstX0, int dstY0,
- int dstX1, int dstY1,
- float z, uint filter )
-{
- util_blit_pixels_writemask( ctx, src_tex,
- src_level,
- srcX0, srcY0,
- srcX1, srcY1,
- srcZ,
- dst,
- dstX0, dstY0,
- dstX1, dstY1,
- z, filter,
- TGSI_WRITEMASK_XYZW );
-}
-
-
/**
* Copy pixel block from src texture to dst surface.
* The sampler view's first_level field indicates the source
@@ -747,8 +861,8 @@ util_blit_pixels_tex(struct blit_state *ctx,
cso_save_vertex_buffers(ctx->cso);
/* set misc state we care about */
- cso_set_blend(ctx->cso, &ctx->blend);
- cso_set_depth_stencil_alpha(ctx->cso, &ctx->depthstencil_keep);
+ cso_set_blend(ctx->cso, &ctx->blend_write_color);
+ cso_set_depth_stencil_alpha(ctx->cso, &ctx->dsa_keep_depthstencil);
cso_set_rasterizer(ctx->cso, &ctx->rasterizer);
cso_set_vertex_elements(ctx->cso, 2, ctx->velem);
cso_set_stream_outputs(ctx->cso, 0, NULL, 0);
@@ -775,7 +889,8 @@ util_blit_pixels_tex(struct blit_state *ctx,
cso_set_fragment_sampler_views(ctx->cso, 1, &src_sampler_view);
/* shaders */
- set_fragment_shader(ctx, TGSI_WRITEMASK_XYZW);
+ set_fragment_shader(ctx, TGSI_WRITEMASK_XYZW,
+ src_sampler_view->texture->target);
set_vertex_shader(ctx);
cso_set_geometry_shader_handle(ctx->cso, NULL);
diff --git a/mesalib/src/gallium/auxiliary/util/u_blit.h b/mesalib/src/gallium/auxiliary/util/u_blit.h
index 810d01b04..56ab03083 100644
--- a/mesalib/src/gallium/auxiliary/util/u_blit.h
+++ b/mesalib/src/gallium/auxiliary/util/u_blit.h
@@ -31,6 +31,8 @@
#include "pipe/p_compiler.h"
+/* for TGSI_WRITEMASK_* specification in util_blit_pixels */
+#include "pipe/p_shader_tokens.h"
#ifdef __cplusplus
@@ -44,6 +46,8 @@ struct pipe_resource;
struct pipe_sampler_view;
struct pipe_surface;
+#define BLIT_WRITEMASK_Z 1
+#define BLIT_WRITEMASK_STENCIL 2
extern struct blit_state *
util_create_blit(struct pipe_context *pipe, struct cso_context *cso);
@@ -61,20 +65,8 @@ util_blit_pixels(struct blit_state *ctx,
struct pipe_surface *dst,
int dstX0, int dstY0,
int dstX1, int dstY1,
- float z, uint filter);
-
-void
-util_blit_pixels_writemask(struct blit_state *ctx,
- struct pipe_resource *src_tex,
- unsigned src_level,
- int srcX0, int srcY0,
- int srcX1, int srcY1,
- int srcZ0,
- struct pipe_surface *dst,
- int dstX0, int dstY0,
- int dstX1, int dstY1,
- float z, uint filter,
- uint writemask);
+ float z, uint filter,
+ uint writemask, uint zs_writemask);
extern void
util_blit_pixels_tex(struct blit_state *ctx,
diff --git a/mesalib/src/gallium/auxiliary/util/u_blitter.c b/mesalib/src/gallium/auxiliary/util/u_blitter.c
index 47d0227a9..b31ac2d5c 100644
--- a/mesalib/src/gallium/auxiliary/util/u_blitter.c
+++ b/mesalib/src/gallium/auxiliary/util/u_blitter.c
@@ -78,6 +78,8 @@ struct blitter_context_priv
/* FS which outputs a depth from a texture,
where the index is PIPE_TEXTURE_* to be sampled. */
void *fs_texfetch_depth[PIPE_MAX_TEXTURE_TYPES];
+ void *fs_texfetch_depthstencil[PIPE_MAX_TEXTURE_TYPES];
+ void *fs_texfetch_stencil[PIPE_MAX_TEXTURE_TYPES];
/* Blend state. */
void *blend_write_color; /**< blend state with writemask of RGBA */
@@ -112,6 +114,7 @@ struct blitter_context_priv
boolean has_geometry_shader;
boolean vertex_has_integers;
boolean has_stream_out;
+ boolean has_stencil_export;
};
static void blitter_draw_rectangle(struct blitter_context *blitter,
@@ -163,6 +166,10 @@ struct blitter_context *util_blitter_create(struct pipe_context *pipe)
pipe->screen->get_param(pipe->screen,
PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS) != 0;
+ ctx->has_stencil_export =
+ pipe->screen->get_param(pipe->screen,
+ PIPE_CAP_SHADER_STENCIL_EXPORT);
+
/* blend state objects */
memset(&blend, 0, sizeof(blend));
ctx->blend_keep_color = pipe->create_blend_state(pipe, &blend);
@@ -314,6 +321,10 @@ void util_blitter_destroy(struct blitter_context *blitter)
pipe->delete_fs_state(pipe, ctx->fs_texfetch_col[i]);
if (ctx->fs_texfetch_depth[i])
pipe->delete_fs_state(pipe, ctx->fs_texfetch_depth[i]);
+ if (ctx->fs_texfetch_depthstencil[i])
+ pipe->delete_fs_state(pipe, ctx->fs_texfetch_depthstencil[i]);
+ if (ctx->fs_texfetch_stencil[i])
+ pipe->delete_fs_state(pipe, ctx->fs_texfetch_stencil[i]);
}
for (i = 0; i <= PIPE_MAX_COLOR_BUFS; i++) {
@@ -653,32 +664,6 @@ void *blitter_get_fs_col(struct blitter_context_priv *ctx, unsigned num_cbufs,
}
}
-/** Convert PIPE_TEXTURE_x to TGSI_TEXTURE_x */
-static unsigned
-pipe_tex_to_tgsi_tex(enum pipe_texture_target pipe_tex_target)
-{
- switch (pipe_tex_target) {
- case PIPE_TEXTURE_1D:
- return TGSI_TEXTURE_1D;
- case PIPE_TEXTURE_2D:
- return TGSI_TEXTURE_2D;
- case PIPE_TEXTURE_RECT:
- return TGSI_TEXTURE_RECT;
- case PIPE_TEXTURE_3D:
- return TGSI_TEXTURE_3D;
- case PIPE_TEXTURE_CUBE:
- return TGSI_TEXTURE_CUBE;
- case PIPE_TEXTURE_1D_ARRAY:
- return TGSI_TEXTURE_1D_ARRAY;
- case PIPE_TEXTURE_2D_ARRAY:
- return TGSI_TEXTURE_2D_ARRAY;
- default:
- assert(0 && "unexpected texture target");
- return TGSI_TEXTURE_UNKNOWN;
- }
-}
-
-
static INLINE
void *blitter_get_fs_texfetch_col(struct blitter_context_priv *ctx,
unsigned tex_target)
@@ -689,7 +674,7 @@ void *blitter_get_fs_texfetch_col(struct blitter_context_priv *ctx,
/* Create the fragment shader on-demand. */
if (!ctx->fs_texfetch_col[tex_target]) {
- unsigned tgsi_tex = pipe_tex_to_tgsi_tex(tex_target);
+ unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(tex_target);
ctx->fs_texfetch_col[tex_target] =
util_make_fragment_tex_shader(pipe, tgsi_tex, TGSI_INTERPOLATE_LINEAR);
@@ -708,7 +693,7 @@ void *blitter_get_fs_texfetch_depth(struct blitter_context_priv *ctx,
/* Create the fragment shader on-demand. */
if (!ctx->fs_texfetch_depth[tex_target]) {
- unsigned tgsi_tex = pipe_tex_to_tgsi_tex(tex_target);
+ unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(tex_target);
ctx->fs_texfetch_depth[tex_target] =
util_make_fragment_tex_shader_writedepth(pipe, tgsi_tex,
@@ -718,6 +703,46 @@ void *blitter_get_fs_texfetch_depth(struct blitter_context_priv *ctx,
return ctx->fs_texfetch_depth[tex_target];
}
+static INLINE
+void *blitter_get_fs_texfetch_depthstencil(struct blitter_context_priv *ctx,
+ unsigned tex_target)
+{
+ struct pipe_context *pipe = ctx->base.pipe;
+
+ assert(tex_target < PIPE_MAX_TEXTURE_TYPES);
+
+ /* Create the fragment shader on-demand. */
+ if (!ctx->fs_texfetch_depthstencil[tex_target]) {
+ unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(tex_target);
+
+ ctx->fs_texfetch_depthstencil[tex_target] =
+ util_make_fragment_tex_shader_writedepthstencil(pipe, tgsi_tex,
+ TGSI_INTERPOLATE_LINEAR);
+ }
+
+ return ctx->fs_texfetch_depthstencil[tex_target];
+}
+
+static INLINE
+void *blitter_get_fs_texfetch_stencil(struct blitter_context_priv *ctx,
+ unsigned tex_target)
+{
+ struct pipe_context *pipe = ctx->base.pipe;
+
+ assert(tex_target < PIPE_MAX_TEXTURE_TYPES);
+
+ /* Create the fragment shader on-demand. */
+ if (!ctx->fs_texfetch_stencil[tex_target]) {
+ unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(tex_target);
+
+ ctx->fs_texfetch_stencil[tex_target] =
+ util_make_fragment_tex_shader_writestencil(pipe, tgsi_tex,
+ TGSI_INTERPOLATE_LINEAR);
+ }
+
+ return ctx->fs_texfetch_stencil[tex_target];
+}
+
static void blitter_set_common_draw_rect_state(struct blitter_context_priv *ctx)
{
struct pipe_context *pipe = ctx->base.pipe;
@@ -892,7 +917,7 @@ void util_blitter_default_src_texture(struct pipe_sampler_view *src_templ,
src_templ->u.tex.last_level = srclevel;
src_templ->u.tex.first_layer = 0;
src_templ->u.tex.last_layer =
- src->target == PIPE_TEXTURE_3D ? src->depth0 - 1
+ src->target == PIPE_TEXTURE_3D ? u_minify(src->depth0, srclevel) - 1
: src->array_size - 1;
src_templ->swizzle_r = PIPE_SWIZZLE_RED;
src_templ->swizzle_g = PIPE_SWIZZLE_GREEN;
@@ -916,6 +941,8 @@ void util_blitter_copy_texture(struct blitter_context *blitter,
struct pipe_sampler_view src_templ, *src_view;
unsigned bind;
boolean is_stencil, is_depth;
+ const struct util_format_description *src_desc =
+ util_format_description(src->format);
/* Give up if textures are not set. */
assert(dst && src);
@@ -925,8 +952,8 @@ void util_blitter_copy_texture(struct blitter_context *blitter,
assert(src->target < PIPE_MAX_TEXTURE_TYPES);
/* Is this a ZS format? */
- is_depth = util_format_get_component_bits(src->format, UTIL_FORMAT_COLORSPACE_ZS, 0) != 0;
- is_stencil = util_format_get_component_bits(src->format, UTIL_FORMAT_COLORSPACE_ZS, 1) != 0;
+ is_depth = util_format_has_depth(src_desc);
+ is_stencil = util_format_has_stencil(src_desc);
if (is_depth || is_stencil)
bind = PIPE_BIND_DEPTH_STENCIL;
@@ -935,7 +962,7 @@ void util_blitter_copy_texture(struct blitter_context *blitter,
/* Check if we can sample from and render to the surfaces. */
/* (assuming copying a stencil buffer is not possible) */
- if ((!ignore_stencil && is_stencil) ||
+ if ((!ignore_stencil && is_stencil && !ctx->has_stencil_export) ||
!screen->is_format_supported(screen, dst->format, dst->target,
dst->nr_samples, bind) ||
!screen->is_format_supported(screen, src->format, src->target,
@@ -976,6 +1003,21 @@ void util_blitter_copy_texture_view(struct blitter_context *blitter,
enum pipe_texture_target src_target = src->texture->target;
unsigned width = srcbox->width;
unsigned height = srcbox->height;
+ boolean is_stencil, is_depth;
+ const struct util_format_description *src_desc =
+ util_format_description(src->format);
+
+ is_depth = util_format_has_depth(src_desc);
+ is_stencil = util_format_has_stencil(src_desc);
+
+ /* If you want a fallback for stencil copies,
+ * use util_blitter_copy_texture. */
+ if (is_stencil && !ctx->has_stencil_export) {
+ is_stencil = FALSE;
+
+ if (!is_depth)
+ return;
+ }
/* Sanity checks. */
if (dst->texture == src->texture &&
@@ -997,12 +1039,25 @@ void util_blitter_copy_texture_view(struct blitter_context *blitter,
fb_state.width = dst->width;
fb_state.height = dst->height;
- if (util_format_is_depth_or_stencil(dst->format)) {
+ if (is_depth || is_stencil) {
pipe->bind_blend_state(pipe, ctx->blend_keep_color);
- pipe->bind_depth_stencil_alpha_state(pipe,
- ctx->dsa_write_depth_keep_stencil);
- pipe->bind_fs_state(pipe,
- blitter_get_fs_texfetch_depth(ctx, src_target));
+
+ if (is_depth && is_stencil) {
+ pipe->bind_depth_stencil_alpha_state(pipe,
+ ctx->dsa_write_depth_stencil);
+ pipe->bind_fs_state(pipe,
+ blitter_get_fs_texfetch_depthstencil(ctx, src_target));
+ } else if (is_depth) {
+ pipe->bind_depth_stencil_alpha_state(pipe,
+ ctx->dsa_write_depth_keep_stencil);
+ pipe->bind_fs_state(pipe,
+ blitter_get_fs_texfetch_depth(ctx, src_target));
+ } else { /* is_stencil */
+ pipe->bind_depth_stencil_alpha_state(pipe,
+ ctx->dsa_keep_depth_write_stencil);
+ pipe->bind_fs_state(pipe,
+ blitter_get_fs_texfetch_stencil(ctx, src_target));
+ }
fb_state.nr_cbufs = 0;
fb_state.zsbuf = dst;
@@ -1017,9 +1072,29 @@ void util_blitter_copy_texture_view(struct blitter_context *blitter,
fb_state.zsbuf = 0;
}
- pipe->bind_fragment_sampler_states(pipe, 1, &ctx->sampler_state);
+ if (is_depth && is_stencil) {
+ /* Setup two samplers, one for depth and the other one for stencil. */
+ struct pipe_sampler_view templ;
+ struct pipe_sampler_view *views[2];
+ void *samplers[2] = {ctx->sampler_state, ctx->sampler_state};
+
+ templ = *src;
+ templ.format = util_format_stencil_only(templ.format);
+ assert(templ.format != PIPE_FORMAT_NONE);
+
+ views[0] = src;
+ views[1] = pipe->create_sampler_view(pipe, src->texture, &templ);
+
+ pipe->set_fragment_sampler_views(pipe, 2, views);
+ pipe->bind_fragment_sampler_states(pipe, 2, samplers);
+
+ pipe_sampler_view_reference(&views[1], NULL);
+ } else {
+ pipe->set_fragment_sampler_views(pipe, 1, &src);
+ pipe->bind_fragment_sampler_states(pipe, 1, &ctx->sampler_state);
+ }
+
pipe->bind_vertex_elements_state(pipe, ctx->velem_state);
- pipe->set_fragment_sampler_views(pipe, 1, &src);
pipe->set_framebuffer_state(pipe, &fb_state);
blitter_set_common_draw_rect_state(ctx);
diff --git a/mesalib/src/gallium/auxiliary/util/u_blitter.h b/mesalib/src/gallium/auxiliary/util/u_blitter.h
index d4d30852b..2db984c8a 100644
--- a/mesalib/src/gallium/auxiliary/util/u_blitter.h
+++ b/mesalib/src/gallium/auxiliary/util/u_blitter.h
@@ -169,8 +169,8 @@ void util_blitter_clear_depth_custom(struct blitter_context *blitter,
* The same holds for depth-stencil formats with the exception that stencil
* cannot be copied unless you set ignore_stencil to FALSE. In that case,
* a software fallback path is taken and both surfaces must be of the same
- * format.
- * XXX implement hw-accel stencil copy using shader stencil export.
+ * format. If the shader stencil export is supported, stencil copy is always
+ * accelerated.
*
* Use pipe_screen->is_format_supported to know your options.
*
diff --git a/mesalib/src/gallium/auxiliary/util/u_format.h b/mesalib/src/gallium/auxiliary/util/u_format.h
index e35e164b4..a718389dd 100644
--- a/mesalib/src/gallium/auxiliary/util/u_format.h
+++ b/mesalib/src/gallium/auxiliary/util/u_format.h
@@ -882,6 +882,35 @@ util_format_linear(enum pipe_format format)
}
/**
+ * Given a depth-stencil format, return the corresponding stencil-only format.
+ * For stencil-only formats, return the format unchanged.
+ */
+static INLINE enum pipe_format
+util_format_stencil_only(enum pipe_format format)
+{
+ switch (format) {
+ /* mask out the depth component */
+ case PIPE_FORMAT_Z24_UNORM_S8_UINT:
+ return PIPE_FORMAT_X24S8_UINT;
+ case PIPE_FORMAT_S8_UINT_Z24_UNORM:
+ return PIPE_FORMAT_S8X24_UINT;
+ case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
+ return PIPE_FORMAT_X32_S8X24_UINT;
+
+ /* stencil only formats */
+ case PIPE_FORMAT_X24S8_UINT:
+ case PIPE_FORMAT_S8X24_UINT:
+ case PIPE_FORMAT_X32_S8X24_UINT:
+ case PIPE_FORMAT_S8_UINT:
+ return format;
+
+ default:
+ assert(0);
+ return PIPE_FORMAT_NONE;
+ }
+}
+
+/**
* Return the number of components stored.
* Formats with block size != 1x1 will always have 1 component (the block).
*/
diff --git a/mesalib/src/gallium/auxiliary/util/u_gen_mipmap.c b/mesalib/src/gallium/auxiliary/util/u_gen_mipmap.c
index 2ff1af70a..a96cf6a30 100644
--- a/mesalib/src/gallium/auxiliary/util/u_gen_mipmap.c
+++ b/mesalib/src/gallium/auxiliary/util/u_gen_mipmap.c
@@ -59,14 +59,17 @@ struct gen_mipmap_state
struct pipe_context *pipe;
struct cso_context *cso;
- struct pipe_blend_state blend;
- struct pipe_depth_stencil_alpha_state depthstencil;
+ struct pipe_blend_state blend_keep_color, blend_write_color;
+ struct pipe_depth_stencil_alpha_state dsa_keep_depth, dsa_write_depth;
struct pipe_rasterizer_state rasterizer;
struct pipe_sampler_state sampler;
struct pipe_vertex_element velem[2];
void *vs;
- void *fs[TGSI_TEXTURE_COUNT]; /**< Not all are used, but simplifies code */
+
+ /** Not all are used, but simplifies code */
+ void *fs_color[TGSI_TEXTURE_COUNT];
+ void *fs_depth[TGSI_TEXTURE_COUNT];
struct pipe_resource *vbuf; /**< quad vertices */
unsigned vbuf_slot;
@@ -1272,11 +1275,16 @@ util_create_gen_mipmap(struct pipe_context *pipe,
ctx->cso = cso;
/* disabled blending/masking */
- memset(&ctx->blend, 0, sizeof(ctx->blend));
- ctx->blend.rt[0].colormask = PIPE_MASK_RGBA;
+ memset(&ctx->blend_keep_color, 0, sizeof(ctx->blend_keep_color));
+ memset(&ctx->blend_write_color, 0, sizeof(ctx->blend_write_color));
+ ctx->blend_write_color.rt[0].colormask = PIPE_MASK_RGBA;
/* no-op depth/stencil/alpha */
- memset(&ctx->depthstencil, 0, sizeof(ctx->depthstencil));
+ memset(&ctx->dsa_keep_depth, 0, sizeof(ctx->dsa_keep_depth));
+ memset(&ctx->dsa_write_depth, 0, sizeof(ctx->dsa_write_depth));
+ ctx->dsa_write_depth.depth.enabled = 1;
+ ctx->dsa_write_depth.depth.func = PIPE_FUNC_ALWAYS;
+ ctx->dsa_write_depth.depth.writemask = 1;
/* rasterizer */
memset(&ctx->rasterizer, 0, sizeof(ctx->rasterizer));
@@ -1318,14 +1326,25 @@ util_create_gen_mipmap(struct pipe_context *pipe,
* Helper function to set the fragment shaders.
*/
static INLINE void
-set_fragment_shader(struct gen_mipmap_state *ctx, uint type)
+set_fragment_shader(struct gen_mipmap_state *ctx, uint type,
+ boolean output_depth)
{
- if (!ctx->fs[type])
- ctx->fs[type] =
- util_make_fragment_tex_shader(ctx->pipe, type,
- TGSI_INTERPOLATE_LINEAR);
+ if (output_depth) {
+ if (!ctx->fs_depth[type])
+ ctx->fs_depth[type] =
+ util_make_fragment_tex_shader_writedepth(ctx->pipe, type,
+ TGSI_INTERPOLATE_LINEAR);
- cso_set_fragment_shader_handle(ctx->cso, ctx->fs[type]);
+ cso_set_fragment_shader_handle(ctx->cso, ctx->fs_depth[type]);
+ }
+ else {
+ if (!ctx->fs_color[type])
+ ctx->fs_color[type] =
+ util_make_fragment_tex_shader(ctx->pipe, type,
+ TGSI_INTERPOLATE_LINEAR);
+
+ cso_set_fragment_shader_handle(ctx->cso, ctx->fs_color[type]);
+ }
}
@@ -1464,9 +1483,13 @@ util_destroy_gen_mipmap(struct gen_mipmap_state *ctx)
struct pipe_context *pipe = ctx->pipe;
unsigned i;
- for (i = 0; i < Elements(ctx->fs); i++)
- if (ctx->fs[i])
- pipe->delete_fs_state(pipe, ctx->fs[i]);
+ for (i = 0; i < Elements(ctx->fs_color); i++)
+ if (ctx->fs_color[i])
+ pipe->delete_fs_state(pipe, ctx->fs_color[i]);
+
+ for (i = 0; i < Elements(ctx->fs_depth); i++)
+ if (ctx->fs_depth[i])
+ pipe->delete_fs_state(pipe, ctx->fs_depth[i]);
if (ctx->vs)
pipe->delete_vs_state(pipe, ctx->vs);
@@ -1500,6 +1523,7 @@ util_gen_mipmap(struct gen_mipmap_state *ctx,
uint dstLevel;
uint offset;
uint type;
+ boolean is_depth = util_format_is_depth_or_stencil(psv->format);
/* The texture object should have room for the levels which we're
* about to generate.
@@ -1538,7 +1562,9 @@ util_gen_mipmap(struct gen_mipmap_state *ctx,
/* check if we can render in the texture's format */
if (!screen->is_format_supported(screen, psv->format, pt->target,
- pt->nr_samples, PIPE_BIND_RENDER_TARGET)) {
+ pt->nr_samples,
+ is_depth ? PIPE_BIND_DEPTH_STENCIL :
+ PIPE_BIND_RENDER_TARGET)) {
fallback_gen_mipmap(ctx, pt, face, baseLevel, lastLevel);
return;
}
@@ -1559,28 +1585,25 @@ util_gen_mipmap(struct gen_mipmap_state *ctx,
cso_save_vertex_buffers(ctx->cso);
/* bind our state */
- cso_set_blend(ctx->cso, &ctx->blend);
- cso_set_depth_stencil_alpha(ctx->cso, &ctx->depthstencil);
+ cso_set_blend(ctx->cso, is_depth ? &ctx->blend_keep_color :
+ &ctx->blend_write_color);
+ cso_set_depth_stencil_alpha(ctx->cso, is_depth ? &ctx->dsa_write_depth :
+ &ctx->dsa_keep_depth);
cso_set_rasterizer(ctx->cso, &ctx->rasterizer);
cso_set_vertex_elements(ctx->cso, 2, ctx->velem);
cso_set_stream_outputs(ctx->cso, 0, NULL, 0);
- set_fragment_shader(ctx, type);
+ set_fragment_shader(ctx, type, is_depth);
set_vertex_shader(ctx);
cso_set_geometry_shader_handle(ctx->cso, NULL);
/* init framebuffer state */
memset(&fb, 0, sizeof(fb));
- fb.nr_cbufs = 1;
/* set min/mag to same filter for faster sw speed */
ctx->sampler.mag_img_filter = filter;
ctx->sampler.min_img_filter = filter;
- /*
- * XXX for small mipmap levels, it may be faster to use the software
- * fallback path...
- */
for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) {
const uint srcLevel = dstLevel - 1;
struct pipe_viewport_state vp;
@@ -1609,7 +1632,9 @@ util_gen_mipmap(struct gen_mipmap_state *ctx,
layer = face;
memset(&surf_templ, 0, sizeof(surf_templ));
- u_surface_default_template(&surf_templ, pt, PIPE_BIND_RENDER_TARGET);
+ u_surface_default_template(&surf_templ, pt,
+ is_depth ? PIPE_BIND_DEPTH_STENCIL :
+ PIPE_BIND_RENDER_TARGET);
surf_templ.u.tex.level = dstLevel;
surf_templ.u.tex.first_layer = layer;
surf_templ.u.tex.last_layer = layer;
@@ -1618,7 +1643,14 @@ util_gen_mipmap(struct gen_mipmap_state *ctx,
/*
* Setup framebuffer / dest surface
*/
- fb.cbufs[0] = surf;
+ if (is_depth) {
+ fb.nr_cbufs = 0;
+ fb.zsbuf = surf;
+ }
+ else {
+ fb.nr_cbufs = 1;
+ fb.cbufs[0] = surf;
+ }
fb.width = u_minify(pt->width0, dstLevel);
fb.height = u_minify(pt->height0, dstLevel);
cso_set_framebuffer(ctx->cso, &fb);
diff --git a/mesalib/src/gallium/auxiliary/util/u_inlines.h b/mesalib/src/gallium/auxiliary/util/u_inlines.h
index 2ec153c58..2d603e4dd 100644
--- a/mesalib/src/gallium/auxiliary/util/u_inlines.h
+++ b/mesalib/src/gallium/auxiliary/util/u_inlines.h
@@ -30,6 +30,7 @@
#include "pipe/p_context.h"
#include "pipe/p_defines.h"
+#include "pipe/p_shader_tokens.h"
#include "pipe/p_state.h"
#include "pipe/p_screen.h"
#include "util/u_debug.h"
@@ -545,6 +546,31 @@ util_query_clear_result(union pipe_query_result *result, unsigned type)
}
}
+/** Convert PIPE_TEXTURE_x to TGSI_TEXTURE_x */
+static INLINE unsigned
+util_pipe_tex_to_tgsi_tex(enum pipe_texture_target pipe_tex_target)
+{
+ switch (pipe_tex_target) {
+ case PIPE_TEXTURE_1D:
+ return TGSI_TEXTURE_1D;
+ case PIPE_TEXTURE_2D:
+ return TGSI_TEXTURE_2D;
+ case PIPE_TEXTURE_RECT:
+ return TGSI_TEXTURE_RECT;
+ case PIPE_TEXTURE_3D:
+ return TGSI_TEXTURE_3D;
+ case PIPE_TEXTURE_CUBE:
+ return TGSI_TEXTURE_CUBE;
+ case PIPE_TEXTURE_1D_ARRAY:
+ return TGSI_TEXTURE_1D_ARRAY;
+ case PIPE_TEXTURE_2D_ARRAY:
+ return TGSI_TEXTURE_2D_ARRAY;
+ default:
+ assert(0 && "unexpected texture target");
+ return TGSI_TEXTURE_UNKNOWN;
+ }
+}
+
#ifdef __cplusplus
}
#endif
diff --git a/mesalib/src/gallium/auxiliary/util/u_simple_shaders.c b/mesalib/src/gallium/auxiliary/util/u_simple_shaders.c
index 320c0f7a8..3476b6ce0 100644
--- a/mesalib/src/gallium/auxiliary/util/u_simple_shaders.c
+++ b/mesalib/src/gallium/auxiliary/util/u_simple_shaders.c
@@ -211,6 +211,106 @@ util_make_fragment_tex_shader_writedepth(struct pipe_context *pipe,
/**
+ * Make a simple fragment texture shader which reads the texture unit 0 and 1
+ * and writes it as depth and stencil, respectively.
+ */
+void *
+util_make_fragment_tex_shader_writedepthstencil(struct pipe_context *pipe,
+ unsigned tex_target,
+ unsigned interp_mode)
+{
+ struct ureg_program *ureg;
+ struct ureg_src depth_sampler, stencil_sampler;
+ struct ureg_src tex;
+ struct ureg_dst out, depth, stencil;
+ struct ureg_src imm;
+
+ ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT );
+ if (ureg == NULL)
+ return NULL;
+
+ depth_sampler = ureg_DECL_sampler( ureg, 0 );
+ stencil_sampler = ureg_DECL_sampler( ureg, 1 );
+
+ tex = ureg_DECL_fs_input( ureg,
+ TGSI_SEMANTIC_GENERIC, 0,
+ interp_mode );
+
+ out = ureg_DECL_output( ureg,
+ TGSI_SEMANTIC_COLOR,
+ 0 );
+
+ depth = ureg_DECL_output( ureg,
+ TGSI_SEMANTIC_POSITION,
+ 0 );
+
+ stencil = ureg_DECL_output( ureg,
+ TGSI_SEMANTIC_STENCIL,
+ 0 );
+
+ imm = ureg_imm4f( ureg, 0, 0, 0, 1 );
+
+ ureg_MOV( ureg, out, imm );
+
+ ureg_TEX( ureg,
+ ureg_writemask(depth, TGSI_WRITEMASK_Z),
+ tex_target, tex, depth_sampler );
+ ureg_TEX( ureg,
+ ureg_writemask(stencil, TGSI_WRITEMASK_Y),
+ tex_target, tex, stencil_sampler );
+ ureg_END( ureg );
+
+ return ureg_create_shader_and_destroy( ureg, pipe );
+}
+
+
+/**
+ * Make a simple fragment texture shader which reads a texture and writes it
+ * as stencil.
+ */
+void *
+util_make_fragment_tex_shader_writestencil(struct pipe_context *pipe,
+ unsigned tex_target,
+ unsigned interp_mode)
+{
+ struct ureg_program *ureg;
+ struct ureg_src stencil_sampler;
+ struct ureg_src tex;
+ struct ureg_dst out, stencil;
+ struct ureg_src imm;
+
+ ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT );
+ if (ureg == NULL)
+ return NULL;
+
+ stencil_sampler = ureg_DECL_sampler( ureg, 0 );
+
+ tex = ureg_DECL_fs_input( ureg,
+ TGSI_SEMANTIC_GENERIC, 0,
+ interp_mode );
+
+ out = ureg_DECL_output( ureg,
+ TGSI_SEMANTIC_COLOR,
+ 0 );
+
+ stencil = ureg_DECL_output( ureg,
+ TGSI_SEMANTIC_STENCIL,
+ 0 );
+
+ imm = ureg_imm4f( ureg, 0, 0, 0, 1 );
+
+ ureg_MOV( ureg, out, imm );
+
+ ureg_TEX( ureg,
+ ureg_writemask(stencil, TGSI_WRITEMASK_Y),
+ tex_target, tex, stencil_sampler );
+ ureg_END( ureg );
+
+ return ureg_create_shader_and_destroy( ureg, pipe );
+}
+
+
+/**
* Make simple fragment color pass-through shader.
*/
void *
diff --git a/mesalib/src/gallium/auxiliary/util/u_simple_shaders.h b/mesalib/src/gallium/auxiliary/util/u_simple_shaders.h
index 5f31b72c4..0764998a3 100644
--- a/mesalib/src/gallium/auxiliary/util/u_simple_shaders.h
+++ b/mesalib/src/gallium/auxiliary/util/u_simple_shaders.h
@@ -75,6 +75,18 @@ util_make_fragment_tex_shader_writedepth(struct pipe_context *pipe,
extern void *
+util_make_fragment_tex_shader_writedepthstencil(struct pipe_context *pipe,
+ unsigned tex_target,
+ unsigned interp_mode);
+
+
+extern void *
+util_make_fragment_tex_shader_writestencil(struct pipe_context *pipe,
+ unsigned tex_target,
+ unsigned interp_mode);
+
+
+extern void *
util_make_fragment_passthrough_shader(struct pipe_context *pipe);
diff --git a/mesalib/src/glsl/ir.h b/mesalib/src/glsl/ir.h
index b54e2f2e0..9bbf3b7ef 100644
--- a/mesalib/src/glsl/ir.h
+++ b/mesalib/src/glsl/ir.h
@@ -1341,7 +1341,8 @@ enum ir_texture_opcode {
class ir_texture : public ir_rvalue {
public:
ir_texture(enum ir_texture_opcode op)
- : op(op), projector(NULL), shadow_comparitor(NULL), offset(NULL)
+ : op(op), coordinate(NULL), projector(NULL), shadow_comparitor(NULL),
+ offset(NULL)
{
this->ir_type = ir_type_texture;
}
diff --git a/mesalib/src/glsl/ir_builder.cpp b/mesalib/src/glsl/ir_builder.cpp
index 9a16c90e5..d96e25c18 100644
--- a/mesalib/src/glsl/ir_builder.cpp
+++ b/mesalib/src/glsl/ir_builder.cpp
@@ -77,6 +77,21 @@ swizzle(operand a, int swizzle, int components)
}
ir_swizzle *
+swizzle_for_size(operand a, int components)
+{
+ void *mem_ctx = ralloc_parent(a.val);
+
+ if (a.val->type->vector_elements < components)
+ components = a.val->type->vector_elements;
+
+ unsigned s[4] = { 0, 1, 2, 3 };
+ for (int i = components; i < 4; i++)
+ s[i] = components - 1;
+
+ return new(mem_ctx) ir_swizzle(a.val, s, components);
+}
+
+ir_swizzle *
swizzle_xxxx(operand a)
{
return swizzle(a, SWIZZLE_XXXX, 4);
@@ -143,6 +158,14 @@ swizzle_xyzw(operand a)
}
ir_expression *
+expr(ir_expression_operation op, operand a)
+{
+ void *mem_ctx = ralloc_parent(a.val);
+
+ return new(mem_ctx) ir_expression(op, a.val);
+}
+
+ir_expression *
expr(ir_expression_operation op, operand a, operand b)
{
void *mem_ctx = ralloc_parent(a.val);
diff --git a/mesalib/src/glsl/ir_builder.h b/mesalib/src/glsl/ir_builder.h
index 0ebcbab95..7a0a196ee 100644
--- a/mesalib/src/glsl/ir_builder.h
+++ b/mesalib/src/glsl/ir_builder.h
@@ -83,6 +83,7 @@ public:
ir_assignment *assign(deref lhs, operand rhs);
ir_assignment *assign(deref lhs, operand rhs, int writemask);
+ir_expression *expr(ir_expression_operation op, operand a);
ir_expression *expr(ir_expression_operation op, operand a, operand b);
ir_expression *add(operand a, operand b);
ir_expression *sub(operand a, operand b);
@@ -90,6 +91,11 @@ ir_expression *mul(operand a, operand b);
ir_expression *dot(operand a, operand b);
ir_expression *saturate(operand a);
+/**
+ * Swizzle away later components, but preserve the ordering.
+ */
+ir_swizzle *swizzle_for_size(operand a, int components);
+
ir_swizzle *swizzle_xxxx(operand a);
ir_swizzle *swizzle_yyyy(operand a);
ir_swizzle *swizzle_zzzz(operand a);
diff --git a/mesalib/src/glsl/linker.cpp b/mesalib/src/glsl/linker.cpp
index 310944752..f06298cf6 100644
--- a/mesalib/src/glsl/linker.cpp
+++ b/mesalib/src/glsl/linker.cpp
@@ -1439,8 +1439,7 @@ public:
bool accumulate_num_outputs(struct gl_shader_program *prog, unsigned *count);
bool store(struct gl_context *ctx, struct gl_shader_program *prog,
struct gl_transform_feedback_info *info, unsigned buffer,
- unsigned varying, const unsigned max_outputs) const;
-
+ const unsigned max_outputs) const;
/**
* True if assign_location() has been called for this object.
@@ -1450,6 +1449,16 @@ public:
return this->location != -1;
}
+ bool is_next_buffer_separator() const
+ {
+ return this->next_buffer_separator;
+ }
+
+ bool is_varying() const
+ {
+ return !this->next_buffer_separator && !this->skip_components;
+ }
+
/**
* Determine whether this object refers to the variable var.
*/
@@ -1527,6 +1536,17 @@ private:
* glGetTransformFeedbackVarying().
*/
unsigned size;
+
+ /**
+ * How many components to skip. If non-zero, this is
+ * gl_SkipComponents{1,2,3,4} from ARB_transform_feedback3.
+ */
+ unsigned skip_components;
+
+ /**
+ * Whether this is gl_NextBuffer from ARB_transform_feedback3.
+ */
+ bool next_buffer_separator;
};
@@ -1546,7 +1566,31 @@ tfeedback_decl::init(struct gl_context *ctx, struct gl_shader_program *prog,
this->location = -1;
this->orig_name = input;
this->is_clip_distance_mesa = false;
+ this->skip_components = 0;
+ this->next_buffer_separator = false;
+ if (ctx->Extensions.ARB_transform_feedback3) {
+ /* Parse gl_NextBuffer. */
+ if (strcmp(input, "gl_NextBuffer") == 0) {
+ this->next_buffer_separator = true;
+ return true;
+ }
+
+ /* Parse gl_SkipComponents. */
+ if (strcmp(input, "gl_SkipComponents1") == 0)
+ this->skip_components = 1;
+ else if (strcmp(input, "gl_SkipComponents2") == 0)
+ this->skip_components = 2;
+ else if (strcmp(input, "gl_SkipComponents3") == 0)
+ this->skip_components = 3;
+ else if (strcmp(input, "gl_SkipComponents4") == 0)
+ this->skip_components = 4;
+
+ if (this->skip_components)
+ return true;
+ }
+
+ /* Parse a declaration. */
const char *bracket = strrchr(input, '[');
if (bracket) {
@@ -1581,6 +1625,8 @@ tfeedback_decl::init(struct gl_context *ctx, struct gl_shader_program *prog,
bool
tfeedback_decl::is_same(const tfeedback_decl &x, const tfeedback_decl &y)
{
+ assert(x.is_varying() && y.is_varying());
+
if (strcmp(x.var_name, y.var_name) != 0)
return false;
if (x.is_subscripted != y.is_subscripted)
@@ -1603,6 +1649,8 @@ tfeedback_decl::assign_location(struct gl_context *ctx,
struct gl_shader_program *prog,
ir_variable *output_var)
{
+ assert(this->is_varying());
+
if (output_var->type->is_array()) {
/* Array variable */
const unsigned matrix_cols =
@@ -1677,6 +1725,10 @@ bool
tfeedback_decl::accumulate_num_outputs(struct gl_shader_program *prog,
unsigned *count)
{
+ if (!this->is_varying()) {
+ return true;
+ }
+
if (!this->is_assigned()) {
/* From GL_EXT_transform_feedback:
* A program will fail to link if:
@@ -1709,9 +1761,16 @@ tfeedback_decl::accumulate_num_outputs(struct gl_shader_program *prog,
bool
tfeedback_decl::store(struct gl_context *ctx, struct gl_shader_program *prog,
struct gl_transform_feedback_info *info,
- unsigned buffer,
- unsigned varying, const unsigned max_outputs) const
+ unsigned buffer, const unsigned max_outputs) const
{
+ assert(!this->next_buffer_separator);
+
+ /* Handle gl_SkipComponents. */
+ if (this->skip_components) {
+ info->BufferStride[buffer] += this->skip_components;
+ return true;
+ }
+
/* From GL_EXT_transform_feedback:
* A program will fail to link if:
*
@@ -1757,9 +1816,9 @@ tfeedback_decl::store(struct gl_context *ctx, struct gl_shader_program *prog,
}
assert(components_so_far == this->num_components());
- info->Varyings[varying].Name = ralloc_strdup(prog, this->orig_name);
- info->Varyings[varying].Type = this->type;
- info->Varyings[varying].Size = this->size;
+ info->Varyings[info->NumVarying].Name = ralloc_strdup(prog, this->orig_name);
+ info->Varyings[info->NumVarying].Type = this->type;
+ info->Varyings[info->NumVarying].Size = this->size;
info->NumVarying++;
return true;
@@ -1781,6 +1840,10 @@ parse_tfeedback_decls(struct gl_context *ctx, struct gl_shader_program *prog,
for (unsigned i = 0; i < num_names; ++i) {
if (!decls[i].init(ctx, prog, mem_ctx, varying_names[i]))
return false;
+
+ if (!decls[i].is_varying())
+ continue;
+
/* From GL_EXT_transform_feedback:
* A program will fail to link if:
*
@@ -1792,6 +1855,9 @@ parse_tfeedback_decls(struct gl_context *ctx, struct gl_shader_program *prog,
* feedback of arrays would be useless otherwise.
*/
for (unsigned j = 0; j < i; ++j) {
+ if (!decls[j].is_varying())
+ continue;
+
if (tfeedback_decl::is_same(decls[i], decls[j])) {
linker_error(prog, "Transform feedback varying %s specified "
"more than once.", varying_names[i]);
@@ -1948,6 +2014,9 @@ assign_varying_locations(struct gl_context *ctx,
}
for (unsigned i = 0; i < num_tfeedback_decls; ++i) {
+ if (!tfeedback_decls[i].is_varying())
+ continue;
+
if (!tfeedback_decls[i].is_assigned() &&
tfeedback_decls[i].matches_var(output_var)) {
if (output_var->location == -1) {
@@ -2059,9 +2128,6 @@ store_tfeedback_info(struct gl_context *ctx, struct gl_shader_program *prog,
memset(&prog->LinkedTransformFeedback, 0,
sizeof(prog->LinkedTransformFeedback));
- prog->LinkedTransformFeedback.NumBuffers =
- separate_attribs_mode ? num_tfeedback_decls : 1;
-
prog->LinkedTransformFeedback.Varyings =
rzalloc_array(prog,
struct gl_transform_feedback_varying_info,
@@ -2077,14 +2143,37 @@ store_tfeedback_info(struct gl_context *ctx, struct gl_shader_program *prog,
struct gl_transform_feedback_output,
num_outputs);
- for (unsigned i = 0; i < num_tfeedback_decls; ++i) {
- unsigned buffer = separate_attribs_mode ? i : 0;
- if (!tfeedback_decls[i].store(ctx, prog, &prog->LinkedTransformFeedback,
- buffer, i, num_outputs))
- return false;
+ unsigned num_buffers = 0;
+
+ if (separate_attribs_mode) {
+ /* GL_SEPARATE_ATTRIBS */
+ for (unsigned i = 0; i < num_tfeedback_decls; ++i) {
+ if (!tfeedback_decls[i].store(ctx, prog, &prog->LinkedTransformFeedback,
+ num_buffers, num_outputs))
+ return false;
+
+ num_buffers++;
+ }
+ }
+ else {
+ /* GL_INVERLEAVED_ATTRIBS */
+ for (unsigned i = 0; i < num_tfeedback_decls; ++i) {
+ if (tfeedback_decls[i].is_next_buffer_separator()) {
+ num_buffers++;
+ continue;
+ }
+
+ if (!tfeedback_decls[i].store(ctx, prog,
+ &prog->LinkedTransformFeedback,
+ num_buffers, num_outputs))
+ return false;
+ }
+ num_buffers++;
}
+
assert(prog->LinkedTransformFeedback.NumOutputs == num_outputs);
+ prog->LinkedTransformFeedback.NumBuffers = num_buffers;
return true;
}
diff --git a/mesalib/src/mapi/glapi/gen/gl_API.xml b/mesalib/src/mapi/glapi/gen/gl_API.xml
index c302ab94a..4c8969803 100644
--- a/mesalib/src/mapi/glapi/gen/gl_API.xml
+++ b/mesalib/src/mapi/glapi/gen/gl_API.xml
@@ -8005,7 +8005,36 @@
<xi:include href="ARB_vertex_type_2_10_10_10_rev.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
-<!-- ARB extensions #86...#94 -->
+<!-- ARB extensions #86...#93 -->
+
+<category name="GL_ARB_transform_feedback3" number="94">
+ <enum name="MAX_TRANSFORM_FEEDBACK_BUFFERS" value="0x8E70"/>
+ <enum name="MAX_VERTEX_STREAMS" value="0x8E71"/>
+
+ <function name="DrawTransformFeedbackStream" offset="assign">
+ <param name="mode" type="GLenum"/>
+ <param name="id" type="GLuint"/>
+ <param name="stream" type="GLuint"/>
+ </function>
+
+ <function name="BeginQueryIndexed" offset="assign">
+ <param name="target" type="GLenum"/>
+ <param name="index" type="GLuint"/>
+ <param name="id" type="GLuint"/>
+ </function>
+
+ <function name="EndQueryIndexed" offset="assign">
+ <param name="target" type="GLenum"/>
+ <param name="index" type="GLuint"/>
+ </function>
+
+ <function name="GetQueryIndexediv" offset="assign">
+ <param name="target" type="GLenum"/>
+ <param name="index" type="GLuint"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLint *"/>
+ </function>
+</category>
<xi:include href="ARB_ES2_compatibility.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
@@ -8015,7 +8044,24 @@
<xi:include href="ARB_robustness.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
-<!-- ARB extensions #106...#116 -->
+<!-- ARB extensions #106...#108 -->
+
+<category name="GL_ARB_transform_feedback_instanced" number="109">
+ <function name="DrawTransformFeedbackInstanced" offset="assign">
+ <param name="mode" type="GLenum"/>
+ <param name="id" type="GLuint"/>
+ <param name="primcount" type="GLsizei"/>
+ </function>
+
+ <function name="DrawTransformFeedbackStreamInstanced" offset="assign">
+ <param name="mode" type="GLenum"/>
+ <param name="id" type="GLuint"/>
+ <param name="stream" type="GLuint"/>
+ <param name="primcount" type="GLsizei"/>
+ </function>
+</category>
+
+<!-- ARB extensions #110...#116 -->
<xi:include href="ARB_base_instance.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
diff --git a/mesalib/src/mesa/main/api_validate.c b/mesalib/src/mesa/main/api_validate.c
index cf6aaf0c6..ece0a2b4a 100644
--- a/mesalib/src/mesa/main/api_validate.c
+++ b/mesalib/src/mesa/main/api_validate.c
@@ -593,26 +593,42 @@ _mesa_validate_DrawElementsInstanced(struct gl_context *ctx,
GLboolean
_mesa_validate_DrawTransformFeedback(struct gl_context *ctx,
GLenum mode,
- struct gl_transform_feedback_object *obj)
+ struct gl_transform_feedback_object *obj,
+ GLuint stream,
+ GLsizei numInstances)
{
ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
FLUSH_CURRENT(ctx, 0);
- if (!_mesa_valid_prim_mode(ctx, mode, "glDrawTransformFeedback")) {
+ if (!_mesa_valid_prim_mode(ctx, mode, "glDrawTransformFeedback*(mode)")) {
return GL_FALSE;
}
if (!obj) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glDrawTransformFeedback(name)");
+ _mesa_error(ctx, GL_INVALID_VALUE, "glDrawTransformFeedback*(name)");
return GL_FALSE;
}
if (!obj->EndedAnytime) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawTransformFeedback");
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawTransformFeedback*");
return GL_FALSE;
}
- if (!check_valid_to_render(ctx, "glDrawTransformFeedback")) {
+ if (stream >= ctx->Const.MaxVertexStreams) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glDrawTransformFeedbackStream*(index>=MaxVertexStream)");
+ return GL_FALSE;
+ }
+
+ if (numInstances <= 0) {
+ if (numInstances < 0)
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glDrawTransformFeedback*Instanced(numInstances=%d)",
+ numInstances);
+ return GL_FALSE;
+ }
+
+ if (!check_valid_to_render(ctx, "glDrawTransformFeedback*")) {
return GL_FALSE;
}
diff --git a/mesalib/src/mesa/main/api_validate.h b/mesalib/src/mesa/main/api_validate.h
index 59f329768..8dc8df4b2 100644
--- a/mesalib/src/mesa/main/api_validate.h
+++ b/mesalib/src/mesa/main/api_validate.h
@@ -83,7 +83,9 @@ _mesa_validate_DrawElementsInstanced(struct gl_context *ctx,
extern GLboolean
_mesa_validate_DrawTransformFeedback(struct gl_context *ctx,
GLenum mode,
- struct gl_transform_feedback_object *obj);
+ struct gl_transform_feedback_object *obj,
+ GLuint stream,
+ GLsizei numInstances);
#endif
diff --git a/mesalib/src/mesa/main/context.c b/mesalib/src/mesa/main/context.c
index 7de714b81..d5ccce076 100644
--- a/mesalib/src/mesa/main/context.c
+++ b/mesalib/src/mesa/main/context.c
@@ -655,6 +655,7 @@ _mesa_init_constants(struct gl_context *ctx)
ctx->Const.MaxTransformFeedbackBuffers = MAX_FEEDBACK_BUFFERS;
ctx->Const.MaxTransformFeedbackSeparateComponents = 4 * MAX_FEEDBACK_ATTRIBS;
ctx->Const.MaxTransformFeedbackInterleavedComponents = 4 * MAX_FEEDBACK_ATTRIBS;
+ ctx->Const.MaxVertexStreams = 1;
/** GL_ARB_uniform_buffer_object */
ctx->Const.MaxCombinedUniformBlocks = 36;
diff --git a/mesalib/src/mesa/main/dd.h b/mesalib/src/mesa/main/dd.h
index c8a765f47..e60d019bb 100644
--- a/mesalib/src/mesa/main/dd.h
+++ b/mesalib/src/mesa/main/dd.h
@@ -1052,6 +1052,14 @@ typedef struct {
GLsizei primcount, GLint basevertex,
GLuint baseinstance);
void (GLAPIENTRYP DrawTransformFeedback)(GLenum mode, GLuint name);
+ void (GLAPIENTRYP DrawTransformFeedbackStream)(GLenum mode, GLuint name,
+ GLuint stream);
+ void (GLAPIENTRYP DrawTransformFeedbackInstanced)(GLenum mode, GLuint name,
+ GLsizei primcount);
+ void (GLAPIENTRYP DrawTransformFeedbackStreamInstanced)(GLenum mode,
+ GLuint name,
+ GLuint stream,
+ GLsizei primcount);
/*@}*/
/**
diff --git a/mesalib/src/mesa/main/dlist.c b/mesalib/src/mesa/main/dlist.c
index a827d132d..40961b15c 100644
--- a/mesalib/src/mesa/main/dlist.c
+++ b/mesalib/src/mesa/main/dlist.c
@@ -472,6 +472,15 @@ typedef enum
/* ARB_timer_query */
OPCODE_QUERY_COUNTER,
+ /* ARB_transform_feedback3 */
+ OPCODE_BEGIN_QUERY_INDEXED,
+ OPCODE_END_QUERY_INDEXED,
+ OPCODE_DRAW_TRANSFORM_FEEDBACK_STREAM,
+
+ /* ARB_transform_feedback_instanced */
+ OPCODE_DRAW_TRANSFORM_FEEDBACK_INSTANCED,
+ OPCODE_DRAW_TRANSFORM_FEEDBACK_STREAM_INSTANCED,
+
/* The following three are meta instructions */
OPCODE_ERROR, /* raise compiled-in error */
OPCODE_CONTINUE,
@@ -504,6 +513,7 @@ union gl_dlist_node
GLuint ui;
GLenum e;
GLfloat f;
+ GLsizei si;
GLvoid *data;
void *next; /* If prev node's opcode==OPCODE_CONTINUE */
};
@@ -5338,7 +5348,6 @@ save_BeginQueryARB(GLenum target, GLuint id)
}
}
-
static void GLAPIENTRY
save_EndQueryARB(GLenum target)
{
@@ -5354,7 +5363,6 @@ save_EndQueryARB(GLenum target)
}
}
-
static void GLAPIENTRY
save_QueryCounter(GLuint id, GLenum target)
{
@@ -5371,6 +5379,39 @@ save_QueryCounter(GLuint id, GLenum target)
}
}
+static void GLAPIENTRY
+save_BeginQueryIndexed(GLenum target, GLuint index, GLuint id)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = alloc_instruction(ctx, OPCODE_BEGIN_QUERY_INDEXED, 3);
+ if (n) {
+ n[1].e = target;
+ n[2].ui = index;
+ n[3].ui = id;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_BeginQueryIndexed(ctx->Exec, (target, index, id));
+ }
+}
+
+static void GLAPIENTRY
+save_EndQueryIndexed(GLenum target, GLuint index)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = alloc_instruction(ctx, OPCODE_END_QUERY_INDEXED, 2);
+ if (n) {
+ n[1].e = target;
+ n[2].ui = index;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_EndQueryIndexed(ctx->Exec, (target, index));
+ }
+}
+
#endif /* FEATURE_queryobj */
@@ -6441,6 +6482,60 @@ save_DrawTransformFeedback(GLenum mode, GLuint name)
}
}
+static void GLAPIENTRY
+save_DrawTransformFeedbackStream(GLenum mode, GLuint name, GLuint stream)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = alloc_instruction(ctx, OPCODE_DRAW_TRANSFORM_FEEDBACK_STREAM, 3);
+ if (n) {
+ n[1].e = mode;
+ n[2].ui = name;
+ n[3].ui = stream;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_DrawTransformFeedbackStream(ctx->Exec, (mode, name, stream));
+ }
+}
+
+static void GLAPIENTRY
+save_DrawTransformFeedbackInstanced(GLenum mode, GLuint name,
+ GLsizei primcount)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = alloc_instruction(ctx, OPCODE_DRAW_TRANSFORM_FEEDBACK_INSTANCED, 3);
+ if (n) {
+ n[1].e = mode;
+ n[2].ui = name;
+ n[3].si = primcount;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_DrawTransformFeedbackInstanced(ctx->Exec, (mode, name, primcount));
+ }
+}
+
+static void GLAPIENTRY
+save_DrawTransformFeedbackStreamInstanced(GLenum mode, GLuint name,
+ GLuint stream, GLsizei primcount)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = alloc_instruction(ctx, OPCODE_DRAW_TRANSFORM_FEEDBACK_STREAM_INSTANCED, 4);
+ if (n) {
+ n[1].e = mode;
+ n[2].ui = name;
+ n[3].ui = stream;
+ n[4].si = primcount;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_DrawTransformFeedbackStreamInstanced(ctx->Exec, (mode, name, stream,
+ primcount));
+ }
+}
/* aka UseProgram() */
static void GLAPIENTRY
@@ -8368,6 +8463,12 @@ execute_list(struct gl_context *ctx, GLuint list)
case OPCODE_QUERY_COUNTER:
CALL_QueryCounter(ctx->Exec, (n[1].ui, n[2].e));
break;
+ case OPCODE_BEGIN_QUERY_INDEXED:
+ CALL_BeginQueryIndexed(ctx->Exec, (n[1].e, n[2].ui, n[3].ui));
+ break;
+ case OPCODE_END_QUERY_INDEXED:
+ CALL_EndQueryIndexed(ctx->Exec, (n[1].e, n[2].ui));
+ break;
#endif
case OPCODE_DRAW_BUFFERS_ARB:
{
@@ -8686,6 +8787,18 @@ execute_list(struct gl_context *ctx, GLuint list)
case OPCODE_DRAW_TRANSFORM_FEEDBACK:
CALL_DrawTransformFeedback(ctx->Exec, (n[1].e, n[2].ui));
break;
+ case OPCODE_DRAW_TRANSFORM_FEEDBACK_STREAM:
+ CALL_DrawTransformFeedbackStream(ctx->Exec,
+ (n[1].e, n[2].ui, n[3].ui));
+ break;
+ case OPCODE_DRAW_TRANSFORM_FEEDBACK_INSTANCED:
+ CALL_DrawTransformFeedbackInstanced(ctx->Exec,
+ (n[1].e, n[2].ui, n[3].si));
+ break;
+ case OPCODE_DRAW_TRANSFORM_FEEDBACK_STREAM_INSTANCED:
+ CALL_DrawTransformFeedbackStreamInstanced(ctx->Exec,
+ (n[1].e, n[2].ui, n[3].ui, n[4].si));
+ break;
case OPCODE_BIND_SAMPLER:
@@ -10461,6 +10574,15 @@ _mesa_create_save_table(void)
SET_PauseTransformFeedback(table, save_PauseTransformFeedback);
SET_ResumeTransformFeedback(table, save_ResumeTransformFeedback);
SET_DrawTransformFeedback(table, save_DrawTransformFeedback);
+ SET_DrawTransformFeedbackStream(table, save_DrawTransformFeedbackStream);
+ SET_DrawTransformFeedbackInstanced(table,
+ save_DrawTransformFeedbackInstanced);
+ SET_DrawTransformFeedbackStreamInstanced(table,
+ save_DrawTransformFeedbackStreamInstanced);
+#if FEATURE_queryobj
+ SET_BeginQueryIndexed(table, save_BeginQueryIndexed);
+ SET_EndQueryIndexed(table, save_EndQueryIndexed);
+#endif
#endif
/* GL_ARB_instanced_arrays */
diff --git a/mesalib/src/mesa/main/extensions.c b/mesalib/src/mesa/main/extensions.c
index dbc2813f2..0675ce75d 100644
--- a/mesalib/src/mesa/main/extensions.c
+++ b/mesalib/src/mesa/main/extensions.c
@@ -141,6 +141,8 @@ static const struct extension extension_table[] = {
{ "GL_ARB_texture_swizzle", o(EXT_texture_swizzle), GL, 2008 },
{ "GL_ARB_timer_query", o(ARB_timer_query), GL, 2010 },
{ "GL_ARB_transform_feedback2", o(ARB_transform_feedback2), GL, 2010 },
+ { "GL_ARB_transform_feedback3", o(ARB_transform_feedback3), GL, 2010 },
+ { "GL_ARB_transform_feedback_instanced", o(ARB_transform_feedback_instanced), GL, 2011 },
{ "GL_ARB_transpose_matrix", o(ARB_transpose_matrix), GL, 1999 },
{ "GL_ARB_uniform_buffer_object", o(ARB_uniform_buffer_object), GL, 2009 },
{ "GL_ARB_vertex_array_bgra", o(EXT_vertex_array_bgra), GL, 2008 },
diff --git a/mesalib/src/mesa/main/fbobject.c b/mesalib/src/mesa/main/fbobject.c
index cfaea62bb..4370c7218 100644
--- a/mesalib/src/mesa/main/fbobject.c
+++ b/mesalib/src/mesa/main/fbobject.c
@@ -1296,6 +1296,9 @@ _mesa_base_fbo_format(struct gl_context *ctx, GLenum internalFormat)
case GL_RGB10_A2UI:
return ctx->Extensions.ARB_texture_rgb10_a2ui ? GL_RGBA : 0;
+
+ case GL_RGB565:
+ return ctx->Extensions.ARB_ES2_compatibility ? GL_RGB : 0;
default:
return 0;
}
diff --git a/mesalib/src/mesa/main/formats.c b/mesalib/src/mesa/main/formats.c
index ccc0b1707..c65c9c2e1 100644
--- a/mesalib/src/mesa/main/formats.c
+++ b/mesalib/src/mesa/main/formats.c
@@ -1860,8 +1860,7 @@ _mesa_format_image_size(gl_format format, GLsizei width,
const GLuint wblocks = (width + bw - 1) / bw;
const GLuint hblocks = (height + bh - 1) / bh;
const GLuint sz = wblocks * hblocks * info->BytesPerBlock;
- assert(depth == 1);
- return sz;
+ return sz * depth;
}
else {
/* non-compressed */
@@ -1887,8 +1886,7 @@ _mesa_format_image_size64(gl_format format, GLsizei width,
const uint64_t wblocks = (width + bw - 1) / bw;
const uint64_t hblocks = (height + bh - 1) / bh;
const uint64_t sz = wblocks * hblocks * info->BytesPerBlock;
- assert(depth == 1);
- return sz;
+ return sz * depth;
}
else {
/* non-compressed */
diff --git a/mesalib/src/mesa/main/get.c b/mesalib/src/mesa/main/get.c
index cff4cf394..15de321e4 100644
--- a/mesalib/src/mesa/main/get.c
+++ b/mesalib/src/mesa/main/get.c
@@ -328,6 +328,7 @@ EXTRA_EXT(ARB_sync);
EXTRA_EXT(ARB_vertex_shader);
EXTRA_EXT(EXT_transform_feedback);
EXTRA_EXT(ARB_transform_feedback2);
+EXTRA_EXT(ARB_transform_feedback3);
EXTRA_EXT(EXT_pixel_buffer_object);
EXTRA_EXT(ARB_vertex_program);
EXTRA_EXT2(NV_point_sprite, ARB_point_sprite);
@@ -1247,6 +1248,14 @@ static const struct value_desc values[] = {
{ GL_TRANSFORM_FEEDBACK_BINDING, LOC_CUSTOM, TYPE_INT, 0,
extra_ARB_transform_feedback2 },
+ /* GL_ARB_transform_feedback3 */
+ { GL_MAX_TRANSFORM_FEEDBACK_BUFFERS,
+ CONTEXT_INT(Const.MaxTransformFeedbackBuffers),
+ extra_ARB_transform_feedback3 },
+ { GL_MAX_VERTEX_STREAMS,
+ CONTEXT_INT(Const.MaxVertexStreams),
+ extra_ARB_transform_feedback3 },
+
/* GL_ARB_geometry_shader4 */
{ GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_ARB,
CONTEXT_INT(Const.MaxGeometryTextureImageUnits),
diff --git a/mesalib/src/mesa/main/image.c b/mesalib/src/mesa/main/image.c
index b6c2645e9..678dfeb2b 100644
--- a/mesalib/src/mesa/main/image.c
+++ b/mesalib/src/mesa/main/image.c
@@ -770,6 +770,7 @@ _mesa_is_color_format(GLenum format)
case GL_R3_G3_B2:
case GL_RGB4:
case GL_RGB5:
+ case GL_RGB565:
case GL_RGB8:
case GL_RGB10:
case GL_RGB12:
diff --git a/mesalib/src/mesa/main/mtypes.h b/mesalib/src/mesa/main/mtypes.h
index bdbb5137e..1f74e6a83 100644
--- a/mesalib/src/mesa/main/mtypes.h
+++ b/mesalib/src/mesa/main/mtypes.h
@@ -2837,6 +2837,7 @@ struct gl_constants
GLuint MaxTransformFeedbackBuffers;
GLuint MaxTransformFeedbackSeparateComponents;
GLuint MaxTransformFeedbackInterleavedComponents;
+ GLuint MaxVertexStreams;
/** GL_EXT_gpu_shader4 */
GLint MinProgramTexelOffset, MaxProgramTexelOffset;
@@ -2937,6 +2938,8 @@ struct gl_extensions
GLboolean ARB_texture_storage;
GLboolean ARB_timer_query;
GLboolean ARB_transform_feedback2;
+ GLboolean ARB_transform_feedback3;
+ GLboolean ARB_transform_feedback_instanced;
GLboolean ARB_transpose_matrix;
GLboolean ARB_uniform_buffer_object;
GLboolean ARB_vertex_array_object;
diff --git a/mesalib/src/mesa/main/queryobj.c b/mesalib/src/mesa/main/queryobj.c
index cb5078411..4492a172b 100644
--- a/mesalib/src/mesa/main/queryobj.c
+++ b/mesalib/src/mesa/main/queryobj.c
@@ -263,28 +263,51 @@ _mesa_IsQueryARB(GLuint id)
return GL_FALSE;
}
+static GLboolean
+query_error_check_index(struct gl_context *ctx, GLenum target, GLuint index)
+{
+ switch (target) {
+ case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
+ case GL_PRIMITIVES_GENERATED:
+ if (index >= ctx->Const.MaxVertexStreams) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glBeginQueryIndexed(index>=MaxVertexStreams)");
+ return GL_FALSE;
+ }
+ break;
+ default:
+ if (index > 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glBeginQueryIndexed(index>0)");
+ return GL_FALSE;
+ }
+ }
+ return GL_TRUE;
+}
static void GLAPIENTRY
-_mesa_BeginQueryARB(GLenum target, GLuint id)
+_mesa_BeginQueryIndexed(GLenum target, GLuint index, GLuint id)
{
struct gl_query_object *q, **bindpt;
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END(ctx);
if (MESA_VERBOSE & VERBOSE_API)
- _mesa_debug(ctx, "glBeginQuery(%s, %u)\n",
- _mesa_lookup_enum_by_nr(target), id);
+ _mesa_debug(ctx, "glBeginQueryIndexed(%s, %u, %u)\n",
+ _mesa_lookup_enum_by_nr(target), index, id);
+
+ if (!query_error_check_index(ctx, target, index))
+ return;
FLUSH_VERTICES(ctx, _NEW_DEPTH);
bindpt = get_query_binding_point(ctx, target);
if (!bindpt) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glBeginQueryARB(target)");
+ _mesa_error(ctx, GL_INVALID_ENUM, "glBeginQuery{Indexed}(target)");
return;
}
if (id == 0) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glBeginQueryARB(id==0)");
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glBeginQuery{Indexed}(id==0)");
return;
}
@@ -293,7 +316,7 @@ _mesa_BeginQueryARB(GLenum target, GLuint id)
/* create new object */
q = ctx->Driver.NewQueryObject(ctx, id);
if (!q) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBeginQueryARB");
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBeginQuery{Indexed}");
return;
}
_mesa_HashInsert(ctx->Query.QueryObjects, id, q);
@@ -302,7 +325,7 @@ _mesa_BeginQueryARB(GLenum target, GLuint id)
/* pre-existing object */
if (q->Active) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glBeginQueryARB(query already active)");
+ "glBeginQuery{Indexed}(query already active)");
return;
}
}
@@ -320,20 +343,24 @@ _mesa_BeginQueryARB(GLenum target, GLuint id)
static void GLAPIENTRY
-_mesa_EndQueryARB(GLenum target)
+_mesa_EndQueryIndexed(GLenum target, GLuint index)
{
struct gl_query_object *q, **bindpt;
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END(ctx);
if (MESA_VERBOSE & VERBOSE_API)
- _mesa_debug(ctx, "glEndQuery(%s)\n", _mesa_lookup_enum_by_nr(target));
+ _mesa_debug(ctx, "glEndQueryIndexed(%s, %u)\n",
+ _mesa_lookup_enum_by_nr(target), index);
+
+ if (!query_error_check_index(ctx, target, index))
+ return;
FLUSH_VERTICES(ctx, _NEW_DEPTH);
bindpt = get_query_binding_point(ctx, target);
if (!bindpt) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glEndQueryARB(target)");
+ _mesa_error(ctx, GL_INVALID_ENUM, "glEndQuery{Indexed}(target)");
return;
}
@@ -343,7 +370,7 @@ _mesa_EndQueryARB(GLenum target)
if (!q || !q->Active) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glEndQueryARB(no matching glBeginQueryARB)");
+ "glEndQuery{Indexed}(no matching glBeginQuery{Indexed})");
return;
}
@@ -351,6 +378,17 @@ _mesa_EndQueryARB(GLenum target)
ctx->Driver.EndQuery(ctx, q);
}
+static void GLAPIENTRY
+_mesa_BeginQueryARB(GLenum target, GLuint id)
+{
+ _mesa_BeginQueryIndexed(target, 0, id);
+}
+
+static void GLAPIENTRY
+_mesa_EndQueryARB(GLenum target)
+{
+ _mesa_EndQueryIndexed(target, 0);
+}
static void GLAPIENTRY
_mesa_QueryCounter(GLuint id, GLenum target)
@@ -410,17 +448,22 @@ _mesa_QueryCounter(GLuint id, GLenum target)
static void GLAPIENTRY
-_mesa_GetQueryivARB(GLenum target, GLenum pname, GLint *params)
+_mesa_GetQueryIndexediv(GLenum target, GLuint index, GLenum pname,
+ GLint *params)
{
struct gl_query_object *q = NULL, **bindpt = NULL;
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END(ctx);
if (MESA_VERBOSE & VERBOSE_API)
- _mesa_debug(ctx, "glGetQueryiv(%s, %s)\n",
+ _mesa_debug(ctx, "glGetQueryIndexediv(%s, %u, %s)\n",
_mesa_lookup_enum_by_nr(target),
+ index,
_mesa_lookup_enum_by_nr(pname));
+ if (!query_error_check_index(ctx, target, index))
+ return;
+
if (target == GL_TIMESTAMP) {
if (!ctx->Extensions.ARB_timer_query) {
_mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryARB(target)");
@@ -430,7 +473,7 @@ _mesa_GetQueryivARB(GLenum target, GLenum pname, GLint *params)
else {
bindpt = get_query_binding_point(ctx, target);
if (!bindpt) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryARB(target)");
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetQuery{Indexed}iv(target)");
return;
}
@@ -445,11 +488,16 @@ _mesa_GetQueryivARB(GLenum target, GLenum pname, GLint *params)
*params = q ? q->Id : 0;
break;
default:
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryivARB(pname)");
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetQuery{Indexed}iv(pname)");
return;
}
}
+static void GLAPIENTRY
+_mesa_GetQueryivARB(GLenum target, GLenum pname, GLint *params)
+{
+ _mesa_GetQueryIndexediv(target, 0, pname, params);
+}
static void GLAPIENTRY
_mesa_GetQueryObjectivARB(GLuint id, GLenum pname, GLint *params)
@@ -650,6 +698,10 @@ _mesa_init_queryobj_dispatch(struct _glapi_table *disp)
SET_GetQueryObjecti64vEXT(disp, _mesa_GetQueryObjecti64vEXT);
SET_GetQueryObjectui64vEXT(disp, _mesa_GetQueryObjectui64vEXT);
+
+ SET_BeginQueryIndexed(disp, _mesa_BeginQueryIndexed);
+ SET_EndQueryIndexed(disp, _mesa_EndQueryIndexed);
+ SET_GetQueryIndexediv(disp, _mesa_GetQueryIndexediv);
}
diff --git a/mesalib/src/mesa/main/texformat.c b/mesalib/src/mesa/main/texformat.c
index 5fdc2ab1f..26bcbc10a 100644
--- a/mesalib/src/mesa/main/texformat.c
+++ b/mesalib/src/mesa/main/texformat.c
@@ -258,6 +258,16 @@ _mesa_choose_tex_format( struct gl_context *ctx, GLint internalFormat,
; /* fallthrough */
}
+ if (ctx->Extensions.ARB_ES2_compatibility) {
+ switch (internalFormat) {
+ case GL_RGB565:
+ RETURN_IF_SUPPORTED(MESA_FORMAT_RGB565);
+ break;
+ default:
+ ; /* fallthrough */
+ }
+ }
+
if (ctx->Extensions.MESA_ycbcr_texture) {
if (internalFormat == GL_YCBCR_MESA) {
if (type == GL_UNSIGNED_SHORT_8_8_MESA)
diff --git a/mesalib/src/mesa/main/teximage.c b/mesalib/src/mesa/main/teximage.c
index b16baaf91..126386ebe 100644
--- a/mesalib/src/mesa/main/teximage.c
+++ b/mesalib/src/mesa/main/teximage.c
@@ -138,6 +138,15 @@ _mesa_base_tex_format( struct gl_context *ctx, GLint internalFormat )
}
}
+ if (ctx->Extensions.ARB_ES2_compatibility) {
+ switch (internalFormat) {
+ case GL_RGB565:
+ return GL_RGB;
+ default:
+ ; /* fallthrough */
+ }
+ }
+
if (ctx->Extensions.ARB_depth_texture) {
switch (internalFormat) {
case GL_DEPTH_COMPONENT:
diff --git a/mesalib/src/mesa/main/transformfeedback.c b/mesalib/src/mesa/main/transformfeedback.c
index 6f8221201..7679b4b08 100644
--- a/mesalib/src/mesa/main/transformfeedback.c
+++ b/mesalib/src/mesa/main/transformfeedback.c
@@ -603,6 +603,38 @@ _mesa_TransformFeedbackVaryings(GLuint program, GLsizei count,
return;
}
+ if (ctx->Extensions.ARB_transform_feedback3) {
+ if (bufferMode == GL_INTERLEAVED_ATTRIBS) {
+ unsigned buffers = 1;
+
+ for (i = 0; i < count; i++) {
+ if (strcmp(varyings[i], "gl_NextBuffer") == 0)
+ buffers++;
+ }
+
+ if (buffers > ctx->Const.MaxTransformFeedbackBuffers) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glTransformFeedbackVaryings(too many gl_NextBuffer "
+ "occurences)");
+ return;
+ }
+ } else {
+ for (i = 0; i < count; i++) {
+ if (strcmp(varyings[i], "gl_NextBuffer") == 0 ||
+ strcmp(varyings[i], "gl_SkipComponents1") == 0 ||
+ strcmp(varyings[i], "gl_SkipComponents2") == 0 ||
+ strcmp(varyings[i], "gl_SkipComponents3") == 0 ||
+ strcmp(varyings[i], "gl_SkipComponents4") == 0) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glTransformFeedbackVaryings(SEPARATE_ATTRIBS,"
+ "varying=%s)",
+ varyings[i]);
+ return;
+ }
+ }
+ }
+ }
+
/* free existing varyings, if any */
for (i = 0; i < shProg->TransformFeedback.NumVarying; i++) {
free(shProg->TransformFeedback.VaryingNames[i]);
diff --git a/mesalib/src/mesa/main/vtxfmt.c b/mesalib/src/mesa/main/vtxfmt.c
index a27596a98..bf7a54c0a 100644
--- a/mesalib/src/mesa/main/vtxfmt.c
+++ b/mesalib/src/mesa/main/vtxfmt.c
@@ -111,6 +111,11 @@ install_vtxfmt( struct _glapi_table *tab, const GLvertexformat *vfmt )
SET_DrawElementsInstancedBaseVertex(tab, vfmt->DrawElementsInstancedBaseVertex);
SET_DrawElementsInstancedBaseVertexBaseInstance(tab, vfmt->DrawElementsInstancedBaseVertexBaseInstance);
SET_DrawTransformFeedback(tab, vfmt->DrawTransformFeedback);
+ SET_DrawTransformFeedbackStream(tab, vfmt->DrawTransformFeedbackStream);
+ SET_DrawTransformFeedbackInstanced(tab,
+ vfmt->DrawTransformFeedbackInstanced);
+ SET_DrawTransformFeedbackStreamInstanced(tab,
+ vfmt->DrawTransformFeedbackStreamInstanced);
/* GL_NV_vertex_program */
SET_VertexAttrib1fNV(tab, vfmt->VertexAttrib1fNV);
diff --git a/mesalib/src/mesa/state_tracker/st_cb_blit.c b/mesalib/src/mesa/state_tracker/st_cb_blit.c
index 27da2c633..1486779fd 100644
--- a/mesalib/src/mesa/state_tracker/st_cb_blit.c
+++ b/mesalib/src/mesa/state_tracker/st_cb_blit.c
@@ -242,7 +242,7 @@ st_BlitFramebuffer(struct gl_context *ctx,
srcX0, srcY0, srcX1, srcY1,
srcAtt->Zoffset + srcAtt->CubeMapFace,
dstSurf, dstX0, dstY0, dstX1, dstY1,
- 0.0, pFilter);
+ 0.0, pFilter, TGSI_WRITEMASK_XYZW, 0);
}
else {
struct st_renderbuffer *srcRb =
@@ -257,7 +257,7 @@ st_BlitFramebuffer(struct gl_context *ctx,
srcX0, srcY0, srcX1, srcY1,
srcSurf->u.tex.first_layer,
dstSurf, dstX0, dstY0, dstX1, dstY1,
- 0.0, pFilter);
+ 0.0, pFilter, TGSI_WRITEMASK_XYZW, 0);
}
}
@@ -281,6 +281,13 @@ st_BlitFramebuffer(struct gl_context *ctx,
struct pipe_surface *dstDepthSurf =
dstDepthRb ? dstDepthRb->surface : NULL;
+ struct st_renderbuffer *srcStencilRb =
+ st_renderbuffer(readFB->Attachment[BUFFER_STENCIL].Renderbuffer);
+ struct st_renderbuffer *dstStencilRb =
+ st_renderbuffer(drawFB->Attachment[BUFFER_STENCIL].Renderbuffer);
+ struct pipe_surface *dstStencilSurf =
+ dstStencilRb ? dstStencilRb->surface : NULL;
+
if ((mask & depthStencil) == depthStencil &&
st_is_depth_stencil_combined(srcDepth, srcStencil) &&
st_is_depth_stencil_combined(dstDepth, dstStencil)) {
@@ -294,7 +301,15 @@ st_BlitFramebuffer(struct gl_context *ctx,
srcX0, srcY0, srcX1, srcY1,
srcDepthRb->surface->u.tex.first_layer,
dstDepthSurf, dstX0, dstY0, dstX1, dstY1,
- 0.0, pFilter);
+ 0.0, pFilter, 0,
+ BLIT_WRITEMASK_Z |
+ (st->has_stencil_export ? BLIT_WRITEMASK_STENCIL
+ : 0));
+
+ if (!st->has_stencil_export) {
+ _mesa_problem(ctx, "st_BlitFramebuffer(STENCIL) "
+ "software fallback not implemented");
+ }
}
else {
/* blitting depth and stencil separately */
@@ -305,12 +320,22 @@ st_BlitFramebuffer(struct gl_context *ctx,
srcX0, srcY0, srcX1, srcY1,
srcDepthRb->surface->u.tex.first_layer,
dstDepthSurf, dstX0, dstY0, dstX1, dstY1,
- 0.0, pFilter);
+ 0.0, pFilter, 0, BLIT_WRITEMASK_Z);
}
if (mask & GL_STENCIL_BUFFER_BIT) {
- /* blit stencil only */
- _mesa_problem(ctx, "st_BlitFramebuffer(STENCIL) not completed");
+ if (st->has_stencil_export) {
+ util_blit_pixels(st->blit, srcStencilRb->texture,
+ srcStencilRb->surface->u.tex.level,
+ srcX0, srcY0, srcX1, srcY1,
+ srcStencilRb->surface->u.tex.first_layer,
+ dstStencilSurf, dstX0, dstY0, dstX1, dstY1,
+ 0.0, pFilter, 0, BLIT_WRITEMASK_STENCIL);
+ }
+ else {
+ _mesa_problem(ctx, "st_BlitFramebuffer(STENCIL) "
+ "software fallback not implemented");
+ }
}
}
}
diff --git a/mesalib/src/mesa/state_tracker/st_cb_drawpixels.c b/mesalib/src/mesa/state_tracker/st_cb_drawpixels.c
index 2bcbada4f..c5f36316b 100644
--- a/mesalib/src/mesa/state_tracker/st_cb_drawpixels.c
+++ b/mesalib/src/mesa/state_tracker/st_cb_drawpixels.c
@@ -403,6 +403,8 @@ internal_format(struct gl_context *ctx, GLenum format, GLenum type)
case GL_UNSIGNED_SHORT_5_6_5:
case GL_UNSIGNED_SHORT_5_6_5_REV:
+ return GL_RGB565;
+
case GL_UNSIGNED_SHORT_5_5_5_1:
case GL_UNSIGNED_SHORT_1_5_5_5_REV:
return GL_RGB5_A1;
@@ -1165,27 +1167,8 @@ st_DrawPixels(struct gl_context *ctx, GLint x, GLint y,
* The stencil is written using the shader stencil export
* functionality. */
if (write_stencil) {
- enum pipe_format stencil_format = PIPE_FORMAT_NONE;
-
- switch (pt->format) {
- case PIPE_FORMAT_Z24_UNORM_S8_UINT:
- case PIPE_FORMAT_X24S8_UINT:
- stencil_format = PIPE_FORMAT_X24S8_UINT;
- break;
- case PIPE_FORMAT_S8_UINT_Z24_UNORM:
- case PIPE_FORMAT_S8X24_UINT:
- stencil_format = PIPE_FORMAT_S8X24_UINT;
- break;
- case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
- case PIPE_FORMAT_X32_S8X24_UINT:
- stencil_format = PIPE_FORMAT_X32_S8X24_UINT;
- break;
- case PIPE_FORMAT_S8_UINT:
- stencil_format = PIPE_FORMAT_S8_UINT;
- break;
- default:
- assert(0);
- }
+ enum pipe_format stencil_format =
+ util_format_stencil_only(pt->format);
sv[1] = st_create_texture_sampler_view_format(st->pipe, pt,
stencil_format);
diff --git a/mesalib/src/mesa/state_tracker/st_cb_texture.c b/mesalib/src/mesa/state_tracker/st_cb_texture.c
index 67c3f9590..a7f57b96f 100644
--- a/mesalib/src/mesa/state_tracker/st_cb_texture.c
+++ b/mesalib/src/mesa/state_tracker/st_cb_texture.c
@@ -944,7 +944,7 @@ st_CopyTexSubImage(struct gl_context *ctx, GLuint dims,
struct pipe_screen *screen = pipe->screen;
enum pipe_format dest_format, src_format;
GLboolean matching_base_formats;
- GLuint format_writemask, sample_count;
+ GLuint color_writemask, zs_writemask, sample_count;
struct pipe_surface *dest_surface = NULL;
GLboolean do_flip = (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP);
struct pipe_surface surf_tmpl;
@@ -1025,15 +1025,17 @@ st_CopyTexSubImage(struct gl_context *ctx, GLuint dims,
}
if (texBaseFormat == GL_DEPTH_COMPONENT) {
- format_writemask = TGSI_WRITEMASK_XYZW;
+ color_writemask = 0;
+ zs_writemask = BLIT_WRITEMASK_Z;
dst_usage = PIPE_BIND_DEPTH_STENCIL;
}
else {
- format_writemask = compatible_src_dst_formats(ctx, &strb->Base, texImage);
+ color_writemask = compatible_src_dst_formats(ctx, &strb->Base, texImage);
+ zs_writemask = 0;
dst_usage = PIPE_BIND_RENDER_TARGET;
}
- if (!format_writemask ||
+ if ((!color_writemask && !zs_writemask) ||
!screen->is_format_supported(screen, src_format,
PIPE_TEXTURE_2D, sample_count,
PIPE_BIND_SAMPLER_VIEW) ||
@@ -1066,17 +1068,17 @@ st_CopyTexSubImage(struct gl_context *ctx, GLuint dims,
dest_surface = pipe->create_surface(pipe, stImage->pt,
&surf_tmpl);
- util_blit_pixels_writemask(st->blit,
- strb->texture,
- strb->surface->u.tex.level,
- srcX, srcY0,
- srcX + width, srcY1,
- strb->surface->u.tex.first_layer,
- dest_surface,
- destX, destY,
- destX + width, destY + height,
- 0.0, PIPE_TEX_MIPFILTER_NEAREST,
- format_writemask);
+ util_blit_pixels(st->blit,
+ strb->texture,
+ strb->surface->u.tex.level,
+ srcX, srcY0,
+ srcX + width, srcY1,
+ strb->surface->u.tex.first_layer,
+ dest_surface,
+ destX, destY,
+ destX + width, destY + height,
+ 0.0, PIPE_TEX_MIPFILTER_NEAREST,
+ color_writemask, zs_writemask);
pipe_surface_reference(&dest_surface, NULL);
/* Restore conditional rendering state. */
diff --git a/mesalib/src/mesa/state_tracker/st_context.c b/mesalib/src/mesa/state_tracker/st_context.c
index 132dcc02f..117ea90f8 100644
--- a/mesalib/src/mesa/state_tracker/st_context.c
+++ b/mesalib/src/mesa/state_tracker/st_context.c
@@ -187,6 +187,8 @@ st_create_context_priv( struct gl_context *ctx, struct pipe_context *pipe )
st->pixel_xfer.cache = _mesa_new_program_cache();
st->force_msaa = st_get_msaa();
+ st->has_stencil_export =
+ screen->get_param(screen, PIPE_CAP_SHADER_STENCIL_EXPORT);
/* GL limits and extensions */
st_init_limits(st);
diff --git a/mesalib/src/mesa/state_tracker/st_context.h b/mesalib/src/mesa/state_tracker/st_context.h
index 734b4d9c1..a3f44b3ab 100644
--- a/mesalib/src/mesa/state_tracker/st_context.h
+++ b/mesalib/src/mesa/state_tracker/st_context.h
@@ -81,7 +81,7 @@ struct st_context
struct draw_stage *rastpos_stage; /**< For glRasterPos */
GLboolean clamp_frag_color_in_shader;
GLboolean clamp_vert_color_in_shader;
-
+ boolean has_stencil_export; /**< can do shader stencil export? */
/* On old libGL's for linux we need to invalidate the drawables
* on glViewpport calls, this is set via a option.
diff --git a/mesalib/src/mesa/state_tracker/st_extensions.c b/mesalib/src/mesa/state_tracker/st_extensions.c
index 5b333ad2c..5099acdb5 100644
--- a/mesalib/src/mesa/state_tracker/st_extensions.c
+++ b/mesalib/src/mesa/state_tracker/st_extensions.c
@@ -355,6 +355,7 @@ void st_init_extensions(struct st_context *st)
{ o(ARB_shadow), PIPE_CAP_TEXTURE_SHADOW_MAP },
{ o(ARB_texture_non_power_of_two), PIPE_CAP_NPOT_TEXTURES },
{ o(ARB_transform_feedback2), PIPE_CAP_STREAM_OUTPUT_PAUSE_RESUME },
+ { o(ARB_transform_feedback3), PIPE_CAP_STREAM_OUTPUT_PAUSE_RESUME },
{ o(EXT_blend_equation_separate), PIPE_CAP_BLEND_EQUATION_SEPARATE },
{ o(EXT_draw_buffers2), PIPE_CAP_INDEP_BLEND_ENABLE },
@@ -641,4 +642,9 @@ void st_init_extensions(struct st_context *st)
screen->get_param(screen, PIPE_CAP_QUERY_TIMESTAMP)) {
ctx->Extensions.ARB_timer_query = GL_TRUE;
}
+
+ if (ctx->Extensions.ARB_transform_feedback2 &&
+ ctx->Extensions.ARB_draw_instanced) {
+ ctx->Extensions.ARB_transform_feedback_instanced = GL_TRUE;
+ }
}
diff --git a/mesalib/src/mesa/state_tracker/st_format.c b/mesalib/src/mesa/state_tracker/st_format.c
index 4265d14b4..57d34411f 100644
--- a/mesalib/src/mesa/state_tracker/st_format.c
+++ b/mesalib/src/mesa/state_tracker/st_format.c
@@ -793,6 +793,10 @@ static const struct format_mapping format_map[] = {
{ PIPE_FORMAT_B5G6R5_UNORM, PIPE_FORMAT_B5G5R5A1_UNORM,
DEFAULT_RGBA_FORMATS }
},
+ {
+ { GL_RGB565 },
+ { PIPE_FORMAT_B5G6R5_UNORM, DEFAULT_RGBA_FORMATS }
+ },
/* basic Alpha formats */
{
diff --git a/mesalib/src/mesa/vbo/vbo_exec_array.c b/mesalib/src/mesa/vbo/vbo_exec_array.c
index d2854dd6c..a923aa1fa 100644
--- a/mesalib/src/mesa/vbo/vbo_exec_array.c
+++ b/mesalib/src/mesa/vbo/vbo_exec_array.c
@@ -1286,12 +1286,17 @@ vbo_exec_MultiDrawElementsBaseVertex(GLenum mode,
static void
vbo_draw_transform_feedback(struct gl_context *ctx, GLenum mode,
struct gl_transform_feedback_object *obj,
- GLuint numInstances)
+ GLuint stream, GLuint numInstances)
{
struct vbo_context *vbo = vbo_context(ctx);
struct vbo_exec_context *exec = &vbo->exec;
struct _mesa_prim prim[2];
+ if (!_mesa_validate_DrawTransformFeedback(ctx, mode, obj, stream,
+ numInstances)) {
+ return;
+ }
+
vbo_bind_arrays(ctx);
/* init most fields to zero */
@@ -1334,11 +1339,52 @@ vbo_exec_DrawTransformFeedback(GLenum mode, GLuint name)
_mesa_debug(ctx, "glDrawTransformFeedback(%s, %d)\n",
_mesa_lookup_enum_by_nr(mode), name);
- if (!_mesa_validate_DrawTransformFeedback(ctx, mode, obj)) {
- return;
- }
+ vbo_draw_transform_feedback(ctx, mode, obj, 0, 1);
+}
+
+static void GLAPIENTRY
+vbo_exec_DrawTransformFeedbackStream(GLenum mode, GLuint name, GLuint stream)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_transform_feedback_object *obj =
+ _mesa_lookup_transform_feedback_object(ctx, name);
+
+ if (MESA_VERBOSE & VERBOSE_DRAW)
+ _mesa_debug(ctx, "glDrawTransformFeedbackStream(%s, %u, %u)\n",
+ _mesa_lookup_enum_by_nr(mode), name, stream);
+
+ vbo_draw_transform_feedback(ctx, mode, obj, stream, 1);
+}
+
+static void GLAPIENTRY
+vbo_exec_DrawTransformFeedbackInstanced(GLenum mode, GLuint name,
+ GLsizei primcount)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_transform_feedback_object *obj =
+ _mesa_lookup_transform_feedback_object(ctx, name);
+
+ if (MESA_VERBOSE & VERBOSE_DRAW)
+ _mesa_debug(ctx, "glDrawTransformFeedbackInstanced(%s, %d)\n",
+ _mesa_lookup_enum_by_nr(mode), name);
+
+ vbo_draw_transform_feedback(ctx, mode, obj, 0, primcount);
+}
+
+static void GLAPIENTRY
+vbo_exec_DrawTransformFeedbackStreamInstanced(GLenum mode, GLuint name,
+ GLuint stream, GLsizei primcount)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_transform_feedback_object *obj =
+ _mesa_lookup_transform_feedback_object(ctx, name);
+
+ if (MESA_VERBOSE & VERBOSE_DRAW)
+ _mesa_debug(ctx, "glDrawTransformFeedbackStreamInstanced"
+ "(%s, %u, %u, %i)\n",
+ _mesa_lookup_enum_by_nr(mode), name, stream, primcount);
- vbo_draw_transform_feedback(ctx, mode, obj, 1);
+ vbo_draw_transform_feedback(ctx, mode, obj, stream, primcount);
}
#endif
@@ -1365,6 +1411,12 @@ vbo_exec_array_init( struct vbo_exec_context *exec )
exec->vtxfmt.DrawElementsInstancedBaseVertexBaseInstance = vbo_exec_DrawElementsInstancedBaseVertexBaseInstance;
#if FEATURE_EXT_transform_feedback
exec->vtxfmt.DrawTransformFeedback = vbo_exec_DrawTransformFeedback;
+ exec->vtxfmt.DrawTransformFeedbackStream =
+ vbo_exec_DrawTransformFeedbackStream;
+ exec->vtxfmt.DrawTransformFeedbackInstanced =
+ vbo_exec_DrawTransformFeedbackInstanced;
+ exec->vtxfmt.DrawTransformFeedbackStreamInstanced =
+ vbo_exec_DrawTransformFeedbackStreamInstanced;
#endif
}
diff --git a/mesalib/src/mesa/vbo/vbo_save_api.c b/mesalib/src/mesa/vbo/vbo_save_api.c
index d27525812..a02a13db5 100644
--- a/mesalib/src/mesa/vbo/vbo_save_api.c
+++ b/mesalib/src/mesa/vbo/vbo_save_api.c
@@ -1068,6 +1068,45 @@ _save_DrawTransformFeedback(GLenum mode, GLuint name)
static void GLAPIENTRY
+_save_DrawTransformFeedbackStream(GLenum mode, GLuint name, GLuint stream)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ (void) mode;
+ (void) name;
+ (void) stream;
+ _mesa_compile_error(ctx, GL_INVALID_OPERATION,
+ "glDrawTransformFeedbackStream");
+}
+
+
+static void GLAPIENTRY
+_save_DrawTransformFeedbackInstanced(GLenum mode, GLuint name,
+ GLsizei primcount)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ (void) mode;
+ (void) name;
+ (void) primcount;
+ _mesa_compile_error(ctx, GL_INVALID_OPERATION,
+ "glDrawTransformFeedbackInstanced");
+}
+
+
+static void GLAPIENTRY
+_save_DrawTransformFeedbackStreamInstanced(GLenum mode, GLuint name,
+ GLuint stream, GLsizei primcount)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ (void) mode;
+ (void) name;
+ (void) stream;
+ (void) primcount;
+ _mesa_compile_error(ctx, GL_INVALID_OPERATION,
+ "glDrawTransformFeedbackStreamInstanced");
+}
+
+
+static void GLAPIENTRY
_save_Rectf(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2)
{
GET_CURRENT_CONTEXT(ctx);
@@ -1416,9 +1455,13 @@ _save_vtxfmt_init(struct gl_context *ctx)
vfmt->DrawRangeElements = _save_DrawRangeElements;
vfmt->DrawElementsBaseVertex = _save_DrawElementsBaseVertex;
vfmt->DrawRangeElementsBaseVertex = _save_DrawRangeElementsBaseVertex;
- vfmt->DrawTransformFeedback = _save_DrawTransformFeedback;
vfmt->MultiDrawElementsEXT = _save_MultiDrawElements;
vfmt->MultiDrawElementsBaseVertex = _save_MultiDrawElementsBaseVertex;
+ vfmt->DrawTransformFeedback = _save_DrawTransformFeedback;
+ vfmt->DrawTransformFeedbackStream = _save_DrawTransformFeedbackStream;
+ vfmt->DrawTransformFeedbackInstanced = _save_DrawTransformFeedbackInstanced;
+ vfmt->DrawTransformFeedbackStreamInstanced =
+ _save_DrawTransformFeedbackStreamInstanced;
}
diff --git a/xorg-server/glx/glxdri2.c b/xorg-server/glx/glxdri2.c
index 909de706a..bce1bfa4b 100644
--- a/xorg-server/glx/glxdri2.c
+++ b/xorg-server/glx/glxdri2.c
@@ -106,6 +106,7 @@ struct __GLXDRIdrawable {
int height;
__DRIbuffer buffers[MAX_DRAWABLE_BUFFERS];
int count;
+ XID dri2_id;
};
static void
@@ -114,6 +115,8 @@ __glXDRIdrawableDestroy(__GLXdrawable * drawable)
__GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable;
const __DRIcoreExtension *core = private->screen->core;
+ FreeResource(private->dri2_id, FALSE);
+
(*core->destroyDrawable) (private->driDrawable);
__glXDrawableRelease(drawable);
@@ -390,7 +393,8 @@ __glXDRIscreenDestroy(__GLXscreen * baseScreen)
}
static Bool
-dri2_convert_glx_attribs(unsigned num_attribs, const uint32_t *attribs,
+dri2_convert_glx_attribs(__GLXDRIscreen *screen, unsigned num_attribs,
+ const uint32_t *attribs,
unsigned *major_ver, unsigned *minor_ver,
uint32_t *flags, int *api, int *reset, unsigned *error)
{
@@ -482,8 +486,8 @@ dri2_convert_glx_attribs(unsigned num_attribs, const uint32_t *attribs,
* don't support OpenGL 3.2 may fail the request for a core profile.
*/
if (*api == __DRI_API_OPENGL_CORE
- && (*major_ver < 3 || (*major_ver < 3 && *minor_ver < 2))) {
- *api == __DRI_API_OPENGL;
+ && (*major_ver < 3 || (*major_ver == 3 && *minor_ver < 2))) {
+ *api = __DRI_API_OPENGL;
}
*error = Success;
@@ -513,11 +517,11 @@ create_driver_context(__GLXDRIcontext * context,
int api;
if (num_attribs != 0) {
- if (!dri2_convert_glx_attribs(num_attribs, attribs,
+ if (!dri2_convert_glx_attribs(screen, num_attribs, attribs,
&major_ver, &minor_ver,
&flags, &api, &reset,
(unsigned *) error))
- return NULL;
+ return;
ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_MAJOR_VERSION;
ctx_attribs[num_ctx_attribs++] = major_ver;
@@ -534,9 +538,9 @@ create_driver_context(__GLXDRIcontext * context,
}
#ifdef __DRI2_ROBUSTNESS
- if (reset != __DRI_CTX_NO_RESET_NOTIFICATION) {
+ if (reset != __DRI_CTX_RESET_NO_NOTIFICATION) {
ctx_attribs[num_ctx_attribs++] =
- __DRI_CTX_ATTRIB_RESET_NOTIFICATION;
+ __DRI_CTX_ATTRIB_RESET_STRATEGY;
ctx_attribs[num_ctx_attribs++] = reset;
}
#endif
@@ -670,8 +674,9 @@ __glXDRIscreenCreateDrawable(ClientPtr client,
private->base.waitGL = __glXDRIdrawableWaitGL;
private->base.waitX = __glXDRIdrawableWaitX;
- if (DRI2CreateDrawable(client, pDraw, drawId,
- __glXDRIinvalidateBuffers, private)) {
+ if (DRI2CreateDrawable2(client, pDraw, drawId,
+ __glXDRIinvalidateBuffers, private,
+ &private->dri2_id)) {
free(private);
return NULL;
}
diff --git a/xorg-server/glx/glxext.c b/xorg-server/glx/glxext.c
index a1f9d42e9..70f0df892 100644
--- a/xorg-server/glx/glxext.c
+++ b/xorg-server/glx/glxext.c
@@ -339,9 +339,6 @@ GlxExtensionInit(void)
if (!__glXContextRes || !__glXDrawableRes)
return;
- if (serverGeneration == 1)
- GlxPushProvider(&__glXDRISWRastProvider);
-
if (!dixRegisterPrivateKey
(&glxClientPrivateKeyRec, PRIVATE_CLIENT, sizeof(__GLXclientState)))
return;
diff --git a/xorg-server/glx/glxserver.h b/xorg-server/glx/glxserver.h
index d9b106b82..1021aec80 100644
--- a/xorg-server/glx/glxserver.h
+++ b/xorg-server/glx/glxserver.h
@@ -97,7 +97,7 @@ struct __GLXprovider {
const char *name;
__GLXprovider *next;
};
-__GLXprovider __glXDRISWRastProvider;
+extern __GLXprovider __glXDRISWRastProvider;
void GlxPushProvider(__GLXprovider * provider);
diff --git a/xorg-server/hw/xfree86/common/xf86AutoConfig.c b/xorg-server/hw/xfree86/common/xf86AutoConfig.c
index 271ce86b6..95d58fe43 100644
--- a/xorg-server/hw/xfree86/common/xf86AutoConfig.c
+++ b/xorg-server/hw/xfree86/common/xf86AutoConfig.c
@@ -39,6 +39,7 @@
#include "xf86Config.h"
#include "xf86Priv.h"
#include "xf86_OSlib.h"
+#include "xf86platformBus.h"
#include "xf86pciBus.h"
#ifdef __sparc__
#include "xf86sbusBus.h"
diff --git a/xorg-server/hw/xfree86/dri2/dri2.c b/xorg-server/hw/xfree86/dri2/dri2.c
index 2ea0c331e..63feed51a 100644
--- a/xorg-server/hw/xfree86/dri2/dri2.c
+++ b/xorg-server/hw/xfree86/dri2/dri2.c
@@ -333,8 +333,9 @@ DRI2AddDrawableRef(DRI2DrawablePtr pPriv, XID id, XID dri2_id,
}
int
-DRI2CreateDrawable(ClientPtr client, DrawablePtr pDraw, XID id,
- DRI2InvalidateProcPtr invalidate, void *priv)
+DRI2CreateDrawable2(ClientPtr client, DrawablePtr pDraw, XID id,
+ DRI2InvalidateProcPtr invalidate, void *priv,
+ XID *dri2_id_out)
{
DRI2DrawablePtr pPriv;
DRI2ClientPtr dri2_client = dri2ClientPrivate(client);
@@ -354,9 +355,19 @@ DRI2CreateDrawable(ClientPtr client, DrawablePtr pDraw, XID id,
if (rc != Success)
return rc;
+ if (dri2_id_out)
+ *dri2_id_out = dri2_id;
+
return Success;
}
+int
+DRI2CreateDrawable(ClientPtr client, DrawablePtr pDraw, XID id,
+ DRI2InvalidateProcPtr invalidate, void *priv)
+{
+ return DRI2CreateDrawable2(client, pDraw, id, invalidate, priv, NULL);
+}
+
static int
DRI2DrawableGone(pointer p, XID id)
{
diff --git a/xorg-server/hw/xfree86/dri2/dri2.h b/xorg-server/hw/xfree86/dri2/dri2.h
index da7825e09..1e7afddbd 100644
--- a/xorg-server/hw/xfree86/dri2/dri2.h
+++ b/xorg-server/hw/xfree86/dri2/dri2.h
@@ -274,6 +274,13 @@ extern _X_EXPORT int DRI2CreateDrawable(ClientPtr client,
DRI2InvalidateProcPtr invalidate,
void *priv);
+extern _X_EXPORT int DRI2CreateDrawable2(ClientPtr client,
+ DrawablePtr pDraw,
+ XID id,
+ DRI2InvalidateProcPtr invalidate,
+ void *priv,
+ XID *dri2_id_out);
+
extern _X_EXPORT DRI2BufferPtr *DRI2GetBuffers(DrawablePtr pDraw,
int *width,
int *height,
diff --git a/xorg-server/hw/xfree86/sdksyms.sh b/xorg-server/hw/xfree86/sdksyms.sh
index c0398da18..07372ad1c 100644
--- a/xorg-server/hw/xfree86/sdksyms.sh
+++ b/xorg-server/hw/xfree86/sdksyms.sh
@@ -46,8 +46,10 @@ cat > sdksyms.c << EOF
#include "misyncstr.h"
/* Xext/Makefile.am -- half is module, half is builtin */
+#ifdef XV
#include "xvdix.h"
#include "xvmcext.h"
+#endif
#include "geext.h"
#include "geint.h"
#ifdef MITSHM
diff --git a/xorg-server/hw/xquartz/pseudoramiX.c b/xorg-server/hw/xquartz/pseudoramiX.c
index 3e1050047..c650dd723 100644
--- a/xorg-server/hw/xquartz/pseudoramiX.c
+++ b/xorg-server/hw/xquartz/pseudoramiX.c
@@ -126,7 +126,7 @@ PseudoramiXAddScreen(int x, int y, int w, int h)
// Initialize PseudoramiX.
// Copied from PanoramiXExtensionInit
void
-PseudoramiXExtensionInit(int argc, char *argv[])
+PseudoramiXExtensionInit(void)
{
Bool success = FALSE;
ExtensionEntry *extEntry;
@@ -257,7 +257,7 @@ ProcPseudoramiXGetScreenSize(ClientPtr client)
REQUEST(xPanoramiXGetScreenSizeReq);
WindowPtr pWin;
xPanoramiXGetScreenSizeReply rep;
- register int n, rc;
+ register int rc;
TRACE();
diff --git a/xorg-server/hw/xquartz/xpr/dri.h b/xorg-server/hw/xquartz/xpr/dri.h
index 7d1c4f212..8717a5186 100644
--- a/xorg-server/hw/xquartz/xpr/dri.h
+++ b/xorg-server/hw/xquartz/xpr/dri.h
@@ -72,6 +72,9 @@ DRIFinishScreenInit(ScreenPtr pScreen);
extern void
DRICloseScreen(ScreenPtr pScreen);
+extern Bool
+DRIExtensionInit(void);
+
extern void
DRIReset(void);
diff --git a/xorg-server/hw/xwin/InitOutput.c b/xorg-server/hw/xwin/InitOutput.c
index 4d0df110f..538b2e101 100644
--- a/xorg-server/hw/xwin/InitOutput.c
+++ b/xorg-server/hw/xwin/InitOutput.c
@@ -147,15 +147,30 @@ winClipboardShutdown(void)
}
#endif
-void
-ddxPushProviders(void)
+static const ExtensionModule xwinExtensions[] = {
+#ifdef GLXEXT
+ { GlxExtensionInit, "GLX", &noGlxExtension },
+#endif
+};
+
+/*
+ * XwinExtensionInit
+ * Initialises Xwin-specific extensions.
+ */
+static
+void XwinExtensionInit(void)
{
+ int i;
+
#ifdef XWIN_GLX_WINDOWS
- if (g_fNativeGl) {
+ if ((g_fNativeGl) && (serverGeneration == 1)) {
/* install the native GL provider */
glxWinPushNativeProvider();
}
#endif
+
+ for (i = 0; i < ARRAY_SIZE(xwinExtensions); i++)
+ LoadExtension(&xwinExtensions[i], TRUE);
}
#if defined(DDXBEFORERESET)
@@ -885,6 +900,8 @@ InitOutput(ScreenInfo * screenInfo, int argc, char *argv[])
{
int i;
+ XwinExtensionInit();
+
/* Log the command line */
winLogCommandLine(argc, argv);
diff --git a/xorg-server/test/xtest.c b/xorg-server/test/xtest.c
index 402d9ceba..e5e5241b7 100644
--- a/xorg-server/test/xtest.c
+++ b/xorg-server/test/xtest.c
@@ -30,6 +30,7 @@
#include "inputstr.h"
#include "scrnintstr.h"
#include "exevents.h"
+#include "extinit.h"
#include "xkbsrv.h"
#include "xserver-properties.h"
#include "syncsrv.h"