diff options
124 files changed, 4282 insertions, 2791 deletions
diff --git a/libX11/modules/lc/gen/lcGenConv.c b/libX11/modules/lc/gen/lcGenConv.c index 7a113a78a..42d63c529 100644 --- a/libX11/modules/lc/gen/lcGenConv.c +++ b/libX11/modules/lc/gen/lcGenConv.c @@ -1784,9 +1784,6 @@ mbtocs( return( 0 ); } - if (*from_left > *to_left) - *from_left = *to_left; - while (*from_left && *to_left) { ch = *inbufptr++; @@ -1872,7 +1869,7 @@ output: return -1; } - /* nomal end */ + /* normal end */ *from = (XPointer) inbufptr; *to = (XPointer) outbufptr; @@ -2171,7 +2168,7 @@ end: return -1; } - /* nomal end */ + /* normal end */ *from = (XPointer) inbufptr; *to = (XPointer) outbufptr; @@ -2225,7 +2222,7 @@ end: return -1; } - /* nomal end */ + /* normal end */ *from = (XPointer) src; *from_left = src_left; diff --git a/libXft/src/xftglyphs.c b/libXft/src/xftglyphs.c index 2639d12aa..4a3b9d606 100644 --- a/libXft/src/xftglyphs.c +++ b/libXft/src/xftglyphs.c @@ -570,6 +570,9 @@ XftFontLoadGlyphs (Display *dpy, xftg->metrics.yOff = -TRUNC(ROUND(glyphslot->advance.y)); } + // compute the size of the final bitmap + ftbit = &glyphslot->bitmap; + width = ftbit->width; height = ftbit->rows; diff --git a/mesalib/configs/linux-dri b/mesalib/configs/linux-dri index a3e9baba2..aa2dddc1c 100644 --- a/mesalib/configs/linux-dri +++ b/mesalib/configs/linux-dri @@ -58,9 +58,9 @@ SRC_DIRS := glx egl $(SRC_DIRS) EGL_DRIVERS_DIRS = glx DRIVER_DIRS = dri -GALLIUM_WINSYS_DIRS = sw sw/xlib drm/vmware drm/intel drm/i965 -GALLIUM_TARGET_DIRS = -GALLIUM_STATE_TRACKERS_DIRS = egl +GALLIUM_WINSYS_DIRS = sw sw/xlib drm/vmware drm/intel drm/i965 svga/drm +GALLIUM_TARGET_DIRS = dri-vmwgfx +GALLIUM_STATE_TRACKERS_DIRS = egl dri DRI_DIRS = i915 i965 nouveau r200 r300 r600 radeon swrast diff --git a/mesalib/configure.ac b/mesalib/configure.ac index 0864b55af..369614528 100644 --- a/mesalib/configure.ac +++ b/mesalib/configure.ac @@ -1858,7 +1858,7 @@ if test "x$with_gallium_drivers" != x; then xnouveau) PKG_CHECK_MODULES([NOUVEAU], [libdrm_nouveau >= $LIBDRM_NOUVEAU_REQUIRED]) GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS nouveau nvfx nv50 nvc0" - gallium_check_st "nouveau/drm" "dri-nouveau" "xorg-nouveau" "" "xvmc-nouveau" + gallium_check_st "nouveau/drm" "dri-nouveau" "xorg-nouveau" "" "xvmc-nouveau" "vdpau-nouveau" ;; xswrast) GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS softpipe" diff --git a/mesalib/docs/contents.html b/mesalib/docs/contents.html index df0fb6474..8882e7318 100644 --- a/mesalib/docs/contents.html +++ b/mesalib/docs/contents.html @@ -64,6 +64,7 @@ a:visited { <LI><A HREF="mangling.html" target="MainFrame">Function Name Mangling</A> <LI><A href="llvmpipe.html" target="MainFrame">Gallium llvmpipe driver</A> <LI><A href="postprocess.html" target="MainFrame">Gallium post-processing</A> +<LI><A href="viewperf.html" target="MainFrame">Viewperf Issues</A> </ul> <b>Developer Topics</b> diff --git a/mesalib/docs/relnotes-7.12.html b/mesalib/docs/relnotes-7.12.html index 4077dac49..514962112 100644 --- a/mesalib/docs/relnotes-7.12.html +++ b/mesalib/docs/relnotes-7.12.html @@ -36,7 +36,7 @@ tbd <h2>New features</h2> <ul> -<li>GL_ARB_ES2_compatibility (r600g) +<li>GL_ARB_ES2_compatibility (r300g, r600g) <li>GL_ARB_depth_buffer_float (r600g) <li>GL_ARB_vertex_type_2_10_10_10_rev (r600g) <li>GL_EXT_packed_float (i965) diff --git a/mesalib/docs/viewperf.html b/mesalib/docs/viewperf.html new file mode 100644 index 000000000..cef584fd8 --- /dev/null +++ b/mesalib/docs/viewperf.html @@ -0,0 +1,134 @@ +<HTML> + +<TITLE>Viewperf Issues</TITLE> + +<link rel="stylesheet" type="text/css" href="mesa.css"></head> + +<BODY> + +<h1>Viewperf Issues</h1> + +<p> +This page lists known issues with +<a href="http://www.spec.org/gwpg/gpc.static/vp11info.html" target="_main">SPEC Viewperf 11</a> +when running on Mesa-based drivers. +</p> + +<p> +The Viewperf data sets are basically GL API traces that are recorded from +CAD applications, then replayed in the Viewperf framework. +</p> + +<p> +The primary problem with these traces is they blindly use features and +OpenGL extensions that were supported by the OpenGL driver when the trace +was recorded, +but there's no checks to see if those features are supported by the driver +when playing back the traces with Viewperf. +</p> + +<p> +These issues have been reported to the SPEC organization in the hope that +they'll be fixed in the future. +</p> + + + +<h2>Catia-03 tests 3, 4, 8</h2> + +<p> +These tests use features of the +<a href="http://www.opengl.org/registry/specs/NV/fragment_program2.txt" +target="_main"> +GL_NV_fragment_program2</a> and +<a href="http://www.opengl.org/registry/specs/NV/vertex_program3.txt" +target="_main"> +GL_NV_vertex_program3</a> extensions without checking if the driver supports +them. +</p> +<p> +When Mesa tries to compile the vertex/fragment programs it generates errors +(which Viewperf ignores). +Subsequent drawing calls become no-ops and the rendering is incorrect. +</p> + + + +<h2>sw-02 tests 1, 2, 4</h2> + +<p> +These tests depend on the +<a href="http://www.opengl.org/registry/specs/NV/primitive_restart.txt" +target="_main">GL_NV_primitive_restart</a> extension. +</p> + +<p> +If the Mesa driver doesn't support this extension the rendering will +be incorrect and the test will fail. +</p> + + +<h2>Lightwave-01 test 3</h2> + +<p> +This test uses a number of mipmapped textures, but the textures are +incomplete because the last/smallest mipmap level (1 x 1 pixel) is +never specified. +</p> + +<p> +A trace captured with +<a href="https://github.com/apitrace/apitrace" target="_main">API trace</a> +shows this sequences of calls like this: + +<pre> +2504 glBindTexture(target = GL_TEXTURE_2D, texture = 55) +2505 glTexImage2D(target = GL_TEXTURE_2D, level = 0, internalformat = GL_RGBA, width = 512, height = 512, border = 0, format = GL_RGB, type = GL_UNSIGNED_SHORT, pixels = blob(1572864)) +2506 glTexImage2D(target = GL_TEXTURE_2D, level = 1, internalformat = GL_RGBA, width = 256, height = 256, border = 0, format = GL_RGB, type = GL_UNSIGNED_SHORT, pixels = blob(393216)) +2507 glTexImage2D(target = GL_TEXTURE_2D, level = 2, internalformat = GL_RGBA, width = 128, height = 128, border = 0, format = GL_RGB, type = GL_UNSIGNED_SHORT, pixels = blob(98304)) +[...] +2512 glTexImage2D(target = GL_TEXTURE_2D, level = 7, internalformat = GL_RGBA, width = 4, height = 4, border = 0, format = GL_RGB, type = GL_UNSIGNED_SHORT, pixels = blob(96)) +2513 glTexImage2D(target = GL_TEXTURE_2D, level = 8, internalformat = GL_RGBA, width = 2, height = 2, border = 0, format = GL_RGB, type = GL_UNSIGNED_SHORT, pixels = blob(24)) +2514 glTexParameteri(target = GL_TEXTURE_2D, pname = GL_TEXTURE_MIN_FILTER, param = GL_LINEAR_MIPMAP_LINEAR) +2515 glTexParameteri(target = GL_TEXTURE_2D, pname = GL_TEXTURE_WRAP_S, param = GL_REPEAT) +2516 glTexParameteri(target = GL_TEXTURE_2D, pname = GL_TEXTURE_WRAP_T, param = GL_REPEAT) +2517 glTexParameteri(target = GL_TEXTURE_2D, pname = GL_TEXTURE_MAG_FILTER, param = GL_NEAREST) +</pre> + +<p> +Note that one would expect call 2514 to be glTexImage(level=9, width=1, +height=1) but it's not there. +</p> + +<p> +The minification filter is GL_LINEAR_MIPMAP_LINEAR and the texture's +GL_TEXTURE_MAX_LEVEL is 1000 (the default) so a full mipmap is expected. +</p> + +<p> +Later, these incomplete textures are bound before drawing calls. +According to the GL specification, if a fragment program or fragment shader +is being used, the sampler should return (0,0,0,1) ("black") when sampling +from an incomplete texture. +This is what Mesa does and the resulting rendering is darker than it should +be. +</p> + +<p> +It appears that NVIDIA's driver (and possibly AMD's driver) detects this case +and returns (1,1,1,1) (white) which causes the rendering to appear brighter +and match the reference image (however, AMD's rendering is <em>much</em> +brighter than NVIDIA's). +</p> + +<p> +If the fallback texture created in _mesa_get_fallback_texture() is +initialized to be full white instead of full black the rendering appears +correct. +However, we have no plans to implement this work-around in Mesa. + +</p> + + +</BODY> +</HTML> diff --git a/mesalib/include/GL/gl.h b/mesalib/include/GL/gl.h index 998a83ab1..e65e1bc8a 100644 --- a/mesalib/include/GL/gl.h +++ b/mesalib/include/GL/gl.h @@ -67,7 +67,7 @@ #elif defined(__CYGWIN__) && defined(USE_OPENGL32) /* use native windows opengl32 */ # define GLAPI extern # define GLAPIENTRY __stdcall -#elif defined(__GNUC__) || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590)) +#elif (defined(__GNUC__) && __GNUC__ >= 4) || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590)) # define GLAPI __attribute__((visibility("default"))) # define GLAPIENTRY #endif /* WIN32 && !CYGWIN */ diff --git a/mesalib/src/gallium/auxiliary/util/u_blitter.c b/mesalib/src/gallium/auxiliary/util/u_blitter.c index b0d538de6..f5cc5cb3b 100644 --- a/mesalib/src/gallium/auxiliary/util/u_blitter.c +++ b/mesalib/src/gallium/auxiliary/util/u_blitter.c @@ -59,7 +59,6 @@ struct blitter_context_priv float vertices[4][2][4]; /**< {pos, color} or {pos, texcoord} */ /* Templates for various state objects. */ - struct pipe_sampler_state template_sampler_state; /* Constant state objects. */ /* Vertex shaders. */ @@ -92,8 +91,8 @@ struct blitter_context_priv void *velem_uint_state; void *velem_sint_state; - /* Sampler state for clamping to a miplevel. */ - void *sampler_state[PIPE_MAX_TEXTURE_LEVELS * 2]; + /* Sampler state. */ + void *sampler_state; /* Rasterizer state. */ void *rs_state; @@ -126,7 +125,7 @@ struct blitter_context *util_blitter_create(struct pipe_context *pipe) struct pipe_blend_state blend; struct pipe_depth_stencil_alpha_state dsa; struct pipe_rasterizer_state rs_state; - struct pipe_sampler_state *sampler_state; + struct pipe_sampler_state sampler_state; struct pipe_vertex_element velem[2]; unsigned i; @@ -192,13 +191,12 @@ struct blitter_context *util_blitter_create(struct pipe_context *pipe) pipe->create_depth_stencil_alpha_state(pipe, &dsa); /* sampler state */ - sampler_state = &ctx->template_sampler_state; - sampler_state->wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; - sampler_state->wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; - sampler_state->wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; - sampler_state->normalized_coords = TRUE; - /* The sampler state objects which sample from a specified mipmap level - * are created on-demand. */ + memset(&sampler_state, 0, sizeof(sampler_state)); + sampler_state.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + sampler_state.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + sampler_state.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + sampler_state.normalized_coords = 1; + ctx->sampler_state = pipe->create_sampler_state(pipe, &sampler_state); /* rasterizer state */ memset(&rs_state, 0, sizeof(rs_state)); @@ -292,10 +290,7 @@ void util_blitter_destroy(struct blitter_context *blitter) pipe->delete_fs_state(pipe, ctx->fs_col_int[i]); } - for (i = 0; i < PIPE_MAX_TEXTURE_LEVELS * 2; i++) - if (ctx->sampler_state[i]) - pipe->delete_sampler_state(pipe, ctx->sampler_state[i]); - + pipe->delete_sampler_state(pipe, ctx->sampler_state); pipe_resource_reference(&ctx->vbuf, NULL); FREE(ctx); } @@ -497,21 +492,22 @@ static void blitter_set_clear_color(struct blitter_context_priv *ctx, } } -static void get_texcoords(struct pipe_resource *src, - unsigned level, +static void get_texcoords(struct pipe_sampler_view *src, + unsigned src_width0, unsigned src_height0, unsigned x1, unsigned y1, unsigned x2, unsigned y2, - boolean normalized, float out[4]) + float out[4]) { - if(normalized) - { - out[0] = x1 / (float)u_minify(src->width0, level); - out[1] = y1 / (float)u_minify(src->height0, level); - out[2] = x2 / (float)u_minify(src->width0, level); - out[3] = y2 / (float)u_minify(src->height0, level); - } - else - { + struct pipe_resource *tex = src->texture; + unsigned level = src->u.tex.first_level; + boolean normalized = tex->target != PIPE_TEXTURE_RECT; + + if (normalized) { + out[0] = x1 / (float)u_minify(src_width0, level); + out[1] = y1 / (float)u_minify(src_height0, level); + out[2] = x2 / (float)u_minify(src_width0, level); + out[3] = y2 / (float)u_minify(src_height0, level); + } else { out[0] = x1; out[1] = y1; out[2] = x2; @@ -535,76 +531,52 @@ static void set_texcoords_in_vertices(const float coord[4], out[1] = coord[3]; /*t3.t*/ } -static void blitter_set_texcoords_2d(struct blitter_context_priv *ctx, - struct pipe_resource *src, - unsigned level, - unsigned x1, unsigned y1, - unsigned x2, unsigned y2) +static void blitter_set_texcoords(struct blitter_context_priv *ctx, + struct pipe_sampler_view *src, + unsigned src_width0, unsigned src_height0, + unsigned layer, + unsigned x1, unsigned y1, + unsigned x2, unsigned y2) { unsigned i; float coord[4]; + float face_coord[4][2]; - get_texcoords(src, level, x1, y1, x2, y2, TRUE, coord); - set_texcoords_in_vertices(coord, &ctx->vertices[0][1][0], 8); + get_texcoords(src, src_width0, src_height0, x1, y1, x2, y2, coord); - for (i = 0; i < 4; i++) { - ctx->vertices[i][1][2] = 0; /*r*/ - ctx->vertices[i][1][3] = 1; /*q*/ + if (src->texture->target == PIPE_TEXTURE_CUBE) { + set_texcoords_in_vertices(coord, &face_coord[0][0], 2); + util_map_texcoords2d_onto_cubemap(layer, + /* pointer, stride in floats */ + &face_coord[0][0], 2, + &ctx->vertices[0][1][0], 8); + } else { + set_texcoords_in_vertices(coord, &ctx->vertices[0][1][0], 8); } -} - -static void blitter_set_texcoords_3d(struct blitter_context_priv *ctx, - struct pipe_resource *src, - unsigned level, - unsigned zslice, - unsigned x1, unsigned y1, - unsigned x2, unsigned y2, - boolean normalized) -{ - int i; - float r = normalized ? zslice / (float)u_minify(src->depth0, level) : zslice; - - blitter_set_texcoords_2d(ctx, src, level, x1, y1, x2, y2); - - for (i = 0; i < 4; i++) - ctx->vertices[i][1][2] = r; /*r*/ -} -static void blitter_set_texcoords_1d_array(struct blitter_context_priv *ctx, - struct pipe_resource *src, - unsigned level, - unsigned zslice, - unsigned x1, unsigned x2) -{ - int i; - float r = zslice; - - blitter_set_texcoords_2d(ctx, src, level, x1, 0, x2, 0); - - for (i = 0; i < 4; i++) - ctx->vertices[i][1][1] = r; /*r*/ -} - -static void blitter_set_texcoords_cube(struct blitter_context_priv *ctx, - struct pipe_resource *src, - unsigned level, unsigned face, - unsigned x1, unsigned y1, - unsigned x2, unsigned y2) -{ - int i; - float coord[4]; - float st[4][2]; + /* Set the layer. */ + switch (src->texture->target) { + case PIPE_TEXTURE_3D: + { + float r = layer / (float)u_minify(src->texture->depth0, + src->u.tex.first_level); + for (i = 0; i < 4; i++) + ctx->vertices[i][1][2] = r; /*r*/ + } + break; - get_texcoords(src, level, x1, y1, x2, y2, TRUE, coord); - set_texcoords_in_vertices(coord, &st[0][0], 2); + case PIPE_TEXTURE_1D_ARRAY: + for (i = 0; i < 4; i++) + ctx->vertices[i][1][1] = layer; /*t*/ + break; - util_map_texcoords2d_onto_cubemap(face, - /* pointer, stride in floats */ - &st[0][0], 2, - &ctx->vertices[0][1][0], 8); + case PIPE_TEXTURE_2D_ARRAY: + for (i = 0; i < 4; i++) + ctx->vertices[i][1][2] = layer; /*r*/ + break; - for (i = 0; i < 4; i++) - ctx->vertices[i][1][3] = 1; /*q*/ + default:; + } } static void blitter_set_dst_dimensions(struct blitter_context_priv *ctx, @@ -615,31 +587,6 @@ static void blitter_set_dst_dimensions(struct blitter_context_priv *ctx, } static INLINE -void **blitter_get_sampler_state(struct blitter_context_priv *ctx, - int miplevel, boolean normalized) -{ - struct pipe_context *pipe = ctx->base.pipe; - struct pipe_sampler_state *sampler_state = &ctx->template_sampler_state; - - assert(miplevel < PIPE_MAX_TEXTURE_LEVELS); - - /* Create the sampler state on-demand. */ - if (!ctx->sampler_state[miplevel * 2 + normalized]) { - sampler_state->lod_bias = miplevel; - sampler_state->min_lod = miplevel; - sampler_state->max_lod = miplevel; - sampler_state->normalized_coords = normalized; - - ctx->sampler_state[miplevel * 2 + normalized] = pipe->create_sampler_state(pipe, - sampler_state); - } - - /* Return void** so that it can be passed to bind_fragment_sampler_states - * directly. */ - return &ctx->sampler_state[miplevel * 2 + normalized]; -} - -static INLINE void *blitter_get_fs_col(struct blitter_context_priv *ctx, unsigned num_cbufs, boolean int_format) { @@ -864,27 +811,16 @@ void util_blitter_copy_texture(struct blitter_context *blitter, struct pipe_context *pipe = ctx->base.pipe; struct pipe_screen *screen = pipe->screen; struct pipe_surface *dstsurf, surf_templ; - struct pipe_framebuffer_state fb_state; struct pipe_sampler_view viewTempl, *view; unsigned bind; - unsigned width = srcbox->width; - unsigned height = srcbox->height; boolean is_stencil, is_depth; - boolean normalized; /* Give up if textures are not set. */ assert(dst && src); if (!dst || !src) return; - /* Sanity checks. */ - if (dst == src) { - assert(!is_overlap(srcbox->x, srcbox->x + width, srcbox->y, srcbox->y + height, - dstx, dstx + width, dsty, dsty + height)); - } assert(src->target < PIPE_MAX_TEXTURE_TYPES); - /* XXX should handle 3d regions */ - assert(srcbox->depth == 1); /* Is this a ZS format? */ is_depth = util_format_get_component_bits(src->format, UTIL_FORMAT_COLORSPACE_ZS, 0) != 0; @@ -902,22 +838,60 @@ void util_blitter_copy_texture(struct blitter_context *blitter, dst->nr_samples, bind) || !screen->is_format_supported(screen, src->format, src->target, src->nr_samples, PIPE_BIND_SAMPLER_VIEW)) { - ctx->base.running = TRUE; + blitter_set_running_flag(ctx); util_resource_copy_region(pipe, dst, dstlevel, dstx, dsty, dstz, src, srclevel, srcbox); - ctx->base.running = FALSE; + blitter_unset_running_flag(ctx); return; } - /* Get surface. */ + /* Initialize the surface. */ memset(&surf_templ, 0, sizeof(surf_templ)); u_surface_default_template(&surf_templ, dst, bind); surf_templ.format = util_format_linear(dst->format); surf_templ.u.tex.level = dstlevel; surf_templ.u.tex.first_layer = dstz; - surf_templ.u.tex.last_layer = dstz; + surf_templ.u.tex.last_layer = dstz + srcbox->depth - 1; dstsurf = pipe->create_surface(pipe, dst, &surf_templ); + /* Initialize the sampler view. */ + u_sampler_view_default_template(&viewTempl, src, + util_format_linear(src->format)); + viewTempl.u.tex.first_level = srclevel; + viewTempl.u.tex.last_level = srclevel; + view = pipe->create_sampler_view(pipe, src, &viewTempl); + + /* Copy. */ + util_blitter_copy_texture_view(blitter, dstsurf, dstx, dsty, view, srcbox, + src->width0, src->height0); + + pipe_surface_reference(&dstsurf, NULL); + pipe_sampler_view_reference(&view, NULL); +} + +void util_blitter_copy_texture_view(struct blitter_context *blitter, + struct pipe_surface *dst, + unsigned dstx, unsigned dsty, + struct pipe_sampler_view *src, + const struct pipe_box *srcbox, + unsigned src_width0, unsigned src_height0) +{ + struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter; + struct pipe_context *pipe = ctx->base.pipe; + struct pipe_framebuffer_state fb_state; + enum pipe_texture_target src_target = src->texture->target; + unsigned width = srcbox->width; + unsigned height = srcbox->height; + + /* Sanity checks. */ + if (dst->texture == src->texture && + dst->u.tex.level == src->u.tex.first_level) { + assert(!is_overlap(srcbox->x, srcbox->x + width, srcbox->y, srcbox->y + height, + dstx, dstx + width, dsty, dsty + height)); + } + /* XXX should handle 3d regions */ + assert(srcbox->depth == 1); + /* Check whether the states are properly saved. */ blitter_set_running_flag(ctx); blitter_check_saved_vertex_states(ctx); @@ -926,60 +900,55 @@ void util_blitter_copy_texture(struct blitter_context *blitter, blitter_check_saved_fb_state(ctx); /* Initialize framebuffer state. */ - fb_state.width = dstsurf->width; - fb_state.height = dstsurf->height; + fb_state.width = dst->width; + fb_state.height = dst->height; - if (is_depth) { + if (util_format_is_depth_or_stencil(dst->format)) { pipe->bind_blend_state(pipe, ctx->blend_keep_color); pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_keep_stencil); pipe->bind_fs_state(pipe, - blitter_get_fs_texfetch_depth(ctx, src->target)); + blitter_get_fs_texfetch_depth(ctx, src_target)); fb_state.nr_cbufs = 0; - fb_state.zsbuf = dstsurf; + fb_state.zsbuf = dst; } else { pipe->bind_blend_state(pipe, ctx->blend_write_color); pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil); pipe->bind_fs_state(pipe, - blitter_get_fs_texfetch_col(ctx, src->target)); + blitter_get_fs_texfetch_col(ctx, src_target)); fb_state.nr_cbufs = 1; - fb_state.cbufs[0] = dstsurf; + fb_state.cbufs[0] = dst; fb_state.zsbuf = 0; } - normalized = src->target != PIPE_TEXTURE_RECT; - - /* Initialize sampler view. */ - u_sampler_view_default_template(&viewTempl, src, util_format_linear(src->format)); - view = pipe->create_sampler_view(pipe, src, &viewTempl); - /* Set rasterizer state, shaders, and textures. */ pipe->bind_rasterizer_state(pipe, ctx->rs_state); pipe->bind_vs_state(pipe, ctx->vs); if (ctx->has_geometry_shader) pipe->bind_gs_state(pipe, NULL); - pipe->bind_fragment_sampler_states(pipe, 1, - blitter_get_sampler_state(ctx, srclevel, normalized)); + pipe->bind_fragment_sampler_states(pipe, 1, &ctx->sampler_state); pipe->bind_vertex_elements_state(pipe, ctx->velem_state); - pipe->set_fragment_sampler_views(pipe, 1, &view); + pipe->set_fragment_sampler_views(pipe, 1, &src); pipe->set_framebuffer_state(pipe, &fb_state); - blitter_set_dst_dimensions(ctx, dstsurf->width, dstsurf->height); + blitter_set_dst_dimensions(ctx, dst->width, dst->height); - switch (src->target) { + switch (src_target) { /* Draw the quad with the draw_rectangle callback. */ case PIPE_TEXTURE_1D: case PIPE_TEXTURE_2D: case PIPE_TEXTURE_RECT: { /* Set texture coordinates. - use a pipe color union - * for interface purposes + * for interface purposes. + * XXX pipe_color_union is a wrong name since we use that to set + * texture coordinates too. */ union pipe_color_union coord; - get_texcoords(src, srclevel, srcbox->x, srcbox->y, - srcbox->x+width, srcbox->y+height, normalized, coord.f); + get_texcoords(src, src_width0, src_height0, srcbox->x, srcbox->y, + srcbox->x+width, srcbox->y+height, coord.f); /* Draw. */ blitter->draw_rectangle(blitter, dstx, dsty, dstx+width, dsty+height, 0, @@ -990,24 +959,14 @@ void util_blitter_copy_texture(struct blitter_context *blitter, /* Draw the quad with the generic codepath. */ default: /* Set texture coordinates. */ - switch (src->target) { + switch (src_target) { case PIPE_TEXTURE_1D_ARRAY: - blitter_set_texcoords_1d_array(ctx, src, srclevel, srcbox->y, - srcbox->x, srcbox->x + width); - break; - case PIPE_TEXTURE_2D_ARRAY: case PIPE_TEXTURE_3D: - blitter_set_texcoords_3d(ctx, src, srclevel, srcbox->z, - srcbox->x, srcbox->y, - srcbox->x + width, srcbox->y + height, - src->target == PIPE_TEXTURE_3D); - break; - case PIPE_TEXTURE_CUBE: - blitter_set_texcoords_cube(ctx, src, srclevel, srcbox->z, - srcbox->x, srcbox->y, - srcbox->x + width, srcbox->y + height); + blitter_set_texcoords(ctx, src, src_width0, src_height0, srcbox->z, + srcbox->y, srcbox->x, + srcbox->x + width, srcbox->y + height); break; default: @@ -1028,9 +987,6 @@ void util_blitter_copy_texture(struct blitter_context *blitter, blitter_restore_textures(ctx); blitter_restore_fb_state(ctx); blitter_unset_running_flag(ctx); - - pipe_surface_reference(&dstsurf, NULL); - pipe_sampler_view_reference(&view, NULL); } /* Clear a region of a color surface to a constant value. */ diff --git a/mesalib/src/gallium/auxiliary/util/u_blitter.h b/mesalib/src/gallium/auxiliary/util/u_blitter.h index 798096e74..3e1457ae0 100644 --- a/mesalib/src/gallium/auxiliary/util/u_blitter.h +++ b/mesalib/src/gallium/auxiliary/util/u_blitter.h @@ -190,6 +190,30 @@ void util_blitter_copy_texture(struct blitter_context *blitter, boolean ignore_stencil); /** + * Same as util_blitter_copy_texture, but dst and src are pipe_surface and + * pipe_sampler_view, respectively. The mipmap level and dstz are part of + * the views. + * + * Drivers can use this to change resource properties (like format, width, + * height) by changing how the views interpret them, instead of changing + * pipe_resource directly. This is usually needed to accelerate copying of + * compressed formats. + * + * src_width0 and src_height0 are sampler_view-private properties that + * override pipe_resource. The blitter uses them for computation of texture + * coordinates. The dst dimensions are supplied through pipe_surface::width + * and height. + * + * NOTE: There are no checks whether the blit is actually supported. + */ +void util_blitter_copy_texture_view(struct blitter_context *blitter, + struct pipe_surface *dst, + unsigned dstx, unsigned dsty, + struct pipe_sampler_view *src, + const struct pipe_box *srcbox, + unsigned src_width0, unsigned src_height0); + +/** * Clear a region of a (color) surface to a constant value. * * These states must be saved in the blitter in addition to the state objects diff --git a/mesalib/src/gallium/auxiliary/util/u_upload_mgr.c b/mesalib/src/gallium/auxiliary/util/u_upload_mgr.c index 71fe53e3a..a2319d0c4 100644 --- a/mesalib/src/gallium/auxiliary/util/u_upload_mgr.c +++ b/mesalib/src/gallium/auxiliary/util/u_upload_mgr.c @@ -131,8 +131,9 @@ u_upload_alloc_buffer( struct u_upload_mgr *upload, upload->bind, PIPE_USAGE_STREAM, size ); - if (upload->buffer == NULL) - goto fail; + if (upload->buffer == NULL) { + return PIPE_ERROR_OUT_OF_MEMORY; + } /* Map the new buffer. */ upload->map = pipe_buffer_map_range(upload->pipe, upload->buffer, @@ -140,17 +141,16 @@ u_upload_alloc_buffer( struct u_upload_mgr *upload, PIPE_TRANSFER_WRITE | PIPE_TRANSFER_FLUSH_EXPLICIT, &upload->transfer); - + if (upload->map == NULL) { + upload->size = 0; + pipe_resource_reference(&upload->buffer, NULL); + return PIPE_ERROR_OUT_OF_MEMORY; + } + upload->size = size; upload->offset = 0; - return 0; - -fail: - if (upload->buffer) - pipe_resource_reference( &upload->buffer, NULL ); - - return PIPE_ERROR_OUT_OF_MEMORY; + return PIPE_OK; } enum pipe_error u_upload_alloc( struct u_upload_mgr *upload, @@ -170,7 +170,7 @@ enum pipe_error u_upload_alloc( struct u_upload_mgr *upload, if (MAX2(upload->offset, alloc_offset) + alloc_size > upload->size) { enum pipe_error ret = u_upload_alloc_buffer(upload, alloc_offset + alloc_size); - if (ret) + if (ret != PIPE_OK) return ret; *flushed = TRUE; @@ -187,6 +187,11 @@ enum pipe_error u_upload_alloc( struct u_upload_mgr *upload, PIPE_TRANSFER_FLUSH_EXPLICIT | PIPE_TRANSFER_UNSYNCHRONIZED, &upload->transfer); + if (!upload->map) { + pipe_resource_reference(outbuf, NULL); + *ptr = NULL; + return PIPE_ERROR_OUT_OF_MEMORY; + } } assert(offset < upload->buffer->width0); @@ -214,7 +219,7 @@ enum pipe_error u_upload_data( struct u_upload_mgr *upload, enum pipe_error ret = u_upload_alloc(upload, min_out_offset, size, out_offset, outbuf, flushed, (void**)&ptr); - if (ret) + if (ret != PIPE_OK) return ret; memcpy(ptr, data, size); @@ -247,8 +252,7 @@ enum pipe_error u_upload_buffer( struct u_upload_mgr *upload, &transfer); if (map == NULL) { - ret = PIPE_ERROR_OUT_OF_MEMORY; - goto done; + return PIPE_ERROR_OUT_OF_MEMORY; } if (0) @@ -261,9 +265,7 @@ enum pipe_error u_upload_buffer( struct u_upload_mgr *upload, out_offset, outbuf, flushed ); -done: - if (map) - pipe_buffer_unmap( upload->pipe, transfer ); + pipe_buffer_unmap( upload->pipe, transfer ); return ret; } diff --git a/mesalib/src/glsl/Makefile b/mesalib/src/glsl/Makefile index b2efb2abc..504f1fb43 100644 --- a/mesalib/src/glsl/Makefile +++ b/mesalib/src/glsl/Makefile @@ -53,6 +53,7 @@ CXX_SOURCES = \ ir_variable_refcount.cpp \ linker.cpp \ link_functions.cpp \ + link_uniforms.cpp \ loop_analysis.cpp \ loop_controls.cpp \ loop_unroll.cpp \ diff --git a/mesalib/src/glsl/SConscript b/mesalib/src/glsl/SConscript index b4786c5e5..09c7edbc4 100644 --- a/mesalib/src/glsl/SConscript +++ b/mesalib/src/glsl/SConscript @@ -64,6 +64,7 @@ glsl_sources = [ 'ir_variable_refcount.cpp', 'linker.cpp', 'link_functions.cpp', + 'link_uniforms.cpp', 'loop_analysis.cpp', 'loop_controls.cpp', 'loop_unroll.cpp', diff --git a/mesalib/src/glsl/builtin_variables.h b/mesalib/src/glsl/builtin_variables.h index d25bbf42a..237b361d8 100644 --- a/mesalib/src/glsl/builtin_variables.h +++ b/mesalib/src/glsl/builtin_variables.h @@ -103,8 +103,8 @@ static const builtin_variable builtin_110_deprecated_uniforms[] = { { ir_var_uniform, -1, "gl_LightModelParameters", "gl_LightModel"}, /* Mesa-internal ATI_envmap_bumpmap state. */ - { ir_var_uniform, -1, "vec2", "gl_MESABumpRotMatrix0"}, - { ir_var_uniform, -1, "vec2", "gl_MESABumpRotMatrix1"}, - { ir_var_uniform, -1, "vec4", "gl_MESAFogParamsOptimized"}, + { ir_var_uniform, -1, "vec2", "gl_BumpRotMatrix0MESA"}, + { ir_var_uniform, -1, "vec2", "gl_BumpRotMatrix1MESA"}, + { ir_var_uniform, -1, "vec4", "gl_FogParamsOptimizedMESA"}, }; diff --git a/mesalib/src/glsl/glsl_parser_extras.cpp b/mesalib/src/glsl/glsl_parser_extras.cpp index a9075b2b1..e2112fe6d 100644 --- a/mesalib/src/glsl/glsl_parser_extras.cpp +++ b/mesalib/src/glsl/glsl_parser_extras.cpp @@ -883,8 +883,27 @@ ast_struct_specifier::ast_struct_specifier(char *identifier, this->declarations.push_degenerate_list_at_head(&declarator_list->link); } +/** + * Do the set of common optimizations passes + * + * \param ir List of instructions to be optimized + * \param linked Is the shader linked? This enables + * optimizations passes that remove code at + * global scope and could cause linking to + * fail. + * \param uniform_locations_assigned Have locations already been assigned for + * uniforms? This prevents the declarations + * of unused uniforms from being removed. + * The setting of this flag only matters if + * \c linked is \c true. + * \param max_unroll_iterations Maximum number of loop iterations to be + * unrolled. Setting to 0 forces all loops + * to be unrolled. + */ bool -do_common_optimization(exec_list *ir, bool linked, unsigned max_unroll_iterations) +do_common_optimization(exec_list *ir, bool linked, + bool uniform_locations_assigned, + unsigned max_unroll_iterations) { GLboolean progress = GL_FALSE; @@ -900,7 +919,7 @@ do_common_optimization(exec_list *ir, bool linked, unsigned max_unroll_iteration progress = do_copy_propagation(ir) || progress; progress = do_copy_propagation_elements(ir) || progress; if (linked) - progress = do_dead_code(ir) || progress; + progress = do_dead_code(ir, uniform_locations_assigned) || progress; else progress = do_dead_code_unlinked(ir) || progress; progress = do_dead_code_local(ir) || progress; diff --git a/mesalib/src/glsl/ir_constant_expression.cpp b/mesalib/src/glsl/ir_constant_expression.cpp index b3fe6cf96..83f084d88 100644 --- a/mesalib/src/glsl/ir_constant_expression.cpp +++ b/mesalib/src/glsl/ir_constant_expression.cpp @@ -39,6 +39,25 @@ #include "ir_visitor.h" #include "glsl_types.h" +/* Using C99 rounding functions for roundToEven() implementation is + * difficult, because round(), rint, and nearbyint() are affected by + * fesetenv(), which the application may have done for its own + * purposes. Mesa's IROUND macro is close to what we want, but it + * rounds away from 0 on n + 0.5. + */ +static int +round_to_even(float val) +{ + int rounded = IROUND(val); + + if (val - floor(val) == 0.5) { + if (rounded % 2 != 0) + rounded += val > 0 ? -1 : 1; + } + + return rounded; +} + static float dot(ir_constant *op0, ir_constant *op1) { @@ -196,6 +215,13 @@ ir_expression::constant_expression_value() } break; + case ir_unop_round_even: + assert(op[0]->type->base_type == GLSL_TYPE_FLOAT); + for (unsigned c = 0; c < op[0]->type->components(); c++) { + data.f[c] = round_to_even(op[0]->value.f[c]); + } + break; + case ir_unop_ceil: assert(op[0]->type->base_type == GLSL_TYPE_FLOAT); for (unsigned c = 0; c < op[0]->type->components(); c++) { @@ -1324,6 +1350,9 @@ ir_call::constant_expression_value() * op[1]->value.f[c]; } } + } else if (strcmp(callee, "round") == 0 || + strcmp(callee, "roundEven") == 0) { + expr = new(mem_ctx) ir_expression(ir_unop_round_even, op[0]); } else if (strcmp(callee, "sign") == 0) { expr = new(mem_ctx) ir_expression(ir_unop_sign, type, op[0], NULL); } else if (strcmp(callee, "sin") == 0) { diff --git a/mesalib/src/glsl/ir_optimization.h b/mesalib/src/glsl/ir_optimization.h index af80e26b9..7b32e84f0 100644 --- a/mesalib/src/glsl/ir_optimization.h +++ b/mesalib/src/glsl/ir_optimization.h @@ -37,7 +37,9 @@ #define MOD_TO_FRACT 0x20 #define INT_DIV_TO_MUL_RCP 0x40 -bool do_common_optimization(exec_list *ir, bool linked, unsigned max_unroll_iterations); +bool do_common_optimization(exec_list *ir, bool linked, + bool uniform_locations_assigned, + unsigned max_unroll_iterations); bool do_algebraic(exec_list *instructions); bool do_constant_folding(exec_list *instructions); @@ -46,7 +48,7 @@ bool do_constant_variable_unlinked(exec_list *instructions); bool do_copy_propagation(exec_list *instructions); bool do_copy_propagation_elements(exec_list *instructions); bool do_constant_propagation(exec_list *instructions); -bool do_dead_code(exec_list *instructions); +bool do_dead_code(exec_list *instructions, bool uniform_locations_assigned); bool do_dead_code_local(exec_list *instructions); bool do_dead_code_unlinked(exec_list *instructions); bool do_dead_functions(exec_list *instructions); diff --git a/mesalib/src/glsl/ir_variable.cpp b/mesalib/src/glsl/ir_variable.cpp index 6ae3b1f9e..1ee84d219 100644 --- a/mesalib/src/glsl/ir_variable.cpp +++ b/mesalib/src/glsl/ir_variable.cpp @@ -166,15 +166,15 @@ static struct gl_builtin_uniform_element gl_NormalScale_elements[] = { {NULL, {STATE_NORMAL_SCALE}, SWIZZLE_XXXX}, }; -static struct gl_builtin_uniform_element gl_MESABumpRotMatrix0_elements[] = { +static struct gl_builtin_uniform_element gl_BumpRotMatrix0MESA_elements[] = { {NULL, {STATE_INTERNAL, STATE_ROT_MATRIX_0}, SWIZZLE_XYZW}, }; -static struct gl_builtin_uniform_element gl_MESABumpRotMatrix1_elements[] = { +static struct gl_builtin_uniform_element gl_BumpRotMatrix1MESA_elements[] = { {NULL, {STATE_INTERNAL, STATE_ROT_MATRIX_1}, SWIZZLE_XYZW}, }; -static struct gl_builtin_uniform_element gl_MESAFogParamsOptimized_elements[] = { +static struct gl_builtin_uniform_element gl_FogParamsOptimizedMESA_elements[] = { {NULL, {STATE_INTERNAL, STATE_FOG_PARAMS_OPTIMIZED}, SWIZZLE_XYZW}, }; @@ -232,11 +232,11 @@ MATRIX(gl_TextureMatrixInverseTranspose, static struct gl_builtin_uniform_element gl_NormalMatrix_elements[] = { { NULL, { STATE_MODELVIEW_MATRIX, 0, 0, 0, STATE_MATRIX_INVERSE}, - SWIZZLE_XYZW }, + MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_Z) }, { NULL, { STATE_MODELVIEW_MATRIX, 0, 1, 1, STATE_MATRIX_INVERSE}, - SWIZZLE_XYZW }, + MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_Z) }, { NULL, { STATE_MODELVIEW_MATRIX, 0, 2, 2, STATE_MATRIX_INVERSE}, - SWIZZLE_XYZW }, + MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_Z) }, }; #undef MATRIX @@ -289,9 +289,9 @@ const struct gl_builtin_uniform_desc _mesa_builtin_uniform_desc[] = { STATEVAR(gl_NormalMatrix), STATEVAR(gl_NormalScale), - STATEVAR(gl_MESABumpRotMatrix0), - STATEVAR(gl_MESABumpRotMatrix1), - STATEVAR(gl_MESAFogParamsOptimized), + STATEVAR(gl_BumpRotMatrix0MESA), + STATEVAR(gl_BumpRotMatrix1MESA), + STATEVAR(gl_FogParamsOptimizedMESA), STATEVAR(gl_CurrentAttribVertMESA), STATEVAR(gl_CurrentAttribFragMESA), @@ -615,6 +615,8 @@ generate_130_uniforms(exec_list *instructions, add_builtin_constant(instructions, symtab, "gl_MaxClipDistances", state->Const.MaxClipPlanes); + add_builtin_constant(instructions, symtab, "gl_MaxVaryingComponents", + state->Const.MaxVaryingFloats); } diff --git a/mesalib/src/glsl/link_uniforms.cpp b/mesalib/src/glsl/link_uniforms.cpp new file mode 100644 index 000000000..6dd1f5354 --- /dev/null +++ b/mesalib/src/glsl/link_uniforms.cpp @@ -0,0 +1,85 @@ +/* + * 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. + */ + +#include "main/core.h" +#include "ir.h" +#include "linker.h" +#include "glsl_symbol_table.h" +#include "program/hash_table.h" + +/** + * \file link_uniforms.cpp + * Assign locations for GLSL uniforms. + * + * \author Ian Romanick <ian.d.romanick@intel.com> + */ + +void +uniform_field_visitor::process(ir_variable *var) +{ + const glsl_type *t = var->type; + + /* Only strdup the name if we actually will need to modify it. */ + if (t->is_record() || (t->is_array() && t->fields.array->is_record())) { + char *name = ralloc_strdup(NULL, var->name); + recursion(var->type, &name, strlen(name)); + ralloc_free(name); + } else { + this->visit_field(t, var->name); + } +} + +void +uniform_field_visitor::recursion(const glsl_type *t, char **name, + unsigned name_length) +{ + /* Records need to have each field processed individually. + * + * Arrays of records need to have each array element processed + * individually, then each field of the resulting array elements processed + * individually. + */ + if (t->is_record()) { + for (unsigned i = 0; i < t->length; i++) { + const char *field = t->fields.structure[i].name; + + /* Append '.field' to the current uniform name. */ + ralloc_asprintf_rewrite_tail(name, name_length, ".%s", field); + + recursion(t->fields.structure[i].type, name, + name_length + 1 + strlen(field)); + } + } else if (t->is_array() && t->fields.array->is_record()) { + for (unsigned i = 0; i < t->length; i++) { + char subscript[13]; + + /* Append the subscript to the current uniform name */ + const unsigned subscript_length = snprintf(subscript, 13, "[%u]", i); + ralloc_asprintf_rewrite_tail(name, name_length, "%s", subscript); + + recursion(t->fields.array, name, name_length + subscript_length); + } + } else { + this->visit_field(t, *name); + } +} diff --git a/mesalib/src/glsl/linker.cpp b/mesalib/src/glsl/linker.cpp index a7c38a342..beadec6f6 100644 --- a/mesalib/src/glsl/linker.cpp +++ b/mesalib/src/glsl/linker.cpp @@ -1742,14 +1742,10 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) if (ctx->ShaderCompilerOptions[i].LowerClipDistance) lower_clip_distance(prog->_LinkedShaders[i]->ir); - while (do_common_optimization(prog->_LinkedShaders[i]->ir, true, 32)) + while (do_common_optimization(prog->_LinkedShaders[i]->ir, true, false, 32)) ; } - update_array_sizes(prog); - - assign_uniform_locations(prog); - /* 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 @@ -1785,6 +1781,12 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) if (prog->_LinkedShaders[MESA_SHADER_VERTEX] != NULL) { demote_shader_inputs_and_outputs(prog->_LinkedShaders[MESA_SHADER_VERTEX], ir_var_out); + + /* Eliminate code that is now dead due to unused vertex outputs being + * demoted. + */ + while (do_dead_code(prog->_LinkedShaders[MESA_SHADER_VERTEX]->ir, false)) + ; } if (prog->_LinkedShaders[MESA_SHADER_GEOMETRY] != NULL) { @@ -1793,14 +1795,30 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) demote_shader_inputs_and_outputs(sh, ir_var_in); demote_shader_inputs_and_outputs(sh, ir_var_inout); demote_shader_inputs_and_outputs(sh, ir_var_out); + + /* Eliminate code that is now dead due to unused geometry outputs being + * demoted. + */ + while (do_dead_code(prog->_LinkedShaders[MESA_SHADER_GEOMETRY]->ir, false)) + ; } if (prog->_LinkedShaders[MESA_SHADER_FRAGMENT] != NULL) { gl_shader *const sh = prog->_LinkedShaders[MESA_SHADER_FRAGMENT]; demote_shader_inputs_and_outputs(sh, ir_var_in); + + /* Eliminate code that is now dead due to unused fragment inputs being + * demoted. This shouldn't actually do anything other than remove + * declarations of the (now unused) global variables. + */ + while (do_dead_code(prog->_LinkedShaders[MESA_SHADER_FRAGMENT]->ir, false)) + ; } + update_array_sizes(prog); + assign_uniform_locations(prog); + /* OpenGL ES requires that a vertex shader and a fragment shader both be * present in a linked program. By checking for use of shading language * version 1.00, we also catch the GL_ARB_ES2_compatibility case. diff --git a/mesalib/src/glsl/linker.h b/mesalib/src/glsl/linker.h index 769cf68b6..78c632961 100644 --- a/mesalib/src/glsl/linker.h +++ b/mesalib/src/glsl/linker.h @@ -1,3 +1,4 @@ +/* -*- c++ -*- */ /* * Copyright © 2010 Intel Corporation * @@ -29,4 +30,46 @@ extern bool link_function_calls(gl_shader_program *prog, gl_shader *main, gl_shader **shader_list, unsigned num_shaders); +/** + * Class for processing all of the leaf fields of an uniform + * + * Leaves are, roughly speaking, the parts of the uniform that the application + * could query with \c glGetUniformLocation (or that could be returned by + * \c glGetActiveUniforms). + * + * Classes my derive from this class to implement specific functionality. + * This class only provides the mechanism to iterate over the leaves. Derived + * classes must implement \c ::visit_field and may override \c ::process. + */ +class uniform_field_visitor { +public: + /** + * Begin processing a uniform + * + * Classes that overload this function should call \c ::process from the + * base class to start the recursive processing of the uniform. + * + * \param var The uniform variable that is to be processed + * + * Calls \c ::visit_field for each leaf of the uniform. + */ + void process(ir_variable *var); + +protected: + /** + * Method invoked for each leaf of the uniform + * + * \param type Type of the field. + * \param name Fully qualified name of the field. + */ + virtual void visit_field(const glsl_type *type, const char *name) = 0; + +private: + /** + * \param name_length Length of the current name \b not including the + * terminating \c NUL character. + */ + void recursion(const glsl_type *t, char **name, unsigned name_length); +}; + #endif /* GLSL_LINKER_H */ diff --git a/mesalib/src/glsl/lower_if_to_cond_assign.cpp b/mesalib/src/glsl/lower_if_to_cond_assign.cpp index 7b89a1539..2c5d5612d 100644 --- a/mesalib/src/glsl/lower_if_to_cond_assign.cpp +++ b/mesalib/src/glsl/lower_if_to_cond_assign.cpp @@ -79,6 +79,9 @@ public: bool lower_if_to_cond_assign(exec_list *instructions, unsigned max_depth) { + if (max_depth == UINT_MAX) + return false; + ir_if_to_cond_assign_visitor v(max_depth); visit_list_elements(&v, instructions); diff --git a/mesalib/src/glsl/main.cpp b/mesalib/src/glsl/main.cpp index f0d951514..519abb5b5 100644 --- a/mesalib/src/glsl/main.cpp +++ b/mesalib/src/glsl/main.cpp @@ -177,7 +177,7 @@ compile_shader(struct gl_context *ctx, struct gl_shader *shader) if (!state->error && !shader->ir->is_empty()) { bool progress; do { - progress = do_common_optimization(shader->ir, false, 32); + progress = do_common_optimization(shader->ir, false, false, 32); } while (progress); validate_ir_tree(shader->ir); diff --git a/mesalib/src/glsl/opt_dead_code.cpp b/mesalib/src/glsl/opt_dead_code.cpp index cb500d2d1..5b9546ad4 100644 --- a/mesalib/src/glsl/opt_dead_code.cpp +++ b/mesalib/src/glsl/opt_dead_code.cpp @@ -42,7 +42,7 @@ static bool debug = false; * for usage on an unlinked instruction stream. */ bool -do_dead_code(exec_list *instructions) +do_dead_code(exec_list *instructions, bool uniform_locations_assigned) { ir_variable_refcount_visitor v; bool progress = false; @@ -94,10 +94,11 @@ do_dead_code(exec_list *instructions) */ /* uniform initializers are precious, and could get used by another - * stage. + * stage. Also, once uniform locations have been assigned, the + * declaration cannot be deleted. */ if (entry->var->mode == ir_var_uniform && - entry->var->constant_value) + (uniform_locations_assigned || entry->var->constant_value)) continue; entry->var->remove(); @@ -132,7 +133,12 @@ do_dead_code_unlinked(exec_list *instructions) foreach_iter(exec_list_iterator, sigiter, *f) { ir_function_signature *sig = (ir_function_signature *) sigiter.get(); - if (do_dead_code(&sig->body)) + /* The setting of the uniform_locations_assigned flag here is + * irrelevent. If there is a uniform declaration encountered + * inside the body of the function, something has already gone + * terribly, terribly wrong. + */ + if (do_dead_code(&sig->body, false)) progress = true; } } diff --git a/mesalib/src/glsl/ralloc.c b/mesalib/src/glsl/ralloc.c index fb48a91c5..f5f3934ac 100644 --- a/mesalib/src/glsl/ralloc.c +++ b/mesalib/src/glsl/ralloc.c @@ -439,7 +439,28 @@ ralloc_asprintf_append(char **str, const char *fmt, ...) bool ralloc_vasprintf_append(char **str, const char *fmt, va_list args) { - size_t existing_length, new_length; + size_t existing_length; + assert(str != NULL); + existing_length = *str ? strlen(*str) : 0; + return ralloc_vasprintf_rewrite_tail(str, existing_length, fmt, args); +} + +bool +ralloc_asprintf_rewrite_tail(char **str, size_t start, const char *fmt, ...) +{ + bool success; + va_list args; + va_start(args, fmt); + success = ralloc_vasprintf_rewrite_tail(str, start, fmt, args); + va_end(args); + return success; +} + +bool +ralloc_vasprintf_rewrite_tail(char **str, size_t start, const char *fmt, + va_list args) +{ + size_t new_length; char *ptr; assert(str != NULL); @@ -450,14 +471,13 @@ ralloc_vasprintf_append(char **str, const char *fmt, va_list args) return true; } - existing_length = strlen(*str); new_length = printf_length(fmt, args); - ptr = resize(*str, existing_length + new_length + 1); + ptr = resize(*str, start + new_length + 1); if (unlikely(ptr == NULL)) return false; - vsnprintf(ptr + existing_length, new_length + 1, fmt, args); + vsnprintf(ptr + start, new_length + 1, fmt, args); *str = ptr; return true; } diff --git a/mesalib/src/glsl/ralloc.h b/mesalib/src/glsl/ralloc.h index d5338152f..1324f3466 100644 --- a/mesalib/src/glsl/ralloc.h +++ b/mesalib/src/glsl/ralloc.h @@ -314,9 +314,60 @@ char *ralloc_asprintf (const void *ctx, const char *fmt, ...); char *ralloc_vasprintf(const void *ctx, const char *fmt, va_list args); /** + * Rewrite the tail of an existing string, starting at a given index. + * + * Overwrites the contents of *str starting at \p start with newly formatted + * text, including a new null-terminator. Allocates more memory as necessary. + * + * This can be used to append formatted text when the length of the existing + * string is already known, saving a strlen() call. + * + * \sa ralloc_asprintf_append + * + * \param str The string to be updated. + * \param start The index to start appending new data at. + * \param fmt A printf-style formatting string + * + * \p str will be updated to the new pointer unless allocation fails. + * + * \return True unless allocation failed. + */ +bool ralloc_asprintf_rewrite_tail(char **str, size_t start, + const char *fmt, ...); + +/** + * Rewrite the tail of an existing string, starting at a given index. + * + * Overwrites the contents of *str starting at \p start with newly formatted + * text, including a new null-terminator. Allocates more memory as necessary. + * + * This can be used to append formatted text when the length of the existing + * string is already known, saving a strlen() call. + * + * \sa ralloc_vasprintf_append + * + * \param str The string to be updated. + * \param start The index to start appending new data at. + * \param fmt A printf-style formatting string + * \param args A va_list containing the data to be formatted + * + * \p str will be updated to the new pointer unless allocation fails. + * + * \return True unless allocation failed. + */ +bool ralloc_vasprintf_rewrite_tail(char **str, size_t start, const char *fmt, + va_list args); + +/** * Append formatted text to the supplied string. * + * This is equivalent to + * \code + * ralloc_asprintf_rewrite_tail(str, strlen(*str), fmt, ...) + * \endcode + * * \sa ralloc_asprintf + * \sa ralloc_asprintf_rewrite_tail * \sa ralloc_strcat * * \p str will be updated to the new pointer unless allocation fails. @@ -328,7 +379,13 @@ bool ralloc_asprintf_append (char **str, const char *fmt, ...); /** * Append formatted text to the supplied string, given a va_list. * + * This is equivalent to + * \code + * ralloc_vasprintf_rewrite_tail(str, strlen(*str), fmt, args) + * \endcode + * * \sa ralloc_vasprintf + * \sa ralloc_vasprintf_rewrite_tail * \sa ralloc_strcat * * \p str will be updated to the new pointer unless allocation fails. diff --git a/mesalib/src/glsl/test_optpass.cpp b/mesalib/src/glsl/test_optpass.cpp index 89b7f8338..6abafb5d3 100644 --- a/mesalib/src/glsl/test_optpass.cpp +++ b/mesalib/src/glsl/test_optpass.cpp @@ -64,7 +64,7 @@ do_optimization(struct exec_list *ir, const char *optimization) if (sscanf(optimization, "do_common_optimization ( %d , %d ) ", &int_0, &int_1) == 2) { - return do_common_optimization(ir, int_0 != 0, int_1); + return do_common_optimization(ir, int_0 != 0, false, int_1); } else if (strcmp(optimization, "do_algebraic") == 0) { return do_algebraic(ir); } else if (strcmp(optimization, "do_constant_folding") == 0) { @@ -80,7 +80,7 @@ do_optimization(struct exec_list *ir, const char *optimization) } else if (strcmp(optimization, "do_constant_propagation") == 0) { return do_constant_propagation(ir); } else if (strcmp(optimization, "do_dead_code") == 0) { - return do_dead_code(ir); + return do_dead_code(ir, false); } else if (strcmp(optimization, "do_dead_code_local") == 0) { return do_dead_code_local(ir); } else if (strcmp(optimization, "do_dead_code_unlinked") == 0) { diff --git a/mesalib/src/mesa/drivers/dri/swrast/swrast.c b/mesalib/src/mesa/drivers/dri/swrast/swrast.c index 1bf39435b..b1abc502f 100644 --- a/mesalib/src/mesa/drivers/dri/swrast/swrast.c +++ b/mesalib/src/mesa/drivers/dri/swrast/swrast.c @@ -57,6 +57,7 @@ #include "main/texstate.h" #include "swrast_priv.h" +#include "swrast/s_context.h" /** @@ -72,6 +73,7 @@ static void swrastSetTexBuffer2(__DRIcontext *pDRICtx, GLint target, struct gl_texture_unit *texUnit; struct gl_texture_object *texObj; struct gl_texture_image *texImage; + struct swrast_texture_image *swImage; uint32_t internalFormat; gl_format texFormat; @@ -82,6 +84,7 @@ static void swrastSetTexBuffer2(__DRIcontext *pDRICtx, GLint target, texUnit = _mesa_get_current_tex_unit(&dri_ctx->Base); texObj = _mesa_select_tex_object(&dri_ctx->Base, texUnit, target); texImage = _mesa_get_tex_image(&dri_ctx->Base, texObj, target, 0); + swImage = swrast_texture_image(texImage); _mesa_lock_texture(&dri_ctx->Base, texObj); @@ -95,7 +98,7 @@ static void swrastSetTexBuffer2(__DRIcontext *pDRICtx, GLint target, _mesa_init_teximage_fields(&dri_ctx->Base, target, texImage, w, h, 1, 0, internalFormat, texFormat); - sPriv->swrast_loader->getImage(dPriv, x, y, w, h, (char *)texImage->Data, + sPriv->swrast_loader->getImage(dPriv, x, y, w, h, (char *)swImage->Data, dPriv->loaderPrivate); _mesa_unlock_texture(&dri_ctx->Base, texObj); diff --git a/mesalib/src/mesa/main/APIspec.xml b/mesalib/src/mesa/main/APIspec.xml index 574480e28..a92bb437c 100644 --- a/mesalib/src/mesa/main/APIspec.xml +++ b/mesalib/src/mesa/main/APIspec.xml @@ -631,12 +631,6 @@ <desc name="pname"> <value name="GL_RGB_SCALE"/> <value name="GL_ALPHA_SCALE"/> - - <desc name="param" convert="true" error="GL_INVALID_VALUE"> - <value name="1.0"/> - <value name="2.0"/> - <value name="4.0"/> - </desc> </desc> <desc name="pname"> diff --git a/mesalib/src/mesa/main/attrib.c b/mesalib/src/mesa/main/attrib.c index e67957d4d..1dc1c1b97 100644 --- a/mesalib/src/mesa/main/attrib.c +++ b/mesalib/src/mesa/main/attrib.c @@ -1279,30 +1279,6 @@ _mesa_PopAttrib(void) /** - * Helper for incrementing/decrementing vertex buffer object reference - * counts when pushing/popping the GL_CLIENT_VERTEX_ARRAY_BIT attribute group. - */ -static void -adjust_buffer_object_ref_counts(struct gl_array_object *arrayObj, GLint step) -{ - GLuint i; - - arrayObj->Vertex.BufferObj->RefCount += step; - arrayObj->Weight.BufferObj->RefCount += step; - arrayObj->Normal.BufferObj->RefCount += step; - arrayObj->Color.BufferObj->RefCount += step; - arrayObj->SecondaryColor.BufferObj->RefCount += step; - arrayObj->FogCoord.BufferObj->RefCount += step; - arrayObj->Index.BufferObj->RefCount += step; - arrayObj->EdgeFlag.BufferObj->RefCount += step; - for (i = 0; i < Elements(arrayObj->TexCoord); i++) - arrayObj->TexCoord[i].BufferObj->RefCount += step; - for (i = 0; i < Elements(arrayObj->VertexAttrib); i++) - arrayObj->VertexAttrib[i].BufferObj->RefCount += step; -} - - -/** * Copy gl_pixelstore_attrib from src to dst, updating buffer * object refcounts. */ @@ -1327,6 +1303,151 @@ copy_pixelstore(struct gl_context *ctx, #define GL_CLIENT_PACK_BIT (1<<20) #define GL_CLIENT_UNPACK_BIT (1<<21) +/** + * Copy gl_array_object from src to dest. + * 'dest' must be in an initialized state. + */ +static void +copy_array_object(struct gl_context *ctx, + struct gl_array_object *dest, + struct gl_array_object *src) +{ + GLuint i; + + /* skip Name */ + /* skip RefCount */ + + /* In theory must be the same anyway, but on recreate make sure it matches */ + dest->VBOonly = src->VBOonly; + + _mesa_copy_client_array(ctx, &dest->Vertex, &src->Vertex); + _mesa_copy_client_array(ctx, &dest->Weight, &src->Weight); + _mesa_copy_client_array(ctx, &dest->Normal, &src->Normal); + _mesa_copy_client_array(ctx, &dest->Color, &src->Color); + _mesa_copy_client_array(ctx, &dest->SecondaryColor, &src->SecondaryColor); + _mesa_copy_client_array(ctx, &dest->FogCoord, &src->FogCoord); + _mesa_copy_client_array(ctx, &dest->Index, &src->Index); + _mesa_copy_client_array(ctx, &dest->EdgeFlag, &src->EdgeFlag); +#if FEATURE_point_size_array + _mesa_copy_client_array(ctx, &dest->PointSize, &src->PointSize); +#endif + for (i = 0; i < Elements(src->TexCoord); i++) + _mesa_copy_client_array(ctx, &dest->TexCoord[i], &src->TexCoord[i]); + for (i = 0; i < Elements(src->VertexAttrib); i++) + _mesa_copy_client_array(ctx, &dest->VertexAttrib[i], &src->VertexAttrib[i]); + + /* _Enabled must be the same than on push */ + dest->_Enabled = src->_Enabled; + dest->_MaxElement = src->_MaxElement; +} + +/** + * Copy gl_array_attrib from src to dest. + * 'dest' must be in an initialized state. + */ +static void +copy_array_attrib(struct gl_context *ctx, + struct gl_array_attrib *dest, + struct gl_array_attrib *src) +{ + /* skip ArrayObj */ + /* skip DefaultArrayObj, Objects */ + dest->ActiveTexture = src->ActiveTexture; + dest->LockFirst = src->LockFirst; + dest->LockCount = src->LockCount; + dest->PrimitiveRestart = src->PrimitiveRestart; + dest->RestartIndex = src->RestartIndex; + /* skip NewState */ + /* skip RebindArrays */ + + copy_array_object(ctx, dest->ArrayObj, src->ArrayObj); + + /* skip ArrayBufferObj */ + /* skip ElementArrayBufferObj */ +} + +/** + * Save the content of src to dest. + */ +static void +save_array_attrib(struct gl_context *ctx, + struct gl_array_attrib *dest, + struct gl_array_attrib *src) +{ + /* Set the Name, needed for restore, but do never overwrite. + * Needs to match value in the object hash. */ + dest->ArrayObj->Name = src->ArrayObj->Name; + /* And copy all of the rest. */ + copy_array_attrib(ctx, dest, src); + + /* Just reference them here */ + _mesa_reference_buffer_object(ctx, &dest->ArrayBufferObj, + src->ArrayBufferObj); + _mesa_reference_buffer_object(ctx, &dest->ElementArrayBufferObj, + src->ElementArrayBufferObj); +} + +/** + * Restore the content of src to dest. + */ +static void +restore_array_attrib(struct gl_context *ctx, + struct gl_array_attrib *dest, + struct gl_array_attrib *src) +{ + /* Restore or recreate the array object by its name ... */ + _mesa_BindVertexArrayAPPLE(src->ArrayObj->Name); + + /* ... and restore its content */ + copy_array_attrib(ctx, dest, src); + + /* Restore or recreate the buffer objects by the names ... */ + _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, + src->ArrayBufferObj->Name); + _mesa_BindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, + src->ElementArrayBufferObj->Name); + + /* Better safe than sorry?! */ + dest->RebindArrays = GL_TRUE; + + /* FIXME: Should some bits in ctx->Array->NewState also be set + * FIXME: here? It seems like it should be set to inclusive-or + * FIXME: of the old ArrayObj->_Enabled and the new _Enabled. + * ... just do it. + */ + dest->NewState |= src->ArrayObj->_Enabled | dest->ArrayObj->_Enabled; +} + +/** + * init/alloc the fields of 'attrib'. + * Needs to the init part matching free_array_attrib_data below. + */ +static void +init_array_attrib_data(struct gl_context *ctx, + struct gl_array_attrib *attrib) +{ + /* Get a non driver gl_array_object. */ + attrib->ArrayObj = CALLOC_STRUCT( gl_array_object ); + _mesa_initialize_array_object(ctx, attrib->ArrayObj, 0); +} + +/** + * Free/unreference the fields of 'attrib' but don't delete it (that's + * done later in the calling code). + * Needs to the cleanup part matching init_array_attrib_data above. + */ +static void +free_array_attrib_data(struct gl_context *ctx, + struct gl_array_attrib *attrib) +{ + /* We use a non driver array object, so don't just unref since we would + * end up using the drivers DeleteArrayObject function for deletion. */ + _mesa_delete_array_object(ctx, attrib->ArrayObj); + attrib->ArrayObj = 0; + _mesa_reference_buffer_object(ctx, &attrib->ArrayBufferObj, NULL); + _mesa_reference_buffer_object(ctx, &attrib->ElementArrayBufferObj, NULL); +} + void GLAPIENTRY _mesa_PushClientAttrib(GLbitfield mask) @@ -1360,26 +1481,10 @@ _mesa_PushClientAttrib(GLbitfield mask) if (mask & GL_CLIENT_VERTEX_ARRAY_BIT) { struct gl_array_attrib *attr; - struct gl_array_object *obj; - - attr = MALLOC_STRUCT( gl_array_attrib ); - obj = MALLOC_STRUCT( gl_array_object ); - -#if FEATURE_ARB_vertex_buffer_object - /* increment ref counts since we're copying pointers to these objects */ - ctx->Array.ArrayBufferObj->RefCount++; - ctx->Array.ElementArrayBufferObj->RefCount++; -#endif - - memcpy( attr, &ctx->Array, sizeof(struct gl_array_attrib) ); - memcpy( obj, ctx->Array.ArrayObj, sizeof(struct gl_array_object) ); - - attr->ArrayObj = obj; - + attr = CALLOC_STRUCT( gl_array_attrib ); + init_array_attrib_data(ctx, attr); + save_array_attrib(ctx, attr, &ctx->Array); save_attrib_data(&head, GL_CLIENT_VERTEX_ARRAY_BIT, attr); - - /* bump reference counts on buffer objects */ - adjust_buffer_object_ref_counts(ctx->Array.ArrayObj, 1); } ctx->ClientAttribStack[ctx->ClientAttribStackDepth] = head; @@ -1426,36 +1531,10 @@ _mesa_PopClientAttrib(void) ctx->NewState |= _NEW_PACKUNPACK; break; case GL_CLIENT_VERTEX_ARRAY_BIT: { - struct gl_array_attrib * data = + struct gl_array_attrib * attr = (struct gl_array_attrib *) node->data; - - adjust_buffer_object_ref_counts(ctx->Array.ArrayObj, -1); - - ctx->Array.ActiveTexture = data->ActiveTexture; - if (data->LockCount != 0) - _mesa_LockArraysEXT(data->LockFirst, data->LockCount); - else if (ctx->Array.LockCount) - _mesa_UnlockArraysEXT(); - - _mesa_BindVertexArrayAPPLE( data->ArrayObj->Name ); - -#if FEATURE_ARB_vertex_buffer_object - _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, - data->ArrayBufferObj->Name); - _mesa_BindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, - data->ElementArrayBufferObj->Name); -#endif - - memcpy( ctx->Array.ArrayObj, data->ArrayObj, - sizeof( struct gl_array_object ) ); - - FREE( data->ArrayObj ); - - /* FIXME: Should some bits in ctx->Array->NewState also be set - * FIXME: here? It seems like it should be set to inclusive-or - * FIXME: of the old ArrayObj->_Enabled and the new _Enabled. - */ - + restore_array_attrib(ctx, &ctx->Array, attr); + free_array_attrib_data(ctx, attr); ctx->NewState |= _NEW_ARRAY; break; } diff --git a/mesalib/src/mesa/main/bufferobj.c b/mesalib/src/mesa/main/bufferobj.c index 67241eb1e..f2e8f568c 100644 --- a/mesalib/src/mesa/main/bufferobj.c +++ b/mesalib/src/mesa/main/bufferobj.c @@ -571,7 +571,7 @@ bind_buffer_object(struct gl_context *ctx, GLenum target, GLuint buffer) /* Get pointer to old buffer object (to be unbound) */ oldBufObj = *bindTarget; - if (oldBufObj && oldBufObj->Name == buffer) + if (oldBufObj && oldBufObj->Name == buffer && !oldBufObj->DeletePending) return; /* rebinding the same buffer object- no change */ /* @@ -773,6 +773,17 @@ _mesa_DeleteBuffersARB(GLsizei n, const GLuint *ids) /* The ID is immediately freed for re-use */ _mesa_HashRemove(ctx->Shared->BufferObjects, ids[i]); + /* Make sure we do not run into the classic ABA problem on bind. + * We don't want to allow re-binding a buffer object that's been + * "deleted" by glDeleteBuffers(). + * + * The explicit rebinding to the default object in the current context + * prevents the above in the current context, but another context + * sharing the same objects might suffer from this problem. + * The alternative would be to do the hash lookup in any case on bind + * which would introduce more runtime overhead than this. + */ + bufObj->DeletePending = GL_TRUE; _mesa_reference_buffer_object(ctx, &bufObj, NULL); } } diff --git a/mesalib/src/mesa/main/compiler.h b/mesalib/src/mesa/main/compiler.h index 89d6cda91..921e30222 100644 --- a/mesalib/src/mesa/main/compiler.h +++ b/mesalib/src/mesa/main/compiler.h @@ -150,7 +150,7 @@ extern "C" { * inline a static function that we later use in an alias. - ajax */ #ifndef PUBLIC -# if defined(__GNUC__) || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590)) +# if (defined(__GNUC__) && __GNUC__ >= 4) || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590)) # define PUBLIC __attribute__((visibility("default"))) # define USED __attribute__((used)) # else diff --git a/mesalib/src/mesa/main/context.h b/mesalib/src/mesa/main/context.h index a4c7ba2c5..a9df0a866 100644 --- a/mesalib/src/mesa/main/context.h +++ b/mesalib/src/mesa/main/context.h @@ -233,7 +233,7 @@ do { \ * glBegin()/glEnd() pair, with return value. * * \param ctx GL context. - * \param retval value to return value in case the assertion fails. + * \param retval value to return in case the assertion fails. */ #define ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, retval) \ do { \ @@ -274,7 +274,7 @@ do { \ * glBegin()/glEnd() pair and flush the vertices, with return value. * * \param ctx GL context. - * \param retval value to return value in case the assertion fails. + * \param retval value to return in case the assertion fails. */ #define ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH_WITH_RETVAL(ctx, retval) \ do { \ diff --git a/mesalib/src/mesa/main/dlist.c b/mesalib/src/mesa/main/dlist.c index 625649e9d..d901bddf8 100644 --- a/mesalib/src/mesa/main/dlist.c +++ b/mesalib/src/mesa/main/dlist.c @@ -939,7 +939,9 @@ unpack_image(struct gl_context *ctx, GLuint dimensions, } return image; } + /* bad access! */ + _mesa_error(ctx, GL_INVALID_OPERATION, "invalid PBO access"); return NULL; } diff --git a/mesalib/src/mesa/main/fbobject.c b/mesalib/src/mesa/main/fbobject.c index f9da54e73..c56062ac6 100644 --- a/mesalib/src/mesa/main/fbobject.c +++ b/mesalib/src/mesa/main/fbobject.c @@ -2486,6 +2486,7 @@ _mesa_GetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment, void GLAPIENTRY _mesa_GenerateMipmapEXT(GLenum target) { + struct gl_texture_image *srcImage; struct gl_texture_object *texObj; GLboolean error; @@ -2532,6 +2533,13 @@ _mesa_GenerateMipmapEXT(GLenum target) } _mesa_lock_texture(ctx, texObj); + + srcImage = _mesa_select_tex_image(ctx, texObj, target, texObj->BaseLevel); + if (!srcImage) { + _mesa_unlock_texture(ctx, texObj); + return; + } + if (target == GL_TEXTURE_CUBE_MAP) { GLuint face; for (face = 0; face < 6; face++) diff --git a/mesalib/src/mesa/main/ff_fragment_shader.cpp b/mesalib/src/mesa/main/ff_fragment_shader.cpp index 160a97c0c..b5500714b 100644 --- a/mesalib/src/mesa/main/ff_fragment_shader.cpp +++ b/mesalib/src/mesa/main/ff_fragment_shader.cpp @@ -1137,8 +1137,8 @@ load_texunit_bumpmap( struct texenv_fragment_program *p, GLuint unit ) ir_variable *rot_mat_0_var, *rot_mat_1_var; ir_dereference_variable *rot_mat_0, *rot_mat_1; - rot_mat_0_var = p->shader->symbols->get_variable("gl_MESABumpRotMatrix0"); - rot_mat_1_var = p->shader->symbols->get_variable("gl_MESABumpRotMatrix1"); + rot_mat_0_var = p->shader->symbols->get_variable("gl_BumpRotMatrix0MESA"); + rot_mat_1_var = p->shader->symbols->get_variable("gl_BumpRotMatrix1MESA"); rot_mat_0 = new(p->mem_ctx) ir_dereference_variable(rot_mat_0_var); rot_mat_1 = new(p->mem_ctx) ir_dereference_variable(rot_mat_1_var); @@ -1229,7 +1229,7 @@ emit_fog_instructions(struct texenv_fragment_program *p, temp = new(p->mem_ctx) ir_dereference_variable(fog_result); fragcolor = new(p->mem_ctx) ir_swizzle(temp, 0, 1, 2, 3, 3); - oparams = p->shader->symbols->get_variable("gl_MESAFogParamsOptimized"); + oparams = p->shader->symbols->get_variable("gl_FogParamsOptimizedMESA"); fogcoord = p->shader->symbols->get_variable("gl_FogFragCoord"); params = p->shader->symbols->get_variable("gl_Fog"); f = new(p->mem_ctx) ir_dereference_variable(fogcoord); @@ -1464,7 +1464,7 @@ create_new_program(struct gl_context *ctx, struct state_key *key) validate_ir_tree(p.shader->ir); - while (do_common_optimization(p.shader->ir, false, 32)) + while (do_common_optimization(p.shader->ir, false, false, 32)) ; reparent_ir(p.shader->ir, p.shader->ir); diff --git a/mesalib/src/mesa/main/imports.c b/mesalib/src/mesa/main/imports.c index 345a1c53e..2469e4265 100644 --- a/mesalib/src/mesa/main/imports.c +++ b/mesalib/src/mesa/main/imports.c @@ -514,7 +514,7 @@ _mesa_ffsll(int64_t val) #endif #if !defined(__GNUC__) ||\ - ((_GNUC__ == 3 && __GNUC_MINOR__ < 4) && __GNUC__ < 4) + ((__GNUC__ * 100 + __GNUC_MINOR__) < 304) /* Not gcc 3.4 or later */ /** * Return number of bits set in given GLuint. */ diff --git a/mesalib/src/mesa/main/imports.h b/mesalib/src/mesa/main/imports.h index 20fa148fe..797f35742 100644 --- a/mesalib/src/mesa/main/imports.h +++ b/mesalib/src/mesa/main/imports.h @@ -453,7 +453,7 @@ static inline int32_t _mesa_next_pow_two_32(uint32_t x) { #if defined(__GNUC__) && \ - ((__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || __GNUC__ >= 4) + ((__GNUC__ * 100 + __GNUC_MINOR__) >= 304) /* gcc 3.4 or later */ uint32_t y = (x != 1); return (1 + y) << ((__builtin_clz(x - y) ^ 31) ); #else @@ -472,7 +472,7 @@ static inline int64_t _mesa_next_pow_two_64(uint64_t x) { #if defined(__GNUC__) && \ - ((__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || __GNUC__ >= 4) + ((__GNUC__ * 100 + __GNUC_MINOR__) >= 304) /* gcc 3.4 or later */ uint64_t y = (x != 1); if (sizeof(x) == sizeof(long)) return (1 + y) << ((__builtin_clzl(x - y) ^ 63)); @@ -499,7 +499,7 @@ static inline GLuint _mesa_logbase2(GLuint n) { #if defined(__GNUC__) && \ - ((__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || __GNUC__ >= 4) + ((__GNUC__ * 100 + __GNUC_MINOR__) >= 304) /* gcc 3.4 or later */ return (31 - __builtin_clz(n | 1)); #else GLuint pos = 0; @@ -576,7 +576,7 @@ _mesa_init_sqrt_table(void); #define _mesa_ffs(i) ffs(i) #define _mesa_ffsll(i) ffsll(i) -#if ((_GNUC__ == 3 && __GNUC_MINOR__ >= 4) || __GNUC__ >= 4) +#if ((__GNUC__ * 100 + __GNUC_MINOR__) >= 304) /* gcc 3.4 or later */ #define _mesa_bitcount(i) __builtin_popcount(i) #define _mesa_bitcount_64(i) __builtin_popcountll(i) #else diff --git a/mesalib/src/mesa/main/mtypes.h b/mesalib/src/mesa/main/mtypes.h index 17c645a7e..411768641 100644 --- a/mesalib/src/mesa/main/mtypes.h +++ b/mesalib/src/mesa/main/mtypes.h @@ -1261,11 +1261,6 @@ struct gl_texture_image GLuint Level; /**< Which mipmap level am I? */ /** Cube map face: index into gl_texture_object::Image[] array */ GLuint Face; - - GLuint RowStride; /**< Padded width in units of texels */ - GLuint *ImageOffsets; /**< if 3D texture: array [Depth] of offsets to - each 2D slice in 'Data', in texels */ - GLvoid *Data; /**< Image data, accessed via FetchTexel() */ }; @@ -1535,6 +1530,7 @@ struct gl_buffer_object GLintptr Offset; /**< Mapped offset */ GLsizeiptr Length; /**< Mapped length */ /*@}*/ + GLboolean DeletePending; /**< true if buffer object is removed from the hash */ GLboolean Written; /**< Ever written to? (for debugging) */ GLboolean Purgeable; /**< Is the buffer purgeable under memory pressure? */ }; @@ -2736,6 +2732,20 @@ struct gl_constants /* GL_ARB_robustness */ GLenum ResetStrategy; + + /** + * Whether the implementation strips out and ignores texture borders. + * + * Many GPU hardware implementations don't support rendering with texture + * borders and mipmapped textures. (Note: not static border color, but the + * old 1-pixel border around each edge). Implementations then have to do + * slow fallbacks to be correct, or just ignore the border and be fast but + * wrong. Setting the flag stripts the border off of TexImage calls, + * providing "fast but wrong" at significantly reduced driver complexity. + * + * Texture borders are deprecated in GL 3.0. + **/ + GLboolean StripTextureBorder; }; diff --git a/mesalib/src/mesa/main/pack.c b/mesalib/src/mesa/main/pack.c index 092e541c5..ecdeaf5dc 100644 --- a/mesalib/src/mesa/main/pack.c +++ b/mesalib/src/mesa/main/pack.c @@ -3717,6 +3717,7 @@ _mesa_unpack_color_span_ubyte(struct gl_context *ctx, if (!indexes) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "pixel unpacking"); + free(rgba); return; } diff --git a/mesalib/src/mesa/main/pixelstore.c b/mesalib/src/mesa/main/pixelstore.c index d957950ed..81474491d 100644 --- a/mesalib/src/mesa/main/pixelstore.c +++ b/mesalib/src/mesa/main/pixelstore.c @@ -214,7 +214,7 @@ _mesa_PixelStorei( GLenum pname, GLint param ) void GLAPIENTRY _mesa_PixelStoref( GLenum pname, GLfloat param ) { - _mesa_PixelStorei( pname, (GLint) param ); + _mesa_PixelStorei( pname, IROUND(param) ); } diff --git a/mesalib/src/mesa/main/state.c b/mesalib/src/mesa/main/state.c index 98ca733c0..80fd03b91 100644 --- a/mesalib/src/mesa/main/state.c +++ b/mesalib/src/mesa/main/state.c @@ -461,7 +461,7 @@ static void update_twoside(struct gl_context *ctx) { if (ctx->Shader.CurrentVertexProgram || - ctx->VertexProgram.Current) { + ctx->VertexProgram._Enabled) { ctx->VertexProgram._TwoSideEnabled = ctx->VertexProgram.TwoSideEnabled; } else { ctx->VertexProgram._TwoSideEnabled = (ctx->Light.Enabled && diff --git a/mesalib/src/mesa/main/texcompress.c b/mesalib/src/mesa/main/texcompress.c index 03e05d5ef..0458b9b68 100644 --- a/mesalib/src/mesa/main/texcompress.c +++ b/mesalib/src/mesa/main/texcompress.c @@ -461,8 +461,8 @@ _mesa_decompress_image(gl_format format, GLuint width, GLuint height, /* setup dummy texture image info */ memset(&texImage, 0, sizeof(texImage)); - texImage.Base.Data = (void *) src; - texImage.Base.RowStride = srcRowStride; + texImage.Data = (void *) src; + texImage.RowStride = srcRowStride; switch (format) { /* DXT formats */ diff --git a/mesalib/src/mesa/main/texcompress_fxt1.c b/mesalib/src/mesa/main/texcompress_fxt1.c index 41630a47c..d5c73e3b4 100644 --- a/mesalib/src/mesa/main/texcompress_fxt1.c +++ b/mesalib/src/mesa/main/texcompress_fxt1.c @@ -177,7 +177,7 @@ _mesa_fetch_texel_2d_f_rgba_fxt1( const struct swrast_texture_image *texImage, /* just sample as GLubyte and convert to float here */ GLubyte rgba[4]; (void) k; - fxt1_decode_1(texImage->Base.Data, texImage->Base.RowStride, i, j, rgba); + fxt1_decode_1(texImage->Data, 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]); @@ -192,7 +192,7 @@ _mesa_fetch_texel_2d_f_rgb_fxt1( const struct swrast_texture_image *texImage, /* just sample as GLubyte and convert to float here */ GLubyte rgba[4]; (void) k; - fxt1_decode_1(texImage->Base.Data, texImage->Base.RowStride, i, j, rgba); + fxt1_decode_1(texImage->Data, 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]); diff --git a/mesalib/src/mesa/main/texcompress_rgtc.c b/mesalib/src/mesa/main/texcompress_rgtc.c index b03cd28b8..3586fc39d 100644 --- a/mesalib/src/mesa/main/texcompress_rgtc.c +++ b/mesalib/src/mesa/main/texcompress_rgtc.c @@ -325,7 +325,7 @@ _mesa_fetch_texel_2d_f_red_rgtc1(const struct swrast_texture_image *texImage, GLint i, GLint j, GLint k, GLfloat *texel) { GLubyte red; - unsigned_fetch_texel_rgtc(texImage->Base.RowStride, (GLubyte *)(texImage->Base.Data), + unsigned_fetch_texel_rgtc(texImage->RowStride, texImage->Data, i, j, &red, 1); texel[RCOMP] = UBYTE_TO_FLOAT(red); texel[GCOMP] = 0.0; @@ -338,7 +338,7 @@ _mesa_fetch_texel_2d_f_signed_red_rgtc1(const struct swrast_texture_image *texIm GLint i, GLint j, GLint k, GLfloat *texel) { GLbyte red; - signed_fetch_texel_rgtc(texImage->Base.RowStride, (GLbyte *)(texImage->Base.Data), + signed_fetch_texel_rgtc(texImage->RowStride, (GLbyte *)(texImage->Data), i, j, &red, 1); texel[RCOMP] = BYTE_TO_FLOAT_TEX(red); texel[GCOMP] = 0.0; @@ -351,9 +351,9 @@ _mesa_fetch_texel_2d_f_rg_rgtc2(const struct swrast_texture_image *texImage, GLint i, GLint j, GLint k, GLfloat *texel) { GLubyte red, green; - unsigned_fetch_texel_rgtc(texImage->Base.RowStride, (GLubyte *)(texImage->Base.Data), + unsigned_fetch_texel_rgtc(texImage->RowStride, texImage->Data, i, j, &red, 2); - unsigned_fetch_texel_rgtc(texImage->Base.RowStride, (GLubyte *)(texImage->Base.Data) + 8, + unsigned_fetch_texel_rgtc(texImage->RowStride, texImage->Data + 8, i, j, &green, 2); texel[RCOMP] = UBYTE_TO_FLOAT(red); texel[GCOMP] = UBYTE_TO_FLOAT(green); @@ -366,9 +366,9 @@ _mesa_fetch_texel_2d_f_signed_rg_rgtc2(const struct swrast_texture_image *texIma GLint i, GLint j, GLint k, GLfloat *texel) { GLbyte red, green; - signed_fetch_texel_rgtc(texImage->Base.RowStride, (GLbyte *)(texImage->Base.Data), + signed_fetch_texel_rgtc(texImage->RowStride, (GLbyte *)(texImage->Data), i, j, &red, 2); - signed_fetch_texel_rgtc(texImage->Base.RowStride, (GLbyte *)(texImage->Base.Data) + 8, + signed_fetch_texel_rgtc(texImage->RowStride, (GLbyte *)(texImage->Data) + 8, i, j, &green, 2); texel[RCOMP] = BYTE_TO_FLOAT_TEX(red); texel[GCOMP] = BYTE_TO_FLOAT_TEX(green); @@ -381,7 +381,7 @@ _mesa_fetch_texel_2d_f_l_latc1(const struct swrast_texture_image *texImage, GLint i, GLint j, GLint k, GLfloat *texel) { GLubyte red; - unsigned_fetch_texel_rgtc(texImage->Base.RowStride, (GLubyte *)(texImage->Base.Data), + unsigned_fetch_texel_rgtc(texImage->RowStride, texImage->Data, i, j, &red, 1); texel[RCOMP] = texel[GCOMP] = @@ -394,7 +394,7 @@ _mesa_fetch_texel_2d_f_signed_l_latc1(const struct swrast_texture_image *texImag GLint i, GLint j, GLint k, GLfloat *texel) { GLbyte red; - signed_fetch_texel_rgtc(texImage->Base.RowStride, (GLbyte *)(texImage->Base.Data), + signed_fetch_texel_rgtc(texImage->RowStride, (GLbyte *)(texImage->Data), i, j, &red, 1); texel[RCOMP] = texel[GCOMP] = @@ -407,9 +407,9 @@ _mesa_fetch_texel_2d_f_la_latc2(const struct swrast_texture_image *texImage, GLint i, GLint j, GLint k, GLfloat *texel) { GLubyte red, green; - unsigned_fetch_texel_rgtc(texImage->Base.RowStride, (GLubyte *)(texImage->Base.Data), + unsigned_fetch_texel_rgtc(texImage->RowStride, texImage->Data, i, j, &red, 2); - unsigned_fetch_texel_rgtc(texImage->Base.RowStride, (GLubyte *)(texImage->Base.Data) + 8, + unsigned_fetch_texel_rgtc(texImage->RowStride, texImage->Data + 8, i, j, &green, 2); texel[RCOMP] = texel[GCOMP] = @@ -422,9 +422,9 @@ _mesa_fetch_texel_2d_f_signed_la_latc2(const struct swrast_texture_image *texIma GLint i, GLint j, GLint k, GLfloat *texel) { GLbyte red, green; - signed_fetch_texel_rgtc(texImage->Base.RowStride, (GLbyte *)(texImage->Base.Data), + signed_fetch_texel_rgtc(texImage->RowStride, (GLbyte *)(texImage->Data), i, j, &red, 2); - signed_fetch_texel_rgtc(texImage->Base.RowStride, (GLbyte *)(texImage->Base.Data) + 8, + signed_fetch_texel_rgtc(texImage->RowStride, (GLbyte *)(texImage->Data) + 8, i, j, &green, 2); texel[RCOMP] = texel[GCOMP] = diff --git a/mesalib/src/mesa/main/texcompress_s3tc.c b/mesalib/src/mesa/main/texcompress_s3tc.c index 29386a37d..11c7db4ef 100644 --- a/mesalib/src/mesa/main/texcompress_s3tc.c +++ b/mesalib/src/mesa/main/texcompress_s3tc.c @@ -402,8 +402,8 @@ fetch_texel_2d_rgb_dxt1( const struct swrast_texture_image *texImage, { (void) k; if (fetch_ext_rgb_dxt1) { - fetch_ext_rgb_dxt1(texImage->Base.RowStride, - (GLubyte *)(texImage)->Base.Data, i, j, texel); + fetch_ext_rgb_dxt1(texImage->RowStride, + texImage->Data, i, j, texel); } else _mesa_debug(NULL, "attempted to decode s3tc texture without library available: fetch_texel_2d_rgb_dxt1"); @@ -430,8 +430,8 @@ fetch_texel_2d_rgba_dxt1( const struct swrast_texture_image *texImage, { (void) k; if (fetch_ext_rgba_dxt1) { - fetch_ext_rgba_dxt1(texImage->Base.RowStride, - (GLubyte *)(texImage)->Base.Data, i, j, texel); + fetch_ext_rgba_dxt1(texImage->RowStride, + texImage->Data, i, j, texel); } else _mesa_debug(NULL, "attempted to decode s3tc texture without library available: fetch_texel_2d_rgba_dxt1\n"); @@ -458,9 +458,8 @@ fetch_texel_2d_rgba_dxt3( const struct swrast_texture_image *texImage, { (void) k; if (fetch_ext_rgba_dxt3) { - fetch_ext_rgba_dxt3(texImage->Base.RowStride, - (GLubyte *)(texImage)->Base.Data, - i, j, texel); + fetch_ext_rgba_dxt3(texImage->RowStride, + texImage->Data, i, j, texel); } else _mesa_debug(NULL, "attempted to decode s3tc texture without library available: fetch_texel_2d_rgba_dxt3\n"); @@ -487,9 +486,8 @@ fetch_texel_2d_rgba_dxt5( const struct swrast_texture_image *texImage, { (void) k; if (fetch_ext_rgba_dxt5) { - fetch_ext_rgba_dxt5(texImage->Base.RowStride, - (GLubyte *)(texImage)->Base.Data, - i, j, texel); + fetch_ext_rgba_dxt5(texImage->RowStride, + texImage->Data, i, j, texel); } else _mesa_debug(NULL, "attempted to decode s3tc texture without library available: fetch_texel_2d_rgba_dxt5\n"); diff --git a/mesalib/src/mesa/main/texformat.c b/mesalib/src/mesa/main/texformat.c index 7f262d6d8..aebe38ee0 100644 --- a/mesalib/src/mesa/main/texformat.c +++ b/mesalib/src/mesa/main/texformat.c @@ -34,6 +34,7 @@ #include "context.h" +#include "enums.h" #include "mfeatures.h" #include "mtypes.h" #include "texcompress.h" @@ -897,7 +898,8 @@ _mesa_choose_tex_format( struct gl_context *ctx, GLint internalFormat, } } - _mesa_problem(ctx, "unexpected format in _mesa_choose_tex_format()"); + _mesa_problem(ctx, "unexpected format %s in _mesa_choose_tex_format()", + _mesa_lookup_enum_by_nr(internalFormat)); return MESA_FORMAT_NONE; } diff --git a/mesalib/src/mesa/main/teximage.c b/mesalib/src/mesa/main/teximage.c index 2d06f84bf..acf7187fd 100644 --- a/mesalib/src/mesa/main/teximage.c +++ b/mesalib/src/mesa/main/teximage.c @@ -58,27 +58,6 @@ /** - * We allocate texture memory on 512-byte boundaries so we can use MMX/SSE - * elsewhere. - */ -void * -_mesa_alloc_texmemory(GLsizei bytes) -{ - return _mesa_align_malloc(bytes, 512); -} - - -/** - * Free texture memory allocated with _mesa_alloc_texmemory() - */ -void -_mesa_free_texmemory(void *m) -{ - _mesa_align_free(m); -} - - -/** * Return the simple base format for a given internal texture format. * For example, given GL_LUMINANCE12_ALPHA4, return GL_LUMINANCE_ALPHA. * @@ -599,29 +578,6 @@ _mesa_new_texture_image( struct gl_context *ctx ) /** - * Free texture image data. - * This function is a fallback called via ctx->Driver.FreeTextureImageBuffer(). - * - * \param texImage texture image. - * - * Free the texture image data if it's not marked as client data. - */ -void -_mesa_free_texture_image_data(struct gl_context *ctx, - struct gl_texture_image *texImage) -{ - (void) ctx; - - if (texImage->Data) { - /* free the old texture data */ - _mesa_free_texmemory(texImage->Data); - } - - texImage->Data = NULL; -} - - -/** * Free a gl_texture_image and associated data. * This function is a fallback called via ctx->Driver.DeleteTextureImage(). * @@ -638,11 +594,6 @@ _mesa_delete_texture_image(struct gl_context *ctx, */ ASSERT(ctx->Driver.FreeTextureImageBuffer); ctx->Driver.FreeTextureImageBuffer( ctx, texImage ); - - ASSERT(texImage->Data == NULL); - if (texImage->ImageOffsets) - free(texImage->ImageOffsets); - free(texImage); } @@ -1084,18 +1035,12 @@ clear_teximage_fields(struct gl_texture_image *img) img->Width = 0; img->Height = 0; img->Depth = 0; - img->RowStride = 0; - if (img->ImageOffsets) { - free(img->ImageOffsets); - img->ImageOffsets = NULL; - } img->Width2 = 0; img->Height2 = 0; img->Depth2 = 0; img->WidthLog2 = 0; img->HeightLog2 = 0; img->DepthLog2 = 0; - img->Data = NULL; img->TexFormat = MESA_FORMAT_NONE; } @@ -1123,8 +1068,6 @@ _mesa_init_teximage_fields(struct gl_context *ctx, GLenum target, GLint border, GLenum internalFormat, gl_format format) { - GLint i; - ASSERT(img); ASSERT(width >= 0); ASSERT(height >= 0); @@ -1161,19 +1104,6 @@ _mesa_init_teximage_fields(struct gl_context *ctx, GLenum target, img->MaxLog2 = MAX2(img->WidthLog2, img->HeightLog2); - /* RowStride and ImageOffsets[] describe how to address texels in 'Data' */ - img->RowStride = width; - /* Allocate the ImageOffsets array and initialize to typical values. - * We allocate the array for 1D/2D textures too in order to avoid special- - * case code in the texstore routines. - */ - if (img->ImageOffsets) - free(img->ImageOffsets); - img->ImageOffsets = (GLuint *) malloc(depth * sizeof(GLuint)); - for (i = 0; i < depth; i++) { - img->ImageOffsets[i] = i * width * height; - } - img->TexFormat = format; } @@ -2316,6 +2246,45 @@ _mesa_choose_texture_format(struct gl_context *ctx, return f; } +/** + * Adjust pixel unpack params and image dimensions to strip off the + * texture border. + * + * Gallium and intel don't support texture borders. They've seldem been used + * and seldom been implemented correctly anyway. + * + * \param unpackNew returns the new pixel unpack parameters + */ +static void +strip_texture_border(GLint *border, + GLint *width, GLint *height, GLint *depth, + const struct gl_pixelstore_attrib *unpack, + struct gl_pixelstore_attrib *unpackNew) +{ + assert(*border > 0); /* sanity check */ + + *unpackNew = *unpack; + + if (unpackNew->RowLength == 0) + unpackNew->RowLength = *width; + + if (depth && unpackNew->ImageHeight == 0) + unpackNew->ImageHeight = *height; + + unpackNew->SkipPixels += *border; + if (height) + unpackNew->SkipRows += *border; + if (depth) + unpackNew->SkipImages += *border; + + assert(*width >= 3); + *width = *width - 2 * *border; + if (height && *height >= 3) + *height = *height - 2 * *border; + if (depth && *depth >= 3) + *depth = *depth - 2 * *border; + *border = 0; +} /** * Common code to implement all the glTexImage1D/2D/3D functions. @@ -2328,6 +2297,8 @@ teximage(struct gl_context *ctx, GLuint dims, const GLvoid *pixels) { GLboolean error; + struct gl_pixelstore_attrib unpack_no_border; + const struct gl_pixelstore_attrib *unpack = &ctx->Unpack; ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); @@ -2392,6 +2363,16 @@ teximage(struct gl_context *ctx, GLuint dims, return; /* error was recorded */ } + /* Allow a hardware driver to just strip out the border, to provide + * reliable but slightly incorrect hardware rendering instead of + * rarely-tested software fallback rendering. + */ + if (border && ctx->Const.StripTextureBorder) { + strip_texture_border(&border, &width, &height, &depth, unpack, + &unpack_no_border); + unpack = &unpack_no_border; + } + if (ctx->NewState & _NEW_PIXEL) _mesa_update_state(ctx); @@ -2409,7 +2390,6 @@ teximage(struct gl_context *ctx, GLuint dims, ctx->Driver.FreeTextureImageBuffer(ctx, texImage); - ASSERT(texImage->Data == NULL); texFormat = _mesa_choose_texture_format(ctx, texObj, target, level, internalFormat, format, type); @@ -2425,19 +2405,19 @@ teximage(struct gl_context *ctx, GLuint dims, case 1: ctx->Driver.TexImage1D(ctx, target, level, internalFormat, width, border, format, - type, pixels, &ctx->Unpack, texObj, + type, pixels, unpack, texObj, texImage); break; case 2: ctx->Driver.TexImage2D(ctx, target, level, internalFormat, width, height, border, format, - type, pixels, &ctx->Unpack, texObj, + type, pixels, unpack, texObj, texImage); break; case 3: ctx->Driver.TexImage3D(ctx, target, level, internalFormat, width, height, depth, border, format, - type, pixels, &ctx->Unpack, texObj, + type, pixels, unpack, texObj, texImage); break; default: @@ -2548,7 +2528,6 @@ _mesa_EGLImageTargetTexture2DOES (GLenum target, GLeglImageOES image) } else { ctx->Driver.FreeTextureImageBuffer(ctx, texImage); - ASSERT(texImage->Data == NULL); ctx->Driver.EGLImageTargetTexture2D(ctx, target, texObj, texImage, image); @@ -2734,6 +2713,16 @@ copyteximage(struct gl_context *ctx, GLuint dims, texObj = _mesa_get_current_tex_object(ctx, target); + if (border && ctx->Const.StripTextureBorder) { + x += border; + width -= border * 2; + if (dims == 2) { + y += border; + height -= border * 2; + } + border = 0; + } + _mesa_lock_texture(ctx, texObj); { texImage = _mesa_get_tex_image(ctx, texObj, target, level); @@ -3370,7 +3359,6 @@ compressedteximage(struct gl_context *ctx, GLuint dims, gl_format texFormat; ctx->Driver.FreeTextureImageBuffer(ctx, texImage); - ASSERT(texImage->Data == NULL); texFormat = _mesa_choose_texture_format(ctx, texObj, target, level, internalFormat, GL_NONE, diff --git a/mesalib/src/mesa/main/teximage.h b/mesalib/src/mesa/main/teximage.h index 6ce0fe92c..fd315bea3 100644 --- a/mesalib/src/mesa/main/teximage.h +++ b/mesalib/src/mesa/main/teximage.h @@ -36,13 +36,6 @@ #include "formats.h" -extern void * -_mesa_alloc_texmemory(GLsizei bytes); - -extern void -_mesa_free_texmemory(void *m); - - /** \name Internal functions */ /*@{*/ @@ -62,10 +55,6 @@ extern void _mesa_delete_texture_image( struct gl_context *ctx, struct gl_texture_image *teximage ); -extern void -_mesa_free_texture_image_data( struct gl_context *ctx, - struct gl_texture_image *texImage ); - extern void _mesa_init_teximage_fields(struct gl_context *ctx, GLenum target, diff --git a/mesalib/src/mesa/main/texobj.c b/mesalib/src/mesa/main/texobj.c index 1b90cca9b..4d9942ba8 100644 --- a/mesalib/src/mesa/main/texobj.c +++ b/mesalib/src/mesa/main/texobj.c @@ -543,12 +543,13 @@ _mesa_test_texobj_completeness( const struct gl_context *ctx, width /= 2; } if (i >= minLevel && i <= maxLevel) { - if (!t->Image[0][i]) { - incomplete(t, "1D Image[0][i] == NULL"); + const struct gl_texture_image *img = t->Image[0][i]; + if (!img) { + incomplete(t, "1D Image[%d] is missing", i); return; } - if (t->Image[0][i]->Width2 != width ) { - incomplete(t, "1D Image[0][i] bad width"); + if (img->Width2 != width ) { + incomplete(t, "1D Image[%d] bad width %u", i, img->Width2); return; } } @@ -570,16 +571,17 @@ _mesa_test_texobj_completeness( const struct gl_context *ctx, height /= 2; } if (i >= minLevel && i <= maxLevel) { - if (!t->Image[0][i]) { - incomplete(t, "2D Image[0][i] == NULL"); + const struct gl_texture_image *img = t->Image[0][i]; + if (!img) { + incomplete(t, "2D Image[%d of %d] is missing", i, maxLevel); return; } - if (t->Image[0][i]->Width2 != width) { - incomplete(t, "2D Image[0][i] bad width"); + if (img->Width2 != width) { + incomplete(t, "2D Image[%d] bad width %u", i, img->Width2); return; } - if (t->Image[0][i]->Height2 != height) { - incomplete(t, "2D Image[0][i] bad height"); + if (img->Height2 != height) { + incomplete(t, "2D Image[i] bad height %u", i, img->Height2); return; } if (width==1 && height==1) { @@ -604,24 +606,25 @@ _mesa_test_texobj_completeness( const struct gl_context *ctx, depth /= 2; } if (i >= minLevel && i <= maxLevel) { - if (!t->Image[0][i]) { - incomplete(t, "3D Image[0][i] == NULL"); + const struct gl_texture_image *img = t->Image[0][i]; + if (!img) { + incomplete(t, "3D Image[%d] is missing", i); return; } - if (t->Image[0][i]->_BaseFormat == GL_DEPTH_COMPONENT) { + if (img->_BaseFormat == GL_DEPTH_COMPONENT) { incomplete(t, "GL_DEPTH_COMPONENT only works with 1/2D tex"); return; } - if (t->Image[0][i]->Width2 != width) { - incomplete(t, "3D Image[0][i] bad width"); + if (img->Width2 != width) { + incomplete(t, "3D Image[%d] bad width %u", i, img->Width2); return; } - if (t->Image[0][i]->Height2 != height) { - incomplete(t, "3D Image[0][i] bad height"); + if (img->Height2 != height) { + incomplete(t, "3D Image[%d] bad height %u", i, img->Height2); return; } - if (t->Image[0][i]->Depth2 != depth) { - incomplete(t, "3D Image[0][i] bad depth"); + if (img->Depth2 != depth) { + incomplete(t, "3D Image[%d] bad depth %u", i, img->Depth2); return; } } diff --git a/mesalib/src/mesa/main/texstore.c b/mesalib/src/mesa/main/texstore.c index cc9fbc020..05c1964d6 100644 --- a/mesalib/src/mesa/main/texstore.c +++ b/mesalib/src/mesa/main/texstore.c @@ -4499,6 +4499,9 @@ _mesa_store_teximage1d(struct gl_context *ctx, GLenum target, GLint level, (void) border; + if (width == 0) + return; + /* allocate storage for texture data */ if (!ctx->Driver.AllocTextureImageBuffer(ctx, texImage, texImage->TexFormat, width, 1, 1)) { @@ -4560,6 +4563,9 @@ _mesa_store_teximage2d(struct gl_context *ctx, GLenum target, GLint level, (void) border; + if (width == 0 || height == 0) + return; + /* allocate storage for texture data */ if (!ctx->Driver.AllocTextureImageBuffer(ctx, texImage, texImage->TexFormat, width, height, 1)) { @@ -4651,6 +4657,9 @@ _mesa_store_teximage3d(struct gl_context *ctx, GLenum target, GLint level, (void) border; + if (width == 0 || height == 0 || depth == 0) + return; + /* allocate storage for texture data */ if (!ctx->Driver.AllocTextureImageBuffer(ctx, texImage, texImage->TexFormat, width, height, depth)) { @@ -4906,7 +4915,6 @@ _mesa_store_compressed_teximage2d(struct gl_context *ctx, ASSERT(texImage->Width > 0); ASSERT(texImage->Height > 0); ASSERT(texImage->Depth == 1); - ASSERT(texImage->Data == NULL); /* was freed in glCompressedTexImage2DARB */ /* allocate storage for texture data */ if (!ctx->Driver.AllocTextureImageBuffer(ctx, texImage, texImage->TexFormat, diff --git a/mesalib/src/mesa/program/ir_to_mesa.cpp b/mesalib/src/mesa/program/ir_to_mesa.cpp index fecab50f7..bdbb6b938 100644 --- a/mesalib/src/mesa/program/ir_to_mesa.cpp +++ b/mesalib/src/mesa/program/ir_to_mesa.cpp @@ -40,6 +40,7 @@ #include "../glsl/program.h" #include "ir_optimization.h" #include "ast.h" +#include "linker.h" #include "main/mtypes.h" #include "main/shaderobj.h" @@ -2587,13 +2588,35 @@ check_resources(const struct gl_context *ctx, } } +class add_uniform_to_shader : public uniform_field_visitor { +public: + add_uniform_to_shader(struct gl_shader_program *shader_program, + struct gl_program_parameter_list *params) + : shader_program(shader_program), params(params), next_sampler(0) + { + /* empty */ + } -static int -add_uniform_to_shader(ir_variable *var, - struct gl_program_parameter_list *params, - unsigned int &next_sampler) + int process(ir_variable *var) + { + this->idx = -1; + this->uniform_field_visitor::process(var); + + return this->idx; + } + +private: + virtual void visit_field(const glsl_type *type, const char *name); + + struct gl_shader_program *shader_program; + struct gl_program_parameter_list *params; + int next_sampler; + int idx; +}; + +void +add_uniform_to_shader::visit_field(const glsl_type *type, const char *name) { - const glsl_type *type = var->type; unsigned int size; if (type->is_vector() || type->is_scalar()) { @@ -2610,10 +2633,9 @@ add_uniform_to_shader(ir_variable *var, file = PROGRAM_UNIFORM; } - int index = _mesa_lookup_parameter_index(params, -1, var->name); + int index = _mesa_lookup_parameter_index(params, -1, name); if (index < 0) { - index = _mesa_add_parameter(params, file, - var->name, size, type->gl_type, + index = _mesa_add_parameter(params, file, name, size, type->gl_type, NULL, NULL, 0x0); /* Sampler uniform values are stored in prog->SamplerUnits, @@ -2622,11 +2644,15 @@ add_uniform_to_shader(ir_variable *var, */ if (file == PROGRAM_SAMPLER) { for (unsigned int j = 0; j < size / 4; j++) - params->ParameterValues[index + j][0].f = next_sampler++; + params->ParameterValues[index + j][0].f = this->next_sampler++; } } - return index; + /* The first part of the uniform that's processed determines the base + * location of the whole uniform (for structures). + */ + if (this->idx < 0) + this->idx = index; } /** @@ -2644,7 +2670,7 @@ _mesa_generate_parameters_list_for_uniforms(struct gl_shader_program struct gl_program_parameter_list *params) { - unsigned int next_sampler = 0; + add_uniform_to_shader add(shader_program, params); foreach_list(node, sh->ir) { ir_variable *var = ((ir_instruction *) node)->as_variable(); @@ -2653,7 +2679,7 @@ _mesa_generate_parameters_list_for_uniforms(struct gl_shader_program || (strncmp(var->name, "gl_", 3) == 0)) continue; - int loc = add_uniform_to_shader(var, params, next_sampler); + int loc = add.process(var); /* The location chosen in the Parameters list here (returned from * _mesa_add_parameter) has to match what the linker chose. @@ -3212,7 +3238,9 @@ _mesa_ir_link_shader(struct gl_context *ctx, struct gl_shader_program *prog) progress = do_lower_jumps(ir, true, true, options->EmitNoMainReturn, options->EmitNoCont, options->EmitNoLoops) || progress; - progress = do_common_optimization(ir, true, options->MaxUnrollIterations) || progress; + progress = do_common_optimization(ir, true, true, + options->MaxUnrollIterations) + || progress; progress = lower_quadop_vector(ir, true) || progress; @@ -3321,7 +3349,7 @@ _mesa_glsl_compile_shader(struct gl_context *ctx, struct gl_shader *shader) /* Do some optimization at compile time to reduce shader IR size * and reduce later work if the same shader is linked multiple times */ - while (do_common_optimization(shader->ir, false, 32)) + while (do_common_optimization(shader->ir, false, false, 32)) ; validate_ir_tree(shader->ir); diff --git a/mesalib/src/mesa/state_tracker/st_cb_texture.c b/mesalib/src/mesa/state_tracker/st_cb_texture.c index 169e235ac..f82346bc6 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_texture.c +++ b/mesalib/src/mesa/state_tracker/st_cb_texture.c @@ -543,45 +543,6 @@ st_AllocTextureImageBuffer(struct gl_context *ctx, } } - -/** - * Adjust pixel unpack params and image dimensions to strip off the - * texture border. - * Gallium doesn't support texture borders. They've seldem been used - * and seldom been implemented correctly anyway. - * \param unpackNew returns the new pixel unpack parameters - */ -static void -strip_texture_border(GLint border, - GLint *width, GLint *height, GLint *depth, - const struct gl_pixelstore_attrib *unpack, - struct gl_pixelstore_attrib *unpackNew) -{ - assert(border > 0); /* sanity check */ - - *unpackNew = *unpack; - - if (unpackNew->RowLength == 0) - unpackNew->RowLength = *width; - - if (depth && unpackNew->ImageHeight == 0) - unpackNew->ImageHeight = *height; - - unpackNew->SkipPixels += border; - if (height) - unpackNew->SkipRows += border; - if (depth) - unpackNew->SkipImages += border; - - assert(*width >= 3); - *width = *width - 2 * border; - if (height && *height >= 3) - *height = *height - 2 * border; - if (depth && *depth >= 3) - *depth = *depth - 2 * border; -} - - /** * Do glTexImage1/2/3D(). */ @@ -602,7 +563,6 @@ st_TexImage(struct gl_context * ctx, struct st_texture_object *stObj = st_texture_object(texObj); struct st_texture_image *stImage = st_texture_image(texImage); GLuint dstRowStride = 0; - struct gl_pixelstore_attrib unpackNB; enum pipe_transfer_usage transfer_usage = 0; GLubyte *dstMap; @@ -627,21 +587,9 @@ st_TexImage(struct gl_context * ctx, stObj->surface_based = GL_FALSE; } - /* gallium does not support texture borders, strip it off */ - if (border) { - strip_texture_border(border, &width, &height, &depth, unpack, &unpackNB); - unpack = &unpackNB; - texImage->Width = width; - texImage->Height = height; - texImage->Depth = depth; - texImage->Border = 0; - border = 0; - } - else { - assert(texImage->Width == width); - assert(texImage->Height == height); - assert(texImage->Depth == depth); - } + assert(texImage->Width == width); + assert(texImage->Height == height); + assert(texImage->Depth == depth); stImage->base.Face = _mesa_tex_target_to_face(target); stImage->base.Level = level; diff --git a/mesalib/src/mesa/state_tracker/st_context.c b/mesalib/src/mesa/state_tracker/st_context.c index 6d4bc544d..a1817720d 100644 --- a/mesalib/src/mesa/state_tracker/st_context.c +++ b/mesalib/src/mesa/state_tracker/st_context.c @@ -144,6 +144,10 @@ st_create_context_priv( struct gl_context *ctx, struct pipe_context *pipe ) /* we want all vertex data to be placed in buffer objects */ vbo_use_buffer_objects(ctx); + + /* make sure that no VBOs are left mapped when we're drawing. */ + vbo_always_unmap_buffers(ctx); + /* Need these flags: */ st->ctx->FragmentProgram._MaintainTexEnvProgram = GL_TRUE; diff --git a/mesalib/src/mesa/state_tracker/st_context.h b/mesalib/src/mesa/state_tracker/st_context.h index 0a3220221..c60780989 100644 --- a/mesalib/src/mesa/state_tracker/st_context.h +++ b/mesalib/src/mesa/state_tracker/st_context.h @@ -75,6 +75,7 @@ struct st_context struct draw_stage *feedback_stage; /**< For GL_FEEDBACK rendermode */ struct draw_stage *selection_stage; /**< For GL_SELECT rendermode */ struct draw_stage *rastpos_stage; /**< For glRasterPos */ + GLboolean sw_primitive_restart; /* On old libGL's for linux we need to invalidate the drawables diff --git a/mesalib/src/mesa/state_tracker/st_draw.c b/mesalib/src/mesa/state_tracker/st_draw.c index 574802084..ff3008a5f 100644 --- a/mesalib/src/mesa/state_tracker/st_draw.c +++ b/mesalib/src/mesa/state_tracker/st_draw.c @@ -353,9 +353,26 @@ setup_interleaved_attribs(struct gl_context *ctx, struct pipe_context *pipe = st->pipe; GLuint attr; const GLubyte *low_addr = NULL; - - /* Find the lowest address of the arrays we're drawing */ + GLboolean usingVBO; /* all arrays in a VBO? */ + struct gl_buffer_object *bufobj; + GLuint user_buffer_size = 0; + GLuint vertex_size = 0; /* bytes per vertex, in bytes */ + GLsizei stride; + + /* Find the lowest address of the arrays we're drawing, + * Init bufobj and stride. + */ if (vpv->num_inputs) { + const GLuint mesaAttr0 = vp->index_to_input[0]; + const struct gl_client_array *array = arrays[mesaAttr0]; + + /* Since we're doing interleaved arrays, we know there'll be at most + * one buffer object and the stride will be the same for all arrays. + * Grab them now. + */ + bufobj = array->BufferObj; + stride = array->StrideB; + low_addr = arrays[vp->index_to_input[0]]->Ptr; for (attr = 1; attr < vpv->num_inputs; attr++) { @@ -363,44 +380,24 @@ setup_interleaved_attribs(struct gl_context *ctx, low_addr = MIN2(low_addr, start); } } + else { + /* not sure we'll ever have zero inputs, but play it safe */ + bufobj = NULL; + stride = 0; + low_addr = 0; + } + + /* are the arrays in user space? */ + usingVBO = bufobj && _mesa_is_bufferobj(bufobj); for (attr = 0; attr < vpv->num_inputs; attr++) { const GLuint mesaAttr = vp->index_to_input[attr]; const struct gl_client_array *array = arrays[mesaAttr]; - struct gl_buffer_object *bufobj = array->BufferObj; - struct st_buffer_object *stobj = st_buffer_object(bufobj); unsigned src_offset = (unsigned) (array->Ptr - low_addr); GLuint element_size = array->_ElementSize; - GLsizei stride = array->StrideB; assert(element_size == array->Size * _mesa_sizeof_type(array->Type)); - if (attr == 0) { - if (bufobj && _mesa_is_bufferobj(bufobj)) { - vbuffer->buffer = NULL; - pipe_resource_reference(&vbuffer->buffer, stobj->buffer); - vbuffer->buffer_offset = pointer_to_offset(low_addr); - } - else { - uint divisor = array->InstanceDivisor; - uint last_index = divisor ? num_instances / divisor : max_index; - uint bytes = src_offset + stride * last_index + element_size; - - vbuffer->buffer = pipe_user_buffer_create(pipe->screen, - (void*) low_addr, - bytes, - PIPE_BIND_VERTEX_BUFFER); - vbuffer->buffer_offset = 0; - - /* Track user vertex buffers. */ - pipe_resource_reference(&st->user_attrib[0].buffer, vbuffer->buffer); - st->user_attrib[0].element_size = element_size; - st->user_attrib[0].stride = stride; - st->num_user_attribs = 1; - } - vbuffer->stride = stride; /* in bytes */ - } - velements[attr].src_offset = src_offset; velements[attr].instance_divisor = array->InstanceDivisor; velements[attr].vertex_buffer_index = 0; @@ -409,6 +406,54 @@ setup_interleaved_attribs(struct gl_context *ctx, array->Format, array->Normalized); assert(velements[attr].src_format); + + if (!usingVBO) { + /* how many bytes referenced by this attribute array? */ + uint divisor = array->InstanceDivisor; + uint last_index = divisor ? num_instances / divisor : max_index; + uint bytes = src_offset + stride * last_index + element_size; + + user_buffer_size = MAX2(user_buffer_size, bytes); + + /* update vertex size */ + vertex_size = MAX2(vertex_size, src_offset + element_size); + } + } + + /* + * Return the vbuffer info and setup user-space attrib info, if needed. + */ + if (vpv->num_inputs == 0) { + /* just defensive coding here */ + vbuffer->buffer = NULL; + vbuffer->buffer_offset = 0; + vbuffer->stride = 0; + st->num_user_attribs = 0; + } + else if (usingVBO) { + /* all interleaved arrays in a VBO */ + struct st_buffer_object *stobj = st_buffer_object(bufobj); + + vbuffer->buffer = NULL; + pipe_resource_reference(&vbuffer->buffer, stobj->buffer); + vbuffer->buffer_offset = pointer_to_offset(low_addr); + vbuffer->stride = stride; + st->num_user_attribs = 0; + } + else { + /* all interleaved arrays in user memory */ + vbuffer->buffer = pipe_user_buffer_create(pipe->screen, + (void*) low_addr, + user_buffer_size, + PIPE_BIND_VERTEX_BUFFER); + vbuffer->buffer_offset = 0; + vbuffer->stride = stride; + + /* Track user vertex buffers. */ + pipe_resource_reference(&st->user_attrib[0].buffer, vbuffer->buffer); + st->user_attrib[0].element_size = vertex_size; + st->user_attrib[0].stride = stride; + st->num_user_attribs = 1; } } @@ -582,6 +627,127 @@ check_uniforms(struct gl_context *ctx) } } +/** Helper code for primitive restart fallback */ +#define DO_DRAW(pipe, cur_start, cur_count) \ + do { \ + info.start = cur_start; \ + info.count = cur_count; \ + if (u_trim_pipe_prim(info.mode, &info.count)) { \ + if (transfer) \ + pipe_buffer_unmap(pipe, transfer); \ + pipe->draw_vbo(pipe, &info); \ + if (transfer) { \ + ptr = pipe_buffer_map(pipe, ibuffer->buffer, PIPE_TRANSFER_READ, &transfer); \ + assert(ptr != NULL); \ + ptr = ADD_POINTERS(ptr, ibuffer->offset); \ + } \ + } \ + } while(0) + +/** More helper code for primitive restart fallback */ +#define PRIM_RESTART_LOOP(elements) \ + do { \ + for (i = start; i < end; i++) { \ + if (elements[i] == info.restart_index) { \ + if (cur_count > 0) { \ + /* draw elts up to prev pos */ \ + DO_DRAW(pipe, cur_start, cur_count); \ + } \ + /* begin new prim at next elt */ \ + cur_start = i + 1; \ + cur_count = 0; \ + } \ + else { \ + cur_count++; \ + } \ + } \ + if (cur_count > 0) { \ + DO_DRAW(pipe, cur_start, cur_count); \ + } \ + } while (0) + +static void +handle_fallback_primitive_restart(struct pipe_context *pipe, + const struct _mesa_index_buffer *ib, + struct pipe_index_buffer *ibuffer, + struct pipe_draw_info *orig_info) +{ + const unsigned start = orig_info->start; + const unsigned count = orig_info->count; + const unsigned end = start + count; + struct pipe_draw_info info = *orig_info; + struct pipe_transfer *transfer = NULL; + unsigned instance, i, cur_start, cur_count; + const void *ptr; + + info.primitive_restart = FALSE; + + if (!info.indexed) { + /* Splitting the draw arrays call is handled by the VBO module */ + if (u_trim_pipe_prim(info.mode, &info.count)) + pipe->draw_vbo(pipe, &info); + + return; + } + + /* info.indexed == TRUE */ + assert(ibuffer); + assert(ibuffer->buffer); + + if (ib) { + struct gl_buffer_object *bufobj = ib->obj; + if (bufobj && bufobj->Name) { + ptr = NULL; + } + else { + ptr = ib->ptr; + } + } else { + ptr = NULL; + } + + if (!ptr) + ptr = pipe_buffer_map(pipe, ibuffer->buffer, PIPE_TRANSFER_READ, &transfer); + + if (!ptr) + return; + ptr = ADD_POINTERS(ptr, ibuffer->offset); + + /* Need to loop over instances as well to preserve draw order */ + for (instance = 0; instance < orig_info->instance_count; instance++) { + info.start_instance = instance + orig_info->start_instance; + info.instance_count = 1; + cur_start = start; + cur_count = 0; + + switch (ibuffer->index_size) { + case 1: + { + const ubyte *elt_ub = (const ubyte *)ptr; + PRIM_RESTART_LOOP(elt_ub); + } + break; + case 2: + { + const ushort *elt_us = (const ushort *)ptr; + PRIM_RESTART_LOOP(elt_us); + } + break; + case 4: + { + const uint *elt_ui = (const uint *)ptr; + PRIM_RESTART_LOOP(elt_ui); + } + break; + default: + assert(0 && "bad index_size in handle_fallback_primitive_restart()"); + } + } + + if (transfer) + pipe_buffer_unmap(pipe, transfer); +} + /** * Translate OpenGL primtive type (GL_POINTS, GL_TRIANGLE_STRIP, etc) to @@ -794,7 +960,22 @@ st_draw_vbo(struct gl_context *ctx, info.max_index = info.start + info.count - 1; } - if (u_trim_pipe_prim(info.mode, &info.count)) + if (info.primitive_restart) { + /* + * Handle primitive restart for drivers that doesn't support it. + * + * The VBO module handles restart inside of draw_arrays for us, + * but we should still remove the primitive_restart flag on the + * info struct, the fallback function does this for us. Just + * remove the flag for all drivers in this case as well. + */ + if (st->sw_primitive_restart || !info.indexed) + handle_fallback_primitive_restart(pipe, ib, &ibuffer, &info); + else + /* don't trim, restarts might be inside index list */ + pipe->draw_vbo(pipe, &info); + } + else if (u_trim_pipe_prim(info.mode, &info.count)) pipe->draw_vbo(pipe, &info); } diff --git a/mesalib/src/mesa/state_tracker/st_extensions.c b/mesalib/src/mesa/state_tracker/st_extensions.c index a1f029089..6b9ff6b72 100644 --- a/mesalib/src/mesa/state_tracker/st_extensions.c +++ b/mesalib/src/mesa/state_tracker/st_extensions.c @@ -222,6 +222,8 @@ void st_init_limits(struct st_context *st) _mesa_override_glsl_version(st->ctx); c->UniformBooleanTrue = ~0; } + + c->StripTextureBorder = GL_TRUE; } @@ -555,8 +557,9 @@ void st_init_extensions(struct st_context *st) #endif } - if (screen->get_param(screen, PIPE_CAP_PRIMITIVE_RESTART)) { - ctx->Extensions.NV_primitive_restart = GL_TRUE; + ctx->Extensions.NV_primitive_restart = GL_TRUE; + if (!screen->get_param(screen, PIPE_CAP_PRIMITIVE_RESTART)) { + st->sw_primitive_restart = GL_TRUE; } if (screen->get_param(screen, PIPE_CAP_DEPTH_CLAMP)) { diff --git a/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp b/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp index 18e8a1db4..145bd7dcd 100644 --- a/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp +++ b/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp @@ -4322,37 +4322,15 @@ compile_tgsi_instruction(struct st_translate *t, } /** - * Emit the TGSI instructions to adjust the WPOS pixel center convention - * Basically, add (adjX, adjY) to the fragment position. - */ -static void -emit_adjusted_wpos(struct st_translate *t, - const struct gl_program *program, - float adjX, float adjY) -{ - struct ureg_program *ureg = t->ureg; - struct ureg_dst wpos_temp = ureg_DECL_temporary(ureg); - struct ureg_src wpos_input = t->inputs[t->inputMapping[FRAG_ATTRIB_WPOS]]; - - /* Note that we bias X and Y and pass Z and W through unchanged. - * The shader might also use gl_FragCoord.w and .z. - */ - ureg_ADD(ureg, wpos_temp, wpos_input, - ureg_imm4f(ureg, adjX, adjY, 0.0f, 0.0f)); - - t->inputs[t->inputMapping[FRAG_ATTRIB_WPOS]] = ureg_src(wpos_temp); -} - - -/** - * Emit the TGSI instructions for inverting the WPOS y coordinate. + * Emit the TGSI instructions for inverting and adjusting WPOS. * This code is unavoidable because it also depends on whether * a FBO is bound (STATE_FB_WPOS_Y_TRANSFORM). */ static void -emit_wpos_inversion(struct st_translate *t, - const struct gl_program *program, - bool invert) +emit_wpos_adjustment( struct st_translate *t, + const struct gl_program *program, + boolean invert, + GLfloat adjX, GLfloat adjY[2]) { struct ureg_program *ureg = t->ureg; @@ -4371,35 +4349,55 @@ emit_wpos_inversion(struct st_translate *t, unsigned wposTransConst = _mesa_add_state_reference(program->Parameters, wposTransformState); - struct ureg_src wpostrans = ureg_DECL_constant(ureg, wposTransConst); - struct ureg_dst wpos_temp; + struct ureg_src wpostrans = ureg_DECL_constant( ureg, wposTransConst ); + struct ureg_dst wpos_temp = ureg_DECL_temporary( ureg ); struct ureg_src wpos_input = t->inputs[t->inputMapping[FRAG_ATTRIB_WPOS]]; - /* MOV wpos_temp, input[wpos] - */ - if (wpos_input.File == TGSI_FILE_TEMPORARY) - wpos_temp = ureg_dst(wpos_input); - else { - wpos_temp = ureg_DECL_temporary(ureg); - ureg_MOV(ureg, wpos_temp, wpos_input); + /* First, apply the coordinate shift: */ + if (adjX || adjY[0] || adjY[1]) { + if (adjY[0] != adjY[1]) { + /* Adjust the y coordinate by adjY[1] or adjY[0] respectively + * depending on whether inversion is actually going to be applied + * or not, which is determined by testing against the inversion + * state variable used below, which will be either +1 or -1. + */ + struct ureg_dst adj_temp = ureg_DECL_temporary(ureg); + + ureg_CMP(ureg, adj_temp, + ureg_scalar(wpostrans, invert ? 2 : 0), + ureg_imm4f(ureg, adjX, adjY[0], 0.0f, 0.0f), + ureg_imm4f(ureg, adjX, adjY[1], 0.0f, 0.0f)); + ureg_ADD(ureg, wpos_temp, wpos_input, ureg_src(adj_temp)); + } else { + ureg_ADD(ureg, wpos_temp, wpos_input, + ureg_imm4f(ureg, adjX, adjY[0], 0.0f, 0.0f)); + } + wpos_input = ureg_src(wpos_temp); + } else { + /* MOV wpos_temp, input[wpos] + */ + ureg_MOV( ureg, wpos_temp, wpos_input ); } + /* Now the conditional y flip: STATE_FB_WPOS_Y_TRANSFORM.xy/zw will be + * inversion/identity, or the other way around if we're drawing to an FBO. + */ if (invert) { /* MAD wpos_temp.y, wpos_input, wpostrans.xxxx, wpostrans.yyyy */ - ureg_MAD(ureg, - ureg_writemask(wpos_temp, TGSI_WRITEMASK_Y), - wpos_input, - ureg_scalar(wpostrans, 0), - ureg_scalar(wpostrans, 1)); + ureg_MAD( ureg, + ureg_writemask(wpos_temp, TGSI_WRITEMASK_Y ), + wpos_input, + ureg_scalar(wpostrans, 0), + ureg_scalar(wpostrans, 1)); } else { /* MAD wpos_temp.y, wpos_input, wpostrans.zzzz, wpostrans.wwww */ - ureg_MAD(ureg, - ureg_writemask(wpos_temp, TGSI_WRITEMASK_Y), - wpos_input, - ureg_scalar(wpostrans, 2), - ureg_scalar(wpostrans, 3)); + ureg_MAD( ureg, + ureg_writemask(wpos_temp, TGSI_WRITEMASK_Y ), + wpos_input, + ureg_scalar(wpostrans, 2), + ureg_scalar(wpostrans, 3)); } /* Use wpos_temp as position input from here on: @@ -4420,8 +4418,37 @@ emit_wpos(struct st_context *st, const struct gl_fragment_program *fp = (const struct gl_fragment_program *) program; struct pipe_screen *pscreen = st->pipe->screen; + GLfloat adjX = 0.0f; + GLfloat adjY[2] = { 0.0f, 0.0f }; boolean invert = FALSE; + /* Query the pixel center conventions supported by the pipe driver and set + * adjX, adjY to help out if it cannot handle the requested one internally. + * + * The bias of the y-coordinate depends on whether y-inversion takes place + * (adjY[1]) or not (adjY[0]), which is in turn dependent on whether we are + * drawing to an FBO (causes additional inversion), and whether the the pipe + * driver origin and the requested origin differ (the latter condition is + * stored in the 'invert' variable). + * + * For height = 100 (i = integer, h = half-integer, l = lower, u = upper): + * + * center shift only: + * i -> h: +0.5 + * h -> i: -0.5 + * + * inversion only: + * l,i -> u,i: ( 0.0 + 1.0) * -1 + 100 = 99 + * l,h -> u,h: ( 0.5 + 0.0) * -1 + 100 = 99.5 + * u,i -> l,i: (99.0 + 1.0) * -1 + 100 = 0 + * u,h -> l,h: (99.5 + 0.0) * -1 + 100 = 0.5 + * + * inversion and center shift: + * l,i -> u,h: ( 0.0 + 0.5) * -1 + 100 = 99.5 + * l,h -> u,i: ( 0.5 + 0.5) * -1 + 100 = 99 + * u,i -> l,h: (99.0 + 0.5) * -1 + 100 = 0.5 + * u,h -> l,i: (99.5 + 0.5) * -1 + 100 = 0 + */ if (fp->OriginUpperLeft) { /* Fragment shader wants origin in upper-left */ if (pscreen->get_param(pscreen, PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT)) { @@ -4449,12 +4476,17 @@ emit_wpos(struct st_context *st, if (fp->PixelCenterInteger) { /* Fragment shader wants pixel center integer */ - if (pscreen->get_param(pscreen, PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER)) + if (pscreen->get_param(pscreen, PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER)) { /* the driver supports pixel center integer */ + adjY[1] = 1.0f; ureg_property_fs_coord_pixel_center(ureg, TGSI_FS_COORD_PIXEL_CENTER_INTEGER); - else if (pscreen->get_param(pscreen, PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER)) + } + else if (pscreen->get_param(pscreen, PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER)) { /* the driver supports pixel center half integer, need to bias X,Y */ - emit_adjusted_wpos(t, program, 0.5f, invert ? 0.5f : -0.5f); + adjX = -0.5f; + adjY[0] = -0.5f; + adjY[1] = 0.5f; + } else assert(0); } @@ -4465,8 +4497,8 @@ emit_wpos(struct st_context *st, } else if (pscreen->get_param(pscreen, PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER)) { /* the driver supports pixel center integer, need to bias X,Y */ + adjX = adjY[0] = adjY[1] = 0.5f; ureg_property_fs_coord_pixel_center(ureg, TGSI_FS_COORD_PIXEL_CENTER_INTEGER); - emit_adjusted_wpos(t, program, 0.5f, invert ? -0.5f : 0.5f); } else assert(0); @@ -4474,7 +4506,7 @@ emit_wpos(struct st_context *st, /* we invert after adjustment so that we avoid the MOV to temporary, * and reuse the adjustment ADD instead */ - emit_wpos_inversion(t, program, invert); + emit_wpos_adjustment(t, program, invert, adjX, adjY); } /** @@ -5026,7 +5058,9 @@ st_link_shader(struct gl_context *ctx, struct gl_shader_program *prog) progress = do_lower_jumps(ir, true, true, options->EmitNoMainReturn, options->EmitNoCont, options->EmitNoLoops) || progress; - progress = do_common_optimization(ir, true, options->MaxUnrollIterations) || progress; + progress = do_common_optimization(ir, true, true, + options->MaxUnrollIterations) + || progress; progress = lower_quadop_vector(ir, false) || progress; diff --git a/mesalib/src/mesa/swrast/s_context.c b/mesalib/src/mesa/swrast/s_context.c index 5287671d7..9112cf30d 100644 --- a/mesalib/src/mesa/swrast/s_context.c +++ b/mesalib/src/mesa/swrast/s_context.c @@ -747,6 +747,12 @@ _swrast_CreateContext( struct gl_context *ctx ) swrast->AllowVertexFog = GL_TRUE; swrast->AllowPixelFog = GL_TRUE; + swrast->Driver.SpanRenderStart = _swrast_span_render_start; + swrast->Driver.SpanRenderFinish = _swrast_span_render_finish; + + ctx->Driver.MapTexture = _swrast_map_texture; + ctx->Driver.UnmapTexture = _swrast_unmap_texture; + /* Optimized Accum buffer */ swrast->_IntegerAccumMode = GL_FALSE; swrast->_IntegerAccumScaler = 0.0; @@ -837,6 +843,24 @@ _swrast_render_primitive( struct gl_context *ctx, GLenum prim ) } +/** called via swrast->Driver.SpanRenderStart() */ +void +_swrast_span_render_start(struct gl_context *ctx) +{ + _swrast_map_textures(ctx); + _swrast_map_renderbuffers(ctx); +} + + +/** called via swrast->Driver.SpanRenderFinish() */ +void +_swrast_span_render_finish(struct gl_context *ctx) +{ + _swrast_unmap_textures(ctx); + _swrast_unmap_renderbuffers(ctx); +} + + void _swrast_render_start( struct gl_context *ctx ) { diff --git a/mesalib/src/mesa/swrast/s_context.h b/mesalib/src/mesa/swrast/s_context.h index ec8451eb8..d3ba37819 100644 --- a/mesalib/src/mesa/swrast/s_context.h +++ b/mesalib/src/mesa/swrast/s_context.h @@ -138,20 +138,17 @@ struct swrast_texture_image /** used for mipmap LOD computation */ GLfloat WidthScale, HeightScale, DepthScale; -#if 0 - GLubyte *Data; /**< The actual texture data in malloc'd memory */ + /** These fields only valid when texture memory is mapped */ + GLint RowStride; /**< Padded width in units of texels */ + GLuint *ImageOffsets; /**< if 3D texture: array [Depth] of offsets to + each 2D slice in 'Data', in texels */ + GLubyte *Data; /**< Image data, accessed via FetchTexel() */ - GLint TexelSize; /**< bytes per texel block */ -#endif + /** Malloc'd texture memory */ + GLubyte *Buffer; FetchTexelFunc FetchTexel; StoreTexelFunc Store; - -#if 0 - /** These fields only valid when texture memory is mapped */ - GLubyte **SliceMaps; /**< points to OneMap or a malloc'd array */ - GLint RowStride; /**< bytes per row of blocks */ -#endif }; @@ -339,6 +336,31 @@ swrast_render_finish(struct gl_context *ctx) } +extern void +_swrast_span_render_start(struct gl_context *ctx); + +extern void +_swrast_span_render_finish(struct gl_context *ctx); + +extern void +_swrast_map_textures(struct gl_context *ctx); + +extern void +_swrast_unmap_textures(struct gl_context *ctx); + +extern void +_swrast_map_texture(struct gl_context *ctx, struct gl_texture_object *texObj); + +extern void +_swrast_unmap_texture(struct gl_context *ctx, struct gl_texture_object *texObj); + + +extern void +_swrast_map_renderbuffers(struct gl_context *ctx); + +extern void +_swrast_unmap_renderbuffers(struct gl_context *ctx); + /** * Size of an RGBA pixel, in bytes, for given datatype. diff --git a/mesalib/src/mesa/swrast/s_fragprog.c b/mesalib/src/mesa/swrast/s_fragprog.c index 7f205a200..1caa0ebc2 100644 --- a/mesalib/src/mesa/swrast/s_fragprog.c +++ b/mesalib/src/mesa/swrast/s_fragprog.c @@ -237,7 +237,8 @@ run_program(struct gl_context *ctx, SWspan *span, GLuint start, GLuint end) else if (depth >= 1.0) span->array->z[i] = ctx->DrawBuffer->_DepthMax; else - span->array->z[i] = IROUND(depth * ctx->DrawBuffer->_DepthMaxF); + span->array->z[i] = + (GLuint) (depth * ctx->DrawBuffer->_DepthMaxF + 0.5F); } } else { diff --git a/mesalib/src/mesa/swrast/s_span.c b/mesalib/src/mesa/swrast/s_span.c index e517c9ae1..4124e444e 100644 --- a/mesalib/src/mesa/swrast/s_span.c +++ b/mesalib/src/mesa/swrast/s_span.c @@ -1251,7 +1251,10 @@ _swrast_write_rgba_span( struct gl_context *ctx, SWspan *span) 4 * span->end * sizeof(GLchan)); } - ASSERT(rb->_BaseFormat == GL_RGBA || rb->_BaseFormat == GL_RGB || + ASSERT(rb->_BaseFormat == GL_RGBA || + rb->_BaseFormat == GL_RGB || + rb->_BaseFormat == GL_RED || + rb->_BaseFormat == GL_RG || rb->_BaseFormat == GL_ALPHA); if (ctx->Color.ColorLogicOpEnabled) { diff --git a/mesalib/src/mesa/swrast/s_texcombine.c b/mesalib/src/mesa/swrast/s_texcombine.c index c67c356c1..a7cbb4424 100644 --- a/mesalib/src/mesa/swrast/s_texcombine.c +++ b/mesalib/src/mesa/swrast/s_texcombine.c @@ -108,6 +108,7 @@ texture_combine( struct gl_context *ctx, GLuint unit, GLuint n, i--; } _mesa_error(ctx, GL_OUT_OF_MEMORY, "texture_combine"); + free(rgba); return; } } diff --git a/mesalib/src/mesa/swrast/s_texfetch_tmp.h b/mesalib/src/mesa/swrast/s_texfetch_tmp.h index c63b2043c..8b7e930f9 100644 --- a/mesalib/src/mesa/swrast/s_texfetch_tmp.h +++ b/mesalib/src/mesa/swrast/s_texfetch_tmp.h @@ -43,7 +43,7 @@ #if DIM == 1 #define TEXEL_ADDR( type, image, i, j, k, size ) \ - ((void) (j), (void) (k), ((type *)(image)->Base.Data + (i) * (size))) + ((void) (j), (void) (k), ((type *)(image)->Data + (i) * (size))) #define FETCH(x) fetch_texel_1d_##x @@ -51,15 +51,15 @@ #define TEXEL_ADDR( type, image, i, j, k, size ) \ ((void) (k), \ - ((type *)(image)->Base.Data + ((image)->Base.RowStride * (j) + (i)) * (size))) + ((type *)(image)->Data + ((image)->RowStride * (j) + (i)) * (size))) #define FETCH(x) fetch_texel_2d_##x #elif DIM == 3 #define TEXEL_ADDR( type, image, i, j, k, size ) \ - ((type *)(image)->Base.Data + ((image)->Base.ImageOffsets[k] \ - + (image)->Base.RowStride * (j) + (i)) * (size)) + ((type *)(image)->Data + ((image)->ImageOffsets[k] \ + + (image)->RowStride * (j) + (i)) * (size)) #define FETCH(x) fetch_texel_3d_##x diff --git a/mesalib/src/mesa/swrast/s_texfilter.c b/mesalib/src/mesa/swrast/s_texfilter.c index f8b0fa1aa..9de5c0276 100644 --- a/mesalib/src/mesa/swrast/s_texfilter.c +++ b/mesalib/src/mesa/swrast/s_texfilter.c @@ -1375,7 +1375,7 @@ opt_sample_rgb_2d(struct gl_context *ctx, GLint i = IFLOOR(texcoords[k][0] * width) & colMask; GLint j = IFLOOR(texcoords[k][1] * height) & rowMask; GLint pos = (j << shift) | i; - GLubyte *texel = ((GLubyte *) img->Data) + 3*pos; + GLubyte *texel = swImg->Data + 3 * pos; rgba[k][RCOMP] = UBYTE_TO_FLOAT(texel[2]); rgba[k][GCOMP] = UBYTE_TO_FLOAT(texel[1]); rgba[k][BCOMP] = UBYTE_TO_FLOAT(texel[0]); @@ -1419,7 +1419,7 @@ opt_sample_rgba_2d(struct gl_context *ctx, const GLint col = IFLOOR(texcoords[i][0] * width) & colMask; const GLint row = IFLOOR(texcoords[i][1] * height) & rowMask; const GLint pos = (row << shift) | col; - const GLuint texel = *((GLuint *) img->Data + pos); + const GLuint texel = *((GLuint *) swImg->Data + pos); rgba[i][RCOMP] = UBYTE_TO_FLOAT( (texel >> 24) ); rgba[i][GCOMP] = UBYTE_TO_FLOAT( (texel >> 16) & 0xff ); rgba[i][BCOMP] = UBYTE_TO_FLOAT( (texel >> 8) & 0xff ); @@ -1442,7 +1442,7 @@ sample_lambda_2d(struct gl_context *ctx, const GLboolean repeatNoBorderPOT = (tObj->Sampler.WrapS == GL_REPEAT) && (tObj->Sampler.WrapT == GL_REPEAT) - && (tImg->Border == 0 && (tImg->Width == tImg->RowStride)) + && (tImg->Border == 0 && (tImg->Width == swImg->RowStride)) && swImg->_IsPowerOfTwo; ASSERT(lambda != NULL); diff --git a/mesalib/src/mesa/swrast/s_texrender.c b/mesalib/src/mesa/swrast/s_texrender.c index 47e458e1c..e2b921512 100644 --- a/mesalib/src/mesa/swrast/s_texrender.c +++ b/mesalib/src/mesa/swrast/s_texrender.c @@ -31,6 +31,15 @@ struct texture_renderbuffer }; +/** cast wrapper */ +static inline struct texture_renderbuffer * +texture_renderbuffer(struct gl_renderbuffer *rb) +{ + return (struct texture_renderbuffer *) rb; +} + + + /** * Get row of values from the renderbuffer that wraps a texture image. */ @@ -38,8 +47,7 @@ static void texture_get_row(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count, GLint x, GLint y, void *values) { - const struct texture_renderbuffer *trb - = (const struct texture_renderbuffer *) rb; + struct texture_renderbuffer *trb = texture_renderbuffer(rb); const GLint z = trb->Zoffset; GLuint i; @@ -107,8 +115,7 @@ static void texture_get_values(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count, const GLint x[], const GLint y[], void *values) { - const struct texture_renderbuffer *trb - = (const struct texture_renderbuffer *) rb; + struct texture_renderbuffer *trb = texture_renderbuffer(rb); const GLint z = trb->Zoffset; GLuint i; @@ -174,8 +181,7 @@ static void texture_put_row(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count, GLint x, GLint y, const void *values, const GLubyte *mask) { - const struct texture_renderbuffer *trb - = (const struct texture_renderbuffer *) rb; + struct texture_renderbuffer *trb = texture_renderbuffer(rb); const GLint z = trb->Zoffset; GLuint i; @@ -236,8 +242,7 @@ static void texture_put_row_rgb(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count, GLint x, GLint y, const void *values, const GLubyte *mask) { - const struct texture_renderbuffer *trb - = (const struct texture_renderbuffer *) rb; + struct texture_renderbuffer *trb = texture_renderbuffer(rb); const GLint z = trb->Zoffset; GLuint i; @@ -296,8 +301,7 @@ static void texture_put_mono_row(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count, GLint x, GLint y, const void *value, const GLubyte *mask) { - const struct texture_renderbuffer *trb - = (const struct texture_renderbuffer *) rb; + struct texture_renderbuffer *trb = texture_renderbuffer(rb); const GLint z = trb->Zoffset; GLuint i; @@ -356,8 +360,7 @@ texture_put_values(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint co const GLint x[], const GLint y[], const void *values, const GLubyte *mask) { - const struct texture_renderbuffer *trb - = (const struct texture_renderbuffer *) rb; + struct texture_renderbuffer *trb = texture_renderbuffer(rb); const GLint z = trb->Zoffset; GLuint i; @@ -415,8 +418,7 @@ texture_put_mono_values(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count, const GLint x[], const GLint y[], const void *value, const GLubyte *mask) { - const struct texture_renderbuffer *trb - = (const struct texture_renderbuffer *) rb; + struct texture_renderbuffer *trb = texture_renderbuffer(rb); const GLint z = trb->Zoffset; GLuint i; @@ -610,7 +612,6 @@ update_wrapper(struct gl_context *ctx, struct gl_renderbuffer_attachment *att) trb->Base.DataType = CHAN_TYPE; trb->Base._BaseFormat = GL_RGBA; } - trb->Base.Data = trb->TexImage->Base.Data; } diff --git a/mesalib/src/mesa/swrast/s_texture.c b/mesalib/src/mesa/swrast/s_texture.c index 36b429cfa..fb1edb318 100644 --- a/mesalib/src/mesa/swrast/s_texture.c +++ b/mesalib/src/mesa/swrast/s_texture.c @@ -69,14 +69,32 @@ _swrast_alloc_texture_image_buffer(struct gl_context *ctx, { struct swrast_texture_image *swImg = swrast_texture_image(texImage); GLuint bytes = _mesa_format_image_size(format, width, height, depth); + GLuint i; /* This _should_ be true (revisit if these ever fail) */ assert(texImage->Width == width); assert(texImage->Height == height); assert(texImage->Depth == depth); - assert(!texImage->Data); - texImage->Data = _mesa_align_malloc(bytes, 512); + assert(!swImg->Buffer); + swImg->Buffer = _mesa_align_malloc(bytes, 512); + if (!swImg->Buffer) + return GL_FALSE; + + /* RowStride and ImageOffsets[] describe how to address texels in 'Data' */ + swImg->RowStride = width; + + /* Allocate the ImageOffsets array and initialize to typical values. + * We allocate the array for 1D/2D textures too in order to avoid special- + * case code in the texstore routines. + */ + swImg->ImageOffsets = (GLuint *) malloc(depth * sizeof(GLuint)); + if (!swImg->ImageOffsets) + return GL_FALSE; + + for (i = 0; i < depth; i++) { + swImg->ImageOffsets[i] = i * width * height; + } if ((width == 1 || _mesa_is_pow_two(texImage->Width2)) && (height == 1 || _mesa_is_pow_two(texImage->Height2)) && @@ -98,7 +116,7 @@ _swrast_alloc_texture_image_buffer(struct gl_context *ctx, swImg->DepthScale = (GLfloat) texImage->Depth; } - return texImage->Data != NULL; + return GL_TRUE; } @@ -109,11 +127,16 @@ void _swrast_free_texture_image_buffer(struct gl_context *ctx, struct gl_texture_image *texImage) { - if (texImage->Data) { - _mesa_align_free(texImage->Data); + struct swrast_texture_image *swImage = swrast_texture_image(texImage); + if (swImage->Buffer) { + _mesa_align_free(swImage->Buffer); + swImage->Buffer = NULL; } - texImage->Data = NULL; + if (swImage->ImageOffsets) { + free(swImage->ImageOffsets); + swImage->ImageOffsets = NULL; + } } @@ -155,6 +178,7 @@ _swrast_map_teximage(struct gl_context *ctx, GLubyte **mapOut, GLint *rowStrideOut) { + struct swrast_texture_image *swImage = swrast_texture_image(texImage); GLubyte *map; GLint stride, texelSize; GLuint bw, bh; @@ -165,9 +189,9 @@ _swrast_map_teximage(struct gl_context *ctx, stride = _mesa_format_row_stride(texImage->TexFormat, texImage->Width); _mesa_get_format_block_size(texImage->TexFormat, &bw, &bh); - assert(texImage->Data); + assert(swImage->Buffer); - map = texImage->Data; + map = swImage->Buffer; if (texImage->TexObject->Target == GL_TEXTURE_3D || texImage->TexObject->Target == GL_TEXTURE_2D_ARRAY) { @@ -200,3 +224,138 @@ _swrast_unmap_teximage(struct gl_context *ctx, { /* nop */ } + + +void +_swrast_map_texture(struct gl_context *ctx, struct gl_texture_object *texObj) +{ + const GLuint faces = texObj->Target == GL_TEXTURE_CUBE_MAP ? 6 : 1; + GLuint face, level; + + for (face = 0; face < faces; face++) { + for (level = texObj->BaseLevel; level < MAX_TEXTURE_LEVELS; level++) { + struct gl_texture_image *texImage = texObj->Image[face][level]; + if (texImage) { + struct swrast_texture_image *swImage = + swrast_texture_image(texImage); + + /* XXX we'll eventually call _swrast_map_teximage() here */ + swImage->Data = swImage->Buffer; + assert(swImage->Buffer); + } + } + } +} + + +void +_swrast_unmap_texture(struct gl_context *ctx, struct gl_texture_object *texObj) +{ + const GLuint faces = texObj->Target == GL_TEXTURE_CUBE_MAP ? 6 : 1; + GLuint face, level; + + for (face = 0; face < faces; face++) { + for (level = texObj->BaseLevel; level < MAX_TEXTURE_LEVELS; level++) { + struct gl_texture_image *texImage = texObj->Image[face][level]; + if (texImage) { + struct swrast_texture_image *swImage + = swrast_texture_image(texImage); + + /* XXX we'll eventually call _swrast_unmap_teximage() here */ + swImage->Data = NULL; + } + } + } +} + + +/** + * Map all textures for reading prior to software rendering. + */ +void +_swrast_map_textures(struct gl_context *ctx) +{ + GLbitfield enabledUnits = ctx->Texture._EnabledUnits; + + /* loop over enabled texture units */ + while (enabledUnits) { + GLuint unit = _mesa_ffs(enabledUnits) - 1; + struct gl_texture_object *texObj = ctx->Texture.Unit[unit]._Current; + + _swrast_map_texture(ctx, texObj); + + enabledUnits &= ~(1 << unit); + } +} + + +/** + * Unmap all textures for reading prior to software rendering. + */ +void +_swrast_unmap_textures(struct gl_context *ctx) +{ + GLbitfield enabledUnits = ctx->Texture._EnabledUnits; + + /* loop over enabled texture units */ + while (enabledUnits) { + GLuint unit = _mesa_ffs(enabledUnits) - 1; + struct gl_texture_object *texObj = ctx->Texture.Unit[unit]._Current; + + _swrast_unmap_texture(ctx, texObj); + + enabledUnits &= ~(1 << unit); + } +} + + +/** + * Map or unmap any textures that we may be rendering to as renderbuffers. + */ +static void +map_unmap_renderbuffers(struct gl_context *ctx, + struct gl_framebuffer *fb, + GLboolean map) +{ + GLuint i; + + for (i = 0; i < Elements(fb->Attachment); i++) { + struct gl_texture_object *texObj = fb->Attachment[i].Texture; + if (texObj) { + const GLuint level = fb->Attachment[i].TextureLevel; + const GLuint face = fb->Attachment[i].CubeMapFace; + struct gl_texture_image *texImage = texObj->Image[face][level]; + if (texImage) { + struct swrast_texture_image *swImage + = swrast_texture_image(texImage); + + if (map) { + /* XXX we'll eventually call _swrast_map_teximage() here */ + swImage->Data = swImage->Buffer; + } + else { + /* XXX we'll eventually call _swrast_unmap_teximage() here */ + swImage->Data = NULL; + } + } + } + } +} + + +void +_swrast_map_renderbuffers(struct gl_context *ctx) +{ + map_unmap_renderbuffers(ctx, ctx->DrawBuffer, GL_TRUE); + if (ctx->ReadBuffer != ctx->DrawBuffer) + map_unmap_renderbuffers(ctx, ctx->ReadBuffer, GL_TRUE); +} + + +void +_swrast_unmap_renderbuffers(struct gl_context *ctx) +{ + map_unmap_renderbuffers(ctx, ctx->DrawBuffer, GL_FALSE); + if (ctx->ReadBuffer != ctx->DrawBuffer) + map_unmap_renderbuffers(ctx, ctx->ReadBuffer, GL_FALSE); +} diff --git a/mesalib/src/mesa/swrast/s_triangle.c b/mesalib/src/mesa/swrast/s_triangle.c index 839c4fd08..b4f8e7479 100644 --- a/mesalib/src/mesa/swrast/s_triangle.c +++ b/mesalib/src/mesa/swrast/s_triangle.c @@ -127,10 +127,12 @@ _swrast_culltriangle( struct gl_context *ctx, ctx->Texture.Unit[0].CurrentTex[TEXTURE_2D_INDEX]; \ const struct gl_texture_image *texImg = \ obj->Image[0][obj->BaseLevel]; \ + const struct swrast_texture_image *swImg = \ + swrast_texture_image_const(texImg); \ const GLfloat twidth = (GLfloat) texImg->Width; \ const GLfloat theight = (GLfloat) texImg->Height; \ const GLint twidth_log2 = texImg->WidthLog2; \ - const GLubyte *texture = (const GLubyte *) texImg->Data; \ + const GLubyte *texture = (const GLubyte *) swImg->Data; \ const GLint smask = texImg->Width - 1; \ const GLint tmask = texImg->Height - 1; \ ASSERT(texImg->TexFormat == MESA_FORMAT_RGB888); \ @@ -181,10 +183,12 @@ _swrast_culltriangle( struct gl_context *ctx, ctx->Texture.Unit[0].CurrentTex[TEXTURE_2D_INDEX]; \ const struct gl_texture_image *texImg = \ obj->Image[0][obj->BaseLevel]; \ + const struct swrast_texture_image *swImg = \ + swrast_texture_image_const(texImg); \ const GLfloat twidth = (GLfloat) texImg->Width; \ const GLfloat theight = (GLfloat) texImg->Height; \ const GLint twidth_log2 = texImg->WidthLog2; \ - const GLubyte *texture = (const GLubyte *) texImg->Data; \ + const GLubyte *texture = (const GLubyte *) swImg->Data; \ const GLint smask = texImg->Width - 1; \ const GLint tmask = texImg->Height - 1; \ ASSERT(texImg->TexFormat == MESA_FORMAT_RGB888); \ @@ -533,9 +537,11 @@ affine_span(struct gl_context *ctx, SWspan *span, ctx->Texture.Unit[0].CurrentTex[TEXTURE_2D_INDEX]; \ const struct gl_texture_image *texImg = \ obj->Image[0][obj->BaseLevel]; \ + const struct swrast_texture_image *swImg = \ + swrast_texture_image_const(texImg); \ const GLfloat twidth = (GLfloat) texImg->Width; \ const GLfloat theight = (GLfloat) texImg->Height; \ - info.texture = (const GLchan *) texImg->Data; \ + info.texture = (const GLchan *) swImg->Data; \ info.twidth_log2 = texImg->WidthLog2; \ info.smask = texImg->Width - 1; \ info.tmask = texImg->Height - 1; \ @@ -800,7 +806,9 @@ fast_persp_span(struct gl_context *ctx, SWspan *span, ctx->Texture.Unit[0].CurrentTex[TEXTURE_2D_INDEX]; \ const struct gl_texture_image *texImg = \ obj->Image[0][obj->BaseLevel]; \ - info.texture = (const GLchan *) texImg->Data; \ + const struct swrast_texture_image *swImg = \ + swrast_texture_image_const(texImg); \ + info.texture = (const GLchan *) swImg->Data; \ info.twidth_log2 = texImg->WidthLog2; \ info.smask = texImg->Width - 1; \ info.tmask = texImg->Height - 1; \ @@ -1062,7 +1070,7 @@ _swrast_choose_triangle( struct gl_context *ctx ) && texObj2D->_Swizzle == SWIZZLE_NOOP && swImg->_IsPowerOfTwo && texImg->Border == 0 - && texImg->Width == texImg->RowStride + && texImg->Width == swImg->RowStride && (format == MESA_FORMAT_RGB888 || format == MESA_FORMAT_RGBA8888) && minFilter == magFilter && ctx->Light.Model.ColorControl == GL_SINGLE_COLOR diff --git a/mesalib/src/mesa/tnl/t_vb_program.c b/mesalib/src/mesa/tnl/t_vb_program.c index 367dfd5bb..836e8e8fa 100644 --- a/mesalib/src/mesa/tnl/t_vb_program.c +++ b/mesalib/src/mesa/tnl/t_vb_program.c @@ -68,6 +68,8 @@ struct vp_stage_data { GLubyte *clipmask; /**< clip flags */ GLubyte ormask, andmask; /**< for clipping */ + GLboolean vertex_textures; + struct gl_program_machine machine; }; diff --git a/mesalib/src/mesa/vbo/vbo_exec.h b/mesalib/src/mesa/vbo/vbo_exec.h index 9a1b5a127..0b72579a8 100644 --- a/mesalib/src/mesa/vbo/vbo_exec.h +++ b/mesalib/src/mesa/vbo/vbo_exec.h @@ -78,9 +78,6 @@ struct vbo_exec_copied_vtx { }; -typedef void (*vbo_attrfv_func)( const GLfloat * ); - - struct vbo_exec_context { struct gl_context *ctx; @@ -113,8 +110,6 @@ struct vbo_exec_context * values are squashed down to the 32 attributes passed to the * vertex program below: */ - enum vp_mode program_mode; - GLuint enabled_flags; const struct gl_client_array *inputs[VERT_ATTRIB_MAX]; } vtx; @@ -126,10 +121,6 @@ struct vbo_exec_context } eval; struct { - enum vp_mode program_mode; - GLuint enabled_flags; - GLuint array_obj; - /* These just mirror the current arrayobj (todo: make arrayobj * look like this and remove the mirror): */ diff --git a/mesalib/src/mesa/vbo/vbo_exec_array.c b/mesalib/src/mesa/vbo/vbo_exec_array.c index 4e4f2c947..7023380a1 100644 --- a/mesalib/src/mesa/vbo/vbo_exec_array.c +++ b/mesalib/src/mesa/vbo/vbo_exec_array.c @@ -422,8 +422,6 @@ bind_array_obj(struct gl_context *ctx) assert(i < Elements(exec->array.generic_array)); exec->array.generic_array[i] = &arrayObj->VertexAttrib[i]; } - - exec->array.array_obj = arrayObj->Name; } @@ -444,10 +442,7 @@ recalculate_input_bindings(struct gl_context *ctx) GLbitfield const_inputs = 0x0; GLuint i; - exec->array.program_mode = get_program_mode(ctx); - exec->array.enabled_flags = ctx->Array.ArrayObj->_Enabled; - - switch (exec->array.program_mode) { + switch (get_program_mode(ctx)) { case VP_NONE: /* When no vertex program is active (or the vertex program is generated * from fixed-function state). We put the material values into the diff --git a/mesalib/src/mesa/vbo/vbo_save.h b/mesalib/src/mesa/vbo/vbo_save.h index a064090cf..a85a7cbf6 100644 --- a/mesalib/src/mesa/vbo/vbo_save.h +++ b/mesalib/src/mesa/vbo/vbo_save.h @@ -146,7 +146,6 @@ struct vbo_save_context { GLuint vert_count; GLuint max_vert; GLboolean dangling_attr_ref; - GLboolean have_materials; GLuint opcode_vertex_list; diff --git a/mkfontscale/data.h b/mkfontscale/data.h index 6fb43ae79..aecb04859 100644 --- a/mkfontscale/data.h +++ b/mkfontscale/data.h @@ -27,7 +27,9 @@ URW++, and both strings appear in the notice. */ static const char *notice_foundries[][2] = - {{"Bigelow", "b&h"}, + {{"Iorsh", "culmus"}, + {"Gnat", "culmus"}, + {"Bigelow", "b&h"}, {"Adobe", "adobe"}, {"Bitstream", "bitstream"}, {"Monotype", "monotype"}, @@ -42,9 +44,7 @@ static const char *notice_foundries[][2] = {"Microsoft", "microsoft"}, {"Omega", "omega"}, {"Font21", "hwan"}, - {"HanYang System", "hanyang"}, - {"Iorsh", "culmus"}, - {"Gnat", "culmus"}}; + {"HanYang System", "hanyang"}}; /* This table is partly taken from ttmkfdir by Joerg Pommnitz. */ diff --git a/pixman/Makefile.am b/pixman/Makefile.am index ff87e26a3..df8677a2f 100644 --- a/pixman/Makefile.am +++ b/pixman/Makefile.am @@ -87,6 +87,8 @@ release-upload: release-check $(tar_gz) $(tar_bz2) $(sha1_tgz) $(sha1_tbz2) $(md scp $(tar_gz) $(tar_bz2) $(RELEASE_XORG_HOST):$(RELEASE_XORG_DIR) ssh $(RELEASE_CAIRO_HOST) "rm -f $(RELEASE_CAIRO_DIR)/LATEST-$(PACKAGE)-[0-9]* && ln -s $(tar_gz) $(RELEASE_CAIRO_DIR)/LATEST-$(PACKAGE)-$(VERSION)" +RELEASE_TYPE = $$(if test "x$(PIXMAN_VERSION_MINOR)" = "x$$(echo "$(PIXMAN_VERSION_MINOR)/2*2" | bc)" ; then echo "stable release in the" ; else echo "development snapshot leading up to a stable"; fi) + release-publish-message: $(HASHFILES) ensure-prev @echo "Please follow the instructions in RELEASING to push stuff out and" @echo "send out the announcement mails. Here is the excerpt you need:" @@ -94,7 +96,7 @@ release-publish-message: $(HASHFILES) ensure-prev @echo "Lists: $(RELEASE_ANNOUNCE_LIST)" @echo "Subject: [ANNOUNCE] $(PACKAGE) release $(VERSION) now available" @echo "============================== CUT HERE ==============================" - @echo "A new $(PACKAGE) release $(VERSION) is now available" + @echo "A new $(PACKAGE) release $(VERSION) is now available. This is a $(RELEASE_TYPE)" @echo "" @echo "tar.gz:" @echo " $(RELEASE_CAIRO_URL)/$(tar_gz)" diff --git a/pixman/pixman/pixman-gradient-walker.c b/pixman/pixman/pixman-gradient-walker.c index dd666b412..048039e89 100644 --- a/pixman/pixman/pixman-gradient-walker.c +++ b/pixman/pixman/pixman-gradient-walker.c @@ -31,7 +31,7 @@ void _pixman_gradient_walker_init (pixman_gradient_walker_t *walker, gradient_t * gradient, - unsigned int spread) + pixman_repeat_t repeat) { walker->num_stops = gradient->n_stops; walker->stops = gradient->stops; @@ -42,112 +42,54 @@ _pixman_gradient_walker_init (pixman_gradient_walker_t *walker, walker->left_rb = 0; walker->right_ag = 0; walker->right_rb = 0; - walker->spread = spread; + walker->repeat = repeat; walker->need_reset = TRUE; } -void -_pixman_gradient_walker_reset (pixman_gradient_walker_t *walker, - pixman_fixed_32_32_t pos) +static void +gradient_walker_reset (pixman_gradient_walker_t *walker, + pixman_fixed_48_16_t pos) { int32_t x, left_x, right_x; - pixman_color_t *left_c, *right_c; + pixman_color_t *left_c, *right_c; int n, count = walker->num_stops; - pixman_gradient_stop_t * stops = walker->stops; - - static const pixman_color_t transparent_black = { 0, 0, 0, 0 }; + pixman_gradient_stop_t *stops = walker->stops; - switch (walker->spread) + if (walker->repeat == PIXMAN_REPEAT_NORMAL) { - case PIXMAN_REPEAT_NORMAL: - x = (int32_t)pos & 0xFFFF; - for (n = 0; n < count; n++) - if (x < stops[n].x) - break; - if (n == 0) - { - left_x = stops[count - 1].x - 0x10000; - left_c = &stops[count - 1].color; - } - else - { - left_x = stops[n - 1].x; - left_c = &stops[n - 1].color; - } - - if (n == count) - { - right_x = stops[0].x + 0x10000; - right_c = &stops[0].color; - } - else - { - right_x = stops[n].x; - right_c = &stops[n].color; - } - left_x += (pos - x); - right_x += (pos - x); - break; - - case PIXMAN_REPEAT_PAD: - for (n = 0; n < count; n++) - if (pos < stops[n].x) - break; - - if (n == 0) - { - left_x = INT32_MIN; - left_c = &stops[0].color; - } - else - { - left_x = stops[n - 1].x; - left_c = &stops[n - 1].color; - } - - if (n == count) - { - right_x = INT32_MAX; - right_c = &stops[n - 1].color; - } - else - { - right_x = stops[n].x; - right_c = &stops[n].color; - } - break; - - case PIXMAN_REPEAT_REFLECT: - x = (int32_t)pos & 0xFFFF; + x = (int32_t)pos & 0xffff; + } + else if (walker->repeat == PIXMAN_REPEAT_REFLECT) + { + x = (int32_t)pos & 0xffff; if ((int32_t)pos & 0x10000) x = 0x10000 - x; - for (n = 0; n < count; n++) - if (x < stops[n].x) - break; - - if (n == 0) - { - left_x = -stops[0].x; - left_c = &stops[0].color; - } - else - { - left_x = stops[n - 1].x; - left_c = &stops[n - 1].color; - } - - if (n == count) - { - right_x = 0x20000 - stops[n - 1].x; - right_c = &stops[n - 1].color; - } - else - { - right_x = stops[n].x; - right_c = &stops[n].color; - } - + } + else + { + x = pos; + } + + for (n = 0; n < count; n++) + { + if (x < stops[n].x) + break; + } + + left_x = stops[n - 1].x; + left_c = &stops[n - 1].color; + + right_x = stops[n].x; + right_c = &stops[n].color; + + if (walker->repeat == PIXMAN_REPEAT_NORMAL) + { + left_x += (pos - x); + right_x += (pos - x); + } + else if (walker->repeat == PIXMAN_REPEAT_REFLECT) + { if ((int32_t)pos & 0x10000) { pixman_color_t *tmp_c; @@ -165,32 +107,6 @@ _pixman_gradient_walker_reset (pixman_gradient_walker_t *walker, } left_x += (pos - x); right_x += (pos - x); - break; - - default: /* REPEAT_NONE */ - for (n = 0; n < count; n++) - if (pos < stops[n].x) - break; - - if (n == 0) - { - left_x = INT32_MIN; - right_x = stops[0].x; - left_c = right_c = (pixman_color_t*) &transparent_black; - } - else if (n == count) - { - left_x = stops[n - 1].x; - right_x = INT32_MAX; - left_c = right_c = (pixman_color_t*) &transparent_black; - } - else - { - left_x = stops[n - 1].x; - right_x = stops[n].x; - left_c = &stops[n - 1].color; - right_c = &stops[n].color; - } } walker->left_x = left_x; @@ -201,8 +117,8 @@ _pixman_gradient_walker_reset (pixman_gradient_walker_t *walker, walker->right_rb = ((right_c->red & 0xff00) << 8) | (right_c->blue >> 8); if (walker->left_x == walker->right_x || - ( walker->left_ag == walker->right_ag && - walker->left_rb == walker->right_rb ) ) + (walker->left_ag == walker->right_ag && + walker->left_rb == walker->right_rb)) { walker->stepper = 0; } @@ -215,20 +131,15 @@ _pixman_gradient_walker_reset (pixman_gradient_walker_t *walker, walker->need_reset = FALSE; } -#define PIXMAN_GRADIENT_WALKER_NEED_RESET(w, x) \ - ( (w)->need_reset || (x) < (w)->left_x || (x) >= (w)->right_x) - - -/* the following assumes that PIXMAN_GRADIENT_WALKER_NEED_RESET(w,x) is FALSE */ uint32_t _pixman_gradient_walker_pixel (pixman_gradient_walker_t *walker, - pixman_fixed_32_32_t x) + pixman_fixed_48_16_t x) { int dist, idist; uint32_t t1, t2, a, color; - if (PIXMAN_GRADIENT_WALKER_NEED_RESET (walker, x)) - _pixman_gradient_walker_reset (walker, x); + if (walker->need_reset || x < walker->left_x || x >= walker->right_x) + gradient_walker_reset (walker, x); dist = ((int)(x - walker->left_x) * walker->stepper) >> 16; idist = 256 - dist; diff --git a/pixman/pixman/pixman-image.c b/pixman/pixman/pixman-image.c index afe587f31..09d7cbc4e 100644 --- a/pixman/pixman/pixman-image.c +++ b/pixman/pixman/pixman-image.c @@ -31,6 +31,50 @@ #include "pixman-private.h" +static const pixman_color_t transparent_black = { 0, 0, 0, 0 }; + +static void +gradient_property_changed (pixman_image_t *image) +{ + gradient_t *gradient = &image->gradient; + int n = gradient->n_stops; + pixman_gradient_stop_t *stops = gradient->stops; + pixman_gradient_stop_t *begin = &(gradient->stops[-1]); + pixman_gradient_stop_t *end = &(gradient->stops[n]); + + switch (gradient->common.repeat) + { + default: + case PIXMAN_REPEAT_NONE: + begin->x = INT32_MIN; + begin->color = transparent_black; + end->x = INT32_MAX; + end->color = transparent_black; + break; + + case PIXMAN_REPEAT_NORMAL: + begin->x = stops[n - 1].x - pixman_fixed_1; + begin->color = stops[n - 1].color; + end->x = stops[0].x + pixman_fixed_1; + end->color = stops[0].color; + break; + + case PIXMAN_REPEAT_REFLECT: + begin->x = - stops[0].x; + begin->color = stops[0].color; + end->x = pixman_int_to_fixed (2) - stops[n - 1].x; + end->color = stops[n - 1].color; + break; + + case PIXMAN_REPEAT_PAD: + begin->x = INT32_MIN; + begin->color = stops[0].color; + end->x = INT32_MAX; + end->color = stops[n - 1].color; + break; + } +} + pixman_bool_t _pixman_init_gradient (gradient_t * gradient, const pixman_gradient_stop_t *stops, @@ -38,14 +82,27 @@ _pixman_init_gradient (gradient_t * gradient, { return_val_if_fail (n_stops > 0, FALSE); - gradient->stops = pixman_malloc_ab (n_stops, sizeof (pixman_gradient_stop_t)); + /* We allocate two extra stops, one before the beginning of the stop list, + * and one after the end. These stops are initialized to whatever color + * would be used for positions outside the range of the stop list. + * + * This saves a bit of computation in the gradient walker. + * + * The pointer we store in the gradient_t struct still points to the + * first user-supplied struct, so when freeing, we will have to + * subtract one. + */ + gradient->stops = + pixman_malloc_ab (n_stops + 2, sizeof (pixman_gradient_stop_t)); if (!gradient->stops) return FALSE; + gradient->stops += 1; memcpy (gradient->stops, stops, n_stops * sizeof (pixman_gradient_stop_t)); - gradient->n_stops = n_stops; + gradient->common.property_changed = gradient_property_changed; + return TRUE; } @@ -102,7 +159,17 @@ _pixman_image_fini (pixman_image_t *image) image->type == CONICAL) { if (image->gradient.stops) - free (image->gradient.stops); + { + /* See _pixman_init_gradient() for an explanation of the - 1 */ + free (image->gradient.stops - 1); + } + + /* This will trigger if someone adds a property_changed + * method to the linear/radial/conical gradient overwriting + * the general one. + */ + assert ( + image->common.property_changed == gradient_property_changed); } if (image->type == BITS && image->bits.free_me) diff --git a/pixman/pixman/pixman-private.h b/pixman/pixman/pixman-private.h index cbd48f3d1..1443bfb3d 100644 --- a/pixman/pixman/pixman-private.h +++ b/pixman/pixman/pixman-private.h @@ -299,29 +299,29 @@ typedef struct uint32_t left_rb; uint32_t right_ag; uint32_t right_rb; - int32_t left_x; - int32_t right_x; - int32_t stepper; + pixman_fixed_t left_x; + pixman_fixed_t right_x; + pixman_fixed_t stepper; pixman_gradient_stop_t *stops; int num_stops; - unsigned int spread; + pixman_repeat_t repeat; - int need_reset; + pixman_bool_t need_reset; } pixman_gradient_walker_t; void _pixman_gradient_walker_init (pixman_gradient_walker_t *walker, gradient_t * gradient, - unsigned int spread); + pixman_repeat_t repeat); void _pixman_gradient_walker_reset (pixman_gradient_walker_t *walker, - pixman_fixed_32_32_t pos); + pixman_fixed_48_16_t pos); uint32_t _pixman_gradient_walker_pixel (pixman_gradient_walker_t *walker, - pixman_fixed_32_32_t x); + pixman_fixed_48_16_t x); /* * Edges diff --git a/xorg-server/Xi/exevents.c b/xorg-server/Xi/exevents.c index ea393d224..1fe284dfc 100644 --- a/xorg-server/Xi/exevents.c +++ b/xorg-server/Xi/exevents.c @@ -653,7 +653,7 @@ DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to, DeviceChangedEvent *dc * Send an XI2 DeviceChangedEvent to all interested clients. */ void -XISendDeviceChangedEvent(DeviceIntPtr device, DeviceIntPtr master, DeviceChangedEvent *dce) +XISendDeviceChangedEvent(DeviceIntPtr device, DeviceChangedEvent *dce) { xXIDeviceChangedEvent *dcce; int rc; @@ -667,7 +667,7 @@ XISendDeviceChangedEvent(DeviceIntPtr device, DeviceIntPtr master, DeviceChanged /* we don't actually swap if there's a NullClient, swapping is done * later when event is delivered. */ - SendEventToAllWindows(master, XI_DeviceChangedMask, (xEvent*)dcce, 1); + SendEventToAllWindows(device, XI_DeviceChangedMask, (xEvent*)dcce, 1); free(dcce); } @@ -701,7 +701,8 @@ ChangeMasterDeviceClasses(DeviceIntPtr device, DeviceChangedEvent *dce) /* FIXME: the classes may have changed since we generated the event. */ DeepCopyDeviceClasses(slave, device, dce); - XISendDeviceChangedEvent(slave, device, dce); + dce->deviceid = device->id; + XISendDeviceChangedEvent(device, dce); } /** @@ -1106,6 +1107,8 @@ SetScrollValuator(DeviceIntPtr dev, int axnum, enum ScrollType type, double incr { AxisInfoPtr ax; int *current_ax; + InternalEvent dce; + DeviceIntPtr master; if (!dev || !dev->valuator || axnum >= dev->valuator->numAxes) return FALSE; @@ -1142,7 +1145,16 @@ SetScrollValuator(DeviceIntPtr dev, int axnum, enum ScrollType type, double incr ax->scroll.type = type; ax->scroll.increment = increment; ax->scroll.flags = flags; - /* FIXME: generate DeviceChanged Events */ + + master = GetMaster(dev, MASTER_ATTACHED); + CreateClassesChangedEvent(&dce, master, dev, DEVCHANGE_POINTER_EVENT | DEVCHANGE_DEVICE_CHANGE); + XISendDeviceChangedEvent(dev, &dce.changed_event); + + /* if the current slave is us, update the master. If not, we'll update + * whenever the next slave switch happens anyway. CMDC sends the event + * for us */ + if (master && master->lastSlave == dev) + ChangeMasterDeviceClasses(master, &dce.changed_event); return TRUE; } diff --git a/xorg-server/Xi/xiquerydevice.c b/xorg-server/Xi/xiquerydevice.c index 9961d1b6f..5f543f620 100644 --- a/xorg-server/Xi/xiquerydevice.c +++ b/xorg-server/Xi/xiquerydevice.c @@ -41,6 +41,7 @@ #include "xserver-properties.h" #include "exevents.h" #include "xace.h" +#include "inpututils.h" #include "xiquerydevice.h" @@ -351,8 +352,7 @@ ListValuatorInfo(DeviceIntPtr dev, xXIValuatorInfo* info, int axisnumber, info->min.frac = 0; info->max.integral = v->axes[axisnumber].max_value; info->max.frac = 0; - info->value.integral = (int)v->axisVal[axisnumber]; - info->value.frac = (int)(v->axisVal[axisnumber] * (1 << 16) * (1 << 16)); + info->value = double_to_fp3232(v->axisVal[axisnumber]); info->resolution = v->axes[axisnumber].resolution; info->number = axisnumber; info->mode = valuator_get_mode(dev, axisnumber); @@ -402,8 +402,7 @@ ListScrollInfo(DeviceIntPtr dev, xXIScrollInfo *info, int axisnumber) ErrorF("[Xi] Unknown scroll type %d. This is a bug.\n", axis->scroll.type); break; } - info->increment.integral = (int)axis->scroll.increment; - info->increment.frac = (unsigned int)(axis->scroll.increment * (1UL << 16) * (1UL << 16)); + info->increment = double_to_fp3232(axis->scroll.increment); info->sourceid = v->sourceid; info->flags = 0; diff --git a/xorg-server/composite/compalloc.c b/xorg-server/composite/compalloc.c index c4430af43..5b53e6931 100644 --- a/xorg-server/composite/compalloc.c +++ b/xorg-server/composite/compalloc.c @@ -196,11 +196,7 @@ compRedirectWindow (ClientPtr pClient, WindowPtr pWin, int update) anyMarked = compMarkWindows (pWin, &pLayerWin); - /* Make sure our borderClip is correct for ValidateTree */ RegionNull(&cw->borderClip); - RegionCopy(&cw->borderClip, &pWin->borderClip); - cw->borderClipX = pWin->drawable.x; - cw->borderClipY = pWin->drawable.y; cw->update = CompositeRedirectAutomatic; cw->clients = 0; cw->oldx = COMP_ORIGIN_INVALID; @@ -658,6 +654,13 @@ compAllocPixmap (WindowPtr pWin) DamageRegister (&pWin->drawable, cw->damage); cw->damageRegistered = TRUE; } + + /* Make sure our borderClip is up to date */ + RegionUninit(&cw->borderClip); + RegionCopy(&cw->borderClip, &pWin->borderClip); + cw->borderClipX = pWin->drawable.x; + cw->borderClipY = pWin->drawable.y; + return TRUE; } diff --git a/xorg-server/configure.ac b/xorg-server/configure.ac index 4bfa82c24..63d59f92d 100644 --- a/xorg-server/configure.ac +++ b/xorg-server/configure.ac @@ -87,6 +87,12 @@ XORG_PROG_RAWCPP # easier overrides at build time. XSERVER_CFLAGS='$(CWARNFLAGS)' +dnl Explicitly add -fno-strict-aliasing since this option should disappear +dnl from util-macros CWARNFLAGS +if test "x$GCC" = xyes ; then + XSERVER_CFLAGS="$XSERVER_CFLAGS -fno-strict-aliasing" +fi + dnl Check for dtrace program (needed to build Xserver dtrace probes) dnl Also checks for <sys/sdt.h>, since some Linux distros have an dnl ISDN trace program named dtrace diff --git a/xorg-server/dix/devices.c b/xorg-server/dix/devices.c index 73c4d1460..c8ae230cd 100644 --- a/xorg-server/dix/devices.c +++ b/xorg-server/dix/devices.c @@ -2368,7 +2368,7 @@ RecalculateMasterButtons(DeviceIntPtr slave) event.keys.max_keycode = master->key->xkbInfo->desc->max_key_code; } - XISendDeviceChangedEvent(master, master, &event); + XISendDeviceChangedEvent(master, &event); } } diff --git a/xorg-server/dix/eventconvert.c b/xorg-server/dix/eventconvert.c index 5269e53bc..d7b161e02 100644 --- a/xorg-server/dix/eventconvert.c +++ b/xorg-server/dix/eventconvert.c @@ -43,10 +43,13 @@ #include "inputstr.h" #include "misc.h" #include "eventstr.h" +#include "exevents.h" #include "exglobals.h" #include "eventconvert.h" +#include "inpututils.h" #include "xiquerydevice.h" #include "xkbsrv.h" +#include "inpututils.h" static int countValuators(DeviceEvent *ev, int *first); @@ -482,6 +485,40 @@ appendValuatorInfo(DeviceChangedEvent *dce, xXIValuatorInfo *info, int axisnumbe } static int +appendScrollInfo(DeviceChangedEvent *dce, xXIScrollInfo *info, int axisnumber) +{ + if (dce->valuators[axisnumber].scroll.type == SCROLL_TYPE_NONE) + return 0; + + info->type = XIScrollClass; + info->length = sizeof(xXIScrollInfo)/4; + info->number = axisnumber; + switch(dce->valuators[axisnumber].scroll.type) + { + case SCROLL_TYPE_VERTICAL: + info->scroll_type = XIScrollTypeVertical; + break; + case SCROLL_TYPE_HORIZONTAL: + info->scroll_type = XIScrollTypeHorizontal; + break; + default: + ErrorF("[Xi] Unknown scroll type %d. This is a bug.\n", dce->valuators[axisnumber].scroll.type); + break; + } + info->increment = double_to_fp3232(dce->valuators[axisnumber].scroll.increment); + info->sourceid = dce->sourceid; + + info->flags = 0; + + if (dce->valuators[axisnumber].scroll.flags & SCROLL_FLAG_DONT_EMULATE) + info->flags |= XIScrollFlagNoEmulation; + if (dce->valuators[axisnumber].scroll.flags & SCROLL_FLAG_PREFERRED) + info->flags |= XIScrollFlagPreferred; + + return info->length * 4; +} + +static int eventToDeviceChanged(DeviceChangedEvent *dce, xEvent **xi) { xXIDeviceChangedEvent *dcce; @@ -496,8 +533,16 @@ eventToDeviceChanged(DeviceChangedEvent *dce, xEvent **xi) len += pad_to_int32(bits_to_bytes(dce->buttons.num_buttons)); } if (dce->num_valuators) + { + int i; + len += sizeof(xXIValuatorInfo) * dce->num_valuators; + for (i = 0; i < dce->num_valuators; i++) + if (dce->valuators[i].scroll.type != SCROLL_TYPE_NONE) + len += sizeof(xXIScrollInfo); + } + nkeys = (dce->keys.max_keycode > 0) ? dce->keys.max_keycode - dce->keys.min_keycode + 1 : 0; if (nkeys > 0) @@ -543,6 +588,15 @@ eventToDeviceChanged(DeviceChangedEvent *dce, xEvent **xi) dcce->num_classes += dce->num_valuators; for (i = 0; i < dce->num_valuators; i++) ptr += appendValuatorInfo(dce, (xXIValuatorInfo*)ptr, i); + + for (i = 0; i < dce->num_valuators; i++) + { + if (dce->valuators[i].scroll.type != SCROLL_TYPE_NONE) + { + dcce->num_classes++; + ptr += appendScrollInfo(dce, (xXIScrollInfo*)ptr, i); + } + } } *xi = (xEvent*)dcce; @@ -633,9 +687,7 @@ eventToDeviceEvent(DeviceEvent *ev, xEvent **xi) if (BitIsOn(ev->valuators.mask, i)) { SetBit(ptr, i); - axisval->integral = trunc(ev->valuators.data[i]); - axisval->frac = (ev->valuators.data[i] - axisval->integral) * - (1 << 16) * (1 << 16); + *axisval = double_to_fp3232(ev->valuators.data[i]); axisval++; } } @@ -679,13 +731,8 @@ eventToRawEvent(RawDeviceEvent *ev, xEvent **xi) if (BitIsOn(ev->valuators.mask, i)) { SetBit(ptr, i); - axisval->integral = trunc(ev->valuators.data[i]); - axisval->frac = (ev->valuators.data[i] - axisval->integral) * - (1 << 16) * (1 << 16); - axisval_raw->integral = trunc(ev->valuators.data_raw[i]); - axisval_raw->frac = - (ev->valuators.data_raw[i] - axisval_raw->integral) * - (1 << 16) * (1 << 16); + *axisval = double_to_fp3232(ev->valuators.data[i]); + *axisval_raw = double_to_fp3232(ev->valuators.data_raw[i]); axisval++; axisval_raw++; } diff --git a/xorg-server/dix/getevents.c b/xorg-server/dix/getevents.c index f000620e3..226d5cd43 100644 --- a/xorg-server/dix/getevents.c +++ b/xorg-server/dix/getevents.c @@ -224,7 +224,7 @@ void CreateClassesChangedEvent(InternalEvent* event, DeviceIntPtr master, DeviceIntPtr slave, - int type) + int flags) { int i; DeviceChangedEvent *dce; @@ -233,13 +233,12 @@ CreateClassesChangedEvent(InternalEvent* event, dce = &event->changed_event; memset(dce, 0, sizeof(DeviceChangedEvent)); dce->deviceid = slave->id; - dce->masterid = master->id; + dce->masterid = master ? master->id : 0; dce->header = ET_Internal; dce->length = sizeof(DeviceChangedEvent); dce->type = ET_DeviceChanged; dce->time = ms; - dce->flags = type; - dce->flags |= DEVCHANGE_SLAVE_SWITCH; + dce->flags = flags; dce->sourceid = slave->id; if (slave->button) @@ -258,6 +257,7 @@ CreateClassesChangedEvent(InternalEvent* event, dce->valuators[i].resolution = slave->valuator->axes[i].resolution; dce->valuators[i].mode = slave->valuator->axes[i].mode; dce->valuators[i].name = slave->valuator->axes[i].label; + dce->valuators[i].scroll = slave->valuator->axes[i].scroll; } } if (slave->key) @@ -688,7 +688,7 @@ UpdateFromMaster(InternalEvent* events, DeviceIntPtr dev, int type, int *num_eve if (master && master->last.slave != dev) { - CreateClassesChangedEvent(events, master, dev, type); + CreateClassesChangedEvent(events, master, dev, type | DEVCHANGE_SLAVE_SWITCH); if (IsPointerDevice(master)) { updateSlaveDeviceCoords(master, dev); @@ -1249,6 +1249,7 @@ fill_pointer_events(InternalEvent *events, DeviceIntPtr pDev, int type, * * @param events The pointer to the event list to fill the events * @param dev The device to generate the events for + * @param type The real type of the event * @param axis The axis number to generate events for * @param mask State before this event in absolute coords * @param[in,out] last Last scroll state posted in absolute coords (modified @@ -1260,6 +1261,7 @@ fill_pointer_events(InternalEvent *events, DeviceIntPtr pDev, int type, static int emulate_scroll_button_events(InternalEvent *events, DeviceIntPtr dev, + int type, int axis, const ValuatorMask *mask, ValuatorMask *last, @@ -1272,6 +1274,7 @@ emulate_scroll_button_events(InternalEvent *events, int num_events = 0; double total; int b; + int flags = 0; if (dev->valuator->axes[axis].scroll.type == SCROLL_TYPE_NONE) return 0; @@ -1282,6 +1285,9 @@ emulate_scroll_button_events(InternalEvent *events, ax = &dev->valuator->axes[axis]; incr = ax->scroll.increment; + if (type != ButtonPress && type != ButtonRelease) + flags |= POINTER_EMULATED; + if (!valuator_mask_isset(last, axis)) valuator_mask_set_double(last, axis, 0); @@ -1309,14 +1315,20 @@ emulate_scroll_button_events(InternalEvent *events, */ if (num_events + 4 < max_events) { - nev_tmp = fill_pointer_events(events, dev, ButtonPress, b, ms, - POINTER_EMULATED, NULL); - events += nev_tmp; - num_events += nev_tmp; - nev_tmp = fill_pointer_events(events, dev, ButtonRelease, b, ms, - POINTER_EMULATED, NULL); - events += nev_tmp; - num_events += nev_tmp; + if (type != ButtonRelease) + { + nev_tmp = fill_pointer_events(events, dev, ButtonPress, b, ms, + flags, NULL); + events += nev_tmp; + num_events += nev_tmp; + } + if (type != ButtonPress) + { + nev_tmp = fill_pointer_events(events, dev, ButtonRelease, b, ms, + flags, NULL); + events += nev_tmp; + num_events += nev_tmp; + } } } @@ -1361,6 +1373,7 @@ GetPointerEvents(InternalEvent *events, DeviceIntPtr pDev, int type, ValuatorMask mask; ValuatorMask scroll; int i; + int realtype = type; /* refuse events from disabled devices */ if (!pDev->enabled) @@ -1413,6 +1426,7 @@ GetPointerEvents(InternalEvent *events, DeviceIntPtr pDev, int type, valuator_mask_set_double(&mask, axis, val); type = MotionNotify; buttons = 0; + flags |= POINTER_EMULATED; } } @@ -1432,7 +1446,7 @@ GetPointerEvents(InternalEvent *events, DeviceIntPtr pDev, int type, valuator_mask_set_double(&scroll, i, pDev->last.valuators[i]); - nev_tmp = emulate_scroll_button_events(events, pDev, i, &scroll, + nev_tmp = emulate_scroll_button_events(events, pDev, realtype, i, &scroll, pDev->last.scroll, ms, GetMaximumEventsNum() - num_events); events += nev_tmp; diff --git a/xorg-server/dix/inpututils.c b/xorg-server/dix/inpututils.c index 5c76361b3..5797f9256 100644 --- a/xorg-server/dix/inpututils.c +++ b/xorg-server/dix/inpututils.c @@ -38,6 +38,7 @@ #include "inpututils.h" #include "eventstr.h" #include "scrnintstr.h" +#include "optionstr.h" /* Check if a button map change is okay with the device. * Returns -1 for BadValue, as it collides with MappingBusy. */ @@ -539,6 +540,42 @@ valuator_mask_get(const ValuatorMask *mask, int valuator) } /** + * Set value to the requested valuator. If the mask bit is set for this + * valuator, value contains the requested valuator value and TRUE is + * returned. + * If the mask bit is not set for this valuator, value is unchanged and + * FALSE is returned. + */ +Bool +valuator_mask_fetch_double(const ValuatorMask *mask, int valuator, double *value) +{ + if (valuator_mask_isset(mask, valuator)) + { + *value = valuator_mask_get_double(mask, valuator); + return TRUE; + } else + return FALSE; +} + +/** + * Set value to the requested valuator. If the mask bit is set for this + * valuator, value contains the requested valuator value and TRUE is + * returned. + * If the mask bit is not set for this valuator, value is unchanged and + * FALSE is returned. + */ +Bool +valuator_mask_fetch(const ValuatorMask *mask, int valuator, int *value) +{ + if (valuator_mask_isset(mask, valuator)) + { + *value = valuator_mask_get(mask, valuator); + return TRUE; + } else + return FALSE; +} + +/** * Remove the valuator from the mask. */ void @@ -634,8 +671,9 @@ point_on_screen(ScreenPtr pScreen, int x, int y) static void input_option_free(InputOption *o) { - free(o->key); - free(o->value); + free(o->opt_name); + free(o->opt_val); + free(o->opt_comment); free(o); } @@ -665,7 +703,7 @@ input_option_new(InputOption* list, const char *key, const char *value) if (list) { - nt_list_for_each_entry(opt, list, next) + nt_list_for_each_entry(opt, list, list.next) { if (strcmp(input_option_get_key(opt), key) == 0) { @@ -679,13 +717,13 @@ input_option_new(InputOption* list, const char *key, const char *value) if (!opt) return NULL; - nt_list_init(opt, next); + nt_list_init(opt, list.next); input_option_set_key(opt, key); input_option_set_value(opt, value); if (list) { - nt_list_append(opt, list, InputOption, next); + nt_list_append(opt, list, InputOption, list.next); return list; } else return opt; @@ -696,9 +734,9 @@ input_option_free_element(InputOption *list, const char *key) { InputOption *element; - nt_list_for_each_entry(element, list, next) { + nt_list_for_each_entry(element, list, list.next) { if (strcmp(input_option_get_key(element), key) == 0) { - nt_list_del(element, list, InputOption, next); + nt_list_del(element, list, InputOption, list.next); input_option_free(element); break; } @@ -714,8 +752,8 @@ input_option_free_list(InputOption **opt) { InputOption *element, *tmp; - nt_list_for_each_entry_safe(element, tmp, *opt, next) { - nt_list_del(element, *opt, InputOption, next); + nt_list_for_each_entry_safe(element, tmp, *opt, list.next) { + nt_list_del(element, *opt, InputOption, list.next); input_option_free(element); } *opt = NULL; @@ -732,7 +770,7 @@ input_option_find(InputOption *list, const char *key) { InputOption *element; - nt_list_for_each_entry(element, list, next) { + nt_list_for_each_entry(element, list, list.next) { if (strcmp(input_option_get_key(element), key) == 0) return element; } @@ -743,29 +781,29 @@ input_option_find(InputOption *list, const char *key) const char* input_option_get_key(const InputOption *opt) { - return opt->key; + return opt->opt_name; } const char* input_option_get_value(const InputOption *opt) { - return opt->value; + return opt->opt_val; } void input_option_set_key(InputOption *opt, const char *key) { - free(opt->key); + free(opt->opt_name); if (key) - opt->key = strdup(key); + opt->opt_name = strdup(key); } void input_option_set_value(InputOption *opt, const char *value) { - free(opt->value); + free(opt->opt_val); if (value) - opt->value = strdup(value); + opt->opt_val = strdup(value); } diff --git a/xorg-server/dix/ptrveloc.c b/xorg-server/dix/ptrveloc.c index fc5cf49b8..1ba531c96 100644 --- a/xorg-server/dix/ptrveloc.c +++ b/xorg-server/dix/ptrveloc.c @@ -658,13 +658,13 @@ QueryTrackers(DeviceVelocityPtr vel, int cur_t){ DebugAccelF("(dix prtacc) query: last tracker in effect\n"); used_offset = vel->num_tracker-1; } -#ifdef PTRACCEL_DEBUGGING if(used_offset >= 0){ +#ifdef PTRACCEL_DEBUGGING MotionTracker *tracker = TRACKER(vel, used_offset); DebugAccelF("(dix prtacc) result: offset %i [dx: %i dy: %i diff: %i]\n", used_offset, tracker->dx, tracker->dy, cur_t - tracker->time); - } #endif + } return result; } diff --git a/xorg-server/hw/kdrive/src/kinput.c b/xorg-server/hw/kdrive/src/kinput.c index 3d87996be..27e33043f 100644 --- a/xorg-server/hw/kdrive/src/kinput.c +++ b/xorg-server/hw/kdrive/src/kinput.c @@ -49,6 +49,7 @@ #include "eventstr.h" #include "xserver-properties.h" #include "inpututils.h" +#include "optionstr.h" #define AtomFromName(x) MakeAtom(x, strlen(x), 1) @@ -364,7 +365,7 @@ KdEnableInput (void) } static KdKeyboardDriver * -KdFindKeyboardDriver (char *name) +KdFindKeyboardDriver (const char *name) { KdKeyboardDriver *ret; @@ -381,7 +382,7 @@ KdFindKeyboardDriver (char *name) } static KdPointerDriver * -KdFindPointerDriver (char *name) +KdFindPointerDriver (const char *name) { KdPointerDriver *ret; @@ -1063,33 +1064,39 @@ KdRemovePointer (KdPointerInfo *pi) static Bool KdGetOptions (InputOption **options, char *string) { - InputOption *newopt = NULL, **tmpo = NULL; + InputOption *newopt = NULL; + char *key = NULL, + *value = NULL; int tam_key = 0; - newopt = calloc(1, sizeof (InputOption)); - if (!newopt) - return FALSE; - - for (tmpo = options; *tmpo; tmpo = &(*tmpo)->next) - ; /* Hello, I'm here */ - *tmpo = newopt; - if (strchr(string, '=')) { tam_key = (strchr(string, '=') - string); - newopt->key = (char *)malloc(tam_key); - strncpy(newopt->key, string, tam_key); - newopt->key[tam_key] = '\0'; - newopt->value = strdup(strchr(string, '=') + 1); + key = malloc(tam_key + 1); + if (!key) + goto out; + + strncpy(key, string, tam_key); + key[tam_key] = '\0'; + value = strdup(strchr(string, '=') + 1); + if (!value) + goto out; } else { - newopt->key = strdup(string); - newopt->value = NULL; + key = strdup(string); + value = NULL; } - newopt->next = NULL; - return TRUE; + newopt = input_option_new(*options, key, value); + if (newopt) + *options = newopt; + +out: + free(key); + free(value); + + return (newopt != NULL); } static void @@ -1097,23 +1104,26 @@ KdParseKbdOptions (KdKeyboardInfo *ki) { InputOption *option = NULL; - for (option = ki->options; option; option = option->next) + nt_list_for_each_entry(option, ki->options, list.next) { - if (strcasecmp(option->key, "XkbRules") == 0) - ki->xkbRules = option->value; - else if (strcasecmp(option->key, "XkbModel") == 0) - ki->xkbModel = option->value; - else if (strcasecmp(option->key, "XkbLayout") == 0) - ki->xkbLayout = option->value; - else if (strcasecmp(option->key, "XkbVariant") == 0) - ki->xkbVariant = option->value; - else if (strcasecmp(option->key, "XkbOptions") == 0) - ki->xkbOptions = option->value; - else if (!strcasecmp (option->key, "device")) - ki->path = strdup(option->value); + const char *key = input_option_get_key(option); + const char *value = input_option_get_value(option); + + if (strcasecmp(key, "XkbRules") == 0) + ki->xkbRules = strdup(value); + else if (strcasecmp(key, "XkbModel") == 0) + ki->xkbModel = strdup(value); + else if (strcasecmp(key, "XkbLayout") == 0) + ki->xkbLayout = strdup(value); + else if (strcasecmp(key, "XkbVariant") == 0) + ki->xkbVariant = strdup(value); + else if (strcasecmp(key, "XkbOptions") == 0) + ki->xkbOptions = strdup(value); + else if (!strcasecmp (key, "device")) + ki->path = strdup(value); else ErrorF("Kbd option key (%s) of value (%s) not assigned!\n", - option->key, option->value); + key, value); } } @@ -1194,23 +1204,26 @@ KdParsePointerOptions (KdPointerInfo *pi) { InputOption *option = NULL; - for (option = pi->options; option; option = option->next) + nt_list_for_each_entry(option, pi->options, list.next) { - if (!strcmp (option->key, "emulatemiddle")) + const char *key = input_option_get_key(option); + const char *value = input_option_get_value(option); + + if (!strcmp (key, "emulatemiddle")) pi->emulateMiddleButton = TRUE; - else if (!strcmp (option->key, "noemulatemiddle")) + else if (!strcmp (key, "noemulatemiddle")) pi->emulateMiddleButton = FALSE; - else if (!strcmp (option->key, "transformcoord")) + else if (!strcmp (key, "transformcoord")) pi->transformCoordinates = TRUE; - else if (!strcmp (option->key, "rawcoord")) + else if (!strcmp (key, "rawcoord")) pi->transformCoordinates = FALSE; - else if (!strcasecmp (option->key, "device")) - pi->path = strdup(option->value); - else if (!strcasecmp (option->key, "protocol")) - pi->protocol = strdup(option->value); + else if (!strcasecmp (key, "device")) + pi->path = strdup(value); + else if (!strcasecmp (key, "protocol")) + pi->protocol = strdup(value); else ErrorF("Pointer option key (%s) of value (%s) not assigned!\n", - option->key, option->value); + key, value); } } @@ -2241,14 +2254,17 @@ NewInputDeviceRequest(InputOption *options, InputAttributes *attrs, KdPointerInfo *pi = NULL; KdKeyboardInfo *ki = NULL; - for (option = options; option; option = option->next) { - if (strcmp(option->key, "type") == 0) { - if (strcmp(option->value, "pointer") == 0) { + nt_list_for_each_entry(option, options, list.next) { + const char *key = input_option_get_key(option); + const char *value = input_option_get_value(option); + + if (strcmp(key, "type") == 0) { + if (strcmp(value, "pointer") == 0) { pi = KdNewPointer(); if (!pi) return BadAlloc; } - else if (strcmp(option->value, "keyboard") == 0) { + else if (strcmp(value, "keyboard") == 0) { ki = KdNewKeyboard(); if (!ki) return BadAlloc; @@ -2259,16 +2275,16 @@ NewInputDeviceRequest(InputOption *options, InputAttributes *attrs, } } #ifdef CONFIG_HAL - else if (strcmp(option->key, "_source") == 0 && - strcmp(option->value, "server/hal") == 0) + else if (strcmp(key, "_source") == 0 && + strcmp(value, "server/hal") == 0) { ErrorF("Ignoring device from HAL.\n"); return BadValue; } #endif #ifdef CONFIG_UDEV - else if (strcmp(option->key, "_source") == 0 && - strcmp(option->value, "server/udev") == 0) + else if (strcmp(key, "_source") == 0 && + strcmp(value, "server/udev") == 0) { ErrorF("Ignoring device from udev.\n"); return BadValue; @@ -2283,16 +2299,19 @@ NewInputDeviceRequest(InputOption *options, InputAttributes *attrs, /* FIXME: change this code below to use KdParseKbdOptions and * KdParsePointerOptions */ - for (option = options; option; option = option->next) { - if (strcmp(option->key, "device") == 0) { - if (pi && option->value) - pi->path = strdup(option->value); - else if (ki && option->value) - ki->path = strdup(option->value); + nt_list_for_each_entry(option, options, list.next) { + const char *key = input_option_get_key(option); + const char *value = input_option_get_value(option); + + if (strcmp(key, "device") == 0) { + if (pi && value) + pi->path = strdup(value); + else if (ki && value) + ki->path = strdup(value); } - else if (strcmp(option->key, "driver") == 0) { + else if (strcmp(key, "driver") == 0) { if (pi) { - pi->driver = KdFindPointerDriver(option->value); + pi->driver = KdFindPointerDriver(value); if (!pi->driver) { ErrorF("couldn't find driver!\n"); KdFreePointer(pi); @@ -2301,7 +2320,7 @@ NewInputDeviceRequest(InputOption *options, InputAttributes *attrs, pi->options = options; } else if (ki) { - ki->driver = KdFindKeyboardDriver(option->value); + ki->driver = KdFindKeyboardDriver(value); if (!ki->driver) { ErrorF("couldn't find driver!\n"); KdFreeKeyboard(ki); diff --git a/xorg-server/hw/vfb/InitOutput.c b/xorg-server/hw/vfb/InitOutput.c index 0e701e518..121854781 100644 --- a/xorg-server/hw/vfb/InitOutput.c +++ b/xorg-server/hw/vfb/InitOutput.c @@ -863,6 +863,8 @@ vfbScreenInit(int index, ScreenPtr pScreen, int argc, char **argv) (1 << DirectColor)), 10, TrueColor, 0x3ff00000, 0x000ffc00, 0x000003ff); break; + default: + return FALSE; } miSetPixmapDepths (); diff --git a/xorg-server/hw/xfree86/common/xf86Config.c b/xorg-server/hw/xfree86/common/xf86Config.c index 5c46152b2..cb4be4210 100644 --- a/xorg-server/hw/xfree86/common/xf86Config.c +++ b/xorg-server/hw/xfree86/common/xf86Config.c @@ -1194,8 +1194,12 @@ checkCoreInputDevices(serverLayoutPtr servlayoutp, Bool implicitLayout) if (Pointer) foundPointer = configInput(Pointer, confInput, from); if (foundPointer) { - Pointer->options = xf86addNewOption(Pointer->options, - xnfstrdup("CorePointer"), "on"); + Pointer->options = xf86AddNewOption(Pointer->options, + "CorePointer", "on"); + Pointer->options = xf86AddNewOption(Pointer->options, + "driver", confInput->inp_driver); + Pointer->options = xf86AddNewOption(Pointer->options, + "identifier", confInput->inp_identifier); servlayoutp->inputs = addDevice(servlayoutp->inputs, Pointer); } } @@ -1284,8 +1288,12 @@ checkCoreInputDevices(serverLayoutPtr servlayoutp, Bool implicitLayout) if (Keyboard) foundKeyboard = configInput(Keyboard, confInput, from); if (foundKeyboard) { - Keyboard->options = xf86addNewOption(Keyboard->options, - xnfstrdup("CoreKeyboard"), "on"); + Keyboard->options = xf86AddNewOption(Keyboard->options, + "CoreKeyboard", "on"); + Keyboard->options = xf86AddNewOption(Keyboard->options, + "driver", confInput->inp_driver); + Keyboard->options = xf86AddNewOption(Keyboard->options, + "identifier", confInput->inp_identifier); servlayoutp->inputs = addDevice(servlayoutp->inputs, Keyboard); } } diff --git a/xorg-server/hw/xfree86/common/xf86Events.c b/xorg-server/hw/xfree86/common/xf86Events.c index c4a4db9be..41ffabde3 100644 --- a/xorg-server/hw/xfree86/common/xf86Events.c +++ b/xorg-server/hw/xfree86/common/xf86Events.c @@ -601,16 +601,15 @@ xf86AddGeneralHandler(int fd, InputHandlerProc proc, pointer data) InputHandlerProc xf86SetConsoleHandler(InputHandlerProc proc, pointer data) { - static InputHandlerProc handler = NULL; - InputHandlerProc old_handler = handler; + static IHPtr handler = NULL; + IHPtr old_handler = handler; if (old_handler) xf86RemoveGeneralHandler(old_handler); - xf86AddGeneralHandler(xf86Info.consoleFd, proc, data); - handler = proc; + handler = xf86AddGeneralHandler(xf86Info.consoleFd, proc, data); - return old_handler; + return (old_handler) ? old_handler->ihproc : NULL; } static void diff --git a/xorg-server/hw/xfree86/common/xf86Helper.c b/xorg-server/hw/xfree86/common/xf86Helper.c index cf577522a..d99522cf6 100644 --- a/xorg-server/hw/xfree86/common/xf86Helper.c +++ b/xorg-server/hw/xfree86/common/xf86Helper.c @@ -1553,13 +1553,7 @@ xf86LoadOneModule(char *name, pointer opt) void xf86UnloadSubModule(pointer mod) { - /* - * This is disabled for now. The loader isn't smart enough yet to undo - * relocations. - */ -#if 0 UnloadSubModule(mod); -#endif } Bool diff --git a/xorg-server/hw/xfree86/common/xf86Init.c b/xorg-server/hw/xfree86/common/xf86Init.c index 74e0bc220..a0fdf29ad 100644 --- a/xorg-server/hw/xfree86/common/xf86Init.c +++ b/xorg-server/hw/xfree86/common/xf86Init.c @@ -811,21 +811,6 @@ InitOutput(ScreenInfo *pScreenInfo, int argc, char **argv) NULL); } -static InputInfoPtr -duplicateDevice(InputInfoPtr pInfo) -{ - InputInfoPtr dup = calloc(1, sizeof(InputInfoRec)); - if (dup) { - dup->name = strdup(pInfo->name); - dup->driver = strdup(pInfo->driver); - dup->options = xf86OptionListDuplicate(pInfo->options); - /* type_name is a const string */ - dup->type_name = pInfo->type_name; - dup->fd = -1; - } - return dup; -} - /** * Initialize all supported input devices present and referenced in the * xorg.conf. @@ -842,20 +827,8 @@ InitInput(int argc, char **argv) /* Initialize all configured input devices */ for (pInfo = xf86ConfigLayout.inputs; pInfo && *pInfo; pInfo++) { - InputInfoPtr dup; - /* Replace obsolete keyboard driver with kbd */ - if (!xf86NameCmp((*pInfo)->driver, "keyboard")) { - strcpy((*pInfo)->driver, "kbd"); - } - - /* Data passed into xf86NewInputDevice will be freed on shutdown. - * Duplicate from xf86ConfigLayout.inputs, otherwise we don't have any - * xorg.conf input devices in the second generation - */ - dup = duplicateDevice(*pInfo); - /* If one fails, the others will too */ - if (xf86NewInputDevice(dup, &dev, TRUE) == BadAlloc) + if (NewInputDeviceRequest((*pInfo)->options, NULL, &dev) == BadAlloc) break; } diff --git a/xorg-server/hw/xfree86/common/xf86Option.c b/xorg-server/hw/xfree86/common/xf86Option.c index 73b6573f1..9c528782f 100644 --- a/xorg-server/hw/xfree86/common/xf86Option.c +++ b/xorg-server/hw/xfree86/common/xf86Option.c @@ -44,6 +44,7 @@ #include "xf86Xinput.h" #include "xf86Optrec.h" #include "xf86Parser.h" +#include "optionstr.h" static Bool ParseOptionValue(int scrnIndex, XF86OptionPtr options, OptionInfoPtr p, Bool markUsed); @@ -298,7 +299,7 @@ xf86CheckPercentOption(XF86OptionPtr optlist, const char *name, double deflt) return LookupPercentOption(optlist, name, deflt, FALSE); } /* - * addNewOption() has the required property of replacing the option value + * xf86AddNewOption() has the required property of replacing the option value * if the option is already present. */ XF86OptionPtr diff --git a/xorg-server/hw/xfree86/common/xf86Optionstr.h b/xorg-server/hw/xfree86/common/xf86Optionstr.h index 8cc82d34c..fc9385617 100644 --- a/xorg-server/hw/xfree86/common/xf86Optionstr.h +++ b/xorg-server/hw/xfree86/common/xf86Optionstr.h @@ -24,16 +24,7 @@ #ifndef XF86OPTIONSTR_H #define XF86OPTIONSTR_H - -/* - * all records that need to be linked lists should contain a GenericList as - * their first field. - */ -typedef struct generic_list_rec -{ - void *next; -} -GenericListRec, *GenericListPtr, *glp; +#include "list.h" /* * All options are stored using this data type. @@ -48,6 +39,6 @@ typedef struct _XF86OptionRec } XF86OptionRec; -typedef struct _XF86OptionRec *XF86OptionPtr; +typedef struct _InputOption *XF86OptionPtr; #endif diff --git a/xorg-server/hw/xfree86/common/xf86Xinput.c b/xorg-server/hw/xfree86/common/xf86Xinput.c index ea1f92761..425b35957 100644 --- a/xorg-server/hw/xfree86/common/xf86Xinput.c +++ b/xorg-server/hw/xfree86/common/xf86Xinput.c @@ -68,6 +68,7 @@ #include "exglobals.h" #include "eventstr.h" #include "inpututils.h" +#include "optionstr.h" #include <string.h> /* InputClassMatches */ #ifdef HAVE_FNMATCH_H @@ -908,7 +909,7 @@ NewInputDeviceRequest (InputOption *options, InputAttributes *attrs, if (!pInfo) return BadAlloc; - nt_list_for_each_entry(option, options, next) { + nt_list_for_each_entry(option, options, list.next) { if (strcasecmp(input_option_get_key(option), "driver") == 0) { if (pInfo->driver) { rval = BadRequest; @@ -946,7 +947,7 @@ NewInputDeviceRequest (InputOption *options, InputAttributes *attrs, } } - nt_list_for_each_entry(option, options, next) { + nt_list_for_each_entry(option, options, list.next) { /* Copy option key/value strings from the provided list */ pInfo->options = xf86AddNewOption(pInfo->options, input_option_get_key(option), diff --git a/xorg-server/hw/xfree86/doc/ddxDesign.xml b/xorg-server/hw/xfree86/doc/ddxDesign.xml index a4baad557..0d5e952a2 100644 --- a/xorg-server/hw/xfree86/doc/ddxDesign.xml +++ b/xorg-server/hw/xfree86/doc/ddxDesign.xml @@ -189,7 +189,7 @@ following changes: <varlistentry><term><emphasis>Keyboard</emphasis></term> <listitem><literallayout> &k.identifier; "Implicit Core Keyboard" - &k.driver; "keyboard" + &k.driver; "kbd" </literallayout></listitem></varlistentry> <varlistentry><term><emphasis>Pointer</emphasis></term> <listitem><literallayout> @@ -206,7 +206,7 @@ following changes: is no &k.serverlayout; section, if the <option>-screen</option> command line options is used, or if the &k.serverlayout; section doesn't reference any &k.inputdevice; sections. In this case, the first - sections with drivers "keyboard" and "mouse" are used as the core + sections with drivers "kbd" and "mouse" are used as the core keyboard and pointer respectively. </para> </sect2> diff --git a/xorg-server/hw/xfree86/loader/loadmod.c b/xorg-server/hw/xfree86/loader/loadmod.c index 9f820993a..a21f43d63 100644 --- a/xorg-server/hw/xfree86/loader/loadmod.c +++ b/xorg-server/hw/xfree86/loader/loadmod.c @@ -94,6 +94,8 @@ const ModuleVersions LoaderVersionInfo = { ABI_FONT_VERSION }; +static int ModuleDuplicated[] = {}; + static void FreeStringList(char **paths) { @@ -785,7 +787,6 @@ ModuleDescPtr DuplicateModule(ModuleDescPtr mod, ModuleDescPtr parent) { ModuleDescPtr ret; - int errmaj, errmin; if (!mod) return NULL; @@ -794,14 +795,11 @@ DuplicateModule(ModuleDescPtr mod, ModuleDescPtr parent) if (ret == NULL) return NULL; - if (!(ret->handle = LoaderOpen(mod->path, &errmaj, &errmin))) { - free(ret); - return NULL; - } + ret->handle = mod->handle; ret->SetupProc = mod->SetupProc; ret->TearDownProc = mod->TearDownProc; - ret->TearDownData = NULL; + ret->TearDownData = ModuleDuplicated; ret->child = DuplicateModule(mod->child, ret); ret->sib = DuplicateModule(mod->sib, parent); ret->parent = parent; @@ -1072,11 +1070,16 @@ UnloadModuleOrDriver(ModuleDescPtr mod) if (mod == NULL || mod->name == NULL) return; - xf86MsgVerb(X_INFO, 3, "UnloadModule: \"%s\"\n", mod->name); + if (mod->parent) + xf86MsgVerb(X_INFO, 3, "UnloadSubModule: \"%s\"\n", mod->name); + else + xf86MsgVerb(X_INFO, 3, "UnloadModule: \"%s\"\n", mod->name); - if ((mod->TearDownProc) && (mod->TearDownData)) - mod->TearDownProc(mod->TearDownData); - LoaderUnload(mod->name, mod->handle); + if (mod->TearDownData != ModuleDuplicated) { + if ((mod->TearDownProc) && (mod->TearDownData)) + mod->TearDownProc(mod->TearDownData); + LoaderUnload(mod->name, mod->handle); + } if (mod->child) UnloadModuleOrDriver(mod->child); @@ -1092,23 +1095,8 @@ UnloadSubModule(pointer _mod) { ModuleDescPtr mod = (ModuleDescPtr)_mod; - if (mod == NULL || mod->name == NULL) - return; - - xf86MsgVerb(X_INFO, 3, "UnloadSubModule: \"%s\"\n", mod->name); - - if ((mod->TearDownProc) && (mod->TearDownData)) - mod->TearDownProc(mod->TearDownData); - LoaderUnload(mod->name, mod->handle); - RemoveChild(mod); - - if (mod->child) - UnloadModuleOrDriver(mod->child); - - free(mod->path); - free(mod->name); - free(mod); + UnloadModuleOrDriver(mod); } static void @@ -1135,6 +1123,7 @@ RemoveChild(ModuleDescPtr child) } if (mdp == child) prevsib->sib = child->sib; + child->sib = NULL; return; } diff --git a/xorg-server/hw/xfree86/man/xorg.conf.man b/xorg-server/hw/xfree86/man/xorg.conf.man index 7f98851b6..996798f1c 100644 --- a/xorg-server/hw/xfree86/man/xorg.conf.man +++ b/xorg-server/hw/xfree86/man/xorg.conf.man @@ -379,7 +379,9 @@ is a number used to order the fontfile FPEs. Examples: .I misc:unscaled:pri=10 \-> /usr/share/X11/fonts/misc .fi .PP -.RE .RE .RE +.RE +.RE +.RE .PP .RS 7 Font server identifiers: diff --git a/xorg-server/hw/xfree86/modes/xf86Crtc.c b/xorg-server/hw/xfree86/modes/xf86Crtc.c index cbe0b5cf6..aac33d32f 100644 --- a/xorg-server/hw/xfree86/modes/xf86Crtc.c +++ b/xorg-server/hw/xfree86/modes/xf86Crtc.c @@ -1915,19 +1915,25 @@ xf86SetScrnInfoModes (ScrnInfoPtr scrn) break; } - if (scrn->modes != NULL) { - /* For some reason, scrn->modes is circular, unlike the other mode - * lists. How great is that? - */ - for (last = scrn->modes; last && last->next; last = last->next) - ; - last->next = scrn->modes; - scrn->modes->prev = last; - if (mode) { - while (scrn->modes != mode) - scrn->modes = scrn->modes->next; - } + if (!scrn->modes) { + scrn->modes = xf86ModesAdd(scrn->modes, + xf86CVTMode(scrn->display->virtualX, + scrn->display->virtualY, + 60, 0, 0)); + } + + /* For some reason, scrn->modes is circular, unlike the other mode + * lists. How great is that? + */ + for (last = scrn->modes; last && last->next; last = last->next) + ; + last->next = scrn->modes; + scrn->modes->prev = last; + if (mode) { + while (scrn->modes != mode) + scrn->modes = scrn->modes->next; } + scrn->currentMode = scrn->modes; #ifdef XFreeXDGA if (scrn->pScreen) @@ -2060,13 +2066,28 @@ xf86TargetPreferred(ScrnInfoPtr scrn, xf86CrtcConfigPtr config, if (o == p) continue; - for (mode = output->probed_modes; mode; mode = mode->next) { - Rotation r = output->initial_rotation; - if (xf86ModeWidth(mode, r) == pref_width && - xf86ModeHeight(mode, r) == pref_height) { + /* + * First see if the preferred mode matches on the next + * output as well. This catches the common case of identical + * monitors and makes sure they all have the same timings + * and refresh. If that fails, we fall back to trying to + * match just width & height. + */ + mode = xf86OutputHasPreferredMode(output, pref_width, + pref_height); + if (mode && xf86ModesEqual(mode, preferred[p])) { preferred[o] = mode; match = TRUE; - } + } else { + for (mode = output->probed_modes; mode; + mode = mode->next) { + Rotation r = output->initial_rotation; + if (xf86ModeWidth(mode, r) == pref_width && + xf86ModeHeight(mode, r) == pref_height) { + preferred[o] = mode; + match = TRUE; + } + } } all_match &= match; @@ -2514,16 +2535,7 @@ xf86InitialConfiguration (ScrnInfoPtr scrn, Bool canGrow) width, height); } - if (have_outputs) { - /* Mirror output modes to scrn mode list */ - xf86SetScrnInfoModes (scrn); - } else { - /* Clear any existing modes from scrn->modes */ - while (scrn->modes != NULL) - xf86DeleteMode(&scrn->modes, scrn->modes); - scrn->modes = xf86ModesAdd(scrn->modes, - xf86CVTMode(width, height, 60, 0, 0)); - } + xf86SetScrnInfoModes (scrn); success = TRUE; bailout: diff --git a/xorg-server/hw/xfree86/os-support/linux/lnx_init.c b/xorg-server/hw/xfree86/os-support/linux/lnx_init.c index 9c9174034..f18271f38 100644 --- a/xorg-server/hw/xfree86/os-support/linux/lnx_init.c +++ b/xorg-server/hw/xfree86/os-support/linux/lnx_init.c @@ -45,15 +45,12 @@ static char vtname[11]; static struct termios tty_attr; /* tty state to restore */ static int tty_mode; /* kbd mode to restore */ -static void *console_handler; - static void drain_console(int fd, void *closure) { errno = 0; if (tcflush(fd, TCIOFLUSH) == -1 && errno == EIO) { - xf86RemoveGeneralHandler(console_handler); - console_handler = NULL; + xf86SetConsoleHandler(NULL, NULL); } } @@ -257,10 +254,11 @@ xf86CloseConsole(void) return; } - if (console_handler) { - xf86RemoveGeneralHandler(console_handler); - console_handler = NULL; - }; + /* + * unregister the drain_console handler + * - what to do if someone else changed it in the meantime? + */ + xf86SetConsoleHandler(NULL, NULL); /* Back to text mode ... */ SYSCALL(ret = ioctl(xf86Info.consoleFd, KDSETMODE, KD_TEXT)); diff --git a/xorg-server/hw/xfree86/parser/Flags.c b/xorg-server/hw/xfree86/parser/Flags.c index 17e079a8c..f0a61707b 100644 --- a/xorg-server/hw/xfree86/parser/Flags.c +++ b/xorg-server/hw/xfree86/parser/Flags.c @@ -1,504 +1,505 @@ -/*
- * Copyright (c) 1997 Metro Link Incorporated
- *
- * 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 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 X CONSORTIUM 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.
- *
- * Except as contained in this notice, the name of the Metro Link shall not be
- * used in advertising or otherwise to promote the sale, use or other dealings
- * in this Software without prior written authorization from Metro Link.
- *
- */
-/*
- * Copyright (c) 1997-2003 by The XFree86 Project, Inc.
- *
- * 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 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
- *
- * Except as contained in this notice, the name of the copyright holder(s)
- * and author(s) shall not be used in advertising or otherwise to promote
- * the sale, use or other dealings in this Software without prior written
- * authorization from the copyright holder(s) and author(s).
- */
-
-
-/* View/edit this file with tab stops set to 4 */
-
-#ifdef HAVE_XORG_CONFIG_H
-#include <xorg-config.h>
-#endif
-
-#include "xf86Parser.h"
-#include "xf86tokens.h"
-#include "Configint.h"
-#include <X11/Xfuncproto.h>
-#include "Xprintf.h"
-
-extern LexRec val;
-
-static xf86ConfigSymTabRec ServerFlagsTab[] =
-{
- {ENDSECTION, "endsection"},
- {NOTRAPSIGNALS, "notrapsignals"},
- {DONTZAP, "dontzap"},
- {DONTZOOM, "dontzoom"},
- {DISABLEVIDMODE, "disablevidmodeextension"},
- {ALLOWNONLOCAL, "allownonlocalxvidtune"},
- {DISABLEMODINDEV, "disablemodindev"},
- {MODINDEVALLOWNONLOCAL, "allownonlocalmodindev"},
- {ALLOWMOUSEOPENFAIL, "allowmouseopenfail"},
- {OPTION, "option"},
- {BLANKTIME, "blanktime"},
- {STANDBYTIME, "standbytime"},
- {SUSPENDTIME, "suspendtime"},
- {OFFTIME, "offtime"},
- {DEFAULTLAYOUT, "defaultserverlayout"},
- {-1, ""},
-};
-
-#define CLEANUP xf86freeFlags
-
-XF86ConfFlagsPtr
-xf86parseFlagsSection (void)
-{
- int token;
- parsePrologue (XF86ConfFlagsPtr, XF86ConfFlagsRec)
-
- while ((token = xf86getToken (ServerFlagsTab)) != ENDSECTION)
- {
- int hasvalue = FALSE;
- int strvalue = FALSE;
- int tokentype;
- switch (token)
- {
- case COMMENT:
- ptr->flg_comment = xf86addComment(ptr->flg_comment, val.str);
- break;
- /*
- * these old keywords are turned into standard generic options.
- * we fall through here on purpose
- */
- case DEFAULTLAYOUT:
- strvalue = TRUE;
- case BLANKTIME:
- case STANDBYTIME:
- case SUSPENDTIME:
- case OFFTIME:
- hasvalue = TRUE;
- case NOTRAPSIGNALS:
- case DONTZAP:
- case DONTZOOM:
- case DISABLEVIDMODE:
- case ALLOWNONLOCAL:
- case DISABLEMODINDEV:
- case MODINDEVALLOWNONLOCAL:
- case ALLOWMOUSEOPENFAIL:
- {
- int i = 0;
- while (ServerFlagsTab[i].token != -1)
- {
- char *tmp;
-
- if (ServerFlagsTab[i].token == token)
- {
- char *valstr = NULL;
- tmp = strdup (ServerFlagsTab[i].name);
- if (hasvalue)
- {
- tokentype = xf86getSubToken(&(ptr->flg_comment));
- if (strvalue) {
- if (tokentype != STRING)
- Error (QUOTE_MSG, tmp);
- valstr = val.str;
- } else {
- if (tokentype != NUMBER)
- Error (NUMBER_MSG, tmp);
- if (asprintf(&valstr, "%d", val.num) == -1)
- valstr = NULL;
- }
- }
- ptr->flg_option_lst = xf86addNewOption
- (ptr->flg_option_lst, tmp, valstr);
- }
- i++;
- }
- }
- break;
- case OPTION:
- ptr->flg_option_lst = xf86parseOption(ptr->flg_option_lst);
- break;
-
- case EOF_TOKEN:
- Error (UNEXPECTED_EOF_MSG, NULL);
- break;
- default:
- Error (INVALID_KEYWORD_MSG, xf86tokenString ());
- break;
- }
- }
-
-#ifdef DEBUG
- printf ("Flags section parsed\n");
-#endif
-
- return ptr;
-}
-
-#undef CLEANUP
-
-void
-xf86printServerFlagsSection (FILE * f, XF86ConfFlagsPtr flags)
-{
- XF86OptionPtr p;
-
- if ((!flags) || (!flags->flg_option_lst))
- return;
- p = flags->flg_option_lst;
- fprintf (f, "Section \"ServerFlags\"\n");
- if (flags->flg_comment)
- fprintf (f, "%s", flags->flg_comment);
- xf86printOptionList(f, p, 1);
- fprintf (f, "EndSection\n\n");
-}
-
-static XF86OptionPtr
-addNewOption2 (XF86OptionPtr head, char *name, char *val, int used)
-{
- XF86OptionPtr new, old = NULL;
-
- /* Don't allow duplicates, free old strings */
- if (head != NULL && (old = xf86findOption(head, name)) != NULL) {
- new = old;
- free(new->opt_name);
- free(new->opt_val);
- }
- else
- new = calloc (1, sizeof (XF86OptionRec));
- new->opt_name = name;
- new->opt_val = val;
- new->opt_used = used;
-
- if (old)
- return head;
- return ((XF86OptionPtr) xf86addListItem ((glp) head, (glp) new));
-}
-
-XF86OptionPtr
-xf86addNewOption (XF86OptionPtr head, char *name, char *val)
-{
- return addNewOption2(head, name, val, 0);
-}
-
-void
-xf86freeFlags (XF86ConfFlagsPtr flags)
-{
- if (flags == NULL)
- return;
- xf86optionListFree (flags->flg_option_lst);
- TestFree(flags->flg_comment);
- free (flags);
-}
-
-XF86OptionPtr
-xf86optionListDup (XF86OptionPtr opt)
-{
- XF86OptionPtr newopt = NULL;
- char *val;
-
- while (opt)
- {
- val = opt->opt_val ? strdup(opt->opt_val) : NULL;
- newopt = xf86addNewOption(newopt, strdup(opt->opt_name), val);
- newopt->opt_used = opt->opt_used;
- if (opt->opt_comment)
- newopt->opt_comment = strdup(opt->opt_comment);
- opt = opt->list.next;
- }
- return newopt;
-}
-
-void
-xf86optionListFree (XF86OptionPtr opt)
-{
- XF86OptionPtr prev;
-
- while (opt)
- {
- TestFree (opt->opt_name);
- TestFree (opt->opt_val);
- TestFree (opt->opt_comment);
- prev = opt;
- opt = opt->list.next;
- free (prev);
- }
-}
-
-char *
-xf86optionName(XF86OptionPtr opt)
-{
- if (opt)
- return opt->opt_name;
- return 0;
-}
-
-char *
-xf86optionValue(XF86OptionPtr opt)
-{
- if (opt)
- return opt->opt_val;
- return 0;
-}
-
-XF86OptionPtr
-xf86newOption(char *name, char *value)
-{
- XF86OptionPtr opt;
-
- opt = calloc(1, sizeof (XF86OptionRec));
- if (!opt)
- return NULL;
-
- opt->opt_used = 0;
- opt->list.next = 0;
- opt->opt_name = name;
- opt->opt_val = value;
-
- return opt;
-}
-
-XF86OptionPtr
-xf86nextOption(XF86OptionPtr list)
-{
- if (!list)
- return NULL;
- return list->list.next;
-}
-
-/*
- * this function searches the given option list for the named option and
- * returns a pointer to the option rec if found. If not found, it returns
- * NULL
- */
-
-XF86OptionPtr
-xf86findOption (XF86OptionPtr list, const char *name)
-{
- while (list)
- {
- if (xf86nameCompare (list->opt_name, name) == 0)
- return list;
- list = list->list.next;
- }
- return NULL;
-}
-
-/*
- * this function searches the given option list for the named option. If
- * found and the option has a parameter, a pointer to the parameter is
- * returned. If the option does not have a parameter an empty string is
- * returned. If the option is not found, a NULL is returned.
- */
-
-char *
-xf86findOptionValue (XF86OptionPtr list, const char *name)
-{
- XF86OptionPtr p = xf86findOption (list, name);
-
- if (p)
- {
- if (p->opt_val)
- return p->opt_val;
- else
- return "";
- }
- return NULL;
-}
-
-XF86OptionPtr
-xf86optionListCreate( const char **options, int count, int used )
-{
- XF86OptionPtr p = NULL;
- char *t1, *t2;
- int i;
-
- if (count == -1)
- {
- for (count = 0; options[count]; count++)
- ;
- }
- if( (count % 2) != 0 )
- {
- fprintf( stderr, "xf86optionListCreate: count must be an even number.\n" );
- return NULL;
- }
- for (i = 0; i < count; i += 2)
- {
- t1 = strdup(options[i]);
- t2 = strdup(options[i + 1]);
- p = addNewOption2 (p, t1, t2, used);
- }
-
- return p;
-}
-
-/* the 2 given lists are merged. If an option with the same name is present in
- * both, the option from the user list - specified in the second argument -
- * is used. The end result is a single valid list of options. Duplicates
- * are freed, and the original lists are no longer guaranteed to be complete.
- */
-XF86OptionPtr
-xf86optionListMerge (XF86OptionPtr head, XF86OptionPtr tail)
-{
- XF86OptionPtr a, b, ap = NULL, bp = NULL;
-
- a = tail;
- b = head;
- while (tail && b) {
- if (xf86nameCompare (a->opt_name, b->opt_name) == 0) {
- if (b == head)
- head = a;
- else
- bp->list.next = a;
- if (a == tail)
- tail = a->list.next;
- else
- ap->list.next = a->list.next;
- a->list.next = b->list.next;
- b->list.next = NULL;
- xf86optionListFree (b);
- b = a->list.next;
- bp = a;
- a = tail;
- ap = NULL;
- } else {
- ap = a;
- if (!(a = a->list.next)) {
- a = tail;
- bp = b;
- b = b->list.next;
- ap = NULL;
- }
- }
- }
-
- if (head) {
- for (a = head; a->list.next; a = a->list.next)
- ;
- a->list.next = tail;
- } else
- head = tail;
-
- return head;
-}
-
-char *
-xf86uLongToString(unsigned long i)
-{
- char *s;
-
- if (asprintf(&s, "%lu", i) == -1)
- return NULL;
- return s;
-}
-
-XF86OptionPtr
-xf86parseOption(XF86OptionPtr head)
-{
- XF86OptionPtr option, cnew, old;
- char *name, *comment = NULL;
- int token;
-
- if ((token = xf86getSubToken(&comment)) != STRING) {
- xf86parseError(BAD_OPTION_MSG, NULL);
- free(comment);
- return head;
- }
-
- name = val.str;
- if ((token = xf86getSubToken(&comment)) == STRING) {
- option = xf86newOption(name, val.str);
- option->opt_comment = comment;
- if ((token = xf86getToken(NULL)) == COMMENT)
- option->opt_comment = xf86addComment(option->opt_comment, val.str);
- else
- xf86unGetToken(token);
- }
- else {
- option = xf86newOption(name, NULL);
- option->opt_comment = comment;
- if (token == COMMENT)
- option->opt_comment = xf86addComment(option->opt_comment, val.str);
- else
- xf86unGetToken(token);
- }
-
- old = NULL;
-
- /* Don't allow duplicates */
- if (head != NULL && (old = xf86findOption(head, name)) != NULL) {
- cnew = old;
- free(option->opt_name);
- TestFree(option->opt_val);
- TestFree(option->opt_comment);
- free(option);
- }
- else
- cnew = option;
-
- if (old == NULL)
- return ((XF86OptionPtr)xf86addListItem((glp)head, (glp)cnew));
-
- return head;
-}
-
-void
-xf86printOptionList(FILE *fp, XF86OptionPtr list, int tabs)
-{
- int i;
-
- if (!list)
- return;
- while (list) {
- for (i = 0; i < tabs; i++)
- fputc('\t', fp);
- if (list->opt_val)
- fprintf(fp, "Option \"%s\" \"%s\"", list->opt_name, list->opt_val);
- else
- fprintf(fp, "Option \"%s\"", list->opt_name);
- if (list->opt_comment)
- fprintf(fp, "%s", list->opt_comment);
- else
- fputc('\n', fp);
- list = list->list.next;
- }
-}
+/* + * Copyright (c) 1997 Metro Link Incorporated + * + * 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 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 X CONSORTIUM 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. + * + * Except as contained in this notice, the name of the Metro Link shall not be + * used in advertising or otherwise to promote the sale, use or other dealings + * in this Software without prior written authorization from Metro Link. + * + */ +/* + * Copyright (c) 1997-2003 by The XFree86 Project, Inc. + * + * 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 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + */ + + +/* View/edit this file with tab stops set to 4 */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include "xf86Parser.h" +#include "xf86tokens.h" +#include "Configint.h" +#include <X11/Xfuncproto.h> +#include "Xprintf.h" +#include "optionstr.h" + +extern LexRec val; + +static xf86ConfigSymTabRec ServerFlagsTab[] = +{ + {ENDSECTION, "endsection"}, + {NOTRAPSIGNALS, "notrapsignals"}, + {DONTZAP, "dontzap"}, + {DONTZOOM, "dontzoom"}, + {DISABLEVIDMODE, "disablevidmodeextension"}, + {ALLOWNONLOCAL, "allownonlocalxvidtune"}, + {DISABLEMODINDEV, "disablemodindev"}, + {MODINDEVALLOWNONLOCAL, "allownonlocalmodindev"}, + {ALLOWMOUSEOPENFAIL, "allowmouseopenfail"}, + {OPTION, "option"}, + {BLANKTIME, "blanktime"}, + {STANDBYTIME, "standbytime"}, + {SUSPENDTIME, "suspendtime"}, + {OFFTIME, "offtime"}, + {DEFAULTLAYOUT, "defaultserverlayout"}, + {-1, ""}, +}; + +#define CLEANUP xf86freeFlags + +XF86ConfFlagsPtr +xf86parseFlagsSection (void) +{ + int token; + parsePrologue (XF86ConfFlagsPtr, XF86ConfFlagsRec) + + while ((token = xf86getToken (ServerFlagsTab)) != ENDSECTION) + { + int hasvalue = FALSE; + int strvalue = FALSE; + int tokentype; + switch (token) + { + case COMMENT: + ptr->flg_comment = xf86addComment(ptr->flg_comment, val.str); + break; + /* + * these old keywords are turned into standard generic options. + * we fall through here on purpose + */ + case DEFAULTLAYOUT: + strvalue = TRUE; + case BLANKTIME: + case STANDBYTIME: + case SUSPENDTIME: + case OFFTIME: + hasvalue = TRUE; + case NOTRAPSIGNALS: + case DONTZAP: + case DONTZOOM: + case DISABLEVIDMODE: + case ALLOWNONLOCAL: + case DISABLEMODINDEV: + case MODINDEVALLOWNONLOCAL: + case ALLOWMOUSEOPENFAIL: + { + int i = 0; + while (ServerFlagsTab[i].token != -1) + { + char *tmp; + + if (ServerFlagsTab[i].token == token) + { + char *valstr = NULL; + tmp = strdup (ServerFlagsTab[i].name); + if (hasvalue) + { + tokentype = xf86getSubToken(&(ptr->flg_comment)); + if (strvalue) { + if (tokentype != STRING) + Error (QUOTE_MSG, tmp); + valstr = val.str; + } else { + if (tokentype != NUMBER) + Error (NUMBER_MSG, tmp); + if (asprintf(&valstr, "%d", val.num) == -1) + valstr = NULL; + } + } + ptr->flg_option_lst = xf86addNewOption + (ptr->flg_option_lst, tmp, valstr); + } + i++; + } + } + break; + case OPTION: + ptr->flg_option_lst = xf86parseOption(ptr->flg_option_lst); + break; + + case EOF_TOKEN: + Error (UNEXPECTED_EOF_MSG, NULL); + break; + default: + Error (INVALID_KEYWORD_MSG, xf86tokenString ()); + break; + } + } + +#ifdef DEBUG + printf ("Flags section parsed\n"); +#endif + + return ptr; +} + +#undef CLEANUP + +void +xf86printServerFlagsSection (FILE * f, XF86ConfFlagsPtr flags) +{ + XF86OptionPtr p; + + if ((!flags) || (!flags->flg_option_lst)) + return; + p = flags->flg_option_lst; + fprintf (f, "Section \"ServerFlags\"\n"); + if (flags->flg_comment) + fprintf (f, "%s", flags->flg_comment); + xf86printOptionList(f, p, 1); + fprintf (f, "EndSection\n\n"); +} + +static XF86OptionPtr +addNewOption2 (XF86OptionPtr head, char *name, char *val, int used) +{ + XF86OptionPtr new, old = NULL; + + /* Don't allow duplicates, free old strings */ + if (head != NULL && (old = xf86findOption(head, name)) != NULL) { + new = old; + free(new->opt_name); + free(new->opt_val); + } + else + new = calloc (1, sizeof (*new)); + new->opt_name = name; + new->opt_val = val; + new->opt_used = used; + + if (old) + return head; + return ((XF86OptionPtr) xf86addListItem ((glp) head, (glp) new)); +} + +XF86OptionPtr +xf86addNewOption (XF86OptionPtr head, char *name, char *val) +{ + return addNewOption2(head, name, val, 0); +} + +void +xf86freeFlags (XF86ConfFlagsPtr flags) +{ + if (flags == NULL) + return; + xf86optionListFree (flags->flg_option_lst); + TestFree(flags->flg_comment); + free (flags); +} + +XF86OptionPtr +xf86optionListDup (XF86OptionPtr opt) +{ + XF86OptionPtr newopt = NULL; + char *val; + + while (opt) + { + val = opt->opt_val ? strdup(opt->opt_val) : NULL; + newopt = xf86addNewOption(newopt, strdup(opt->opt_name), val); + newopt->opt_used = opt->opt_used; + if (opt->opt_comment) + newopt->opt_comment = strdup(opt->opt_comment); + opt = opt->list.next; + } + return newopt; +} + +void +xf86optionListFree (XF86OptionPtr opt) +{ + XF86OptionPtr prev; + + while (opt) + { + TestFree (opt->opt_name); + TestFree (opt->opt_val); + TestFree (opt->opt_comment); + prev = opt; + opt = opt->list.next; + free (prev); + } +} + +char * +xf86optionName(XF86OptionPtr opt) +{ + if (opt) + return opt->opt_name; + return 0; +} + +char * +xf86optionValue(XF86OptionPtr opt) +{ + if (opt) + return opt->opt_val; + return 0; +} + +XF86OptionPtr +xf86newOption(char *name, char *value) +{ + XF86OptionPtr opt; + + opt = calloc(1, sizeof (*opt)); + if (!opt) + return NULL; + + opt->opt_used = 0; + opt->list.next = 0; + opt->opt_name = name; + opt->opt_val = value; + + return opt; +} + +XF86OptionPtr +xf86nextOption(XF86OptionPtr list) +{ + if (!list) + return NULL; + return list->list.next; +} + +/* + * this function searches the given option list for the named option and + * returns a pointer to the option rec if found. If not found, it returns + * NULL + */ + +XF86OptionPtr +xf86findOption (XF86OptionPtr list, const char *name) +{ + while (list) + { + if (xf86nameCompare (list->opt_name, name) == 0) + return list; + list = list->list.next; + } + return NULL; +} + +/* + * this function searches the given option list for the named option. If + * found and the option has a parameter, a pointer to the parameter is + * returned. If the option does not have a parameter an empty string is + * returned. If the option is not found, a NULL is returned. + */ + +char * +xf86findOptionValue (XF86OptionPtr list, const char *name) +{ + XF86OptionPtr p = xf86findOption (list, name); + + if (p) + { + if (p->opt_val) + return p->opt_val; + else + return ""; + } + return NULL; +} + +XF86OptionPtr +xf86optionListCreate( const char **options, int count, int used ) +{ + XF86OptionPtr p = NULL; + char *t1, *t2; + int i; + + if (count == -1) + { + for (count = 0; options[count]; count++) + ; + } + if( (count % 2) != 0 ) + { + fprintf( stderr, "xf86optionListCreate: count must be an even number.\n" ); + return NULL; + } + for (i = 0; i < count; i += 2) + { + t1 = strdup(options[i]); + t2 = strdup(options[i + 1]); + p = addNewOption2 (p, t1, t2, used); + } + + return p; +} + +/* the 2 given lists are merged. If an option with the same name is present in + * both, the option from the user list - specified in the second argument - + * is used. The end result is a single valid list of options. Duplicates + * are freed, and the original lists are no longer guaranteed to be complete. + */ +XF86OptionPtr +xf86optionListMerge (XF86OptionPtr head, XF86OptionPtr tail) +{ + XF86OptionPtr a, b, ap = NULL, bp = NULL; + + a = tail; + b = head; + while (tail && b) { + if (xf86nameCompare (a->opt_name, b->opt_name) == 0) { + if (b == head) + head = a; + else + bp->list.next = a; + if (a == tail) + tail = a->list.next; + else + ap->list.next = a->list.next; + a->list.next = b->list.next; + b->list.next = NULL; + xf86optionListFree (b); + b = a->list.next; + bp = a; + a = tail; + ap = NULL; + } else { + ap = a; + if (!(a = a->list.next)) { + a = tail; + bp = b; + b = b->list.next; + ap = NULL; + } + } + } + + if (head) { + for (a = head; a->list.next; a = a->list.next) + ; + a->list.next = tail; + } else + head = tail; + + return head; +} + +char * +xf86uLongToString(unsigned long i) +{ + char *s; + + if (asprintf(&s, "%lu", i) == -1) + return NULL; + return s; +} + +XF86OptionPtr +xf86parseOption(XF86OptionPtr head) +{ + XF86OptionPtr option, cnew, old; + char *name, *comment = NULL; + int token; + + if ((token = xf86getSubToken(&comment)) != STRING) { + xf86parseError(BAD_OPTION_MSG, NULL); + free(comment); + return head; + } + + name = val.str; + if ((token = xf86getSubToken(&comment)) == STRING) { + option = xf86newOption(name, val.str); + option->opt_comment = comment; + if ((token = xf86getToken(NULL)) == COMMENT) + option->opt_comment = xf86addComment(option->opt_comment, val.str); + else + xf86unGetToken(token); + } + else { + option = xf86newOption(name, NULL); + option->opt_comment = comment; + if (token == COMMENT) + option->opt_comment = xf86addComment(option->opt_comment, val.str); + else + xf86unGetToken(token); + } + + old = NULL; + + /* Don't allow duplicates */ + if (head != NULL && (old = xf86findOption(head, name)) != NULL) { + cnew = old; + free(option->opt_name); + TestFree(option->opt_val); + TestFree(option->opt_comment); + free(option); + } + else + cnew = option; + + if (old == NULL) + return ((XF86OptionPtr)xf86addListItem((glp)head, (glp)cnew)); + + return head; +} + +void +xf86printOptionList(FILE *fp, XF86OptionPtr list, int tabs) +{ + int i; + + if (!list) + return; + while (list) { + for (i = 0; i < tabs; i++) + fputc('\t', fp); + if (list->opt_val) + fprintf(fp, "Option \"%s\" \"%s\"", list->opt_name, list->opt_val); + else + fprintf(fp, "Option \"%s\"", list->opt_name); + if (list->opt_comment) + fprintf(fp, "%s", list->opt_comment); + else + fputc('\n', fp); + list = list->list.next; + } +} diff --git a/xorg-server/hw/xfree86/parser/Layout.c b/xorg-server/hw/xfree86/parser/Layout.c index 60e83390f..4487b0df6 100644 --- a/xorg-server/hw/xfree86/parser/Layout.c +++ b/xorg-server/hw/xfree86/parser/Layout.c @@ -1,558 +1,558 @@ -/*
- *
- * Copyright (c) 1997 Metro Link Incorporated
- *
- * 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 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 X CONSORTIUM 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.
- *
- * Except as contained in this notice, the name of the Metro Link shall not be
- * used in advertising or otherwise to promote the sale, use or other dealings
- * in this Software without prior written authorization from Metro Link.
- *
- */
-/*
- * Copyright (c) 1997-2003 by The XFree86 Project, Inc.
- *
- * 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 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
- *
- * Except as contained in this notice, the name of the copyright holder(s)
- * and author(s) shall not be used in advertising or otherwise to promote
- * the sale, use or other dealings in this Software without prior written
- * authorization from the copyright holder(s) and author(s).
- */
-
-
-/* View/edit this file with tab stops set to 4 */
-
-#ifdef HAVE_XORG_CONFIG_H
-#include <xorg-config.h>
-#endif
-
-#include "xf86Parser.h"
-#include "xf86tokens.h"
-#include "Configint.h"
-#include <string.h>
-
-
-/* Needed for auto server layout */
-extern int xf86CheckBoolOption(void* optlist, const char *name, int deflt);
-
-extern LexRec val;
-
-static xf86ConfigSymTabRec LayoutTab[] =
-{
- {ENDSECTION, "endsection"},
- {SCREEN, "screen"},
- {IDENTIFIER, "identifier"},
- {INACTIVE, "inactive"},
- {INPUTDEVICE, "inputdevice"},
- {OPTION, "option"},
- {-1, ""},
-};
-
-static xf86ConfigSymTabRec AdjTab[] =
-{
- {RIGHTOF, "rightof"},
- {LEFTOF, "leftof"},
- {ABOVE, "above"},
- {BELOW, "below"},
- {RELATIVE, "relative"},
- {ABSOLUTE, "absolute"},
- {-1, ""},
-};
-
-#define CLEANUP xf86freeLayoutList
-
-XF86ConfLayoutPtr
-xf86parseLayoutSection (void)
-{
- int has_ident = FALSE;
- int token;
- parsePrologue (XF86ConfLayoutPtr, XF86ConfLayoutRec)
-
- while ((token = xf86getToken (LayoutTab)) != ENDSECTION)
- {
- switch (token)
- {
- case COMMENT:
- ptr->lay_comment = xf86addComment(ptr->lay_comment, val.str);
- break;
- case IDENTIFIER:
- if (xf86getSubToken (&(ptr->lay_comment)) != STRING)
- Error (QUOTE_MSG, "Identifier");
- if (has_ident == TRUE)
- Error (MULTIPLE_MSG, "Identifier");
- ptr->lay_identifier = val.str;
- has_ident = TRUE;
- break;
- case INACTIVE:
- {
- XF86ConfInactivePtr iptr;
-
- iptr = calloc (1, sizeof (XF86ConfInactiveRec));
- iptr->list.next = NULL;
- if (xf86getSubToken (&(ptr->lay_comment)) != STRING) {
- free (iptr);
- Error (INACTIVE_MSG, NULL);
- }
- iptr->inactive_device_str = val.str;
- ptr->lay_inactive_lst = (XF86ConfInactivePtr)
- xf86addListItem ((glp) ptr->lay_inactive_lst, (glp) iptr);
- }
- break;
- case SCREEN:
- {
- XF86ConfAdjacencyPtr aptr;
- int absKeyword = 0;
-
- aptr = calloc (1, sizeof (XF86ConfAdjacencyRec));
- aptr->list.next = NULL;
- aptr->adj_scrnum = -1;
- aptr->adj_where = CONF_ADJ_OBSOLETE;
- aptr->adj_x = 0;
- aptr->adj_y = 0;
- aptr->adj_refscreen = NULL;
- if ((token = xf86getSubToken (&(ptr->lay_comment))) == NUMBER)
- aptr->adj_scrnum = val.num;
- else
- xf86unGetToken (token);
- token = xf86getSubToken(&(ptr->lay_comment));
- if (token != STRING) {
- free(aptr);
- Error (SCREEN_MSG, NULL);
- }
- aptr->adj_screen_str = val.str;
-
- token = xf86getSubTokenWithTab(&(ptr->lay_comment), AdjTab);
- switch (token)
- {
- case RIGHTOF:
- aptr->adj_where = CONF_ADJ_RIGHTOF;
- break;
- case LEFTOF:
- aptr->adj_where = CONF_ADJ_LEFTOF;
- break;
- case ABOVE:
- aptr->adj_where = CONF_ADJ_ABOVE;
- break;
- case BELOW:
- aptr->adj_where = CONF_ADJ_BELOW;
- break;
- case RELATIVE:
- aptr->adj_where = CONF_ADJ_RELATIVE;
- break;
- case ABSOLUTE:
- aptr->adj_where = CONF_ADJ_ABSOLUTE;
- absKeyword = 1;
- break;
- case EOF_TOKEN:
- free(aptr);
- Error (UNEXPECTED_EOF_MSG, NULL);
- break;
- default:
- xf86unGetToken (token);
- token = xf86getSubToken(&(ptr->lay_comment));
- if (token == STRING)
- aptr->adj_where = CONF_ADJ_OBSOLETE;
- else
- aptr->adj_where = CONF_ADJ_ABSOLUTE;
- }
- switch (aptr->adj_where)
- {
- case CONF_ADJ_ABSOLUTE:
- if (absKeyword)
- token = xf86getSubToken(&(ptr->lay_comment));
- if (token == NUMBER)
- {
- aptr->adj_x = val.num;
- token = xf86getSubToken(&(ptr->lay_comment));
- if (token != NUMBER) {
- free(aptr);
- Error(INVALID_SCR_MSG, NULL);
- }
- aptr->adj_y = val.num;
- } else {
- if (absKeyword) {
- free(aptr);
- Error(INVALID_SCR_MSG, NULL);
- } else
- xf86unGetToken (token);
- }
- break;
- case CONF_ADJ_RIGHTOF:
- case CONF_ADJ_LEFTOF:
- case CONF_ADJ_ABOVE:
- case CONF_ADJ_BELOW:
- case CONF_ADJ_RELATIVE:
- token = xf86getSubToken(&(ptr->lay_comment));
- if (token != STRING) {
- free(aptr);
- Error(INVALID_SCR_MSG, NULL);
- }
- aptr->adj_refscreen = val.str;
- if (aptr->adj_where == CONF_ADJ_RELATIVE)
- {
- token = xf86getSubToken(&(ptr->lay_comment));
- if (token != NUMBER) {
- free(aptr);
- Error(INVALID_SCR_MSG, NULL);
- }
- aptr->adj_x = val.num;
- token = xf86getSubToken(&(ptr->lay_comment));
- if (token != NUMBER) {
- free(aptr);
- Error(INVALID_SCR_MSG, NULL);
- }
- aptr->adj_y = val.num;
- }
- break;
- case CONF_ADJ_OBSOLETE:
- /* top */
- aptr->adj_top_str = val.str;
-
- /* bottom */
- if (xf86getSubToken (&(ptr->lay_comment)) != STRING) {
- free(aptr);
- Error (SCREEN_MSG, NULL);
- }
- aptr->adj_bottom_str = val.str;
-
- /* left */
- if (xf86getSubToken (&(ptr->lay_comment)) != STRING) {
- free(aptr);
- Error (SCREEN_MSG, NULL);
- }
- aptr->adj_left_str = val.str;
-
- /* right */
- if (xf86getSubToken (&(ptr->lay_comment)) != STRING) {
- free(aptr);
- Error (SCREEN_MSG, NULL);
- }
- aptr->adj_right_str = val.str;
-
- }
- ptr->lay_adjacency_lst = (XF86ConfAdjacencyPtr)
- xf86addListItem ((glp) ptr->lay_adjacency_lst, (glp) aptr);
- }
- break;
- case INPUTDEVICE:
- {
- XF86ConfInputrefPtr iptr;
-
- iptr = calloc (1, sizeof (XF86ConfInputrefRec));
- iptr->list.next = NULL;
- iptr->iref_option_lst = NULL;
- if (xf86getSubToken (&(ptr->lay_comment)) != STRING) {
- free(iptr);
- Error (INPUTDEV_MSG, NULL);
- }
- iptr->iref_inputdev_str = val.str;
- while ((token = xf86getSubToken (&(ptr->lay_comment))) == STRING)
- {
- iptr->iref_option_lst =
- xf86addNewOption (iptr->iref_option_lst, val.str, NULL);
- }
- xf86unGetToken (token);
- ptr->lay_input_lst = (XF86ConfInputrefPtr)
- xf86addListItem ((glp) ptr->lay_input_lst, (glp) iptr);
- }
- break;
- case OPTION:
- ptr->lay_option_lst = xf86parseOption(ptr->lay_option_lst);
- break;
- case EOF_TOKEN:
- Error (UNEXPECTED_EOF_MSG, NULL);
- break;
- default:
- Error (INVALID_KEYWORD_MSG, xf86tokenString ());
- break;
- }
- }
-
- if (!has_ident)
- Error (NO_IDENT_MSG, NULL);
-
-#ifdef DEBUG
- printf ("Layout section parsed\n");
-#endif
-
- return ptr;
-}
-
-#undef CLEANUP
-
-void
-xf86printLayoutSection (FILE * cf, XF86ConfLayoutPtr ptr)
-{
- XF86ConfAdjacencyPtr aptr;
- XF86ConfInactivePtr iptr;
- XF86ConfInputrefPtr inptr;
- XF86OptionPtr optr;
-
- while (ptr)
- {
- fprintf (cf, "Section \"ServerLayout\"\n");
- if (ptr->lay_comment)
- fprintf (cf, "%s", ptr->lay_comment);
- if (ptr->lay_identifier)
- fprintf (cf, "\tIdentifier \"%s\"\n", ptr->lay_identifier);
-
- for (aptr = ptr->lay_adjacency_lst; aptr; aptr = aptr->list.next)
- {
- fprintf (cf, "\tScreen ");
- if (aptr->adj_scrnum >= 0)
- fprintf (cf, "%2d", aptr->adj_scrnum);
- else
- fprintf (cf, " ");
- fprintf (cf, " \"%s\"", aptr->adj_screen_str);
- switch(aptr->adj_where)
- {
- case CONF_ADJ_OBSOLETE:
- fprintf (cf, " \"%s\"", aptr->adj_top_str);
- fprintf (cf, " \"%s\"", aptr->adj_bottom_str);
- fprintf (cf, " \"%s\"", aptr->adj_right_str);
- fprintf (cf, " \"%s\"\n", aptr->adj_left_str);
- break;
- case CONF_ADJ_ABSOLUTE:
- if (aptr->adj_x != -1)
- fprintf (cf, " %d %d\n", aptr->adj_x, aptr->adj_y);
- else
- fprintf (cf, "\n");
- break;
- case CONF_ADJ_RIGHTOF:
- fprintf (cf, " RightOf \"%s\"\n", aptr->adj_refscreen);
- break;
- case CONF_ADJ_LEFTOF:
- fprintf (cf, " LeftOf \"%s\"\n", aptr->adj_refscreen);
- break;
- case CONF_ADJ_ABOVE:
- fprintf (cf, " Above \"%s\"\n", aptr->adj_refscreen);
- break;
- case CONF_ADJ_BELOW:
- fprintf (cf, " Below \"%s\"\n", aptr->adj_refscreen);
- break;
- case CONF_ADJ_RELATIVE:
- fprintf (cf, " Relative \"%s\" %d %d\n", aptr->adj_refscreen,
- aptr->adj_x, aptr->adj_y);
- break;
- }
- }
- for (iptr = ptr->lay_inactive_lst; iptr; iptr = iptr->list.next)
- fprintf (cf, "\tInactive \"%s\"\n", iptr->inactive_device_str);
- for (inptr = ptr->lay_input_lst; inptr; inptr = inptr->list.next)
- {
- fprintf (cf, "\tInputDevice \"%s\"", inptr->iref_inputdev_str);
- for (optr = inptr->iref_option_lst; optr; optr = optr->list.next)
- {
- fprintf(cf, " \"%s\"", optr->opt_name);
- }
- fprintf(cf, "\n");
- }
- xf86printOptionList(cf, ptr->lay_option_lst, 1);
- fprintf (cf, "EndSection\n\n");
- ptr = ptr->list.next;
- }
-}
-
-static void
-xf86freeAdjacencyList (XF86ConfAdjacencyPtr ptr)
-{
- XF86ConfAdjacencyPtr prev;
-
- while (ptr)
- {
- TestFree (ptr->adj_screen_str);
- TestFree (ptr->adj_top_str);
- TestFree (ptr->adj_bottom_str);
- TestFree (ptr->adj_left_str);
- TestFree (ptr->adj_right_str);
-
- prev = ptr;
- ptr = ptr->list.next;
- free (prev);
- }
-
-}
-
-static void
-xf86freeInputrefList (XF86ConfInputrefPtr ptr)
-{
- XF86ConfInputrefPtr prev;
-
- while (ptr)
- {
- TestFree (ptr->iref_inputdev_str);
- xf86optionListFree (ptr->iref_option_lst);
- prev = ptr;
- ptr = ptr->list.next;
- free (prev);
- }
-
-}
-
-void
-xf86freeLayoutList (XF86ConfLayoutPtr ptr)
-{
- XF86ConfLayoutPtr prev;
-
- while (ptr)
- {
- TestFree (ptr->lay_identifier);
- TestFree (ptr->lay_comment);
- xf86freeAdjacencyList (ptr->lay_adjacency_lst);
- xf86freeInputrefList (ptr->lay_input_lst);
- prev = ptr;
- ptr = ptr->list.next;
- free (prev);
- }
-}
-
-int
-xf86layoutAddInputDevices(XF86ConfigPtr config, XF86ConfLayoutPtr layout)
-{
- int count = 0;
- XF86ConfInputPtr input = config->conf_input_lst;
- XF86ConfInputrefPtr inptr;
-
- /* add all AutoServerLayout devices to the server layout */
- while (input)
- {
- if (xf86CheckBoolOption(input->inp_option_lst, "AutoServerLayout", FALSE))
- {
- XF86ConfInputrefPtr iref = layout->lay_input_lst;
-
- /* avoid duplicates if referenced but lists AutoServerLayout too */
- while (iref)
- {
- if (strcmp(iref->iref_inputdev_str, input->inp_identifier) == 0)
- break;
- iref = iref->list.next;
- }
-
- if (!iref)
- {
- XF86ConfInputrefPtr iptr;
- iptr = calloc(1, sizeof(XF86ConfInputrefRec));
- iptr->iref_inputdev_str = input->inp_identifier;
- layout->lay_input_lst = (XF86ConfInputrefPtr)
- xf86addListItem((glp)layout->lay_input_lst, (glp)iptr);
- count++;
- }
- }
- input = input->list.next;
- }
-
- inptr = layout->lay_input_lst;
- while (inptr)
- {
- input = xf86findInput (inptr->iref_inputdev_str,
- config->conf_input_lst);
- if (!input)
- {
- xf86validationError (UNDEFINED_INPUT_MSG,
- inptr->iref_inputdev_str, layout->lay_identifier);
- return -1;
- }
- else
- inptr->iref_inputdev = input;
- inptr = inptr->list.next;
- }
-
- return count;
-}
-
-int
-xf86validateLayout (XF86ConfigPtr p)
-{
- XF86ConfLayoutPtr layout = p->conf_layout_lst;
- XF86ConfAdjacencyPtr adj;
- XF86ConfInactivePtr iptr;
- XF86ConfScreenPtr screen;
- XF86ConfDevicePtr device;
-
- while (layout)
- {
- adj = layout->lay_adjacency_lst;
- while (adj)
- {
- /* the first one can't be "" but all others can */
- screen = xf86findScreen (adj->adj_screen_str, p->conf_screen_lst);
- if (!screen)
- {
- xf86validationError (UNDEFINED_SCREEN_MSG,
- adj->adj_screen_str, layout->lay_identifier);
- return FALSE;
- }
- else
- adj->adj_screen = screen;
-
- adj = adj->list.next;
- }
- iptr = layout->lay_inactive_lst;
- while (iptr)
- {
- device = xf86findDevice (iptr->inactive_device_str,
- p->conf_device_lst);
- if (!device)
- {
- xf86validationError (UNDEFINED_DEVICE_LAY_MSG,
- iptr->inactive_device_str, layout->lay_identifier);
- return FALSE;
- }
- else
- iptr->inactive_device = device;
- iptr = iptr->list.next;
- }
-
- if (xf86layoutAddInputDevices(p, layout) == -1)
- return FALSE;
-
- layout = layout->list.next;
- }
- return TRUE;
-}
-
-XF86ConfLayoutPtr
-xf86findLayout (const char *name, XF86ConfLayoutPtr list)
-{
- while (list)
- {
- if (xf86nameCompare (list->lay_identifier, name) == 0)
- return list;
- list = list->list.next;
- }
- return NULL;
-}
-
+/* + * + * Copyright (c) 1997 Metro Link Incorporated + * + * 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 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 X CONSORTIUM 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. + * + * Except as contained in this notice, the name of the Metro Link shall not be + * used in advertising or otherwise to promote the sale, use or other dealings + * in this Software without prior written authorization from Metro Link. + * + */ +/* + * Copyright (c) 1997-2003 by The XFree86 Project, Inc. + * + * 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 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + */ + + +/* View/edit this file with tab stops set to 4 */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include "xf86Parser.h" +#include "xf86tokens.h" +#include "Configint.h" +#include <string.h> +#include "optionstr.h" + +/* Needed for auto server layout */ +extern int xf86CheckBoolOption(void* optlist, const char *name, int deflt); + +extern LexRec val; + +static xf86ConfigSymTabRec LayoutTab[] = +{ + {ENDSECTION, "endsection"}, + {SCREEN, "screen"}, + {IDENTIFIER, "identifier"}, + {INACTIVE, "inactive"}, + {INPUTDEVICE, "inputdevice"}, + {OPTION, "option"}, + {-1, ""}, +}; + +static xf86ConfigSymTabRec AdjTab[] = +{ + {RIGHTOF, "rightof"}, + {LEFTOF, "leftof"}, + {ABOVE, "above"}, + {BELOW, "below"}, + {RELATIVE, "relative"}, + {ABSOLUTE, "absolute"}, + {-1, ""}, +}; + +#define CLEANUP xf86freeLayoutList + +XF86ConfLayoutPtr +xf86parseLayoutSection (void) +{ + int has_ident = FALSE; + int token; + parsePrologue (XF86ConfLayoutPtr, XF86ConfLayoutRec) + + while ((token = xf86getToken (LayoutTab)) != ENDSECTION) + { + switch (token) + { + case COMMENT: + ptr->lay_comment = xf86addComment(ptr->lay_comment, val.str); + break; + case IDENTIFIER: + if (xf86getSubToken (&(ptr->lay_comment)) != STRING) + Error (QUOTE_MSG, "Identifier"); + if (has_ident == TRUE) + Error (MULTIPLE_MSG, "Identifier"); + ptr->lay_identifier = val.str; + has_ident = TRUE; + break; + case INACTIVE: + { + XF86ConfInactivePtr iptr; + + iptr = calloc (1, sizeof (XF86ConfInactiveRec)); + iptr->list.next = NULL; + if (xf86getSubToken (&(ptr->lay_comment)) != STRING) { + free (iptr); + Error (INACTIVE_MSG, NULL); + } + iptr->inactive_device_str = val.str; + ptr->lay_inactive_lst = (XF86ConfInactivePtr) + xf86addListItem ((glp) ptr->lay_inactive_lst, (glp) iptr); + } + break; + case SCREEN: + { + XF86ConfAdjacencyPtr aptr; + int absKeyword = 0; + + aptr = calloc (1, sizeof (XF86ConfAdjacencyRec)); + aptr->list.next = NULL; + aptr->adj_scrnum = -1; + aptr->adj_where = CONF_ADJ_OBSOLETE; + aptr->adj_x = 0; + aptr->adj_y = 0; + aptr->adj_refscreen = NULL; + if ((token = xf86getSubToken (&(ptr->lay_comment))) == NUMBER) + aptr->adj_scrnum = val.num; + else + xf86unGetToken (token); + token = xf86getSubToken(&(ptr->lay_comment)); + if (token != STRING) { + free(aptr); + Error (SCREEN_MSG, NULL); + } + aptr->adj_screen_str = val.str; + + token = xf86getSubTokenWithTab(&(ptr->lay_comment), AdjTab); + switch (token) + { + case RIGHTOF: + aptr->adj_where = CONF_ADJ_RIGHTOF; + break; + case LEFTOF: + aptr->adj_where = CONF_ADJ_LEFTOF; + break; + case ABOVE: + aptr->adj_where = CONF_ADJ_ABOVE; + break; + case BELOW: + aptr->adj_where = CONF_ADJ_BELOW; + break; + case RELATIVE: + aptr->adj_where = CONF_ADJ_RELATIVE; + break; + case ABSOLUTE: + aptr->adj_where = CONF_ADJ_ABSOLUTE; + absKeyword = 1; + break; + case EOF_TOKEN: + free(aptr); + Error (UNEXPECTED_EOF_MSG, NULL); + break; + default: + xf86unGetToken (token); + token = xf86getSubToken(&(ptr->lay_comment)); + if (token == STRING) + aptr->adj_where = CONF_ADJ_OBSOLETE; + else + aptr->adj_where = CONF_ADJ_ABSOLUTE; + } + switch (aptr->adj_where) + { + case CONF_ADJ_ABSOLUTE: + if (absKeyword) + token = xf86getSubToken(&(ptr->lay_comment)); + if (token == NUMBER) + { + aptr->adj_x = val.num; + token = xf86getSubToken(&(ptr->lay_comment)); + if (token != NUMBER) { + free(aptr); + Error(INVALID_SCR_MSG, NULL); + } + aptr->adj_y = val.num; + } else { + if (absKeyword) { + free(aptr); + Error(INVALID_SCR_MSG, NULL); + } else + xf86unGetToken (token); + } + break; + case CONF_ADJ_RIGHTOF: + case CONF_ADJ_LEFTOF: + case CONF_ADJ_ABOVE: + case CONF_ADJ_BELOW: + case CONF_ADJ_RELATIVE: + token = xf86getSubToken(&(ptr->lay_comment)); + if (token != STRING) { + free(aptr); + Error(INVALID_SCR_MSG, NULL); + } + aptr->adj_refscreen = val.str; + if (aptr->adj_where == CONF_ADJ_RELATIVE) + { + token = xf86getSubToken(&(ptr->lay_comment)); + if (token != NUMBER) { + free(aptr); + Error(INVALID_SCR_MSG, NULL); + } + aptr->adj_x = val.num; + token = xf86getSubToken(&(ptr->lay_comment)); + if (token != NUMBER) { + free(aptr); + Error(INVALID_SCR_MSG, NULL); + } + aptr->adj_y = val.num; + } + break; + case CONF_ADJ_OBSOLETE: + /* top */ + aptr->adj_top_str = val.str; + + /* bottom */ + if (xf86getSubToken (&(ptr->lay_comment)) != STRING) { + free(aptr); + Error (SCREEN_MSG, NULL); + } + aptr->adj_bottom_str = val.str; + + /* left */ + if (xf86getSubToken (&(ptr->lay_comment)) != STRING) { + free(aptr); + Error (SCREEN_MSG, NULL); + } + aptr->adj_left_str = val.str; + + /* right */ + if (xf86getSubToken (&(ptr->lay_comment)) != STRING) { + free(aptr); + Error (SCREEN_MSG, NULL); + } + aptr->adj_right_str = val.str; + + } + ptr->lay_adjacency_lst = (XF86ConfAdjacencyPtr) + xf86addListItem ((glp) ptr->lay_adjacency_lst, (glp) aptr); + } + break; + case INPUTDEVICE: + { + XF86ConfInputrefPtr iptr; + + iptr = calloc (1, sizeof (XF86ConfInputrefRec)); + iptr->list.next = NULL; + iptr->iref_option_lst = NULL; + if (xf86getSubToken (&(ptr->lay_comment)) != STRING) { + free(iptr); + Error (INPUTDEV_MSG, NULL); + } + iptr->iref_inputdev_str = val.str; + while ((token = xf86getSubToken (&(ptr->lay_comment))) == STRING) + { + iptr->iref_option_lst = + xf86addNewOption (iptr->iref_option_lst, val.str, NULL); + } + xf86unGetToken (token); + ptr->lay_input_lst = (XF86ConfInputrefPtr) + xf86addListItem ((glp) ptr->lay_input_lst, (glp) iptr); + } + break; + case OPTION: + ptr->lay_option_lst = xf86parseOption(ptr->lay_option_lst); + break; + case EOF_TOKEN: + Error (UNEXPECTED_EOF_MSG, NULL); + break; + default: + Error (INVALID_KEYWORD_MSG, xf86tokenString ()); + break; + } + } + + if (!has_ident) + Error (NO_IDENT_MSG, NULL); + +#ifdef DEBUG + printf ("Layout section parsed\n"); +#endif + + return ptr; +} + +#undef CLEANUP + +void +xf86printLayoutSection (FILE * cf, XF86ConfLayoutPtr ptr) +{ + XF86ConfAdjacencyPtr aptr; + XF86ConfInactivePtr iptr; + XF86ConfInputrefPtr inptr; + XF86OptionPtr optr; + + while (ptr) + { + fprintf (cf, "Section \"ServerLayout\"\n"); + if (ptr->lay_comment) + fprintf (cf, "%s", ptr->lay_comment); + if (ptr->lay_identifier) + fprintf (cf, "\tIdentifier \"%s\"\n", ptr->lay_identifier); + + for (aptr = ptr->lay_adjacency_lst; aptr; aptr = aptr->list.next) + { + fprintf (cf, "\tScreen "); + if (aptr->adj_scrnum >= 0) + fprintf (cf, "%2d", aptr->adj_scrnum); + else + fprintf (cf, " "); + fprintf (cf, " \"%s\"", aptr->adj_screen_str); + switch(aptr->adj_where) + { + case CONF_ADJ_OBSOLETE: + fprintf (cf, " \"%s\"", aptr->adj_top_str); + fprintf (cf, " \"%s\"", aptr->adj_bottom_str); + fprintf (cf, " \"%s\"", aptr->adj_right_str); + fprintf (cf, " \"%s\"\n", aptr->adj_left_str); + break; + case CONF_ADJ_ABSOLUTE: + if (aptr->adj_x != -1) + fprintf (cf, " %d %d\n", aptr->adj_x, aptr->adj_y); + else + fprintf (cf, "\n"); + break; + case CONF_ADJ_RIGHTOF: + fprintf (cf, " RightOf \"%s\"\n", aptr->adj_refscreen); + break; + case CONF_ADJ_LEFTOF: + fprintf (cf, " LeftOf \"%s\"\n", aptr->adj_refscreen); + break; + case CONF_ADJ_ABOVE: + fprintf (cf, " Above \"%s\"\n", aptr->adj_refscreen); + break; + case CONF_ADJ_BELOW: + fprintf (cf, " Below \"%s\"\n", aptr->adj_refscreen); + break; + case CONF_ADJ_RELATIVE: + fprintf (cf, " Relative \"%s\" %d %d\n", aptr->adj_refscreen, + aptr->adj_x, aptr->adj_y); + break; + } + } + for (iptr = ptr->lay_inactive_lst; iptr; iptr = iptr->list.next) + fprintf (cf, "\tInactive \"%s\"\n", iptr->inactive_device_str); + for (inptr = ptr->lay_input_lst; inptr; inptr = inptr->list.next) + { + fprintf (cf, "\tInputDevice \"%s\"", inptr->iref_inputdev_str); + for (optr = inptr->iref_option_lst; optr; optr = optr->list.next) + { + fprintf(cf, " \"%s\"", optr->opt_name); + } + fprintf(cf, "\n"); + } + xf86printOptionList(cf, ptr->lay_option_lst, 1); + fprintf (cf, "EndSection\n\n"); + ptr = ptr->list.next; + } +} + +static void +xf86freeAdjacencyList (XF86ConfAdjacencyPtr ptr) +{ + XF86ConfAdjacencyPtr prev; + + while (ptr) + { + TestFree (ptr->adj_screen_str); + TestFree (ptr->adj_top_str); + TestFree (ptr->adj_bottom_str); + TestFree (ptr->adj_left_str); + TestFree (ptr->adj_right_str); + + prev = ptr; + ptr = ptr->list.next; + free (prev); + } + +} + +static void +xf86freeInputrefList (XF86ConfInputrefPtr ptr) +{ + XF86ConfInputrefPtr prev; + + while (ptr) + { + TestFree (ptr->iref_inputdev_str); + xf86optionListFree (ptr->iref_option_lst); + prev = ptr; + ptr = ptr->list.next; + free (prev); + } + +} + +void +xf86freeLayoutList (XF86ConfLayoutPtr ptr) +{ + XF86ConfLayoutPtr prev; + + while (ptr) + { + TestFree (ptr->lay_identifier); + TestFree (ptr->lay_comment); + xf86freeAdjacencyList (ptr->lay_adjacency_lst); + xf86freeInputrefList (ptr->lay_input_lst); + prev = ptr; + ptr = ptr->list.next; + free (prev); + } +} + +int +xf86layoutAddInputDevices(XF86ConfigPtr config, XF86ConfLayoutPtr layout) +{ + int count = 0; + XF86ConfInputPtr input = config->conf_input_lst; + XF86ConfInputrefPtr inptr; + + /* add all AutoServerLayout devices to the server layout */ + while (input) + { + if (xf86CheckBoolOption(input->inp_option_lst, "AutoServerLayout", FALSE)) + { + XF86ConfInputrefPtr iref = layout->lay_input_lst; + + /* avoid duplicates if referenced but lists AutoServerLayout too */ + while (iref) + { + if (strcmp(iref->iref_inputdev_str, input->inp_identifier) == 0) + break; + iref = iref->list.next; + } + + if (!iref) + { + XF86ConfInputrefPtr iptr; + iptr = calloc(1, sizeof(XF86ConfInputrefRec)); + iptr->iref_inputdev_str = input->inp_identifier; + layout->lay_input_lst = (XF86ConfInputrefPtr) + xf86addListItem((glp)layout->lay_input_lst, (glp)iptr); + count++; + } + } + input = input->list.next; + } + + inptr = layout->lay_input_lst; + while (inptr) + { + input = xf86findInput (inptr->iref_inputdev_str, + config->conf_input_lst); + if (!input) + { + xf86validationError (UNDEFINED_INPUT_MSG, + inptr->iref_inputdev_str, layout->lay_identifier); + return -1; + } + else + inptr->iref_inputdev = input; + inptr = inptr->list.next; + } + + return count; +} + +int +xf86validateLayout (XF86ConfigPtr p) +{ + XF86ConfLayoutPtr layout = p->conf_layout_lst; + XF86ConfAdjacencyPtr adj; + XF86ConfInactivePtr iptr; + XF86ConfScreenPtr screen; + XF86ConfDevicePtr device; + + while (layout) + { + adj = layout->lay_adjacency_lst; + while (adj) + { + /* the first one can't be "" but all others can */ + screen = xf86findScreen (adj->adj_screen_str, p->conf_screen_lst); + if (!screen) + { + xf86validationError (UNDEFINED_SCREEN_MSG, + adj->adj_screen_str, layout->lay_identifier); + return FALSE; + } + else + adj->adj_screen = screen; + + adj = adj->list.next; + } + iptr = layout->lay_inactive_lst; + while (iptr) + { + device = xf86findDevice (iptr->inactive_device_str, + p->conf_device_lst); + if (!device) + { + xf86validationError (UNDEFINED_DEVICE_LAY_MSG, + iptr->inactive_device_str, layout->lay_identifier); + return FALSE; + } + else + iptr->inactive_device = device; + iptr = iptr->list.next; + } + + if (xf86layoutAddInputDevices(p, layout) == -1) + return FALSE; + + layout = layout->list.next; + } + return TRUE; +} + +XF86ConfLayoutPtr +xf86findLayout (const char *name, XF86ConfLayoutPtr list) +{ + while (list) + { + if (xf86nameCompare (list->lay_identifier, name) == 0) + return list; + list = list->list.next; + } + return NULL; +} + diff --git a/xorg-server/hw/xnest/Events.c b/xorg-server/hw/xnest/Events.c index 2399313c6..619427ded 100644 --- a/xorg-server/hw/xnest/Events.c +++ b/xorg-server/hw/xnest/Events.c @@ -198,8 +198,6 @@ xnestCollectEvents(void) case DestroyNotify: if (xnestParentWindow != (Window) 0 && X.xdestroywindow.window == xnestParentWindow) - CloseWellKnownConnections(); - OsCleanup(1); exit (0); break; diff --git a/xorg-server/hw/xnest/Keyboard.c b/xorg-server/hw/xnest/Keyboard.c index 9dba46ccd..5ef376b91 100644 --- a/xorg-server/hw/xnest/Keyboard.c +++ b/xorg-server/hw/xnest/Keyboard.c @@ -1,251 +1,268 @@ -/*
-
-Copyright 1993 by Davor Matic
-
-Permission to use, copy, modify, distribute, and sell this software
-and its documentation for any purpose is hereby granted without fee,
-provided that the above copyright notice appear in all copies and that
-both that copyright notice and this permission notice appear in
-supporting documentation. Davor Matic makes no representations about
-the suitability of this software for any purpose. It is provided "as
-is" without express or implied warranty.
-
-*/
-
-#ifdef HAVE_XNEST_CONFIG_H
-#include <xnest-config.h>
-#endif
-
-#include <X11/X.h>
-#include <X11/Xproto.h>
-#include <X11/keysym.h>
-#include "screenint.h"
-#include "inputstr.h"
-#include "misc.h"
-#include "scrnintstr.h"
-#include "servermd.h"
-
-#include "Xnest.h"
-
-#include "Display.h"
-#include "Screen.h"
-#include "Keyboard.h"
-#include "Args.h"
-#include "Events.h"
-
-#include <X11/extensions/XKB.h>
-#include "xkbsrv.h"
-#include <X11/extensions/XKBconfig.h>
-
-extern Bool
-XkbQueryExtension(
- Display * /* dpy */,
- int * /* opcodeReturn */,
- int * /* eventBaseReturn */,
- int * /* errorBaseReturn */,
- int * /* majorRtrn */,
- int * /* minorRtrn */
-);
-
-extern XkbDescPtr XkbGetKeyboard(
- Display * /* dpy */,
- unsigned int /* which */,
- unsigned int /* deviceSpec */
-);
-
-extern Status XkbGetControls(
- Display * /* dpy */,
- unsigned long /* which */,
- XkbDescPtr /* desc */
-);
-
-DeviceIntPtr xnestKeyboardDevice = NULL;
-
-void
-xnestBell(int volume, DeviceIntPtr pDev, pointer ctrl, int cls)
-{
- XBell(xnestDisplay, volume);
-}
-
-void
-DDXRingBell(int volume, int pitch, int duration)
-{
- XBell(xnestDisplay, volume);
-}
-
-void
-xnestChangeKeyboardControl(DeviceIntPtr pDev, KeybdCtrl *ctrl)
-{
-#if 0
- unsigned long value_mask;
- XKeyboardControl values;
- int i;
-
- value_mask = KBKeyClickPercent |
- KBBellPercent |
- KBBellPitch |
- KBBellDuration |
- KBAutoRepeatMode;
-
- values.key_click_percent = ctrl->click;
- values.bell_percent = ctrl->bell;
- values.bell_pitch = ctrl->bell_pitch;
- values.bell_duration = ctrl->bell_duration;
- values.auto_repeat_mode = ctrl->autoRepeat ?
- AutoRepeatModeOn : AutoRepeatModeOff;
-
- XChangeKeyboardControl(xnestDisplay, value_mask, &values);
-
- /*
- value_mask = KBKey | KBAutoRepeatMode;
- At this point, we need to walk through the vector and compare it
- to the current server vector. If there are differences, report them.
- */
-
- value_mask = KBLed | KBLedMode;
- for (i = 1; i <= 32; i++) {
- values.led = i;
- values.led_mode = (ctrl->leds & (1 << (i - 1))) ? LedModeOn : LedModeOff;
- XChangeKeyboardControl(xnestDisplay, value_mask, &values);
- }
-#endif
-}
-
-int
-xnestKeyboardProc(DeviceIntPtr pDev, int onoff)
-{
- KeySym *keymap;
- int mapWidth;
- int min_keycode, max_keycode;
- KeySymsRec keySyms;
- int i;
- XKeyboardState values;
- XkbDescPtr xkb;
- int op, event, error, major, minor;
-
- switch (onoff)
- {
- case DEVICE_INIT:
- XDisplayKeycodes(xnestDisplay, &min_keycode, &max_keycode);
-#ifdef _XSERVER64
- {
- KeySym64 *keymap64;
- int i, len;
- keymap64 = XGetKeyboardMapping(xnestDisplay,
- min_keycode,
- max_keycode - min_keycode + 1,
- &mapWidth);
- len = (max_keycode - min_keycode + 1) * mapWidth;
- keymap = (KeySym *)malloc(len * sizeof(KeySym));
- for(i = 0; i < len; ++i)
- keymap[i] = keymap64[i];
- XFree(keymap64);
- }
-#else
- keymap = XGetKeyboardMapping(xnestDisplay,
- min_keycode,
- max_keycode - min_keycode + 1,
- &mapWidth);
-#endif
-
- keySyms.minKeyCode = min_keycode;
- keySyms.maxKeyCode = max_keycode;
- keySyms.mapWidth = mapWidth;
- keySyms.map = keymap;
-
- if (XkbQueryExtension(xnestDisplay, &op, &event, &error, &major, &minor) == 0) {
- ErrorF("Unable to initialize XKEYBOARD extension.\n");
- goto XkbError;
- }
- xkb = XkbGetKeyboard(xnestDisplay, XkbGBN_AllComponentsMask, XkbUseCoreKbd);
- if (xkb == NULL || xkb->geom == NULL) {
- ErrorF("Couldn't get keyboard.\n");
- goto XkbError;
- }
- XkbGetControls(xnestDisplay, XkbAllControlsMask, xkb);
-
- InitKeyboardDeviceStruct(pDev, NULL,
- xnestBell, xnestChangeKeyboardControl);
- XkbDDXChangeControls(pDev, xkb->ctrls, xkb->ctrls);
- XkbFreeKeyboard(xkb, 0, False);
- free(keymap);
- break;
- case DEVICE_ON:
- xnestEventMask |= XNEST_KEYBOARD_EVENT_MASK;
- for (i = 0; i < xnestNumScreens; i++)
- XSelectInput(xnestDisplay, xnestDefaultWindows[i], xnestEventMask);
- break;
- case DEVICE_OFF:
- xnestEventMask &= ~XNEST_KEYBOARD_EVENT_MASK;
- for (i = 0; i < xnestNumScreens; i++)
- XSelectInput(xnestDisplay, xnestDefaultWindows[i], xnestEventMask);
- break;
- case DEVICE_CLOSE:
- break;
- }
- return Success;
-
-XkbError:
- XGetKeyboardControl(xnestDisplay, &values);
- memmove((char *)defaultKeyboardControl.autoRepeats,
- (char *)values.auto_repeats,
- sizeof(values.auto_repeats));
-
- InitKeyboardDeviceStruct(pDev, NULL,
- xnestBell, xnestChangeKeyboardControl);
- free(keymap);
- return Success;
-}
-
-Bool
-LegalModifier(unsigned int key, DeviceIntPtr pDev)
-{
- return TRUE;
-}
-
-void
-xnestUpdateModifierState(unsigned int state)
-{
- DeviceIntPtr pDev = xnestKeyboardDevice;
- KeyClassPtr keyc = pDev->key;
- int i;
- CARD8 mask;
- int xkb_state;
-
- if (!pDev)
- return;
-
- xkb_state = XkbStateFieldFromRec(&pDev->key->xkbInfo->state);
- state = state & 0xff;
-
- if (xkb_state == state)
- return;
-
- for (i = 0, mask = 1; i < 8; i++, mask <<= 1) {
- int key;
-
- /* Modifier is down, but shouldn't be
- */
- if ((xkb_state & mask) && !(state & mask)) {
- int count = keyc->modifierKeyCount[i];
-
- for (key = 0; key < MAP_LENGTH; key++)
- if (keyc->xkbInfo->desc->map->modmap[key] & mask) {
- if (key_is_down(pDev, key, KEY_PROCESSED))
- xnestQueueKeyEvent(KeyRelease, key);
-
- if (--count == 0)
- break;
- }
- }
-
- /* Modifier shoud be down, but isn't
- */
- if (!(xkb_state & mask) && (state & mask))
- for (key = 0; key < MAP_LENGTH; key++)
- if (keyc->xkbInfo->desc->map->modmap[key] & mask) {
- xnestQueueKeyEvent(KeyPress, key);
- break;
- }
- }
-}
+/* + +Copyright 1993 by Davor Matic + +Permission to use, copy, modify, distribute, and sell this software +and its documentation for any purpose is hereby granted without fee, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation. Davor Matic makes no representations about +the suitability of this software for any purpose. It is provided "as +is" without express or implied warranty. + +*/ + +#ifdef HAVE_XNEST_CONFIG_H +#include <xnest-config.h> +#endif + +#include <X11/X.h> +#include <X11/Xproto.h> +#include <X11/keysym.h> +#include "screenint.h" +#include "inputstr.h" +#include "misc.h" +#include "scrnintstr.h" +#include "servermd.h" + +#include "Xnest.h" + +#include "Display.h" +#include "Screen.h" +#include "Keyboard.h" +#include "Args.h" +#include "Events.h" + +#include <X11/extensions/XKB.h> +#include "xkbsrv.h" +#include <X11/extensions/XKBconfig.h> + +extern Bool +XkbQueryExtension( + Display * /* dpy */, + int * /* opcodeReturn */, + int * /* eventBaseReturn */, + int * /* errorBaseReturn */, + int * /* majorRtrn */, + int * /* minorRtrn */ +); + +extern XkbDescPtr XkbGetKeyboard( + Display * /* dpy */, + unsigned int /* which */, + unsigned int /* deviceSpec */ +); + +extern Status XkbGetControls( + Display * /* dpy */, + unsigned long /* which */, + XkbDescPtr /* desc */ +); + +DeviceIntPtr xnestKeyboardDevice = NULL; + +void +xnestBell(int volume, DeviceIntPtr pDev, pointer ctrl, int cls) +{ + XBell(xnestDisplay, volume); +} + +void +DDXRingBell(int volume, int pitch, int duration) +{ + XBell(xnestDisplay, volume); +} + +void +xnestChangeKeyboardControl(DeviceIntPtr pDev, KeybdCtrl *ctrl) +{ +#if 0 + unsigned long value_mask; + XKeyboardControl values; + int i; + + value_mask = KBKeyClickPercent | + KBBellPercent | + KBBellPitch | + KBBellDuration | + KBAutoRepeatMode; + + values.key_click_percent = ctrl->click; + values.bell_percent = ctrl->bell; + values.bell_pitch = ctrl->bell_pitch; + values.bell_duration = ctrl->bell_duration; + values.auto_repeat_mode = ctrl->autoRepeat ? + AutoRepeatModeOn : AutoRepeatModeOff; + + XChangeKeyboardControl(xnestDisplay, value_mask, &values); + + /* + value_mask = KBKey | KBAutoRepeatMode; + At this point, we need to walk through the vector and compare it + to the current server vector. If there are differences, report them. + */ + + value_mask = KBLed | KBLedMode; + for (i = 1; i <= 32; i++) { + values.led = i; + values.led_mode = (ctrl->leds & (1 << (i - 1))) ? LedModeOn : LedModeOff; + XChangeKeyboardControl(xnestDisplay, value_mask, &values); + } +#endif +} + +int +xnestKeyboardProc(DeviceIntPtr pDev, int onoff) +{ + XModifierKeymap *modifier_keymap; + KeySym *keymap; + int mapWidth; + int min_keycode, max_keycode; + KeySymsRec keySyms; + CARD8 modmap[MAP_LENGTH]; + int i, j; + XKeyboardState values; + XkbDescPtr xkb; + int op, event, error, major, minor; + + switch (onoff) + { + case DEVICE_INIT: + XDisplayKeycodes(xnestDisplay, &min_keycode, &max_keycode); +#ifdef _XSERVER64 + { + KeySym64 *keymap64; + int len; + keymap64 = XGetKeyboardMapping(xnestDisplay, + min_keycode, + max_keycode - min_keycode + 1, + &mapWidth); + len = (max_keycode - min_keycode + 1) * mapWidth; + keymap = (KeySym *)malloc(len * sizeof(KeySym)); + for(i = 0; i < len; ++i) + keymap[i] = keymap64[i]; + XFree(keymap64); + } +#else + keymap = XGetKeyboardMapping(xnestDisplay, + min_keycode, + max_keycode - min_keycode + 1, + &mapWidth); +#endif + + memset(modmap, 0, sizeof(modmap)); + modifier_keymap = XGetModifierMapping(xnestDisplay); + for (j = 0; j < 8; j++) + for(i = 0; i < modifier_keymap->max_keypermod; i++) { + CARD8 keycode; + if ((keycode = modifier_keymap->modifiermap[j * modifier_keymap->max_keypermod + i])) + modmap[keycode] |= 1<<j; + } + XFreeModifiermap(modifier_keymap); + + keySyms.minKeyCode = min_keycode; + keySyms.maxKeyCode = max_keycode; + keySyms.mapWidth = mapWidth; + keySyms.map = keymap; + + if (XkbQueryExtension(xnestDisplay, &op, &event, &error, &major, &minor) == 0) { + ErrorF("Unable to initialize XKEYBOARD extension.\n"); + goto XkbError; + } + xkb = XkbGetKeyboard(xnestDisplay, XkbGBN_AllComponentsMask, XkbUseCoreKbd); + if (xkb == NULL || xkb->geom == NULL) { + ErrorF("Couldn't get keyboard.\n"); + goto XkbError; + } + XkbGetControls(xnestDisplay, XkbAllControlsMask, xkb); + + InitKeyboardDeviceStruct(pDev, NULL, + xnestBell, xnestChangeKeyboardControl); + + XkbApplyMappingChange(pDev, &keySyms, keySyms.minKeyCode, + keySyms.maxKeyCode - keySyms.minKeyCode + 1, + modmap, serverClient); + + XkbDDXChangeControls(pDev, xkb->ctrls, xkb->ctrls); + XkbFreeKeyboard(xkb, 0, False); + free(keymap); + break; + case DEVICE_ON: + xnestEventMask |= XNEST_KEYBOARD_EVENT_MASK; + for (i = 0; i < xnestNumScreens; i++) + XSelectInput(xnestDisplay, xnestDefaultWindows[i], xnestEventMask); + break; + case DEVICE_OFF: + xnestEventMask &= ~XNEST_KEYBOARD_EVENT_MASK; + for (i = 0; i < xnestNumScreens; i++) + XSelectInput(xnestDisplay, xnestDefaultWindows[i], xnestEventMask); + break; + case DEVICE_CLOSE: + break; + } + return Success; + +XkbError: + XGetKeyboardControl(xnestDisplay, &values); + memmove((char *)defaultKeyboardControl.autoRepeats, + (char *)values.auto_repeats, + sizeof(values.auto_repeats)); + + InitKeyboardDeviceStruct(pDev, NULL, + xnestBell, xnestChangeKeyboardControl); + free(keymap); + return Success; +} + +Bool +LegalModifier(unsigned int key, DeviceIntPtr pDev) +{ + return TRUE; +} + +void +xnestUpdateModifierState(unsigned int state) +{ + DeviceIntPtr pDev = xnestKeyboardDevice; + KeyClassPtr keyc = pDev->key; + int i; + CARD8 mask; + int xkb_state; + + if (!pDev) + return; + + xkb_state = XkbStateFieldFromRec(&pDev->key->xkbInfo->state); + state = state & 0xff; + + if (xkb_state == state) + return; + + for (i = 0, mask = 1; i < 8; i++, mask <<= 1) { + int key; + + /* Modifier is down, but shouldn't be + */ + if ((xkb_state & mask) && !(state & mask)) { + int count = keyc->modifierKeyCount[i]; + + for (key = 0; key < MAP_LENGTH; key++) + if (keyc->xkbInfo->desc->map->modmap[key] & mask) { + if (key_is_down(pDev, key, KEY_PROCESSED)) + xnestQueueKeyEvent(KeyRelease, key); + + if (--count == 0) + break; + } + } + + /* Modifier shoud be down, but isn't + */ + if (!(xkb_state & mask) && (state & mask)) + for (key = 0; key < MAP_LENGTH; key++) + if (keyc->xkbInfo->desc->map->modmap[key] & mask) { + xnestQueueKeyEvent(KeyPress, key); + break; + } + } +} diff --git a/xorg-server/hw/xquartz/darwin.c b/xorg-server/hw/xquartz/darwin.c index b483000f8..465a96d12 100644 --- a/xorg-server/hw/xquartz/darwin.c +++ b/xorg-server/hw/xquartz/darwin.c @@ -621,7 +621,7 @@ void OsVendorInit(void) char *lf; char *home = getenv("HOME"); assert(home); - assert(0 < asprintf(&lf, "%s/Library/Logs/X11.%s.log", home, bundle_id_prefix)); + assert(0 < asprintf(&lf, "%s/Library/Logs/%s.X11.log", home, bundle_id_prefix)); LogInit(lf, ".old"); free(lf); diff --git a/xorg-server/hw/xquartz/xpr/appledri.c b/xorg-server/hw/xquartz/xpr/appledri.c index 1304d5a43..6b4a8a383 100644 --- a/xorg-server/hw/xquartz/xpr/appledri.c +++ b/xorg-server/hw/xquartz/xpr/appledri.c @@ -2,7 +2,7 @@ Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. Copyright 2000 VA Linux Systems, Inc. -Copyright (c) 2002, 2009 Apple Computer, Inc. +Copyright (c) 2002, 2009-2011 Apple Inc. All Rights Reserved. Permission is hereby granted, free of charge, to any person obtaining a @@ -102,6 +102,9 @@ ProcAppleDRIQueryVersion( if (client->swapped) { swaps(&rep.sequenceNumber); swapl(&rep.length); + swaps(&rep.majorVersion); + swaps(&rep.minorVersion); + swapl(&rep.patchVersion); } WriteToClient(client, sizeof(xAppleDRIQueryVersionReply), (char *)&rep); return Success; @@ -133,6 +136,11 @@ ProcAppleDRIQueryDirectRenderingCapable( if (!LocalClient(client)) rep.isCapable = 0; + if (client->swapped) { + swaps(&rep.sequenceNumber); + swapl(&rep.length); + } + WriteToClient(client, sizeof(xAppleDRIQueryDirectRenderingCapableReply), (char *)&rep); return Success; @@ -157,6 +165,13 @@ ProcAppleDRIAuthConnection( ErrorF("Failed to authenticate %u\n", (unsigned int)stuff->magic); rep.authenticated = 0; } + + if (client->swapped) { + swaps(&rep.sequenceNumber); + swapl(&rep.length); + swapl(&rep.authenticated); /* Yes, this is a CARD32 ... sigh */ + } + WriteToClient(client, sizeof(xAppleDRIAuthConnectionReply), (char *)&rep); return Success; } @@ -216,6 +231,14 @@ ProcAppleDRICreateSurface( rep.key_1 = key[1]; rep.uid = sid; + if (client->swapped) { + swaps(&rep.sequenceNumber); + swapl(&rep.length); + swapl(&rep.key_0); + swapl(&rep.key_1); + swapl(&rep.uid); + } + WriteToClient(client, sizeof(xAppleDRICreateSurfaceReply), (char *)&rep); return Success; } @@ -277,9 +300,8 @@ ProcAppleDRICreatePixmap(ClientPtr client) rep.stringLength = strlen(path) + 1; - /* No need for swapping, because this only runs if LocalClient is true. */ rep.type = X_Reply; - rep.length = sizeof(rep) + rep.stringLength; + rep.length = bytes_to_int32(rep.stringLength); rep.sequenceNumber = client->sequence; rep.width = width; rep.height = height; @@ -290,8 +312,19 @@ ProcAppleDRICreatePixmap(ClientPtr client) if(sizeof(rep) != sz_xAppleDRICreatePixmapReply) ErrorF("error sizeof(rep) is %zu\n", sizeof(rep)); - WriteReplyToClient(client, sizeof(rep), &rep); - (void)WriteToClient(client, rep.stringLength, path); + if (client->swapped) { + swaps(&rep.sequenceNumber); + swapl(&rep.length); + swapl(&rep.stringLength); + swapl(&rep.width); + swapl(&rep.height); + swapl(&rep.pitch); + swapl(&rep.bpp); + swapl(&rep.size); + } + + WriteToClient(client, sizeof(rep), &rep); + WriteToClient(client, rep.stringLength, path); return Success; } @@ -377,21 +410,107 @@ SProcAppleDRIQueryVersion( } static int +SProcAppleDRIQueryDirectRenderingCapable( + register ClientPtr client +) +{ + REQUEST(xAppleDRIQueryDirectRenderingCapableReq); + swaps(&stuff->length); + swapl(&stuff->screen); + return ProcAppleDRIQueryDirectRenderingCapable(client); +} + +static int +SProcAppleDRIAuthConnection( + register ClientPtr client +) +{ + REQUEST(xAppleDRIAuthConnectionReq); + swaps(&stuff->length); + swapl(&stuff->screen); + swapl(&stuff->magic); + return ProcAppleDRIAuthConnection(client); +} + +static int +SProcAppleDRICreateSurface( + register ClientPtr client +) +{ + REQUEST(xAppleDRICreateSurfaceReq); + swaps(&stuff->length); + swapl(&stuff->screen); + swapl(&stuff->drawable); + swapl(&stuff->client_id); + return ProcAppleDRICreateSurface(client); +} + +static int +SProcAppleDRIDestroySurface( + register ClientPtr client +) +{ + REQUEST(xAppleDRIDestroySurfaceReq); + swaps(&stuff->length); + swapl(&stuff->screen); + swapl(&stuff->drawable); + return ProcAppleDRIDestroySurface(client); +} + +static int +SProcAppleDRICreatePixmap( + register ClientPtr client +) +{ + REQUEST(xAppleDRICreatePixmapReq); + swaps(&stuff->length); + swapl(&stuff->screen); + swapl(&stuff->drawable); + return ProcAppleDRICreatePixmap(client); +} + +static int +SProcAppleDRIDestroyPixmap( + register ClientPtr client +) +{ + REQUEST(xAppleDRIDestroyPixmapReq); + swaps(&stuff->length); + swapl(&stuff->drawable); + return ProcAppleDRIDestroyPixmap(client); +} + +static int SProcAppleDRIDispatch ( register ClientPtr client ) { REQUEST(xReq); - /* It is bound to be non-local when there is byte swapping */ + switch (stuff->data) + { + case X_AppleDRIQueryVersion: + return SProcAppleDRIQueryVersion(client); + case X_AppleDRIQueryDirectRenderingCapable: + return SProcAppleDRIQueryDirectRenderingCapable(client); + } + if (!LocalClient(client)) return DRIErrorBase + AppleDRIClientNotLocal; - /* only local clients are allowed DRI access */ switch (stuff->data) { - case X_AppleDRIQueryVersion: - return SProcAppleDRIQueryVersion(client); + case X_AppleDRIAuthConnection: + return SProcAppleDRIAuthConnection(client); + case X_AppleDRICreateSurface: + return SProcAppleDRICreateSurface(client); + case X_AppleDRIDestroySurface: + return SProcAppleDRIDestroySurface(client); + case X_AppleDRICreatePixmap: + return SProcAppleDRICreatePixmap(client); + case X_AppleDRIDestroyPixmap: + return SProcAppleDRIDestroyPixmap(client); + default: return BadRequest; } diff --git a/xorg-server/hw/xquartz/xpr/appledristr.h b/xorg-server/hw/xquartz/xpr/appledristr.h index c569719b7..b5ffe5b46 100644 --- a/xorg-server/hw/xquartz/xpr/appledristr.h +++ b/xorg-server/hw/xquartz/xpr/appledristr.h @@ -42,209 +42,225 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define APPLEDRINAME "Apple-DRI" -#define APPLE_DRI_MAJOR_VERSION 1 /* current version numbers */ +#define APPLE_DRI_MAJOR_VERSION 1 /* current version numbers */ #define APPLE_DRI_MINOR_VERSION 0 #define APPLE_DRI_PATCH_VERSION 0 -typedef struct _AppleDRIQueryVersion { - CARD8 reqType; /* always DRIReqCode */ - CARD8 driReqType; /* always X_DRIQueryVersion */ - CARD16 length B16; +typedef struct _AppleDRIQueryVersion +{ + CARD8 reqType; /* always DRIReqCode */ + CARD8 driReqType; /* always X_DRIQueryVersion */ + CARD16 length B16; } xAppleDRIQueryVersionReq; #define sz_xAppleDRIQueryVersionReq 4 -typedef struct { - BYTE type; /* X_Reply */ - BOOL pad1; - CARD16 sequenceNumber B16; - CARD32 length B32; - CARD16 majorVersion B16; /* major version of DRI protocol */ - CARD16 minorVersion B16; /* minor version of DRI protocol */ - CARD32 patchVersion B32; /* patch version of DRI protocol */ - CARD32 pad3 B32; - CARD32 pad4 B32; - CARD32 pad5 B32; - CARD32 pad6 B32; +typedef struct +{ + BYTE type; /* X_Reply */ + BOOL pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD16 majorVersion B16; /* major version of DRI protocol */ + CARD16 minorVersion B16; /* minor version of DRI protocol */ + CARD32 patchVersion B32; /* patch version of DRI protocol */ + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; + CARD32 pad6 B32; } xAppleDRIQueryVersionReply; #define sz_xAppleDRIQueryVersionReply 32 -typedef struct _AppleDRIQueryDirectRenderingCapable { - CARD8 reqType; /* always DRIReqCode */ - CARD8 driReqType; /* X_DRIQueryDirectRenderingCapable */ - CARD16 length B16; - CARD32 screen B32; +typedef struct _AppleDRIQueryDirectRenderingCapable +{ + CARD8 reqType; /* always DRIReqCode */ + CARD8 driReqType; /* X_DRIQueryDirectRenderingCapable */ + CARD16 length B16; + CARD32 screen B32; } xAppleDRIQueryDirectRenderingCapableReq; #define sz_xAppleDRIQueryDirectRenderingCapableReq 8 -typedef struct { - BYTE type; /* X_Reply */ - BOOL pad1; - CARD16 sequenceNumber B16; - CARD32 length B32; - BOOL isCapable; - BOOL pad2; - BOOL pad3; - BOOL pad4; - CARD32 pad5 B32; - CARD32 pad6 B32; - CARD32 pad7 B32; - CARD32 pad8 B32; - CARD32 pad9 B32; +typedef struct +{ + BYTE type; /* X_Reply */ + BOOL pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + BOOL isCapable; + BOOL pad2; + BOOL pad3; + BOOL pad4; + CARD32 pad5 B32; + CARD32 pad6 B32; + CARD32 pad7 B32; + CARD32 pad8 B32; + CARD32 pad9 B32; } xAppleDRIQueryDirectRenderingCapableReply; #define sz_xAppleDRIQueryDirectRenderingCapableReply 32 -typedef struct _AppleDRIAuthConnection { - CARD8 reqType; /* always DRIReqCode */ - CARD8 driReqType; /* always X_DRICloseConnection */ - CARD16 length B16; - CARD32 screen B32; - CARD32 magic B32; +typedef struct _AppleDRIAuthConnection +{ + CARD8 reqType; /* always DRIReqCode */ + CARD8 driReqType; /* always X_DRICloseConnection */ + CARD16 length B16; + CARD32 screen B32; + CARD32 magic B32; } xAppleDRIAuthConnectionReq; #define sz_xAppleDRIAuthConnectionReq 12 -typedef struct { - BYTE type; - BOOL pad1; - CARD16 sequenceNumber B16; - CARD32 length B32; - CARD32 authenticated B32; - CARD32 pad2 B32; - CARD32 pad3 B32; - CARD32 pad4 B32; - CARD32 pad5 B32; - CARD32 pad6 B32; +typedef struct +{ + BYTE type; + BOOL pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 authenticated B32; + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; + CARD32 pad6 B32; } xAppleDRIAuthConnectionReply; #define zx_xAppleDRIAuthConnectionReply 32 -typedef struct _AppleDRICreateSurface { - CARD8 reqType; /* always DRIReqCode */ - CARD8 driReqType; /* always X_DRICreateSurface */ - CARD16 length B16; - CARD32 screen B32; - CARD32 drawable B32; - CARD32 client_id B32; +typedef struct _AppleDRICreateSurface +{ + CARD8 reqType; /* always DRIReqCode */ + CARD8 driReqType; /* always X_DRICreateSurface */ + CARD16 length B16; + CARD32 screen B32; + CARD32 drawable B32; + CARD32 client_id B32; } xAppleDRICreateSurfaceReq; #define sz_xAppleDRICreateSurfaceReq 16 -typedef struct { - BYTE type; /* X_Reply */ - BOOL pad1; - CARD16 sequenceNumber B16; - CARD32 length B32; - CARD32 key_0 B32; - CARD32 key_1 B32; - CARD32 uid B32; - CARD32 pad4 B32; - CARD32 pad5 B32; - CARD32 pad6 B32; +typedef struct +{ + BYTE type; /* X_Reply */ + BOOL pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 key_0 B32; + CARD32 key_1 B32; + CARD32 uid B32; + CARD32 pad4 B32; + CARD32 pad5 B32; + CARD32 pad6 B32; } xAppleDRICreateSurfaceReply; #define sz_xAppleDRICreateSurfaceReply 32 -typedef struct _AppleDRIDestroySurface { - CARD8 reqType; /* always DRIReqCode */ - CARD8 driReqType; /* always X_DRIDestroySurface */ - CARD16 length B16; - CARD32 screen B32; - CARD32 drawable B32; +typedef struct _AppleDRIDestroySurface +{ + CARD8 reqType; /* always DRIReqCode */ + CARD8 driReqType; /* always X_DRIDestroySurface */ + CARD16 length B16; + CARD32 screen B32; + CARD32 drawable B32; } xAppleDRIDestroySurfaceReq; #define sz_xAppleDRIDestroySurfaceReq 12 -typedef struct _AppleDRINotify { - BYTE type; /* always eventBase + event type */ - BYTE kind; - CARD16 sequenceNumber B16; - CARD32 time B32; /* time of change */ - CARD32 pad1 B32; - CARD32 arg B32; - CARD32 pad3 B32; - CARD32 pad4 B32; - CARD32 pad5 B32; - CARD32 pad6 B32; +typedef struct _AppleDRINotify +{ + BYTE type; /* always eventBase + event type */ + BYTE kind; + CARD16 sequenceNumber B16; + CARD32 time B32; /* time of change */ + CARD32 pad1 B32; + CARD32 arg B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; + CARD32 pad6 B32; } xAppleDRINotifyEvent; #define sz_xAppleDRINotifyEvent 32 -typedef struct { - CARD8 reqType; - CARD8 driReqType; - CARD16 length B16; - CARD32 screen B32; - CARD32 drawable B32; - BOOL doubleSwap; - CARD8 pad1, pad2, pad3; +typedef struct +{ + CARD8 reqType; + CARD8 driReqType; + CARD16 length B16; + CARD32 screen B32; + CARD32 drawable B32; + BOOL doubleSwap; + CARD8 pad1, pad2, pad3; } xAppleDRICreateSharedBufferReq; #define sz_xAppleDRICreateSharedBufferReq 16 -typedef struct { - BYTE type; - BYTE data1; - CARD16 sequenceNumber B16; - CARD32 length B32; - CARD32 stringLength B32; /* 0 on error */ - CARD32 width B32; - CARD32 height B32; - CARD32 pad1 B32; - CARD32 pad2 B32; - CARD32 pad3 B32; +typedef struct +{ + BYTE type; + BYTE data1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 stringLength B32; /* 0 on error */ + CARD32 width B32; + CARD32 height B32; + CARD32 pad1 B32; + CARD32 pad2 B32; + CARD32 pad3 B32; } xAppleDRICreateSharedBufferReply; #define sz_xAppleDRICreateSharedBufferReply 32 -typedef struct { - CARD8 reqType; - CARD8 driReqType; - CARD16 length B16; - CARD32 screen B32; - CARD32 drawable B32; +typedef struct +{ + CARD8 reqType; + CARD8 driReqType; + CARD16 length B16; + CARD32 screen B32; + CARD32 drawable B32; } xAppleDRISwapBuffersReq; #define sz_xAppleDRISwapBuffersReq 12 -typedef struct { - CARD8 reqType; /*1*/ - CARD8 driReqType; /*2*/ - CARD16 length B16; /*4*/ - CARD32 screen B32; /*8*/ - CARD32 drawable B32; /*12*/ +typedef struct +{ + CARD8 reqType; /*1 */ + CARD8 driReqType; /*2 */ + CARD16 length B16; /*4 */ + CARD32 screen B32; /*8 */ + CARD32 drawable B32; /*12 */ } xAppleDRICreatePixmapReq; #define sz_xAppleDRICreatePixmapReq 12 -typedef struct { - BYTE type; /*1*/ - BOOL pad1; /*2*/ - CARD16 sequenceNumber B16; /*4*/ - CARD32 length B32; /*8*/ - CARD32 width B32; /*12*/ - CARD32 height B32; /*16*/ - CARD32 pitch B32; /*20*/ - CARD32 bpp B32; /*24*/ - CARD32 size B32; /*28*/ - CARD32 stringLength B32; /*32*/ +typedef struct +{ + BYTE type; /*1 */ + BOOL pad1; /*2 */ + CARD16 sequenceNumber B16; /*4 */ + CARD32 length B32; /*8 */ + CARD32 width B32; /*12 */ + CARD32 height B32; /*16 */ + CARD32 pitch B32; /*20 */ + CARD32 bpp B32; /*24 */ + CARD32 size B32; /*28 */ + CARD32 stringLength B32; /*32 */ } xAppleDRICreatePixmapReply; #define sz_xAppleDRICreatePixmapReply 32 -typedef struct { - CARD8 reqType; /*1*/ - CARD8 driReqType; /*2*/ - CARD16 length B16; /*4*/ - CARD32 drawable B32; /*8*/ +typedef struct +{ + CARD8 reqType; /*1 */ + CARD8 driReqType; /*2 */ + CARD16 length B16; /*4 */ + CARD32 drawable B32; /*8 */ } xAppleDRIDestroyPixmapReq; #define sz_xAppleDRIDestroyPixmapReq 8 #ifdef _APPLEDRI_SERVER_ -void AppleDRISendEvent ( +void AppleDRISendEvent( #if NeedFunctionPrototypes - int /* type */, - unsigned int /* mask */, - int /* which */, - int /* arg */ + int /* type */ , + unsigned int /* mask */ , + int /* which */ , + int /* arg */ #endif -); + ); #endif /* _APPLEDRI_SERVER_ */ #endif /* _APPLEDRISTR_H_ */ diff --git a/xorg-server/hw/xwin/man/XWinrc.man b/xorg-server/hw/xwin/man/XWinrc.man index e4c454fba..71d8dad23 100644 --- a/xorg-server/hw/xwin/man/XWinrc.man +++ b/xorg-server/hw/xwin/man/XWinrc.man @@ -88,15 +88,15 @@ this may be useful if you want no dialogs. This instruction defines a menu and asigns a \fIMenu_Name\fP to it. \fIMenu_Item_Line\fP are lines of any of the following types: .TP 8 -.B \t SEPARATOR +.B SEPARATOR .TP 8 -.B \t \fIItem_Label\fP EXEC \fICommand\fP +.B \fIItem_Label\fP EXEC \fICommand\fP .TP 8 -.B \t \fIItem_Label\fP MENU \fIpreviously-defined-menu-name\fP +.B \fIItem_Label\fP MENU \fIpreviously-defined-menu-name\fP .TP 8 -.B \t \fIItem_Label\fP ALWAYSONTOP +.B \fIItem_Label\fP ALWAYSONTOP .TP 8 -.B \t \fIItem_Label\fP RELOAD +.B \fIItem_Label\fP RELOAD .br The \fIItem_Label\fP is the string that is written in the menu item. .br diff --git a/xorg-server/include/eventstr.h b/xorg-server/include/eventstr.h index 2de077fd2..4d836fb14 100644 --- a/xorg-server/include/eventstr.h +++ b/xorg-server/include/eventstr.h @@ -153,6 +153,7 @@ struct _DeviceChangedEvent uint32_t resolution; /**< Resolution counts/m */ uint8_t mode; /**< Relative or Absolute */ Atom name; /**< Axis name */ + ScrollInfo scroll; /**< Smooth scrolling info */ } valuators[MAX_VALUATORS]; struct { diff --git a/xorg-server/include/exevents.h b/xorg-server/include/exevents.h index 4fe6c61a9..720fb2e5a 100644 --- a/xorg-server/include/exevents.h +++ b/xorg-server/include/exevents.h @@ -322,8 +322,7 @@ extern int XIShouldNotify(ClientPtr client, DeviceIntPtr dev); extern void -XISendDeviceChangedEvent(DeviceIntPtr device, DeviceIntPtr master, - DeviceChangedEvent *dce); +XISendDeviceChangedEvent(DeviceIntPtr device, DeviceChangedEvent *dce); extern int XISetEventMask(DeviceIntPtr dev, WindowPtr win, ClientPtr client, diff --git a/xorg-server/include/input.h b/xorg-server/include/input.h index b7de5ca3d..4eee47ce4 100644 --- a/xorg-server/include/input.h +++ b/xorg-server/include/input.h @@ -427,7 +427,8 @@ extern _X_EXPORT void FreeEventList(InternalEvent *list, int num_events); extern void CreateClassesChangedEvent(InternalEvent *event, DeviceIntPtr master, DeviceIntPtr slave, - int type); + int flags); + extern InternalEvent * UpdateFromMaster( InternalEvent *events, DeviceIntPtr pDev, @@ -597,6 +598,10 @@ extern _X_EXPORT void valuator_mask_copy(ValuatorMask *dest, extern _X_EXPORT int valuator_mask_get(const ValuatorMask *mask, int valnum); extern _X_EXPORT double valuator_mask_get_double(const ValuatorMask *mask, int valnum); +extern _X_EXPORT Bool valuator_mask_fetch(const ValuatorMask *mask, + int valnum, int *val); +extern _X_EXPORT Bool valuator_mask_fetch_double(const ValuatorMask *mask, + int valnum, double *val); /* InputOption handling interface */ extern _X_EXPORT InputOption* input_option_new(InputOption *list, const char *key, const char *value); diff --git a/xorg-server/include/inputstr.h b/xorg-server/include/inputstr.h index 9d4108ef5..7a1554075 100644 --- a/xorg-server/include/inputstr.h +++ b/xorg-server/include/inputstr.h @@ -621,11 +621,4 @@ static inline WindowPtr DeepestSpriteWin(SpritePtr sprite) return sprite->spriteTrace[sprite->spriteTraceGood - 1]; } -struct _InputOption { - char *key; - char *value; - struct _InputOption *next; -}; - - #endif /* INPUTSTRUCT_H */ diff --git a/xorg-server/include/list.h b/xorg-server/include/list.h index 7825dce52..4706e178b 100644 --- a/xorg-server/include/list.h +++ b/xorg-server/include/list.h @@ -438,4 +438,16 @@ list_is_empty(struct list *head) nt_list_init(__e, _member); \ } while(0) +/** + * DO NOT USE THIS. + * This is a remainder of the xfree86 DDX attempt of having a set of generic + * list functions. Unfortunately, the xf86OptionRec uses it and we can't + * easily get rid of it. Do not use for new code. + */ +typedef struct generic_list_rec +{ + void *next; +} +GenericListRec, *GenericListPtr, *glp; + #endif diff --git a/xorg-server/include/optionstr.h b/xorg-server/include/optionstr.h new file mode 100644 index 000000000..a71d245fa --- /dev/null +++ b/xorg-server/include/optionstr.h @@ -0,0 +1,14 @@ +#ifndef OPTIONSTR_H_ +#define OPTIONSTR_H_ +#include "list.h" + + +struct _InputOption { + GenericListRec list; + char *opt_name; + char *opt_val; + int opt_used; + char *opt_comment; +}; + +#endif /* INPUTSTRUCT_H */ diff --git a/xorg-server/man/Xserver.man b/xorg-server/man/Xserver.man index 02cca5263..0cd9b941c 100644 --- a/xorg-server/man/Xserver.man +++ b/xorg-server/man/Xserver.man @@ -100,6 +100,12 @@ specifies a file which contains a collection of authorization records used to authenticate access. See also the \fIxdm\fP(1) and \fIXsecurity\fP(__miscmansuffix__) manual pages. .TP 8 +.BI \-background\ none +Asks the driver not to clear the background on startup, if the driver supports that. +May be useful for smooth transition with eg. fbdev driver. +For security reasons this is not the default as the screen contents might +show a previous user session. +.TP 8 .B \-br sets the default root window to solid black instead of the standard root weave pattern. This is the default unless -retro or -wr is specified. diff --git a/xorg-server/mi/mieq.c b/xorg-server/mi/mieq.c index 7cc0e7c51..3d51a567b 100644 --- a/xorg-server/mi/mieq.c +++ b/xorg-server/mi/mieq.c @@ -59,7 +59,12 @@ in this Software without prior written authorization from The Open Group. # include <X11/extensions/dpmsconst.h> #endif -#define QUEUE_SIZE 512 +/* Maximum size should be initial size multiplied by a power of 2 */ +#define QUEUE_INITIAL_SIZE 256 +#define QUEUE_RESERVED_SIZE 64 +#define QUEUE_MAXIMUM_SIZE 4096 +#define QUEUE_DROP_BACKTRACE_FREQUENCY 100 +#define QUEUE_DROP_BACKTRACE_MAX 10 #define EnqueueScreen(dev) dev->spriteInfo->sprite->pEnqueueScreen #define DequeueScreen(dev) dev->spriteInfo->sprite->pDequeueScreen @@ -74,7 +79,9 @@ typedef struct _EventQueue { HWEventQueueType head, tail; /* long for SetInputCheck */ CARD32 lastEventTime; /* to avoid time running backwards */ int lastMotion; /* device ID if last event motion? */ - EventRec events[QUEUE_SIZE]; /* static allocation for signals */ + EventRec *events; /* our queue as an array */ + size_t nevents; /* the number of buckets in our queue */ + size_t dropped; /* counter for number of consecutive dropped events */ mieqHandler handlers[128]; /* custom event handler */ } EventQueueRec, *EventQueuePtr; @@ -99,25 +106,87 @@ static inline void wait_for_server_init(void) { } #endif +static size_t +mieqNumEnqueued(EventQueuePtr eventQueue) { + size_t n_enqueued = 0; + if (eventQueue->nevents) { + /* % is not well-defined with negative numbers... sigh */ + n_enqueued = eventQueue->tail - eventQueue->head + eventQueue->nevents; + if (n_enqueued >= eventQueue->nevents) + n_enqueued -= eventQueue->nevents; + } + return n_enqueued; +} + +/* Pre-condition: Called with miEventQueueMutex held */ +static Bool +mieqGrowQueue(EventQueuePtr eventQueue, size_t new_nevents) { + size_t i, n_enqueued, first_hunk; + EventRec *new_events; + + if (!eventQueue) { + ErrorF("[mi] mieqGrowQueue called with a NULL eventQueue\n"); + return FALSE; + } + + if (new_nevents <= eventQueue->nevents) + return FALSE; + + new_events = calloc(new_nevents, sizeof(EventRec)); + if (new_events == NULL) { + ErrorF("[mi] mieqGrowQueue memory allocation error.\n"); + return FALSE; + } + + n_enqueued = mieqNumEnqueued(eventQueue); + + /* We block signals, so an mieqEnqueue triggered by SIGIO does not + * write to our queue as we are modifying it. + */ + OsBlockSignals(); + + /* First copy the existing events */ + first_hunk = eventQueue->nevents - eventQueue->head; + memcpy(new_events, + &eventQueue->events[eventQueue->head], + first_hunk * sizeof(EventRec)); + memcpy(&new_events[first_hunk], + eventQueue->events, + eventQueue->head * sizeof(EventRec)); + + /* Initialize the new portion */ + for (i = eventQueue->nevents; i < new_nevents; i++) { + InternalEvent* evlist = InitEventList(1); + if (!evlist) { + size_t j; + for (j = 0; j < i; j++) + FreeEventList(new_events[j].events, 1); + free(new_events); + OsReleaseSignals(); + return FALSE; + } + new_events[i].events = evlist; + } + + /* And update our record */ + eventQueue->tail = n_enqueued; + eventQueue->head = 0; + eventQueue->nevents = new_nevents; + free(eventQueue->events); + eventQueue->events = new_events; + + OsReleaseSignals(); + return TRUE; +} + Bool mieqInit(void) { - int i; - - miEventQueue.head = miEventQueue.tail = 0; + memset(&miEventQueue, 0, sizeof(miEventQueue)); miEventQueue.lastEventTime = GetTimeInMillis (); - miEventQueue.lastMotion = FALSE; - for (i = 0; i < 128; i++) - miEventQueue.handlers[i] = NULL; - for (i = 0; i < QUEUE_SIZE; i++) - { - if (miEventQueue.events[i].events == NULL) { - InternalEvent* evlist = InitEventList(1); - if (!evlist) - FatalError("Could not allocate event queue.\n"); - miEventQueue.events[i].events = evlist; - } - } + + if(!mieqGrowQueue(&miEventQueue, QUEUE_INITIAL_SIZE)) + FatalError("Could not allocate event queue.\n"); SetInputCheck(&miEventQueue.head, &miEventQueue.tail); return TRUE; @@ -127,13 +196,34 @@ void mieqFini(void) { int i; - for (i = 0; i < QUEUE_SIZE; i++) + for (i = 0; i < miEventQueue.nevents; i++) { if (miEventQueue.events[i].events != NULL) { FreeEventList(miEventQueue.events[i].events, 1); miEventQueue.events[i].events = NULL; } } + free(miEventQueue.events); +} + +/* This function will determine if the given event is allowed to used the reserved + * queue space. + */ +static Bool +mieqReservedCandidate(InternalEvent *e) { + switch(e->any.type) { + case ET_KeyRelease: + case ET_ButtonRelease: +#if XFreeXDGA + case ET_DGAEvent: +#endif + case ET_RawKeyRelease: + case ET_RawButtonRelease: + case ET_XQuartz: + return TRUE; + default: + return FALSE; + } } /* @@ -151,6 +241,7 @@ mieqEnqueue(DeviceIntPtr pDev, InternalEvent *e) int isMotion = 0; int evlen; Time time; + size_t n_enqueued; #ifdef XQUARTZ wait_for_server_init(); @@ -159,32 +250,40 @@ mieqEnqueue(DeviceIntPtr pDev, InternalEvent *e) verify_internal_event(e); + n_enqueued = mieqNumEnqueued(&miEventQueue); + /* avoid merging events from different devices */ if (e->any.type == ET_Motion) isMotion = pDev->id; if (isMotion && isMotion == miEventQueue.lastMotion && oldtail != miEventQueue.head) { - oldtail = (oldtail - 1) % QUEUE_SIZE; - } - else { - static int stuck = 0; + oldtail = (oldtail - 1) % miEventQueue.nevents; + } else if ((n_enqueued + 1 == miEventQueue.nevents) || + ((n_enqueued + 1 >= miEventQueue.nevents - QUEUE_RESERVED_SIZE) && !mieqReservedCandidate(e))) { /* Toss events which come in late. Usually this means your server's * stuck in an infinite loop somewhere, but SIGIO is still getting - * handled. */ - if (((oldtail + 1) % QUEUE_SIZE) == miEventQueue.head) { - if (!stuck) { - ErrorF("[mi] EQ overflowing. The server is probably stuck " - "in an infinite loop.\n"); - xorg_backtrace(); - stuck = 1; + * handled. + */ + miEventQueue.dropped++; + if (miEventQueue.dropped == 1) { + ErrorF("[mi] EQ overflowing. Additional events will be discarded until existing events are processed.\n"); + xorg_backtrace(); + ErrorF("[mi] These backtraces from mieqEnqueue may point to a culprit higher up the stack.\n"); + ErrorF("[mi] mieq is *NOT* the cause. It is a victim.\n"); + } else if (miEventQueue.dropped % QUEUE_DROP_BACKTRACE_FREQUENCY == 0 && + miEventQueue.dropped / QUEUE_DROP_BACKTRACE_FREQUENCY <= QUEUE_DROP_BACKTRACE_MAX) { + ErrorF("[mi] EQ overflow continuing. %lu events have been dropped.\n", miEventQueue.dropped); + if (miEventQueue.dropped / QUEUE_DROP_BACKTRACE_FREQUENCY == QUEUE_DROP_BACKTRACE_MAX) { + ErrorF("[mi] No further overflow reports will be reported until the clog is cleared.\n"); } + xorg_backtrace(); + } + #ifdef XQUARTZ - pthread_mutex_unlock(&miEventQueueMutex); + pthread_mutex_unlock(&miEventQueueMutex); #endif - return; - } - stuck = 0; + return; } evlen = e->any.length; @@ -203,7 +302,7 @@ mieqEnqueue(DeviceIntPtr pDev, InternalEvent *e) miEventQueue.events[oldtail].pDev = pDev; miEventQueue.lastMotion = isMotion; - miEventQueue.tail = (oldtail + 1) % QUEUE_SIZE; + miEventQueue.tail = (oldtail + 1) % miEventQueue.nevents; #ifdef XQUARTZ pthread_mutex_unlock(&miEventQueueMutex); #endif @@ -437,11 +536,28 @@ mieqProcessInputEvents(void) static InternalEvent event; DeviceIntPtr dev = NULL, master = NULL; + size_t n_enqueued; #ifdef XQUARTZ pthread_mutex_lock(&miEventQueueMutex); #endif - + + /* Grow our queue if we are reaching capacity: < 2 * QUEUE_RESERVED_SIZE remaining */ + n_enqueued = mieqNumEnqueued(&miEventQueue); + if (n_enqueued >= (miEventQueue.nevents - (2 * QUEUE_RESERVED_SIZE)) && + miEventQueue.nevents < QUEUE_MAXIMUM_SIZE) { + ErrorF("[mi] Increasing EQ size to %lu to prevent dropped events.\n", miEventQueue.nevents << 1); + if (!mieqGrowQueue(&miEventQueue, miEventQueue.nevents << 1)) { + ErrorF("[mi] Increasing the size of EQ failed.\n"); + } + } + + if (miEventQueue.dropped) { + ErrorF("[mi] EQ processing has resumed after %lu dropped events.\n", miEventQueue.dropped); + ErrorF("[mi] This may be caused my a misbehaving driver monopolizing the server's resources.\n"); + miEventQueue.dropped = 0; + } + while (miEventQueue.head != miEventQueue.tail) { e = &miEventQueue.events[miEventQueue.head]; @@ -449,7 +565,7 @@ mieqProcessInputEvents(void) dev = e->pDev; screen = e->pScreen; - miEventQueue.head = (miEventQueue.head + 1) % QUEUE_SIZE; + miEventQueue.head = (miEventQueue.head + 1) % miEventQueue.nevents; #ifdef XQUARTZ pthread_mutex_unlock(&miEventQueueMutex); diff --git a/xorg-server/randr/rrproperty.c b/xorg-server/randr/rrproperty.c index 6ed24d3aa..d0a90203b 100644 --- a/xorg-server/randr/rrproperty.c +++ b/xorg-server/randr/rrproperty.c @@ -549,18 +549,31 @@ int ProcRRDeleteOutputProperty (ClientPtr client) { REQUEST(xRRDeleteOutputPropertyReq); - RROutputPtr output; - + RROutputPtr output; + RRPropertyPtr prop; + REQUEST_SIZE_MATCH(xRRDeleteOutputPropertyReq); UpdateCurrentTime(); VERIFY_RR_OUTPUT(stuff->output, output, DixReadAccess); - + if (!ValidAtom(stuff->property)) { client->errorValue = stuff->property; return BadAtom; } + prop = RRQueryOutputProperty(output, stuff->property); + if (!prop) + { + client->errorValue = stuff->property; + return BadName; + } + + if (prop->immutable) + { + client->errorValue = stuff->property; + return BadAccess; + } RRDeleteOutputProperty(output, stuff->property); return Success; diff --git a/xorg-server/render/mipict.c b/xorg-server/render/mipict.c index 61b368472..caa76e396 100644 --- a/xorg-server/render/mipict.c +++ b/xorg-server/render/mipict.c @@ -569,6 +569,64 @@ miRenderPixelToColor (PictFormatPtr format, } } +void +miTriStrip (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int npoints, + xPointFixed *points) +{ + xTriangle *tris, *tri; + int ntri; + + ntri = npoints - 2; + tris = malloc(ntri * sizeof (xTriangle)); + if (!tris) + return; + + for (tri = tris; npoints >= 3; npoints--, points++, tri++) + { + tri->p1 = points[0]; + tri->p2 = points[1]; + tri->p3 = points[2]; + } + CompositeTriangles (op, pSrc, pDst, maskFormat, xSrc, ySrc, ntri, tris); + free(tris); +} + +void +miTriFan (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int npoints, + xPointFixed *points) +{ + xTriangle *tris, *tri; + xPointFixed *first; + int ntri; + + ntri = npoints - 2; + tris = malloc(ntri * sizeof (xTriangle)); + if (!tris) + return; + + first = points++; + for (tri = tris; npoints >= 3; npoints--, points++, tri++) + { + tri->p1 = *first; + tri->p2 = points[0]; + tri->p3 = points[1]; + } + CompositeTriangles (op, pSrc, pDst, maskFormat, xSrc, ySrc, ntri, tris); + free(tris); +} + Bool miPictureInit (ScreenPtr pScreen, PictFormatPtr formats, int nformats) { @@ -602,5 +660,8 @@ miPictureInit (ScreenPtr pScreen, PictFormatPtr formats, int nformats) ps->AddTraps = 0; /* requires DDX support */ ps->AddTriangles = 0; /* requires DDX support */ + ps->TriStrip = miTriStrip; /* converts call to CompositeTriangles */ + ps->TriFan = miTriFan; + return TRUE; } diff --git a/xorg-server/render/mipict.h b/xorg-server/render/mipict.h index f2df601e4..4399a6fad 100644 --- a/xorg-server/render/mipict.h +++ b/xorg-server/render/mipict.h @@ -1,165 +1,185 @@ -/*
- *
- * Copyright © 2000 SuSE, Inc.
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation, and that the name of SuSE not be used in advertising or
- * publicity pertaining to distribution of the software without specific,
- * written prior permission. SuSE makes no representations about the
- * suitability of this software for any purpose. It is provided "as is"
- * without express or implied warranty.
- *
- * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
- * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- * Author: Keith Packard, SuSE, Inc.
- */
-
-#ifndef _MIPICT_H_
-#define _MIPICT_H_
-
-#include "picturestr.h"
-
-#define MI_MAX_INDEXED 256 /* XXX depth must be <= 8 */
-
-#if MI_MAX_INDEXED <= 256
-typedef CARD8 miIndexType;
-#endif
-
-typedef struct _miIndexed {
- Bool color;
- CARD32 rgba[MI_MAX_INDEXED];
- miIndexType ent[32768];
-} miIndexedRec, *miIndexedPtr;
-
-#define miCvtR8G8B8to15(s) ((((s) >> 3) & 0x001f) | \
- (((s) >> 6) & 0x03e0) | \
- (((s) >> 9) & 0x7c00))
-#define miIndexToEnt15(mif,rgb15) ((mif)->ent[rgb15])
-#define miIndexToEnt24(mif,rgb24) miIndexToEnt15(mif,miCvtR8G8B8to15(rgb24))
-
-#define miIndexToEntY24(mif,rgb24) ((mif)->ent[CvtR8G8B8toY15(rgb24)])
-
-extern _X_EXPORT int
-miCreatePicture (PicturePtr pPicture);
-
-extern _X_EXPORT void
-miDestroyPicture (PicturePtr pPicture);
-
-extern _X_EXPORT void
-miDestroyPictureClip (PicturePtr pPicture);
-
-extern _X_EXPORT int
-miChangePictureClip (PicturePtr pPicture,
- int type,
- pointer value,
- int n);
-
-extern _X_EXPORT void
-miChangePicture (PicturePtr pPicture,
- Mask mask);
-
-extern _X_EXPORT void
-miValidatePicture (PicturePtr pPicture,
- Mask mask);
-
-extern _X_EXPORT int
-miChangePictureTransform (PicturePtr pPicture,
- PictTransform *transform);
-
-extern _X_EXPORT int
-miChangePictureFilter (PicturePtr pPicture,
- int filter,
- xFixed *params,
- int nparams);
-
-extern _X_EXPORT void
-miCompositeSourceValidate (PicturePtr pPicture);
-
-extern _X_EXPORT Bool
-miComputeCompositeRegion (RegionPtr pRegion,
- PicturePtr pSrc,
- PicturePtr pMask,
- PicturePtr pDst,
- INT16 xSrc,
- INT16 ySrc,
- INT16 xMask,
- INT16 yMask,
- INT16 xDst,
- INT16 yDst,
- CARD16 width,
- CARD16 height);
-
-extern _X_EXPORT Bool
-miPictureInit (ScreenPtr pScreen, PictFormatPtr formats, int nformats);
-
-extern _X_EXPORT Bool
-miRealizeGlyph (ScreenPtr pScreen,
- GlyphPtr glyph);
-
-extern _X_EXPORT void
-miUnrealizeGlyph (ScreenPtr pScreen,
- GlyphPtr glyph);
-
-extern _X_EXPORT void
-miGlyphs (CARD8 op,
- PicturePtr pSrc,
- PicturePtr pDst,
- PictFormatPtr maskFormat,
- INT16 xSrc,
- INT16 ySrc,
- int nlist,
- GlyphListPtr list,
- GlyphPtr *glyphs);
-
-extern _X_EXPORT void
-miRenderColorToPixel (PictFormatPtr pPict,
- xRenderColor *color,
- CARD32 *pixel);
-
-extern _X_EXPORT void
-miRenderPixelToColor (PictFormatPtr pPict,
- CARD32 pixel,
- xRenderColor *color);
-
-extern _X_EXPORT Bool
-miIsSolidAlpha (PicturePtr pSrc);
-
-extern _X_EXPORT void
-miCompositeRects (CARD8 op,
- PicturePtr pDst,
- xRenderColor *color,
- int nRect,
- xRectangle *rects);
-
-extern _X_EXPORT void
-miTrapezoidBounds (int ntrap, xTrapezoid *traps, BoxPtr box);
-
-extern _X_EXPORT void
-miPointFixedBounds (int npoint, xPointFixed *points, BoxPtr bounds);
-
-extern _X_EXPORT void
-miTriangleBounds (int ntri, xTriangle *tris, BoxPtr bounds);
-
-extern _X_EXPORT Bool
-miInitIndexed (ScreenPtr pScreen,
- PictFormatPtr pFormat);
-
-extern _X_EXPORT void
-miCloseIndexed (ScreenPtr pScreen,
- PictFormatPtr pFormat);
-
-extern _X_EXPORT void
-miUpdateIndexed (ScreenPtr pScreen,
- PictFormatPtr pFormat,
- int ndef,
- xColorItem *pdef);
-
-#endif /* _MIPICT_H_ */
+/* + * + * Copyright © 2000 SuSE, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Keith Packard, SuSE, Inc. + */ + +#ifndef _MIPICT_H_ +#define _MIPICT_H_ + +#include "picturestr.h" + +#define MI_MAX_INDEXED 256 /* XXX depth must be <= 8 */ + +#if MI_MAX_INDEXED <= 256 +typedef CARD8 miIndexType; +#endif + +typedef struct _miIndexed { + Bool color; + CARD32 rgba[MI_MAX_INDEXED]; + miIndexType ent[32768]; +} miIndexedRec, *miIndexedPtr; + +#define miCvtR8G8B8to15(s) ((((s) >> 3) & 0x001f) | \ + (((s) >> 6) & 0x03e0) | \ + (((s) >> 9) & 0x7c00)) +#define miIndexToEnt15(mif,rgb15) ((mif)->ent[rgb15]) +#define miIndexToEnt24(mif,rgb24) miIndexToEnt15(mif,miCvtR8G8B8to15(rgb24)) + +#define miIndexToEntY24(mif,rgb24) ((mif)->ent[CvtR8G8B8toY15(rgb24)]) + +extern _X_EXPORT int +miCreatePicture (PicturePtr pPicture); + +extern _X_EXPORT void +miDestroyPicture (PicturePtr pPicture); + +extern _X_EXPORT void +miDestroyPictureClip (PicturePtr pPicture); + +extern _X_EXPORT int +miChangePictureClip (PicturePtr pPicture, + int type, + pointer value, + int n); + +extern _X_EXPORT void +miChangePicture (PicturePtr pPicture, + Mask mask); + +extern _X_EXPORT void +miValidatePicture (PicturePtr pPicture, + Mask mask); + +extern _X_EXPORT int +miChangePictureTransform (PicturePtr pPicture, + PictTransform *transform); + +extern _X_EXPORT int +miChangePictureFilter (PicturePtr pPicture, + int filter, + xFixed *params, + int nparams); + +extern _X_EXPORT void +miCompositeSourceValidate (PicturePtr pPicture); + +extern _X_EXPORT Bool +miComputeCompositeRegion (RegionPtr pRegion, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height); + +extern _X_EXPORT Bool +miPictureInit (ScreenPtr pScreen, PictFormatPtr formats, int nformats); + +extern _X_EXPORT Bool +miRealizeGlyph (ScreenPtr pScreen, + GlyphPtr glyph); + +extern _X_EXPORT void +miUnrealizeGlyph (ScreenPtr pScreen, + GlyphPtr glyph); + +extern _X_EXPORT void +miGlyphs (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int nlist, + GlyphListPtr list, + GlyphPtr *glyphs); + +extern _X_EXPORT void +miRenderColorToPixel (PictFormatPtr pPict, + xRenderColor *color, + CARD32 *pixel); + +extern _X_EXPORT void +miRenderPixelToColor (PictFormatPtr pPict, + CARD32 pixel, + xRenderColor *color); + +extern _X_EXPORT Bool +miIsSolidAlpha (PicturePtr pSrc); + +extern _X_EXPORT void +miCompositeRects (CARD8 op, + PicturePtr pDst, + xRenderColor *color, + int nRect, + xRectangle *rects); + +extern _X_EXPORT void +miTriStrip (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int npoints, + xPointFixed *points); + +extern _X_EXPORT void +miTriFan (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int npoints, + xPointFixed *points); + +extern _X_EXPORT void +miTrapezoidBounds (int ntrap, xTrapezoid *traps, BoxPtr box); + +extern _X_EXPORT void +miPointFixedBounds (int npoint, xPointFixed *points, BoxPtr bounds); + +extern _X_EXPORT void +miTriangleBounds (int ntri, xTriangle *tris, BoxPtr bounds); + +extern _X_EXPORT Bool +miInitIndexed (ScreenPtr pScreen, + PictFormatPtr pFormat); + +extern _X_EXPORT void +miCloseIndexed (ScreenPtr pScreen, + PictFormatPtr pFormat); + +extern _X_EXPORT void +miUpdateIndexed (ScreenPtr pScreen, + PictFormatPtr pFormat, + int ndef, + xColorItem *pdef); + +#endif /* _MIPICT_H_ */ diff --git a/xorg-server/render/picture.c b/xorg-server/render/picture.c index 5640c4d96..f13459665 100644 --- a/xorg-server/render/picture.c +++ b/xorg-server/render/picture.c @@ -1715,23 +1715,14 @@ CompositeTriStrip (CARD8 op, int npoints, xPointFixed *points) { - xTriangle *tris, *tri; - int ntri; - + PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); + if (npoints < 3) return; - ntri = npoints - 2; - tris = malloc(ntri * sizeof (xTriangle)); - if (!tris) - return; - for (tri = tris; npoints >= 3; npoints--, points++, tri++) - { - tri->p1 = points[0]; - tri->p2 = points[1]; - tri->p3 = points[2]; - } - CompositeTriangles (op, pSrc, pDst, maskFormat, xSrc, ySrc, ntri, tris); - free(tris); + + ValidatePicture (pSrc); + ValidatePicture (pDst); + (*ps->TriStrip) (op, pSrc, pDst, maskFormat, xSrc, ySrc, npoints, points); } void @@ -1744,25 +1735,14 @@ CompositeTriFan (CARD8 op, int npoints, xPointFixed *points) { - xTriangle *tris, *tri; - xPointFixed *first; - int ntri; - + PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); + if (npoints < 3) return; - ntri = npoints - 2; - tris = malloc(ntri * sizeof (xTriangle)); - if (!tris) - return; - first = points++; - for (tri = tris; npoints >= 3; npoints--, points++, tri++) - { - tri->p1 = *first; - tri->p2 = points[0]; - tri->p3 = points[1]; - } - CompositeTriangles (op, pSrc, pDst, maskFormat, xSrc, ySrc, ntri, tris); - free(tris); + + ValidatePicture (pSrc); + ValidatePicture (pDst); + (*ps->TriFan) (op, pSrc, pDst, maskFormat, xSrc, ySrc, npoints, points); } void diff --git a/xorg-server/render/picturestr.h b/xorg-server/render/picturestr.h index 7b7f9112d..1f3f5a433 100644 --- a/xorg-server/render/picturestr.h +++ b/xorg-server/render/picturestr.h @@ -260,6 +260,24 @@ typedef void (*TrianglesProcPtr) (CARD8 op, int ntri, xTriangle *tris); +typedef void (*TriStripProcPtr) (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int npoint, + xPointFixed *points); + +typedef void (*TriFanProcPtr) (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int npoint, + xPointFixed *points); + typedef Bool (*InitIndexedProcPtr) (ScreenPtr pScreen, PictFormatPtr pFormat); @@ -348,6 +366,9 @@ typedef struct _PictureScreen { RealizeGlyphProcPtr RealizeGlyph; UnrealizeGlyphProcPtr UnrealizeGlyph; +#define PICTURE_SCREEN_VERSION 2 + TriStripProcPtr TriStrip; + TriFanProcPtr TriFan; } PictureScreenRec, *PictureScreenPtr; extern _X_EXPORT DevPrivateKeyRec PictureScreenPrivateKeyRec; diff --git a/xorg-server/test/input.c b/xorg-server/test/input.c index bc41c226d..5b4c8c193 100644 --- a/xorg-server/test/input.c +++ b/xorg-server/test/input.c @@ -40,6 +40,7 @@ #include "dixgrabs.h" #include "eventstr.h" #include "inpututils.h" +#include "mi.h" #include "assert.h" /** @@ -1199,14 +1200,19 @@ static void dix_input_valuator_masks(void) assert(valuator_mask_num_valuators(mask) == num_vals); for (i = 0; i < nvaluators; i++) { + double val; if (i < first_val || i >= first_val + num_vals) + { assert(!valuator_mask_isset(mask, i)); - else + assert(!valuator_mask_fetch_double(mask, i, &val)); + } else { assert(valuator_mask_isset(mask, i)); assert(valuator_mask_get(mask, i) == val_ranged[i - first_val]); assert(valuator_mask_get_double(mask, i) == val_ranged[i - first_val]); + assert(valuator_mask_fetch_double(mask, i, &val)); + assert(val_ranged[i - first_val] == val); } } @@ -1218,10 +1224,18 @@ static void dix_input_valuator_masks(void) for (i = 0; i < nvaluators; i++) { + double a, b; assert(valuator_mask_isset(mask, i) == valuator_mask_isset(copy, i)); + + if (!valuator_mask_isset(mask, i)) + continue; + assert(valuator_mask_get(mask, i) == valuator_mask_get(copy, i)); assert(valuator_mask_get_double(mask, i) == valuator_mask_get_double(copy, i)); + assert(valuator_mask_fetch_double(mask, i, &a)); + assert(valuator_mask_fetch_double(copy, i, &b)); + assert(a == b); } valuator_mask_free(&mask); @@ -1467,8 +1481,6 @@ _test_double_fp16_values(double orig_d) { FP1616 first_fp16, final_fp16; double final_d; - char first_fp16_s[64]; - char final_fp16_s[64]; if (orig_d > 0x7FFF) { printf("Test out of range\n"); @@ -1479,10 +1491,15 @@ _test_double_fp16_values(double orig_d) final_d = fp1616_to_double(first_fp16); final_fp16 = double_to_fp1616(final_d); - snprintf(first_fp16_s, sizeof(first_fp16_s), "%d + %u * 2^-16", (first_fp16 & 0xffff0000) >> 16, first_fp16 & 0xffff); - snprintf(final_fp16_s, sizeof(final_fp16_s), "%d + %u * 2^-16", (final_fp16 & 0xffff0000) >> 16, final_fp16 & 0xffff); - - printf("FP16: original double: %f first fp16: %s, re-encoded double: %f, final fp16: %s\n", orig_d, first_fp16_s, final_d, final_fp16_s); + /* { + * char first_fp16_s[64]; + * char final_fp16_s[64]; + * snprintf(first_fp16_s, sizeof(first_fp16_s), "%d + %u * 2^-16", (first_fp16 & 0xffff0000) >> 16, first_fp16 & 0xffff); + * snprintf(final_fp16_s, sizeof(final_fp16_s), "%d + %u * 2^-16", (final_fp16 & 0xffff0000) >> 16, final_fp16 & 0xffff); + * + * printf("FP16: original double: %f first fp16: %s, re-encoded double: %f, final fp16: %s\n", orig_d, first_fp16_s, final_d, final_fp16_s); + * } + */ /* since we lose precision, we only do rough range testing */ assert(final_d > orig_d - 0.1); @@ -1590,6 +1607,73 @@ dix_double_fp_conversion(void) } } +/* The mieq test verifies that events added to the queue come out in the same + * order that they went in. + */ +static uint32_t mieq_test_event_last_processed; + +static void +mieq_test_event_handler(int screenNum, InternalEvent *ie, DeviceIntPtr dev) { + RawDeviceEvent *e = (RawDeviceEvent *)ie; + + assert(e->type == ET_RawMotion); + assert(e->flags > mieq_test_event_last_processed); + mieq_test_event_last_processed = e->flags; +} + +static void _mieq_test_generate_events(uint32_t start, uint32_t count) { + count += start; + while (start < count) { + RawDeviceEvent e = {0}; + e.header = ET_Internal; + e.type = ET_RawMotion; + e.length = sizeof(e); + e.time = GetTimeInMillis(); + e.flags = start; + + mieqEnqueue(NULL, (InternalEvent*)&e); + + start++; + } +} + +#define mieq_test_generate_events(c) { _mieq_test_generate_events(next, c); next += c; } + +static void +mieq_test(void) { + uint32_t next = 1; + + mieq_test_event_last_processed = 0; + mieqInit(); + mieqSetHandler(ET_RawMotion, mieq_test_event_handler); + + /* Enough to fit the buffer but trigger a grow */ + mieq_test_generate_events(180); + + /* We should resize to 512 now */ + mieqProcessInputEvents(); + + /* Some should now get dropped */ + mieq_test_generate_events(500); + + /* Tell us how many got dropped, 1024 now */ + mieqProcessInputEvents(); + + /* Now make it 2048 */ + mieq_test_generate_events(900); + mieqProcessInputEvents(); + + /* Now make it 4096 (max) */ + mieq_test_generate_events(1950); + mieqProcessInputEvents(); + + /* Now overflow one last time with the maximal queue and reach the verbosity limit */ + mieq_test_generate_events(10000); + mieqProcessInputEvents(); + + mieqFini(); +} + int main(int argc, char** argv) { dix_double_fp_conversion(); @@ -1608,6 +1692,7 @@ int main(int argc, char** argv) dix_valuator_alloc(); dix_get_master(); input_option_test(); + mieq_test(); return 0; } diff --git a/xorg-server/test/xi2/protocol-eventconvert.c b/xorg-server/test/xi2/protocol-eventconvert.c index bfa23b51f..ba2d96ad1 100644 --- a/xorg-server/test/xi2/protocol-eventconvert.c +++ b/xorg-server/test/xi2/protocol-eventconvert.c @@ -30,6 +30,7 @@ #include "eventstr.h" #include "eventconvert.h" #include "exevents.h" +#include "inpututils.h" #include <X11/extensions/XI2proto.h> static void test_values_XIRawEvent(RawDeviceEvent *in, xXIRawEvent *out, @@ -104,8 +105,7 @@ static void test_values_XIRawEvent(RawDeviceEvent *in, xXIRawEvent *out, value = (FP3232*)(((unsigned char*)&out[1]) + out->valuators_len * 4); value += nvals; - vi.integral = trunc(in->valuators.data[i]); - vi.frac = in->valuators.data[i] - vi.integral; + vi = double_to_fp3232(in->valuators.data[i]); vo.integral = value->integral; vo.frac = value->frac; @@ -120,8 +120,7 @@ static void test_values_XIRawEvent(RawDeviceEvent *in, xXIRawEvent *out, raw_value = value + bits_set; - vi.integral = trunc(in->valuators.data_raw[i]); - vi.frac = in->valuators.data_raw[i] - vi.integral; + vi = double_to_fp3232(in->valuators.data_raw[i]); vo.integral = raw_value->integral; vo.frac = raw_value->frac; @@ -748,6 +747,26 @@ static void test_values_XIDeviceChangedEvent(DeviceChangedEvent *in, } break; + case XIScrollClass: + { + xXIScrollInfo *s = (xXIScrollInfo*)any; + assert(s->length == + bytes_to_int32(sizeof(xXIScrollInfo))); + + assert(s->sourceid == in->sourceid); + assert(s->number < in->num_valuators); + switch(s->type) + { + case XIScrollTypeVertical: + assert(in->valuators[s->number].scroll.type == SCROLL_TYPE_VERTICAL); + break; + case XIScrollTypeHorizontal: + assert(in->valuators[s->number].scroll.type == SCROLL_TYPE_HORIZONTAL); + break; + } + if (s->flags & XIScrollFlagPreferred) + assert(in->valuators[s->number].scroll.flags & SCROLL_FLAG_PREFERRED); + } default: printf("Invalid class type.\n\n"); assert(1); diff --git a/xorg-server/xkb/xkbActions.c b/xorg-server/xkb/xkbActions.c index 529b53c37..78a3319b8 100644 --- a/xorg-server/xkb/xkbActions.c +++ b/xorg-server/xkb/xkbActions.c @@ -344,15 +344,18 @@ _XkbFilterLockState( XkbSrvInfoPtr xkbi, filter->keycode = keycode; filter->active = 1; filter->filterOthers = 0; - filter->priv = 0; + filter->priv = xkbi->state.locked_mods&pAction->mods.mask; filter->filter = _XkbFilterLockState; filter->upAction = *pAction; - xkbi->state.locked_mods^= pAction->mods.mask; + if (!(filter->upAction.mods.flags&XkbSA_LockNoLock)) + xkbi->state.locked_mods|= pAction->mods.mask; xkbi->setMods = pAction->mods.mask; } else if (filter->keycode==keycode) { filter->active = 0; xkbi->clearMods = filter->upAction.mods.mask; + if (!(filter->upAction.mods.flags&XkbSA_LockNoUnlock)) + xkbi->state.locked_mods&= ~filter->priv; } return 1; } |