diff options
82 files changed, 2154 insertions, 1377 deletions
diff --git a/libXft/man/Xft.man b/libXft/man/Xft.man index 4ed2742d2..62439281c 100644 --- a/libXft/man/Xft.man +++ b/libXft/man/Xft.man @@ -750,7 +750,7 @@ functions) and frees the memory that was allocated for it. .nf \fBvoid\fR \fBXftDrawString8 (XftDraw *\fId\fB,\fR -\fB XRenderColor *\fIcolor\fB,\fR +\fB XftColor *\fIcolor\fB,\fR \fB XftFont *\fIfont\fB,\fR \fB int \fIx\fB,\fR \fB int \fIy\fB,\fR @@ -770,14 +770,11 @@ in .I color at position .IR x , " y" . -The -.B XRenderColor -data type is defined by the X Rendering Extension library. .PP .nf \fBvoid\fR \fBXftDrawRect (XftDraw *\fId\fB,\fR -\fB XRenderColor *\fIcolor\fB,\fR +\fB XftColor *\fIcolor\fB,\fR \fB int \fIx\fB,\fR \fB int \fIy\fB,\fR \fB unsigned int \fIwidth\fB,\fR diff --git a/mesalib/configure.ac b/mesalib/configure.ac index a133902c6..1294740a4 100644 --- a/mesalib/configure.ac +++ b/mesalib/configure.ac @@ -341,18 +341,18 @@ AC_ARG_ENABLE([debug], if test "x$enable_debug" = xyes; then DEFINES_FOR_BUILD="$DEFINES_FOR_BUILD -DDEBUG" if test "x$GCC_FOR_BUILD" = xyes; then - CFLAGS_FOR_BUILD="$CFLAGS_FOR_BUILD -g" + CFLAGS_FOR_BUILD="$CFLAGS_FOR_BUILD -g -O0" fi if test "x$GXX_FOR_BUILD" = xyes; then - CXXFLAGS_FOR_BUILD="$CXXFLAGS_FOR_BUILD -g" + CXXFLAGS_FOR_BUILD="$CXXFLAGS_FOR_BUILD -g -O0" fi DEFINES="$DEFINES -DDEBUG" if test "x$GCC" = xyes; then - CFLAGS="$CFLAGS -g" + CFLAGS="$CFLAGS -g -O0" fi if test "x$GXX" = xyes; then - CXXFLAGS="$CXXFLAGS -g" + CXXFLAGS="$CXXFLAGS -g -O0" fi fi diff --git a/mesalib/docs/GL3.txt b/mesalib/docs/GL3.txt index ba1b0d1a1..34cce729b 100644 --- a/mesalib/docs/GL3.txt +++ b/mesalib/docs/GL3.txt @@ -95,8 +95,8 @@ GL_ARB_gpu_shader_fp64 not started GL_ARB_sample_shading not started GL_ARB_shader_subroutine not started GL_ARB_tessellation_shader not started -GL_ARB_texture_buffer_object_rgb32 not started -GL_ARB_texture_cube_map_array DONE (softpipe) +GL_ARB_texture_buffer_object_rgb32 DONE (softpipe) +GL_ARB_texture_cube_map_array DONE (i965, softpipe) GL_ARB_texture_gather not started GL_ARB_transform_feedback2 DONE GL_ARB_transform_feedback3 DONE diff --git a/mesalib/docs/relnotes-9.1.html b/mesalib/docs/relnotes-9.1.html index 3a8c77bfc..ffca27539 100644 --- a/mesalib/docs/relnotes-9.1.html +++ b/mesalib/docs/relnotes-9.1.html @@ -46,6 +46,7 @@ Note: some of the new features are only available with certain drivers. <ul> <li>GL_ARB_map_buffer_alignment</li> <li>GL_ARB_texture_cube_map_array</li> +<li>GL_ARB_texture_buffer_object_rgb32</li> </ul> diff --git a/mesalib/m4/ax_prog_cc_for_build.m4 b/mesalib/m4/ax_prog_cc_for_build.m4 index 08095a83d..6369809aa 100644 --- a/mesalib/m4/ax_prog_cc_for_build.m4 +++ b/mesalib/m4/ax_prog_cc_for_build.m4 @@ -40,30 +40,9 @@ AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_PROG_CPP])dnl AC_REQUIRE([AC_EXEEXT])dnl AC_REQUIRE([AC_CANONICAL_SYSTEM])dnl -dnl -pushdef([AC_TRY_COMPILER], [ -cat > conftest.$ac_ext << EOF -#line __oline__ "configure" -#include "confdefs.h" -[$1] -EOF -# If we can't run a trivial program, we are probably using a cross -compiler. -# Fail miserably. -if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} && (./conftest; -exit) 2>/dev/null; then - [$2]=yes -else - echo "configure: failed program was:" >&AC_FD_CC - cat conftest.$ac_ext >&AC_FD_CC - [$2]=no -fi -[$3]=no -rm -fr conftest*])dnl dnl Use the standard macros, but make them use other variable names dnl -pushdef([cross_compiling], [#])dnl pushdef([ac_cv_prog_CPP], ac_cv_build_prog_CPP)dnl pushdef([ac_cv_prog_gcc], ac_cv_build_prog_gcc)dnl pushdef([ac_cv_prog_cc_works], ac_cv_build_prog_cc_works)dnl @@ -91,16 +70,21 @@ pushdef([ac_cv_host_os], ac_cv_build_os)dnl pushdef([ac_cpp], ac_build_cpp)dnl pushdef([ac_compile], ac_build_compile)dnl pushdef([ac_link], ac_build_link)dnl -pushdef([ac_tool_prefix], [#])dnl + +save_cross_compiling=$cross_compiling +save_ac_tool_prefix=$ac_tool_prefix +cross_compiling=no +ac_tool_prefix= AC_PROG_CC AC_PROG_CPP AC_EXEEXT +ac_tool_prefix=$save_ac_tool_prefix +cross_compiling=$save_cross_compiling + dnl Restore the old definitions dnl -popdef([AC_TRY_COMPILER])dnl -popdef([ac_tool_prefix])dnl popdef([ac_link])dnl popdef([ac_compile])dnl popdef([ac_cpp])dnl @@ -114,6 +98,7 @@ popdef([host_vendor])dnl popdef([host_cpu])dnl popdef([host_alias])dnl popdef([host])dnl +popdef([LDFLAGS])dnl popdef([CPPFLAGS])dnl popdef([CFLAGS])dnl popdef([CPP])dnl @@ -123,10 +108,10 @@ popdef([ac_exeext])dnl popdef([ac_cv_objext])dnl popdef([ac_cv_exeext])dnl popdef([ac_cv_prog_cc_g])dnl -popdef([ac_cv_prog_cc_works])dnl popdef([ac_cv_prog_cc_cross])dnl +popdef([ac_cv_prog_cc_works])dnl popdef([ac_cv_prog_gcc])dnl -popdef([cross_compiling])dnl +popdef([ac_cv_prog_CPP])dnl dnl Finally, set Makefile variables dnl diff --git a/mesalib/m4/ax_prog_cxx_for_build.m4 b/mesalib/m4/ax_prog_cxx_for_build.m4 index 4a099f9fb..ecf8db94e 100644 --- a/mesalib/m4/ax_prog_cxx_for_build.m4 +++ b/mesalib/m4/ax_prog_cxx_for_build.m4 @@ -38,30 +38,9 @@ AC_REQUIRE([AX_PROG_CC_FOR_BUILD])dnl AC_REQUIRE([AC_PROG_CXX])dnl AC_REQUIRE([AC_PROG_CXXCPP])dnl AC_REQUIRE([AC_CANONICAL_SYSTEM])dnl -dnl -pushdef([AC_TRY_COMPILER], [ -cat > conftest.$ac_ext << EOF -#line __oline__ "configure" -#include "confdefs.h" -[$1] -EOF -# If we can't run a trivial program, we are probably using a cross -compiler. -# Fail miserably. -if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} && (./conftest; -exit) 2>/dev/null; then - [$2]=yes -else - echo "configure: failed program was:" >&AC_FD_CC - cat conftest.$ac_ext >&AC_FD_CC - [$2]=no -fi -[$3]=no -rm -fr conftest*])dnl dnl Use the standard macros, but make them use other variable names dnl -pushdef([cross_compiling], [#])dnl pushdef([ac_cv_prog_CXXCPP], ac_cv_build_prog_CXXCPP)dnl pushdef([ac_cv_prog_gxx], ac_cv_build_prog_gxx)dnl pushdef([ac_cv_prog_cxx_works], ac_cv_build_prog_cxx_works)dnl @@ -70,6 +49,7 @@ pushdef([ac_cv_prog_cxx_g], ac_cv_build_prog_cxx_g)dnl pushdef([CXX], CXX_FOR_BUILD)dnl pushdef([CXXCPP], CXXCPP_FOR_BUILD)dnl pushdef([CXXFLAGS], CXXFLAGS_FOR_BUILD)dnl +pushdef([CPPFLAGS], CPPFLAGS_FOR_BUILD)dnl pushdef([CXXCPPFLAGS], CXXCPPFLAGS_FOR_BUILD)dnl pushdef([host], build)dnl pushdef([host_alias], build_alias)dnl @@ -84,15 +64,20 @@ pushdef([ac_cv_host_os], ac_cv_build_os)dnl pushdef([ac_cxxcpp], ac_build_cxxcpp)dnl pushdef([ac_compile], ac_build_compile)dnl pushdef([ac_link], ac_build_link)dnl -pushdef([ac_tool_prefix], [#])dnl + +save_cross_compiling=$cross_compiling +save_ac_tool_prefix=$ac_tool_prefix +cross_compiling=no +ac_tool_prefix= AC_PROG_CXX AC_PROG_CXXCPP +ac_tool_prefix=$save_ac_tool_prefix +cross_compiling=$save_cross_compiling + dnl Restore the old definitions dnl -popdef([AC_TRY_COMPILER])dnl -popdef([ac_tool_prefix])dnl popdef([ac_link])dnl popdef([ac_compile])dnl popdef([ac_cxxcpp])dnl @@ -107,14 +92,15 @@ popdef([host_cpu])dnl popdef([host_alias])dnl popdef([host])dnl popdef([CXXCPPFLAGS])dnl +popdef([CPPFLAGS])dnl popdef([CXXFLAGS])dnl popdef([CXXCPP])dnl popdef([CXX])dnl popdef([ac_cv_prog_cxx_g])dnl -popdef([ac_cv_prog_cxx_works])dnl popdef([ac_cv_prog_cxx_cross])dnl +popdef([ac_cv_prog_cxx_works])dnl popdef([ac_cv_prog_gxx])dnl -popdef([cross_compiling])dnl +popdef([ac_cv_prog_CXXCPP])dnl dnl Finally, set Makefile variables dnl diff --git a/mesalib/src/gallium/auxiliary/Makefile.sources b/mesalib/src/gallium/auxiliary/Makefile.sources index 724178535..e54e9201c 100644 --- a/mesalib/src/gallium/auxiliary/Makefile.sources +++ b/mesalib/src/gallium/auxiliary/Makefile.sources @@ -130,6 +130,7 @@ C_SOURCES := \ util/u_slab.c \ util/u_snprintf.c \ util/u_staging.c \ + util/u_suballoc.c \ util/u_surface.c \ util/u_surfaces.c \ util/u_texture.c \ diff --git a/mesalib/src/gallium/auxiliary/util/u_blit.c b/mesalib/src/gallium/auxiliary/util/u_blit.c index ab1549e2d..9fe15b810 100644 --- a/mesalib/src/gallium/auxiliary/util/u_blit.c +++ b/mesalib/src/gallium/auxiliary/util/u_blit.c @@ -666,6 +666,7 @@ util_blit_pixels(struct blit_state *ctx, cso_save_geometry_shader(ctx->cso); cso_save_vertex_elements(ctx->cso); cso_save_aux_vertex_buffer_slot(ctx->cso); + cso_save_render_condition(ctx->cso); /* set misc state we care about */ if (writemask) @@ -677,6 +678,7 @@ util_blit_pixels(struct blit_state *ctx, 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); + cso_set_render_condition(ctx->cso, NULL, 0); /* default sampler state */ ctx->sampler.normalized_coords = normalized; @@ -799,6 +801,7 @@ util_blit_pixels(struct blit_state *ctx, cso_restore_vertex_elements(ctx->cso); cso_restore_aux_vertex_buffer_slot(ctx->cso); cso_restore_stream_outputs(ctx->cso); + cso_restore_render_condition(ctx->cso); pipe_sampler_view_reference(&sampler_view, NULL); if (dst_surface != dst) diff --git a/mesalib/src/gallium/auxiliary/util/u_blitter.c b/mesalib/src/gallium/auxiliary/util/u_blitter.c index e788b6594..7c7e06219 100644 --- a/mesalib/src/gallium/auxiliary/util/u_blitter.c +++ b/mesalib/src/gallium/auxiliary/util/u_blitter.c @@ -1053,29 +1053,6 @@ void util_blitter_custom_clear_depth(struct blitter_context *blitter, 0, PIPE_FORMAT_NONE, &color, depth, 0, NULL, custom_dsa); } -static -boolean is_overlap(int dstx, int dsty, int dstz, - const struct pipe_box *srcbox) -{ - struct pipe_box src = *srcbox; - - if (src.width < 0) { - src.x += src.width; - src.width = -src.width; - } - if (src.height < 0) { - src.y += src.height; - src.height = -src.height; - } - if (src.depth < 0) { - src.z += src.depth; - src.depth = -src.depth; - } - return src.x < dstx+src.width && src.x+src.width > dstx && - src.y < dsty+src.height && src.y+src.height > dsty && - src.z < dstz+src.depth && src.z+src.depth > dstz; -} - void util_blitter_default_dst_texture(struct pipe_surface *dst_templ, struct pipe_resource *dst, unsigned dstlevel, @@ -1083,12 +1060,6 @@ void util_blitter_default_dst_texture(struct pipe_surface *dst_templ, const struct pipe_box *srcbox) { memset(dst_templ, 0, sizeof(*dst_templ)); - dst_templ->format = dst->format; - if (util_format_is_depth_or_stencil(dst->format)) { - dst_templ->usage = PIPE_BIND_DEPTH_STENCIL; - } else { - dst_templ->usage = PIPE_BIND_RENDER_TARGET; - } dst_templ->format = util_format_linear(dst->format); dst_templ->u.tex.level = dstlevel; dst_templ->u.tex.first_layer = dstz; @@ -1267,11 +1238,6 @@ void util_blitter_blit_generic(struct blitter_context *blitter, return; } - /* Sanity checks. */ - if (dst->texture == src->texture && - dst->u.tex.level == src->u.tex.first_level) { - assert(!is_overlap(dstx, dsty, 0, srcbox)); - } /* XXX should handle 3d regions */ assert(srcbox->depth == 1); @@ -1743,7 +1709,6 @@ void util_blitter_custom_resolve_color(struct blitter_context *blitter, surf_tmpl.u.tex.level = dst_level; surf_tmpl.u.tex.first_layer = dst_layer; surf_tmpl.u.tex.last_layer = dst_layer; - surf_tmpl.usage = PIPE_BIND_RENDER_TARGET; dstsurf = pipe->create_surface(pipe, dst, &surf_tmpl); @@ -1822,149 +1787,3 @@ void util_blitter_custom_color(struct blitter_context *blitter, blitter_restore_render_cond(ctx); blitter_unset_running_flag(ctx); } - -/* Return whether this is an RGBA, Z, S, or combined ZS format. - */ -static unsigned get_format_mask(enum pipe_format format) -{ - const struct util_format_description *desc = util_format_description(format); - - assert(desc); - - if (util_format_has_depth(desc)) { - if (util_format_has_stencil(desc)) { - return PIPE_MASK_ZS; - } else { - return PIPE_MASK_Z; - } - } else { - if (util_format_has_stencil(desc)) { - return PIPE_MASK_S; - } else { - return PIPE_MASK_RGBA; - } - } -} - -/* Return if the box is totally inside the resource. - */ -static boolean is_box_inside_resource(const struct pipe_resource *res, - const struct pipe_box *box, - unsigned level) -{ - unsigned width = 1, height = 1, depth = 1; - - switch (res->target) { - case PIPE_BUFFER: - width = res->width0; - height = 1; - depth = 1; - break; - case PIPE_TEXTURE_1D: - width = u_minify(res->width0, level); - height = 1; - depth = 1; - break; - case PIPE_TEXTURE_2D: - case PIPE_TEXTURE_RECT: - width = u_minify(res->width0, level); - height = u_minify(res->height0, level); - depth = 1; - break; - case PIPE_TEXTURE_3D: - width = u_minify(res->width0, level); - height = u_minify(res->height0, level); - depth = u_minify(res->depth0, level); - break; - case PIPE_TEXTURE_CUBE: - width = u_minify(res->width0, level); - height = u_minify(res->height0, level); - depth = 6; - break; - case PIPE_TEXTURE_1D_ARRAY: - width = u_minify(res->width0, level); - height = 1; - depth = res->array_size; - break; - case PIPE_TEXTURE_2D_ARRAY: - width = u_minify(res->width0, level); - height = u_minify(res->height0, level); - depth = res->array_size; - break; - case PIPE_TEXTURE_CUBE_ARRAY: - width = u_minify(res->width0, level); - height = u_minify(res->height0, level); - depth = res->array_size; - assert(res->array_size % 6 == 0); - break; - case PIPE_MAX_TEXTURE_TYPES:; - } - - return box->x >= 0 && - box->x + box->width <= (int) width && - box->y >= 0 && - box->y + box->height <= (int) height && - box->z >= 0 && - box->z + box->depth <= (int) depth; -} - -static unsigned get_sample_count(const struct pipe_resource *res) -{ - return res->nr_samples ? res->nr_samples : 1; -} - -boolean util_try_blit_via_copy_region(struct pipe_context *ctx, - const struct pipe_blit_info *blit) -{ - unsigned mask = get_format_mask(blit->dst.format); - - /* No format conversions. */ - if (blit->src.resource->format != blit->src.format || - blit->dst.resource->format != blit->dst.format || - !util_is_format_compatible( - util_format_description(blit->src.resource->format), - util_format_description(blit->dst.resource->format))) { - return FALSE; - } - - /* No masks, no filtering, no scissor. */ - if ((blit->mask & mask) != mask || - blit->filter != PIPE_TEX_FILTER_NEAREST || - blit->scissor_enable) { - return FALSE; - } - - /* No flipping. */ - if (blit->src.box.width < 0 || - blit->src.box.height < 0 || - blit->src.box.depth < 0) { - return FALSE; - } - - /* No scaling. */ - if (blit->src.box.width != blit->dst.box.width || - blit->src.box.height != blit->dst.box.height || - blit->src.box.depth != blit->dst.box.depth) { - return FALSE; - } - - /* No out-of-bounds access. */ - if (!is_box_inside_resource(blit->src.resource, &blit->src.box, - blit->src.level) || - !is_box_inside_resource(blit->dst.resource, &blit->dst.box, - blit->dst.level)) { - return FALSE; - } - - /* Sample counts must match. */ - if (get_sample_count(blit->src.resource) != - get_sample_count(blit->dst.resource)) { - return FALSE; - } - - ctx->resource_copy_region(ctx, blit->dst.resource, blit->dst.level, - blit->dst.box.x, blit->dst.box.y, blit->dst.box.z, - blit->src.resource, blit->src.level, - &blit->src.box); - return TRUE; -} diff --git a/mesalib/src/gallium/auxiliary/util/u_blitter.h b/mesalib/src/gallium/auxiliary/util/u_blitter.h index 99175409b..0b5e4aa45 100644 --- a/mesalib/src/gallium/auxiliary/util/u_blitter.h +++ b/mesalib/src/gallium/auxiliary/util/u_blitter.h @@ -152,17 +152,6 @@ void util_blitter_draw_rectangle(struct blitter_context *blitter, enum blitter_attrib_type type, const union pipe_color_union *attrib); -/** - * Try to do a blit using resource_copy_region. The function calls - * resource_copy_region if the blit description is compatible with it. - * - * It returns TRUE if the blit was done using resource_copy_region. - * - * It returns FALSE otherwise and the caller must fall back to a more generic - * codepath for the blit operation. (e.g. by using u_blitter) - */ -boolean util_try_blit_via_copy_region(struct pipe_context *ctx, - const struct pipe_blit_info *blit); /* * These states must be saved before any of the following functions are called: diff --git a/mesalib/src/gallium/auxiliary/util/u_debug.c b/mesalib/src/gallium/auxiliary/util/u_debug.c index ee97b7adb..ce472b020 100644 --- a/mesalib/src/gallium/auxiliary/util/u_debug.c +++ b/mesalib/src/gallium/auxiliary/util/u_debug.c @@ -537,8 +537,7 @@ void debug_dump_texture(struct pipe_context *pipe, return; /* XXX for now, just dump image for layer=0, level=0 */ - memset(&surf_tmpl, 0, sizeof(surf_tmpl)); - u_surface_default_template(&surf_tmpl, texture, 0 /* no bind flag - not a surface */); + u_surface_default_template(&surf_tmpl, texture); surface = pipe->create_surface(pipe, texture, &surf_tmpl); if (surface) { debug_dump_surface(pipe, prefix, surface); diff --git a/mesalib/src/gallium/auxiliary/util/u_dump_state.c b/mesalib/src/gallium/auxiliary/util/u_dump_state.c index f5d8b4373..09faffe73 100644 --- a/mesalib/src/gallium/auxiliary/util/u_dump_state.c +++ b/mesalib/src/gallium/auxiliary/util/u_dump_state.c @@ -661,8 +661,6 @@ util_dump_surface(FILE *stream, const struct pipe_surface *state) util_dump_member(stream, uint, state, width); util_dump_member(stream, uint, state, height); - util_dump_member(stream, uint, state, usage); - util_dump_member(stream, ptr, state, texture); util_dump_member(stream, uint, state, u.tex.level); util_dump_member(stream, uint, state, u.tex.first_layer); diff --git a/mesalib/src/gallium/auxiliary/util/u_gen_mipmap.c b/mesalib/src/gallium/auxiliary/util/u_gen_mipmap.c index 48ebdb9fa..e1f18f39c 100644 --- a/mesalib/src/gallium/auxiliary/util/u_gen_mipmap.c +++ b/mesalib/src/gallium/auxiliary/util/u_gen_mipmap.c @@ -1566,6 +1566,7 @@ util_gen_mipmap(struct gen_mipmap_state *ctx, cso_save_viewport(ctx->cso); cso_save_vertex_elements(ctx->cso); cso_save_aux_vertex_buffer_slot(ctx->cso); + cso_save_render_condition(ctx->cso); /* bind our state */ cso_set_blend(ctx->cso, is_depth ? &ctx->blend_keep_color : @@ -1576,6 +1577,7 @@ util_gen_mipmap(struct gen_mipmap_state *ctx, cso_set_sample_mask(ctx->cso, ~0); cso_set_vertex_elements(ctx->cso, 2, ctx->velem); cso_set_stream_outputs(ctx->cso, 0, NULL, 0); + cso_set_render_condition(ctx->cso, NULL, 0); set_fragment_shader(ctx, type, is_depth); set_vertex_shader(ctx); @@ -1615,10 +1617,7 @@ util_gen_mipmap(struct gen_mipmap_state *ctx, } else layer = face; - memset(&surf_templ, 0, sizeof(surf_templ)); - u_surface_default_template(&surf_templ, pt, - is_depth ? PIPE_BIND_DEPTH_STENCIL : - PIPE_BIND_RENDER_TARGET); + u_surface_default_template(&surf_templ, pt); surf_templ.u.tex.level = dstLevel; surf_templ.u.tex.first_layer = layer; surf_templ.u.tex.last_layer = layer; @@ -1699,4 +1698,5 @@ util_gen_mipmap(struct gen_mipmap_state *ctx, cso_restore_vertex_elements(ctx->cso); cso_restore_stream_outputs(ctx->cso); cso_restore_aux_vertex_buffer_slot(ctx->cso); + cso_restore_render_condition(ctx->cso); } diff --git a/mesalib/src/gallium/auxiliary/util/u_inlines.h b/mesalib/src/gallium/auxiliary/util/u_inlines.h index 469f95461..582aacdca 100644 --- a/mesalib/src/gallium/auxiliary/util/u_inlines.h +++ b/mesalib/src/gallium/auxiliary/util/u_inlines.h @@ -188,14 +188,12 @@ pipe_so_target_reference(struct pipe_stream_output_target **ptr, static INLINE void pipe_surface_reset(struct pipe_context *ctx, struct pipe_surface* ps, - struct pipe_resource *pt, unsigned level, unsigned layer, - unsigned flags) + struct pipe_resource *pt, unsigned level, unsigned layer) { pipe_resource_reference(&ps->texture, pt); ps->format = pt->format; ps->width = u_minify(pt->width0, level); ps->height = u_minify(pt->height0, level); - ps->usage = flags; ps->u.tex.level = level; ps->u.tex.first_layer = ps->u.tex.last_layer = layer; ps->context = ctx; @@ -203,12 +201,11 @@ pipe_surface_reset(struct pipe_context *ctx, struct pipe_surface* ps, static INLINE void pipe_surface_init(struct pipe_context *ctx, struct pipe_surface* ps, - struct pipe_resource *pt, unsigned level, unsigned layer, - unsigned flags) + struct pipe_resource *pt, unsigned level, unsigned layer) { ps->texture = 0; pipe_reference_init(&ps->reference, 1); - pipe_surface_reset(ctx, ps, pt, level, layer, flags); + pipe_surface_reset(ctx, ps, pt, level, layer); } /* Return true if the surfaces are equal. */ diff --git a/mesalib/src/gallium/auxiliary/util/u_suballoc.c b/mesalib/src/gallium/auxiliary/util/u_suballoc.c new file mode 100644 index 000000000..efa9a0c5e --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_suballoc.c @@ -0,0 +1,132 @@ +/************************************************************************** + * + * Copyright 2009 VMware, Inc. + * Copyright 2012 Marek Olšák <maraeo@gmail.com> + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +/* A simple allocator that suballocates memory from a large buffer. */ + +#include "pipe/p_defines.h" +#include "util/u_inlines.h" +#include "pipe/p_context.h" +#include "util/u_memory.h" +#include "util/u_math.h" + +#include "u_suballoc.h" + + +struct u_suballocator { + struct pipe_context *pipe; + + unsigned size; /* Size of the whole buffer, in bytes. */ + unsigned alignment; /* Alignment of each sub-allocation. */ + unsigned bind; /* Bitmask of PIPE_BIND_* flags. */ + unsigned usage; /* One of PIPE_USAGE_* flags. */ + boolean zero_buffer_memory; /* If the buffer contents should be zeroed. */ + + struct pipe_resource *buffer; /* The buffer we suballocate from. */ + unsigned offset; /* Aligned offset pointing at the first unused byte. */ +}; + + +/** + * Create a suballocator. + * + * \p zero_buffer_memory determines whether the buffer contents should be + * cleared to 0 after the allocation. + */ +struct u_suballocator * +u_suballocator_create(struct pipe_context *pipe, unsigned size, + unsigned alignment, unsigned bind, unsigned usage, + boolean zero_buffer_memory) +{ + struct u_suballocator *allocator = CALLOC_STRUCT(u_suballocator); + if (!allocator) + return NULL; + + allocator->pipe = pipe; + allocator->size = align(size, alignment); + allocator->alignment = alignment; + allocator->bind = bind; + allocator->usage = usage; + allocator->zero_buffer_memory = zero_buffer_memory; + return allocator; +} + +void +u_suballocator_destroy(struct u_suballocator *allocator) +{ + pipe_resource_reference(&allocator->buffer, NULL); + FREE(allocator); +} + +void +u_suballocator_alloc(struct u_suballocator *allocator, unsigned size, + unsigned *out_offset, struct pipe_resource **outbuf) +{ + unsigned alloc_size = align(size, allocator->alignment); + + /* Don't allow allocations larger than the buffer size. */ + if (alloc_size > allocator->size) + goto fail; + + /* Make sure we have enough space in the buffer. */ + if (!allocator->buffer || + allocator->offset + alloc_size > allocator->size) { + /* Allocate a new buffer. */ + pipe_resource_reference(&allocator->buffer, NULL); + allocator->offset = 0; + allocator->buffer = + pipe_buffer_create(allocator->pipe->screen, allocator->bind, + allocator->usage, allocator->size); + if (!allocator->buffer) + goto fail; + + /* Clear the memory if needed. */ + if (allocator->zero_buffer_memory) { + struct pipe_transfer *transfer = NULL; + void *ptr; + + ptr = pipe_buffer_map(allocator->pipe, allocator->buffer, + PIPE_TRANSFER_WRITE, &transfer); + memset(ptr, 0, allocator->size); + pipe_buffer_unmap(allocator->pipe, transfer); + } + } + + assert(allocator->offset % allocator->alignment == 0); + assert(allocator->offset < allocator->buffer->width0); + assert(allocator->offset + alloc_size <= allocator->buffer->width0); + + /* Return the buffer. */ + *out_offset = allocator->offset; + pipe_resource_reference(outbuf, allocator->buffer); + + allocator->offset += alloc_size; + return; + +fail: + pipe_resource_reference(outbuf, NULL); +} diff --git a/mesalib/src/gallium/auxiliary/util/u_suballoc.h b/mesalib/src/gallium/auxiliary/util/u_suballoc.h new file mode 100644 index 000000000..1f5550ffa --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_suballoc.h @@ -0,0 +1,48 @@ +/************************************************************************** + * + * Copyright 2009 VMware, Inc. + * Copyright 2012 Marek Olšák <maraeo@gmail.com> + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +/* A simple allocator that suballocates memory from a large buffer. */ + +#ifndef U_SUBALLOC +#define U_SUBALLOC + +struct u_suballocator; + +struct u_suballocator * +u_suballocator_create(struct pipe_context *pipe, unsigned size, + unsigned alignment, unsigned bind, unsigned usage, + boolean zero_buffer_memory); + +void +u_suballocator_destroy(struct u_suballocator *allocator); + +void +u_suballocator_alloc(struct u_suballocator *allocator, unsigned size, + unsigned *out_offset, struct pipe_resource **outbuf); + +#endif diff --git a/mesalib/src/gallium/auxiliary/util/u_surface.c b/mesalib/src/gallium/auxiliary/util/u_surface.c index 2c197c3df..5e771c950 100644 --- a/mesalib/src/gallium/auxiliary/util/u_surface.c +++ b/mesalib/src/gallium/auxiliary/util/u_surface.c @@ -49,14 +49,11 @@ */ void u_surface_default_template(struct pipe_surface *surf, - const struct pipe_resource *texture, - unsigned bind) + const struct pipe_resource *texture) { memset(surf, 0, sizeof(*surf)); surf->format = texture->format; - /* XXX should filter out all non-rt/ds bind flags ? */ - surf->usage = bind; } /** @@ -110,7 +107,7 @@ util_create_rgba_texture(struct pipe_context *pipe, return FALSE; /* create surface */ - u_surface_default_template(&surf_templ, *textureOut, bind); + u_surface_default_template(&surf_templ, *textureOut); return TRUE; } @@ -531,3 +528,163 @@ util_clear_depth_stencil(struct pipe_context *pipe, pipe->transfer_unmap(pipe, dst_trans); } } + + +/* Return whether this is an RGBA, Z, S, or combined ZS format. + */ +static unsigned +get_format_mask(enum pipe_format format) +{ + const struct util_format_description *desc = util_format_description(format); + + assert(desc); + + if (util_format_has_depth(desc)) { + if (util_format_has_stencil(desc)) { + return PIPE_MASK_ZS; + } else { + return PIPE_MASK_Z; + } + } else { + if (util_format_has_stencil(desc)) { + return PIPE_MASK_S; + } else { + return PIPE_MASK_RGBA; + } + } +} + +/* Return if the box is totally inside the resource. + */ +static boolean +is_box_inside_resource(const struct pipe_resource *res, + const struct pipe_box *box, + unsigned level) +{ + unsigned width = 1, height = 1, depth = 1; + + switch (res->target) { + case PIPE_BUFFER: + width = res->width0; + height = 1; + depth = 1; + break; + case PIPE_TEXTURE_1D: + width = u_minify(res->width0, level); + height = 1; + depth = 1; + break; + case PIPE_TEXTURE_2D: + case PIPE_TEXTURE_RECT: + width = u_minify(res->width0, level); + height = u_minify(res->height0, level); + depth = 1; + break; + case PIPE_TEXTURE_3D: + width = u_minify(res->width0, level); + height = u_minify(res->height0, level); + depth = u_minify(res->depth0, level); + break; + case PIPE_TEXTURE_CUBE: + width = u_minify(res->width0, level); + height = u_minify(res->height0, level); + depth = 6; + break; + case PIPE_TEXTURE_1D_ARRAY: + width = u_minify(res->width0, level); + height = 1; + depth = res->array_size; + break; + case PIPE_TEXTURE_2D_ARRAY: + width = u_minify(res->width0, level); + height = u_minify(res->height0, level); + depth = res->array_size; + break; + case PIPE_TEXTURE_CUBE_ARRAY: + width = u_minify(res->width0, level); + height = u_minify(res->height0, level); + depth = res->array_size; + assert(res->array_size % 6 == 0); + break; + case PIPE_MAX_TEXTURE_TYPES:; + } + + return box->x >= 0 && + box->x + box->width <= (int) width && + box->y >= 0 && + box->y + box->height <= (int) height && + box->z >= 0 && + box->z + box->depth <= (int) depth; +} + +static unsigned +get_sample_count(const struct pipe_resource *res) +{ + return res->nr_samples ? res->nr_samples : 1; +} + +/** + * Try to do a blit using resource_copy_region. The function calls + * resource_copy_region if the blit description is compatible with it. + * + * It returns TRUE if the blit was done using resource_copy_region. + * + * It returns FALSE otherwise and the caller must fall back to a more generic + * codepath for the blit operation. (e.g. by using u_blitter) + */ +boolean +util_try_blit_via_copy_region(struct pipe_context *ctx, + const struct pipe_blit_info *blit) +{ + unsigned mask = get_format_mask(blit->dst.format); + + /* No format conversions. */ + if (blit->src.resource->format != blit->src.format || + blit->dst.resource->format != blit->dst.format || + !util_is_format_compatible( + util_format_description(blit->src.resource->format), + util_format_description(blit->dst.resource->format))) { + return FALSE; + } + + /* No masks, no filtering, no scissor. */ + if ((blit->mask & mask) != mask || + blit->filter != PIPE_TEX_FILTER_NEAREST || + blit->scissor_enable) { + return FALSE; + } + + /* No flipping. */ + if (blit->src.box.width < 0 || + blit->src.box.height < 0 || + blit->src.box.depth < 0) { + return FALSE; + } + + /* No scaling. */ + if (blit->src.box.width != blit->dst.box.width || + blit->src.box.height != blit->dst.box.height || + blit->src.box.depth != blit->dst.box.depth) { + return FALSE; + } + + /* No out-of-bounds access. */ + if (!is_box_inside_resource(blit->src.resource, &blit->src.box, + blit->src.level) || + !is_box_inside_resource(blit->dst.resource, &blit->dst.box, + blit->dst.level)) { + return FALSE; + } + + /* Sample counts must match. */ + if (get_sample_count(blit->src.resource) != + get_sample_count(blit->dst.resource)) { + return FALSE; + } + + ctx->resource_copy_region(ctx, blit->dst.resource, blit->dst.level, + blit->dst.box.x, blit->dst.box.y, blit->dst.box.z, + blit->src.resource, blit->src.level, + &blit->src.box); + return TRUE; +} diff --git a/mesalib/src/gallium/auxiliary/util/u_surface.h b/mesalib/src/gallium/auxiliary/util/u_surface.h index dd4d5785e..fe950c818 100644 --- a/mesalib/src/gallium/auxiliary/util/u_surface.h +++ b/mesalib/src/gallium/auxiliary/util/u_surface.h @@ -42,8 +42,7 @@ extern "C" { extern void u_surface_default_template(struct pipe_surface *view, - const struct pipe_resource *texture, - unsigned bind); + const struct pipe_resource *texture); extern boolean util_create_rgba_texture(struct pipe_context *ctx, @@ -98,6 +97,10 @@ util_clear_depth_stencil(struct pipe_context *pipe, unsigned dstx, unsigned dsty, unsigned width, unsigned height); +extern boolean +util_try_blit_via_copy_region(struct pipe_context *ctx, + const struct pipe_blit_info *blit); + #ifdef __cplusplus } diff --git a/mesalib/src/gallium/auxiliary/util/u_surfaces.c b/mesalib/src/gallium/auxiliary/util/u_surfaces.c index b0cfec2a8..c2f2b74c9 100644 --- a/mesalib/src/gallium/auxiliary/util/u_surfaces.c +++ b/mesalib/src/gallium/auxiliary/util/u_surfaces.c @@ -32,7 +32,7 @@ boolean util_surfaces_do_get(struct util_surfaces *us, unsigned surface_struct_size, struct pipe_context *ctx, struct pipe_resource *pt, - unsigned level, unsigned layer, unsigned flags, + unsigned level, unsigned layer, struct pipe_surface **res) { struct pipe_surface *ps; @@ -65,7 +65,7 @@ util_surfaces_do_get(struct util_surfaces *us, unsigned surface_struct_size, return FALSE; } - pipe_surface_init(ctx, ps, pt, level, layer, flags); + pipe_surface_init(ctx, ps, pt, level, layer); if(pt->target == PIPE_TEXTURE_3D || pt->target == PIPE_TEXTURE_CUBE) cso_hash_insert(us->u.hash, (layer << 8) | level, ps); diff --git a/mesalib/src/gallium/auxiliary/util/u_surfaces.h b/mesalib/src/gallium/auxiliary/util/u_surfaces.h index 9581feda7..1605215cb 100644 --- a/mesalib/src/gallium/auxiliary/util/u_surfaces.h +++ b/mesalib/src/gallium/auxiliary/util/u_surfaces.h @@ -46,14 +46,14 @@ struct util_surfaces boolean util_surfaces_do_get(struct util_surfaces *us, unsigned surface_struct_size, struct pipe_context *ctx, struct pipe_resource *pt, - unsigned level, unsigned layer, unsigned flags, + unsigned level, unsigned layer, struct pipe_surface **res); /* fast inline path for the very common case */ static INLINE boolean util_surfaces_get(struct util_surfaces *us, unsigned surface_struct_size, struct pipe_context *ctx, struct pipe_resource *pt, - unsigned level, unsigned layer, unsigned flags, + unsigned level, unsigned layer, struct pipe_surface **res) { if(likely((pt->target == PIPE_TEXTURE_2D || pt->target == PIPE_TEXTURE_RECT) && us->u.array)) @@ -67,7 +67,7 @@ util_surfaces_get(struct util_surfaces *us, unsigned surface_struct_size, } } - return util_surfaces_do_get(us, surface_struct_size, ctx, pt, level, layer, flags, res); + return util_surfaces_do_get(us, surface_struct_size, ctx, pt, level, layer, res); } static INLINE struct pipe_surface * diff --git a/mesalib/src/glsl/Makefile.sources b/mesalib/src/glsl/Makefile.sources index 5e098fc05..d984c5ca7 100644 --- a/mesalib/src/glsl/Makefile.sources +++ b/mesalib/src/glsl/Makefile.sources @@ -57,6 +57,7 @@ LIBGLSL_FILES = \ $(GLSL_SRCDIR)/lower_jumps.cpp \ $(GLSL_SRCDIR)/lower_mat_op_to_vec.cpp \ $(GLSL_SRCDIR)/lower_noise.cpp \ + $(GLSL_SRCDIR)/lower_packed_varyings.cpp \ $(GLSL_SRCDIR)/lower_texture_projection.cpp \ $(GLSL_SRCDIR)/lower_variable_index_to_cond_assign.cpp \ $(GLSL_SRCDIR)/lower_vec_index_to_cond_assign.cpp \ diff --git a/mesalib/src/glsl/glsl_parser_extras.cpp b/mesalib/src/glsl/glsl_parser_extras.cpp index d36089226..91122cc60 100644 --- a/mesalib/src/glsl/glsl_parser_extras.cpp +++ b/mesalib/src/glsl/glsl_parser_extras.cpp @@ -151,7 +151,7 @@ _mesa_glsl_parse_state::check_version(unsigned required_glsl_version, va_list args; va_start(args, fmt); - char *problem = ralloc_vasprintf(ctx, fmt, args); + char *problem = ralloc_vasprintf(this, fmt, args); va_end(args); const char *glsl_version_string = glsl_compute_version_string(ctx, false, required_glsl_version); @@ -159,14 +159,14 @@ _mesa_glsl_parse_state::check_version(unsigned required_glsl_version, = glsl_compute_version_string(ctx, true, required_glsl_es_version); const char *requirement_string = ""; if (required_glsl_version && required_glsl_es_version) { - requirement_string = ralloc_asprintf(ctx, " (%s or %s required)", + requirement_string = ralloc_asprintf(this, " (%s or %s required)", glsl_version_string, glsl_es_version_string); } else if (required_glsl_version) { - requirement_string = ralloc_asprintf(ctx, " (%s required)", + requirement_string = ralloc_asprintf(this, " (%s required)", glsl_version_string); } else if (required_glsl_es_version) { - requirement_string = ralloc_asprintf(ctx, " (%s required)", + requirement_string = ralloc_asprintf(this, " (%s required)", glsl_es_version_string); } _mesa_glsl_error(locp, this, "%s in %s%s.", diff --git a/mesalib/src/glsl/ir.cpp b/mesalib/src/glsl/ir.cpp index 7b0a487b6..703f5ec58 100644 --- a/mesalib/src/glsl/ir.cpp +++ b/mesalib/src/glsl/ir.cpp @@ -1492,6 +1492,7 @@ ir_variable::ir_variable(const struct glsl_type *type, const char *name, this->explicit_location = false; this->has_initializer = false; this->location = -1; + this->location_frac = 0; this->uniform_block = -1; this->warn_extension = NULL; this->constant_value = NULL; diff --git a/mesalib/src/glsl/ir.h b/mesalib/src/glsl/ir.h index 89c516c87..85fc5ce95 100644 --- a/mesalib/src/glsl/ir.h +++ b/mesalib/src/glsl/ir.h @@ -437,6 +437,24 @@ public: unsigned has_initializer:1; /** + * Is this variable a generic output or input that has not yet been matched + * up to a variable in another stage of the pipeline? + * + * This is used by the linker as scratch storage while assigning locations + * to generic inputs and outputs. + */ + unsigned is_unmatched_generic_inout:1; + + /** + * If non-zero, then this variable may be packed along with other variables + * into a single varying slot, so this offset should be applied when + * accessing components. For example, an offset of 1 means that the x + * component of this variable is actually stored in component y of the + * location specified by \c location. + */ + unsigned location_frac:2; + + /** * \brief Layout qualifier for gl_FragDepth. * * This is not equal to \c ir_depth_layout_none if and only if this diff --git a/mesalib/src/glsl/ir_optimization.h b/mesalib/src/glsl/ir_optimization.h index 2220d511e..6b9519174 100644 --- a/mesalib/src/glsl/ir_optimization.h +++ b/mesalib/src/glsl/ir_optimization.h @@ -72,9 +72,12 @@ bool lower_noise(exec_list *instructions); bool lower_variable_index_to_cond_assign(exec_list *instructions, bool lower_input, bool lower_output, bool lower_temp, bool lower_uniform); bool lower_quadop_vector(exec_list *instructions, bool dont_lower_swz); -bool lower_clip_distance(exec_list *instructions); +bool lower_clip_distance(gl_shader *shader); void lower_output_reads(exec_list *instructions); void lower_ubo_reference(struct gl_shader *shader, exec_list *instructions); +void lower_packed_varyings(void *mem_ctx, unsigned location_base, + unsigned locations_used, ir_variable_mode mode, + gl_shader *shader); bool optimize_redundant_jumps(exec_list *instructions); bool optimize_split_arrays(exec_list *instructions, bool linked); diff --git a/mesalib/src/glsl/linker.cpp b/mesalib/src/glsl/linker.cpp index 29fc5d841..be08156e0 100644 --- a/mesalib/src/glsl/linker.cpp +++ b/mesalib/src/glsl/linker.cpp @@ -76,6 +76,8 @@ extern "C" { #include "main/shaderobj.h" } +#define ALIGN(value, alignment) (((value) + alignment - 1) & ~(alignment - 1)) + /** * Visitor that determines whether or not a variable is ever written. */ @@ -200,19 +202,38 @@ linker_warning(gl_shader_program *prog, const char *fmt, ...) void -link_invalidate_variable_locations(gl_shader *sh, enum ir_variable_mode mode, - int generic_base) +link_invalidate_variable_locations(gl_shader *sh, int input_base, + int output_base) { foreach_list(node, sh->ir) { ir_variable *const var = ((ir_instruction *) node)->as_variable(); - if ((var == NULL) || (var->mode != (unsigned) mode)) - continue; + if (var == NULL) + continue; + + int base; + switch (var->mode) { + case ir_var_in: + base = input_base; + break; + case ir_var_out: + base = output_base; + break; + default: + continue; + } /* Only assign locations for generic attributes / varyings / etc. */ - if ((var->location >= generic_base) && !var->explicit_location) - var->location = -1; + if ((var->location >= base) && !var->explicit_location) + var->location = -1; + + if ((var->location == -1) && !var->explicit_location) { + var->is_unmatched_generic_inout = 1; + var->location_frac = 0; + } else { + var->is_unmatched_generic_inout = 0; + } } } @@ -1309,8 +1330,6 @@ assign_attribute_or_color_locations(gl_shader_program *prog, (target_index == MESA_SHADER_VERTEX) ? ir_var_in : ir_var_out; - link_invalidate_variable_locations(sh, direction, generic_base); - /* Temporary storage for the set of attributes that need locations assigned. */ struct temp_attr { @@ -1352,6 +1371,7 @@ assign_attribute_or_color_locations(gl_shader_program *prog, if (prog->AttributeBindings->get(binding, var->name)) { assert(binding >= VERT_ATTRIB_GENERIC0); var->location = binding; + var->is_unmatched_generic_inout = 0; } } else if (target_index == MESA_SHADER_FRAGMENT) { unsigned binding; @@ -1360,6 +1380,7 @@ assign_attribute_or_color_locations(gl_shader_program *prog, if (prog->FragDataBindings->get(binding, var->name)) { assert(binding >= FRAG_RESULT_DATA0); var->location = binding; + var->is_unmatched_generic_inout = 0; if (prog->FragDataIndexBindings->get(index, var->name)) { var->index = index; @@ -1475,6 +1496,7 @@ assign_attribute_or_color_locations(gl_shader_program *prog, } to_assign[i].var->location = generic_base + location; + to_assign[i].var->is_unmatched_generic_inout = 0; used_locations |= (use_mask << location); } @@ -1498,7 +1520,7 @@ demote_shader_inputs_and_outputs(gl_shader *sh, enum ir_variable_mode mode) * its value is used by other shader stages. This will cause the variable * to have a location assigned. */ - if (var->location == -1) { + if (var->is_unmatched_generic_inout) { var->mode = ir_var_auto; } } @@ -1517,18 +1539,12 @@ public: static bool is_same(const tfeedback_decl &x, const tfeedback_decl &y); bool assign_location(struct gl_context *ctx, struct gl_shader_program *prog, ir_variable *output_var); - bool accumulate_num_outputs(struct gl_shader_program *prog, unsigned *count); + unsigned get_num_outputs() const; bool store(struct gl_context *ctx, struct gl_shader_program *prog, struct gl_transform_feedback_info *info, unsigned buffer, const unsigned max_outputs) const; - - /** - * True if assign_location() has been called for this object. - */ - bool is_assigned() const - { - return this->location != -1; - } + ir_variable *find_output_var(gl_shader_program *prog, + gl_shader *producer) const; bool is_next_buffer_separator() const { @@ -1541,19 +1557,8 @@ public: } /** - * Determine whether this object refers to the variable var. - */ - bool matches_var(ir_variable *var) const - { - if (this->is_clip_distance_mesa) - return strcmp(var->name, "gl_ClipDistanceMESA") == 0; - else - return strcmp(var->name, this->var_name) == 0; - } - - /** * The total number of varying components taken up by this variable. Only - * valid if is_assigned() is true. + * valid if assign_location() has been called. */ unsigned num_components() const { @@ -1598,6 +1603,17 @@ private: int location; /** + * If non-zero, then this variable may be packed along with other variables + * into a single varying slot, so this offset should be applied when + * accessing components. For example, an offset of 1 means that the x + * component of this variable is actually stored in component y of the + * location specified by \c location. + * + * Only valid if location != -1. + */ + unsigned location_frac; + + /** * If location != -1, the number of vector elements in this variable, or 1 * if this variable is a scalar. */ @@ -1736,6 +1752,8 @@ tfeedback_decl::assign_location(struct gl_context *ctx, /* Array variable */ const unsigned matrix_cols = output_var->type->fields.array->matrix_columns; + const unsigned vector_elements = + output_var->type->fields.array->vector_elements; unsigned actual_array_size = this->is_clip_distance_mesa ? prog->Vert.ClipDistanceArraySize : output_var->type->array_size(); @@ -1751,16 +1769,22 @@ tfeedback_decl::assign_location(struct gl_context *ctx, if (this->is_clip_distance_mesa) { this->location = output_var->location + this->array_subscript / 4; + this->location_frac = this->array_subscript % 4; } else { - this->location = - output_var->location + this->array_subscript * matrix_cols; + unsigned fine_location + = output_var->location * 4 + output_var->location_frac; + unsigned array_elem_size = vector_elements * matrix_cols; + fine_location += array_elem_size * this->array_subscript; + this->location = fine_location / 4; + this->location_frac = fine_location % 4; } this->size = 1; } else { this->location = output_var->location; + this->location_frac = output_var->location_frac; this->size = actual_array_size; } - this->vector_elements = output_var->type->fields.array->vector_elements; + this->vector_elements = vector_elements; this->matrix_columns = matrix_cols; if (this->is_clip_distance_mesa) this->type = GL_FLOAT; @@ -1775,6 +1799,7 @@ tfeedback_decl::assign_location(struct gl_context *ctx, return false; } this->location = output_var->location; + this->location_frac = output_var->location_frac; this->size = 1; this->vector_elements = output_var->type->vector_elements; this->matrix_columns = output_var->type->matrix_columns; @@ -1802,34 +1827,14 @@ tfeedback_decl::assign_location(struct gl_context *ctx, } -bool -tfeedback_decl::accumulate_num_outputs(struct gl_shader_program *prog, - unsigned *count) +unsigned +tfeedback_decl::get_num_outputs() const { if (!this->is_varying()) { - return true; + return 0; } - if (!this->is_assigned()) { - /* From GL_EXT_transform_feedback: - * A program will fail to link if: - * - * * any variable name specified in the <varyings> array is not - * declared as an output in the geometry shader (if present) or - * the vertex shader (if no geometry shader is present); - */ - linker_error(prog, "Transform feedback varying %s undeclared.", - this->orig_name); - return false; - } - - unsigned translated_size = this->size; - if (this->is_clip_distance_mesa) - translated_size = (translated_size + 3) / 4; - - *count += translated_size * this->matrix_columns; - - return true; + return (this->num_components() + this->location_frac + 3)/4; } @@ -1867,35 +1872,23 @@ tfeedback_decl::store(struct gl_context *ctx, struct gl_shader_program *prog, return false; } - unsigned translated_size = this->size; - if (this->is_clip_distance_mesa) - translated_size = (translated_size + 3) / 4; - unsigned components_so_far = 0; - for (unsigned index = 0; index < translated_size; ++index) { - for (unsigned v = 0; v < this->matrix_columns; ++v) { - unsigned num_components = this->vector_elements; - assert(info->NumOutputs < max_outputs); - info->Outputs[info->NumOutputs].ComponentOffset = 0; - if (this->is_clip_distance_mesa) { - if (this->is_subscripted) { - num_components = 1; - info->Outputs[info->NumOutputs].ComponentOffset = - this->array_subscript % 4; - } else { - num_components = MIN2(4, this->size - components_so_far); - } - } - info->Outputs[info->NumOutputs].OutputRegister = - this->location + v + index * this->matrix_columns; - info->Outputs[info->NumOutputs].NumComponents = num_components; - info->Outputs[info->NumOutputs].OutputBuffer = buffer; - info->Outputs[info->NumOutputs].DstOffset = info->BufferStride[buffer]; - ++info->NumOutputs; - info->BufferStride[buffer] += num_components; - components_so_far += num_components; - } + unsigned location = this->location; + unsigned location_frac = this->location_frac; + unsigned num_components = this->num_components(); + while (num_components > 0) { + unsigned output_size = MIN2(num_components, 4 - location_frac); + assert(info->NumOutputs < max_outputs); + info->Outputs[info->NumOutputs].ComponentOffset = location_frac; + info->Outputs[info->NumOutputs].OutputRegister = location; + info->Outputs[info->NumOutputs].NumComponents = output_size; + info->Outputs[info->NumOutputs].OutputBuffer = buffer; + info->Outputs[info->NumOutputs].DstOffset = info->BufferStride[buffer]; + ++info->NumOutputs; + info->BufferStride[buffer] += output_size; + num_components -= output_size; + location++; + location_frac = 0; } - assert(components_so_far == this->num_components()); info->Varyings[info->NumVarying].Name = ralloc_strdup(prog, this->orig_name); info->Varyings[info->NumVarying].Type = this->type; @@ -1906,6 +1899,29 @@ tfeedback_decl::store(struct gl_context *ctx, struct gl_shader_program *prog, } +ir_variable * +tfeedback_decl::find_output_var(gl_shader_program *prog, + gl_shader *producer) const +{ + const char *name = this->is_clip_distance_mesa + ? "gl_ClipDistanceMESA" : this->var_name; + ir_variable *var = producer->symbols->get_variable(name); + if (var && var->mode == ir_var_out) + return var; + + /* From GL_EXT_transform_feedback: + * A program will fail to link if: + * + * * any variable name specified in the <varyings> array is not + * declared as an output in the geometry shader (if present) or + * the vertex shader (if no geometry shader is present); + */ + linker_error(prog, "Transform feedback varying %s undeclared.", + this->orig_name); + return NULL; +} + + /** * Parse all the transform feedback declarations that were passed to * glTransformFeedbackVaryings() and store them in tfeedback_decl objects. @@ -1951,61 +1967,294 @@ parse_tfeedback_decls(struct gl_context *ctx, struct gl_shader_program *prog, /** - * Assign a location for a variable that is produced in one pipeline stage - * (the "producer") and consumed in the next stage (the "consumer"). - * - * \param input_var is the input variable declaration in the consumer. - * - * \param output_var is the output variable declaration in the producer. - * - * \param input_index is the counter that keeps track of assigned input - * locations in the consumer. - * - * \param output_index is the counter that keeps track of assigned output - * locations in the producer. + * Data structure recording the relationship between outputs of one shader + * stage (the "producer") and inputs of another (the "consumer"). + */ +class varying_matches +{ +public: + varying_matches(bool disable_varying_packing); + ~varying_matches(); + void record(ir_variable *producer_var, ir_variable *consumer_var); + unsigned assign_locations(); + void store_locations(unsigned producer_base, unsigned consumer_base) const; + +private: + /** + * If true, this driver disables varying packing, so all varyings need to + * be aligned on slot boundaries, and take up a number of slots equal to + * their number of matrix columns times their array size. + */ + const bool disable_varying_packing; + + /** + * Enum representing the order in which varyings are packed within a + * packing class. + * + * Currently we pack vec4's first, then vec2's, then scalar values, then + * vec3's. This order ensures that the only vectors that are at risk of + * having to be "double parked" (split between two adjacent varying slots) + * are the vec3's. + */ + enum packing_order_enum { + PACKING_ORDER_VEC4, + PACKING_ORDER_VEC2, + PACKING_ORDER_SCALAR, + PACKING_ORDER_VEC3, + }; + + static unsigned compute_packing_class(ir_variable *var); + static packing_order_enum compute_packing_order(ir_variable *var); + static int match_comparator(const void *x_generic, const void *y_generic); + + /** + * Structure recording the relationship between a single producer output + * and a single consumer input. + */ + struct match { + /** + * Packing class for this varying, computed by compute_packing_class(). + */ + unsigned packing_class; + + /** + * Packing order for this varying, computed by compute_packing_order(). + */ + packing_order_enum packing_order; + unsigned num_components; + + /** + * The output variable in the producer stage. + */ + ir_variable *producer_var; + + /** + * The input variable in the consumer stage. + */ + ir_variable *consumer_var; + + /** + * The location which has been assigned for this varying. This is + * expressed in multiples of a float, with the first generic varying + * (i.e. the one referred to by VERT_RESULT_VAR0 or FRAG_ATTRIB_VAR0) + * represented by the value 0. + */ + unsigned generic_location; + } *matches; + + /** + * The number of elements in the \c matches array that are currently in + * use. + */ + unsigned num_matches; + + /** + * The number of elements that were set aside for the \c matches array when + * it was allocated. + */ + unsigned matches_capacity; +}; + + +varying_matches::varying_matches(bool disable_varying_packing) + : disable_varying_packing(disable_varying_packing) +{ + /* Note: this initial capacity is rather arbitrarily chosen to be large + * enough for many cases without wasting an unreasonable amount of space. + * varying_matches::record() will resize the array if there are more than + * this number of varyings. + */ + this->matches_capacity = 8; + this->matches = (match *) + malloc(sizeof(*this->matches) * this->matches_capacity); + this->num_matches = 0; +} + + +varying_matches::~varying_matches() +{ + free(this->matches); +} + + +/** + * Record the given producer/consumer variable pair in the list of variables + * that should later be assigned locations. * - * It is permissible for \c input_var to be NULL (this happens if a variable - * is output by the producer and consumed by transform feedback, but not - * consumed by the consumer). + * It is permissible for \c consumer_var to be NULL (this happens if a + * variable is output by the producer and consumed by transform feedback, but + * not consumed by the consumer). * - * If the variable has already been assigned a location, this function has no - * effect. + * If \c producer_var has already been paired up with a consumer_var, or + * producer_var is part of fixed pipeline functionality (and hence already has + * a location assigned), this function has no effect. */ void -assign_varying_location(ir_variable *input_var, ir_variable *output_var, - unsigned *input_index, unsigned *output_index) +varying_matches::record(ir_variable *producer_var, ir_variable *consumer_var) { - if (output_var->location != -1) { - /* Location already assigned. */ + if (!producer_var->is_unmatched_generic_inout) { + /* Either a location already exists for this variable (since it is part + * of fixed functionality), or it has already been recorded as part of a + * previous match. + */ return; } - if (input_var) { - assert(input_var->location == -1); - input_var->location = *input_index; + if (this->num_matches == this->matches_capacity) { + this->matches_capacity *= 2; + this->matches = (match *) + realloc(this->matches, + sizeof(*this->matches) * this->matches_capacity); + } + this->matches[this->num_matches].packing_class + = this->compute_packing_class(producer_var); + this->matches[this->num_matches].packing_order + = this->compute_packing_order(producer_var); + if (this->disable_varying_packing) { + unsigned slots = producer_var->type->is_array() + ? (producer_var->type->length + * producer_var->type->fields.array->matrix_columns) + : producer_var->type->matrix_columns; + this->matches[this->num_matches].num_components = 4 * slots; + } else { + this->matches[this->num_matches].num_components + = producer_var->type->component_slots(); + } + this->matches[this->num_matches].producer_var = producer_var; + this->matches[this->num_matches].consumer_var = consumer_var; + this->num_matches++; + producer_var->is_unmatched_generic_inout = 0; + if (consumer_var) + consumer_var->is_unmatched_generic_inout = 0; +} + + +/** + * Choose locations for all of the variable matches that were previously + * passed to varying_matches::record(). + */ +unsigned +varying_matches::assign_locations() +{ + /* Sort varying matches into an order that makes them easy to pack. */ + qsort(this->matches, this->num_matches, sizeof(*this->matches), + &varying_matches::match_comparator); + + unsigned generic_location = 0; + + for (unsigned i = 0; i < this->num_matches; i++) { + /* Advance to the next slot if this varying has a different packing + * class than the previous one, and we're not already on a slot + * boundary. + */ + if (i > 0 && + this->matches[i - 1].packing_class + != this->matches[i].packing_class) { + generic_location = ALIGN(generic_location, 4); + } + + this->matches[i].generic_location = generic_location; + + generic_location += this->matches[i].num_components; } - output_var->location = *output_index; + return (generic_location + 3) / 4; +} - /* FINISHME: Support for "varying" records in GLSL 1.50. */ - assert(!output_var->type->is_record()); - if (output_var->type->is_array()) { - const unsigned slots = output_var->type->length - * output_var->type->fields.array->matrix_columns; +/** + * Update the producer and consumer shaders to reflect the locations + * assignments that were made by varying_matches::assign_locations(). + */ +void +varying_matches::store_locations(unsigned producer_base, + unsigned consumer_base) const +{ + for (unsigned i = 0; i < this->num_matches; i++) { + ir_variable *producer_var = this->matches[i].producer_var; + ir_variable *consumer_var = this->matches[i].consumer_var; + unsigned generic_location = this->matches[i].generic_location; + unsigned slot = generic_location / 4; + unsigned offset = generic_location % 4; + + producer_var->location = producer_base + slot; + producer_var->location_frac = offset; + if (consumer_var) { + assert(consumer_var->location == -1); + consumer_var->location = consumer_base + slot; + consumer_var->location_frac = offset; + } + } +} + + +/** + * Compute the "packing class" of the given varying. This is an unsigned + * integer with the property that two variables in the same packing class can + * be safely backed into the same vec4. + */ +unsigned +varying_matches::compute_packing_class(ir_variable *var) +{ + /* In this initial implementation we conservatively assume that variables + * can only be packed if their base type (float/int/uint/bool) matches and + * their interpolation and centroid qualifiers match. + * + * TODO: relax these restrictions when the driver back-end permits. + */ + unsigned packing_class = var->centroid ? 1 : 0; + packing_class *= 4; + packing_class += var->interpolation; + packing_class *= GLSL_TYPE_ERROR; + packing_class += var->type->get_scalar_type()->base_type; + return packing_class; +} - *output_index += slots; - *input_index += slots; - } else { - const unsigned slots = output_var->type->matrix_columns; - *output_index += slots; - *input_index += slots; +/** + * Compute the "packing order" of the given varying. This is a sort key we + * use to determine when to attempt to pack the given varying relative to + * other varyings in the same packing class. + */ +varying_matches::packing_order_enum +varying_matches::compute_packing_order(ir_variable *var) +{ + const glsl_type *element_type = var->type; + + /* FINISHME: Support for "varying" records in GLSL 1.50. */ + while (element_type->base_type == GLSL_TYPE_ARRAY) { + element_type = element_type->fields.array; + } + + switch (element_type->vector_elements) { + case 1: return PACKING_ORDER_SCALAR; + case 2: return PACKING_ORDER_VEC2; + case 3: return PACKING_ORDER_VEC3; + case 4: return PACKING_ORDER_VEC4; + default: + assert(!"Unexpected value of vector_elements"); + return PACKING_ORDER_VEC4; } } /** + * Comparison function passed to qsort() to sort varyings by packing_class and + * then by packing_order. + */ +int +varying_matches::match_comparator(const void *x_generic, const void *y_generic) +{ + const match *x = (const match *) x_generic; + const match *y = (const match *) y_generic; + + if (x->packing_class != y->packing_class) + return x->packing_class - y->packing_class; + return x->packing_order - y->packing_order; +} + + +/** * Is the given variable a varying variable to be counted against the * limit in ctx->Const.MaxVarying? * This includes variables such as texcoords, colors and generic @@ -2052,14 +2301,16 @@ is_varying_var(GLenum shaderType, const ir_variable *var) */ bool assign_varying_locations(struct gl_context *ctx, + void *mem_ctx, struct gl_shader_program *prog, gl_shader *producer, gl_shader *consumer, unsigned num_tfeedback_decls, tfeedback_decl *tfeedback_decls) { /* FINISHME: Set dynamically when geometry shader support is added. */ - unsigned output_index = VERT_RESULT_VAR0; - unsigned input_index = FRAG_ATTRIB_VAR0; + const unsigned producer_base = VERT_RESULT_VAR0; + const unsigned consumer_base = FRAG_ATTRIB_VAR0; + varying_matches matches(ctx->Const.DisableVaryingPacking); /* Operate in a total of three passes. * @@ -2072,10 +2323,6 @@ assign_varying_locations(struct gl_context *ctx, * not being inputs. This lets the optimizer eliminate them. */ - link_invalidate_variable_locations(producer, ir_var_out, VERT_RESULT_VAR0); - if (consumer) - link_invalidate_variable_locations(consumer, ir_var_in, FRAG_ATTRIB_VAR0); - foreach_list(node, producer->ir) { ir_variable *const output_var = ((ir_instruction *) node)->as_variable(); @@ -2089,23 +2336,51 @@ assign_varying_locations(struct gl_context *ctx, input_var = NULL; if (input_var) { - assign_varying_location(input_var, output_var, &input_index, - &output_index); + matches.record(output_var, input_var); } + } - for (unsigned i = 0; i < num_tfeedback_decls; ++i) { - if (!tfeedback_decls[i].is_varying()) - continue; + 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) { - assign_varying_location(input_var, output_var, &input_index, - &output_index); - } - if (!tfeedback_decls[i].assign_location(ctx, prog, output_var)) - return false; - } + ir_variable *output_var + = tfeedback_decls[i].find_output_var(prog, producer); + + if (output_var == NULL) + return false; + + if (output_var->is_unmatched_generic_inout) { + matches.record(output_var, NULL); + } + } + + const unsigned slots_used = matches.assign_locations(); + matches.store_locations(producer_base, consumer_base); + + for (unsigned i = 0; i < num_tfeedback_decls; ++i) { + if (!tfeedback_decls[i].is_varying()) + continue; + + ir_variable *output_var + = tfeedback_decls[i].find_output_var(prog, producer); + + if (!tfeedback_decls[i].assign_location(ctx, prog, output_var)) + return false; + } + + if (ctx->Const.DisableVaryingPacking) { + /* Transform feedback code assumes varyings are packed, so if the driver + * has disabled varying packing, make sure it does not support transform + * feedback. + */ + assert(!ctx->Extensions.EXT_transform_feedback); + } else { + lower_packed_varyings(mem_ctx, producer_base, slots_used, ir_var_out, + producer); + if (consumer) { + lower_packed_varyings(mem_ctx, consumer_base, slots_used, ir_var_in, + consumer); } } @@ -2118,7 +2393,7 @@ assign_varying_locations(struct gl_context *ctx, if ((var == NULL) || (var->mode != ir_var_in)) continue; - if (var->location == -1) { + if (var->is_unmatched_generic_inout) { if (prog->Version <= 120) { /* On page 25 (page 31 of the PDF) of the GLSL 1.20 spec: * @@ -2215,8 +2490,7 @@ store_tfeedback_info(struct gl_context *ctx, struct gl_shader_program *prog, unsigned num_outputs = 0; for (unsigned i = 0; i < num_tfeedback_decls; ++i) - if (!tfeedback_decls[i].accumulate_num_outputs(prog, &num_outputs)) - return false; + num_outputs += tfeedback_decls[i].get_num_outputs(); prog->LinkedTransformFeedback.Outputs = rzalloc_array(prog, @@ -2568,8 +2842,9 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) if (!prog->LinkStatus) goto done; - if (ctx->ShaderCompilerOptions[i].LowerClipDistance) - lower_clip_distance(prog->_LinkedShaders[i]->ir); + if (ctx->ShaderCompilerOptions[i].LowerClipDistance) { + lower_clip_distance(prog->_LinkedShaders[i]); + } unsigned max_unroll = ctx->ShaderCompilerOptions[i].MaxUnrollIterations; @@ -2577,6 +2852,19 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) ; } + /* Mark all generic shader inputs and outputs as unpaired. */ + if (prog->_LinkedShaders[MESA_SHADER_VERTEX] != NULL) { + link_invalidate_variable_locations( + prog->_LinkedShaders[MESA_SHADER_VERTEX], + VERT_ATTRIB_GENERIC0, VERT_RESULT_VAR0); + } + /* FINISHME: Geometry shaders not implemented yet */ + if (prog->_LinkedShaders[MESA_SHADER_FRAGMENT] != NULL) { + link_invalidate_variable_locations( + prog->_LinkedShaders[MESA_SHADER_FRAGMENT], + FRAG_ATTRIB_VAR0, FRAG_RESULT_DATA0); + } + /* FINISHME: The value of the max_attribute_index parameter is * FINISHME: implementation dependent based on the value of * FINISHME: GL_MAX_VERTEX_ATTRIBS. GL_MAX_VERTEX_ATTRIBS must be @@ -2623,7 +2911,7 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) continue; if (!assign_varying_locations( - ctx, prog, prog->_LinkedShaders[prev], prog->_LinkedShaders[i], + ctx, mem_ctx, prog, prog->_LinkedShaders[prev], prog->_LinkedShaders[i], i == MESA_SHADER_FRAGMENT ? num_tfeedback_decls : 0, tfeedback_decls)) goto done; @@ -2636,7 +2924,7 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) * locations for use by transform feedback. */ if (!assign_varying_locations( - ctx, prog, prog->_LinkedShaders[prev], NULL, num_tfeedback_decls, + ctx, mem_ctx, prog, prog->_LinkedShaders[prev], NULL, num_tfeedback_decls, tfeedback_decls)) goto done; } diff --git a/mesalib/src/glsl/lower_clip_distance.cpp b/mesalib/src/glsl/lower_clip_distance.cpp index 031691471..09bdc36e1 100644 --- a/mesalib/src/glsl/lower_clip_distance.cpp +++ b/mesalib/src/glsl/lower_clip_distance.cpp @@ -45,6 +45,7 @@ * LowerClipDistance flag in gl_shader_compiler_options to true. */ +#include "glsl_symbol_table.h" #include "ir_hierarchical_visitor.h" #include "ir.h" @@ -334,11 +335,14 @@ lower_clip_distance_visitor::visit_leave(ir_call *ir) bool -lower_clip_distance(exec_list *instructions) +lower_clip_distance(gl_shader *shader) { lower_clip_distance_visitor v; - visit_list_elements(&v, instructions); + visit_list_elements(&v, shader->ir); + + if (v.new_clip_distance_var) + shader->symbols->add_variable(v.new_clip_distance_var); return v.progress; } diff --git a/mesalib/src/glsl/lower_packed_varyings.cpp b/mesalib/src/glsl/lower_packed_varyings.cpp new file mode 100644 index 000000000..09c551c4e --- /dev/null +++ b/mesalib/src/glsl/lower_packed_varyings.cpp @@ -0,0 +1,364 @@ +/* + * Copyright © 2011 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +/** + * \file lower_varyings_to_packed.cpp + * + * This lowering pass generates GLSL code that manually packs varyings into + * vec4 slots, for the benefit of back-ends that don't support packed varyings + * natively. + * + * For example, the following shader: + * + * out mat3x2 foo; // location=4, location_frac=0 + * out vec3 bar[2]; // location=5, location_frac=2 + * + * main() + * { + * ... + * } + * + * Is rewritten to: + * + * mat3x2 foo; + * vec3 bar[2]; + * out vec4 packed4; // location=4, location_frac=0 + * out vec4 packed5; // location=5, location_frac=0 + * out vec4 packed6; // location=6, location_frac=0 + * + * main() + * { + * ... + * packed4.xy = foo[0]; + * packed4.zw = foo[1]; + * packed5.xy = foo[2]; + * packed5.zw = bar[0].xy; + * packed6.x = bar[0].z; + * packed6.yzw = bar[1]; + * } + * + * This lowering pass properly handles "double parking" of a varying vector + * across two varying slots. For example, in the code above, two of the + * components of bar[0] are stored in packed5, and the remaining component is + * stored in packed6. + * + * Note that in theory, the extra instructions may cause some loss of + * performance. However, hopefully in most cases the performance loss will + * either be absorbed by a later optimization pass, or it will be offset by + * memory bandwidth savings (because fewer varyings are used). + */ + +#include "glsl_symbol_table.h" +#include "ir.h" +#include "ir_optimization.h" + +/** + * Visitor that performs varying packing. For each varying declared in the + * shader, this visitor determines whether it needs to be packed. If so, it + * demotes it to an ordinary global, creates new packed varyings, and + * generates assignments to convert between the original varying and the + * packed varying. + */ +class lower_packed_varyings_visitor +{ +public: + lower_packed_varyings_visitor(void *mem_ctx, unsigned location_base, + unsigned locations_used, + ir_variable_mode mode, + exec_list *main_instructions); + + void run(exec_list *instructions); + +private: + unsigned lower_rvalue(ir_rvalue *rvalue, unsigned fine_location, + ir_variable *unpacked_var, const char *name); + unsigned lower_arraylike(ir_rvalue *rvalue, unsigned array_size, + unsigned fine_location, + ir_variable *unpacked_var, const char *name); + ir_variable *get_packed_varying(unsigned location, + ir_variable *unpacked_var, + const char *name); + bool needs_lowering(ir_variable *var); + + /** + * Memory context used to allocate new instructions for the shader. + */ + void * const mem_ctx; + + /** + * Location representing the first generic varying slot for this shader + * stage (e.g. VERT_RESULT_VAR0 if we are packing vertex shader outputs). + * Varyings whose location is less than this value are assumed to + * correspond to special fixed function hardware, so they are not lowered. + */ + const unsigned location_base; + + /** + * Number of generic varying slots which are used by this shader. This is + * used to allocate temporary intermediate data structures. If any any + * varying used by this shader has a location greater than or equal to + * location_base + locations_used, an assertion will fire. + */ + const unsigned locations_used; + + /** + * Array of pointers to the packed varyings that have been created for each + * generic varying slot. NULL entries in this array indicate varying slots + * for which a packed varying has not been created yet. + */ + ir_variable **packed_varyings; + + /** + * Type of varying which is being lowered in this pass (either ir_var_in or + * ir_var_out). + */ + const ir_variable_mode mode; + + /** + * List of instructions corresponding to the main() function. This is + * where we add instructions to pack or unpack the varyings. + */ + exec_list *main_instructions; +}; + +lower_packed_varyings_visitor::lower_packed_varyings_visitor( + void *mem_ctx, unsigned location_base, unsigned locations_used, + ir_variable_mode mode, exec_list *main_instructions) + : mem_ctx(mem_ctx), + location_base(location_base), + locations_used(locations_used), + packed_varyings((ir_variable **) + rzalloc_array_size(mem_ctx, sizeof(*packed_varyings), + locations_used)), + mode(mode), + main_instructions(main_instructions) +{ +} + +void +lower_packed_varyings_visitor::run(exec_list *instructions) +{ + foreach_list (node, instructions) { + ir_variable *var = ((ir_instruction *) node)->as_variable(); + if (var == NULL) + continue; + + if (var->mode != this->mode || + var->location < (int) this->location_base || + !this->needs_lowering(var)) + continue; + + /* Change the old varying into an ordinary global. */ + var->mode = ir_var_auto; + + /* Create a reference to the old varying. */ + ir_dereference_variable *deref + = new(this->mem_ctx) ir_dereference_variable(var); + + /* Recursively pack or unpack it. */ + this->lower_rvalue(deref, var->location * 4 + var->location_frac, var, + var->name); + } +} + +/** + * Recursively pack or unpack the given varying (or portion of a varying) by + * traversing all of its constituent vectors. + * + * \param fine_location is the location where the first constituent vector + * should be packed--the word "fine" indicates that this location is expressed + * in multiples of a float, rather than multiples of a vec4 as is used + * elsewhere in Mesa. + * + * \return the location where the next constituent vector (after this one) + * should be packed. + */ +unsigned +lower_packed_varyings_visitor::lower_rvalue(ir_rvalue *rvalue, + unsigned fine_location, + ir_variable *unpacked_var, + const char *name) +{ + /* FINISHME: Support for "varying" records in GLSL 1.50. */ + assert(!rvalue->type->is_record()); + + if (rvalue->type->is_array()) { + /* Arrays are packed/unpacked by considering each array element in + * sequence. + */ + return this->lower_arraylike(rvalue, rvalue->type->array_size(), + fine_location, unpacked_var, name); + } else if (rvalue->type->is_matrix()) { + /* Matrices are packed/unpacked by considering each column vector in + * sequence. + */ + return this->lower_arraylike(rvalue, rvalue->type->matrix_columns, + fine_location, unpacked_var, name); + } else if (rvalue->type->vector_elements + fine_location % 4 > 4) { + /* This vector is going to be "double parked" across two varying slots, + * so handle it as two separate assignments. + */ + unsigned left_components = 4 - fine_location % 4; + unsigned right_components + = rvalue->type->vector_elements - left_components; + unsigned left_swizzle_values[4] = { 0, 0, 0, 0 }; + unsigned right_swizzle_values[4] = { 0, 0, 0, 0 }; + char left_swizzle_name[4] = { 0, 0, 0, 0 }; + char right_swizzle_name[4] = { 0, 0, 0, 0 }; + for (unsigned i = 0; i < left_components; i++) { + left_swizzle_values[i] = i; + left_swizzle_name[i] = "xyzw"[i]; + } + for (unsigned i = 0; i < right_components; i++) { + right_swizzle_values[i] = i + left_components; + right_swizzle_name[i] = "xyzw"[i + left_components]; + } + ir_swizzle *left_swizzle = new(this->mem_ctx) + ir_swizzle(rvalue, left_swizzle_values, left_components); + ir_swizzle *right_swizzle = new(this->mem_ctx) + ir_swizzle(rvalue->clone(this->mem_ctx, NULL), right_swizzle_values, + right_components); + char *left_name + = ralloc_asprintf(this->mem_ctx, "%s.%s", name, left_swizzle_name); + char *right_name + = ralloc_asprintf(this->mem_ctx, "%s.%s", name, right_swizzle_name); + fine_location = this->lower_rvalue(left_swizzle, fine_location, + unpacked_var, left_name); + return this->lower_rvalue(right_swizzle, fine_location, unpacked_var, + right_name); + } else { + /* No special handling is necessary; pack the rvalue into the + * varying. + */ + unsigned swizzle_values[4] = { 0, 0, 0, 0 }; + unsigned components = rvalue->type->vector_elements; + unsigned location = fine_location / 4; + unsigned location_frac = fine_location % 4; + for (unsigned i = 0; i < components; ++i) + swizzle_values[i] = i + location_frac; + ir_dereference_variable *packed_deref = new(this->mem_ctx) + ir_dereference_variable(this->get_packed_varying(location, + unpacked_var, name)); + ir_swizzle *swizzle = new(this->mem_ctx) + ir_swizzle(packed_deref, swizzle_values, components); + if (this->mode == ir_var_out) { + ir_assignment *assignment = new(this->mem_ctx) + ir_assignment(swizzle, rvalue); + this->main_instructions->push_tail(assignment); + } else { + ir_assignment *assignment = new(this->mem_ctx) + ir_assignment(rvalue, swizzle); + this->main_instructions->push_head(assignment); + } + return fine_location + components; + } +} + +/** + * Recursively pack or unpack a varying for which we need to iterate over its + * constituent elements, accessing each one using an ir_dereference_array. + * This takes care of both arrays and matrices, since ir_dereference_array + * treats a matrix like an array of its column vectors. + */ +unsigned +lower_packed_varyings_visitor::lower_arraylike(ir_rvalue *rvalue, + unsigned array_size, + unsigned fine_location, + ir_variable *unpacked_var, + const char *name) +{ + for (unsigned i = 0; i < array_size; i++) { + if (i != 0) + rvalue = rvalue->clone(this->mem_ctx, NULL); + ir_constant *constant = new(this->mem_ctx) ir_constant(i); + ir_dereference_array *dereference_array = new(this->mem_ctx) + ir_dereference_array(rvalue, constant); + char *subscripted_name + = ralloc_asprintf(this->mem_ctx, "%s[%d]", name, i); + fine_location = this->lower_rvalue(dereference_array, fine_location, + unpacked_var, subscripted_name); + } + return fine_location; +} + +/** + * Retrieve the packed varying corresponding to the given varying location. + * If no packed varying has been created for the given varying location yet, + * create it and add it to the shader before returning it. + * + * The newly created varying inherits its base type (float, uint, or int) and + * interpolation parameters from \c unpacked_var. + */ +ir_variable * +lower_packed_varyings_visitor::get_packed_varying(unsigned location, + ir_variable *unpacked_var, + const char *name) +{ + unsigned slot = location - this->location_base; + assert(slot < locations_used); + if (this->packed_varyings[slot] == NULL) { + char *packed_name = ralloc_asprintf(this->mem_ctx, "packed:%s", name); + const glsl_type *packed_type = glsl_type::get_instance( + unpacked_var->type->get_scalar_type()->base_type, 4, 1); + ir_variable *packed_var = new(this->mem_ctx) + ir_variable(packed_type, packed_name, this->mode); + packed_var->centroid = unpacked_var->centroid; + packed_var->interpolation = unpacked_var->interpolation; + packed_var->location = location; + unpacked_var->insert_before(packed_var); + this->packed_varyings[slot] = packed_var; + } else { + ralloc_asprintf_append((char **) &this->packed_varyings[slot]->name, + ",%s", name); + } + return this->packed_varyings[slot]; +} + +bool +lower_packed_varyings_visitor::needs_lowering(ir_variable *var) +{ + /* Things composed of vec4's don't need lowering. Everything else does. */ + const glsl_type *type = var->type; + if (type->is_array()) + type = type->fields.array; + if (type->vector_elements == 4) + return false; + return true; +} + +void +lower_packed_varyings(void *mem_ctx, unsigned location_base, + unsigned locations_used, ir_variable_mode mode, + gl_shader *shader) +{ + exec_list *instructions = shader->ir; + ir_function *main_func = shader->symbols->get_function("main"); + exec_list void_parameters; + ir_function_signature *main_func_sig + = main_func->matching_signature(&void_parameters); + exec_list *main_instructions = &main_func_sig->body; + lower_packed_varyings_visitor visitor(mem_ctx, location_base, + locations_used, mode, + main_instructions); + visitor.run(instructions); +} diff --git a/mesalib/src/mapi/glapi/gen/gl_genexec.py b/mesalib/src/mapi/glapi/gen/gl_genexec.py index 593d1955b..da9ae716a 100644 --- a/mesalib/src/mapi/glapi/gen/gl_genexec.py +++ b/mesalib/src/mapi/glapi/gen/gl_genexec.py @@ -22,7 +22,7 @@ # IN THE SOFTWARE. # This script generates the file api_exec.c, which contains -# _mesa_create_exec_table(). It is responsible for populating all +# _mesa_initialize_exec_table(). It is responsible for populating all # entries in the "exec" dispatch table that aren't dynamic. import collections @@ -112,29 +112,26 @@ header = """/** /** - * Initialize a dispatch table with pointers to Mesa's immediate-mode - * commands. + * Initialize a context's exec table with pointers to Mesa's supported + * GL functions. * - * Pointers to glBegin()/glEnd() object commands and a few others - * are provided via the GLvertexformat interface. + * This function depends on ctx->Version. * * \param ctx GL context to which \c exec belongs. - * \param exec dispatch table. */ -struct _glapi_table * -_mesa_create_exec_table(struct gl_context *ctx) +void +_mesa_initialize_exec_table(struct gl_context *ctx) { struct _glapi_table *exec; - exec = _mesa_alloc_dispatch_table(_gloffset_COUNT); - if (exec == NULL) - return NULL; + exec = ctx->Exec; + assert(exec != NULL); + assert(ctx->Version > 0); """ footer = """ - return exec; } """ diff --git a/mesalib/src/mesa/Android.libmesa_glsl_utils.mk b/mesalib/src/mesa/Android.libmesa_glsl_utils.mk index 9beeda57f..9c5f3493c 100644 --- a/mesalib/src/mesa/Android.libmesa_glsl_utils.mk +++ b/mesalib/src/mesa/Android.libmesa_glsl_utils.mk @@ -35,6 +35,8 @@ include $(CLEAR_VARS) LOCAL_MODULE := libmesa_glsl_utils +LOCAL_C_INCLUDES := $(MESA_TOP)/src/glsl + LOCAL_SRC_FILES := \ main/hash_table.c \ program/prog_hash_table.c \ @@ -52,6 +54,8 @@ include $(CLEAR_VARS) LOCAL_MODULE := libmesa_glsl_utils LOCAL_IS_HOST_MODULE := true +LOCAL_C_INCLUDES := $(MESA_TOP)/src/glsl + LOCAL_SRC_FILES := \ main/hash_table.c \ program/prog_hash_table.c \ diff --git a/mesalib/src/mesa/drivers/dri/swrast/swrast.c b/mesalib/src/mesa/drivers/dri/swrast/swrast.c index 005ab08d4..c6b2f0df7 100644..100755 --- a/mesalib/src/mesa/drivers/dri/swrast/swrast.c +++ b/mesalib/src/mesa/drivers/dri/swrast/swrast.c @@ -36,12 +36,15 @@ #include <windows.h> #endif +#include "main/api_exec.h" #include "main/context.h" #include "main/extensions.h" #include "main/formats.h" #include "main/framebuffer.h" #include "main/imports.h" #include "main/renderbuffer.h" +#include "main/version.h" +#include "main/vtxfmt.h" #include "swrast/swrast.h" #include "swrast/s_renderbuffer.h" #include "swrast_setup/swrast_setup.h" @@ -791,6 +794,11 @@ dri_create_context(gl_api api, break; } + _mesa_compute_version(mesaCtx); + + _mesa_initialize_exec_table(mesaCtx); + _mesa_initialize_vbo_vtxfmt(mesaCtx); + *error = __DRI_CTX_ERROR_SUCCESS; return GL_TRUE; diff --git a/mesalib/src/mesa/drivers/windows/gdi/wmesa.c b/mesalib/src/mesa/drivers/windows/gdi/wmesa.c index 50347cf77..af9ae6be6 100644 --- a/mesalib/src/mesa/drivers/windows/gdi/wmesa.c +++ b/mesalib/src/mesa/drivers/windows/gdi/wmesa.c @@ -12,6 +12,7 @@ #include "main/framebuffer.h" #include "main/renderbuffer.h" #include "main/macros.h" +#include "main/vtxfmt.h" #include "drivers/common/driverfuncs.h" #include "drivers/common/meta.h" #include "vbo/vbo.h" @@ -637,6 +638,12 @@ WMesaContext WMesaCreateContext(HDC hDC, _swsetup_Wakeup(ctx); TNL_CONTEXT(ctx)->Driver.RunPipeline = _tnl_run_pipeline; + _mesa_compute_version(ctx); + + /* Exec table initialization requires the version to be computed */ + _mesa_initialize_exec_table(ctx); + _mesa_initialize_vbo_vtxfmt(ctx); + return c; } diff --git a/mesalib/src/mesa/main/api_exec.h b/mesalib/src/mesa/main/api_exec.h index 7d37ff754..8292c12de 100644 --- a/mesalib/src/mesa/main/api_exec.h +++ b/mesalib/src/mesa/main/api_exec.h @@ -33,8 +33,8 @@ struct gl_context; extern struct _glapi_table * _mesa_alloc_dispatch_table(int size); -extern struct _glapi_table * -_mesa_create_exec_table(struct gl_context *ctx); +extern void +_mesa_initialize_exec_table(struct gl_context *ctx); #endif diff --git a/mesalib/src/mesa/main/bufferobj.c b/mesalib/src/mesa/main/bufferobj.c index ce873ecd7..107711560 100644 --- a/mesalib/src/mesa/main/bufferobj.c +++ b/mesalib/src/mesa/main/bufferobj.c @@ -93,8 +93,8 @@ get_buffer_target(struct gl_context *ctx, GLenum target) } break; case GL_TEXTURE_BUFFER: - if (_mesa_is_desktop_gl(ctx) - && ctx->Extensions.ARB_texture_buffer_object) { + if (ctx->API == API_OPENGL_CORE && + ctx->Extensions.ARB_texture_buffer_object) { return &ctx->Texture.BufferObject; } break; diff --git a/mesalib/src/mesa/main/context.c b/mesalib/src/mesa/main/context.c index fa552e818..fc2db1271 100644 --- a/mesalib/src/mesa/main/context.c +++ b/mesalib/src/mesa/main/context.c @@ -935,8 +935,8 @@ _mesa_initialize_context(struct gl_context *ctx, return GL_FALSE; } - /* setup the API dispatch tables */ - ctx->Exec = _mesa_create_exec_table(ctx); + /* setup the API dispatch tables with all nop functions */ + ctx->Exec = _mesa_alloc_dispatch_table(_gloffset_COUNT); if (!ctx->Exec) { _mesa_reference_shared_state(ctx, &ctx->Shared, NULL); @@ -971,7 +971,6 @@ _mesa_initialize_context(struct gl_context *ctx, return GL_FALSE; } - _mesa_install_save_vtxfmt( ctx, &ctx->ListState.ListVtxfmt ); /* fall-through */ case API_OPENGL_CORE: break; @@ -1462,7 +1461,7 @@ _mesa_make_current( struct gl_context *newCtx, } if (newCtx->FirstTimeCurrent) { - _mesa_compute_version(newCtx); + assert(newCtx->Version > 0); newCtx->Extensions.String = _mesa_make_extension_string(newCtx); diff --git a/mesalib/src/mesa/main/extensions.c b/mesalib/src/mesa/main/extensions.c index 11cbea2b4..98711b395 100644 --- a/mesalib/src/mesa/main/extensions.c +++ b/mesalib/src/mesa/main/extensions.c @@ -126,7 +126,8 @@ static const struct extension extension_table[] = { { "GL_ARB_shadow", o(ARB_shadow), GLL, 2001 }, { "GL_ARB_sync", o(ARB_sync), GL, 2003 }, { "GL_ARB_texture_border_clamp", o(ARB_texture_border_clamp), GLL, 2000 }, - { "GL_ARB_texture_buffer_object", o(ARB_texture_buffer_object), GL, 2008 }, + { "GL_ARB_texture_buffer_object", o(ARB_texture_buffer_object), GLC, 2008 }, + { "GL_ARB_texture_buffer_object_rgb32", o(ARB_texture_buffer_object_rgb32), GLC, 2009 }, { "GL_ARB_texture_compression", o(dummy_true), GLL, 2000 }, { "GL_ARB_texture_compression_rgtc", o(ARB_texture_compression_rgtc), GL, 2004 }, { "GL_ARB_texture_cube_map", o(ARB_texture_cube_map), GLL, 1999 }, diff --git a/mesalib/src/mesa/main/get.c b/mesalib/src/mesa/main/get.c index 97dccd0ed..f3dbda2d3 100644 --- a/mesalib/src/mesa/main/get.c +++ b/mesalib/src/mesa/main/get.c @@ -129,6 +129,7 @@ enum value_extra { EXTRA_VERSION_31, EXTRA_VERSION_32, EXTRA_API_GL, + EXTRA_API_GL_CORE, EXTRA_API_ES2, EXTRA_NEW_BUFFERS, EXTRA_NEW_FRAG_CLAMP, @@ -283,6 +284,7 @@ static const int extra_GLSL_130[] = { }; static const int extra_texture_buffer_object[] = { + EXTRA_API_GL_CORE, EXTRA_VERSION_31, EXT(ARB_texture_buffer_object), EXTRA_END @@ -329,7 +331,6 @@ EXTRA_EXT2(ARB_vertex_program, ARB_fragment_program); EXTRA_EXT(ARB_geometry_shader4); EXTRA_EXT(ARB_color_buffer_float); EXTRA_EXT(EXT_framebuffer_sRGB); -EXTRA_EXT(ARB_texture_buffer_object); EXTRA_EXT(OES_EGL_image_external); EXTRA_EXT(ARB_blend_func_extended); EXTRA_EXT(ARB_uniform_buffer_object); @@ -879,6 +880,12 @@ check_extra(struct gl_context *ctx, const char *func, const struct value_desc *d enabled++; } break; + case EXTRA_API_GL_CORE: + if (ctx->API == API_OPENGL_CORE) { + total++; + enabled++; + } + break; case EXTRA_NEW_BUFFERS: if (ctx->NewState & _NEW_BUFFERS) _mesa_update_state(ctx); diff --git a/mesalib/src/mesa/main/glformats.c b/mesalib/src/mesa/main/glformats.c index fefa9c441..f33a0503d 100644 --- a/mesalib/src/mesa/main/glformats.c +++ b/mesalib/src/mesa/main/glformats.c @@ -308,6 +308,48 @@ _mesa_bytes_per_pixel(GLenum format, GLenum type) /** + * Get the number of bytes for a vertex attrib with the given number of + * components and type. + * + * \param comps number of components. + * \param type data type. + * + * \return bytes per attribute, or -1 if a bad comps/type combination was given. + */ +GLint +_mesa_bytes_per_vertex_attrib(GLint comps, GLenum type) +{ + switch (type) { + case GL_BYTE: + case GL_UNSIGNED_BYTE: + return comps * sizeof(GLubyte); + case GL_SHORT: + case GL_UNSIGNED_SHORT: + return comps * sizeof(GLshort); + case GL_INT: + case GL_UNSIGNED_INT: + return comps * sizeof(GLint); + case GL_FLOAT: + return comps * sizeof(GLfloat); + case GL_HALF_FLOAT_ARB: + return comps * sizeof(GLhalfARB); + case GL_DOUBLE: + return comps * sizeof(GLdouble); + case GL_FIXED: + return comps * sizeof(GLfixed); + case GL_INT_2_10_10_10_REV: + case GL_UNSIGNED_INT_2_10_10_10_REV: + if (comps == 4) + return sizeof(GLuint); + else + return -1; + default: + return -1; + } +} + + +/** * Test if the given format is an integer (non-normalized) format. */ GLboolean diff --git a/mesalib/src/mesa/main/glformats.h b/mesalib/src/mesa/main/glformats.h index 5d0995140..ccfb5e13c 100644 --- a/mesalib/src/mesa/main/glformats.h +++ b/mesalib/src/mesa/main/glformats.h @@ -49,6 +49,9 @@ _mesa_components_in_format( GLenum format ); extern GLint _mesa_bytes_per_pixel( GLenum format, GLenum type ); +extern GLint +_mesa_bytes_per_vertex_attrib(GLint comps, GLenum type); + extern GLboolean _mesa_is_type_integer(GLenum type); diff --git a/mesalib/src/mesa/main/mtypes.h b/mesalib/src/mesa/main/mtypes.h index 11a832281..67eaadd9f 100644 --- a/mesalib/src/mesa/main/mtypes.h +++ b/mesalib/src/mesa/main/mtypes.h @@ -2928,6 +2928,17 @@ struct gl_constants /** GL_ARB_map_buffer_alignment */ GLuint MinMapBufferAlignment; + + /** + * Disable varying packing. This is out of spec, but potentially useful + * for older platforms that supports a limited number of texture + * indirections--on these platforms, unpacking the varyings in the fragment + * shader increases the number of texture indirections by 1, which might + * make some shaders not executable at all. + * + * Drivers that support transform feedback must set this value to GL_FALSE. + */ + GLboolean DisableVaryingPacking; }; @@ -2978,6 +2989,7 @@ struct gl_extensions GLboolean ARB_sync; GLboolean ARB_texture_border_clamp; GLboolean ARB_texture_buffer_object; + GLboolean ARB_texture_buffer_object_rgb32; GLboolean ARB_texture_compression_rgtc; GLboolean ARB_texture_cube_map; GLboolean ARB_texture_cube_map_array; diff --git a/mesalib/src/mesa/main/texcompress.c b/mesalib/src/mesa/main/texcompress.c index 372a483fa..33c580a88 100644 --- a/mesalib/src/mesa/main/texcompress.c +++ b/mesalib/src/mesa/main/texcompress.c @@ -42,7 +42,6 @@ #include "texcompress_rgtc.h" #include "texcompress_s3tc.h" #include "texcompress_etc.h" -#include "swrast/s_context.h" /** @@ -523,129 +522,67 @@ _mesa_compressed_image_address(GLint col, GLint row, GLint img, /** - * Decompress a compressed texture image, returning a GL_RGBA/GL_FLOAT image. - * \param srcRowStride stride in bytes between rows of blocks in the - * compressed source image. + * Return a texel-fetch function for the given format, or NULL if + * invalid format. */ -void -_mesa_decompress_image(gl_format format, GLuint width, GLuint height, - const GLubyte *src, GLint srcRowStride, - GLfloat *dest) +compressed_fetch_func +_mesa_get_compressed_fetch_func(gl_format format) { - void (*fetch)(const struct swrast_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel); - struct swrast_texture_image texImage; /* dummy teximage */ - GLuint i, j; - GLuint bytes, bw, bh; - - bytes = _mesa_get_format_bytes(format); - _mesa_get_format_block_size(format, &bw, &bh); - - /* setup dummy texture image info */ - memset(&texImage, 0, sizeof(texImage)); - texImage.Map = (void *) src; - - /* XXX This line is a bit of a hack to adapt to the row stride - * convention used by the texture decompression functions. - */ - texImage.RowStride = srcRowStride * bh / bytes; - switch (format) { - /* DXT formats */ case MESA_FORMAT_RGB_DXT1: - fetch = _mesa_fetch_texel_rgb_dxt1; - break; case MESA_FORMAT_RGBA_DXT1: - fetch = _mesa_fetch_texel_rgba_dxt1; - break; case MESA_FORMAT_RGBA_DXT3: - fetch = _mesa_fetch_texel_rgba_dxt3; - break; case MESA_FORMAT_RGBA_DXT5: - fetch = _mesa_fetch_texel_rgba_dxt5; - break; - - /* FXT1 formats */ + return _mesa_get_dxt_fetch_func(format); case MESA_FORMAT_RGB_FXT1: - fetch = _mesa_fetch_texel_2d_f_rgb_fxt1; - break; case MESA_FORMAT_RGBA_FXT1: - fetch = _mesa_fetch_texel_2d_f_rgba_fxt1; - break; - - /* Red/RG formats */ + return _mesa_get_fxt_fetch_func(format); case MESA_FORMAT_RED_RGTC1: - fetch = _mesa_fetch_texel_red_rgtc1; - break; - case MESA_FORMAT_SIGNED_RED_RGTC1: - fetch = _mesa_fetch_texel_signed_red_rgtc1; - break; - case MESA_FORMAT_RG_RGTC2: - fetch = _mesa_fetch_texel_rg_rgtc2; - break; - case MESA_FORMAT_SIGNED_RG_RGTC2: - fetch = _mesa_fetch_texel_signed_rg_rgtc2; - break; - - /* L/LA formats */ case MESA_FORMAT_L_LATC1: - fetch = _mesa_fetch_texel_l_latc1; - break; + case MESA_FORMAT_SIGNED_RED_RGTC1: case MESA_FORMAT_SIGNED_L_LATC1: - fetch = _mesa_fetch_texel_signed_l_latc1; - break; + case MESA_FORMAT_RG_RGTC2: case MESA_FORMAT_LA_LATC2: - fetch = _mesa_fetch_texel_la_latc2; - break; + case MESA_FORMAT_SIGNED_RG_RGTC2: case MESA_FORMAT_SIGNED_LA_LATC2: - fetch = _mesa_fetch_texel_signed_la_latc2; - break; - - /* ETC1 formats */ + return _mesa_get_compressed_rgtc_func(format); case MESA_FORMAT_ETC1_RGB8: - fetch = _mesa_fetch_texel_2d_f_etc1_rgb8; - break; + return _mesa_get_etc_fetch_func(format); + default: + return NULL; + } +} - /* ETC2 formats */ - case MESA_FORMAT_ETC2_RGB8: - fetch = _mesa_fetch_texel_2d_f_etc2_rgb8; - break; - case MESA_FORMAT_ETC2_SRGB8: - fetch = _mesa_fetch_texel_2d_f_etc2_srgb8; - break; - case MESA_FORMAT_ETC2_RGBA8_EAC: - fetch = _mesa_fetch_texel_2d_f_etc2_rgba8_eac; - break; - case MESA_FORMAT_ETC2_SRGB8_ALPHA8_EAC: - fetch = _mesa_fetch_texel_2d_f_etc2_srgb8_alpha8_eac; - break; - case MESA_FORMAT_ETC2_R11_EAC: - fetch = _mesa_fetch_texel_2d_f_etc2_r11_eac; - break; - case MESA_FORMAT_ETC2_RG11_EAC: - fetch = _mesa_fetch_texel_2d_f_etc2_rg11_eac; - break; - case MESA_FORMAT_ETC2_SIGNED_R11_EAC: - fetch = _mesa_fetch_texel_2d_f_etc2_signed_r11_eac; - break; - case MESA_FORMAT_ETC2_SIGNED_RG11_EAC: - fetch = _mesa_fetch_texel_2d_f_etc2_signed_rg11_eac; - break; - case MESA_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1: - fetch = _mesa_fetch_texel_2d_f_etc2_rgb8_punchthrough_alpha1; - break; - case MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1: - fetch = _mesa_fetch_texel_2d_f_etc2_srgb8_punchthrough_alpha1; - break; - default: +/** + * Decompress a compressed texture image, returning a GL_RGBA/GL_FLOAT image. + * \param srcRowStride stride in bytes between rows of blocks in the + * compressed source image. + */ +void +_mesa_decompress_image(gl_format format, GLuint width, GLuint height, + const GLubyte *src, GLint srcRowStride, + GLfloat *dest) +{ + compressed_fetch_func fetch; + GLuint i, j; + GLuint bytes, bw, bh; + GLint stride; + + bytes = _mesa_get_format_bytes(format); + _mesa_get_format_block_size(format, &bw, &bh); + + fetch = _mesa_get_compressed_fetch_func(format); + if (!fetch) { _mesa_problem(NULL, "Unexpected format in _mesa_decompress_image()"); return; } + + stride = srcRowStride * bh / bytes; for (j = 0; j < height; j++) { for (i = 0; i < width; i++) { - fetch(&texImage, i, j, 0, dest); + fetch(src, NULL, stride, i, j, 0, dest); dest += 4; } } diff --git a/mesalib/src/mesa/main/texcompress.h b/mesalib/src/mesa/main/texcompress.h index 359b9168a..b45e7cf1b 100644 --- a/mesalib/src/mesa/main/texcompress.h +++ b/mesalib/src/mesa/main/texcompress.h @@ -48,6 +48,18 @@ _mesa_compressed_image_address(GLint col, GLint row, GLint img, gl_format mesaFormat, GLsizei width, const GLubyte *image); + +/** A function to fetch one texel from a compressed texture */ +typedef void (*compressed_fetch_func)(const GLubyte *map, + const GLuint imageOffsets[], + GLint rowStride, + GLint i, GLint j, GLint k, + GLfloat *texel); + +extern compressed_fetch_func +_mesa_get_compressed_fetch_func(gl_format format); + + extern void _mesa_decompress_image(gl_format format, GLuint width, GLuint height, const GLubyte *src, GLint srcRowStride, diff --git a/mesalib/src/mesa/main/texcompress_etc.c b/mesalib/src/mesa/main/texcompress_etc.c index 73d2fa4fe..7ad4ddeb6 100644 --- a/mesalib/src/mesa/main/texcompress_etc.c +++ b/mesalib/src/mesa/main/texcompress_etc.c @@ -43,9 +43,9 @@ #include "texcompress_etc.h" #include "texstore.h" #include "macros.h" -#include "swrast/s_context.h" #include "format_unpack.h" + struct etc2_block { int distance; uint64_t pixel_indices[2]; @@ -113,25 +113,6 @@ _mesa_texstore_etc1_rgb8(TEXSTORE_PARAMS) return GL_FALSE; } -void -_mesa_fetch_texel_2d_f_etc1_rgb8(const struct swrast_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel) -{ - struct etc1_block block; - GLubyte dst[3]; - const GLubyte *src; - - src = (const GLubyte *) texImage->Map + - (((texImage->RowStride + 3) / 4) * (j / 4) + (i / 4)) * 8; - - etc1_parse_block(&block, src); - etc1_fetch_texel(&block, i % 4, j % 4, dst); - - texel[RCOMP] = UBYTE_TO_FLOAT(dst[0]); - texel[GCOMP] = UBYTE_TO_FLOAT(dst[1]); - texel[BCOMP] = UBYTE_TO_FLOAT(dst[2]); - texel[ACOMP] = 1.0f; -} /** * Decode texture data in format `MESA_FORMAT_ETC1_RGB8` to @@ -231,7 +212,7 @@ etc2_base_color1_h_mode(const uint8_t *in, GLuint index) break; } return ((x << 4) | (x & 0xf)); - } +} static uint8_t etc2_base_color2_h_mode(const uint8_t *in, GLuint index) @@ -253,7 +234,7 @@ etc2_base_color2_h_mode(const uint8_t *in, GLuint index) break; } return ((x << 4) | (x & 0xf)); - } +} static uint8_t etc2_base_color_o_planar(const uint8_t *in, GLuint index) @@ -468,7 +449,7 @@ etc2_rgb8_parse_block(struct etc2_block *block, */ block->base_colors[0][i] = etc1_base_color_diff_hi(src[i]); block->base_colors[1][i] = etc1_base_color_diff_lo(src[i]); - } + } } if (block->is_ind_mode || block->is_diff_mode) { @@ -756,10 +737,10 @@ etc2_unpack_srgb8(uint8_t *dst_row, } } src += bs; - } + } src_row += src_stride; - } + } } static void @@ -792,10 +773,10 @@ etc2_unpack_rgba8(uint8_t *dst_row, } } src += bs; - } + } src_row += src_stride; - } + } } static void @@ -836,10 +817,10 @@ etc2_unpack_srgb8_alpha8(uint8_t *dst_row, } } src += bs; - } + } src_row += src_stride; - } + } } static void @@ -871,10 +852,10 @@ etc2_unpack_r11(uint8_t *dst_row, } } src += bs; - } + } src_row += src_stride; - } + } } static void @@ -919,10 +900,10 @@ etc2_unpack_rg11(uint8_t *dst_row, } } src += bs; - } + } src_row += src_stride; - } + } } static void @@ -955,10 +936,10 @@ etc2_unpack_signed_r11(uint8_t *dst_row, } } src += bs; - } + } src_row += src_stride; - } + } } static void @@ -1003,10 +984,10 @@ etc2_unpack_signed_rg11(uint8_t *dst_row, } } src += bs; - } + } src_row += src_stride; - } + } } static void @@ -1166,16 +1147,112 @@ _mesa_texstore_etc2_srgb8_punchthrough_alpha1(TEXSTORE_PARAMS) return GL_FALSE; } + +/** + * Decode texture data in any one of following formats: + * `MESA_FORMAT_ETC2_RGB8` + * `MESA_FORMAT_ETC2_SRGB8` + * `MESA_FORMAT_ETC2_RGBA8_EAC` + * `MESA_FORMAT_ETC2_SRGB8_ALPHA8_EAC` + * `MESA_FORMAT_ETC2_R11_EAC` + * `MESA_FORMAT_ETC2_RG11_EAC` + * `MESA_FORMAT_ETC2_SIGNED_R11_EAC` + * `MESA_FORMAT_ETC2_SIGNED_RG11_EAC` + * `MESA_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1` + * `MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1` + * + * The size of the source data must be a multiple of the ETC2 block size + * even if the texture image's dimensions are not aligned to 4. + * + * \param src_width in pixels + * \param src_height in pixels + * \param dst_stride in bytes + */ + void -_mesa_fetch_texel_2d_f_etc2_rgb8(const struct swrast_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel) +_mesa_unpack_etc2_format(uint8_t *dst_row, + unsigned dst_stride, + const uint8_t *src_row, + unsigned src_stride, + unsigned src_width, + unsigned src_height, + gl_format format) +{ + if (format == MESA_FORMAT_ETC2_RGB8) + etc2_unpack_rgb8(dst_row, dst_stride, + src_row, src_stride, + src_width, src_height); + else if (format == MESA_FORMAT_ETC2_SRGB8) + etc2_unpack_srgb8(dst_row, dst_stride, + src_row, src_stride, + src_width, src_height); + else if (format == MESA_FORMAT_ETC2_RGBA8_EAC) + etc2_unpack_rgba8(dst_row, dst_stride, + src_row, src_stride, + src_width, src_height); + else if (format == MESA_FORMAT_ETC2_SRGB8_ALPHA8_EAC) + etc2_unpack_srgb8_alpha8(dst_row, dst_stride, + src_row, src_stride, + src_width, src_height); + else if (format == MESA_FORMAT_ETC2_R11_EAC) + etc2_unpack_r11(dst_row, dst_stride, + src_row, src_stride, + src_width, src_height); + else if (format == MESA_FORMAT_ETC2_RG11_EAC) + etc2_unpack_rg11(dst_row, dst_stride, + src_row, src_stride, + src_width, src_height); + else if (format == MESA_FORMAT_ETC2_SIGNED_R11_EAC) + etc2_unpack_signed_r11(dst_row, dst_stride, + src_row, src_stride, + src_width, src_height); + else if (format == MESA_FORMAT_ETC2_SIGNED_RG11_EAC) + etc2_unpack_signed_rg11(dst_row, dst_stride, + src_row, src_stride, + src_width, src_height); + else if (format == MESA_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1) + etc2_unpack_rgb8_punchthrough_alpha1(dst_row, dst_stride, + src_row, src_stride, + src_width, src_height); + else if (format == MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1) + etc2_unpack_srgb8_punchthrough_alpha1(dst_row, dst_stride, + src_row, src_stride, + src_width, src_height); +} + + + +static void +fetch_etc1_rgb8(const GLubyte *map, const GLuint imageOffsets[], + GLint rowStride, GLint i, GLint j, GLint k, + GLfloat *texel) +{ + struct etc1_block block; + GLubyte dst[3]; + const GLubyte *src; + + src = map + (((rowStride + 3) / 4) * (j / 4) + (i / 4)) * 8; + + etc1_parse_block(&block, src); + etc1_fetch_texel(&block, i % 4, j % 4, dst); + + texel[RCOMP] = UBYTE_TO_FLOAT(dst[0]); + texel[GCOMP] = UBYTE_TO_FLOAT(dst[1]); + texel[BCOMP] = UBYTE_TO_FLOAT(dst[2]); + texel[ACOMP] = 1.0f; +} + + +static void +fetch_etc2_rgb8(const GLubyte *map, const GLuint imageOffsets[], + GLint rowStride, GLint i, GLint j, GLint k, + GLfloat *texel) { struct etc2_block block; uint8_t dst[3]; const uint8_t *src; - src = texImage->Map + - (((texImage->RowStride + 3) / 4) * (j / 4) + (i / 4)) * 8; + src = map + (((rowStride + 3) / 4) * (j / 4) + (i / 4)) * 8; etc2_rgb8_parse_block(&block, src, false /* punchthrough_alpha */); @@ -1188,16 +1265,16 @@ _mesa_fetch_texel_2d_f_etc2_rgb8(const struct swrast_texture_image *texImage, texel[ACOMP] = 1.0f; } -void -_mesa_fetch_texel_2d_f_etc2_srgb8(const struct swrast_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel) +static void +fetch_etc2_srgb8(const GLubyte *map, const GLuint imageOffsets[], + GLint rowStride, GLint i, GLint j, GLint k, + GLfloat *texel) { struct etc2_block block; uint8_t dst[3]; const uint8_t *src; - src = texImage->Map + - (((texImage->RowStride + 3) / 4) * (j / 4) + (i / 4)) * 8; + src = map + (((rowStride + 3) / 4) * (j / 4) + (i / 4)) * 8; etc2_rgb8_parse_block(&block, src, false /* punchthrough_alpha */); @@ -1210,16 +1287,16 @@ _mesa_fetch_texel_2d_f_etc2_srgb8(const struct swrast_texture_image *texImage, texel[ACOMP] = 1.0f; } -void -_mesa_fetch_texel_2d_f_etc2_rgba8_eac(const struct swrast_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel) +static void +fetch_etc2_rgba8_eac(const GLubyte *map, const GLuint imageOffsets[], + GLint rowStride, GLint i, GLint j, GLint k, + GLfloat *texel) { struct etc2_block block; uint8_t dst[4]; const uint8_t *src; - src = texImage->Map + - (((texImage->RowStride + 3) / 4) * (j / 4) + (i / 4)) * 16; + src = map + (((rowStride + 3) / 4) * (j / 4) + (i / 4)) * 16; etc2_rgba8_parse_block(&block, src); etc2_rgba8_fetch_texel(&block, i % 4, j % 4, dst); @@ -1230,18 +1307,16 @@ _mesa_fetch_texel_2d_f_etc2_rgba8_eac(const struct swrast_texture_image *texImag texel[ACOMP] = UBYTE_TO_FLOAT(dst[3]); } -void -_mesa_fetch_texel_2d_f_etc2_srgb8_alpha8_eac(const struct - swrast_texture_image *texImage, - GLint i, GLint j, - GLint k, GLfloat *texel) +static void +fetch_etc2_srgb8_alpha8_eac(const GLubyte *map, const GLuint imageOffsets[], + GLint rowStride, GLint i, GLint j, GLint k, + GLfloat *texel) { struct etc2_block block; uint8_t dst[4]; const uint8_t *src; - src = texImage->Map + - (((texImage->RowStride + 3) / 4) * (j / 4) + (i / 4)) * 16; + src = map + (((rowStride + 3) / 4) * (j / 4) + (i / 4)) * 16; etc2_rgba8_parse_block(&block, src); etc2_rgba8_fetch_texel(&block, i % 4, j % 4, dst); @@ -1252,16 +1327,16 @@ _mesa_fetch_texel_2d_f_etc2_srgb8_alpha8_eac(const struct texel[ACOMP] = UBYTE_TO_FLOAT(dst[3]); } -void -_mesa_fetch_texel_2d_f_etc2_r11_eac(const struct swrast_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel) +static void +fetch_etc2_r11_eac(const GLubyte *map, const GLuint imageOffsets[], + GLint rowStride, GLint i, GLint j, GLint k, + GLfloat *texel) { struct etc2_block block; GLushort dst; const uint8_t *src; - src = texImage->Map + - (((texImage->RowStride + 3) / 4) * (j / 4) + (i / 4)) * 8; + src = map + (((rowStride + 3) / 4) * (j / 4) + (i / 4)) * 8; etc2_r11_parse_block(&block, src); etc2_r11_fetch_texel(&block, i % 4, j % 4, (uint8_t *)&dst); @@ -1272,18 +1347,16 @@ _mesa_fetch_texel_2d_f_etc2_r11_eac(const struct swrast_texture_image *texImage, texel[ACOMP] = 1.0f; } -void -_mesa_fetch_texel_2d_f_etc2_rg11_eac(const struct - swrast_texture_image *texImage, - GLint i, GLint j, - GLint k, GLfloat *texel) +static void +fetch_etc2_rg11_eac(const GLubyte *map, const GLuint imageOffsets[], + GLint rowStride, GLint i, GLint j, GLint k, + GLfloat *texel) { struct etc2_block block; GLushort dst[2]; const uint8_t *src; - src = texImage->Map + - (((texImage->RowStride + 3) / 4) * (j / 4) + (i / 4)) * 16; + src = map + (((rowStride + 3) / 4) * (j / 4) + (i / 4)) * 16; /* red component */ etc2_r11_parse_block(&block, src); @@ -1299,16 +1372,16 @@ _mesa_fetch_texel_2d_f_etc2_rg11_eac(const struct texel[ACOMP] = 1.0f; } -void -_mesa_fetch_texel_2d_f_etc2_signed_r11_eac(const struct swrast_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel) +static void +fetch_etc2_signed_r11_eac(const GLubyte *map, const GLuint imageOffsets[], + GLint rowStride, GLint i, GLint j, GLint k, + GLfloat *texel) { struct etc2_block block; GLushort dst; const uint8_t *src; - src = texImage->Map + - (((texImage->RowStride + 3) / 4) * (j / 4) + (i / 4)) * 8; + src = map + (((rowStride + 3) / 4) * (j / 4) + (i / 4)) * 8; etc2_r11_parse_block(&block, src); etc2_signed_r11_fetch_texel(&block, i % 4, j % 4, (uint8_t *)&dst); @@ -1319,16 +1392,16 @@ _mesa_fetch_texel_2d_f_etc2_signed_r11_eac(const struct swrast_texture_image *te texel[ACOMP] = 1.0f; } -void -_mesa_fetch_texel_2d_f_etc2_signed_rg11_eac(const struct swrast_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel) +static void +fetch_etc2_signed_rg11_eac(const GLubyte *map, const GLuint imageOffsets[], + GLint rowStride, GLint i, GLint j, GLint k, + GLfloat *texel) { struct etc2_block block; GLushort dst[2]; const uint8_t *src; - src = texImage->Map + - (((texImage->RowStride + 3) / 4) * (j / 4) + (i / 4)) * 16; + src = map + (((rowStride + 3) / 4) * (j / 4) + (i / 4)) * 16; /* red component */ etc2_r11_parse_block(&block, src); @@ -1344,18 +1417,17 @@ _mesa_fetch_texel_2d_f_etc2_signed_rg11_eac(const struct swrast_texture_image *t texel[ACOMP] = 1.0f; } -void -_mesa_fetch_texel_2d_f_etc2_rgb8_punchthrough_alpha1( - const struct swrast_texture_image *texImage, - GLint i, GLint j, - GLint k, GLfloat *texel) +static void +fetch_etc2_rgb8_punchthrough_alpha1(const GLubyte *map, + const GLuint imageOffsets[], + GLint rowStride, GLint i, GLint j, GLint k, + GLfloat *texel) { struct etc2_block block; uint8_t dst[4]; const uint8_t *src; - src = texImage->Map + - (((texImage->RowStride + 3) / 4) * (j / 4) + (i / 4)) * 8; + src = map + (((rowStride + 3) / 4) * (j / 4) + (i / 4)) * 8; etc2_rgb8_parse_block(&block, src, true /* punchthrough alpha */); @@ -1367,18 +1439,18 @@ _mesa_fetch_texel_2d_f_etc2_rgb8_punchthrough_alpha1( texel[ACOMP] = UBYTE_TO_FLOAT(dst[3]); } -void -_mesa_fetch_texel_2d_f_etc2_srgb8_punchthrough_alpha1( - const struct swrast_texture_image *texImage, - GLint i, GLint j, - GLint k, GLfloat *texel) +static void +fetch_etc2_srgb8_punchthrough_alpha1(const GLubyte *map, + const GLuint imageOffsets[], + GLint rowStride, + GLint i, GLint j, GLint k, + GLfloat *texel) { struct etc2_block block; uint8_t dst[4]; const uint8_t *src; - src = texImage->Map + - (((texImage->RowStride + 3) / 4) * (j / 4) + (i / 4)) * 8; + src = map + (((rowStride + 3) / 4) * (j / 4) + (i / 4)) * 8; etc2_rgb8_parse_block(&block, src, true /* punchthrough alpha */); @@ -1390,74 +1462,34 @@ _mesa_fetch_texel_2d_f_etc2_srgb8_punchthrough_alpha1( texel[ACOMP] = UBYTE_TO_FLOAT(dst[3]); } -/** - * Decode texture data in any one of following formats: - * `MESA_FORMAT_ETC2_RGB8` - * `MESA_FORMAT_ETC2_SRGB8` - * `MESA_FORMAT_ETC2_RGBA8_EAC` - * `MESA_FORMAT_ETC2_SRGB8_ALPHA8_EAC` - * `MESA_FORMAT_ETC2_R11_EAC` - * `MESA_FORMAT_ETC2_RG11_EAC` - * `MESA_FORMAT_ETC2_SIGNED_R11_EAC` - * `MESA_FORMAT_ETC2_SIGNED_RG11_EAC` - * `MESA_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1` - * `MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1` - * - * The size of the source data must be a multiple of the ETC2 block size - * even if the texture image's dimensions are not aligned to 4. - * - * \param src_width in pixels - * \param src_height in pixels - * \param dst_stride in bytes - */ -void -_mesa_unpack_etc2_format(uint8_t *dst_row, - unsigned dst_stride, - const uint8_t *src_row, - unsigned src_stride, - unsigned src_width, - unsigned src_height, - gl_format format) +compressed_fetch_func +_mesa_get_etc_fetch_func(gl_format format) { - if (format == MESA_FORMAT_ETC2_RGB8) - etc2_unpack_rgb8(dst_row, dst_stride, - src_row, src_stride, - src_width, src_height); - else if (format == MESA_FORMAT_ETC2_SRGB8) - etc2_unpack_srgb8(dst_row, dst_stride, - src_row, src_stride, - src_width, src_height); - else if (format == MESA_FORMAT_ETC2_RGBA8_EAC) - etc2_unpack_rgba8(dst_row, dst_stride, - src_row, src_stride, - src_width, src_height); - else if (format == MESA_FORMAT_ETC2_SRGB8_ALPHA8_EAC) - etc2_unpack_srgb8_alpha8(dst_row, dst_stride, - src_row, src_stride, - src_width, src_height); - else if (format == MESA_FORMAT_ETC2_R11_EAC) - etc2_unpack_r11(dst_row, dst_stride, - src_row, src_stride, - src_width, src_height); - else if (format == MESA_FORMAT_ETC2_RG11_EAC) - etc2_unpack_rg11(dst_row, dst_stride, - src_row, src_stride, - src_width, src_height); - else if (format == MESA_FORMAT_ETC2_SIGNED_R11_EAC) - etc2_unpack_signed_r11(dst_row, dst_stride, - src_row, src_stride, - src_width, src_height); - else if (format == MESA_FORMAT_ETC2_SIGNED_RG11_EAC) - etc2_unpack_signed_rg11(dst_row, dst_stride, - src_row, src_stride, - src_width, src_height); - else if (format == MESA_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1) - etc2_unpack_rgb8_punchthrough_alpha1(dst_row, dst_stride, - src_row, src_stride, - src_width, src_height); - else if (format == MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1) - etc2_unpack_srgb8_punchthrough_alpha1(dst_row, dst_stride, - src_row, src_stride, - src_width, src_height); + switch (format) { + case MESA_FORMAT_ETC1_RGB8: + return fetch_etc1_rgb8; + case MESA_FORMAT_ETC2_RGB8: + return fetch_etc2_rgb8; + case MESA_FORMAT_ETC2_SRGB8: + return fetch_etc2_srgb8; + case MESA_FORMAT_ETC2_RGBA8_EAC: + return fetch_etc2_rgba8_eac; + case MESA_FORMAT_ETC2_SRGB8_ALPHA8_EAC: + return fetch_etc2_srgb8_alpha8_eac; + case MESA_FORMAT_ETC2_R11_EAC: + return fetch_etc2_r11_eac; + case MESA_FORMAT_ETC2_RG11_EAC: + return fetch_etc2_rg11_eac; + case MESA_FORMAT_ETC2_SIGNED_R11_EAC: + return fetch_etc2_signed_r11_eac; + case MESA_FORMAT_ETC2_SIGNED_RG11_EAC: + return fetch_etc2_signed_rg11_eac; + case MESA_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1: + return fetch_etc2_rgb8_punchthrough_alpha1; + case MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1: + return fetch_etc2_srgb8_punchthrough_alpha1; + default: + return NULL; + } } diff --git a/mesalib/src/mesa/main/texcompress_etc.h b/mesalib/src/mesa/main/texcompress_etc.h index 5e086d4e7..503d0388a 100644 --- a/mesalib/src/mesa/main/texcompress_etc.h +++ b/mesalib/src/mesa/main/texcompress_etc.h @@ -27,9 +27,9 @@ #include <inttypes.h> #include "glheader.h" #include "mfeatures.h" +#include "texcompress.h" #include "texstore.h" -struct swrast_texture_image; GLboolean _mesa_texstore_etc1_rgb8(TEXSTORE_PARAMS); @@ -65,50 +65,6 @@ GLboolean _mesa_texstore_etc2_srgb8_punchthrough_alpha1(TEXSTORE_PARAMS); void -_mesa_fetch_texel_2d_f_etc1_rgb8(const struct swrast_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel); -void -_mesa_fetch_texel_2d_f_etc2_rgb8(const struct swrast_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel); -void -_mesa_fetch_texel_2d_f_etc2_srgb8(const struct swrast_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel); - -void -_mesa_fetch_texel_2d_f_etc2_rgba8_eac(const struct swrast_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel); -void -_mesa_fetch_texel_2d_f_etc2_srgb8_alpha8_eac(const struct - swrast_texture_image *texImage, - GLint i, GLint j, - GLint k, GLfloat *texel); -void -_mesa_fetch_texel_2d_f_etc2_r11_eac(const struct swrast_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel); -void -_mesa_fetch_texel_2d_f_etc2_rg11_eac(const struct swrast_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel); -void -_mesa_fetch_texel_2d_f_etc2_signed_r11_eac(const struct - swrast_texture_image *texImage, - GLint i, GLint j, - GLint k, GLfloat *texel); -void -_mesa_fetch_texel_2d_f_etc2_signed_rg11_eac(const struct - swrast_texture_image *texImage, - GLint i, GLint j, - GLint k, GLfloat *texel); -void -_mesa_fetch_texel_2d_f_etc2_rgb8_punchthrough_alpha1( - const struct swrast_texture_image *texImage, - GLint i, GLint j, - GLint k, GLfloat *texel); -void -_mesa_fetch_texel_2d_f_etc2_srgb8_punchthrough_alpha1( - const struct swrast_texture_image *texImage, - GLint i, GLint j, - GLint k, GLfloat *texel); -void _mesa_etc1_unpack_rgba8888(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, @@ -123,4 +79,8 @@ _mesa_unpack_etc2_format(uint8_t *dst_row, unsigned src_width, unsigned src_height, gl_format format); + +compressed_fetch_func +_mesa_get_etc_fetch_func(gl_format format); + #endif diff --git a/mesalib/src/mesa/main/texcompress_fxt1.c b/mesalib/src/mesa/main/texcompress_fxt1.c index eeed78891..f7254f92e 100644 --- a/mesalib/src/mesa/main/texcompress_fxt1.c +++ b/mesalib/src/mesa/main/texcompress_fxt1.c @@ -39,7 +39,6 @@ #include "texcompress.h" #include "texcompress_fxt1.h" #include "texstore.h" -#include "swrast/s_context.h" static void @@ -151,37 +150,6 @@ _mesa_texstore_rgba_fxt1(TEXSTORE_PARAMS) } -void -_mesa_fetch_texel_2d_f_rgba_fxt1( const struct swrast_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel ) -{ - /* just sample as GLubyte and convert to float here */ - GLubyte rgba[4]; - (void) k; - fxt1_decode_1(texImage->Map, texImage->RowStride, i, j, rgba); - texel[RCOMP] = UBYTE_TO_FLOAT(rgba[RCOMP]); - texel[GCOMP] = UBYTE_TO_FLOAT(rgba[GCOMP]); - texel[BCOMP] = UBYTE_TO_FLOAT(rgba[BCOMP]); - texel[ACOMP] = UBYTE_TO_FLOAT(rgba[ACOMP]); -} - - -void -_mesa_fetch_texel_2d_f_rgb_fxt1( const struct swrast_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel ) -{ - /* just sample as GLubyte and convert to float here */ - GLubyte rgba[4]; - (void) k; - fxt1_decode_1(texImage->Map, texImage->RowStride, i, j, rgba); - texel[RCOMP] = UBYTE_TO_FLOAT(rgba[RCOMP]); - texel[GCOMP] = UBYTE_TO_FLOAT(rgba[GCOMP]); - texel[BCOMP] = UBYTE_TO_FLOAT(rgba[BCOMP]); - texel[ACOMP] = 1.0F; -} - - - /***************************************************************************\ * FXT1 encoder * @@ -1643,3 +1611,45 @@ fxt1_decode_1 (const void *texture, GLint stride, /* in pixels */ decode_1[mode](code, t, rgba); } + + + + +static void +fetch_rgb_fxt1(const GLubyte *map, const GLuint imageOffsets[], + GLint rowStride, GLint i, GLint j, GLint k, GLfloat *texel) +{ + GLubyte rgba[4]; + fxt1_decode_1(map, rowStride, i, j, rgba); + texel[RCOMP] = UBYTE_TO_FLOAT(rgba[RCOMP]); + texel[GCOMP] = UBYTE_TO_FLOAT(rgba[GCOMP]); + texel[BCOMP] = UBYTE_TO_FLOAT(rgba[BCOMP]); + texel[ACOMP] = 1.0F; +} + + +static void +fetch_rgba_fxt1(const GLubyte *map, const GLuint imageOffsets[], + GLint rowStride, GLint i, GLint j, GLint k, GLfloat *texel) +{ + GLubyte rgba[4]; + fxt1_decode_1(map, rowStride, i, j, rgba); + texel[RCOMP] = UBYTE_TO_FLOAT(rgba[RCOMP]); + texel[GCOMP] = UBYTE_TO_FLOAT(rgba[GCOMP]); + texel[BCOMP] = UBYTE_TO_FLOAT(rgba[BCOMP]); + texel[ACOMP] = UBYTE_TO_FLOAT(rgba[ACOMP]); +} + + +compressed_fetch_func +_mesa_get_fxt_fetch_func(gl_format format) +{ + switch (format) { + case MESA_FORMAT_RGB_FXT1: + return fetch_rgb_fxt1; + case MESA_FORMAT_RGBA_FXT1: + return fetch_rgba_fxt1; + default: + return NULL; + } +} diff --git a/mesalib/src/mesa/main/texcompress_fxt1.h b/mesalib/src/mesa/main/texcompress_fxt1.h index 2a8b8d653..5949df90f 100644 --- a/mesalib/src/mesa/main/texcompress_fxt1.h +++ b/mesalib/src/mesa/main/texcompress_fxt1.h @@ -29,7 +29,6 @@ #include "mfeatures.h" #include "texstore.h" -struct swrast_texture_image; extern GLboolean _mesa_texstore_rgb_fxt1(TEXSTORE_PARAMS); @@ -37,12 +36,8 @@ _mesa_texstore_rgb_fxt1(TEXSTORE_PARAMS); extern GLboolean _mesa_texstore_rgba_fxt1(TEXSTORE_PARAMS); -extern void -_mesa_fetch_texel_2d_f_rgba_fxt1(const struct swrast_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel); -extern void -_mesa_fetch_texel_2d_f_rgb_fxt1(const struct swrast_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel); +compressed_fetch_func +_mesa_get_fxt_fetch_func(gl_format format); #endif /* TEXCOMPRESS_FXT1_H */ diff --git a/mesalib/src/mesa/main/texcompress_rgtc.c b/mesalib/src/mesa/main/texcompress_rgtc.c index 5773459d7..fa9172aa2 100644 --- a/mesalib/src/mesa/main/texcompress_rgtc.c +++ b/mesalib/src/mesa/main/texcompress_rgtc.c @@ -43,7 +43,6 @@ #include "texcompress.h" #include "texcompress_rgtc.h" #include "texstore.h" -#include "swrast/s_context.h" #define RGTC_DEBUG 0 @@ -291,113 +290,120 @@ _mesa_texstore_signed_rg_rgtc2(TEXSTORE_PARAMS) return GL_TRUE; } -void -_mesa_fetch_texel_red_rgtc1(const struct swrast_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel) + +#define TAG(x) unsigned_##x + +#define TYPE GLubyte +#define T_MIN 0 +#define T_MAX 0xff + +#include "texcompress_rgtc_tmp.h" + +#undef TAG +#undef TYPE +#undef T_MIN +#undef T_MAX + +#define TAG(x) signed_##x +#define TYPE GLbyte +#define T_MIN (GLbyte)-128 +#define T_MAX (GLbyte)127 + +#include "texcompress_rgtc_tmp.h" + +#undef TAG +#undef TYPE +#undef T_MIN +#undef T_MAX + + + +static void +fetch_red_rgtc1(const GLubyte *map, const GLuint imageOffsets[], + GLint rowStride, GLint i, GLint j, GLint k, GLfloat *texel) { GLubyte red; - GLint sliceOffset = k ? texImage->ImageOffsets[k] / 2 : 0; - unsigned_fetch_texel_rgtc(texImage->RowStride, - texImage->Map + sliceOffset, - i, j, &red, 1); + GLuint sliceOffset = k ? imageOffsets[k] / 2 : 0; + unsigned_fetch_texel_rgtc(rowStride, map + sliceOffset, i, j, &red, 1); texel[RCOMP] = UBYTE_TO_FLOAT(red); texel[GCOMP] = 0.0; texel[BCOMP] = 0.0; texel[ACOMP] = 1.0; } -void -_mesa_fetch_texel_signed_red_rgtc1(const struct swrast_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel) +static void +fetch_l_latc1(const GLubyte *map, const GLuint imageOffsets[], + GLint rowStride, GLint i, GLint j, GLint k, GLfloat *texel) { - GLbyte red; - GLint sliceOffset = k ? texImage->ImageOffsets[k] / 2 : 0; - signed_fetch_texel_rgtc(texImage->RowStride, - (GLbyte *)(texImage->Map) + sliceOffset, - i, j, &red, 1); - texel[RCOMP] = BYTE_TO_FLOAT_TEX(red); - texel[GCOMP] = 0.0; - texel[BCOMP] = 0.0; - texel[ACOMP] = 1.0; -} - -void -_mesa_fetch_texel_rg_rgtc2(const struct swrast_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel) -{ - GLubyte red, green; - GLint sliceOffset = k ? texImage->ImageOffsets[k] : 0; - unsigned_fetch_texel_rgtc(texImage->RowStride, - texImage->Map + sliceOffset, - i, j, &red, 2); - unsigned_fetch_texel_rgtc(texImage->RowStride, - texImage->Map + sliceOffset + 8, - i, j, &green, 2); - texel[RCOMP] = UBYTE_TO_FLOAT(red); - texel[GCOMP] = UBYTE_TO_FLOAT(green); - texel[BCOMP] = 0.0; + GLubyte red; + GLuint sliceOffset = k ? imageOffsets[k] / 2 : 0; + unsigned_fetch_texel_rgtc(rowStride, map + sliceOffset, i, j, &red, 1); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = UBYTE_TO_FLOAT(red); texel[ACOMP] = 1.0; } -void -_mesa_fetch_texel_signed_rg_rgtc2(const struct swrast_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel) +static void +fetch_signed_red_rgtc1(const GLubyte *map, const GLuint imageOffsets[], + GLint rowStride, GLint i, GLint j, GLint k, + GLfloat *texel) { - GLbyte red, green; - GLint sliceOffset = k ? texImage->ImageOffsets[k] : 0; - signed_fetch_texel_rgtc(texImage->RowStride, - (GLbyte *)(texImage->Map) + sliceOffset, - i, j, &red, 2); - signed_fetch_texel_rgtc(texImage->RowStride, - (GLbyte *)(texImage->Map) + sliceOffset + 8, - i, j, &green, 2); + GLbyte red; + GLuint sliceOffset = k ? imageOffsets[k] / 2 : 0; + signed_fetch_texel_rgtc(rowStride, (const GLbyte *) map + sliceOffset, + i, j, &red, 1); texel[RCOMP] = BYTE_TO_FLOAT_TEX(red); - texel[GCOMP] = BYTE_TO_FLOAT_TEX(green); + texel[GCOMP] = 0.0; texel[BCOMP] = 0.0; texel[ACOMP] = 1.0; } -void -_mesa_fetch_texel_l_latc1(const struct swrast_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel) +static void +fetch_signed_l_latc1(const GLubyte *map, const GLuint imageOffsets[], + GLint rowStride, GLint i, GLint j, GLint k, + GLfloat *texel) { GLubyte red; - GLint sliceOffset = k ? texImage->ImageOffsets[k] / 2 : 0; - unsigned_fetch_texel_rgtc(texImage->RowStride, - texImage->Map + sliceOffset, - i, j, &red, 1); + GLuint sliceOffset = k ? imageOffsets[k] / 2 : 0; + unsigned_fetch_texel_rgtc(rowStride, map + sliceOffset, i, j, &red, 1); texel[RCOMP] = texel[GCOMP] = - texel[BCOMP] = UBYTE_TO_FLOAT(red); + texel[BCOMP] = BYTE_TO_FLOAT(red); texel[ACOMP] = 1.0; } -void -_mesa_fetch_texel_signed_l_latc1(const struct swrast_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel) +static void +fetch_rg_rgtc2(const GLubyte *map, const GLuint imageOffsets[], + GLint rowStride, GLint i, GLint j, GLint k, + GLfloat *texel) { - GLbyte red; - GLint sliceOffset = k ? texImage->ImageOffsets[k] / 2 : 0; - signed_fetch_texel_rgtc(texImage->RowStride, - (GLbyte *)(texImage->Map) + sliceOffset, - i, j, &red, 1); - texel[RCOMP] = - texel[GCOMP] = - texel[BCOMP] = BYTE_TO_FLOAT_TEX(red); + GLubyte red, green; + GLuint sliceOffset = k ? imageOffsets[k] : 0; + unsigned_fetch_texel_rgtc(rowStride, + map + sliceOffset, + i, j, &red, 2); + unsigned_fetch_texel_rgtc(rowStride, + map + sliceOffset + 8, + i, j, &green, 2); + texel[RCOMP] = UBYTE_TO_FLOAT(red); + texel[GCOMP] = UBYTE_TO_FLOAT(green); + texel[BCOMP] = 0.0; texel[ACOMP] = 1.0; } -void -_mesa_fetch_texel_la_latc2(const struct swrast_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel) +static void +fetch_la_latc2(const GLubyte *map, const GLuint imageOffsets[], + GLint rowStride, GLint i, GLint j, GLint k, + GLfloat *texel) { GLubyte red, green; - GLint sliceOffset = k ? texImage->ImageOffsets[k] : 0; - unsigned_fetch_texel_rgtc(texImage->RowStride, - texImage->Map + sliceOffset, + GLuint sliceOffset = k ? imageOffsets[k] : 0; + unsigned_fetch_texel_rgtc(rowStride, + map + sliceOffset, i, j, &red, 2); - unsigned_fetch_texel_rgtc(texImage->RowStride, - texImage->Map + sliceOffset + 8, + unsigned_fetch_texel_rgtc(rowStride, + map + sliceOffset + 8, i, j, &green, 2); texel[RCOMP] = texel[GCOMP] = @@ -405,17 +411,39 @@ _mesa_fetch_texel_la_latc2(const struct swrast_texture_image *texImage, texel[ACOMP] = UBYTE_TO_FLOAT(green); } -void -_mesa_fetch_texel_signed_la_latc2(const struct swrast_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel) + +static void +fetch_signed_rg_rgtc2(const GLubyte *map, const GLuint imageOffsets[], + GLint rowStride, GLint i, GLint j, GLint k, + GLfloat *texel) +{ + GLbyte red, green; + GLuint sliceOffset = k ? imageOffsets[k] : 0; + signed_fetch_texel_rgtc(rowStride, + (GLbyte *) map + sliceOffset, + i, j, &red, 2); + signed_fetch_texel_rgtc(rowStride, + (GLbyte *) map + sliceOffset + 8, + i, j, &green, 2); + texel[RCOMP] = BYTE_TO_FLOAT_TEX(red); + texel[GCOMP] = BYTE_TO_FLOAT_TEX(green); + texel[BCOMP] = 0.0; + texel[ACOMP] = 1.0; +} + + +static void +fetch_signed_la_latc2(const GLubyte *map, const GLuint imageOffsets[], + GLint rowStride, GLint i, GLint j, GLint k, + GLfloat *texel) { GLbyte red, green; - GLint sliceOffset = k ? texImage->ImageOffsets[k] : 0; - signed_fetch_texel_rgtc(texImage->RowStride, - (GLbyte *)(texImage->Map) + sliceOffset, + GLuint sliceOffset = k ? imageOffsets[k] : 0; + signed_fetch_texel_rgtc(rowStride, + (GLbyte *) map + sliceOffset, i, j, &red, 2); - signed_fetch_texel_rgtc(texImage->RowStride, - (GLbyte *)(texImage->Map) + sliceOffset + 8, + signed_fetch_texel_rgtc(rowStride, + (GLbyte *) map + sliceOffset + 8, i, j, &green, 2); texel[RCOMP] = texel[GCOMP] = @@ -423,27 +451,28 @@ _mesa_fetch_texel_signed_la_latc2(const struct swrast_texture_image *texImage, texel[ACOMP] = BYTE_TO_FLOAT_TEX(green); } -#define TAG(x) unsigned_##x - -#define TYPE GLubyte -#define T_MIN 0 -#define T_MAX 0xff - -#include "texcompress_rgtc_tmp.h" - -#undef TAG -#undef TYPE -#undef T_MIN -#undef T_MAX - -#define TAG(x) signed_##x -#define TYPE GLbyte -#define T_MIN (GLbyte)-128 -#define T_MAX (GLbyte)127 -#include "texcompress_rgtc_tmp.h" - -#undef TAG -#undef TYPE -#undef T_MIN -#undef T_MAX +compressed_fetch_func +_mesa_get_compressed_rgtc_func(gl_format format) +{ + switch (format) { + case MESA_FORMAT_RED_RGTC1: + return fetch_red_rgtc1; + case MESA_FORMAT_L_LATC1: + return fetch_l_latc1; + case MESA_FORMAT_SIGNED_RED_RGTC1: + return fetch_signed_red_rgtc1; + case MESA_FORMAT_SIGNED_L_LATC1: + return fetch_signed_l_latc1; + case MESA_FORMAT_RG_RGTC2: + return fetch_rg_rgtc2; + case MESA_FORMAT_LA_LATC2: + return fetch_la_latc2; + case MESA_FORMAT_SIGNED_RG_RGTC2: + return fetch_signed_rg_rgtc2; + case MESA_FORMAT_SIGNED_LA_LATC2: + return fetch_signed_la_latc2; + default: + return NULL; + } +} diff --git a/mesalib/src/mesa/main/texcompress_rgtc.h b/mesalib/src/mesa/main/texcompress_rgtc.h index 91fda882d..9e1cce438 100644 --- a/mesalib/src/mesa/main/texcompress_rgtc.h +++ b/mesalib/src/mesa/main/texcompress_rgtc.h @@ -28,7 +28,6 @@ #include "mfeatures.h" #include "texstore.h" -struct swrast_texture_image; extern GLboolean _mesa_texstore_red_rgtc1(TEXSTORE_PARAMS); @@ -42,36 +41,8 @@ _mesa_texstore_rg_rgtc2(TEXSTORE_PARAMS); extern GLboolean _mesa_texstore_signed_rg_rgtc2(TEXSTORE_PARAMS); -extern void -_mesa_fetch_texel_red_rgtc1(const struct swrast_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel); +extern compressed_fetch_func +_mesa_get_compressed_rgtc_func(gl_format format); -extern void -_mesa_fetch_texel_signed_red_rgtc1(const struct swrast_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel); - -extern void -_mesa_fetch_texel_rg_rgtc2(const struct swrast_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel); - -extern void -_mesa_fetch_texel_signed_rg_rgtc2(const struct swrast_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel); - -extern void -_mesa_fetch_texel_l_latc1(const struct swrast_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel); - -extern void -_mesa_fetch_texel_signed_l_latc1(const struct swrast_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel); - -extern void -_mesa_fetch_texel_la_latc2(const struct swrast_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel); - -extern void -_mesa_fetch_texel_signed_la_latc2(const struct swrast_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel); #endif diff --git a/mesalib/src/mesa/main/texcompress_s3tc.c b/mesalib/src/mesa/main/texcompress_s3tc.c index 476b998e0..23a5a0868 100644 --- a/mesalib/src/mesa/main/texcompress_s3tc.c +++ b/mesalib/src/mesa/main/texcompress_s3tc.c @@ -44,7 +44,6 @@ #include "texcompress.h" #include "texcompress_s3tc.h" #include "texstore.h" -#include "swrast/s_context.h" #include "format_unpack.h" @@ -58,7 +57,7 @@ #define DXTN_LIBNAME "libtxc_dxtn.so" #endif -typedef void (*dxtFetchTexelFuncExt)( GLint srcRowstride, GLubyte *pixdata, GLint col, GLint row, GLvoid *texelOut ); +typedef void (*dxtFetchTexelFuncExt)( GLint srcRowstride, const GLubyte *pixdata, GLint col, GLint row, GLvoid *texelOut ); static dxtFetchTexelFuncExt fetch_ext_rgb_dxt1 = NULL; static dxtFetchTexelFuncExt fetch_ext_rgba_dxt1 = NULL; @@ -332,165 +331,105 @@ _mesa_texstore_rgba_dxt5(TEXSTORE_PARAMS) } +/** Report problem with dxt texture decompression, once */ static void -fetch_texel_2d_rgb_dxt1(const struct swrast_texture_image *texImage, - GLint i, GLint j, GLint k, GLubyte *texel) +problem(const char *func) { - if (fetch_ext_rgb_dxt1) { - GLint sliceOffset = k ? texImage->ImageOffsets[k] / 2 : 0; - fetch_ext_rgb_dxt1(texImage->RowStride, - texImage->Map + sliceOffset, i, j, texel); + static GLboolean warned = GL_FALSE; + if (!warned) { + _mesa_debug(NULL, "attempted to decode DXT texture without " + "library available: %s\n", func); + warned = GL_TRUE; } - else - _mesa_debug(NULL, "attempted to decode s3tc texture without library available: fetch_texel_2d_rgb_dxt1"); } -void -_mesa_fetch_texel_rgb_dxt1(const struct swrast_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel) +static void +fetch_rgb_dxt1(const GLubyte *map, const GLuint imageOffsets[], + GLint rowStride, GLint i, GLint j, GLint k, GLfloat *texel) { - /* just sample as GLubyte and convert to float here */ - GLubyte rgba[4]; - fetch_texel_2d_rgb_dxt1(texImage, i, j, k, rgba); - texel[RCOMP] = UBYTE_TO_FLOAT(rgba[RCOMP]); - texel[GCOMP] = UBYTE_TO_FLOAT(rgba[GCOMP]); - texel[BCOMP] = UBYTE_TO_FLOAT(rgba[BCOMP]); - texel[ACOMP] = UBYTE_TO_FLOAT(rgba[ACOMP]); + if (fetch_ext_rgb_dxt1) { + GLuint sliceOffset = k ? imageOffsets[k] / 2 : 0; + GLubyte tex[4]; + fetch_ext_rgb_dxt1(rowStride, map + sliceOffset, i, j, tex); + texel[RCOMP] = UBYTE_TO_FLOAT(tex[RCOMP]); + texel[GCOMP] = UBYTE_TO_FLOAT(tex[GCOMP]); + texel[BCOMP] = UBYTE_TO_FLOAT(tex[BCOMP]); + texel[ACOMP] = UBYTE_TO_FLOAT(tex[ACOMP]); + } + else { + problem("rgb_dxt1"); + } } - static void -fetch_texel_2d_rgba_dxt1(const struct swrast_texture_image *texImage, - GLint i, GLint j, GLint k, GLubyte *texel) +fetch_rgba_dxt1(const GLubyte *map, const GLuint imageOffsets[], + GLint rowStride, GLint i, GLint j, GLint k, GLfloat *texel) { if (fetch_ext_rgba_dxt1) { - GLint sliceOffset = k ? texImage->ImageOffsets[k] / 2 : 0; - fetch_ext_rgba_dxt1(texImage->RowStride, - texImage->Map + sliceOffset, i, j, texel); + GLuint sliceOffset = k ? imageOffsets[k] / 2 : 0; + GLubyte tex[4]; + fetch_ext_rgba_dxt1(rowStride, map + sliceOffset, i, j, tex); + texel[RCOMP] = UBYTE_TO_FLOAT(tex[RCOMP]); + texel[GCOMP] = UBYTE_TO_FLOAT(tex[GCOMP]); + texel[BCOMP] = UBYTE_TO_FLOAT(tex[BCOMP]); + texel[ACOMP] = UBYTE_TO_FLOAT(tex[ACOMP]); + } + else { + problem("rgba_dxt1"); } - else - _mesa_debug(NULL, "attempted to decode s3tc texture without library available: fetch_texel_2d_rgba_dxt1\n"); -} - - -void -_mesa_fetch_texel_rgba_dxt1(const struct swrast_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel) -{ - /* just sample as GLubyte and convert to float here */ - GLubyte rgba[4]; - fetch_texel_2d_rgba_dxt1(texImage, i, j, k, rgba); - texel[RCOMP] = UBYTE_TO_FLOAT(rgba[RCOMP]); - texel[GCOMP] = UBYTE_TO_FLOAT(rgba[GCOMP]); - texel[BCOMP] = UBYTE_TO_FLOAT(rgba[BCOMP]); - texel[ACOMP] = UBYTE_TO_FLOAT(rgba[ACOMP]); } - static void -fetch_texel_2d_rgba_dxt3(const struct swrast_texture_image *texImage, - GLint i, GLint j, GLint k, GLubyte *texel) +fetch_rgba_dxt3(const GLubyte *map, const GLuint imageOffsets[], + GLint rowStride, GLint i, GLint j, GLint k, GLfloat *texel) { if (fetch_ext_rgba_dxt3) { - GLint sliceOffset = k ? texImage->ImageOffsets[k] : 0; - fetch_ext_rgba_dxt3(texImage->RowStride, - texImage->Map + sliceOffset, i, j, texel); + GLuint sliceOffset = k ? imageOffsets[k] : 0; + GLubyte tex[4]; + fetch_ext_rgba_dxt3(rowStride, map + sliceOffset, i, j, tex); + texel[RCOMP] = UBYTE_TO_FLOAT(tex[RCOMP]); + texel[GCOMP] = UBYTE_TO_FLOAT(tex[GCOMP]); + texel[BCOMP] = UBYTE_TO_FLOAT(tex[BCOMP]); + texel[ACOMP] = UBYTE_TO_FLOAT(tex[ACOMP]); + } + else { + problem("rgba_dxt3"); } - else - _mesa_debug(NULL, "attempted to decode s3tc texture without library available: fetch_texel_2d_rgba_dxt3\n"); -} - - -void -_mesa_fetch_texel_rgba_dxt3(const struct swrast_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel) -{ - /* just sample as GLubyte and convert to float here */ - GLubyte rgba[4]; - fetch_texel_2d_rgba_dxt3(texImage, i, j, k, rgba); - texel[RCOMP] = UBYTE_TO_FLOAT(rgba[RCOMP]); - texel[GCOMP] = UBYTE_TO_FLOAT(rgba[GCOMP]); - texel[BCOMP] = UBYTE_TO_FLOAT(rgba[BCOMP]); - texel[ACOMP] = UBYTE_TO_FLOAT(rgba[ACOMP]); } - static void -fetch_texel_2d_rgba_dxt5(const struct swrast_texture_image *texImage, - GLint i, GLint j, GLint k, GLubyte *texel) +fetch_rgba_dxt5(const GLubyte *map, const GLuint imageOffsets[], + GLint rowStride, GLint i, GLint j, GLint k, GLfloat *texel) { if (fetch_ext_rgba_dxt5) { - GLint sliceOffset = k ? texImage->ImageOffsets[k] : 0; - fetch_ext_rgba_dxt5(texImage->RowStride, - texImage->Map + sliceOffset, i, j, texel); + GLuint sliceOffset = k ? imageOffsets[k] : 0; + GLubyte tex[4]; + fetch_ext_rgba_dxt5(rowStride, map + sliceOffset, i, j, tex); + texel[RCOMP] = UBYTE_TO_FLOAT(tex[RCOMP]); + texel[GCOMP] = UBYTE_TO_FLOAT(tex[GCOMP]); + texel[BCOMP] = UBYTE_TO_FLOAT(tex[BCOMP]); + texel[ACOMP] = UBYTE_TO_FLOAT(tex[ACOMP]); + } + else { + problem("rgba_dxt5"); } - else - _mesa_debug(NULL, "attempted to decode s3tc texture without library available: fetch_texel_2d_rgba_dxt5\n"); -} - - -void -_mesa_fetch_texel_rgba_dxt5(const struct swrast_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel) -{ - /* just sample as GLubyte and convert to float here */ - GLubyte rgba[4]; - fetch_texel_2d_rgba_dxt5(texImage, i, j, k, rgba); - texel[RCOMP] = UBYTE_TO_FLOAT(rgba[RCOMP]); - texel[GCOMP] = UBYTE_TO_FLOAT(rgba[GCOMP]); - texel[BCOMP] = UBYTE_TO_FLOAT(rgba[BCOMP]); - texel[ACOMP] = UBYTE_TO_FLOAT(rgba[ACOMP]); -} - -void -_mesa_fetch_texel_srgb_dxt1(const struct swrast_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel) -{ - /* just sample as GLubyte and convert to float here */ - GLubyte rgba[4]; - fetch_texel_2d_rgb_dxt1(texImage, i, j, k, rgba); - texel[RCOMP] = _mesa_nonlinear_to_linear(rgba[RCOMP]); - texel[GCOMP] = _mesa_nonlinear_to_linear(rgba[GCOMP]); - texel[BCOMP] = _mesa_nonlinear_to_linear(rgba[BCOMP]); - texel[ACOMP] = UBYTE_TO_FLOAT(rgba[ACOMP]); } -void -_mesa_fetch_texel_srgba_dxt1(const struct swrast_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel) -{ - /* just sample as GLubyte and convert to float here */ - GLubyte rgba[4]; - fetch_texel_2d_rgba_dxt1(texImage, i, j, k, rgba); - texel[RCOMP] = _mesa_nonlinear_to_linear(rgba[RCOMP]); - texel[GCOMP] = _mesa_nonlinear_to_linear(rgba[GCOMP]); - texel[BCOMP] = _mesa_nonlinear_to_linear(rgba[BCOMP]); - texel[ACOMP] = UBYTE_TO_FLOAT(rgba[ACOMP]); -} -void -_mesa_fetch_texel_srgba_dxt3(const struct swrast_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel) +compressed_fetch_func +_mesa_get_dxt_fetch_func(gl_format format) { - /* just sample as GLubyte and convert to float here */ - GLubyte rgba[4]; - fetch_texel_2d_rgba_dxt3(texImage, i, j, k, rgba); - texel[RCOMP] = _mesa_nonlinear_to_linear(rgba[RCOMP]); - texel[GCOMP] = _mesa_nonlinear_to_linear(rgba[GCOMP]); - texel[BCOMP] = _mesa_nonlinear_to_linear(rgba[BCOMP]); - texel[ACOMP] = UBYTE_TO_FLOAT(rgba[ACOMP]); -} - -void -_mesa_fetch_texel_srgba_dxt5(const struct swrast_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel) -{ - /* just sample as GLubyte and convert to float here */ - GLubyte rgba[4]; - fetch_texel_2d_rgba_dxt5(texImage, i, j, k, rgba); - texel[RCOMP] = _mesa_nonlinear_to_linear(rgba[RCOMP]); - texel[GCOMP] = _mesa_nonlinear_to_linear(rgba[GCOMP]); - texel[BCOMP] = _mesa_nonlinear_to_linear(rgba[BCOMP]); - texel[ACOMP] = UBYTE_TO_FLOAT(rgba[ACOMP]); + switch (format) { + case MESA_FORMAT_RGB_DXT1: + return fetch_rgb_dxt1; + case MESA_FORMAT_RGBA_DXT1: + return fetch_rgba_dxt1; + case MESA_FORMAT_RGBA_DXT3: + return fetch_rgba_dxt3; + case MESA_FORMAT_RGBA_DXT5: + return fetch_rgba_dxt5; + default: + return NULL; + } } diff --git a/mesalib/src/mesa/main/texcompress_s3tc.h b/mesalib/src/mesa/main/texcompress_s3tc.h index 524ac0c13..d9ef68992 100644 --- a/mesalib/src/mesa/main/texcompress_s3tc.h +++ b/mesalib/src/mesa/main/texcompress_s3tc.h @@ -29,9 +29,9 @@ #include "glheader.h" #include "mfeatures.h" #include "texstore.h" +#include "texcompress.h" struct gl_context; -struct swrast_texture_image; extern GLboolean _mesa_texstore_rgb_dxt1(TEXSTORE_PARAMS); @@ -45,39 +45,12 @@ _mesa_texstore_rgba_dxt3(TEXSTORE_PARAMS); extern GLboolean _mesa_texstore_rgba_dxt5(TEXSTORE_PARAMS); -extern void -_mesa_fetch_texel_rgb_dxt1(const struct swrast_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel); - -extern void -_mesa_fetch_texel_rgba_dxt1(const struct swrast_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel); - -extern void -_mesa_fetch_texel_rgba_dxt3(const struct swrast_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel); - -extern void -_mesa_fetch_texel_rgba_dxt5(const struct swrast_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel); extern void -_mesa_fetch_texel_srgb_dxt1(const struct swrast_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel); - -extern void -_mesa_fetch_texel_srgba_dxt1(const struct swrast_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel); +_mesa_init_texture_s3tc(struct gl_context *ctx); -extern void -_mesa_fetch_texel_srgba_dxt3(const struct swrast_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel); +extern compressed_fetch_func +_mesa_get_dxt_fetch_func(gl_format format); -extern void -_mesa_fetch_texel_srgba_dxt5(const struct swrast_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel); - -extern void -_mesa_init_texture_s3tc(struct gl_context *ctx); #endif /* TEXCOMPRESS_S3TC_H */ diff --git a/mesalib/src/mesa/main/teximage.c b/mesalib/src/mesa/main/teximage.c index 83b7e1488..7a0d944fd 100644 --- a/mesalib/src/mesa/main/teximage.c +++ b/mesalib/src/mesa/main/teximage.c @@ -791,9 +791,9 @@ _mesa_select_tex_object(struct gl_context *ctx, case GL_PROXY_TEXTURE_2D_ARRAY_EXT: return arrayTex ? ctx->Texture.ProxyTex[TEXTURE_2D_ARRAY_INDEX] : NULL; case GL_TEXTURE_BUFFER: - return _mesa_is_desktop_gl(ctx) - && ctx->Extensions.ARB_texture_buffer_object - ? texUnit->CurrentTex[TEXTURE_BUFFER_INDEX] : NULL; + return ctx->API == API_OPENGL_CORE && + ctx->Extensions.ARB_texture_buffer_object ? + texUnit->CurrentTex[TEXTURE_BUFFER_INDEX] : NULL; case GL_TEXTURE_EXTERNAL_OES: return ctx->Extensions.OES_EGL_image_external ? texUnit->CurrentTex[TEXTURE_EXTERNAL_INDEX] : NULL; @@ -994,9 +994,8 @@ _mesa_max_texture_levels(struct gl_context *ctx, GLenum target) return ctx->Extensions.ARB_texture_cube_map_array ? ctx->Const.MaxCubeTextureLevels : 0; case GL_TEXTURE_BUFFER: - return _mesa_is_desktop_gl(ctx) - && ctx->Extensions.ARB_texture_buffer_object - ? 1 : 0; + return ctx->API == API_OPENGL_CORE && + ctx->Extensions.ARB_texture_buffer_object ? 1 : 0; case GL_TEXTURE_EXTERNAL_OES: /* fall-through */ default: @@ -3849,6 +3848,13 @@ get_texbuffer_format(const struct gl_context *ctx, GLenum internalFormat) case GL_R32UI: return MESA_FORMAT_R_UINT32; + case GL_RGB32F: + return MESA_FORMAT_RGB_FLOAT32; + case GL_RGB32UI: + return MESA_FORMAT_RGB_UINT32; + case GL_RGB32I: + return MESA_FORMAT_RGB_INT32; + default: return MESA_FORMAT_NONE; } @@ -3880,6 +3886,12 @@ validate_texbuffer_format(const struct gl_context *ctx, GLenum internalFormat) if (base_format == GL_R || base_format == GL_RG) return MESA_FORMAT_NONE; } + + if (!ctx->Extensions.ARB_texture_buffer_object_rgb32) { + GLenum base_format = _mesa_get_format_base_format(format); + if (base_format == GL_RGB) + return MESA_FORMAT_NONE; + } return format; } @@ -3895,8 +3907,8 @@ _mesa_TexBuffer(GLenum target, GLenum internalFormat, GLuint buffer) GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); - if (!(ctx->Extensions.ARB_texture_buffer_object - && _mesa_is_desktop_gl(ctx))) { + if (!(ctx->API == API_OPENGL_CORE && + ctx->Extensions.ARB_texture_buffer_object)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glTexBuffer"); return; } diff --git a/mesalib/src/mesa/main/texobj.c b/mesalib/src/mesa/main/texobj.c index d650c75e4..cb7ac19a8 100644 --- a/mesalib/src/mesa/main/texobj.c +++ b/mesalib/src/mesa/main/texobj.c @@ -1148,9 +1148,9 @@ target_enum_to_index(struct gl_context *ctx, GLenum target) || _mesa_is_gles3(ctx) ? TEXTURE_2D_ARRAY_INDEX : -1; case GL_TEXTURE_BUFFER_ARB: - return _mesa_is_desktop_gl(ctx) - && ctx->Extensions.ARB_texture_buffer_object - ? TEXTURE_BUFFER_INDEX : -1; + return ctx->API == API_OPENGL_CORE && + ctx->Extensions.ARB_texture_buffer_object ? + TEXTURE_BUFFER_INDEX : -1; case GL_TEXTURE_EXTERNAL_OES: return _mesa_is_gles(ctx) && ctx->Extensions.OES_EGL_image_external ? TEXTURE_EXTERNAL_INDEX : -1; diff --git a/mesalib/src/mesa/main/texparam.c b/mesalib/src/mesa/main/texparam.c index c2d161f9a..ca5a21f78 100644 --- a/mesalib/src/mesa/main/texparam.c +++ b/mesalib/src/mesa/main/texparam.c @@ -976,7 +976,7 @@ legal_get_tex_level_parameter_target(struct gl_context *ctx, GLenum target) * From the OpenGL 3.1 spec: * "target may also be TEXTURE_BUFFER, indicating the texture buffer." */ - return _mesa_is_desktop_gl(ctx) && ctx->Version >= 31; + return ctx->API == API_OPENGL_CORE && ctx->Version >= 31; default: return GL_FALSE; } diff --git a/mesalib/src/mesa/main/uniform_query.cpp b/mesalib/src/mesa/main/uniform_query.cpp index c71577c6e..b6b73d16f 100644 --- a/mesalib/src/mesa/main/uniform_query.cpp +++ b/mesalib/src/mesa/main/uniform_query.cpp @@ -97,12 +97,16 @@ _mesa_GetActiveUniformsiv(GLuint program, for (i = 0; i < uniformCount; i++) { GLuint index = uniformIndices[i]; - const struct gl_uniform_storage *uni = &shProg->UniformStorage[index]; if (index >= shProg->NumUserUniformStorage) { _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniformsiv(index)"); return; } + } + + for (i = 0; i < uniformCount; i++) { + GLuint index = uniformIndices[i]; + const struct gl_uniform_storage *uni = &shProg->UniformStorage[index]; switch (pname) { case GL_UNIFORM_TYPE: diff --git a/mesalib/src/mesa/main/uniforms.c b/mesalib/src/mesa/main/uniforms.c index 3f156bf10..77b195edb 100644 --- a/mesalib/src/mesa/main/uniforms.c +++ b/mesalib/src/mesa/main/uniforms.c @@ -614,14 +614,14 @@ _mesa_UniformBlockBinding(GLuint program, if (uniformBlockIndex >= shProg->NumUniformBlocks) { _mesa_error(ctx, GL_INVALID_VALUE, - "glUniformBlockBinding(block index %d >= %d)", + "glUniformBlockBinding(block index %u >= %u)", uniformBlockIndex, shProg->NumUniformBlocks); return; } if (uniformBlockBinding >= ctx->Const.MaxUniformBufferBindings) { _mesa_error(ctx, GL_INVALID_VALUE, - "glUniformBlockBinding(block binding %d >= %d)", + "glUniformBlockBinding(block binding %u >= %u)", uniformBlockBinding, ctx->Const.MaxUniformBufferBindings); return; } @@ -667,7 +667,7 @@ _mesa_GetActiveUniformBlockiv(GLuint program, if (uniformBlockIndex >= shProg->NumUniformBlocks) { _mesa_error(ctx, GL_INVALID_VALUE, - "glGetActiveUniformBlockiv(block index %d >= %d)", + "glGetActiveUniformBlockiv(block index %u >= %u)", uniformBlockIndex, shProg->NumUniformBlocks); return; } @@ -750,7 +750,7 @@ _mesa_GetActiveUniformBlockName(GLuint program, if (uniformBlockIndex >= shProg->NumUniformBlocks) { _mesa_error(ctx, GL_INVALID_VALUE, - "glGetActiveUniformBlockiv(block index %d >= %d)", + "glGetActiveUniformBlockiv(block index %u >= %u)", uniformBlockIndex, shProg->NumUniformBlocks); return; } diff --git a/mesalib/src/mesa/main/varray.c b/mesalib/src/mesa/main/varray.c index f77014397..5e4d6c3e6 100644 --- a/mesalib/src/mesa/main/varray.c +++ b/mesalib/src/mesa/main/varray.c @@ -251,7 +251,8 @@ update_array(struct gl_context *ctx, return; } - elementSize = _mesa_sizeof_type(type) * size; + elementSize = _mesa_bytes_per_vertex_attrib(size, type); + assert(elementSize != -1); array = &ctx->Array.ArrayObj->VertexAttrib[attrib]; array->Size = size; diff --git a/mesalib/src/mesa/main/version.c b/mesalib/src/mesa/main/version.c index cfaf4bbda..91234e4d7 100644 --- a/mesalib/src/mesa/main/version.c +++ b/mesalib/src/mesa/main/version.c @@ -345,6 +345,12 @@ _mesa_compute_version(struct gl_context *ctx) switch (ctx->API) { case API_OPENGL_COMPAT: + /* Disable GLSL 1.40 and later for legacy contexts. + * This disallows creation of the GL 3.1 compatibility context. */ + if (ctx->Const.GLSLVersion > 130) { + ctx->Const.GLSLVersion = 130; + } + /* fall through */ case API_OPENGL_CORE: compute_version(ctx); break; diff --git a/mesalib/src/mesa/main/vtxfmt.c b/mesalib/src/mesa/main/vtxfmt.c index 674edb5e1..6d687de60 100644 --- a/mesalib/src/mesa/main/vtxfmt.c +++ b/mesalib/src/mesa/main/vtxfmt.c @@ -36,6 +36,7 @@ #include "eval.h" #include "dlist.h" #include "main/dispatch.h" +#include "vbo/vbo_context.h" /** @@ -46,6 +47,8 @@ static void install_vtxfmt(struct gl_context *ctx, struct _glapi_table *tab, const GLvertexformat *vfmt) { + assert(ctx->Version > 0); + if (ctx->API != API_OPENGL_CORE && ctx->API != API_OPENGLES2) { SET_Color4f(tab, vfmt->Color4f); } @@ -262,3 +265,20 @@ _mesa_install_save_vtxfmt(struct gl_context *ctx, const GLvertexformat *vfmt) if (_mesa_is_desktop_gl(ctx)) install_vtxfmt( ctx, ctx->Save, vfmt ); } + + +/** + * Install VBO vtxfmt functions. + * + * This function depends on ctx->Version. + */ +void +_mesa_initialize_vbo_vtxfmt(struct gl_context *ctx) +{ + struct vbo_exec_context *exec = &vbo_context(ctx)->exec; + _mesa_install_exec_vtxfmt(ctx, &exec->vtxfmt); + if (ctx->API == API_OPENGL_COMPAT) { + _mesa_install_save_vtxfmt(ctx, &ctx->ListState.ListVtxfmt); + } +} + diff --git a/mesalib/src/mesa/main/vtxfmt.h b/mesalib/src/mesa/main/vtxfmt.h index 65a0e6c8e..16ffb6ffd 100644 --- a/mesalib/src/mesa/main/vtxfmt.h +++ b/mesalib/src/mesa/main/vtxfmt.h @@ -39,5 +39,6 @@ extern void _mesa_install_exec_vtxfmt( struct gl_context *ctx, const GLvertexformat *vfmt ); extern void _mesa_install_save_vtxfmt( struct gl_context *ctx, const GLvertexformat *vfmt ); +extern void _mesa_initialize_vbo_vtxfmt(struct gl_context *ctx); #endif /* _VTXFMT_H_ */ diff --git a/mesalib/src/mesa/state_tracker/st_atom_framebuffer.c b/mesalib/src/mesa/state_tracker/st_atom_framebuffer.c index a10dbfbd0..3df8691f4 100644 --- a/mesalib/src/mesa/state_tracker/st_atom_framebuffer.c +++ b/mesalib/src/mesa/state_tracker/st_atom_framebuffer.c @@ -71,7 +71,6 @@ update_renderbuffer_surface(struct st_context *st, struct pipe_surface surf_tmpl; memset(&surf_tmpl, 0, sizeof(surf_tmpl)); surf_tmpl.format = format; - surf_tmpl.usage = PIPE_BIND_RENDER_TARGET; surf_tmpl.u.tex.level = level; surf_tmpl.u.tex.first_layer = strb->rtt_face + strb->rtt_slice; surf_tmpl.u.tex.last_layer = strb->rtt_face + strb->rtt_slice; diff --git a/mesalib/src/mesa/state_tracker/st_atom_rasterizer.c b/mesalib/src/mesa/state_tracker/st_atom_rasterizer.c index d9e9d21f6..f20df9e9b 100644 --- a/mesalib/src/mesa/state_tracker/st_atom_rasterizer.c +++ b/mesalib/src/mesa/state_tracker/st_atom_rasterizer.c @@ -230,8 +230,7 @@ static void update_raster_state( struct st_context *st ) raster->line_stipple_factor = ctx->Line.StippleFactor - 1; /* _NEW_MULTISAMPLE */ - if (ctx->Multisample._Enabled || st->force_msaa) - raster->multisample = 1; + raster->multisample = ctx->Multisample._Enabled; /* _NEW_SCISSOR */ if (ctx->Scissor.Enabled) diff --git a/mesalib/src/mesa/state_tracker/st_cb_condrender.c b/mesalib/src/mesa/state_tracker/st_cb_condrender.c index 1ced560e1..3a5835ecd 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_condrender.c +++ b/mesalib/src/mesa/state_tracker/st_cb_condrender.c @@ -38,6 +38,7 @@ #include "pipe/p_context.h" #include "pipe/p_defines.h" +#include "cso_cache/cso_context.h" #include "st_context.h" #include "st_cb_queryobj.h" #include "st_cb_condrender.h" @@ -53,7 +54,6 @@ st_BeginConditionalRender(struct gl_context *ctx, struct gl_query_object *q, { struct st_query_object *stq = st_query_object(q); struct st_context *st = st_context(ctx); - struct pipe_context *pipe = st->pipe; uint m; st_flush_bitmap_cache(st); @@ -76,10 +76,7 @@ st_BeginConditionalRender(struct gl_context *ctx, struct gl_query_object *q, m = PIPE_RENDER_COND_WAIT; } - st->render_condition = stq->pq; - st->condition_mode = m; - - pipe->render_condition(pipe, stq->pq, m); + cso_set_render_condition(st->cso_context, stq->pq, m); } @@ -90,13 +87,11 @@ static void st_EndConditionalRender(struct gl_context *ctx, struct gl_query_object *q) { struct st_context *st = st_context(ctx); - struct pipe_context *pipe = st->pipe; (void) q; st_flush_bitmap_cache(st); - pipe->render_condition(pipe, NULL, 0); - st->render_condition = NULL; + cso_set_render_condition(st->cso_context, NULL, 0); } diff --git a/mesalib/src/mesa/state_tracker/st_cb_eglimage.c b/mesalib/src/mesa/state_tracker/st_cb_eglimage.c index 0679e7d44..8c78e5ef4 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_eglimage.c +++ b/mesalib/src/mesa/state_tracker/st_cb_eglimage.c @@ -76,10 +76,8 @@ st_egl_image_target_renderbuffer_storage(struct gl_context *ctx, struct st_context *st = st_context(ctx); struct st_renderbuffer *strb = st_renderbuffer(rb); struct pipe_surface *ps; - unsigned usage; - usage = PIPE_BIND_RENDER_TARGET; - ps = st_manager_get_egl_image_surface(st, (void *) image_handle, usage); + ps = st_manager_get_egl_image_surface(st, (void *) image_handle); if (ps) { strb->Base.Width = ps->width; strb->Base.Height = ps->height; @@ -146,10 +144,8 @@ st_egl_image_target_texture_2d(struct gl_context *ctx, GLenum target, { struct st_context *st = st_context(ctx); struct pipe_surface *ps; - unsigned usage; - usage = PIPE_BIND_SAMPLER_VIEW; - ps = st_manager_get_egl_image_surface(st, (void *) image_handle, usage); + ps = st_manager_get_egl_image_surface(st, (void *) image_handle); if (ps) { st_bind_surface(ctx, target, texObj, texImage, ps); pipe_surface_reference(&ps, NULL); diff --git a/mesalib/src/mesa/state_tracker/st_cb_fbo.c b/mesalib/src/mesa/state_tracker/st_cb_fbo.c index ae280bfa9..bf206b025 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_fbo.c +++ b/mesalib/src/mesa/state_tracker/st_cb_fbo.c @@ -206,7 +206,7 @@ st_renderbuffer_alloc_storage(struct gl_context * ctx, if (!strb->texture) return FALSE; - u_surface_default_template(&surf_tmpl, strb->texture, templ.bind); + u_surface_default_template(&surf_tmpl, strb->texture); strb->surface = pipe->create_surface(pipe, strb->texture, &surf_tmpl); @@ -444,7 +444,6 @@ st_render_texture(struct gl_context *ctx, memset(&surf_tmpl, 0, sizeof(surf_tmpl)); surf_tmpl.format = ctx->Color.sRGBEnabled ? strb->texture->format : util_format_linear(strb->texture->format); - surf_tmpl.usage = PIPE_BIND_RENDER_TARGET; surf_tmpl.u.tex.level = strb->rtt_level; surf_tmpl.u.tex.first_layer = strb->rtt_face + strb->rtt_slice; surf_tmpl.u.tex.last_layer = strb->rtt_face + strb->rtt_slice; diff --git a/mesalib/src/mesa/state_tracker/st_cb_texture.c b/mesalib/src/mesa/state_tracker/st_cb_texture.c index ae069eb2c..bf13526d2 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_texture.c +++ b/mesalib/src/mesa/state_tracker/st_cb_texture.c @@ -60,7 +60,6 @@ #include "pipe/p_shader_tokens.h" #include "util/u_tile.h" #include "util/u_blit.h" -#include "util/u_blitter.h" #include "util/u_format.h" #include "util/u_surface.h" #include "util/u_sampler.h" @@ -1089,14 +1088,8 @@ st_CopyTexSubImage(struct gl_context *ctx, GLuint dims, goto fallback; } - /* Disable conditional rendering. */ - if (st->render_condition) { - pipe->render_condition(pipe, NULL, 0); - } - memset(&surf_tmpl, 0, sizeof(surf_tmpl)); surf_tmpl.format = util_format_linear(stImage->pt->format); - surf_tmpl.usage = dst_usage; surf_tmpl.u.tex.level = stImage->base.Level; surf_tmpl.u.tex.first_layer = stImage->base.Face + destZ; surf_tmpl.u.tex.last_layer = stImage->base.Face + destZ; @@ -1115,13 +1108,6 @@ st_CopyTexSubImage(struct gl_context *ctx, GLuint dims, 0.0, PIPE_TEX_MIPFILTER_NEAREST, color_writemask, 0); pipe_surface_reference(&dest_surface, NULL); - - /* Restore conditional rendering state. */ - if (st->render_condition) { - pipe->render_condition(pipe, st->render_condition, - st->condition_mode); - } - return; fallback: diff --git a/mesalib/src/mesa/state_tracker/st_context.c b/mesalib/src/mesa/state_tracker/st_context.c index 69bd50336..368a30b68 100644 --- a/mesalib/src/mesa/state_tracker/st_context.c +++ b/mesalib/src/mesa/state_tracker/st_context.c @@ -27,9 +27,12 @@ #include "main/imports.h" #include "main/accum.h" +#include "main/api_exec.h" #include "main/context.h" #include "main/samplerobj.h" #include "main/shaderobj.h" +#include "main/version.h" +#include "main/vtxfmt.h" #include "program/prog_cache.h" #include "vbo/vbo.h" #include "glapi/glapi.h" @@ -97,22 +100,6 @@ void st_invalidate_state(struct gl_context * ctx, GLuint new_state) _vbo_InvalidateState(ctx, new_state); } - -/** - * Check for multisample env var override. - */ -int -st_get_msaa(void) -{ - const char *msaa = _mesa_getenv("__GL_FSAA_MODE"); - if (msaa) - return atoi(msaa); - return 0; -} - - - - static struct st_context * st_create_context_priv( struct gl_context *ctx, struct pipe_context *pipe, const struct st_config_options *options) @@ -193,7 +180,6 @@ 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); @@ -201,6 +187,11 @@ st_create_context_priv( struct gl_context *ctx, struct pipe_context *pipe, st_init_limits(st); st_init_extensions(st); + _mesa_compute_version(ctx); + + _mesa_initialize_exec_table(ctx); + _mesa_initialize_vbo_vtxfmt(ctx); + return st; } diff --git a/mesalib/src/mesa/state_tracker/st_context.h b/mesalib/src/mesa/state_tracker/st_context.h index 2cc52773e..eeb7f0c4f 100644 --- a/mesalib/src/mesa/state_tracker/st_context.h +++ b/mesalib/src/mesa/state_tracker/st_context.h @@ -185,16 +185,11 @@ struct st_context struct cso_context *cso_context; - int force_msaa; void *winsys_drawable_handle; /* The number of vertex buffers from the last call of validate_arrays. */ unsigned last_num_vbuffers; - /* Active render condition. */ - struct pipe_query *render_condition; - unsigned condition_mode; - int32_t draw_stamp; int32_t read_stamp; @@ -265,9 +260,6 @@ st_fb_orientation(const struct gl_framebuffer *fb) #define ST_CALLOC_STRUCT(T) (struct T *) calloc(1, sizeof(struct T)) -extern int -st_get_msaa(void); - extern struct st_context * st_create_context(gl_api api, struct pipe_context *pipe, const struct gl_config *visual, diff --git a/mesalib/src/mesa/state_tracker/st_extensions.c b/mesalib/src/mesa/state_tracker/st_extensions.c index 93ef7a91c..262cc3d6c 100644 --- a/mesalib/src/mesa/state_tracker/st_extensions.c +++ b/mesalib/src/mesa/state_tracker/st_extensions.c @@ -494,6 +494,14 @@ void st_init_extensions(struct st_context *st) PIPE_FORMAT_B10G10R10A2_SSCALED } }, }; + static const struct st_extension_format_mapping tbo_rgb32[] = { + { {o(ARB_texture_buffer_object_rgb32) }, + { PIPE_FORMAT_R32G32B32_FLOAT, + PIPE_FORMAT_R32G32B32_UINT, + PIPE_FORMAT_R32G32B32_SINT, + } }, + }; + /* * Extensions that are supported by all Gallium drivers: */ @@ -570,10 +578,7 @@ void st_init_extensions(struct st_context *st) glsl_feature_level = screen->get_param(screen, PIPE_CAP_GLSL_FEATURE_LEVEL); if (glsl_feature_level >= 140) { - if (ctx->API == API_OPENGL_CORE) - ctx->Const.GLSLVersion = 140; - else - ctx->Const.GLSLVersion = 130; + ctx->Const.GLSLVersion = 140; } else if (glsl_feature_level >= 130) { ctx->Const.GLSLVersion = 130; } else { @@ -664,6 +669,24 @@ void st_init_extensions(struct st_context *st) if (ctx->Const.MinMapBufferAlignment >= 64) { ctx->Extensions.ARB_map_buffer_alignment = GL_TRUE; } - if (screen->get_param(screen, PIPE_CAP_TEXTURE_BUFFER_OBJECTS)) + if (screen->get_param(screen, PIPE_CAP_TEXTURE_BUFFER_OBJECTS)) { ctx->Extensions.ARB_texture_buffer_object = GL_TRUE; + init_format_extensions(st, tbo_rgb32, Elements(tbo_rgb32), + PIPE_BUFFER, PIPE_BIND_SAMPLER_VIEW); + } + + + /* Unpacking a varying in the fragment shader costs 1 texture indirection. + * If the number of available texture indirections is very limited, then we + * prefer to disable varying packing rather than run the risk of varying + * packing preventing a shader from running. + */ + if (screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT, + PIPE_SHADER_CAP_MAX_TEX_INDIRECTIONS) <= 8) { + /* We can't disable varying packing if transform feedback is available, + * because transform feedback code assumes a packed varying layout. + */ + if (!ctx->Extensions.EXT_transform_feedback) + ctx->Const.DisableVaryingPacking = GL_TRUE; + } } diff --git a/mesalib/src/mesa/state_tracker/st_gen_mipmap.c b/mesalib/src/mesa/state_tracker/st_gen_mipmap.c index c09261312..8ce2e06a2 100644 --- a/mesalib/src/mesa/state_tracker/st_gen_mipmap.c +++ b/mesalib/src/mesa/state_tracker/st_gen_mipmap.c @@ -93,18 +93,9 @@ st_render_mipmap(struct st_context *st, psv = st_create_texture_sampler_view(pipe, stObj->pt); - /* Disable conditional rendering. */ - if (st->render_condition) { - pipe->render_condition(pipe, NULL, 0); - } - util_gen_mipmap(st->gen_mipmap, psv, face, baseLevel, lastLevel, PIPE_TEX_FILTER_LINEAR); - if (st->render_condition) { - pipe->render_condition(pipe, st->render_condition, st->condition_mode); - } - pipe_sampler_view_reference(&psv, NULL); return TRUE; diff --git a/mesalib/src/mesa/state_tracker/st_manager.c b/mesalib/src/mesa/state_tracker/st_manager.c index b065db0ac..30f5ca5ed 100644 --- a/mesalib/src/mesa/state_tracker/st_manager.c +++ b/mesalib/src/mesa/state_tracker/st_manager.c @@ -224,8 +224,7 @@ st_framebuffer_validate(struct st_framebuffer *stfb, continue; } - u_surface_default_template(&surf_tmpl, textures[i], - PIPE_BIND_RENDER_TARGET); + u_surface_default_template(&surf_tmpl, textures[i]); ps = st->pipe->create_surface(st->pipe, textures[i], &surf_tmpl); if (ps) { pipe_surface_reference(&strb->surface, ps); @@ -285,7 +284,6 @@ st_framebuffer_add_renderbuffer(struct st_framebuffer *stfb, { struct gl_renderbuffer *rb; enum pipe_format format; - int samples; boolean sw; if (!stfb->iface) @@ -313,11 +311,7 @@ st_framebuffer_add_renderbuffer(struct st_framebuffer *stfb, if (format == PIPE_FORMAT_NONE) return FALSE; - samples = stfb->iface->visual->samples; - if (!samples) - samples = st_get_msaa(); - - rb = st_new_renderbuffer_fb(format, samples, sw); + rb = st_new_renderbuffer_fb(format, stfb->iface->visual->samples, sw); if (!rb) return FALSE; @@ -653,8 +647,6 @@ st_api_create_context(struct st_api *stapi, struct st_manager *smapi, /* need to perform version check */ if (attribs->major > 1 || attribs->minor > 0) { - _mesa_compute_version(st->ctx); - /* Is the actual version less than the requested version? */ if (st->ctx->Version < attribs->major * 10 + attribs->minor) { @@ -797,8 +789,7 @@ st_manager_flush_frontbuffer(struct st_context *st) * FIXME: I think this should operate on resources, not surfaces */ struct pipe_surface * -st_manager_get_egl_image_surface(struct st_context *st, - void *eglimg, unsigned usage) +st_manager_get_egl_image_surface(struct st_context *st, void *eglimg) { struct st_manager *smapi = (struct st_manager *) st->iface.st_context_private; @@ -812,7 +803,7 @@ st_manager_get_egl_image_surface(struct st_context *st, if (!smapi->get_egl_image(smapi, eglimg, &stimg)) return NULL; - u_surface_default_template(&surf_tmpl, stimg.texture, usage); + u_surface_default_template(&surf_tmpl, stimg.texture); surf_tmpl.u.tex.level = stimg.level; surf_tmpl.u.tex.first_layer = stimg.layer; surf_tmpl.u.tex.last_layer = stimg.layer; diff --git a/mesalib/src/mesa/state_tracker/st_manager.h b/mesalib/src/mesa/state_tracker/st_manager.h index 6a9497839..f729cff1f 100644 --- a/mesalib/src/mesa/state_tracker/st_manager.h +++ b/mesalib/src/mesa/state_tracker/st_manager.h @@ -36,8 +36,7 @@ struct st_context; struct pipe_surface * -st_manager_get_egl_image_surface(struct st_context *st, - void *eglimg, unsigned usage); +st_manager_get_egl_image_surface(struct st_context *st, void *eglimg); void st_manager_flush_frontbuffer(struct st_context *st); diff --git a/mesalib/src/mesa/swrast/s_context.h b/mesalib/src/mesa/swrast/s_context.h index 18353c416..f3f188e47 100644 --- a/mesalib/src/mesa/swrast/s_context.h +++ b/mesalib/src/mesa/swrast/s_context.h @@ -45,6 +45,7 @@ #include "main/compiler.h" #include "main/mtypes.h" +#include "main/texcompress.h" #include "program/prog_execute.h" #include "swrast.h" #include "s_fragprog.h" @@ -146,6 +147,9 @@ struct swrast_texture_image GLubyte *Buffer; FetchTexelFunc FetchTexel; + + /** For fetching texels from compressed textures */ + compressed_fetch_func FetchCompressedTexel; }; diff --git a/mesalib/src/mesa/swrast/s_texfetch.c b/mesalib/src/mesa/swrast/s_texfetch.c index 86b01a0b3..1f1964172 100644 --- a/mesalib/src/mesa/swrast/s_texfetch.c +++ b/mesalib/src/mesa/swrast/s_texfetch.c @@ -88,6 +88,23 @@ nonlinear_to_linear(GLubyte cs8) #define DIM 3 #include "s_texfetch_tmp.h" + +/** + * All compressed texture texel fetching is done though this function. + * Basically just call a core-Mesa texel fetch function. + */ +static void +fetch_compressed(const struct swrast_texture_image *swImage, + GLint i, GLint j, GLint k, GLfloat *texel) +{ + swImage->FetchCompressedTexel(swImage->Map, + swImage->ImageOffsets, + swImage->RowStride, + i, j, k, texel); +} + + + /** * Null texel fetch function. * @@ -426,64 +443,64 @@ texfetch_funcs[] = }, { MESA_FORMAT_SRGB_DXT1, - _mesa_fetch_texel_srgb_dxt1, - _mesa_fetch_texel_srgb_dxt1, - _mesa_fetch_texel_srgb_dxt1 + fetch_compressed, + fetch_compressed, + fetch_compressed }, { MESA_FORMAT_SRGBA_DXT1, - _mesa_fetch_texel_srgba_dxt1, - _mesa_fetch_texel_srgba_dxt1, - _mesa_fetch_texel_srgba_dxt1 + fetch_compressed, + fetch_compressed, + fetch_compressed }, { MESA_FORMAT_SRGBA_DXT3, - _mesa_fetch_texel_srgba_dxt3, - _mesa_fetch_texel_srgba_dxt3, - _mesa_fetch_texel_srgba_dxt3 + fetch_compressed, + fetch_compressed, + fetch_compressed }, { MESA_FORMAT_SRGBA_DXT5, - _mesa_fetch_texel_srgba_dxt5, - _mesa_fetch_texel_srgba_dxt5, - _mesa_fetch_texel_srgba_dxt5 + fetch_compressed, + fetch_compressed, + fetch_compressed }, { MESA_FORMAT_RGB_FXT1, - NULL, - _mesa_fetch_texel_2d_f_rgb_fxt1, - NULL + fetch_compressed, + fetch_compressed, + fetch_compressed }, { MESA_FORMAT_RGBA_FXT1, - NULL, - _mesa_fetch_texel_2d_f_rgba_fxt1, - NULL + fetch_compressed, + fetch_compressed, + fetch_compressed }, { MESA_FORMAT_RGB_DXT1, - _mesa_fetch_texel_rgb_dxt1, - _mesa_fetch_texel_rgb_dxt1, - _mesa_fetch_texel_rgb_dxt1 + fetch_compressed, + fetch_compressed, + fetch_compressed }, { MESA_FORMAT_RGBA_DXT1, - _mesa_fetch_texel_rgba_dxt1, - _mesa_fetch_texel_rgba_dxt1, - _mesa_fetch_texel_rgba_dxt1 + fetch_compressed, + fetch_compressed, + fetch_compressed }, { MESA_FORMAT_RGBA_DXT3, - _mesa_fetch_texel_rgba_dxt3, - _mesa_fetch_texel_rgba_dxt3, - _mesa_fetch_texel_rgba_dxt3 + fetch_compressed, + fetch_compressed, + fetch_compressed }, { MESA_FORMAT_RGBA_DXT5, - _mesa_fetch_texel_rgba_dxt5, - _mesa_fetch_texel_rgba_dxt5, - _mesa_fetch_texel_rgba_dxt5 + fetch_compressed, + fetch_compressed, + fetch_compressed }, { MESA_FORMAT_RGBA_FLOAT32, @@ -976,117 +993,117 @@ texfetch_funcs[] = }, { MESA_FORMAT_RED_RGTC1, - _mesa_fetch_texel_red_rgtc1, - _mesa_fetch_texel_red_rgtc1, - _mesa_fetch_texel_red_rgtc1 + fetch_compressed, + fetch_compressed, + fetch_compressed }, { MESA_FORMAT_SIGNED_RED_RGTC1, - _mesa_fetch_texel_signed_red_rgtc1, - _mesa_fetch_texel_signed_red_rgtc1, - _mesa_fetch_texel_signed_red_rgtc1 + fetch_compressed, + fetch_compressed, + fetch_compressed }, { MESA_FORMAT_RG_RGTC2, - _mesa_fetch_texel_rg_rgtc2, - _mesa_fetch_texel_rg_rgtc2, - _mesa_fetch_texel_rg_rgtc2 + fetch_compressed, + fetch_compressed, + fetch_compressed }, { MESA_FORMAT_SIGNED_RG_RGTC2, - _mesa_fetch_texel_signed_rg_rgtc2, - _mesa_fetch_texel_signed_rg_rgtc2, - _mesa_fetch_texel_signed_rg_rgtc2 + fetch_compressed, + fetch_compressed, + fetch_compressed }, { MESA_FORMAT_L_LATC1, - _mesa_fetch_texel_l_latc1, - _mesa_fetch_texel_l_latc1, - _mesa_fetch_texel_l_latc1 + fetch_compressed, + fetch_compressed, + fetch_compressed }, { MESA_FORMAT_SIGNED_L_LATC1, - _mesa_fetch_texel_signed_l_latc1, - _mesa_fetch_texel_signed_l_latc1, - _mesa_fetch_texel_signed_l_latc1 + fetch_compressed, + fetch_compressed, + fetch_compressed }, { MESA_FORMAT_LA_LATC2, - _mesa_fetch_texel_la_latc2, - _mesa_fetch_texel_la_latc2, - _mesa_fetch_texel_la_latc2 + fetch_compressed, + fetch_compressed, + fetch_compressed }, { MESA_FORMAT_SIGNED_LA_LATC2, - _mesa_fetch_texel_signed_la_latc2, - _mesa_fetch_texel_signed_la_latc2, - _mesa_fetch_texel_signed_la_latc2 + fetch_compressed, + fetch_compressed, + fetch_compressed }, { MESA_FORMAT_ETC1_RGB8, - NULL, - _mesa_fetch_texel_2d_f_etc1_rgb8, - NULL + fetch_compressed, + fetch_compressed, + fetch_compressed }, { MESA_FORMAT_ETC2_RGB8, - NULL, - _mesa_fetch_texel_2d_f_etc2_rgb8, - NULL + fetch_compressed, + fetch_compressed, + fetch_compressed }, { MESA_FORMAT_ETC2_SRGB8, - NULL, - _mesa_fetch_texel_2d_f_etc2_srgb8, - NULL + fetch_compressed, + fetch_compressed, + fetch_compressed }, { MESA_FORMAT_ETC2_RGBA8_EAC, - NULL, - _mesa_fetch_texel_2d_f_etc2_rgba8_eac, - NULL + fetch_compressed, + fetch_compressed, + fetch_compressed }, { MESA_FORMAT_ETC2_SRGB8_ALPHA8_EAC, - NULL, - _mesa_fetch_texel_2d_f_etc2_srgb8_alpha8_eac, - NULL + fetch_compressed, + fetch_compressed, + fetch_compressed }, { MESA_FORMAT_ETC2_R11_EAC, - NULL, - _mesa_fetch_texel_2d_f_etc2_r11_eac, - NULL + fetch_compressed, + fetch_compressed, + fetch_compressed }, { MESA_FORMAT_ETC2_RG11_EAC, - NULL, - _mesa_fetch_texel_2d_f_etc2_rg11_eac, - NULL + fetch_compressed, + fetch_compressed, + fetch_compressed }, { MESA_FORMAT_ETC2_SIGNED_R11_EAC, - NULL, - _mesa_fetch_texel_2d_f_etc2_signed_r11_eac, - NULL + fetch_compressed, + fetch_compressed, + fetch_compressed }, { MESA_FORMAT_ETC2_SIGNED_RG11_EAC, - NULL, - _mesa_fetch_texel_2d_f_etc2_signed_rg11_eac, - NULL + fetch_compressed, + fetch_compressed, + fetch_compressed }, { MESA_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1, - NULL, - _mesa_fetch_texel_2d_f_etc2_rgb8_punchthrough_alpha1, - NULL + fetch_compressed, + fetch_compressed, + fetch_compressed }, { MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1, - NULL, - _mesa_fetch_texel_2d_f_etc2_srgb8_punchthrough_alpha1, - NULL + fetch_compressed, + fetch_compressed, + fetch_compressed }, { MESA_FORMAT_SIGNED_A8, @@ -1175,9 +1192,15 @@ texfetch_funcs[] = }; -FetchTexelFunc -_mesa_get_texel_fetch_func(gl_format format, GLuint dims) +/** + * Initialize the texture image's FetchTexel methods. + */ +static void +set_fetch_functions(const struct gl_sampler_object *samp, + struct swrast_texture_image *texImage, GLuint dims) { + gl_format format = texImage->Base.TexFormat; + #ifdef DEBUG /* check that the table entries are sorted by format name */ gl_format fmt; @@ -1188,39 +1211,29 @@ _mesa_get_texel_fetch_func(gl_format format, GLuint dims) STATIC_ASSERT(Elements(texfetch_funcs) == MESA_FORMAT_COUNT); + if (samp->sRGBDecode == GL_SKIP_DECODE_EXT && + _mesa_get_format_color_encoding(format) == GL_SRGB) { + format = _mesa_get_srgb_format_linear(format); + } + assert(format < MESA_FORMAT_COUNT); switch (dims) { case 1: - return texfetch_funcs[format].Fetch1D; + texImage->FetchTexel = texfetch_funcs[format].Fetch1D; + break; case 2: - return texfetch_funcs[format].Fetch2D; + texImage->FetchTexel = texfetch_funcs[format].Fetch2D; + break; case 3: - return texfetch_funcs[format].Fetch3D; + texImage->FetchTexel = texfetch_funcs[format].Fetch3D; + break; default: - assert(0 && "bad dims in _mesa_get_texel_fetch_func"); - return NULL; + assert(!"Bad dims in set_fetch_functions()"); } -} - -/** - * Initialize the texture image's FetchTexel methods. - */ -static void -set_fetch_functions(struct gl_sampler_object *samp, - struct swrast_texture_image *texImage, GLuint dims) -{ - gl_format format = texImage->Base.TexFormat; - - ASSERT(dims == 1 || dims == 2 || dims == 3); - - if (samp->sRGBDecode == GL_SKIP_DECODE_EXT && - _mesa_get_format_color_encoding(format) == GL_SRGB) { - format = _mesa_get_srgb_format_linear(format); - } + texImage->FetchCompressedTexel = _mesa_get_compressed_fetch_func(format); - texImage->FetchTexel = _mesa_get_texel_fetch_func(format, dims); ASSERT(texImage->FetchTexel); } diff --git a/mesalib/src/mesa/swrast/s_texfetch.h b/mesalib/src/mesa/swrast/s_texfetch.h index 33950ce44..4e4397e13 100644 --- a/mesalib/src/mesa/swrast/s_texfetch.h +++ b/mesalib/src/mesa/swrast/s_texfetch.h @@ -29,9 +29,6 @@ #include "swrast/s_context.h" -extern FetchTexelFunc -_mesa_get_texel_fetch_func(gl_format format, GLuint dims); - void _mesa_update_fetch_functions(struct gl_context *ctx, GLuint unit); diff --git a/mesalib/src/mesa/vbo/vbo_exec.c b/mesalib/src/mesa/vbo/vbo_exec.c index 81a4d25ff..361d7a3e4 100644 --- a/mesalib/src/mesa/vbo/vbo_exec.c +++ b/mesalib/src/mesa/vbo/vbo_exec.c @@ -49,10 +49,6 @@ void vbo_exec_init( struct gl_context *ctx ) vbo_exec_vtx_init( exec ); vbo_exec_array_init( exec ); - /* Hook our functions into exec and compile dispatch tables. - */ - _mesa_install_exec_vtxfmt( ctx, &exec->vtxfmt ); - ctx->Driver.NeedFlush = 0; ctx->Driver.CurrentExecPrimitive = PRIM_OUTSIDE_BEGIN_END; ctx->Driver.BeginVertices = vbo_exec_BeginVertices; diff --git a/mesalib/src/mesa/vbo/vbo_exec_api.c b/mesalib/src/mesa/vbo/vbo_exec_api.c index 2aaa2895c..657c9aaee 100644 --- a/mesalib/src/mesa/vbo/vbo_exec_api.c +++ b/mesalib/src/mesa/vbo/vbo_exec_api.c @@ -1120,10 +1120,6 @@ void vbo_exec_vtx_init( struct vbo_exec_context *exec ) vbo_exec_vtxfmt_init( exec ); _mesa_noop_vtxfmt_init(&exec->vtxfmt_noop); - /* Hook our functions into the dispatch table. - */ - _mesa_install_exec_vtxfmt( ctx, &exec->vtxfmt ); - for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) { ASSERT(i < Elements(exec->vtx.attrsz)); exec->vtx.attrsz[i] = 0; diff --git a/mesalib/src/mesa/vbo/vbo_save_api.c b/mesalib/src/mesa/vbo/vbo_save_api.c index 75b8ca338..b4c90a05c 100644 --- a/mesalib/src/mesa/vbo/vbo_save_api.c +++ b/mesalib/src/mesa/vbo/vbo_save_api.c @@ -1667,5 +1667,4 @@ vbo_save_api_init(struct vbo_save_context *save) ctx->ListState.ListVtxfmt.DrawRangeElements = _save_OBE_DrawRangeElements; ctx->ListState.ListVtxfmt.MultiDrawElementsEXT = _save_OBE_MultiDrawElements; ctx->ListState.ListVtxfmt.MultiDrawElementsBaseVertex = _save_OBE_MultiDrawElementsBaseVertex; - _mesa_install_save_vtxfmt(ctx, &ctx->ListState.ListVtxfmt); } diff --git a/pixman/demos/conical-test.c b/pixman/demos/conical-test.c index 1e08e42f7..6b3243016 100644 --- a/pixman/demos/conical-test.c +++ b/pixman/demos/conical-test.c @@ -46,40 +46,6 @@ create_conical (int index) &c, pixman_double_to_fixed (angle), stops, NUM_STOPS); } -#define CHECK_SIZE 25 - -static void -fill_checkerboard (pixman_image_t *image, int width, int height) -{ -#define C1 0xaaaa -#define C2 0x8888 - - pixman_color_t check1 = { C1, C1, C1, 0xffff }; - pixman_color_t check2 = { C2, C2, C2, 0xffff }; - pixman_image_t *c1, *c2; - int i, j; - - c1 = pixman_image_create_solid_fill (&check1); - c2 = pixman_image_create_solid_fill (&check2); - - for (j = 0; j < height; j += CHECK_SIZE) - { - for (i = 0; i < width; i += CHECK_SIZE) - { - pixman_image_t *src; - - if ((((i / CHECK_SIZE) ^ (j / CHECK_SIZE)) & 1) == 0) - src = c1; - else - src = c2; - - pixman_image_composite32 (PIXMAN_OP_SRC, src, NULL, image, - 0, 0, 0, 0, i, j, - CHECK_SIZE, CHECK_SIZE); - } - } -} - int main (int argc, char **argv) { @@ -92,8 +58,8 @@ main (int argc, char **argv) dest_img = pixman_image_create_bits (PIXMAN_a8r8g8b8, WIDTH, HEIGHT, NULL, 0); - - fill_checkerboard (dest_img, WIDTH, HEIGHT); + + draw_checkerboard (dest_img, 25, 0xffaaaaaa, 0xff888888); pixman_transform_init_identity (&transform); diff --git a/pixman/demos/radial-test.c b/pixman/demos/radial-test.c index e64f3577f..08a367cd2 100644 --- a/pixman/demos/radial-test.c +++ b/pixman/demos/radial-test.c @@ -1,7 +1,7 @@ #include "../test/utils.h" #include "gtk-utils.h" -#define NUM_GRADIENTS 7 +#define NUM_GRADIENTS 9 #define NUM_STOPS 3 #define NUM_REPEAT 4 #define SIZE 128 @@ -28,6 +28,9 @@ * centers (0, 0) and (1, 0), but with different radiuses. From left * to right: * + * - Degenerate start circle completely inside the end circle + * 0.00 -> 1.75; dr = 1.75 > 0; a = 1 - 1.75^2 < 0 + * * - Small start circle completely inside the end circle * 0.25 -> 1.75; dr = 1.5 > 0; a = 1 - 1.50^2 < 0 * @@ -49,15 +52,20 @@ * - Small end circle completely inside the start circle * 1.75 -> 0.25; dr = -1.5 > 0; a = 1 - 1.50^2 < 0 * + * - Degenerate end circle completely inside the start circle + * 0.00 -> 1.75; dr = 1.75 > 0; a = 1 - 1.75^2 < 0 + * */ const static double radiuses[NUM_GRADIENTS] = { + 0.00, 0.25, 0.50, 0.50, 1.00, 1.00, 1.50, + 1.75, 1.75 }; @@ -139,6 +147,8 @@ main (int argc, char **argv) WIDTH, HEIGHT, NULL, 0); + draw_checkerboard (dest_img, 25, 0xffaaaaaa, 0xffbbbbbb); + pixman_transform_init_identity (&transform); /* diff --git a/pixman/pixman/pixman-radial-gradient.c b/pixman/pixman/pixman-radial-gradient.c index 8d562468d..6a217963d 100644 --- a/pixman/pixman/pixman-radial-gradient.c +++ b/pixman/pixman/pixman-radial-gradient.c @@ -109,7 +109,7 @@ radial_compute_color (double a, } else { - if (t * dr > mindr) + if (t * dr >= mindr) return _pixman_gradient_walker_pixel (walker, t); } @@ -145,9 +145,9 @@ radial_compute_color (double a, } else { - if (t0 * dr > mindr) + if (t0 * dr >= mindr) return _pixman_gradient_walker_pixel (walker, t0); - else if (t1 * dr > mindr) + else if (t1 * dr >= mindr) return _pixman_gradient_walker_pixel (walker, t1); } } diff --git a/pixman/test/utils.c b/pixman/test/utils.c index 66c8dcb89..08eaabbf6 100644 --- a/pixman/test/utils.c +++ b/pixman/test/utils.c @@ -548,6 +548,60 @@ write_png (pixman_image_t *image, const char *filename) #endif +static void +color8_to_color16 (uint32_t color8, pixman_color_t *color16) +{ + color16->alpha = ((color8 & 0xff000000) >> 24); + color16->red = ((color8 & 0x00ff0000) >> 16); + color16->green = ((color8 & 0x0000ff00) >> 8); + color16->blue = ((color8 & 0x000000ff) >> 0); + + color16->alpha |= color16->alpha << 8; + color16->red |= color16->red << 8; + color16->blue |= color16->blue << 8; + color16->green |= color16->green << 8; +} + +void +draw_checkerboard (pixman_image_t *image, + int check_size, + uint32_t color1, uint32_t color2) +{ + pixman_color_t check1, check2; + pixman_image_t *c1, *c2; + int n_checks_x, n_checks_y; + int i, j; + + color8_to_color16 (color1, &check1); + color8_to_color16 (color2, &check2); + + c1 = pixman_image_create_solid_fill (&check1); + c2 = pixman_image_create_solid_fill (&check2); + + n_checks_x = ( + pixman_image_get_width (image) + check_size - 1) / check_size; + n_checks_y = ( + pixman_image_get_height (image) + check_size - 1) / check_size; + + for (j = 0; j < n_checks_y; j++) + { + for (i = 0; i < n_checks_x; i++) + { + pixman_image_t *src; + + if (((i ^ j) & 1)) + src = c1; + else + src = c2; + + pixman_image_composite32 (PIXMAN_OP_SRC, src, NULL, image, + 0, 0, 0, 0, + i * check_size, j * check_size, + check_size, check_size); + } + } +} + /* * A function, which can be used as a core part of the test programs, * intended to detect various problems with the help of fuzzing input diff --git a/pixman/test/utils.h b/pixman/test/utils.h index 78cf0d16d..45b457ead 100644 --- a/pixman/test/utils.h +++ b/pixman/test/utils.h @@ -124,6 +124,11 @@ a8r8g8b8_to_rgba_np (uint32_t *dst, uint32_t *src, int n_pixels); pixman_bool_t write_png (pixman_image_t *image, const char *filename); +void +draw_checkerboard (pixman_image_t *image, + int check_size, + uint32_t color1, uint32_t color2); + /* A pair of macros which can help to detect corruption of * floating point registers after a function call. This may * happen if _mm_empty() call is forgotten in MMX/SSE2 fast |