diff options
author | marha <marha@users.sourceforge.net> | 2011-12-17 13:43:14 +0100 |
---|---|---|
committer | Marc Haesen <marc@hc-consult.be> | 2011-12-17 13:43:14 +0100 |
commit | abacebe06d9f3d2fe1b7d256bd86cddbfa592a85 (patch) | |
tree | a05bb04105e9dd1cda779071d9ca274b86840c7e | |
parent | 47913e82955ec8e2b1ba4d4b145497dede9163b5 (diff) | |
download | vcxsrv-abacebe06d9f3d2fe1b7d256bd86cddbfa592a85.tar.gz vcxsrv-abacebe06d9f3d2fe1b7d256bd86cddbfa592a85.tar.bz2 vcxsrv-abacebe06d9f3d2fe1b7d256bd86cddbfa592a85.zip |
libX11 libxtrans mesa xserver git update 17 dec 2011
65 files changed, 2414 insertions, 1767 deletions
diff --git a/X11/xtrans/Xtranssock.c b/X11/xtrans/Xtranssock.c index 66f9862b9..dfa41cfe9 100644 --- a/X11/xtrans/Xtranssock.c +++ b/X11/xtrans/Xtranssock.c @@ -458,6 +458,7 @@ TRANS(SocketReopen) (int i _X_UNUSED, int type, int fd, char *port) XtransConnInfo ciptr; int portlen; struct sockaddr *addr; + size_t addrlen; prmsg (3,"SocketReopen(%d,%d,%s)\n", type, fd, port); @@ -488,26 +489,27 @@ TRANS(SocketReopen) (int i _X_UNUSED, int type, int fd, char *port) ciptr->fd = fd; - if ((addr = calloc (1, portlen + 2)) == NULL) { + addrlen = portlen + offsetof(struct sockaddr, sa_data); + if ((addr = calloc (1, addrlen)) == NULL) { prmsg (1, "SocketReopen: malloc(addr) failed\n"); free (ciptr); return NULL; } ciptr->addr = (char *) addr; - ciptr->addrlen = portlen + 2; + ciptr->addrlen = addrlen; - if ((ciptr->peeraddr = calloc (1, portlen + 2)) == NULL) { + if ((ciptr->peeraddr = calloc (1, addrlen)) == NULL) { prmsg (1, "SocketReopen: malloc(portaddr) failed\n"); free (addr); free (ciptr); return NULL; } - ciptr->peeraddrlen = portlen + 2; + ciptr->peeraddrlen = addrlen; /* Initialize ciptr structure as if it were a normally-opened unix socket */ ciptr->flags = TRANS_LOCAL | TRANS_NOUNLINK; #ifdef BSD44SOCKETS - addr->sa_len = portlen + 1; + addr->sa_len = addrlen; #endif addr->sa_family = AF_UNIX; #ifdef HAS_STRLCPY @@ -516,7 +518,7 @@ TRANS(SocketReopen) (int i _X_UNUSED, int type, int fd, char *port) strncpy(addr->sa_data, port, portlen); #endif ciptr->family = AF_UNIX; - memcpy(ciptr->peeraddr, ciptr->addr, sizeof(struct sockaddr)); + memcpy(ciptr->peeraddr, ciptr->addr, addrlen); ciptr->port = rindex(addr->sa_data, ':'); if (ciptr->port == NULL) { if (is_numeric(addr->sa_data)) { diff --git a/libX11/src/QuColors.c b/libX11/src/QuColors.c index 3aa2838ac..237b8bf03 100644 --- a/libX11/src/QuColors.c +++ b/libX11/src/QuColors.c @@ -1,77 +1,99 @@ -/*
-
-Copyright 1986, 1998 The Open Group
-
-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.
-
-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
-OPEN GROUP 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 Open Group 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 Open Group.
-
-*/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include "Xlibint.h"
-
-int
-XQueryColors(
- register Display *dpy,
- Colormap cmap,
- XColor *defs, /* RETURN */
- int ncolors)
-{
- register int i;
- xrgb *color;
- xQueryColorsReply rep;
- long nbytes;
- register xQueryColorsReq *req;
-
- LockDisplay(dpy);
- GetReq(QueryColors, req);
-
- req->cmap = cmap;
- req->length += ncolors; /* each pixel is a CARD32 */
-
- for (i = 0; i < ncolors; i++)
- Data32 (dpy, (long *)&defs[i].pixel, 4L);
- /* XXX this isn't very efficient */
-
- if (_XReply(dpy, (xReply *) &rep, 0, xFalse) != 0) {
- if ((color = (xrgb *)
- Xmalloc((unsigned) (nbytes = (long) ncolors * SIZEOF(xrgb))))) {
-
- _XRead(dpy, (char *) color, nbytes);
-
- for (i = 0; i < ncolors; i++) {
- register XColor *def = &defs[i];
- register xrgb *rgb = &color[i];
- def->red = rgb->red;
- def->green = rgb->green;
- def->blue = rgb->blue;
- def->flags = DoRed | DoGreen | DoBlue;
- }
- Xfree((char *)color);
- }
- else _XEatData(dpy, (unsigned long) nbytes);
- }
- UnlockDisplay(dpy);
- SyncHandle();
- return 1;
-}
-
+/* + +Copyright 1986, 1998 The Open Group + +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. + +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 +OPEN GROUP 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 Open Group 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 Open Group. + +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include "Xlibint.h" + +static void +_XQueryColors( + register Display *dpy, + Colormap cmap, + XColor *defs, /* RETURN */ + int ncolors) +{ + register int i; + xrgb *color; + xQueryColorsReply rep; + long nbytes; + register xQueryColorsReq *req; + + GetReq(QueryColors, req); + + req->cmap = cmap; + SetReqLen(req, ncolors, ncolors); /* each pixel is a CARD32 */ + + for (i = 0; i < ncolors; i++) + Data32 (dpy, (long *)&defs[i].pixel, 4L); + /* XXX this isn't very efficient */ + + if (_XReply(dpy, (xReply *) &rep, 0, xFalse) != 0) { + if ((color = (xrgb *) + Xmalloc((unsigned) (nbytes = (long) ncolors * SIZEOF(xrgb))))) { + + _XRead(dpy, (char *) color, nbytes); + + for (i = 0; i < ncolors; i++) { + register XColor *def = &defs[i]; + register xrgb *rgb = &color[i]; + def->red = rgb->red; + def->green = rgb->green; + def->blue = rgb->blue; + def->flags = DoRed | DoGreen | DoBlue; + } + Xfree((char *)color); + } + else _XEatData(dpy, (unsigned long) nbytes); + } +} + +int +XQueryColors( + register Display * const dpy, + const Colormap cmap, + XColor *defs, /* RETURN */ + int ncolors) +{ + int n; + + if (dpy->bigreq_size > 0) + n = dpy->bigreq_size - (sizeof (xQueryColorsReq) >> 2) - 1; + else + n = dpy->max_request_size - (sizeof (xQueryColorsReq) >> 2); + + LockDisplay(dpy); + while (ncolors >= n) { + _XQueryColors(dpy, cmap, defs, n); + defs += n; + ncolors -= n; + } + if (ncolors > 0) + _XQueryColors(dpy, cmap, defs, ncolors); + UnlockDisplay(dpy); + SyncHandle(); + return 1; +} diff --git a/mesalib/src/gallium/auxiliary/util/u_blit.c b/mesalib/src/gallium/auxiliary/util/u_blit.c index 3a0d7d424..bba0031d7 100644 --- a/mesalib/src/gallium/auxiliary/util/u_blit.c +++ b/mesalib/src/gallium/auxiliary/util/u_blit.c @@ -529,6 +529,7 @@ util_blit_pixels_writemask(struct blit_state *ctx, cso_save_rasterizer(ctx->cso); cso_save_samplers(ctx->cso); cso_save_fragment_sampler_views(ctx->cso); + cso_save_stream_outputs(ctx->cso); cso_save_viewport(ctx->cso); cso_save_framebuffer(ctx->cso); cso_save_fragment_shader(ctx->cso); @@ -546,6 +547,7 @@ util_blit_pixels_writemask(struct blit_state *ctx, cso_set_rasterizer(ctx->cso, &ctx->rasterizer); cso_set_clip(ctx->cso, &ctx->clip); cso_set_vertex_elements(ctx->cso, 2, ctx->velem); + cso_set_stream_outputs(ctx->cso, 0, NULL, 0); /* sampler */ ctx->sampler.normalized_coords = normalized; @@ -622,6 +624,7 @@ util_blit_pixels_writemask(struct blit_state *ctx, cso_restore_clip(ctx->cso); cso_restore_vertex_elements(ctx->cso); cso_restore_vertex_buffers(ctx->cso); + cso_restore_stream_outputs(ctx->cso); pipe_sampler_view_reference(&sampler_view, NULL); if (dst_surface != dst) @@ -722,6 +725,7 @@ util_blit_pixels_tex(struct blit_state *ctx, cso_save_rasterizer(ctx->cso); cso_save_samplers(ctx->cso); cso_save_fragment_sampler_views(ctx->cso); + cso_save_stream_outputs(ctx->cso); cso_save_viewport(ctx->cso); cso_save_framebuffer(ctx->cso); cso_save_fragment_shader(ctx->cso); @@ -737,6 +741,7 @@ util_blit_pixels_tex(struct blit_state *ctx, cso_set_rasterizer(ctx->cso, &ctx->rasterizer); cso_set_clip(ctx->cso, &ctx->clip); cso_set_vertex_elements(ctx->cso, 2, ctx->velem); + cso_set_stream_outputs(ctx->cso, 0, NULL, 0); /* sampler */ ctx->sampler.normalized_coords = normalized; @@ -801,4 +806,5 @@ util_blit_pixels_tex(struct blit_state *ctx, cso_restore_clip(ctx->cso); cso_restore_vertex_elements(ctx->cso); cso_restore_vertex_buffers(ctx->cso); + cso_restore_stream_outputs(ctx->cso); } diff --git a/mesalib/src/gallium/auxiliary/util/u_blitter.c b/mesalib/src/gallium/auxiliary/util/u_blitter.c index f5cc5cb3b..3c501814e 100644 --- a/mesalib/src/gallium/auxiliary/util/u_blitter.c +++ b/mesalib/src/gallium/auxiliary/util/u_blitter.c @@ -63,6 +63,7 @@ struct blitter_context_priv /* Constant state objects. */ /* Vertex shaders. */ void *vs; /**< Vertex shader which passes {pos, generic} to the output.*/ + void *vs_pos_only; /**< Vertex shader which passes pos to the output.*/ /* Fragment shaders. */ /* The shader at index i outputs color to color buffers 0,1,...,i-1. */ @@ -87,15 +88,18 @@ struct blitter_context_priv void *dsa_keep_depth_stencil; void *dsa_keep_depth_write_stencil; + /* Vertex elements states. */ void *velem_state; void *velem_uint_state; void *velem_sint_state; + void *velem_state_readbuf; /* Sampler state. */ void *sampler_state; /* Rasterizer state. */ void *rs_state; + void *rs_discard_state; /* Viewport state. */ struct pipe_viewport_state viewport; @@ -109,6 +113,7 @@ struct blitter_context_priv boolean has_geometry_shader; boolean vertex_has_integers; + boolean has_stream_out; }; static void blitter_draw_rectangle(struct blitter_context *blitter, @@ -148,6 +153,7 @@ struct blitter_context *util_blitter_create(struct pipe_context *pipe) ctx->base.saved_num_sampler_views = ~0; ctx->base.saved_num_sampler_states = ~0; ctx->base.saved_num_vertex_buffers = ~0; + ctx->base.saved_num_so_targets = ~0; ctx->has_geometry_shader = pipe->screen->get_shader_param(pipe->screen, PIPE_SHADER_GEOMETRY, @@ -155,6 +161,9 @@ struct blitter_context *util_blitter_create(struct pipe_context *pipe) ctx->vertex_has_integers = pipe->screen->get_shader_param(pipe->screen, PIPE_SHADER_VERTEX, PIPE_SHADER_CAP_INTEGERS); + ctx->has_stream_out = + pipe->screen->get_param(pipe->screen, + PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS) != 0; /* blend state objects */ memset(&blend, 0, sizeof(blend)); @@ -205,7 +214,12 @@ struct blitter_context *util_blitter_create(struct pipe_context *pipe) rs_state.flatshade = 1; ctx->rs_state = pipe->create_rasterizer_state(pipe, &rs_state); - /* vertex elements state */ + if (ctx->has_stream_out) { + rs_state.rasterizer_discard = 1; + ctx->rs_discard_state = pipe->create_rasterizer_state(pipe, &rs_state); + } + + /* vertex elements states */ memset(&velem[0], 0, sizeof(velem[0]) * 2); for (i = 0; i < 2; i++) { velem[i].src_offset = i * 4 * sizeof(float); @@ -229,9 +243,14 @@ struct blitter_context *util_blitter_create(struct pipe_context *pipe) ctx->velem_uint_state = pipe->create_vertex_elements_state(pipe, 2, &velem[0]); } + if (ctx->has_stream_out) { + velem[0].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; + ctx->velem_state_readbuf = pipe->create_vertex_elements_state(pipe, 1, &velem[0]); + } + /* fragment shaders are created on-demand */ - /* vertex shader */ + /* vertex shaders */ { const uint semantic_names[] = { TGSI_SEMANTIC_POSITION, TGSI_SEMANTIC_GENERIC }; @@ -240,6 +259,20 @@ struct blitter_context *util_blitter_create(struct pipe_context *pipe) util_make_vertex_passthrough_shader(pipe, 2, semantic_names, semantic_indices); } + if (ctx->has_stream_out) { + struct pipe_stream_output_info so; + const uint semantic_names[] = { TGSI_SEMANTIC_POSITION }; + const uint semantic_indices[] = { 0 }; + + memset(&so, 0, sizeof(so)); + so.num_outputs = 1; + so.output[0].register_mask = TGSI_WRITEMASK_XYZW; + so.stride = 4; + + ctx->vs_pos_only = + util_make_vertex_passthrough_shader_with_so(pipe, 1, semantic_names, + semantic_indices, &so); + } /* set invariant vertex coordinates */ for (i = 0; i < 4; i++) @@ -269,12 +302,18 @@ void util_blitter_destroy(struct blitter_context *blitter) pipe->delete_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_write_stencil); pipe->delete_rasterizer_state(pipe, ctx->rs_state); + if (ctx->rs_discard_state) + pipe->delete_rasterizer_state(pipe, ctx->rs_discard_state); pipe->delete_vs_state(pipe, ctx->vs); + if (ctx->vs_pos_only) + pipe->delete_vs_state(pipe, ctx->vs_pos_only); pipe->delete_vertex_elements_state(pipe, ctx->velem_state); if (ctx->vertex_has_integers) { pipe->delete_vertex_elements_state(pipe, ctx->velem_sint_state); pipe->delete_vertex_elements_state(pipe, ctx->velem_uint_state); } + if (ctx->velem_state_readbuf) + pipe->delete_vertex_elements_state(pipe, ctx->velem_state_readbuf); for (i = 0; i < PIPE_MAX_TEXTURE_TYPES; i++) { if (ctx->fs_texfetch_col[i]) @@ -319,6 +358,7 @@ static void blitter_check_saved_vertex_states(struct blitter_context_priv *ctx) ctx->base.saved_velem_state != INVALID_PTR && ctx->base.saved_vs != INVALID_PTR && (!ctx->has_geometry_shader || ctx->base.saved_gs != INVALID_PTR) && + (!ctx->has_stream_out || ctx->base.saved_num_so_targets != ~0) && ctx->base.saved_rs_state != INVALID_PTR); } @@ -354,6 +394,18 @@ static void blitter_restore_vertex_states(struct blitter_context_priv *ctx) ctx->base.saved_gs = INVALID_PTR; } + /* Stream outputs. */ + if (ctx->has_stream_out) { + pipe->set_stream_output_targets(pipe, + ctx->base.saved_num_so_targets, + ctx->base.saved_so_targets, ~0); + + for (i = 0; i < ctx->base.saved_num_so_targets; i++) + pipe_so_target_reference(&ctx->base.saved_so_targets[i], NULL); + + ctx->base.saved_num_so_targets = ~0; + } + /* Rasterizer. */ pipe->bind_rasterizer_state(pipe, ctx->base.saved_rs_state); ctx->base.saved_rs_state = INVALID_PTR; @@ -1160,3 +1212,52 @@ void util_blitter_custom_depth_stencil(struct blitter_context *blitter, blitter_restore_fb_state(ctx); blitter_unset_running_flag(ctx); } + +void util_blitter_copy_buffer(struct blitter_context *blitter, + struct pipe_resource *dst, + unsigned dstx, + struct pipe_resource *src, + unsigned srcx, + unsigned size) +{ + struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter; + struct pipe_context *pipe = ctx->base.pipe; + struct pipe_vertex_buffer vb; + struct pipe_stream_output_target *so_target; + + /* Drivers not capable of Stream Out should not call this function + * in the first place. */ + assert(ctx->has_stream_out); + + /* Some alignment is required. */ + if (srcx % 4 != 0 || dstx % 4 != 0 || size % 16 != 0 || + !ctx->has_stream_out) { + struct pipe_box box; + u_box_1d(srcx, size, &box); + util_resource_copy_region(pipe, dst, 0, dstx, 0, 0, src, 0, &box); + return; + } + + blitter_set_running_flag(ctx); + blitter_check_saved_vertex_states(ctx); + + vb.buffer = src; + vb.buffer_offset = srcx; + vb.stride = 4; + + pipe->set_vertex_buffers(pipe, 1, &vb); + pipe->bind_vertex_elements_state(pipe, ctx->velem_state_readbuf); + pipe->bind_vs_state(pipe, ctx->vs_pos_only); + if (ctx->has_geometry_shader) + pipe->bind_gs_state(pipe, NULL); + pipe->bind_rasterizer_state(pipe, ctx->rs_discard_state); + + so_target = pipe->create_stream_output_target(pipe, dst, dstx, size); + pipe->set_stream_output_targets(pipe, 1, &so_target, 0); + + util_draw_arrays(pipe, PIPE_PRIM_POINTS, 0, size / 16); + + blitter_restore_vertex_states(ctx); + blitter_unset_running_flag(ctx); + pipe_so_target_reference(&so_target, NULL); +} diff --git a/mesalib/src/gallium/auxiliary/util/u_blitter.h b/mesalib/src/gallium/auxiliary/util/u_blitter.h index 3e1457ae0..f605a7e7a 100644 --- a/mesalib/src/gallium/auxiliary/util/u_blitter.h +++ b/mesalib/src/gallium/auxiliary/util/u_blitter.h @@ -104,6 +104,9 @@ struct blitter_context int saved_num_vertex_buffers; struct pipe_vertex_buffer saved_vertex_buffers[PIPE_MAX_ATTRIBS]; + + int saved_num_so_targets; + struct pipe_stream_output_target *saved_so_targets[PIPE_MAX_SO_BUFFERS]; }; /** @@ -131,6 +134,7 @@ struct pipe_context *util_blitter_get_pipe(struct blitter_context *blitter) * - vertex elements * - vertex shader * - geometry shader (if supported) + * - stream output targets (if supported) * - rasterizer state */ @@ -214,6 +218,17 @@ void util_blitter_copy_texture_view(struct blitter_context *blitter, unsigned src_width0, unsigned src_height0); /** + * Copy data from one buffer to another using the Stream Output functionality. + * Some alignment is required, otherwise software fallback is used. + */ +void util_blitter_copy_buffer(struct blitter_context *blitter, + struct pipe_resource *dst, + unsigned dstx, + struct pipe_resource *src, + unsigned srcx, + unsigned size); + +/** * 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 @@ -379,6 +394,20 @@ util_blitter_save_vertex_buffers(struct blitter_context *blitter, num_vertex_buffers); } +static INLINE void +util_blitter_save_so_targets(struct blitter_context *blitter, + int num_targets, + struct pipe_stream_output_target **targets) +{ + unsigned i; + assert(num_targets <= Elements(blitter->saved_so_targets)); + + blitter->saved_num_so_targets = num_targets; + for (i = 0; i < num_targets; i++) + pipe_so_target_reference(&blitter->saved_so_targets[i], + targets[i]); +} + #ifdef __cplusplus } #endif diff --git a/mesalib/src/gallium/auxiliary/util/u_debug_describe.c b/mesalib/src/gallium/auxiliary/util/u_debug_describe.c index 3574accc0..df73ed83e 100644 --- a/mesalib/src/gallium/auxiliary/util/u_debug_describe.c +++ b/mesalib/src/gallium/auxiliary/util/u_debug_describe.c @@ -79,3 +79,13 @@ debug_describe_sampler_view(char* buf, const struct pipe_sampler_view *ptr) debug_describe_resource(res, ptr->texture); util_sprintf(buf, "pipe_sampler_view<%s,%s>", res, util_format_short_name(ptr->format)); } + +void +debug_describe_so_target(char* buf, + const struct pipe_stream_output_target *ptr) +{ + char res[128]; + debug_describe_resource(res, ptr->buffer); + util_sprintf(buf, "pipe_stream_output_target<%s,%u,%u>", res, + ptr->buffer_offset, ptr->buffer_size); +} diff --git a/mesalib/src/gallium/auxiliary/util/u_debug_describe.h b/mesalib/src/gallium/auxiliary/util/u_debug_describe.h index 447e838e4..4f7882b0b 100644 --- a/mesalib/src/gallium/auxiliary/util/u_debug_describe.h +++ b/mesalib/src/gallium/auxiliary/util/u_debug_describe.h @@ -1,49 +1,51 @@ -/**************************************************************************
- *
- * Copyright 2010 Luca Barbieri
- *
- * 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- **************************************************************************/
-
-#ifndef U_DEBUG_DESCRIBE_H_
-#define U_DEBUG_DESCRIBE_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct pipe_reference;
-struct pipe_resource;
-struct pipe_surface;
-struct pipe_sampler_view;
-
-/* a 256-byte buffer is necessary and sufficient */
-void debug_describe_reference(char* buf, const struct pipe_reference*ptr);
-void debug_describe_resource(char* buf, const struct pipe_resource *ptr);
-void debug_describe_surface(char* buf, const struct pipe_surface *ptr);
-void debug_describe_sampler_view(char* buf, const struct pipe_sampler_view *ptr);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* U_DEBUG_DESCRIBE_H_ */
+/************************************************************************** + * + * Copyright 2010 Luca Barbieri + * + * 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef U_DEBUG_DESCRIBE_H_ +#define U_DEBUG_DESCRIBE_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +struct pipe_reference; +struct pipe_resource; +struct pipe_surface; +struct pipe_sampler_view; + +/* a 256-byte buffer is necessary and sufficient */ +void debug_describe_reference(char* buf, const struct pipe_reference*ptr); +void debug_describe_resource(char* buf, const struct pipe_resource *ptr); +void debug_describe_surface(char* buf, const struct pipe_surface *ptr); +void debug_describe_sampler_view(char* buf, const struct pipe_sampler_view *ptr); +void debug_describe_so_target(char* buf, + const struct pipe_stream_output_target *ptr); + +#ifdef __cplusplus +} +#endif + +#endif /* U_DEBUG_DESCRIBE_H_ */ diff --git a/mesalib/src/gallium/auxiliary/util/u_dump_state.c b/mesalib/src/gallium/auxiliary/util/u_dump_state.c index 917d7cd35..91f4aae69 100644 --- a/mesalib/src/gallium/auxiliary/util/u_dump_state.c +++ b/mesalib/src/gallium/auxiliary/util/u_dump_state.c @@ -423,6 +423,7 @@ void util_dump_shader_state(FILE *stream, const struct pipe_shader_state *state) { char str[8192]; + unsigned i; if(!state) { util_dump_null(stream); @@ -437,6 +438,24 @@ util_dump_shader_state(FILE *stream, const struct pipe_shader_state *state) util_dump_string(stream, str); util_dump_member_end(stream); + util_dump_member_begin(stream, "stream_output"); + util_dump_struct_begin(stream, "pipe_stream_output_info"); + util_dump_member(stream, uint, &state->stream_output, num_outputs); + util_dump_member(stream, uint, &state->stream_output, stride); + util_dump_array_begin(stream); + for(i = 0; i < state->stream_output.num_outputs; ++i) { + util_dump_elem_begin(stream); + util_dump_struct_begin(stream, ""); /* anonymous */ + util_dump_member(stream, uint, &state->stream_output.output[i], register_index); + util_dump_member(stream, uint, &state->stream_output.output[i], register_mask); + util_dump_member(stream, uint, &state->stream_output.output[i], output_buffer); + util_dump_struct_end(stream); + util_dump_elem_end(stream); + } + util_dump_array_end(stream); + util_dump_struct_end(stream); + util_dump_member_end(stream); + util_dump_struct_end(stream); } diff --git a/mesalib/src/gallium/auxiliary/util/u_gen_mipmap.c b/mesalib/src/gallium/auxiliary/util/u_gen_mipmap.c index 436a0e424..7cce815be 100644 --- a/mesalib/src/gallium/auxiliary/util/u_gen_mipmap.c +++ b/mesalib/src/gallium/auxiliary/util/u_gen_mipmap.c @@ -1558,6 +1558,7 @@ util_gen_mipmap(struct gen_mipmap_state *ctx, cso_save_rasterizer(ctx->cso); cso_save_samplers(ctx->cso); cso_save_fragment_sampler_views(ctx->cso); + cso_save_stream_outputs(ctx->cso); cso_save_framebuffer(ctx->cso); cso_save_fragment_shader(ctx->cso); cso_save_vertex_shader(ctx->cso); @@ -1572,6 +1573,7 @@ util_gen_mipmap(struct gen_mipmap_state *ctx, cso_set_rasterizer(ctx->cso, &ctx->rasterizer); cso_set_clip(ctx->cso, &ctx->clip); cso_set_vertex_elements(ctx->cso, 2, ctx->velem); + cso_set_stream_outputs(ctx->cso, 0, NULL, 0); set_fragment_shader(ctx, type); set_vertex_shader(ctx); @@ -1688,4 +1690,5 @@ util_gen_mipmap(struct gen_mipmap_state *ctx, cso_restore_viewport(ctx->cso); cso_restore_clip(ctx->cso); cso_restore_vertex_elements(ctx->cso); + cso_restore_stream_outputs(ctx->cso); } diff --git a/mesalib/src/gallium/auxiliary/util/u_inlines.h b/mesalib/src/gallium/auxiliary/util/u_inlines.h index ad47439d0..44283909a 100644 --- a/mesalib/src/gallium/auxiliary/util/u_inlines.h +++ b/mesalib/src/gallium/auxiliary/util/u_inlines.h @@ -1,459 +1,471 @@ -/**************************************************************************
- *
- * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- **************************************************************************/
-
-#ifndef U_INLINES_H
-#define U_INLINES_H
-
-#include "pipe/p_context.h"
-#include "pipe/p_defines.h"
-#include "pipe/p_state.h"
-#include "pipe/p_screen.h"
-#include "util/u_debug.h"
-#include "util/u_debug_describe.h"
-#include "util/u_debug_refcnt.h"
-#include "util/u_atomic.h"
-#include "util/u_box.h"
-#include "util/u_math.h"
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-/*
- * Reference counting helper functions.
- */
-
-
-static INLINE void
-pipe_reference_init(struct pipe_reference *reference, unsigned count)
-{
- p_atomic_set(&reference->count, count);
-}
-
-static INLINE boolean
-pipe_is_referenced(struct pipe_reference *reference)
-{
- return p_atomic_read(&reference->count) != 0;
-}
-
-/**
- * Update reference counting.
- * The old thing pointed to, if any, will be unreferenced.
- * Both 'ptr' and 'reference' may be NULL.
- * \return TRUE if the object's refcount hits zero and should be destroyed.
- */
-static INLINE boolean
-pipe_reference_described(struct pipe_reference *ptr,
- struct pipe_reference *reference,
- debug_reference_descriptor get_desc)
-{
- boolean destroy = FALSE;
-
- if(ptr != reference) {
- /* bump the reference.count first */
- if (reference) {
- assert(pipe_is_referenced(reference));
- p_atomic_inc(&reference->count);
- debug_reference(reference, get_desc, 1);
- }
-
- if (ptr) {
- assert(pipe_is_referenced(ptr));
- if (p_atomic_dec_zero(&ptr->count)) {
- destroy = TRUE;
- }
- debug_reference(ptr, get_desc, -1);
- }
- }
-
- return destroy;
-}
-
-static INLINE boolean
-pipe_reference(struct pipe_reference *ptr, struct pipe_reference *reference)
-{
- return pipe_reference_described(ptr, reference,
- (debug_reference_descriptor)debug_describe_reference);
-}
-
-static INLINE void
-pipe_surface_reference(struct pipe_surface **ptr, struct pipe_surface *surf)
-{
- struct pipe_surface *old_surf = *ptr;
-
- if (pipe_reference_described(&(*ptr)->reference, &surf->reference,
- (debug_reference_descriptor)debug_describe_surface))
- old_surf->context->surface_destroy(old_surf->context, old_surf);
- *ptr = surf;
-}
-
-static INLINE void
-pipe_resource_reference(struct pipe_resource **ptr, struct pipe_resource *tex)
-{
- struct pipe_resource *old_tex = *ptr;
-
- if (pipe_reference_described(&(*ptr)->reference, &tex->reference,
- (debug_reference_descriptor)debug_describe_resource))
- old_tex->screen->resource_destroy(old_tex->screen, old_tex);
- *ptr = tex;
-}
-
-static INLINE void
-pipe_sampler_view_reference(struct pipe_sampler_view **ptr, struct pipe_sampler_view *view)
-{
- struct pipe_sampler_view *old_view = *ptr;
-
- if (pipe_reference_described(&(*ptr)->reference, &view->reference,
- (debug_reference_descriptor)debug_describe_sampler_view))
- old_view->context->sampler_view_destroy(old_view->context, old_view);
- *ptr = view;
-}
-
-static INLINE void
-pipe_surface_reset(struct pipe_context *ctx, struct pipe_surface* ps,
- struct pipe_resource *pt, unsigned level, unsigned layer,
- unsigned flags)
-{
- pipe_resource_reference(&ps->texture, pt);
- ps->format = pt->format;
- ps->width = u_minify(pt->width0, level);
- ps->height = u_minify(pt->height0, level);
- ps->usage = flags;
- ps->u.tex.level = level;
- ps->u.tex.first_layer = ps->u.tex.last_layer = layer;
- ps->context = ctx;
-}
-
-static INLINE void
-pipe_surface_init(struct pipe_context *ctx, struct pipe_surface* ps,
- struct pipe_resource *pt, unsigned level, unsigned layer,
- unsigned flags)
-{
- ps->texture = 0;
- pipe_reference_init(&ps->reference, 1);
- pipe_surface_reset(ctx, ps, pt, level, layer, flags);
-}
-
-/* Return true if the surfaces are equal. */
-static INLINE boolean
-pipe_surface_equal(struct pipe_surface *s1, struct pipe_surface *s2)
-{
- return s1->texture == s2->texture &&
- s1->format == s2->format &&
- (s1->texture->target != PIPE_BUFFER ||
- (s1->u.buf.first_element == s2->u.buf.first_element &&
- s1->u.buf.last_element == s2->u.buf.last_element)) &&
- (s1->texture->target == PIPE_BUFFER ||
- (s1->u.tex.level == s2->u.tex.level &&
- s1->u.tex.first_layer == s2->u.tex.first_layer &&
- s1->u.tex.last_layer == s2->u.tex.last_layer));
-}
-
-/*
- * Convenience wrappers for screen buffer functions.
- */
-
-static INLINE struct pipe_resource *
-pipe_buffer_create( struct pipe_screen *screen,
- unsigned bind,
- unsigned usage,
- unsigned size )
-{
- struct pipe_resource buffer;
- memset(&buffer, 0, sizeof buffer);
- buffer.target = PIPE_BUFFER;
- buffer.format = PIPE_FORMAT_R8_UNORM; /* want TYPELESS or similar */
- buffer.bind = bind;
- buffer.usage = usage;
- buffer.flags = 0;
- buffer.width0 = size;
- buffer.height0 = 1;
- buffer.depth0 = 1;
- buffer.array_size = 1;
- return screen->resource_create(screen, &buffer);
-}
-
-
-static INLINE struct pipe_resource *
-pipe_user_buffer_create( struct pipe_screen *screen, void *ptr, unsigned size,
- unsigned usage )
-{
- return screen->user_buffer_create(screen, ptr, size, usage);
-}
-
-static INLINE void *
-pipe_buffer_map_range(struct pipe_context *pipe,
- struct pipe_resource *buffer,
- unsigned offset,
- unsigned length,
- unsigned usage,
- struct pipe_transfer **transfer)
-{
- struct pipe_box box;
- void *map;
-
- assert(offset < buffer->width0);
- assert(offset + length <= buffer->width0);
- assert(length);
-
- u_box_1d(offset, length, &box);
-
- *transfer = pipe->get_transfer( pipe,
- buffer,
- 0,
- usage,
- &box);
-
- if (*transfer == NULL)
- return NULL;
-
- map = pipe->transfer_map( pipe, *transfer );
- if (map == NULL) {
- pipe->transfer_destroy( pipe, *transfer );
- *transfer = NULL;
- return NULL;
- }
-
- /* Match old screen->buffer_map_range() behaviour, return pointer
- * to where the beginning of the buffer would be:
- */
- return (void *)((char *)map - offset);
-}
-
-
-static INLINE void *
-pipe_buffer_map(struct pipe_context *pipe,
- struct pipe_resource *buffer,
- unsigned usage,
- struct pipe_transfer **transfer)
-{
- return pipe_buffer_map_range(pipe, buffer, 0, buffer->width0, usage, transfer);
-}
-
-
-static INLINE void
-pipe_buffer_unmap(struct pipe_context *pipe,
- struct pipe_transfer *transfer)
-{
- if (transfer) {
- pipe->transfer_unmap(pipe, transfer);
- pipe->transfer_destroy(pipe, transfer);
- }
-}
-
-static INLINE void
-pipe_buffer_flush_mapped_range(struct pipe_context *pipe,
- struct pipe_transfer *transfer,
- unsigned offset,
- unsigned length)
-{
- struct pipe_box box;
- int transfer_offset;
-
- assert(length);
- assert(transfer->box.x <= offset);
- assert(offset + length <= transfer->box.x + transfer->box.width);
-
- /* Match old screen->buffer_flush_mapped_range() behaviour, where
- * offset parameter is relative to the start of the buffer, not the
- * mapped range.
- */
- transfer_offset = offset - transfer->box.x;
-
- u_box_1d(transfer_offset, length, &box);
-
- pipe->transfer_flush_region(pipe, transfer, &box);
-}
-
-static INLINE void
-pipe_buffer_write(struct pipe_context *pipe,
- struct pipe_resource *buf,
- unsigned offset,
- unsigned size,
- const void *data)
-{
- struct pipe_box box;
- unsigned usage = PIPE_TRANSFER_WRITE;
-
- if (offset == 0 && size == buf->width0) {
- usage |= PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE;
- } else {
- usage |= PIPE_TRANSFER_DISCARD_RANGE;
- }
-
- u_box_1d(offset, size, &box);
-
- pipe->transfer_inline_write( pipe,
- buf,
- 0,
- usage,
- &box,
- data,
- size,
- 0);
-}
-
-/**
- * Special case for writing non-overlapping ranges.
- *
- * We can avoid GPU/CPU synchronization when writing range that has never
- * been written before.
- */
-static INLINE void
-pipe_buffer_write_nooverlap(struct pipe_context *pipe,
- struct pipe_resource *buf,
- unsigned offset, unsigned size,
- const void *data)
-{
- struct pipe_box box;
-
- u_box_1d(offset, size, &box);
-
- pipe->transfer_inline_write(pipe,
- buf,
- 0,
- (PIPE_TRANSFER_WRITE |
- PIPE_TRANSFER_NOOVERWRITE),
- &box,
- data,
- 0, 0);
-}
-
-static INLINE void
-pipe_buffer_read(struct pipe_context *pipe,
- struct pipe_resource *buf,
- unsigned offset,
- unsigned size,
- void *data)
-{
- struct pipe_transfer *src_transfer;
- ubyte *map;
-
- map = (ubyte *) pipe_buffer_map_range(pipe,
- buf,
- offset, size,
- PIPE_TRANSFER_READ,
- &src_transfer);
-
- if (map)
- memcpy(data, map + offset, size);
-
- pipe_buffer_unmap(pipe, src_transfer);
-}
-
-static INLINE struct pipe_transfer *
-pipe_get_transfer( struct pipe_context *context,
- struct pipe_resource *resource,
- unsigned level, unsigned layer,
- enum pipe_transfer_usage usage,
- unsigned x, unsigned y,
- unsigned w, unsigned h)
-{
- struct pipe_box box;
- u_box_2d_zslice( x, y, layer, w, h, &box );
- return context->get_transfer( context,
- resource,
- level,
- usage,
- &box );
-}
-
-static INLINE void *
-pipe_transfer_map( struct pipe_context *context,
- struct pipe_transfer *transfer )
-{
- return context->transfer_map( context, transfer );
-}
-
-static INLINE void
-pipe_transfer_unmap( struct pipe_context *context,
- struct pipe_transfer *transfer )
-{
- context->transfer_unmap( context, transfer );
-}
-
-
-static INLINE void
-pipe_transfer_destroy( struct pipe_context *context,
- struct pipe_transfer *transfer )
-{
- context->transfer_destroy(context, transfer);
-}
-
-
-static INLINE boolean util_get_offset(
- const struct pipe_rasterizer_state *templ,
- unsigned fill_mode)
-{
- switch(fill_mode) {
- case PIPE_POLYGON_MODE_POINT:
- return templ->offset_point;
- case PIPE_POLYGON_MODE_LINE:
- return templ->offset_line;
- case PIPE_POLYGON_MODE_FILL:
- return templ->offset_tri;
- default:
- assert(0);
- return FALSE;
- }
-}
-
-/**
- * This function is used to copy an array of pipe_vertex_buffer structures,
- * while properly referencing the pipe_vertex_buffer::buffer member.
- *
- * \sa util_copy_framebuffer_state
- */
-static INLINE void util_copy_vertex_buffers(struct pipe_vertex_buffer *dst,
- unsigned *dst_count,
- const struct pipe_vertex_buffer *src,
- unsigned src_count)
-{
- unsigned i;
-
- /* Reference the buffers of 'src' in 'dst'. */
- for (i = 0; i < src_count; i++) {
- pipe_resource_reference(&dst[i].buffer, src[i].buffer);
- }
- /* Unreference the rest of the buffers in 'dst'. */
- for (; i < *dst_count; i++) {
- pipe_resource_reference(&dst[i].buffer, NULL);
- }
-
- /* Update the size of 'dst' and copy over the other members
- * of pipe_vertex_buffer. */
- *dst_count = src_count;
- memcpy(dst, src, src_count * sizeof(struct pipe_vertex_buffer));
-}
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* U_INLINES_H */
+/************************************************************************** + * + * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef U_INLINES_H +#define U_INLINES_H + +#include "pipe/p_context.h" +#include "pipe/p_defines.h" +#include "pipe/p_state.h" +#include "pipe/p_screen.h" +#include "util/u_debug.h" +#include "util/u_debug_describe.h" +#include "util/u_debug_refcnt.h" +#include "util/u_atomic.h" +#include "util/u_box.h" +#include "util/u_math.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* + * Reference counting helper functions. + */ + + +static INLINE void +pipe_reference_init(struct pipe_reference *reference, unsigned count) +{ + p_atomic_set(&reference->count, count); +} + +static INLINE boolean +pipe_is_referenced(struct pipe_reference *reference) +{ + return p_atomic_read(&reference->count) != 0; +} + +/** + * Update reference counting. + * The old thing pointed to, if any, will be unreferenced. + * Both 'ptr' and 'reference' may be NULL. + * \return TRUE if the object's refcount hits zero and should be destroyed. + */ +static INLINE boolean +pipe_reference_described(struct pipe_reference *ptr, + struct pipe_reference *reference, + debug_reference_descriptor get_desc) +{ + boolean destroy = FALSE; + + if(ptr != reference) { + /* bump the reference.count first */ + if (reference) { + assert(pipe_is_referenced(reference)); + p_atomic_inc(&reference->count); + debug_reference(reference, get_desc, 1); + } + + if (ptr) { + assert(pipe_is_referenced(ptr)); + if (p_atomic_dec_zero(&ptr->count)) { + destroy = TRUE; + } + debug_reference(ptr, get_desc, -1); + } + } + + return destroy; +} + +static INLINE boolean +pipe_reference(struct pipe_reference *ptr, struct pipe_reference *reference) +{ + return pipe_reference_described(ptr, reference, + (debug_reference_descriptor)debug_describe_reference); +} + +static INLINE void +pipe_surface_reference(struct pipe_surface **ptr, struct pipe_surface *surf) +{ + struct pipe_surface *old_surf = *ptr; + + if (pipe_reference_described(&(*ptr)->reference, &surf->reference, + (debug_reference_descriptor)debug_describe_surface)) + old_surf->context->surface_destroy(old_surf->context, old_surf); + *ptr = surf; +} + +static INLINE void +pipe_resource_reference(struct pipe_resource **ptr, struct pipe_resource *tex) +{ + struct pipe_resource *old_tex = *ptr; + + if (pipe_reference_described(&(*ptr)->reference, &tex->reference, + (debug_reference_descriptor)debug_describe_resource)) + old_tex->screen->resource_destroy(old_tex->screen, old_tex); + *ptr = tex; +} + +static INLINE void +pipe_sampler_view_reference(struct pipe_sampler_view **ptr, struct pipe_sampler_view *view) +{ + struct pipe_sampler_view *old_view = *ptr; + + if (pipe_reference_described(&(*ptr)->reference, &view->reference, + (debug_reference_descriptor)debug_describe_sampler_view)) + old_view->context->sampler_view_destroy(old_view->context, old_view); + *ptr = view; +} + +static INLINE void +pipe_so_target_reference(struct pipe_stream_output_target **ptr, + struct pipe_stream_output_target *target) +{ + struct pipe_stream_output_target *old = *ptr; + + if (pipe_reference_described(&(*ptr)->reference, &target->reference, + (debug_reference_descriptor)debug_describe_so_target)) + old->context->stream_output_target_destroy(old->context, old); + *ptr = target; +} + +static INLINE void +pipe_surface_reset(struct pipe_context *ctx, struct pipe_surface* ps, + struct pipe_resource *pt, unsigned level, unsigned layer, + unsigned flags) +{ + pipe_resource_reference(&ps->texture, pt); + ps->format = pt->format; + ps->width = u_minify(pt->width0, level); + ps->height = u_minify(pt->height0, level); + ps->usage = flags; + ps->u.tex.level = level; + ps->u.tex.first_layer = ps->u.tex.last_layer = layer; + ps->context = ctx; +} + +static INLINE void +pipe_surface_init(struct pipe_context *ctx, struct pipe_surface* ps, + struct pipe_resource *pt, unsigned level, unsigned layer, + unsigned flags) +{ + ps->texture = 0; + pipe_reference_init(&ps->reference, 1); + pipe_surface_reset(ctx, ps, pt, level, layer, flags); +} + +/* Return true if the surfaces are equal. */ +static INLINE boolean +pipe_surface_equal(struct pipe_surface *s1, struct pipe_surface *s2) +{ + return s1->texture == s2->texture && + s1->format == s2->format && + (s1->texture->target != PIPE_BUFFER || + (s1->u.buf.first_element == s2->u.buf.first_element && + s1->u.buf.last_element == s2->u.buf.last_element)) && + (s1->texture->target == PIPE_BUFFER || + (s1->u.tex.level == s2->u.tex.level && + s1->u.tex.first_layer == s2->u.tex.first_layer && + s1->u.tex.last_layer == s2->u.tex.last_layer)); +} + +/* + * Convenience wrappers for screen buffer functions. + */ + +static INLINE struct pipe_resource * +pipe_buffer_create( struct pipe_screen *screen, + unsigned bind, + unsigned usage, + unsigned size ) +{ + struct pipe_resource buffer; + memset(&buffer, 0, sizeof buffer); + buffer.target = PIPE_BUFFER; + buffer.format = PIPE_FORMAT_R8_UNORM; /* want TYPELESS or similar */ + buffer.bind = bind; + buffer.usage = usage; + buffer.flags = 0; + buffer.width0 = size; + buffer.height0 = 1; + buffer.depth0 = 1; + buffer.array_size = 1; + return screen->resource_create(screen, &buffer); +} + + +static INLINE struct pipe_resource * +pipe_user_buffer_create( struct pipe_screen *screen, void *ptr, unsigned size, + unsigned usage ) +{ + return screen->user_buffer_create(screen, ptr, size, usage); +} + +static INLINE void * +pipe_buffer_map_range(struct pipe_context *pipe, + struct pipe_resource *buffer, + unsigned offset, + unsigned length, + unsigned usage, + struct pipe_transfer **transfer) +{ + struct pipe_box box; + void *map; + + assert(offset < buffer->width0); + assert(offset + length <= buffer->width0); + assert(length); + + u_box_1d(offset, length, &box); + + *transfer = pipe->get_transfer( pipe, + buffer, + 0, + usage, + &box); + + if (*transfer == NULL) + return NULL; + + map = pipe->transfer_map( pipe, *transfer ); + if (map == NULL) { + pipe->transfer_destroy( pipe, *transfer ); + *transfer = NULL; + return NULL; + } + + /* Match old screen->buffer_map_range() behaviour, return pointer + * to where the beginning of the buffer would be: + */ + return (void *)((char *)map - offset); +} + + +static INLINE void * +pipe_buffer_map(struct pipe_context *pipe, + struct pipe_resource *buffer, + unsigned usage, + struct pipe_transfer **transfer) +{ + return pipe_buffer_map_range(pipe, buffer, 0, buffer->width0, usage, transfer); +} + + +static INLINE void +pipe_buffer_unmap(struct pipe_context *pipe, + struct pipe_transfer *transfer) +{ + if (transfer) { + pipe->transfer_unmap(pipe, transfer); + pipe->transfer_destroy(pipe, transfer); + } +} + +static INLINE void +pipe_buffer_flush_mapped_range(struct pipe_context *pipe, + struct pipe_transfer *transfer, + unsigned offset, + unsigned length) +{ + struct pipe_box box; + int transfer_offset; + + assert(length); + assert(transfer->box.x <= offset); + assert(offset + length <= transfer->box.x + transfer->box.width); + + /* Match old screen->buffer_flush_mapped_range() behaviour, where + * offset parameter is relative to the start of the buffer, not the + * mapped range. + */ + transfer_offset = offset - transfer->box.x; + + u_box_1d(transfer_offset, length, &box); + + pipe->transfer_flush_region(pipe, transfer, &box); +} + +static INLINE void +pipe_buffer_write(struct pipe_context *pipe, + struct pipe_resource *buf, + unsigned offset, + unsigned size, + const void *data) +{ + struct pipe_box box; + unsigned usage = PIPE_TRANSFER_WRITE; + + if (offset == 0 && size == buf->width0) { + usage |= PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE; + } else { + usage |= PIPE_TRANSFER_DISCARD_RANGE; + } + + u_box_1d(offset, size, &box); + + pipe->transfer_inline_write( pipe, + buf, + 0, + usage, + &box, + data, + size, + 0); +} + +/** + * Special case for writing non-overlapping ranges. + * + * We can avoid GPU/CPU synchronization when writing range that has never + * been written before. + */ +static INLINE void +pipe_buffer_write_nooverlap(struct pipe_context *pipe, + struct pipe_resource *buf, + unsigned offset, unsigned size, + const void *data) +{ + struct pipe_box box; + + u_box_1d(offset, size, &box); + + pipe->transfer_inline_write(pipe, + buf, + 0, + (PIPE_TRANSFER_WRITE | + PIPE_TRANSFER_NOOVERWRITE), + &box, + data, + 0, 0); +} + +static INLINE void +pipe_buffer_read(struct pipe_context *pipe, + struct pipe_resource *buf, + unsigned offset, + unsigned size, + void *data) +{ + struct pipe_transfer *src_transfer; + ubyte *map; + + map = (ubyte *) pipe_buffer_map_range(pipe, + buf, + offset, size, + PIPE_TRANSFER_READ, + &src_transfer); + + if (map) + memcpy(data, map + offset, size); + + pipe_buffer_unmap(pipe, src_transfer); +} + +static INLINE struct pipe_transfer * +pipe_get_transfer( struct pipe_context *context, + struct pipe_resource *resource, + unsigned level, unsigned layer, + enum pipe_transfer_usage usage, + unsigned x, unsigned y, + unsigned w, unsigned h) +{ + struct pipe_box box; + u_box_2d_zslice( x, y, layer, w, h, &box ); + return context->get_transfer( context, + resource, + level, + usage, + &box ); +} + +static INLINE void * +pipe_transfer_map( struct pipe_context *context, + struct pipe_transfer *transfer ) +{ + return context->transfer_map( context, transfer ); +} + +static INLINE void +pipe_transfer_unmap( struct pipe_context *context, + struct pipe_transfer *transfer ) +{ + context->transfer_unmap( context, transfer ); +} + + +static INLINE void +pipe_transfer_destroy( struct pipe_context *context, + struct pipe_transfer *transfer ) +{ + context->transfer_destroy(context, transfer); +} + + +static INLINE boolean util_get_offset( + const struct pipe_rasterizer_state *templ, + unsigned fill_mode) +{ + switch(fill_mode) { + case PIPE_POLYGON_MODE_POINT: + return templ->offset_point; + case PIPE_POLYGON_MODE_LINE: + return templ->offset_line; + case PIPE_POLYGON_MODE_FILL: + return templ->offset_tri; + default: + assert(0); + return FALSE; + } +} + +/** + * This function is used to copy an array of pipe_vertex_buffer structures, + * while properly referencing the pipe_vertex_buffer::buffer member. + * + * \sa util_copy_framebuffer_state + */ +static INLINE void util_copy_vertex_buffers(struct pipe_vertex_buffer *dst, + unsigned *dst_count, + const struct pipe_vertex_buffer *src, + unsigned src_count) +{ + unsigned i; + + /* Reference the buffers of 'src' in 'dst'. */ + for (i = 0; i < src_count; i++) { + pipe_resource_reference(&dst[i].buffer, src[i].buffer); + } + /* Unreference the rest of the buffers in 'dst'. */ + for (; i < *dst_count; i++) { + pipe_resource_reference(&dst[i].buffer, NULL); + } + + /* Update the size of 'dst' and copy over the other members + * of pipe_vertex_buffer. */ + *dst_count = src_count; + memcpy(dst, src, src_count * sizeof(struct pipe_vertex_buffer)); +} + +#ifdef __cplusplus +} +#endif + +#endif /* U_INLINES_H */ diff --git a/mesalib/src/gallium/auxiliary/util/u_simple_shaders.c b/mesalib/src/gallium/auxiliary/util/u_simple_shaders.c index 141763190..320c0f7a8 100644 --- a/mesalib/src/gallium/auxiliary/util/u_simple_shaders.c +++ b/mesalib/src/gallium/auxiliary/util/u_simple_shaders.c @@ -1,243 +1,255 @@ -/**************************************************************************
- *
- * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
- * All Rights Reserved.
- * Copyright 2009 Marek Olšák <maraeo@gmail.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- **************************************************************************/
-
-/**
- * @file
- * Simple vertex/fragment shader generators.
- *
- * @author Brian Paul
- Marek Olšák
- */
-
-
-#include "pipe/p_context.h"
-#include "pipe/p_shader_tokens.h"
-#include "pipe/p_state.h"
-#include "util/u_simple_shaders.h"
-#include "util/u_debug.h"
-#include "tgsi/tgsi_ureg.h"
-
-
-
-/**
- * Make simple vertex pass-through shader.
- * \param num_attribs number of attributes to pass through
- * \param semantic_names array of semantic names for each attribute
- * \param semantic_indexes array of semantic indexes for each attribute
- */
-void *
-util_make_vertex_passthrough_shader(struct pipe_context *pipe,
- uint num_attribs,
- const uint *semantic_names,
- const uint *semantic_indexes)
-{
- struct ureg_program *ureg;
- uint i;
-
- ureg = ureg_create( TGSI_PROCESSOR_VERTEX );
- if (ureg == NULL)
- return NULL;
-
- for (i = 0; i < num_attribs; i++) {
- struct ureg_src src;
- struct ureg_dst dst;
-
- src = ureg_DECL_vs_input( ureg, i );
-
- dst = ureg_DECL_output( ureg,
- semantic_names[i],
- semantic_indexes[i]);
-
- ureg_MOV( ureg, dst, src );
- }
-
- ureg_END( ureg );
-
- return ureg_create_shader_and_destroy( ureg, pipe );
-}
-
-
-/**
- * Make simple fragment texture shader:
- * IMM {0,0,0,1} // (if writemask != 0xf)
- * MOV OUT[0], IMM[0] // (if writemask != 0xf)
- * TEX OUT[0].writemask, IN[0], SAMP[0], 2D;
- * END;
- *
- * \param tex_target one of PIPE_TEXTURE_x
- * \parma interp_mode either TGSI_INTERPOLATE_LINEAR or PERSPECTIVE
- * \param writemask mask of TGSI_WRITEMASK_x
- */
-void *
-util_make_fragment_tex_shader_writemask(struct pipe_context *pipe,
- unsigned tex_target,
- unsigned interp_mode,
- unsigned writemask )
-{
- struct ureg_program *ureg;
- struct ureg_src sampler;
- struct ureg_src tex;
- struct ureg_dst out;
-
- assert(interp_mode == TGSI_INTERPOLATE_LINEAR ||
- interp_mode == TGSI_INTERPOLATE_PERSPECTIVE);
-
- ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT );
- if (ureg == NULL)
- return NULL;
-
- sampler = ureg_DECL_sampler( ureg, 0 );
-
- tex = ureg_DECL_fs_input( ureg,
- TGSI_SEMANTIC_GENERIC, 0,
- interp_mode );
-
- out = ureg_DECL_output( ureg,
- TGSI_SEMANTIC_COLOR,
- 0 );
-
- if (writemask != TGSI_WRITEMASK_XYZW) {
- struct ureg_src imm = ureg_imm4f( ureg, 0, 0, 0, 1 );
-
- ureg_MOV( ureg, out, imm );
- }
-
- ureg_TEX( ureg,
- ureg_writemask(out, writemask),
- tex_target, tex, sampler );
- ureg_END( ureg );
-
- return ureg_create_shader_and_destroy( ureg, pipe );
-}
-
-
-/**
- * Make a simple fragment shader that sets the output color to a color
- * taken from a texture.
- * \param tex_target one of PIPE_TEXTURE_x
- */
-void *
-util_make_fragment_tex_shader(struct pipe_context *pipe, unsigned tex_target,
- unsigned interp_mode)
-{
- return util_make_fragment_tex_shader_writemask( pipe,
- tex_target,
- interp_mode,
- TGSI_WRITEMASK_XYZW );
-}
-
-
-/**
- * Make a simple fragment texture shader which reads an X component from
- * a texture and writes it as depth.
- */
-void *
-util_make_fragment_tex_shader_writedepth(struct pipe_context *pipe,
- unsigned tex_target,
- unsigned interp_mode)
-{
- struct ureg_program *ureg;
- struct ureg_src sampler;
- struct ureg_src tex;
- struct ureg_dst out, depth;
- struct ureg_src imm;
-
- ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT );
- if (ureg == NULL)
- return NULL;
-
- sampler = ureg_DECL_sampler( ureg, 0 );
-
- tex = ureg_DECL_fs_input( ureg,
- TGSI_SEMANTIC_GENERIC, 0,
- interp_mode );
-
- out = ureg_DECL_output( ureg,
- TGSI_SEMANTIC_COLOR,
- 0 );
-
- depth = ureg_DECL_output( ureg,
- TGSI_SEMANTIC_POSITION,
- 0 );
-
- imm = ureg_imm4f( ureg, 0, 0, 0, 1 );
-
- ureg_MOV( ureg, out, imm );
-
- ureg_TEX( ureg,
- ureg_writemask(depth, TGSI_WRITEMASK_Z),
- tex_target, tex, sampler );
- ureg_END( ureg );
-
- return ureg_create_shader_and_destroy( ureg, pipe );
-}
-
-
-/**
- * Make simple fragment color pass-through shader.
- */
-void *
-util_make_fragment_passthrough_shader(struct pipe_context *pipe)
-{
- return util_make_fragment_cloneinput_shader(pipe, 1, TGSI_SEMANTIC_COLOR,
- TGSI_INTERPOLATE_PERSPECTIVE);
-}
-
-
-/**
- * Make a fragment shader that copies the input color to N output colors.
- */
-void *
-util_make_fragment_cloneinput_shader(struct pipe_context *pipe, int num_cbufs,
- int input_semantic,
- int input_interpolate)
-{
- struct ureg_program *ureg;
- struct ureg_src src;
- struct ureg_dst dst[PIPE_MAX_COLOR_BUFS];
- int i;
-
- assert(num_cbufs <= PIPE_MAX_COLOR_BUFS);
-
- ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT );
- if (ureg == NULL)
- return NULL;
-
- src = ureg_DECL_fs_input( ureg, input_semantic, 0,
- input_interpolate );
-
- for (i = 0; i < num_cbufs; i++)
- dst[i] = ureg_DECL_output( ureg, TGSI_SEMANTIC_COLOR, i );
-
- for (i = 0; i < num_cbufs; i++)
- ureg_MOV( ureg, dst[i], src );
-
- ureg_END( ureg );
-
- return ureg_create_shader_and_destroy( ureg, pipe );
-}
+/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * Copyright 2009 Marek Olšák <maraeo@gmail.com> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +/** + * @file + * Simple vertex/fragment shader generators. + * + * @author Brian Paul + Marek Olšák + */ + + +#include "pipe/p_context.h" +#include "pipe/p_shader_tokens.h" +#include "pipe/p_state.h" +#include "util/u_simple_shaders.h" +#include "util/u_debug.h" +#include "tgsi/tgsi_ureg.h" + + + +/** + * Make simple vertex pass-through shader. + * \param num_attribs number of attributes to pass through + * \param semantic_names array of semantic names for each attribute + * \param semantic_indexes array of semantic indexes for each attribute + */ +void * +util_make_vertex_passthrough_shader(struct pipe_context *pipe, + uint num_attribs, + const uint *semantic_names, + const uint *semantic_indexes) +{ + return util_make_vertex_passthrough_shader_with_so(pipe, num_attribs, + semantic_names, + semantic_indexes, NULL); +} + +void * +util_make_vertex_passthrough_shader_with_so(struct pipe_context *pipe, + uint num_attribs, + const uint *semantic_names, + const uint *semantic_indexes, + const struct pipe_stream_output_info *so) +{ + struct ureg_program *ureg; + uint i; + + ureg = ureg_create( TGSI_PROCESSOR_VERTEX ); + if (ureg == NULL) + return NULL; + + for (i = 0; i < num_attribs; i++) { + struct ureg_src src; + struct ureg_dst dst; + + src = ureg_DECL_vs_input( ureg, i ); + + dst = ureg_DECL_output( ureg, + semantic_names[i], + semantic_indexes[i]); + + ureg_MOV( ureg, dst, src ); + } + + ureg_END( ureg ); + + return ureg_create_shader_with_so_and_destroy( ureg, pipe, so ); +} + + +/** + * Make simple fragment texture shader: + * IMM {0,0,0,1} // (if writemask != 0xf) + * MOV OUT[0], IMM[0] // (if writemask != 0xf) + * TEX OUT[0].writemask, IN[0], SAMP[0], 2D; + * END; + * + * \param tex_target one of PIPE_TEXTURE_x + * \parma interp_mode either TGSI_INTERPOLATE_LINEAR or PERSPECTIVE + * \param writemask mask of TGSI_WRITEMASK_x + */ +void * +util_make_fragment_tex_shader_writemask(struct pipe_context *pipe, + unsigned tex_target, + unsigned interp_mode, + unsigned writemask ) +{ + struct ureg_program *ureg; + struct ureg_src sampler; + struct ureg_src tex; + struct ureg_dst out; + + assert(interp_mode == TGSI_INTERPOLATE_LINEAR || + interp_mode == TGSI_INTERPOLATE_PERSPECTIVE); + + ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT ); + if (ureg == NULL) + return NULL; + + sampler = ureg_DECL_sampler( ureg, 0 ); + + tex = ureg_DECL_fs_input( ureg, + TGSI_SEMANTIC_GENERIC, 0, + interp_mode ); + + out = ureg_DECL_output( ureg, + TGSI_SEMANTIC_COLOR, + 0 ); + + if (writemask != TGSI_WRITEMASK_XYZW) { + struct ureg_src imm = ureg_imm4f( ureg, 0, 0, 0, 1 ); + + ureg_MOV( ureg, out, imm ); + } + + ureg_TEX( ureg, + ureg_writemask(out, writemask), + tex_target, tex, sampler ); + ureg_END( ureg ); + + return ureg_create_shader_and_destroy( ureg, pipe ); +} + + +/** + * Make a simple fragment shader that sets the output color to a color + * taken from a texture. + * \param tex_target one of PIPE_TEXTURE_x + */ +void * +util_make_fragment_tex_shader(struct pipe_context *pipe, unsigned tex_target, + unsigned interp_mode) +{ + return util_make_fragment_tex_shader_writemask( pipe, + tex_target, + interp_mode, + TGSI_WRITEMASK_XYZW ); +} + + +/** + * Make a simple fragment texture shader which reads an X component from + * a texture and writes it as depth. + */ +void * +util_make_fragment_tex_shader_writedepth(struct pipe_context *pipe, + unsigned tex_target, + unsigned interp_mode) +{ + struct ureg_program *ureg; + struct ureg_src sampler; + struct ureg_src tex; + struct ureg_dst out, depth; + struct ureg_src imm; + + ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT ); + if (ureg == NULL) + return NULL; + + sampler = ureg_DECL_sampler( ureg, 0 ); + + tex = ureg_DECL_fs_input( ureg, + TGSI_SEMANTIC_GENERIC, 0, + interp_mode ); + + out = ureg_DECL_output( ureg, + TGSI_SEMANTIC_COLOR, + 0 ); + + depth = ureg_DECL_output( ureg, + TGSI_SEMANTIC_POSITION, + 0 ); + + imm = ureg_imm4f( ureg, 0, 0, 0, 1 ); + + ureg_MOV( ureg, out, imm ); + + ureg_TEX( ureg, + ureg_writemask(depth, TGSI_WRITEMASK_Z), + tex_target, tex, sampler ); + ureg_END( ureg ); + + return ureg_create_shader_and_destroy( ureg, pipe ); +} + + +/** + * Make simple fragment color pass-through shader. + */ +void * +util_make_fragment_passthrough_shader(struct pipe_context *pipe) +{ + return util_make_fragment_cloneinput_shader(pipe, 1, TGSI_SEMANTIC_COLOR, + TGSI_INTERPOLATE_PERSPECTIVE); +} + + +/** + * Make a fragment shader that copies the input color to N output colors. + */ +void * +util_make_fragment_cloneinput_shader(struct pipe_context *pipe, int num_cbufs, + int input_semantic, + int input_interpolate) +{ + struct ureg_program *ureg; + struct ureg_src src; + struct ureg_dst dst[PIPE_MAX_COLOR_BUFS]; + int i; + + assert(num_cbufs <= PIPE_MAX_COLOR_BUFS); + + ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT ); + if (ureg == NULL) + return NULL; + + src = ureg_DECL_fs_input( ureg, input_semantic, 0, + input_interpolate ); + + for (i = 0; i < num_cbufs; i++) + dst[i] = ureg_DECL_output( ureg, TGSI_SEMANTIC_COLOR, i ); + + for (i = 0; i < num_cbufs; i++) + ureg_MOV( ureg, dst[i], src ); + + ureg_END( ureg ); + + return ureg_create_shader_and_destroy( ureg, pipe ); +} diff --git a/mesalib/src/gallium/auxiliary/util/u_simple_shaders.h b/mesalib/src/gallium/auxiliary/util/u_simple_shaders.h index 9a0fe6375..5f31b72c4 100644 --- a/mesalib/src/gallium/auxiliary/util/u_simple_shaders.h +++ b/mesalib/src/gallium/auxiliary/util/u_simple_shaders.h @@ -1,83 +1,91 @@ -/**************************************************************************
- *
- * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- **************************************************************************/
-
-
-#ifndef U_SIMPLE_SHADERS_H
-#define U_SIMPLE_SHADERS_H
-
-
-#include "pipe/p_compiler.h"
-
-
-struct pipe_context;
-struct pipe_shader_state;
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-extern void *
-util_make_vertex_passthrough_shader(struct pipe_context *pipe,
- uint num_attribs,
- const uint *semantic_names,
- const uint *semantic_indexes);
-
-
-extern void *
-util_make_fragment_tex_shader_writemask(struct pipe_context *pipe,
- unsigned tex_target,
- unsigned interp_mode,
- unsigned writemask);
-
-extern void *
-util_make_fragment_tex_shader(struct pipe_context *pipe, unsigned tex_target,
- unsigned interp_mode);
-
-
-extern void *
-util_make_fragment_tex_shader_writedepth(struct pipe_context *pipe,
- unsigned tex_target,
- unsigned interp_mode);
-
-
-extern void *
-util_make_fragment_passthrough_shader(struct pipe_context *pipe);
-
-
-extern void *
-util_make_fragment_cloneinput_shader(struct pipe_context *pipe, int num_cbufs,
- int input_semantic,
- int input_interpolate);
-
-#ifdef __cplusplus
-}
-#endif
-
-
-#endif
+/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + + +#ifndef U_SIMPLE_SHADERS_H +#define U_SIMPLE_SHADERS_H + + +#include "pipe/p_compiler.h" + + +struct pipe_context; +struct pipe_shader_state; +struct pipe_stream_output_info; + + +#ifdef __cplusplus +extern "C" { +#endif + + +extern void * +util_make_vertex_passthrough_shader(struct pipe_context *pipe, + uint num_attribs, + const uint *semantic_names, + const uint *semantic_indexes); + +extern void * +util_make_vertex_passthrough_shader_with_so(struct pipe_context *pipe, + uint num_attribs, + const uint *semantic_names, + const uint *semantic_indexes, + const struct pipe_stream_output_info *so); + + +extern void * +util_make_fragment_tex_shader_writemask(struct pipe_context *pipe, + unsigned tex_target, + unsigned interp_mode, + unsigned writemask); + +extern void * +util_make_fragment_tex_shader(struct pipe_context *pipe, unsigned tex_target, + unsigned interp_mode); + + +extern void * +util_make_fragment_tex_shader_writedepth(struct pipe_context *pipe, + unsigned tex_target, + unsigned interp_mode); + + +extern void * +util_make_fragment_passthrough_shader(struct pipe_context *pipe); + + +extern void * +util_make_fragment_cloneinput_shader(struct pipe_context *pipe, int num_cbufs, + int input_semantic, + int input_interpolate); + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/mesalib/src/mesa/drivers/common/meta.c b/mesalib/src/mesa/drivers/common/meta.c index 259041f67..1683c85e9 100644 --- a/mesalib/src/mesa/drivers/common/meta.c +++ b/mesalib/src/mesa/drivers/common/meta.c @@ -2943,43 +2943,20 @@ _mesa_meta_GenerateMipmap(struct gl_context *ctx, GLenum target, break; } - /* Set MaxLevel large enough to hold the new level when we allocate it */ + /* Allocate storage for the destination mipmap image(s) */ + + /* Set MaxLevel large enough to hold the new level when we allocate it */ _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, dstLevel); - /* Create empty dest image */ - if (target == GL_TEXTURE_1D) { - _mesa_TexImage1D(target, dstLevel, srcImage->InternalFormat, - dstWidth, border, - GL_RGBA, GL_UNSIGNED_BYTE, NULL); - } - else if (target == GL_TEXTURE_3D) { - _mesa_TexImage3D(target, dstLevel, srcImage->InternalFormat, - dstWidth, dstHeight, dstDepth, border, - GL_RGBA, GL_UNSIGNED_BYTE, NULL); - } - else { - /* 2D or cube */ - _mesa_TexImage2D(faceTarget, dstLevel, srcImage->InternalFormat, - dstWidth, dstHeight, border, - GL_RGBA, GL_UNSIGNED_BYTE, NULL); - - if (target == GL_TEXTURE_CUBE_MAP) { - /* If texturing from a cube, we need to make sure all src faces - * have been defined (even if we're not sampling from them.) - * Otherwise the texture object will be 'incomplete' and - * texturing from it will not be allowed. - */ - GLuint face; - for (face = 0; face < 6; face++) { - if (!texObj->Image[face][srcLevel] || - texObj->Image[face][srcLevel]->Width != srcWidth) { - _mesa_TexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, - srcLevel, srcImage->InternalFormat, - srcWidth, srcHeight, border, - GL_RGBA, GL_UNSIGNED_BYTE, NULL); - } - } - } + if (!_mesa_prepare_mipmap_level(ctx, texObj, dstLevel, + dstWidth, dstHeight, dstDepth, + srcImage->Border, + srcImage->InternalFormat, + srcImage->TexFormat)) { + /* All done. We either ran out of memory or we would go beyond the + * last valid level of an immutable texture if we continued. + */ + break; } /* limit minification to src level */ diff --git a/mesalib/src/mesa/main/api_validate.c b/mesalib/src/mesa/main/api_validate.c index efdecb212..945f12752 100644 --- a/mesalib/src/mesa/main/api_validate.c +++ b/mesalib/src/mesa/main/api_validate.c @@ -474,3 +474,37 @@ _mesa_validate_DrawElementsInstanced(struct gl_context *ctx, return GL_TRUE; } + + +#if FEATURE_EXT_transform_feedback + +GLboolean +_mesa_validate_DrawTransformFeedback(struct gl_context *ctx, + GLenum mode, + struct gl_transform_feedback_object *obj) +{ + ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); + + if (!_mesa_valid_prim_mode(ctx, mode)) { + _mesa_error(ctx, GL_INVALID_ENUM, "glDrawTransformFeedback(mode)"); + return GL_FALSE; + } + + if (!obj) { + _mesa_error(ctx, GL_INVALID_VALUE, "glDrawTransformFeedback(name)"); + return GL_FALSE; + } + + if (!obj->EndedAnytime) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawTransformFeedback"); + return GL_FALSE; + } + + if (!check_valid_to_render(ctx, "glDrawTransformFeedback")) { + return GL_FALSE; + } + + return GL_TRUE; +} + +#endif diff --git a/mesalib/src/mesa/main/api_validate.h b/mesalib/src/mesa/main/api_validate.h index 7d6a66012..f4948424c 100644 --- a/mesalib/src/mesa/main/api_validate.h +++ b/mesalib/src/mesa/main/api_validate.h @@ -29,9 +29,11 @@ #include "glheader.h" +#include "mfeatures.h" struct gl_buffer_object; struct gl_context; +struct gl_transform_feedback_object; extern GLuint @@ -70,5 +72,13 @@ _mesa_validate_DrawElementsInstanced(struct gl_context *ctx, const GLvoid *indices, GLsizei primcount, GLint basevertex); +#if FEATURE_EXT_transform_feedback + +extern GLboolean +_mesa_validate_DrawTransformFeedback(struct gl_context *ctx, + GLenum mode, + struct gl_transform_feedback_object *obj); + +#endif #endif diff --git a/mesalib/src/mesa/main/dd.h b/mesalib/src/mesa/main/dd.h index d6f70d1c4..01cfff8ab 100644 --- a/mesalib/src/mesa/main/dd.h +++ b/mesalib/src/mesa/main/dd.h @@ -964,8 +964,6 @@ struct dd_function_table { struct gl_transform_feedback_object *obj); void (*ResumeTransformFeedback)(struct gl_context *ctx, struct gl_transform_feedback_object *obj); - void (*DrawTransformFeedback)(struct gl_context *ctx, GLenum mode, - struct gl_transform_feedback_object *obj); /** * \name GL_NV_texture_barrier interface @@ -1194,6 +1192,7 @@ typedef struct { void (GLAPIENTRYP DrawElementsInstancedBaseVertex)(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount, GLint basevertex); + void (GLAPIENTRYP DrawTransformFeedback)(GLenum mode, GLuint name); /*@}*/ /** diff --git a/mesalib/src/mesa/main/dlist.c b/mesalib/src/mesa/main/dlist.c index e1acc8028..b3edae0e6 100644 --- a/mesalib/src/mesa/main/dlist.c +++ b/mesalib/src/mesa/main/dlist.c @@ -1422,7 +1422,7 @@ save_ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *value) } } if (ctx->ExecuteFlag) { - /*CALL_ClearBufferiv(ctx->Exec, (buffer, drawbuffer, value));*/ + CALL_ClearBufferiv(ctx->Exec, (buffer, drawbuffer, value)); } } @@ -1450,7 +1450,7 @@ save_ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *value) } } if (ctx->ExecuteFlag) { - /*CALL_ClearBufferuiv(ctx->Exec, (buffer, drawbuffer, value));*/ + CALL_ClearBufferuiv(ctx->Exec, (buffer, drawbuffer, value)); } } @@ -1478,7 +1478,7 @@ save_ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *value) } } if (ctx->ExecuteFlag) { - /*CALL_ClearBufferuiv(ctx->Exec, (buffer, drawbuffer, value));*/ + CALL_ClearBufferfv(ctx->Exec, (buffer, drawbuffer, value)); } } @@ -1498,7 +1498,7 @@ save_ClearBufferfi(GLenum buffer, GLint drawbuffer, n[4].i = stencil; } if (ctx->ExecuteFlag) { - /*CALL_ClearBufferfi(ctx->Exec, (buffer, drawbuffer, depth, stencil));*/ + CALL_ClearBufferfi(ctx->Exec, (buffer, drawbuffer, depth, stencil)); } } @@ -7545,36 +7545,36 @@ execute_list(struct gl_context *ctx, GLuint list) break; case OPCODE_CLEAR_BUFFER_IV: { - /*GLint value[4]; + GLint value[4]; value[0] = n[3].i; value[1] = n[4].i; value[2] = n[5].i; value[3] = n[6].i; - CALL_ClearBufferiv(ctx->Exec, (n[1].e, n[2].i, value));*/ + CALL_ClearBufferiv(ctx->Exec, (n[1].e, n[2].i, value)); } break; case OPCODE_CLEAR_BUFFER_UIV: { - /*GLuint value[4]; + GLuint value[4]; value[0] = n[3].ui; value[1] = n[4].ui; value[2] = n[5].ui; value[3] = n[6].ui; - CALL_ClearBufferiv(ctx->Exec, (n[1].e, n[2].i, value));*/ + CALL_ClearBufferuiv(ctx->Exec, (n[1].e, n[2].i, value)); } break; case OPCODE_CLEAR_BUFFER_FV: { - /*GLfloat value[4]; + GLfloat value[4]; value[0] = n[3].f; value[1] = n[4].f; value[2] = n[5].f; value[3] = n[6].f; - CALL_ClearBufferfv(ctx->Exec, (n[1].e, n[2].i, value));*/ + CALL_ClearBufferfv(ctx->Exec, (n[1].e, n[2].i, value)); } break; case OPCODE_CLEAR_BUFFER_FI: - /*CALL_ClearBufferfi(ctx->Exec, (n[1].e, n[2].i, n[3].f, n[4].i));*/ + CALL_ClearBufferfi(ctx->Exec, (n[1].e, n[2].i, n[3].f, n[4].i)); break; case OPCODE_CLEAR_COLOR: CALL_ClearColor(ctx->Exec, (n[1].f, n[2].f, n[3].f, n[4].f)); diff --git a/mesalib/src/mesa/main/fbobject.c b/mesalib/src/mesa/main/fbobject.c index 611a6d0b0..912170aba 100644 --- a/mesalib/src/mesa/main/fbobject.c +++ b/mesalib/src/mesa/main/fbobject.c @@ -819,7 +819,7 @@ _mesa_test_framebuffer_completeness(struct gl_context *ctx, fbo_incomplete("width or height mismatch", -1); return; } - /* check that all color buffer have same format */ + /* check that all color buffers are the same format */ if (intFormat != GL_NONE && f != intFormat) { fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT; fbo_incomplete("format mismatch", -1); @@ -831,8 +831,7 @@ _mesa_test_framebuffer_completeness(struct gl_context *ctx, fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE; fbo_incomplete("inconsistant number of samples", i); return; - } - + } } } @@ -1273,7 +1272,7 @@ _mesa_base_fbo_format(struct gl_context *ctx, GLenum internalFormat) case GL_RG32I: return ctx->Extensions.ARB_texture_rg && ctx->Extensions.EXT_texture_integer ? GL_RG : 0; - + case GL_INTENSITY8I_EXT: case GL_INTENSITY8UI_EXT: case GL_INTENSITY16I_EXT: @@ -1820,7 +1819,7 @@ _mesa_DeleteFramebuffersEXT(GLsizei n, const GLuint *framebuffers) /* bind default */ ASSERT(fb->RefCount >= 2); _mesa_BindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); - } + } } /* remove from hash table immediately, to free the ID */ @@ -1897,6 +1896,7 @@ _mesa_CheckFramebufferStatusEXT(GLenum target) return buffer->_Status; } + /** * Replicate the src attachment point. Used by framebuffer_texture() when * the same texture is attached at GL_DEPTH_ATTACHMENT and @@ -1911,7 +1911,7 @@ reuse_framebuffer_texture_attachment(struct gl_framebuffer *fb, struct gl_renderbuffer_attachment *src_att = &fb->Attachment[src]; assert(src_att->Texture != NULL); - assert (src_att->Renderbuffer != NULL); + assert(src_att->Renderbuffer != NULL); _mesa_reference_texobj(&dst_att->Texture, src_att->Texture); _mesa_reference_renderbuffer(&dst_att->Renderbuffer, src_att->Renderbuffer); @@ -1921,6 +1921,7 @@ reuse_framebuffer_texture_attachment(struct gl_framebuffer *fb, dst_att->Zoffset = src_att->Zoffset; } + /** * Common code called by glFramebufferTexture1D/2D/3DEXT(). */ @@ -1949,7 +1950,6 @@ framebuffer_texture(struct gl_context *ctx, const char *caller, GLenum target, return; } - /* The textarget, level, and zoffset parameters are only validated if * texture is non-zero. */ @@ -2002,7 +2002,7 @@ framebuffer_texture(struct gl_context *ctx, const char *caller, GLenum target, } } - if ((level < 0) || + if ((level < 0) || (level >= _mesa_max_texture_levels(ctx, texObj->Target))) { _mesa_error(ctx, GL_INVALID_VALUE, "glFramebufferTexture%sEXT(level)", caller); @@ -2031,7 +2031,7 @@ framebuffer_texture(struct gl_context *ctx, const char *caller, GLenum target, reuse_framebuffer_texture_attachment(fb, BUFFER_DEPTH, BUFFER_STENCIL); } else if (attachment == GL_STENCIL_ATTACHMENT && - texObj== fb->Attachment[BUFFER_DEPTH].Texture) { + texObj == fb->Attachment[BUFFER_DEPTH].Texture) { /* As above, but with depth and stencil juxtasposed. */ reuse_framebuffer_texture_attachment(fb, BUFFER_STENCIL, BUFFER_DEPTH); @@ -2797,6 +2797,7 @@ _mesa_BlitFramebufferEXT(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, } #endif /* FEATURE_EXT_framebuffer_blit */ + #if FEATURE_ARB_geometry_shader4 void GLAPIENTRY _mesa_FramebufferTextureARB(GLenum target, GLenum attachment, @@ -2808,6 +2809,7 @@ _mesa_FramebufferTextureARB(GLenum target, GLenum attachment, "not implemented!"); } + void GLAPIENTRY _mesa_FramebufferTextureFaceARB(GLenum target, GLenum attachment, GLuint texture, GLint level, GLenum face) diff --git a/mesalib/src/mesa/main/format_unpack.c b/mesalib/src/mesa/main/format_unpack.c index 4f23f3dec..32d198ce8 100644 --- a/mesalib/src/mesa/main/format_unpack.c +++ b/mesalib/src/mesa/main/format_unpack.c @@ -1822,6 +1822,10 @@ unpack_float_z_Z32X24S8(GLuint n, const void *src, GLfloat *dst) +/** + * Unpack Z values. + * The returned values will always be in the range [0.0, 1.0]. + */ void _mesa_unpack_float_z_row(gl_format format, GLuint n, const void *src, GLfloat *dst) @@ -1901,6 +1905,10 @@ unpack_uint_z_Z32(const void *src, GLuint *dst, GLuint n) } +/** + * Unpack Z values. + * The returned values will always be in the range [0, 0xffffffff]. + */ void _mesa_unpack_uint_z_row(gl_format format, GLuint n, const void *src, GLuint *dst) diff --git a/mesalib/src/mesa/main/mipmap.c b/mesalib/src/mesa/main/mipmap.c index fd6e582ec..867cb22e2 100644 --- a/mesalib/src/mesa/main/mipmap.c +++ b/mesalib/src/mesa/main/mipmap.c @@ -1803,6 +1803,81 @@ next_mipmap_level_size(GLenum target, GLint border, } } + +/** + * Helper function for mipmap generation. + * Make sure the specified destination mipmap level is the right size/format + * for mipmap generation. If not, (re) allocate it. + * \return GL_TRUE if successful, GL_FALSE if mipmap generation should stop + */ +GLboolean +_mesa_prepare_mipmap_level(struct gl_context *ctx, + struct gl_texture_object *texObj, GLuint level, + GLsizei width, GLsizei height, GLsizei depth, + GLsizei border, GLenum intFormat, gl_format format) +{ + const GLuint numFaces = texObj->Target == GL_TEXTURE_CUBE_MAP ? 6 : 1; + GLuint face; + + if (texObj->Immutable) { + /* The texture was created with glTexStorage() so the number/size of + * mipmap levels is fixed and the storage for all images is already + * allocated. + */ + if (!texObj->Image[0][level]) { + /* No more levels to create - we're done */ + return GL_FALSE; + } + else { + /* Nothing to do - the texture memory must have already been + * allocated to the right size so we're all set. + */ + return GL_TRUE; + } + } + + for (face = 0; face < numFaces; face++) { + struct gl_texture_image *dstImage; + GLenum target; + + if (numFaces == 1) + target = texObj->Target; + else + target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + face; + + dstImage = _mesa_get_tex_image(ctx, texObj, target, level); + if (!dstImage) { + /* out of memory */ + return GL_FALSE; + } + + if (dstImage->Width != width || + dstImage->Height != height || + dstImage->Depth != depth || + dstImage->Border != border || + dstImage->InternalFormat != intFormat || + dstImage->TexFormat != format) { + /* need to (re)allocate image */ + ctx->Driver.FreeTextureImageBuffer(ctx, dstImage); + + _mesa_init_teximage_fields(ctx, target, dstImage, + width, height, depth, + border, intFormat, format); + + ctx->Driver.AllocTextureImageBuffer(ctx, dstImage, + format, width, height, depth); + + /* in case the mipmap level is part of an FBO: */ + _mesa_update_fbo_texture(ctx, texObj, face, level); + + ctx->NewState |= _NEW_TEXTURE; + } + } + + return GL_TRUE; +} + + static void generate_mipmap_uncompressed(struct gl_context *ctx, GLenum target, struct gl_texture_object *texObj, @@ -1841,31 +1916,20 @@ generate_mipmap_uncompressed(struct gl_context *ctx, GLenum target, if (!nextLevel) return; - /* get dest gl_texture_image */ - dstImage = _mesa_get_tex_image(ctx, texObj, target, level + 1); - if (!dstImage) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps"); + if (!_mesa_prepare_mipmap_level(ctx, texObj, level + 1, + dstWidth, dstHeight, dstDepth, + border, srcImage->InternalFormat, + srcImage->TexFormat)) { return; } - /* Free old image data */ - ctx->Driver.FreeTextureImageBuffer(ctx, dstImage); - - _mesa_init_teximage_fields(ctx, target, dstImage, dstWidth, dstHeight, - dstDepth, border, srcImage->InternalFormat, - srcImage->TexFormat); - - /* Alloc storage for new texture image */ - if (!ctx->Driver.AllocTextureImageBuffer(ctx, dstImage, - dstImage->TexFormat, - dstWidth, dstHeight, - dstDepth)) { + /* get dest gl_texture_image */ + dstImage = _mesa_get_tex_image(ctx, texObj, target, level + 1); + if (!dstImage) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps"); return; } - ASSERT(dstImage->TexFormat); - if (target == GL_TEXTURE_1D_ARRAY) { srcDepth = srcHeight; dstDepth = dstHeight; @@ -2052,9 +2116,7 @@ generate_mipmap_compressed(struct gl_context *ctx, GLenum target, return; } - /* Free old image data */ - ctx->Driver.FreeTextureImageBuffer(ctx, dstImage); - + /* rescale src image to dest image */ _mesa_generate_mipmap_level(target, temp_datatype, components, border, srcWidth, srcHeight, srcDepth, (const GLubyte **) &temp_src, @@ -2062,19 +2124,19 @@ generate_mipmap_compressed(struct gl_context *ctx, GLenum target, dstWidth, dstHeight, dstDepth, &temp_dst, temp_dst_stride); - /* initialize new image */ - _mesa_init_teximage_fields(ctx, target, dstImage, dstWidth, dstHeight, - dstDepth, border, srcImage->InternalFormat, - srcImage->TexFormat); - - /* Free old dest texture image buffer */ - ctx->Driver.FreeTextureImageBuffer(ctx, dstImage); + if (!_mesa_prepare_mipmap_level(ctx, texObj, level + 1, + dstWidth, dstHeight, dstDepth, + border, srcImage->InternalFormat, + srcImage->TexFormat)) { + return; + } - ctx->Driver.TexImage2D(ctx, target, level + 1, - srcImage->InternalFormat, - dstWidth, dstHeight, border, - temp_base_format, temp_datatype, - temp_dst, &ctx->DefaultPacking, texObj, dstImage); + /* The image space was allocated above so use glTexSubImage now */ + ctx->Driver.TexSubImage2D(ctx, target, level + 1, + 0, 0, dstWidth, dstHeight, + temp_base_format, temp_datatype, + temp_dst, &ctx->DefaultPacking, + texObj, dstImage); /* swap src and dest pointers */ { diff --git a/mesalib/src/mesa/main/mipmap.h b/mesalib/src/mesa/main/mipmap.h index 1fb9146a1..072794cb6 100644 --- a/mesalib/src/mesa/main/mipmap.h +++ b/mesalib/src/mesa/main/mipmap.h @@ -41,6 +41,12 @@ _mesa_generate_mipmap_level(GLenum target, GLint dstRowStride); +extern GLboolean +_mesa_prepare_mipmap_level(struct gl_context *ctx, + struct gl_texture_object *texObj, GLuint level, + GLsizei width, GLsizei height, GLsizei depth, + GLsizei border, GLenum intFormat, gl_format format); + extern void _mesa_generate_mipmap(struct gl_context *ctx, GLenum target, struct gl_texture_object *texObj); diff --git a/mesalib/src/mesa/main/mtypes.h b/mesalib/src/mesa/main/mtypes.h index 193434976..0e29dc0dc 100644 --- a/mesalib/src/mesa/main/mtypes.h +++ b/mesalib/src/mesa/main/mtypes.h @@ -2355,6 +2355,8 @@ struct gl_transform_feedback_object GLint RefCount; GLboolean Active; /**< Is transform feedback enabled? */ GLboolean Paused; /**< Is transform feedback paused? */ + GLboolean EndedAnytime; /**< Has EndTransformFeedback been called + at least once? */ /** The feedback buffers */ GLuint BufferNames[MAX_FEEDBACK_ATTRIBS]; diff --git a/mesalib/src/mesa/main/texformat.c b/mesalib/src/mesa/main/texformat.c index c776b4160..7e60541c3 100644 --- a/mesalib/src/mesa/main/texformat.c +++ b/mesalib/src/mesa/main/texformat.c @@ -118,6 +118,8 @@ _mesa_choose_tex_format( struct gl_context *ctx, GLint internalFormat, break; case GL_R3_G3_B2: RETURN_IF_SUPPORTED(MESA_FORMAT_RGB332); + RETURN_IF_SUPPORTED(MESA_FORMAT_RGB565); + RETURN_IF_SUPPORTED(MESA_FORMAT_RGB565_REV); RETURN_IF_SUPPORTED(MESA_FORMAT_RGB888); RETURN_IF_SUPPORTED(MESA_FORMAT_XRGB8888); RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB8888); diff --git a/mesalib/src/mesa/main/texgetimage.c b/mesalib/src/mesa/main/texgetimage.c index ae0d51fbb..3f2418729 100644 --- a/mesalib/src/mesa/main/texgetimage.c +++ b/mesalib/src/mesa/main/texgetimage.c @@ -708,6 +708,14 @@ getteximage_error_check(struct gl_context *ctx, GLenum target, GLint level, return GL_TRUE; } + if (!_mesa_is_legal_format_and_type(ctx, format, type)) { + /*GL_INVALID_OPERATION is generated by a format/type + * mismatch (see the 1.2 spec page 94, sec 3.6.4.) + */ + _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(target)"); + return GL_TRUE; + } + baseFormat = _mesa_get_format_base_format(texImage->TexFormat); /* Make sure the requested image format is compatible with the diff --git a/mesalib/src/mesa/main/teximage.c b/mesalib/src/mesa/main/teximage.c index 8a002b675..eccc0fd39 100644 --- a/mesalib/src/mesa/main/teximage.c +++ b/mesalib/src/mesa/main/teximage.c @@ -2205,9 +2205,10 @@ check_rtt_cb(GLuint key, void *data, void *userData) * in size or format since that effects FBO completeness. * Any FBOs rendering into the texture must be re-validated. */ -static void -update_fbo_texture(struct gl_context *ctx, struct gl_texture_object *texObj, - GLuint face, GLuint level) +void +_mesa_update_fbo_texture(struct gl_context *ctx, + struct gl_texture_object *texObj, + GLuint face, GLuint level) { /* Only check this texture if it's been marked as RenderToTexture */ if (texObj->_RenderToTexture) { @@ -2502,7 +2503,7 @@ teximage(struct gl_context *ctx, GLuint dims, check_gen_mipmap(ctx, target, texObj, level); - update_fbo_texture(ctx, texObj, face, level); + _mesa_update_fbo_texture(ctx, texObj, face, level); /* state update */ texObj->_Complete = GL_FALSE; @@ -2844,7 +2845,7 @@ copyteximage(struct gl_context *ctx, GLuint dims, check_gen_mipmap(ctx, target, texObj, level); - update_fbo_texture(ctx, texObj, face, level); + _mesa_update_fbo_texture(ctx, texObj, face, level); /* state update */ texObj->_Complete = GL_FALSE; diff --git a/mesalib/src/mesa/main/teximage.h b/mesalib/src/mesa/main/teximage.h index 9cc7d5a54..d756646ce 100644 --- a/mesalib/src/mesa/main/teximage.h +++ b/mesalib/src/mesa/main/teximage.h @@ -80,6 +80,10 @@ _mesa_choose_texture_format(struct gl_context *ctx, GLenum target, GLint level, GLenum internalFormat, GLenum format, GLenum type); +extern void +_mesa_update_fbo_texture(struct gl_context *ctx, + struct gl_texture_object *texObj, + GLuint face, GLuint level); extern void _mesa_clear_texture_image(struct gl_context *ctx, diff --git a/mesalib/src/mesa/main/transformfeedback.c b/mesalib/src/mesa/main/transformfeedback.c index 799245d4e..824f66a35 100644 --- a/mesalib/src/mesa/main/transformfeedback.c +++ b/mesalib/src/mesa/main/transformfeedback.c @@ -294,18 +294,6 @@ resume_transform_feedback(struct gl_context *ctx, /* nop */ } -/** Default fallback for ctx->Driver.DrawTransformFeedback() */ -static void -draw_transform_feedback(struct gl_context *ctx, GLenum mode, - struct gl_transform_feedback_object *obj) -{ - /* XXX to do */ - /* - * Get number of vertices in obj's feedback buffer. - * Call ctx->Exec.DrawArrays(mode, 0, count); - */ -} - /** * Plug in default device driver functions for transform feedback. @@ -320,7 +308,6 @@ _mesa_init_transform_feedback_functions(struct dd_function_table *driver) driver->EndTransformFeedback = end_transform_feedback; driver->PauseTransformFeedback = pause_transform_feedback; driver->ResumeTransformFeedback = resume_transform_feedback; - driver->DrawTransformFeedback = draw_transform_feedback; } @@ -342,7 +329,6 @@ _mesa_init_transform_feedback_dispatch(struct _glapi_table *disp) SET_IsTransformFeedback(disp, _mesa_IsTransformFeedback); SET_PauseTransformFeedback(disp, _mesa_PauseTransformFeedback); SET_ResumeTransformFeedback(disp, _mesa_ResumeTransformFeedback); - SET_DrawTransformFeedback(disp, _mesa_DrawTransformFeedback); } @@ -401,6 +387,7 @@ _mesa_EndTransformFeedback(void) FLUSH_VERTICES(ctx, _NEW_TRANSFORM_FEEDBACK); ctx->TransformFeedback.CurrentObject->Active = GL_FALSE; + ctx->TransformFeedback.CurrentObject->EndedAnytime = GL_TRUE; assert(ctx->Driver.EndTransformFeedback); ctx->Driver.EndTransformFeedback(ctx, obj); @@ -714,8 +701,8 @@ _mesa_GetTransformFeedbackVarying(GLuint program, GLuint index, -static struct gl_transform_feedback_object * -lookup_transform_feedback_object(struct gl_context *ctx, GLuint name) +struct gl_transform_feedback_object * +_mesa_lookup_transform_feedback_object(struct gl_context *ctx, GLuint name) { if (name == 0) { return ctx->TransformFeedback.DefaultObject; @@ -780,7 +767,7 @@ _mesa_IsTransformFeedback(GLuint name) ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); - if (name && lookup_transform_feedback_object(ctx, name)) + if (name && _mesa_lookup_transform_feedback_object(ctx, name)) return GL_TRUE; else return GL_FALSE; @@ -809,7 +796,7 @@ _mesa_BindTransformFeedback(GLenum target, GLuint name) return; } - obj = lookup_transform_feedback_object(ctx, name); + obj = _mesa_lookup_transform_feedback_object(ctx, name); if (!obj) { _mesa_error(ctx, GL_INVALID_OPERATION, "glBindTransformFeedback(name=%u)", name); @@ -844,7 +831,7 @@ _mesa_DeleteTransformFeedbacks(GLsizei n, const GLuint *names) for (i = 0; i < n; i++) { if (names[i] > 0) { struct gl_transform_feedback_object *obj - = lookup_transform_feedback_object(ctx, names[i]); + = _mesa_lookup_transform_feedback_object(ctx, names[i]); if (obj) { if (obj->Active) { _mesa_error(ctx, GL_INVALID_OPERATION, @@ -912,40 +899,4 @@ _mesa_ResumeTransformFeedback(void) ctx->Driver.ResumeTransformFeedback(ctx, obj); } - -/** - * Draw the vertex data in a transform feedback object. - * \param mode GL_POINTS, GL_LINES, GL_TRIANGLE_STRIP, etc. - * \param name the transform feedback object - * The number of vertices comes from the transform feedback object. - * User still has to setup of the vertex attribute info with - * glVertexPointer, glColorPointer, etc. - * Part of GL_ARB_transform_feedback2. - */ -void GLAPIENTRY -_mesa_DrawTransformFeedback(GLenum mode, GLuint name) -{ - GET_CURRENT_CONTEXT(ctx); - struct gl_transform_feedback_object *obj = - lookup_transform_feedback_object(ctx, name); - - if (mode > GL_POLYGON) { - _mesa_error(ctx, GL_INVALID_ENUM, - "glDrawTransformFeedback(mode=0x%x)", mode); - return; - } - if (!obj) { - _mesa_error(ctx, GL_INVALID_VALUE, - "glDrawTransformFeedback(name = %u)", name); - return; - } - - /* XXX check if EndTransformFeedback has never been called while - * the object was bound - */ - - assert(ctx->Driver.DrawTransformFeedback); - ctx->Driver.DrawTransformFeedback(ctx, mode, obj); -} - #endif /* FEATURE_EXT_transform_feedback */ diff --git a/mesalib/src/mesa/main/transformfeedback.h b/mesalib/src/mesa/main/transformfeedback.h index 9447effa9..8a6672d58 100644 --- a/mesalib/src/mesa/main/transformfeedback.h +++ b/mesalib/src/mesa/main/transformfeedback.h @@ -87,6 +87,9 @@ _mesa_GetTransformFeedbackVarying(GLuint program, GLuint index, /*** GL_ARB_transform_feedback2 ***/ +struct gl_transform_feedback_object * +_mesa_lookup_transform_feedback_object(struct gl_context *ctx, GLuint name); + extern void GLAPIENTRY _mesa_GenTransformFeedbacks(GLsizei n, GLuint *names); @@ -105,9 +108,6 @@ _mesa_PauseTransformFeedback(void); extern void GLAPIENTRY _mesa_ResumeTransformFeedback(void); -extern void GLAPIENTRY -_mesa_DrawTransformFeedback(GLenum mode, GLuint name); - #else /* FEATURE_EXT_transform_feedback */ static inline GLboolean diff --git a/mesalib/src/mesa/main/varray.h b/mesalib/src/mesa/main/varray.h index 6fcc0a336..b6041bd78 100644 --- a/mesalib/src/mesa/main/varray.h +++ b/mesalib/src/mesa/main/varray.h @@ -245,6 +245,13 @@ _mesa_DrawRangeElementsBaseVertex(GLenum mode, GLuint start, GLuint end, const GLvoid *indices, GLint basevertex); +#if FEATURE_EXT_transform_feedback + +extern void GLAPIENTRY +_mesa_DrawTransformFeedback(GLenum mode, GLuint name); + +#endif + extern void GLAPIENTRY _mesa_PrimitiveRestartIndex(GLuint index); diff --git a/mesalib/src/mesa/main/vtxfmt.c b/mesalib/src/mesa/main/vtxfmt.c index 03735d779..f3cca937d 100644 --- a/mesalib/src/mesa/main/vtxfmt.c +++ b/mesalib/src/mesa/main/vtxfmt.c @@ -107,6 +107,7 @@ install_vtxfmt( struct _glapi_table *tab, const GLvertexformat *vfmt ) SET_DrawArraysInstancedARB(tab, vfmt->DrawArraysInstanced); SET_DrawElementsInstancedARB(tab, vfmt->DrawElementsInstanced); SET_DrawElementsInstancedBaseVertex(tab, vfmt->DrawElementsInstancedBaseVertex); + SET_DrawTransformFeedback(tab, vfmt->DrawTransformFeedback); /* GL_NV_vertex_program */ SET_VertexAttrib1fNV(tab, vfmt->VertexAttrib1fNV); diff --git a/mesalib/src/mesa/program/prog_parameter_layout.c b/mesalib/src/mesa/program/prog_parameter_layout.c index 28fca3b92..e4f2db3b3 100644 --- a/mesalib/src/mesa/program/prog_parameter_layout.c +++ b/mesalib/src/mesa/program/prog_parameter_layout.c @@ -138,6 +138,7 @@ _mesa_layout_parameters(struct asm_parser_state *state) inst->SrcReg[i].Symbol->param_binding_length); if (new_begin < 0) { + _mesa_free_parameter_list(layout); return GL_FALSE; } diff --git a/mesalib/src/mesa/state_tracker/st_atom_pixeltransfer.c b/mesalib/src/mesa/state_tracker/st_atom_pixeltransfer.c index afca60976..fb1e4092c 100644 --- a/mesalib/src/mesa/state_tracker/st_atom_pixeltransfer.c +++ b/mesalib/src/mesa/state_tracker/st_atom_pixeltransfer.c @@ -266,6 +266,7 @@ get_pixel_transfer_program(struct gl_context *ctx, const struct state_key *key) if (!fp->Base.Instructions) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating pixel transfer program"); + _mesa_free_parameter_list(params); return NULL; } diff --git a/mesalib/src/mesa/state_tracker/st_atom_rasterizer.c b/mesalib/src/mesa/state_tracker/st_atom_rasterizer.c index 250cbb226..4aa0b4e2a 100644 --- a/mesalib/src/mesa/state_tracker/st_atom_rasterizer.c +++ b/mesalib/src/mesa/state_tracker/st_atom_rasterizer.c @@ -256,9 +256,11 @@ static void update_raster_state( struct st_context *st ) /* _NEW_FRAG_CLAMP */ raster->clamp_fragment_color = ctx->Color._ClampFragmentColor; - raster->gl_rasterization_rules = 1; + /* _NEW_TRANSFORM */ + raster->rasterizer_discard = ctx->TransformFeedback.RasterDiscard; + cso_set_rasterizer(st->cso_context, raster); } @@ -273,7 +275,8 @@ const struct st_tracked_state st_update_rasterizer = { _NEW_POLYGON | _NEW_PROGRAM | _NEW_SCISSOR | - _NEW_FRAG_CLAMP), /* mesa state dependencies*/ + _NEW_FRAG_CLAMP | + _NEW_TRANSFORM), /* mesa state dependencies*/ ST_NEW_VERTEX_PROGRAM, /* state tracker dependencies */ }, update_raster_state /* update function */ diff --git a/mesalib/src/mesa/state_tracker/st_cb_bitmap.c b/mesalib/src/mesa/state_tracker/st_cb_bitmap.c index fa37be0b6..af33bcf86 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_bitmap.c +++ b/mesalib/src/mesa/state_tracker/st_cb_bitmap.c @@ -483,6 +483,7 @@ draw_bitmap_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z, cso_save_fragment_sampler_views(cso); cso_save_viewport(cso); cso_save_fragment_shader(cso); + cso_save_stream_outputs(cso); cso_save_vertex_shader(cso); cso_save_geometry_shader(cso); cso_save_vertex_elements(cso); @@ -542,6 +543,7 @@ draw_bitmap_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z, } cso_set_vertex_elements(cso, 3, st->velems_util_draw); + cso_set_stream_outputs(st->cso_context, 0, NULL, 0); /* convert Z from [0,1] to [-1,-1] to match viewport Z scale/bias */ z = z * 2.0f - 1.0f; @@ -568,6 +570,7 @@ draw_bitmap_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z, cso_restore_geometry_shader(cso); cso_restore_vertex_elements(cso); cso_restore_vertex_buffers(cso); + cso_restore_stream_outputs(cso); } diff --git a/mesalib/src/mesa/state_tracker/st_cb_clear.c b/mesalib/src/mesa/state_tracker/st_cb_clear.c index 61d98aeb9..23700eeb7 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_clear.c +++ b/mesalib/src/mesa/state_tracker/st_cb_clear.c @@ -250,6 +250,7 @@ clear_with_quad(struct gl_context *ctx, cso_save_viewport(st->cso_context); cso_save_clip(st->cso_context); cso_save_fragment_shader(st->cso_context); + cso_save_stream_outputs(st->cso_context); cso_save_vertex_shader(st->cso_context); cso_save_geometry_shader(st->cso_context); cso_save_vertex_elements(st->cso_context); @@ -306,6 +307,7 @@ clear_with_quad(struct gl_context *ctx, } cso_set_vertex_elements(st->cso_context, 2, st->velems_util_draw); + cso_set_stream_outputs(st->cso_context, 0, NULL, 0); cso_set_rasterizer(st->cso_context, &st->clear.raster); @@ -350,6 +352,7 @@ clear_with_quad(struct gl_context *ctx, cso_restore_geometry_shader(st->cso_context); cso_restore_vertex_elements(st->cso_context); cso_restore_vertex_buffers(st->cso_context); + cso_restore_stream_outputs(st->cso_context); } diff --git a/mesalib/src/mesa/state_tracker/st_cb_drawpixels.c b/mesalib/src/mesa/state_tracker/st_cb_drawpixels.c index 65b444552..318ba7d06 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_drawpixels.c +++ b/mesalib/src/mesa/state_tracker/st_cb_drawpixels.c @@ -671,6 +671,7 @@ draw_textured_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z, cso_save_samplers(cso); cso_save_fragment_sampler_views(cso); cso_save_fragment_shader(cso); + cso_save_stream_outputs(cso); cso_save_vertex_shader(cso); cso_save_geometry_shader(cso); cso_save_vertex_elements(cso); @@ -761,6 +762,7 @@ draw_textured_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z, } cso_set_vertex_elements(cso, 3, st->velems_util_draw); + cso_set_stream_outputs(st->cso_context, 0, NULL, 0); /* texture state: */ cso_set_fragment_sampler_views(cso, num_sampler_view, sv); @@ -796,6 +798,7 @@ draw_textured_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z, cso_restore_geometry_shader(cso); cso_restore_vertex_elements(cso); cso_restore_vertex_buffers(cso); + cso_restore_stream_outputs(cso); if (write_stencil) { cso_restore_depth_stencil_alpha(cso); cso_restore_blend(cso); diff --git a/mesalib/src/mesa/state_tracker/st_cb_drawtex.c b/mesalib/src/mesa/state_tracker/st_cb_drawtex.c index 332b0d1b6..6144eb99c 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_drawtex.c +++ b/mesalib/src/mesa/state_tracker/st_cb_drawtex.c @@ -227,6 +227,7 @@ st_DrawTex(struct gl_context *ctx, GLfloat x, GLfloat y, GLfloat z, cso_save_viewport(cso); + cso_save_stream_outputs(cso); cso_save_vertex_shader(cso); cso_save_geometry_shader(cso); cso_save_vertex_elements(cso); @@ -246,6 +247,7 @@ st_DrawTex(struct gl_context *ctx, GLfloat x, GLfloat y, GLfloat z, velements[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; } cso_set_vertex_elements(cso, numAttribs, velements); + cso_set_stream_outputs(st->cso_context, 0, NULL, 0); /* viewport state: viewport matching window dims */ { @@ -281,6 +283,7 @@ st_DrawTex(struct gl_context *ctx, GLfloat x, GLfloat y, GLfloat z, cso_restore_geometry_shader(cso); cso_restore_vertex_elements(cso); cso_restore_vertex_buffers(cso); + cso_restore_stream_outputs(cso); } diff --git a/mesalib/src/mesa/state_tracker/st_cb_rasterpos.c b/mesalib/src/mesa/state_tracker/st_cb_rasterpos.c index 2e9eb7265..2c21dc9a7 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_rasterpos.c +++ b/mesalib/src/mesa/state_tracker/st_cb_rasterpos.c @@ -1,272 +1,273 @@ -/**************************************************************************
- *
- * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- **************************************************************************/
-
-/**
- * glRasterPos implementation. Basically render a GL_POINT with our
- * private draw module. Plug in a special "rasterpos" stage at the end
- * of the 'draw' pipeline to capture the results and update the current
- * raster pos attributes.
- *
- * Authors:
- * Brian Paul
- */
-
-
-#include "main/imports.h"
-#include "main/macros.h"
-#include "main/mfeatures.h"
-#include "main/feedback.h"
-
-#include "st_context.h"
-#include "st_atom.h"
-#include "st_draw.h"
-#include "st_cb_rasterpos.h"
-#include "draw/draw_context.h"
-#include "draw/draw_pipe.h"
-#include "vbo/vbo.h"
-
-
-#if FEATURE_rastpos
-
-/**
- * Our special drawing pipeline stage (replaces rasterization).
- */
-struct rastpos_stage
-{
- struct draw_stage stage; /**< Base class */
- struct gl_context *ctx; /**< Rendering context */
-
- /* vertex attrib info we can setup once and re-use */
- struct gl_client_array array[VERT_ATTRIB_MAX];
- const struct gl_client_array *arrays[VERT_ATTRIB_MAX];
- struct _mesa_prim prim;
-};
-
-
-static INLINE struct rastpos_stage *
-rastpos_stage( struct draw_stage *stage )
-{
- return (struct rastpos_stage *) stage;
-}
-
-static void
-rastpos_flush( struct draw_stage *stage, unsigned flags )
-{
- /* no-op */
-}
-
-static void
-rastpos_reset_stipple_counter( struct draw_stage *stage )
-{
- /* no-op */
-}
-
-static void
-rastpos_tri( struct draw_stage *stage, struct prim_header *prim )
-{
- /* should never get here */
- assert(0);
-}
-
-static void
-rastpos_line( struct draw_stage *stage, struct prim_header *prim )
-{
- /* should never get here */
- assert(0);
-}
-
-static void
-rastpos_destroy(struct draw_stage *stage)
-{
- free(stage);
-}
-
-
-/**
- * Update a raster pos attribute from the vertex result if it's present,
- * else copy the current attrib.
- */
-static void
-update_attrib(struct gl_context *ctx, const GLuint *outputMapping,
- const struct vertex_header *vert,
- GLfloat *dest,
- GLuint result, GLuint defaultAttrib)
-{
- const GLfloat *src;
- const GLuint k = outputMapping[result];
- if (k != ~0U)
- src = vert->data[k];
- else
- src = ctx->Current.Attrib[defaultAttrib];
- COPY_4V(dest, src);
-}
-
-
-/**
- * Normally, this function would render a GL_POINT.
- */
-static void
-rastpos_point(struct draw_stage *stage, struct prim_header *prim)
-{
- struct rastpos_stage *rs = rastpos_stage(stage);
- struct gl_context *ctx = rs->ctx;
- struct st_context *st = st_context(ctx);
- const GLfloat height = (GLfloat) ctx->DrawBuffer->Height;
- const GLuint *outputMapping = st->vertex_result_to_slot;
- const GLfloat *pos;
- GLuint i;
-
- /* if we get here, we didn't get clipped */
- ctx->Current.RasterPosValid = GL_TRUE;
-
- /* update raster pos */
- pos = prim->v[0]->data[0];
- ctx->Current.RasterPos[0] = pos[0];
- if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP)
- ctx->Current.RasterPos[1] = height - pos[1]; /* invert Y */
- else
- ctx->Current.RasterPos[1] = pos[1];
- ctx->Current.RasterPos[2] = pos[2];
- ctx->Current.RasterPos[3] = pos[3];
-
- /* update other raster attribs */
- update_attrib(ctx, outputMapping, prim->v[0],
- ctx->Current.RasterColor,
- VERT_RESULT_COL0, VERT_ATTRIB_COLOR0);
-
- update_attrib(ctx, outputMapping, prim->v[0],
- ctx->Current.RasterSecondaryColor,
- VERT_RESULT_COL1, VERT_ATTRIB_COLOR1);
-
- for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) {
- update_attrib(ctx, outputMapping, prim->v[0],
- ctx->Current.RasterTexCoords[i],
- VERT_RESULT_TEX0 + i, VERT_ATTRIB_TEX0 + i);
- }
-
- if (ctx->RenderMode == GL_SELECT) {
- _mesa_update_hitflag( ctx, ctx->Current.RasterPos[2] );
- }
-}
-
-
-/**
- * Create rasterpos "drawing" stage.
- */
-static struct rastpos_stage *
-new_draw_rastpos_stage(struct gl_context *ctx, struct draw_context *draw)
-{
- struct rastpos_stage *rs = ST_CALLOC_STRUCT(rastpos_stage);
- GLuint i;
-
- rs->stage.draw = draw;
- rs->stage.next = NULL;
- rs->stage.point = rastpos_point;
- rs->stage.line = rastpos_line;
- rs->stage.tri = rastpos_tri;
- rs->stage.flush = rastpos_flush;
- rs->stage.destroy = rastpos_destroy;
- rs->stage.reset_stipple_counter = rastpos_reset_stipple_counter;
- rs->stage.destroy = rastpos_destroy;
- rs->ctx = ctx;
-
- for (i = 0; i < Elements(rs->array); i++) {
- rs->array[i].Size = 4;
- rs->array[i].Type = GL_FLOAT;
- rs->array[i].Format = GL_RGBA;
- rs->array[i].Stride = 0;
- rs->array[i].StrideB = 0;
- rs->array[i].Ptr = (GLubyte *) ctx->Current.Attrib[i];
- rs->array[i].Enabled = GL_TRUE;
- rs->array[i].Normalized = GL_TRUE;
- rs->array[i].BufferObj = NULL;
- rs->arrays[i] = &rs->array[i];
- }
-
- rs->prim.mode = GL_POINTS;
- rs->prim.indexed = 0;
- rs->prim.begin = 1;
- rs->prim.end = 1;
- rs->prim.weak = 0;
- rs->prim.start = 0;
- rs->prim.count = 1;
-
- return rs;
-}
-
-
-static void
-st_RasterPos(struct gl_context *ctx, const GLfloat v[4])
-{
- struct st_context *st = st_context(ctx);
- struct draw_context *draw = st->draw;
- struct rastpos_stage *rs;
-
- if (st->rastpos_stage) {
- /* get rastpos stage info */
- rs = rastpos_stage(st->rastpos_stage);
- }
- else {
- /* create rastpos draw stage */
- rs = new_draw_rastpos_stage(ctx, draw);
- st->rastpos_stage = &rs->stage;
- }
-
- /* plug our rastpos stage into the draw module */
- draw_set_rasterize_stage(st->draw, st->rastpos_stage);
-
- /* make sure everything's up to date */
- st_validate_state(st);
-
- /* This will get set only if rastpos_point(), above, gets called */
- ctx->Current.RasterPosValid = GL_FALSE;
-
- /* All vertex attribs but position were previously initialized above.
- * Just plug in position pointer now.
- */
- rs->array[0].Ptr = (GLubyte *) v;
-
- /* draw the point */
- st_feedback_draw_vbo(ctx, rs->arrays, &rs->prim, 1, NULL, GL_TRUE, 0, 1);
-
- /* restore draw's rasterization stage depending on rendermode */
- if (ctx->RenderMode == GL_FEEDBACK) {
- draw_set_rasterize_stage(draw, st->feedback_stage);
- }
- else if (ctx->RenderMode == GL_SELECT) {
- draw_set_rasterize_stage(draw, st->selection_stage);
- }
-}
-
-
-
-void st_init_rasterpos_functions(struct dd_function_table *functions)
-{
- functions->RasterPos = st_RasterPos;
-}
-
-#endif /* FEATURE_rastpos */
+/************************************************************************** + * + * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +/** + * glRasterPos implementation. Basically render a GL_POINT with our + * private draw module. Plug in a special "rasterpos" stage at the end + * of the 'draw' pipeline to capture the results and update the current + * raster pos attributes. + * + * Authors: + * Brian Paul + */ + + +#include "main/imports.h" +#include "main/macros.h" +#include "main/mfeatures.h" +#include "main/feedback.h" + +#include "st_context.h" +#include "st_atom.h" +#include "st_draw.h" +#include "st_cb_rasterpos.h" +#include "draw/draw_context.h" +#include "draw/draw_pipe.h" +#include "vbo/vbo.h" + + +#if FEATURE_rastpos + +/** + * Our special drawing pipeline stage (replaces rasterization). + */ +struct rastpos_stage +{ + struct draw_stage stage; /**< Base class */ + struct gl_context *ctx; /**< Rendering context */ + + /* vertex attrib info we can setup once and re-use */ + struct gl_client_array array[VERT_ATTRIB_MAX]; + const struct gl_client_array *arrays[VERT_ATTRIB_MAX]; + struct _mesa_prim prim; +}; + + +static INLINE struct rastpos_stage * +rastpos_stage( struct draw_stage *stage ) +{ + return (struct rastpos_stage *) stage; +} + +static void +rastpos_flush( struct draw_stage *stage, unsigned flags ) +{ + /* no-op */ +} + +static void +rastpos_reset_stipple_counter( struct draw_stage *stage ) +{ + /* no-op */ +} + +static void +rastpos_tri( struct draw_stage *stage, struct prim_header *prim ) +{ + /* should never get here */ + assert(0); +} + +static void +rastpos_line( struct draw_stage *stage, struct prim_header *prim ) +{ + /* should never get here */ + assert(0); +} + +static void +rastpos_destroy(struct draw_stage *stage) +{ + free(stage); +} + + +/** + * Update a raster pos attribute from the vertex result if it's present, + * else copy the current attrib. + */ +static void +update_attrib(struct gl_context *ctx, const GLuint *outputMapping, + const struct vertex_header *vert, + GLfloat *dest, + GLuint result, GLuint defaultAttrib) +{ + const GLfloat *src; + const GLuint k = outputMapping[result]; + if (k != ~0U) + src = vert->data[k]; + else + src = ctx->Current.Attrib[defaultAttrib]; + COPY_4V(dest, src); +} + + +/** + * Normally, this function would render a GL_POINT. + */ +static void +rastpos_point(struct draw_stage *stage, struct prim_header *prim) +{ + struct rastpos_stage *rs = rastpos_stage(stage); + struct gl_context *ctx = rs->ctx; + struct st_context *st = st_context(ctx); + const GLfloat height = (GLfloat) ctx->DrawBuffer->Height; + const GLuint *outputMapping = st->vertex_result_to_slot; + const GLfloat *pos; + GLuint i; + + /* if we get here, we didn't get clipped */ + ctx->Current.RasterPosValid = GL_TRUE; + + /* update raster pos */ + pos = prim->v[0]->data[0]; + ctx->Current.RasterPos[0] = pos[0]; + if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) + ctx->Current.RasterPos[1] = height - pos[1]; /* invert Y */ + else + ctx->Current.RasterPos[1] = pos[1]; + ctx->Current.RasterPos[2] = pos[2]; + ctx->Current.RasterPos[3] = pos[3]; + + /* update other raster attribs */ + update_attrib(ctx, outputMapping, prim->v[0], + ctx->Current.RasterColor, + VERT_RESULT_COL0, VERT_ATTRIB_COLOR0); + + update_attrib(ctx, outputMapping, prim->v[0], + ctx->Current.RasterSecondaryColor, + VERT_RESULT_COL1, VERT_ATTRIB_COLOR1); + + for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) { + update_attrib(ctx, outputMapping, prim->v[0], + ctx->Current.RasterTexCoords[i], + VERT_RESULT_TEX0 + i, VERT_ATTRIB_TEX0 + i); + } + + if (ctx->RenderMode == GL_SELECT) { + _mesa_update_hitflag( ctx, ctx->Current.RasterPos[2] ); + } +} + + +/** + * Create rasterpos "drawing" stage. + */ +static struct rastpos_stage * +new_draw_rastpos_stage(struct gl_context *ctx, struct draw_context *draw) +{ + struct rastpos_stage *rs = ST_CALLOC_STRUCT(rastpos_stage); + GLuint i; + + rs->stage.draw = draw; + rs->stage.next = NULL; + rs->stage.point = rastpos_point; + rs->stage.line = rastpos_line; + rs->stage.tri = rastpos_tri; + rs->stage.flush = rastpos_flush; + rs->stage.destroy = rastpos_destroy; + rs->stage.reset_stipple_counter = rastpos_reset_stipple_counter; + rs->stage.destroy = rastpos_destroy; + rs->ctx = ctx; + + for (i = 0; i < Elements(rs->array); i++) { + rs->array[i].Size = 4; + rs->array[i].Type = GL_FLOAT; + rs->array[i].Format = GL_RGBA; + rs->array[i].Stride = 0; + rs->array[i].StrideB = 0; + rs->array[i].Ptr = (GLubyte *) ctx->Current.Attrib[i]; + rs->array[i].Enabled = GL_TRUE; + rs->array[i].Normalized = GL_TRUE; + rs->array[i].BufferObj = NULL; + rs->arrays[i] = &rs->array[i]; + } + + rs->prim.mode = GL_POINTS; + rs->prim.indexed = 0; + rs->prim.begin = 1; + rs->prim.end = 1; + rs->prim.weak = 0; + rs->prim.start = 0; + rs->prim.count = 1; + + return rs; +} + + +static void +st_RasterPos(struct gl_context *ctx, const GLfloat v[4]) +{ + struct st_context *st = st_context(ctx); + struct draw_context *draw = st->draw; + struct rastpos_stage *rs; + + if (st->rastpos_stage) { + /* get rastpos stage info */ + rs = rastpos_stage(st->rastpos_stage); + } + else { + /* create rastpos draw stage */ + rs = new_draw_rastpos_stage(ctx, draw); + st->rastpos_stage = &rs->stage; + } + + /* plug our rastpos stage into the draw module */ + draw_set_rasterize_stage(st->draw, st->rastpos_stage); + + /* make sure everything's up to date */ + st_validate_state(st); + + /* This will get set only if rastpos_point(), above, gets called */ + ctx->Current.RasterPosValid = GL_FALSE; + + /* All vertex attribs but position were previously initialized above. + * Just plug in position pointer now. + */ + rs->array[0].Ptr = (GLubyte *) v; + + /* draw the point */ + st_feedback_draw_vbo(ctx, rs->arrays, &rs->prim, 1, NULL, GL_TRUE, 0, 1, + NULL); + + /* restore draw's rasterization stage depending on rendermode */ + if (ctx->RenderMode == GL_FEEDBACK) { + draw_set_rasterize_stage(draw, st->feedback_stage); + } + else if (ctx->RenderMode == GL_SELECT) { + draw_set_rasterize_stage(draw, st->selection_stage); + } +} + + + +void st_init_rasterpos_functions(struct dd_function_table *functions) +{ + functions->RasterPos = st_RasterPos; +} + +#endif /* FEATURE_rastpos */ diff --git a/mesalib/src/mesa/state_tracker/st_cb_xformfb.c b/mesalib/src/mesa/state_tracker/st_cb_xformfb.c index 378b4822b..2fc28dc24 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_xformfb.c +++ b/mesalib/src/mesa/state_tracker/st_cb_xformfb.c @@ -1,134 +1,197 @@ -/**************************************************************************
- *
- * Copyright 2010 VMware, Inc.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL THE AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- **************************************************************************/
-
-
-/**
- * Transform feedback functions.
- *
- * \author Brian Paul
- */
-
-
-#include "main/imports.h"
-#include "main/context.h"
-#include "main/mfeatures.h"
-#include "main/transformfeedback.h"
-
-#include "st_cb_xformfb.h"
-
-
-#if FEATURE_EXT_transform_feedback
-
-#if 0
-static struct gl_transform_feedback_object *
-st_new_transform_feedback(struct gl_context *ctx, GLuint name)
-{
- struct gl_transform_feedback_object *obj;
- obj = CALLOC_STRUCT(gl_transform_feedback_object);
- if (obj) {
- obj->Name = name;
- obj->RefCount = 1;
- }
- return obj;
-}
-#endif
-
-#if 0
-static void
-st_delete_transform_feedback(struct gl_context *ctx,
- struct gl_transform_feedback_object *obj)
-{
- GLuint i;
-
- for (i = 0; i < Elements(obj->Buffers); i++) {
- _mesa_reference_buffer_object(ctx, &obj->Buffers[i], NULL);
- }
-
- free(obj);
-}
-#endif
-
-
-static void
-st_begin_transform_feedback(struct gl_context *ctx, GLenum mode,
- struct gl_transform_feedback_object *obj)
-{
- /* to-do */
-}
-
-
-static void
-st_end_transform_feedback(struct gl_context *ctx,
- struct gl_transform_feedback_object *obj)
-{
- /* to-do */
-}
-
-
-static void
-st_pause_transform_feedback(struct gl_context *ctx,
- struct gl_transform_feedback_object *obj)
-{
- /* to-do */
-}
-
-
-static void
-st_resume_transform_feedback(struct gl_context *ctx,
- struct gl_transform_feedback_object *obj)
-{
- /* to-do */
-}
-
-
-static void
-st_draw_transform_feedback(struct gl_context *ctx, GLenum mode,
- struct gl_transform_feedback_object *obj)
-{
- /* XXX to do */
- /*
- * Get number of vertices in obj's feedback buffer.
- * Call ctx->Exec.DrawArrays(mode, 0, count);
- */
-}
-
-
-void
-st_init_xformfb_functions(struct dd_function_table *functions)
-{
- /* let core Mesa plug in its functions */
- _mesa_init_transform_feedback_functions(functions);
-
- /* then override a few: */
- functions->BeginTransformFeedback = st_begin_transform_feedback;
- functions->EndTransformFeedback = st_end_transform_feedback;
- functions->PauseTransformFeedback = st_pause_transform_feedback;
- functions->ResumeTransformFeedback = st_resume_transform_feedback;
- functions->DrawTransformFeedback = st_draw_transform_feedback;
-}
-
-#endif /* FEATURE_EXT_transform_feedback */
+/************************************************************************** + * + * Copyright 2010 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + + +/** + * Transform feedback functions. + * + * \author Brian Paul + * Marek Olšák + */ + + +#include "main/bufferobj.h" +#include "main/context.h" +#include "main/mfeatures.h" +#include "main/transformfeedback.h" + +#include "st_cb_bufferobjects.h" +#include "st_cb_xformfb.h" +#include "st_context.h" + +#include "pipe/p_context.h" +#include "util/u_draw.h" +#include "util/u_inlines.h" +#include "cso_cache/cso_context.h" + +#if FEATURE_EXT_transform_feedback + +struct st_transform_feedback_object { + struct gl_transform_feedback_object base; + + unsigned num_targets; + struct pipe_stream_output_target *targets[PIPE_MAX_SO_BUFFERS]; +}; + + +static struct gl_transform_feedback_object * +st_new_transform_feedback(struct gl_context *ctx, GLuint name) +{ + struct st_transform_feedback_object *obj; + + obj = CALLOC_STRUCT(st_transform_feedback_object); + if (!obj) + return NULL; + + obj->base.Name = name; + obj->base.RefCount = 1; + return &obj->base; +} + + +static void +st_delete_transform_feedback(struct gl_context *ctx, + struct gl_transform_feedback_object *obj) +{ + struct st_transform_feedback_object *sobj = + (struct st_transform_feedback_object*)obj; + unsigned i; + + /* Unreference targets. */ + for (i = 0; i < sobj->num_targets; i++) { + pipe_so_target_reference(&sobj->targets[i], NULL); + } + + for (i = 0; i < Elements(sobj->base.Buffers); i++) { + _mesa_reference_buffer_object(ctx, &sobj->base.Buffers[i], NULL); + } + + free(obj); +} + + +/* XXX Do we really need the mode? */ +static void +st_begin_transform_feedback(struct gl_context *ctx, GLenum mode, + struct gl_transform_feedback_object *obj) +{ + struct st_context *st = st_context(ctx); + struct pipe_context *pipe = st->pipe; + struct st_transform_feedback_object *sobj = + (struct st_transform_feedback_object*)obj; + unsigned i, max_num_targets; + + max_num_targets = MIN2(Elements(sobj->base.Buffers), + Elements(sobj->targets)); + + /* Convert the transform feedback state into the gallium representation. */ + for (i = 0; i < max_num_targets; i++) { + struct st_buffer_object *bo = st_buffer_object(sobj->base.Buffers[i]); + + if (bo) { + /* Check whether we need to recreate the target. */ + if (!sobj->targets[i] || + sobj->targets[i]->buffer != bo->buffer || + sobj->targets[i]->buffer_offset != sobj->base.Offset[i] || + sobj->targets[i]->buffer_size != sobj->base.Size[i]) { + /* Create a new target. */ + struct pipe_stream_output_target *so_target = + pipe->create_stream_output_target(pipe, bo->buffer, + sobj->base.Offset[i], + sobj->base.Size[i]); + + pipe_so_target_reference(&sobj->targets[i], NULL); + sobj->targets[i] = so_target; + } + + sobj->num_targets = i+1; + } else { + pipe_so_target_reference(&sobj->targets[i], NULL); + } + } + + /* Start writing at the beginning of each target. */ + cso_set_stream_outputs(st->cso_context, sobj->num_targets, sobj->targets, + 0); +} + + +static void +st_stop_transform_feedback(struct gl_context *ctx, + struct gl_transform_feedback_object *obj) +{ + struct st_context *st = st_context(ctx); + cso_set_stream_outputs(st->cso_context, 0, NULL, 0); +} + + +static void +st_resume_transform_feedback(struct gl_context *ctx, + struct gl_transform_feedback_object *obj) +{ + struct st_context *st = st_context(ctx); + struct st_transform_feedback_object *sobj = + (struct st_transform_feedback_object*)obj; + + cso_set_stream_outputs(st->cso_context, sobj->num_targets, sobj->targets, + ~0); +} + +/* Set count_from_stream_output to any stream output target + * from the transform feedback object. */ +void +st_transform_feedback_draw_init(struct gl_transform_feedback_object *obj, + struct pipe_draw_info *out) +{ + struct st_transform_feedback_object *sobj = + (struct st_transform_feedback_object*)obj; + unsigned i; + + for (i = 0; i < Elements(sobj->targets); i++) { + if (sobj->targets[i]) { + out->count_from_stream_output = sobj->targets[i]; + return; + } + } + + assert(0); + out->count_from_stream_output = NULL; +} + + +void +st_init_xformfb_functions(struct dd_function_table *functions) +{ + functions->NewTransformFeedback = st_new_transform_feedback; + functions->DeleteTransformFeedback = st_delete_transform_feedback; + functions->BeginTransformFeedback = st_begin_transform_feedback; + functions->EndTransformFeedback = st_stop_transform_feedback; + functions->PauseTransformFeedback = st_stop_transform_feedback; + functions->ResumeTransformFeedback = st_resume_transform_feedback; +} + +#endif /* FEATURE_EXT_transform_feedback */ diff --git a/mesalib/src/mesa/state_tracker/st_cb_xformfb.h b/mesalib/src/mesa/state_tracker/st_cb_xformfb.h index e07f500ce..c5261b39b 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_xformfb.h +++ b/mesalib/src/mesa/state_tracker/st_cb_xformfb.h @@ -1,51 +1,63 @@ -/**************************************************************************
- *
- * Copyright 2010 VMware, Inc.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL THE AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- **************************************************************************/
-
-#ifndef ST_CB_XFORMFB_H
-#define ST_CB_XFORMFB_H
-
-
-#include "main/compiler.h"
-#include "main/mfeatures.h"
-
-struct dd_function_table;
-
-#if FEATURE_EXT_transform_feedback
-
-extern void
-st_init_xformfb_functions(struct dd_function_table *functions);
-
-#else
-
-static INLINE void
-st_init_xformfb_functions(struct dd_function_table *functions)
-{
-}
-
-#endif /* FEATURE_EXT_transform_feedback */
-
-#endif /* ST_CB_XFORMFB_H */
+/************************************************************************** + * + * Copyright 2010 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef ST_CB_XFORMFB_H +#define ST_CB_XFORMFB_H + + +#include "main/compiler.h" +#include "main/mfeatures.h" + +struct dd_function_table; +struct gl_transform_feedback_object; +struct pipe_draw_info; + +#if FEATURE_EXT_transform_feedback + +extern void +st_init_xformfb_functions(struct dd_function_table *functions); + +extern void +st_transform_feedback_draw_init(struct gl_transform_feedback_object *obj, + struct pipe_draw_info *out); + +#else + +static INLINE void +st_init_xformfb_functions(struct dd_function_table *functions) +{ +} + +static INLINE void +st_transform_feedback_draw_init(struct gl_transform_feedback_object *obj, + struct pipe_draw_info *out) +{ +} + +#endif /* FEATURE_EXT_transform_feedback */ + +#endif /* ST_CB_XFORMFB_H */ diff --git a/mesalib/src/mesa/state_tracker/st_draw.c b/mesalib/src/mesa/state_tracker/st_draw.c index fd1c8ee48..87a997865 100644 --- a/mesalib/src/mesa/state_tracker/st_draw.c +++ b/mesalib/src/mesa/state_tracker/st_draw.c @@ -51,6 +51,7 @@ #include "st_context.h" #include "st_atom.h" #include "st_cb_bufferobjects.h" +#include "st_cb_xformfb.h" #include "st_draw.h" #include "st_program.h" @@ -926,7 +927,8 @@ st_draw_vbo(struct gl_context *ctx, const struct _mesa_index_buffer *ib, GLboolean index_bounds_valid, GLuint min_index, - GLuint max_index) + GLuint max_index, + struct gl_transform_feedback_object *tfb_vertcount) { struct st_context *st = st_context(ctx); struct pipe_context *pipe = st->pipe; @@ -1032,6 +1034,11 @@ st_draw_vbo(struct gl_context *ctx, info.restart_index = ctx->Array.RestartIndex; } + /* Set info.count_from_stream_output. */ + if (tfb_vertcount) { + st_transform_feedback_draw_init(tfb_vertcount, &info); + } + /* do actual drawing */ for (i = 0; i < nr_prims; i++) { info.mode = translate_prim( ctx, prims[i].mode ); @@ -1044,7 +1051,10 @@ st_draw_vbo(struct gl_context *ctx, info.max_index = info.start + info.count - 1; } - if (info.primitive_restart) { + if (info.count_from_stream_output) { + pipe->draw_vbo(pipe, &info); + } + else if (info.primitive_restart) { if (st->sw_primitive_restart) { /* Handle primitive restart for drivers that doesn't support it */ handle_fallback_primitive_restart(pipe, ib, &ibuffer, &info); diff --git a/mesalib/src/mesa/state_tracker/st_draw.h b/mesalib/src/mesa/state_tracker/st_draw.h index 23e1c7821..2623cdbb1 100644 --- a/mesalib/src/mesa/state_tracker/st_draw.h +++ b/mesalib/src/mesa/state_tracker/st_draw.h @@ -1,91 +1,93 @@ -/**************************************************************************
- *
- * Copyright 2004 Tungsten Graphics, Inc., Cedar Park, Texas.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- **************************************************************************/
-
- /*
- * Authors:
- * Keith Whitwell <keith@tungstengraphics.com>
- */
-
-
-#ifndef ST_DRAW_H
-#define ST_DRAW_H
-
-#include "main/compiler.h"
-#include "main/glheader.h"
-
-struct _mesa_index_buffer;
-struct _mesa_prim;
-struct gl_client_array;
-struct gl_context;
-struct st_context;
-
-void st_init_draw( struct st_context *st );
-
-void st_destroy_draw( struct st_context *st );
-
-extern void
-st_draw_vbo(struct gl_context *ctx,
- const struct gl_client_array **arrays,
- const struct _mesa_prim *prims,
- GLuint nr_prims,
- const struct _mesa_index_buffer *ib,
- GLboolean index_bounds_valid,
- GLuint min_index,
- GLuint max_index);
-
-extern void
-st_feedback_draw_vbo(struct gl_context *ctx,
- const struct gl_client_array **arrays,
- const struct _mesa_prim *prims,
- GLuint nr_prims,
- const struct _mesa_index_buffer *ib,
- GLboolean index_bounds_valid,
- GLuint min_index,
- GLuint max_index);
-
-/* Internal function:
- */
-extern enum pipe_format
-st_pipe_vertex_format(GLenum type, GLuint size, GLenum format,
- GLboolean normalized);
-
-
-/**
- * When drawing with VBOs, the addresses specified with
- * glVertex/Color/TexCoordPointer() are really offsets into the VBO, not real
- * addresses. At some point we need to convert those pointers to offsets.
- * This function is basically a cast wrapper to avoid warnings when building
- * in 64-bit mode.
- */
-static INLINE unsigned
-pointer_to_offset(const void *ptr)
-{
- return (unsigned) (((unsigned long) ptr) & 0xffffffffUL);
-}
-
-
-#endif
+/************************************************************************** + * + * Copyright 2004 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + + /* + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + */ + + +#ifndef ST_DRAW_H +#define ST_DRAW_H + +#include "main/compiler.h" +#include "main/glheader.h" + +struct _mesa_index_buffer; +struct _mesa_prim; +struct gl_client_array; +struct gl_context; +struct st_context; + +void st_init_draw( struct st_context *st ); + +void st_destroy_draw( struct st_context *st ); + +extern void +st_draw_vbo(struct gl_context *ctx, + const struct gl_client_array **arrays, + const struct _mesa_prim *prims, + GLuint nr_prims, + const struct _mesa_index_buffer *ib, + GLboolean index_bounds_valid, + GLuint min_index, + GLuint max_index, + struct gl_transform_feedback_object *tfb_vertcount); + +extern void +st_feedback_draw_vbo(struct gl_context *ctx, + const struct gl_client_array **arrays, + const struct _mesa_prim *prims, + GLuint nr_prims, + const struct _mesa_index_buffer *ib, + GLboolean index_bounds_valid, + GLuint min_index, + GLuint max_index, + struct gl_transform_feedback_object *tfb_vertcount); + +/* Internal function: + */ +extern enum pipe_format +st_pipe_vertex_format(GLenum type, GLuint size, GLenum format, + GLboolean normalized); + + +/** + * When drawing with VBOs, the addresses specified with + * glVertex/Color/TexCoordPointer() are really offsets into the VBO, not real + * addresses. At some point we need to convert those pointers to offsets. + * This function is basically a cast wrapper to avoid warnings when building + * in 64-bit mode. + */ +static INLINE unsigned +pointer_to_offset(const void *ptr) +{ + return (unsigned) (((unsigned long) ptr) & 0xffffffffUL); +} + + +#endif diff --git a/mesalib/src/mesa/state_tracker/st_draw_feedback.c b/mesalib/src/mesa/state_tracker/st_draw_feedback.c index a7e6a0f1b..4c1e67495 100644 --- a/mesalib/src/mesa/state_tracker/st_draw_feedback.c +++ b/mesalib/src/mesa/state_tracker/st_draw_feedback.c @@ -97,7 +97,8 @@ st_feedback_draw_vbo(struct gl_context *ctx, const struct _mesa_index_buffer *ib, GLboolean index_bounds_valid, GLuint min_index, - GLuint max_index) + GLuint max_index, + struct gl_transform_feedback_object *tfb_vertcount) { struct st_context *st = st_context(ctx); struct pipe_context *pipe = st->pipe; diff --git a/mesalib/src/mesa/state_tracker/st_extensions.c b/mesalib/src/mesa/state_tracker/st_extensions.c index 457d5d62a..47a178b8b 100644 --- a/mesalib/src/mesa/state_tracker/st_extensions.c +++ b/mesalib/src/mesa/state_tracker/st_extensions.c @@ -221,6 +221,13 @@ void st_init_limits(struct st_context *st) c->UniformBooleanTrue = ~0; + c->MaxTransformFeedbackSeparateAttribs = + screen->get_param(screen, PIPE_CAP_MAX_STREAM_OUTPUT_SEPARATE_ATTRIBS); + c->MaxTransformFeedbackSeparateComponents = + screen->get_param(screen, PIPE_CAP_MAX_STREAM_OUTPUT_SEPARATE_COMPONENTS); + c->MaxTransformFeedbackInterleavedComponents = + screen->get_param(screen, PIPE_CAP_MAX_STREAM_OUTPUT_INTERLEAVED_COMPONENTS); + c->StripTextureBorder = GL_TRUE; c->GLSLSkipStrictMaxUniformLimitCheck = @@ -682,4 +689,12 @@ void st_init_extensions(struct st_context *st) PIPE_BIND_SAMPLER_VIEW)) ctx->Extensions.ARB_texture_rgb10_a2ui = GL_TRUE; + if (screen->get_param(screen, PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS) != 0) { + ctx->Extensions.EXT_transform_feedback = GL_TRUE; + + if (screen->get_param(screen, + PIPE_CAP_STREAM_OUTPUT_PAUSE_RESUME) != 0) { + ctx->Extensions.ARB_transform_feedback2 = GL_TRUE; + } + } } 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 9ef65c8fd..b929806ad 100644 --- a/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp +++ b/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp @@ -5095,4 +5095,31 @@ st_link_shader(struct gl_context *ctx, struct gl_shader_program *prog) return GL_TRUE; } +void +st_translate_stream_output_info(struct glsl_to_tgsi_visitor *glsl_to_tgsi, + const GLuint outputMapping[], + struct pipe_stream_output_info *so) +{ + static unsigned comps_to_mask[] = { + 0, + TGSI_WRITEMASK_X, + TGSI_WRITEMASK_XY, + TGSI_WRITEMASK_XYZ, + TGSI_WRITEMASK_XYZW + }; + unsigned i; + struct gl_transform_feedback_info *info = + &glsl_to_tgsi->shader_program->LinkedTransformFeedback; + + for (i = 0; i < info->NumOutputs; i++) { + assert(info->Outputs[i].NumComponents < Elements(comps_to_mask)); + so->output[i].register_index = + outputMapping[info->Outputs[i].OutputRegister]; + so->output[i].register_mask = + comps_to_mask[info->Outputs[i].NumComponents]; + so->output[i].output_buffer = info->Outputs[i].OutputBuffer; + } + so->num_outputs = info->NumOutputs; +} + } /* extern "C" */ diff --git a/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.h b/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.h index fafe52e31..1f71f33fd 100644 --- a/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.h +++ b/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.h @@ -66,6 +66,12 @@ st_new_shader_program(struct gl_context *ctx, GLuint name); GLboolean st_link_shader(struct gl_context *ctx, struct gl_shader_program *prog); +void +st_translate_stream_output_info(struct glsl_to_tgsi_visitor *glsl_to_tgsi, + const GLuint outputMapping[], + struct pipe_stream_output_info *so); + + #ifdef __cplusplus } #endif diff --git a/mesalib/src/mesa/state_tracker/st_program.c b/mesalib/src/mesa/state_tracker/st_program.c index 04d3ef60f..b83c56165 100644 --- a/mesalib/src/mesa/state_tracker/st_program.c +++ b/mesalib/src/mesa/state_tracker/st_program.c @@ -367,6 +367,12 @@ st_translate_vertex_program(struct st_context *st, ureg_destroy( ureg ); + if (stvp->glsl_to_tgsi) { + st_translate_stream_output_info(stvp->glsl_to_tgsi, + stvp->result_to_output, + &vpv->tgsi.stream_output); + } + vpv->driver_shader = pipe->create_vs_state(pipe, &vpv->tgsi); if (ST_DEBUG & DEBUG_TGSI) { @@ -994,6 +1000,12 @@ st_translate_geometry_program(struct st_context *st, stgp->tgsi.tokens = ureg_get_tokens( ureg, NULL ); ureg_destroy( ureg ); + if (stgp->glsl_to_tgsi) { + st_translate_stream_output_info(stgp->glsl_to_tgsi, + outputMapping, + &stgp->tgsi.stream_output); + } + /* fill in new variant */ gpv->driver_shader = pipe->create_gs_state(pipe, &stgp->tgsi); gpv->key = *key; diff --git a/mesalib/src/mesa/swrast/s_blit.c b/mesalib/src/mesa/swrast/s_blit.c index 2817ec12f..803ad2e89 100644 --- a/mesalib/src/mesa/swrast/s_blit.c +++ b/mesalib/src/mesa/swrast/s_blit.c @@ -478,7 +478,15 @@ simple_blit(struct gl_context *ctx, ASSERT(srcX1 - srcX0 == dstX1 - dstX0); ASSERT(srcY1 - srcY0 == dstY1 - dstY0); - /* determine if copy should be bottom-to-top or top-to-bottom */ + /* From the GL_ARB_framebuffer_object spec: + * + * "If the source and destination buffers are identical, and the source + * and destination rectangles overlap, the result of the blit operation + * is undefined." + * + * However, we provide the expected result anyway by flipping the order of + * the memcpy of rows. + */ if (srcY0 > dstY0) { /* src above dst: copy bottom-to-top */ yStep = 1; diff --git a/mesalib/src/mesa/swrast/s_drawpix.c b/mesalib/src/mesa/swrast/s_drawpix.c index b6c433753..7259881c1 100644 --- a/mesalib/src/mesa/swrast/s_drawpix.c +++ b/mesalib/src/mesa/swrast/s_drawpix.c @@ -625,7 +625,8 @@ draw_depth_stencil_pixels(struct gl_context *ctx, GLint x, GLint y, GL_DEPTH_STENCIL_EXT, type, i, 0); if (ctx->Depth.Mask) { - if (!scaleOrBias && ctx->DrawBuffer->Visual.depthBits == 24) { + if (!scaleOrBias && ctx->DrawBuffer->Visual.depthBits == 24 && + type == GL_UNSIGNED_INT_24_8) { /* fast path 24-bit zbuffer */ GLuint zValues[MAX_WIDTH]; GLint j; @@ -639,7 +640,8 @@ draw_depth_stencil_pixels(struct gl_context *ctx, GLint x, GLint y, else depthRb->PutRow(ctx, depthRb, width, x, y + i, zValues,NULL); } - else if (!scaleOrBias && ctx->DrawBuffer->Visual.depthBits == 16) { + else if (!scaleOrBias && ctx->DrawBuffer->Visual.depthBits == 16 && + type == GL_UNSIGNED_INT_24_8) { /* fast path 16-bit zbuffer */ GLushort zValues[MAX_WIDTH]; GLint j; diff --git a/mesalib/src/mesa/tnl/t_draw.c b/mesalib/src/mesa/tnl/t_draw.c index 03424d7a4..83ded1949 100644 --- a/mesalib/src/mesa/tnl/t_draw.c +++ b/mesalib/src/mesa/tnl/t_draw.c @@ -430,7 +430,8 @@ void _tnl_vbo_draw_prims(struct gl_context *ctx, const struct _mesa_index_buffer *ib, GLboolean index_bounds_valid, GLuint min_index, - GLuint max_index) + GLuint max_index, + struct gl_transform_feedback_object *tfb_vertcount) { if (!index_bounds_valid) vbo_get_minmax_index(ctx, prim, ib, &min_index, &max_index); diff --git a/mesalib/src/mesa/tnl/tnl.h b/mesalib/src/mesa/tnl/tnl.h index 3ca0c5ebb..d3889811e 100644 --- a/mesalib/src/mesa/tnl/tnl.h +++ b/mesalib/src/mesa/tnl/tnl.h @@ -1,103 +1,104 @@ -/*
- * Mesa 3-D graphics library
- * Version: 7.1
- *
- * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, 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
- * BRIAN PAUL 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.
- *
- * Authors:
- * Keith Whitwell <keith@tungstengraphics.com>
- */
-
-#ifndef _TNL_H
-#define _TNL_H
-
-#include "main/glheader.h"
-
-struct gl_client_array;
-struct gl_context;
-struct gl_program;
-
-
-/* These are the public-access functions exported from tnl. (A few
- * more are currently hooked into dispatch directly by the module
- * itself.)
- */
-extern GLboolean
-_tnl_CreateContext( struct gl_context *ctx );
-
-extern void
-_tnl_DestroyContext( struct gl_context *ctx );
-
-extern void
-_tnl_InvalidateState( struct gl_context *ctx, GLuint new_state );
-
-/* Functions to revive the tnl module after being unhooked from
- * dispatch and/or driver callbacks.
- */
-
-extern void
-_tnl_wakeup( struct gl_context *ctx );
-
-/* Driver configuration options:
- */
-extern void
-_tnl_need_projected_coords( struct gl_context *ctx, GLboolean flag );
-
-
-/* Control whether T&L does per-vertex fog
- */
-extern void
-_tnl_allow_vertex_fog( struct gl_context *ctx, GLboolean value );
-
-extern void
-_tnl_allow_pixel_fog( struct gl_context *ctx, GLboolean value );
-
-extern GLboolean
-_tnl_program_string(struct gl_context *ctx, GLenum target, struct gl_program *program);
-
-struct _mesa_prim;
-struct _mesa_index_buffer;
-
-void
-_tnl_draw_prims( struct gl_context *ctx,
- const struct gl_client_array *arrays[],
- const struct _mesa_prim *prim,
- GLuint nr_prims,
- const struct _mesa_index_buffer *ib,
- GLuint min_index,
- GLuint max_index);
-
-void
-_tnl_vbo_draw_prims( struct gl_context *ctx,
- const struct gl_client_array *arrays[],
- const struct _mesa_prim *prim,
- GLuint nr_prims,
- const struct _mesa_index_buffer *ib,
- GLboolean index_bounds_valid,
- GLuint min_index,
- GLuint max_index);
-
-extern void
-_mesa_load_tracked_matrices(struct gl_context *ctx);
-
-extern void
-_tnl_RasterPos(struct gl_context *ctx, const GLfloat vObj[4]);
-
-#endif
+/* + * Mesa 3-D graphics library + * Version: 7.1 + * + * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, 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 + * BRIAN PAUL 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. + * + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + */ + +#ifndef _TNL_H +#define _TNL_H + +#include "main/glheader.h" + +struct gl_client_array; +struct gl_context; +struct gl_program; + + +/* These are the public-access functions exported from tnl. (A few + * more are currently hooked into dispatch directly by the module + * itself.) + */ +extern GLboolean +_tnl_CreateContext( struct gl_context *ctx ); + +extern void +_tnl_DestroyContext( struct gl_context *ctx ); + +extern void +_tnl_InvalidateState( struct gl_context *ctx, GLuint new_state ); + +/* Functions to revive the tnl module after being unhooked from + * dispatch and/or driver callbacks. + */ + +extern void +_tnl_wakeup( struct gl_context *ctx ); + +/* Driver configuration options: + */ +extern void +_tnl_need_projected_coords( struct gl_context *ctx, GLboolean flag ); + + +/* Control whether T&L does per-vertex fog + */ +extern void +_tnl_allow_vertex_fog( struct gl_context *ctx, GLboolean value ); + +extern void +_tnl_allow_pixel_fog( struct gl_context *ctx, GLboolean value ); + +extern GLboolean +_tnl_program_string(struct gl_context *ctx, GLenum target, struct gl_program *program); + +struct _mesa_prim; +struct _mesa_index_buffer; + +void +_tnl_draw_prims( struct gl_context *ctx, + const struct gl_client_array *arrays[], + const struct _mesa_prim *prim, + GLuint nr_prims, + const struct _mesa_index_buffer *ib, + GLuint min_index, + GLuint max_index); + +void +_tnl_vbo_draw_prims( struct gl_context *ctx, + const struct gl_client_array *arrays[], + const struct _mesa_prim *prim, + GLuint nr_prims, + const struct _mesa_index_buffer *ib, + GLboolean index_bounds_valid, + GLuint min_index, + GLuint max_index, + struct gl_transform_feedback_object *tfb_vertcount ); + +extern void +_mesa_load_tracked_matrices(struct gl_context *ctx); + +extern void +_tnl_RasterPos(struct gl_context *ctx, const GLfloat vObj[4]); + +#endif diff --git a/mesalib/src/mesa/vbo/vbo.h b/mesalib/src/mesa/vbo/vbo.h index 9fbb07f3d..f357657af 100644 --- a/mesalib/src/mesa/vbo/vbo.h +++ b/mesalib/src/mesa/vbo/vbo.h @@ -36,6 +36,7 @@ struct gl_client_array; struct gl_context; +struct gl_transform_feedback_object; struct _mesa_prim { GLuint mode:8; /**< GL_POINTS, GL_LINES, GL_QUAD_STRIP, etc */ @@ -77,7 +78,8 @@ typedef void (*vbo_draw_func)( struct gl_context *ctx, const struct _mesa_index_buffer *ib, GLboolean index_bounds_valid, GLuint min_index, - GLuint max_index ); + GLuint max_index, + struct gl_transform_feedback_object *tfb_vertcount ); diff --git a/mesalib/src/mesa/vbo/vbo_context.h b/mesalib/src/mesa/vbo/vbo_context.h index ef8a2a2b6..1a1cc928b 100644 --- a/mesalib/src/mesa/vbo/vbo_context.h +++ b/mesalib/src/mesa/vbo/vbo_context.h @@ -67,6 +67,7 @@ struct vbo_context { struct gl_client_array *generic_currval; struct gl_client_array *mat_currval; + /** Map VERT_ATTRIB_x to VBO_ATTRIB_y */ GLuint map_vp_none[VERT_ATTRIB_MAX]; GLuint map_vp_arb[VERT_ATTRIB_MAX]; diff --git a/mesalib/src/mesa/vbo/vbo_exec_array.c b/mesalib/src/mesa/vbo/vbo_exec_array.c index 97221a54d..a6e41e9c5 100644 --- a/mesalib/src/mesa/vbo/vbo_exec_array.c +++ b/mesalib/src/mesa/vbo/vbo_exec_array.c @@ -34,6 +34,7 @@ #include "main/bufferobj.h" #include "main/enums.h" #include "main/macros.h" +#include "main/transformfeedback.h" #include "vbo_context.h" @@ -608,7 +609,7 @@ vbo_draw_arrays(struct gl_context *ctx, GLenum mode, GLint start, /* draw one or two prims */ check_buffers_are_unmapped(exec->array.inputs); vbo->draw_prims(ctx, exec->array.inputs, prim, primCount, NULL, - GL_TRUE, start, start + count - 1); + GL_TRUE, start, start + count - 1, NULL); } } else { @@ -618,7 +619,8 @@ vbo_draw_arrays(struct gl_context *ctx, GLenum mode, GLint start, check_buffers_are_unmapped(exec->array.inputs); vbo->draw_prims(ctx, exec->array.inputs, prim, 1, NULL, - GL_TRUE, start, start + count - 1); + GL_TRUE, start, start + count - 1, + NULL); } } @@ -824,7 +826,7 @@ vbo_validated_drawrangeelements(struct gl_context *ctx, GLenum mode, check_buffers_are_unmapped(exec->array.inputs); vbo->draw_prims( ctx, exec->array.inputs, prim, 1, &ib, - index_bounds_valid, start, end ); + index_bounds_valid, start, end, NULL ); } @@ -1168,7 +1170,7 @@ vbo_validated_multidrawelements(struct gl_context *ctx, GLenum mode, check_buffers_are_unmapped(exec->array.inputs); vbo->draw_prims(ctx, exec->array.inputs, prim, primcount, &ib, - GL_FALSE, ~0, ~0); + GL_FALSE, ~0, ~0, NULL); } else { /* render one prim at a time */ for (i = 0; i < primcount; i++) { @@ -1193,7 +1195,7 @@ vbo_validated_multidrawelements(struct gl_context *ctx, GLenum mode, check_buffers_are_unmapped(exec->array.inputs); vbo->draw_prims(ctx, exec->array.inputs, prim, 1, &ib, - GL_FALSE, ~0, ~0); + GL_FALSE, ~0, ~0, NULL); } } @@ -1245,6 +1247,76 @@ vbo_exec_MultiDrawElementsBaseVertex(GLenum mode, basevertex); } +#if FEATURE_EXT_transform_feedback + +static void +vbo_draw_transform_feedback(struct gl_context *ctx, GLenum mode, + struct gl_transform_feedback_object *obj, + GLuint numInstances) +{ + struct vbo_context *vbo = vbo_context(ctx); + struct vbo_exec_context *exec = &vbo->exec; + struct _mesa_prim prim[2]; + + vbo_bind_arrays(ctx); + + /* Again... because we may have changed the bitmask of per-vertex varying + * attributes. If we regenerate the fixed-function vertex program now + * we may be able to prune down the number of vertex attributes which we + * need in the shader. + */ + if (ctx->NewState) + _mesa_update_state(ctx); + + /* init most fields to zero */ + memset(prim, 0, sizeof(prim)); + prim[0].begin = 1; + prim[0].end = 1; + prim[0].mode = mode; + prim[0].num_instances = numInstances; + + /* Maybe we should do some primitive splitting for primitive restart + * (like in DrawArrays), but we have no way to know how many vertices + * will be rendered. */ + + check_buffers_are_unmapped(exec->array.inputs); + vbo->draw_prims(ctx, exec->array.inputs, prim, 1, NULL, + GL_TRUE, 0, 0, obj); +} + +/** + * Like DrawArrays, but take the count from a transform feedback object. + * \param mode GL_POINTS, GL_LINES, GL_TRIANGLE_STRIP, etc. + * \param name the transform feedback object + * User still has to setup of the vertex attribute info with + * glVertexPointer, glColorPointer, etc. + * Part of GL_ARB_transform_feedback2. + */ +static void GLAPIENTRY +vbo_exec_DrawTransformFeedback(GLenum mode, GLuint name) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_transform_feedback_object *obj = + _mesa_lookup_transform_feedback_object(ctx, name); + + if (MESA_VERBOSE & VERBOSE_DRAW) + _mesa_debug(ctx, "glDrawTransformFeedback(%s, %d)\n", + _mesa_lookup_enum_by_nr(mode), name); + + if (!_mesa_validate_DrawTransformFeedback(ctx, mode, obj)) { + return; + } + + FLUSH_CURRENT(ctx, 0); + + if (!_mesa_valid_to_render(ctx, "glDrawTransformFeedback")) { + return; + } + + vbo_draw_transform_feedback(ctx, mode, obj, 1); +} + +#endif /** * Plug in the immediate-mode vertex array drawing commands into the @@ -1263,6 +1335,7 @@ vbo_exec_array_init( struct vbo_exec_context *exec ) exec->vtxfmt.DrawArraysInstanced = vbo_exec_DrawArraysInstanced; exec->vtxfmt.DrawElementsInstanced = vbo_exec_DrawElementsInstanced; exec->vtxfmt.DrawElementsInstancedBaseVertex = vbo_exec_DrawElementsInstancedBaseVertex; + exec->vtxfmt.DrawTransformFeedback = vbo_exec_DrawTransformFeedback; } @@ -1338,3 +1411,13 @@ _mesa_MultiDrawElementsBaseVertex(GLenum mode, vbo_exec_MultiDrawElementsBaseVertex(mode, count, type, indices, primcount, basevertex); } + +#if FEATURE_EXT_transform_feedback + +void GLAPIENTRY +_mesa_DrawTransformFeedback(GLenum mode, GLuint name) +{ + vbo_exec_DrawTransformFeedback(mode, name); +} + +#endif diff --git a/mesalib/src/mesa/vbo/vbo_exec_draw.c b/mesalib/src/mesa/vbo/vbo_exec_draw.c index 4962b54e1..dd5363beb 100644 --- a/mesalib/src/mesa/vbo/vbo_exec_draw.c +++ b/mesalib/src/mesa/vbo/vbo_exec_draw.c @@ -411,7 +411,8 @@ vbo_exec_vtx_flush(struct vbo_exec_context *exec, GLboolean keepUnmapped) NULL, GL_TRUE, 0, - exec->vtx.vert_count - 1); + exec->vtx.vert_count - 1, + NULL); /* If using a real VBO, get new storage -- unless asked not to. */ diff --git a/mesalib/src/mesa/vbo/vbo_rebase.c b/mesalib/src/mesa/vbo/vbo_rebase.c index 97c8d1297..597a8f469 100644 --- a/mesalib/src/mesa/vbo/vbo_rebase.c +++ b/mesalib/src/mesa/vbo/vbo_rebase.c @@ -233,7 +233,8 @@ void vbo_rebase_prims( struct gl_context *ctx, ib, GL_TRUE, 0, - max_index - min_index ); + max_index - min_index, + NULL ); if (tmp_indices) free(tmp_indices); diff --git a/mesalib/src/mesa/vbo/vbo_save_api.c b/mesalib/src/mesa/vbo/vbo_save_api.c index 9d8bada04..952136747 100644 --- a/mesalib/src/mesa/vbo/vbo_save_api.c +++ b/mesalib/src/mesa/vbo/vbo_save_api.c @@ -999,6 +999,16 @@ _save_MultiDrawElementsBaseVertex(GLenum mode, const GLsizei *count, static void GLAPIENTRY +_save_DrawTransformFeedback(GLenum mode, GLuint name) +{ + GET_CURRENT_CONTEXT(ctx); + (void) mode; + (void) name; + _mesa_compile_error(ctx, GL_INVALID_OPERATION, "glDrawTransformFeedback"); +} + + +static void GLAPIENTRY _save_Rectf(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2) { GET_CURRENT_CONTEXT(ctx); @@ -1347,6 +1357,7 @@ _save_vtxfmt_init(struct gl_context *ctx) vfmt->DrawRangeElements = _save_DrawRangeElements; vfmt->DrawElementsBaseVertex = _save_DrawElementsBaseVertex; vfmt->DrawRangeElementsBaseVertex = _save_DrawRangeElementsBaseVertex; + vfmt->DrawTransformFeedback = _save_DrawTransformFeedback; vfmt->MultiDrawElementsEXT = _save_MultiDrawElements; vfmt->MultiDrawElementsBaseVertex = _save_MultiDrawElementsBaseVertex; } diff --git a/mesalib/src/mesa/vbo/vbo_save_draw.c b/mesalib/src/mesa/vbo/vbo_save_draw.c index 0773786b3..fa93ca48f 100644 --- a/mesalib/src/mesa/vbo/vbo_save_draw.c +++ b/mesalib/src/mesa/vbo/vbo_save_draw.c @@ -299,7 +299,8 @@ vbo_save_playback_vertex_list(struct gl_context *ctx, void *data) NULL, GL_TRUE, 0, /* Node is a VBO, so this is ok */ - node->count - 1); + node->count - 1, + NULL); } } diff --git a/mesalib/src/mesa/vbo/vbo_split_copy.c b/mesalib/src/mesa/vbo/vbo_split_copy.c index 4dcf71ef5..b53293c31 100644 --- a/mesalib/src/mesa/vbo/vbo_split_copy.c +++ b/mesalib/src/mesa/vbo/vbo_split_copy.c @@ -196,7 +196,8 @@ flush( struct copy_context *copy ) ©->dstib, GL_TRUE, 0, - copy->dstbuf_nr - 1 ); + copy->dstbuf_nr - 1, + NULL ); /* Reset all pointers: */ diff --git a/mesalib/src/mesa/vbo/vbo_split_inplace.c b/mesalib/src/mesa/vbo/vbo_split_inplace.c index f6aa576b6..9e596f668 100644 --- a/mesalib/src/mesa/vbo/vbo_split_inplace.c +++ b/mesalib/src/mesa/vbo/vbo_split_inplace.c @@ -89,7 +89,8 @@ static void flush_vertex( struct split_context *split ) split->ib ? &ib : NULL, !split->ib, split->min_index, - split->max_index); + split->max_index, + NULL); split->dstprim_nr = 0; split->min_index = ~0; diff --git a/xorg-server/configure.ac b/xorg-server/configure.ac index 27bf6abfd..518eb06a9 100644 --- a/xorg-server/configure.ac +++ b/xorg-server/configure.ac @@ -212,7 +212,7 @@ AC_CHECK_FUNC([dlopen], [], AC_SUBST(DLOPEN_LIBS) dnl Checks for library functions. -AC_CHECK_FUNCS([backtrace ffs \ +AC_CHECK_FUNCS([backtrace ffs geteuid getuid issetugid getresuid \ getdtablesize getifaddrs getpeereid getpeerucred getzoneid \ mmap shmctl64 strncasecmp vasprintf vsnprintf walkcontext]) AC_REPLACE_FUNCS([strcasecmp strcasestr strlcat strlcpy strndup]) diff --git a/xorg-server/hw/xfree86/common/xf86Config.c b/xorg-server/hw/xfree86/common/xf86Config.c index 569695c8a..f51be7e9c 100644 --- a/xorg-server/hw/xfree86/common/xf86Config.c +++ b/xorg-server/hw/xfree86/common/xf86Config.c @@ -72,8 +72,8 @@ * These paths define the way the config file search is done. The escape * sequences are documented in parser/scan.c. */ -#ifndef ROOT_CONFIGPATH -#define ROOT_CONFIGPATH "%A," "%R," \ +#ifndef ALL_CONFIGPATH +#define ALL_CONFIGPATH "%A," "%R," \ "/etc/X11/%R," "%P/etc/X11/%R," \ "%E," "%F," \ "/etc/X11/%F," "%P/etc/X11/%F," \ @@ -83,8 +83,8 @@ "%P/lib/X11/%X.%H," \ "%P/lib/X11/%X" #endif -#ifndef USER_CONFIGPATH -#define USER_CONFIGPATH "/etc/X11/%S," "%P/etc/X11/%S," \ +#ifndef RESTRICTED_CONFIGPATH +#define RESTRICTED_CONFIGPATH "/etc/X11/%S," "%P/etc/X11/%S," \ "/etc/X11/%G," "%P/etc/X11/%G," \ "/etc/X11/%X," "/etc/%X," \ "%P/etc/X11/%X.%H," \ @@ -92,14 +92,14 @@ "%P/lib/X11/%X.%H," \ "%P/lib/X11/%X" #endif -#ifndef ROOT_CONFIGDIRPATH -#define ROOT_CONFIGDIRPATH "%A," "%R," \ +#ifndef ALL_CONFIGDIRPATH +#define ALL_CONFIGDIRPATH "%A," "%R," \ "/etc/X11/%R," "%C/X11/%R," \ "/etc/X11/%X," "%C/X11/%X" #endif -#ifndef USER_CONFIGDIRPATH -#define USER_CONFIGDIRPATH "/etc/X11/%R," "%C/X11/%R," \ - "/etc/X11/%X," "%C/X11/%X" +#ifndef RESTRICTED_CONFIGDIRPATH +#define RESTRICTED_CONFIGDIRPATH "/etc/X11/%R," "%C/X11/%R," \ + "/etc/X11/%X," "%C/X11/%X" #endif #ifndef SYS_CONFIGDIRPATH #define SYS_CONFIGDIRPATH "/usr/share/X11/%X," "%D/X11/%X" @@ -2310,12 +2310,12 @@ xf86HandleConfigFile(Bool autoconfig) MessageType filefrom = X_DEFAULT; MessageType dirfrom = X_DEFAULT; - if (getuid() == 0) { - filesearch = ROOT_CONFIGPATH; - dirsearch = ROOT_CONFIGDIRPATH; + if (!xf86PrivsElevated()) { + filesearch = ALL_CONFIGPATH; + dirsearch = ALL_CONFIGDIRPATH; } else { - filesearch = USER_CONFIGPATH; - dirsearch = USER_CONFIGDIRPATH; + filesearch = RESTRICTED_CONFIGPATH; + dirsearch = RESTRICTED_CONFIGDIRPATH; } if (xf86ConfigFile) diff --git a/xorg-server/hw/xfree86/common/xf86Init.c b/xorg-server/hw/xfree86/common/xf86Init.c index c1e48eed2..5263b5f73 100644 --- a/xorg-server/hw/xfree86/common/xf86Init.c +++ b/xorg-server/hw/xfree86/common/xf86Init.c @@ -238,6 +238,65 @@ xf86PrintMarkers(void) LogPrintMarkers(); } +Bool xf86PrivsElevated(void) +{ + static Bool privsTested = FALSE; + static Bool privsElevated = TRUE; + + if (!privsTested) { +#if defined(WIN32) + privsElevated = FALSE; +#else + if ((getuid() != geteuid()) || (getgid() != getegid())) { + privsElevated = TRUE; + } else { +#if defined(HAVE_ISSETUGID) + privsElevated = issetugid(); +#elif defined(HAVE_GETRESUID) + uid_t ruid, euid, suid; + gid_t rgid, egid, sgid; + + if ((getresuid(&ruid, &euid, &suid) == 0) && + (getresgid(&rgid, &egid, &sgid) == 0)) { + privsElevated = (euid != suid) || (egid != sgid); + } + else { + printf("Failed getresuid or getresgid"); + /* Something went wrong, make defensive assumption */ + privsElevated = TRUE; + } +#else + if (getuid()==0) { + /* running as root: uid==euid==0 */ + privsElevated = FALSE; + } + else { + /* + * If there are saved ID's the process might still be privileged + * even though the above test succeeded. If issetugid() and + * getresgid() aren't available, test this by trying to set + * euid to 0. + */ + unsigned int oldeuid; + oldeuid = geteuid(); + + if (seteuid(0) != 0) { + privsElevated = FALSE; + } else { + if (seteuid(oldeuid) != 0) { + FatalError("Failed to drop privileges. Exiting\n"); + } + privsElevated = TRUE; + } + } +#endif + } +#endif + privsTested = TRUE; + } + return privsElevated; +} + static Bool xf86CreateRootWindow(WindowPtr pWin) { @@ -872,7 +931,7 @@ OsVendorInit(void) #ifdef O_NONBLOCK if (!beenHere) { - if (geteuid() == 0 && getuid() != geteuid()) + if (xf86PrivsElevated()) { int status; @@ -1043,10 +1102,11 @@ ddxProcessArgument(int argc, char **argv, int i) FatalError("Required argument to %s not specified\n", argv[i]); \ } - /* First the options that are only allowed for root */ + /* First the options that are not allowed with elevated privileges */ if (!strcmp(argv[i], "-modulepath") || !strcmp(argv[i], "-logfile")) { - if ( (geteuid() == 0) && (getuid() != 0) ) { - FatalError("The '%s' option can only be used by root.\n", argv[i]); + if (xf86PrivsElevated()) { + FatalError("The '%s' option cannot be used with " + "elevated privileges.\n", argv[i]); } else if (!strcmp(argv[i], "-modulepath")) { @@ -1074,9 +1134,9 @@ ddxProcessArgument(int argc, char **argv, int i) if (!strcmp(argv[i], "-config") || !strcmp(argv[i], "-xf86config")) { CHECK_FOR_REQUIRED_ARGUMENT(); - if (getuid() != 0 && !xf86PathIsSafe(argv[i + 1])) { + if (xf86PrivsElevated() && !xf86PathIsSafe(argv[i + 1])) { FatalError("\nInvalid argument for %s\n" - "\tFor non-root users, the file specified with %s must be\n" + "\tWith elevated privileges, the file specified with %s must be\n" "\ta relative path and must not contain any \"..\" elements.\n" "\tUsing default "__XCONFIGFILE__" search path.\n\n", argv[i], argv[i]); @@ -1087,9 +1147,9 @@ ddxProcessArgument(int argc, char **argv, int i) if (!strcmp(argv[i], "-configdir")) { CHECK_FOR_REQUIRED_ARGUMENT(); - if (getuid() != 0 && !xf86PathIsSafe(argv[i + 1])) { + if (xf86PrivsElevated() && !xf86PathIsSafe(argv[i + 1])) { FatalError("\nInvalid argument for %s\n" - "\tFor non-root users, the file specified with %s must be\n" + "\tWith elevated privileges, the file specified with %s must be\n" "\ta relative path and must not contain any \"..\" elements.\n" "\tUsing default "__XCONFIGDIR__" search path.\n\n", argv[i], argv[i]); @@ -1375,7 +1435,7 @@ ddxUseMsg(void) ErrorF("\n"); ErrorF("\n"); ErrorF("Device Dependent Usage\n"); - if (getuid() == 0 || geteuid() != 0) + if (!xf86PrivsElevated()) { ErrorF("-modulepath paths specify the module search path\n"); ErrorF("-logfile file specify a log file name\n"); diff --git a/xorg-server/hw/xfree86/common/xf86Priv.h b/xorg-server/hw/xfree86/common/xf86Priv.h index e0b18098e..255407b48 100644 --- a/xorg-server/hw/xfree86/common/xf86Priv.h +++ b/xorg-server/hw/xfree86/common/xf86Priv.h @@ -145,6 +145,7 @@ extern _X_EXPORT Bool xf86LoadModules(char **list, pointer *optlist); extern _X_EXPORT int xf86SetVerbosity(int verb); extern _X_EXPORT int xf86SetLogVerbosity(int verb); extern _X_EXPORT Bool xf86CallDriverProbe( struct _DriverRec * drv, Bool detect_only ); +extern _X_EXPORT Bool xf86PrivsElevated(void); #endif /* _NO_XF86_PROTOTYPES */ diff --git a/xorg-server/include/xorg-config.h.in b/xorg-server/include/xorg-config.h.in index 6b9230f3c..2cc416ae7 100644 --- a/xorg-server/include/xorg-config.h.in +++ b/xorg-server/include/xorg-config.h.in @@ -130,4 +130,10 @@ /* Use libpciaccess */ #undef XSERVER_LIBPCIACCESS +/* Have setugid */ +#undef HAVE_ISSETUGID + +/* Have getresuid */ +#undef HAVE_GETRESUID + #endif /* _XORG_CONFIG_H_ */ |