diff options
Diffstat (limited to 'mesalib/src')
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 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; } |