aboutsummaryrefslogtreecommitdiff
path: root/mesalib/src
diff options
context:
space:
mode:
Diffstat (limited to 'mesalib/src')
-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
39 files changed, 1222 insertions, 286 deletions
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 01460b49b..8bdc47908 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 805c031ae..a578aa594 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;
}