diff options
author | marha <marha@users.sourceforge.net> | 2014-03-04 08:57:07 +0100 |
---|---|---|
committer | marha <marha@users.sourceforge.net> | 2014-03-04 08:57:07 +0100 |
commit | 321c01267ae1c446f1bd22b642567fcafa016c02 (patch) | |
tree | 69f6e12bdfd1ccda5d054398321bc1876dd3fc89 /mesalib/src | |
parent | 982ac918afe6a1c02d5cf735d7b6c56443a048cc (diff) | |
download | vcxsrv-321c01267ae1c446f1bd22b642567fcafa016c02.tar.gz vcxsrv-321c01267ae1c446f1bd22b642567fcafa016c02.tar.bz2 vcxsrv-321c01267ae1c446f1bd22b642567fcafa016c02.zip |
libX11 libxcb mesa xserver xcb-proto xkeyboard-config git update 4 Mar 2014
xserver commit b634e909895f6001e7d9543e1350b20c82c8c01c
libxcb commit 4ffa6f83b92763eb901c7ddb7c20775e24d507ca
libxcb/xcb-proto commit 4270141a7cb3c68f50251be19a5a628aa18553e6
xkeyboard-config commit d9e3d0ec1a48a5f61ea6dd6d20b8682eeecf3a39
libX11 commit d6bd988bc00494914b38b95ee5df77ac4f32f19f
libXdmcp commit 089081dca4ba3598c6f9bf401c029378943b5854
libXext commit d5447c0156f556114dbf97d6064c0c7b0fcd5f70
libfontenc commit 0037a42107b952c9d903719615747e760e4e7247
libXinerama commit edd95182b26eb5d576d4878c559e0f17dddaa909
libXau commit 1e4635be11154dd8262f37b379511bd627defa2a
xkbcomp commit 31b90ee4ffc774e0da540277907fc5540c0b012c
pixman commit 82d094654a46bd97d47f1f132a01ae0a74b986f3
xextproto commit 66afec3f49e8eb0d4c2e9af7088fc3116d4bafd7
randrproto commit a4a6694c059d74247c16527eef4a0ec9f56bbef6
glproto commit f84853d97d5749308992412a215fa518b6536eb3
mkfontscale commit eac564e0fc9052a39981ea47b271f7f3d2821944
xwininfo commit ba0d1b0da21d2dbdd81098ed5778f3792b472e13
libXft commit 4acfdaf95adb0a05c2a25550bdde036c865902f4
libXmu commit 22d9c590901e121936f50dee97dc60c4f7defb63
libxtrans commit 3f0de269abe59353acbd7a5587d68ce0da91db67
fontconfig commit e310d2fac2d874d5aa76c609df70cc7b871c0b6d
mesa commit 1a568e0f2b65e4e1e1d19a6dece3a792a33da825
Diffstat (limited to 'mesalib/src')
145 files changed, 7083 insertions, 2853 deletions
diff --git a/mesalib/src/gallium/Automake.inc b/mesalib/src/gallium/Automake.inc index 1e4a34f5d..1acc99ef5 100644 --- a/mesalib/src/gallium/Automake.inc +++ b/mesalib/src/gallium/Automake.inc @@ -51,12 +51,14 @@ GALLIUM_VIDEO_CFLAGS = \ $(VISIBILITY_CFLAGS) -# TODO: add -export-symbols-regex +DRI_VERSION_SCRIPT ?= $(top_srcdir)/src/gallium/state_trackers/dri/dri.link + GALLIUM_DRI_LINKER_FLAGS = \ -module \ -avoid-version \ + -Wl,--version-script=$(DRI_VERSION_SCRIPT) \ -shared \ - -Wl,-Bsymbolic + -no-undefined GALLIUM_VDPAU_LINKER_FLAGS = \ -module \ @@ -76,7 +78,11 @@ GALLIUM_VDPAU_LIB_DEPS = \ $(top_builddir)/src/gallium/auxiliary/libgallium.la \ $(top_builddir)/src/gallium/state_trackers/vdpau/libvdpautracker.la \ $(VDPAU_LIBS) \ - $(LIBDRM_LIBS) + $(LIBDRM_LIBS) \ + -lm \ + $(CLOCK_LIB) \ + $(PTHREAD_LIBS) \ + $(DLOPEN_LIBS) GALLIUM_XVMC_LIB_DEPS = \ $(top_builddir)/src/gallium/auxiliary/libgallium.la \ diff --git a/mesalib/src/gallium/auxiliary/Makefile.sources b/mesalib/src/gallium/auxiliary/Makefile.sources index c89cbddd0..8919783c2 100644 --- a/mesalib/src/gallium/auxiliary/Makefile.sources +++ b/mesalib/src/gallium/auxiliary/Makefile.sources @@ -91,6 +91,7 @@ C_SOURCES := \ translate/translate_sse.c \ util/u_debug.c \ util/u_debug_describe.c \ + util/u_debug_flush.c \ util/u_debug_memory.c \ util/u_debug_refcnt.c \ util/u_debug_stack.c \ @@ -155,7 +156,8 @@ C_SOURCES := \ vl/vl_idct.c \ vl/vl_mc.c \ vl/vl_vertex_buffers.c \ - vl/vl_video_buffer.c + vl/vl_video_buffer.c \ + vl/vl_deint_filter.c GENERATED_SOURCES := \ indices/u_indices_gen.c \ diff --git a/mesalib/src/gallium/auxiliary/util/u_debug_flush.c b/mesalib/src/gallium/auxiliary/util/u_debug_flush.c new file mode 100644 index 000000000..9cf70db58 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_debug_flush.c @@ -0,0 +1,391 @@ +/************************************************************************** + * + * Copyright 2012 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 VMWARE 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 + * u_debug_flush.c Debug flush and map-related issues: + * - Flush while synchronously mapped. + * - Command stream reference while synchronously mapped. + * - Synchronous map while referenced on command stream. + * - Recursive maps. + * - Unmap while not mapped. + * + * @author Thomas Hellstrom <thellstrom@vmware.com> + */ + +#ifdef DEBUG +#include "pipe/p_compiler.h" +#include "util/u_debug_stack.h" +#include "util/u_debug.h" +#include "util/u_memory.h" +#include "util/u_debug_flush.h" +#include "util/u_hash_table.h" +#include "util/u_double_list.h" +#include "util/u_inlines.h" +#include "os/os_thread.h" +#include <stdio.h> + +struct debug_flush_buf { + /* Atomic */ + struct pipe_reference reference; /* Must be the first member. */ + pipe_mutex mutex; + /* Immutable */ + boolean supports_unsync; + unsigned bt_depth; + /* Protected by mutex */ + boolean mapped; + boolean mapped_sync; + struct debug_stack_frame *map_frame; +}; + +struct debug_flush_item { + struct debug_flush_buf *fbuf; + unsigned bt_depth; + struct debug_stack_frame *ref_frame; +}; + +struct debug_flush_ctx { + /* Contexts are used by a single thread at a time */ + unsigned bt_depth; + boolean catch_map_of_referenced; + struct util_hash_table *ref_hash; + struct list_head head; +}; + +pipe_static_mutex(list_mutex); +static struct list_head ctx_list = {&ctx_list, &ctx_list}; + +static struct debug_stack_frame * +debug_flush_capture_frame(int start, int depth) +{ + struct debug_stack_frame *frames; + + frames = CALLOC(depth, sizeof(*frames)); + if (!frames) + return NULL; + + debug_backtrace_capture(frames, start, depth); + return frames; +} + +static int +debug_flush_pointer_compare(void *key1, void *key2) +{ + return (key1 == key2) ? 0 : 1; +} + +static unsigned +debug_flush_pointer_hash(void *key) +{ + return (unsigned) (unsigned long) key; +} + +struct debug_flush_buf * +debug_flush_buf_create(boolean supports_unsync, unsigned bt_depth) +{ + struct debug_flush_buf *fbuf = CALLOC_STRUCT(debug_flush_buf); + + if (!fbuf) + goto out_no_buf; + + fbuf->supports_unsync = supports_unsync; + fbuf->bt_depth = bt_depth; + pipe_reference_init(&fbuf->reference, 1); + pipe_mutex_init(fbuf->mutex); + + return fbuf; +out_no_buf: + debug_printf("Debug flush buffer creation failed.\n"); + debug_printf("Debug flush checking for this buffer will be incomplete.\n"); + return NULL; +} + +void +debug_flush_buf_reference(struct debug_flush_buf **dst, + struct debug_flush_buf *src) +{ + struct debug_flush_buf *fbuf = *dst; + + if (pipe_reference(&(*dst)->reference, &src->reference)) { + if (fbuf->map_frame) + FREE(fbuf->map_frame); + + FREE(fbuf); + } + + *dst = src; +} + +static void +debug_flush_item_destroy(struct debug_flush_item *item) +{ + debug_flush_buf_reference(&item->fbuf, NULL); + + if (item->ref_frame) + FREE(item->ref_frame); + + FREE(item); +} + +struct debug_flush_ctx * +debug_flush_ctx_create(boolean catch_reference_of_mapped, unsigned bt_depth) +{ + struct debug_flush_ctx *fctx = CALLOC_STRUCT(debug_flush_ctx); + + if (!fctx) + goto out_no_ctx; + + fctx->ref_hash = util_hash_table_create(debug_flush_pointer_hash, + debug_flush_pointer_compare); + + if (!fctx->ref_hash) + goto out_no_ref_hash; + + fctx->bt_depth = bt_depth; + pipe_mutex_lock(list_mutex); + list_addtail(&fctx->head, &ctx_list); + pipe_mutex_unlock(list_mutex); + + return fctx; + + out_no_ref_hash: + FREE(fctx); +out_no_ctx: + debug_printf("Debug flush context creation failed.\n"); + debug_printf("Debug flush checking for this context will be incomplete.\n"); + return NULL; +} + +static void +debug_flush_alert(const char *s, const char *op, + unsigned start, unsigned depth, + boolean continued, + boolean capture, + const struct debug_stack_frame *frame) +{ + if (capture) + frame = debug_flush_capture_frame(start, depth); + + if (s) + debug_printf("%s ", s); + if (frame) { + debug_printf("%s backtrace follows:\n", op); + debug_backtrace_dump(frame, depth); + } else + debug_printf("No %s backtrace was captured.\n", op); + + if (continued) + debug_printf("**********************************\n"); + else + debug_printf("*********END OF MESSAGE***********\n\n\n"); + + if (capture) + FREE((void *)frame); +} + + +void +debug_flush_map(struct debug_flush_buf *fbuf, unsigned flags) +{ + boolean mapped_sync = FALSE; + + if (!fbuf) + return; + + pipe_mutex_lock(fbuf->mutex); + if (fbuf->mapped) { + debug_flush_alert("Recursive map detected.", "Map", + 2, fbuf->bt_depth, TRUE, TRUE, NULL); + debug_flush_alert(NULL, "Previous map", 0, fbuf->bt_depth, FALSE, + FALSE, fbuf->map_frame); + } else if (!(flags & PIPE_TRANSFER_UNSYNCHRONIZED) || + !fbuf->supports_unsync) { + fbuf->mapped_sync = mapped_sync = TRUE; + } + fbuf->map_frame = debug_flush_capture_frame(1, fbuf->bt_depth); + fbuf->mapped = TRUE; + pipe_mutex_unlock(fbuf->mutex); + + if (mapped_sync) { + struct debug_flush_ctx *fctx; + + pipe_mutex_lock(list_mutex); + LIST_FOR_EACH_ENTRY(fctx, &ctx_list, head) { + struct debug_flush_item *item = + util_hash_table_get(fctx->ref_hash, fbuf); + + if (item && fctx->catch_map_of_referenced) { + debug_flush_alert("Already referenced map detected.", + "Map", 2, fbuf->bt_depth, TRUE, TRUE, NULL); + debug_flush_alert(NULL, "Reference", 0, item->bt_depth, + FALSE, FALSE, item->ref_frame); + } + } + pipe_mutex_unlock(list_mutex); + } +} + +void +debug_flush_unmap(struct debug_flush_buf *fbuf) +{ + if (!fbuf) + return; + + pipe_mutex_lock(fbuf->mutex); + if (!fbuf->mapped) + debug_flush_alert("Unmap not previously mapped detected.", "Map", + 2, fbuf->bt_depth, FALSE, TRUE, NULL); + + fbuf->mapped_sync = FALSE; + fbuf->mapped = FALSE; + if (fbuf->map_frame) { + FREE(fbuf->map_frame); + fbuf->map_frame = NULL; + } + pipe_mutex_unlock(fbuf->mutex); +} + +void +debug_flush_cb_reference(struct debug_flush_ctx *fctx, + struct debug_flush_buf *fbuf) +{ + struct debug_flush_item *item; + + if (!fctx || !fbuf) + return; + + item = util_hash_table_get(fctx->ref_hash, fbuf); + + pipe_mutex_lock(fbuf->mutex); + if (fbuf->mapped_sync) { + debug_flush_alert("Reference of mapped buffer detected.", "Reference", + 2, fctx->bt_depth, TRUE, TRUE, NULL); + debug_flush_alert(NULL, "Map", 0, fbuf->bt_depth, FALSE, + FALSE, fbuf->map_frame); + } + pipe_mutex_unlock(fbuf->mutex); + + if (!item) { + item = CALLOC_STRUCT(debug_flush_item); + if (item) { + debug_flush_buf_reference(&item->fbuf, fbuf); + item->bt_depth = fctx->bt_depth; + item->ref_frame = debug_flush_capture_frame(2, item->bt_depth); + if (util_hash_table_set(fctx->ref_hash, fbuf, item) != PIPE_OK) { + debug_flush_item_destroy(item); + goto out_no_item; + } + return; + } + goto out_no_item; + } + return; + +out_no_item: + debug_printf("Debug flush command buffer reference creation failed.\n"); + debug_printf("Debug flush checking will be incomplete " + "for this command batch.\n"); +} + +static enum pipe_error +debug_flush_might_flush_cb(void *key, void *value, void *data) +{ + struct debug_flush_item *item = + (struct debug_flush_item *) value; + struct debug_flush_buf *fbuf = item->fbuf; + const char *reason = (const char *) data; + char message[80]; + + snprintf(message, sizeof(message), + "%s referenced mapped buffer detected.", reason); + + pipe_mutex_lock(fbuf->mutex); + if (fbuf->mapped_sync) { + debug_flush_alert(message, reason, 3, item->bt_depth, TRUE, TRUE, NULL); + debug_flush_alert(NULL, "Map", 0, fbuf->bt_depth, TRUE, FALSE, + fbuf->map_frame); + debug_flush_alert(NULL, "First reference", 0, item->bt_depth, FALSE, + FALSE, item->ref_frame); + } + pipe_mutex_unlock(fbuf->mutex); + + return PIPE_OK; +} + +void +debug_flush_might_flush(struct debug_flush_ctx *fctx) +{ + if (!fctx) + return; + + util_hash_table_foreach(fctx->ref_hash, + debug_flush_might_flush_cb, + "Might flush"); +} + +static enum pipe_error +debug_flush_flush_cb(void *key, void *value, void *data) +{ + struct debug_flush_item *item = + (struct debug_flush_item *) value; + + debug_flush_item_destroy(item); + + return PIPE_OK; +} + + +void +debug_flush_flush(struct debug_flush_ctx *fctx) +{ + if (!fctx) + return; + + util_hash_table_foreach(fctx->ref_hash, + debug_flush_might_flush_cb, + "Flush"); + util_hash_table_foreach(fctx->ref_hash, + debug_flush_flush_cb, + NULL); + util_hash_table_clear(fctx->ref_hash); +} + +void +debug_flush_ctx_destroy(struct debug_flush_ctx *fctx) +{ + if (!fctx) + return; + + list_del(&fctx->head); + util_hash_table_foreach(fctx->ref_hash, + debug_flush_flush_cb, + NULL); + util_hash_table_clear(fctx->ref_hash); + util_hash_table_destroy(fctx->ref_hash); + FREE(fctx); +} +#endif diff --git a/mesalib/src/gallium/auxiliary/util/u_debug_flush.h b/mesalib/src/gallium/auxiliary/util/u_debug_flush.h new file mode 100644 index 000000000..a604167f0 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_debug_flush.h @@ -0,0 +1,138 @@ +/************************************************************************** + * + * Copyright 2012 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 VMWARE 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 + * u_debug_flush.h - Header for debugging flush- and map- related issues. + * - Flush while synchronously mapped. + * - Command stream reference while synchronously mapped. + * - Synchronous map while referenced on command stream. + * - Recursive maps. + * - Unmap while not mapped. + * + * @author Thomas Hellstrom <thellstrom@vmware.com> + */ +#ifdef DEBUG + +#ifndef U_DEBUG_FLUSH_H_ +#define U_DEBUG_FLUSH_H_ + +struct debug_flush_buf; +struct debug_flush_ctx; + +/** + * Create a buffer (AKA allocation) representation. + * + * @param support_unsync Whether unsynchronous maps are truly supported. + * @param bt_depth Depth of backtrace to be captured for this buffer + * representation. + */ +struct debug_flush_buf * +debug_flush_buf_create(boolean supports_unsync, unsigned bt_depth); + +/** + * Reference a buffer representation. + * + * @param dst Pointer copy destination + * @param src Pointer copy source (may be NULL). + * + * Replace a pointer to a buffer representation with proper refcounting. + */ +void +debug_flush_buf_reference(struct debug_flush_buf **dst, + struct debug_flush_buf *src); + +/** + * Create a context representation. + * + * @param catch_map_of_referenced Whether to catch synchronous maps of buffers + * already present on the command stream. + * @param bt_depth Depth of backtrace to be captured for this context + * representation. + */ +struct debug_flush_ctx * +debug_flush_ctx_create(boolean catch_map_of_referenced, unsigned bt_depth); + +/** + * Destroy a context representation. + * + * @param fctx The context representation to destroy. + */ +void +debug_flush_ctx_destroy(struct debug_flush_ctx *fctx); + +/** + * Map annotation + * + * @param fbuf The buffer representation to map. + * @param flags Pipebuffer flags for the map. + * + * Used to annotate a map of the buffer described by the buffer representation. + */ +void debug_flush_map(struct debug_flush_buf *fbuf, unsigned flags); + +/** + * Unmap annotation + * + * @param fbuf The buffer representation to map. + * + * Used to annotate an unmap of the buffer described by the + * buffer representation. + */ +void debug_flush_unmap(struct debug_flush_buf *fbuf); + +/** + * Might flush annotation + * + * @param fctx The context representation that might be flushed. + * + * Used to annotate a conditional (possible) flush of the given context. + */ +void debug_flush_might_flush(struct debug_flush_ctx *fctx); + +/** + * Flush annotation + * + * @param fctx The context representation that is flushed. + * + * Used to annotate a real flush of the given context. + */ +void debug_flush_flush(struct debug_flush_ctx *fctx); + + +/** + * Flush annotation + * + * @param fctx The context representation that is flushed. + * + * Used to annotate a real flush of the given context. + */ +void debug_flush_cb_reference(struct debug_flush_ctx *fctx, + struct debug_flush_buf *fbuf); + +#endif +#endif diff --git a/mesalib/src/gallium/auxiliary/util/u_format.c b/mesalib/src/gallium/auxiliary/util/u_format.c index 6b602bf32..056f82f72 100644 --- a/mesalib/src/gallium/auxiliary/util/u_format.c +++ b/mesalib/src/gallium/auxiliary/util/u_format.c @@ -527,7 +527,7 @@ util_format_fits_8unorm(const struct util_format_description *format_desc) } -void +boolean util_format_translate(enum pipe_format dst_format, void *dst, unsigned dst_stride, unsigned dst_x, unsigned dst_y, @@ -555,7 +555,7 @@ util_format_translate(enum pipe_format dst_format, util_copy_rect(dst, dst_format, dst_stride, dst_x, dst_y, width, height, src, (int)src_stride, src_x, src_y); - return; + return TRUE; } assert(dst_x % dst_format_desc->block.width == 0); @@ -621,7 +621,7 @@ util_format_translate(enum pipe_format dst_format, FREE(tmp_z); - return; + return TRUE; } if (util_format_fits_8unorm(src_format_desc) || @@ -629,10 +629,15 @@ util_format_translate(enum pipe_format dst_format, unsigned tmp_stride; uint8_t *tmp_row; + if (!src_format_desc->unpack_rgba_8unorm || + !dst_format_desc->pack_rgba_8unorm) { + return FALSE; + } + tmp_stride = MAX2(width, x_step) * 4 * sizeof *tmp_row; tmp_row = MALLOC(y_step * tmp_stride); if (!tmp_row) - return; + return FALSE; while (height >= y_step) { src_format_desc->unpack_rgba_8unorm(tmp_row, tmp_stride, src_row, src_stride, width, y_step); @@ -654,10 +659,15 @@ util_format_translate(enum pipe_format dst_format, unsigned tmp_stride; float *tmp_row; + if (!src_format_desc->unpack_rgba_float || + !dst_format_desc->pack_rgba_float) { + return FALSE; + } + tmp_stride = MAX2(width, x_step) * 4 * sizeof *tmp_row; tmp_row = MALLOC(y_step * tmp_stride); if (!tmp_row) - return; + return FALSE; while (height >= y_step) { src_format_desc->unpack_rgba_float(tmp_row, tmp_stride, src_row, src_stride, width, y_step); @@ -675,6 +685,7 @@ util_format_translate(enum pipe_format dst_format, FREE(tmp_row); } + return TRUE; } void util_format_compose_swizzles(const unsigned char swz1[4], diff --git a/mesalib/src/gallium/auxiliary/util/u_format.h b/mesalib/src/gallium/auxiliary/util/u_format.h index 5f86e2d2c..e36a9e237 100644 --- a/mesalib/src/gallium/auxiliary/util/u_format.h +++ b/mesalib/src/gallium/auxiliary/util/u_format.h @@ -1190,7 +1190,7 @@ util_format_write_4i(enum pipe_format format, boolean util_format_fits_8unorm(const struct util_format_description *format_desc); -void +boolean util_format_translate(enum pipe_format dst_format, void *dst, unsigned dst_stride, unsigned dst_x, unsigned dst_y, diff --git a/mesalib/src/gallium/auxiliary/util/u_math.h b/mesalib/src/gallium/auxiliary/util/u_math.h index b5e06630a..ec03e4e58 100644 --- a/mesalib/src/gallium/auxiliary/util/u_math.h +++ b/mesalib/src/gallium/auxiliary/util/u_math.h @@ -112,10 +112,13 @@ static INLINE float logf( float f ) #define logf(x) ((float)log((double)(x))) #endif /* logf */ +#if _MSC_VER < 1800 #define isfinite(x) _finite((double)(x)) #define isnan(x) _isnan((double)(x)) +#endif /* _MSC_VER < 1800 */ #endif /* _MSC_VER < 1400 && !defined(__cplusplus) */ +#if _MSC_VER < 1800 static INLINE double log2( double x ) { const double invln2 = 1.442695041; @@ -133,6 +136,7 @@ roundf(float x) { return x >= 0.0f ? floorf(x + 0.5f) : ceilf(x - 0.5f); } +#endif #define INFINITY (DBL_MAX + DBL_MAX) #define NAN (INFINITY - INFINITY) @@ -717,13 +721,18 @@ util_bitcount(unsigned n) */ #ifdef PIPE_ARCH_BIG_ENDIAN +#define util_le64_to_cpu(x) util_bswap64(x) #define util_le32_to_cpu(x) util_bswap32(x) #define util_le16_to_cpu(x) util_bswap16(x) #else +#define util_le64_to_cpu(x) (x) #define util_le32_to_cpu(x) (x) #define util_le16_to_cpu(x) (x) #endif +#define util_cpu_to_le64(x) util_le64_to_cpu(x) +#define util_cpu_to_le32(x) util_le32_to_cpu(x) +#define util_cpu_to_le16(x) util_le16_to_cpu(x) /** * Reverse byte order of a 32 bit word. @@ -731,7 +740,8 @@ util_bitcount(unsigned n) static INLINE uint32_t util_bswap32(uint32_t n) { -#if defined(PIPE_CC_GCC) && (PIPE_CC_GCC_VERSION >= 403) +/* We need the gcc version checks for non-autoconf build system */ +#if defined(HAVE___BUILTIN_BSWAP32) || (defined(PIPE_CC_GCC) && (PIPE_CC_GCC_VERSION >= 403)) return __builtin_bswap32(n); #else return (n >> 24) | @@ -741,6 +751,20 @@ util_bswap32(uint32_t n) #endif } +/** + * Reverse byte order of a 64bit word. + */ +static INLINE uint64_t +util_bswap64(uint64_t n) +{ +#if defined(HAVE___BUILTIN_BSWAP64) + return __builtin_bswap64(n); +#else + return ((uint64_t)util_bswap32(n) << 32) | + util_bswap32((n >> 32)); +#endif +} + /** * Reverse byte order of a 16 bit word. diff --git a/mesalib/src/gallium/auxiliary/util/u_range.h b/mesalib/src/gallium/auxiliary/util/u_range.h index 4b1d0d1be..efe25ef5e 100644 --- a/mesalib/src/gallium/auxiliary/util/u_range.h +++ b/mesalib/src/gallium/auxiliary/util/u_range.h @@ -36,6 +36,8 @@ #include "os/os_thread.h" +#include "util/u_math.h" + struct util_range { unsigned start; /* inclusive */ unsigned end; /* exclusive */ diff --git a/mesalib/src/gallium/auxiliary/util/u_upload_mgr.c b/mesalib/src/gallium/auxiliary/util/u_upload_mgr.c index 7349d0068..744ea2e5e 100644 --- a/mesalib/src/gallium/auxiliary/util/u_upload_mgr.c +++ b/mesalib/src/gallium/auxiliary/util/u_upload_mgr.c @@ -44,11 +44,12 @@ struct u_upload_mgr { unsigned default_size; /* Minimum size of the upload buffer, in bytes. */ unsigned alignment; /* Alignment of each sub-allocation. */ unsigned bind; /* Bitmask of PIPE_BIND_* flags. */ + unsigned map_flags; /* Bitmask of PIPE_TRANSFER_* flags. */ + boolean map_persistent; /* If persistent mappings are supported. */ struct pipe_resource *buffer; /* Upload buffer. */ struct pipe_transfer *transfer; /* Transfer object for the upload buffer. */ uint8_t *map; /* Pointer to the mapped upload buffer. */ - unsigned size; /* Actual size of the upload buffer. */ unsigned offset; /* Aligned offset to the upload buffer, pointing * at the first unused byte. */ }; @@ -67,20 +68,39 @@ struct u_upload_mgr *u_upload_create( struct pipe_context *pipe, upload->default_size = default_size; upload->alignment = alignment; upload->bind = bind; - upload->buffer = NULL; + + upload->map_persistent = + pipe->screen->get_param(pipe->screen, + PIPE_CAP_BUFFER_MAP_PERSISTENT_COHERENT); + + if (upload->map_persistent) { + upload->map_flags = PIPE_TRANSFER_WRITE | + PIPE_TRANSFER_PERSISTENT | + PIPE_TRANSFER_COHERENT; + } + else { + upload->map_flags = PIPE_TRANSFER_WRITE | + PIPE_TRANSFER_UNSYNCHRONIZED | + PIPE_TRANSFER_FLUSH_EXPLICIT; + } return upload; } -void u_upload_unmap( struct u_upload_mgr *upload ) + +static void upload_unmap_internal(struct u_upload_mgr *upload, boolean destroying) { + if (!destroying && upload->map_persistent) + return; + if (upload->transfer) { struct pipe_box *box = &upload->transfer->box; - if ((int) upload->offset > box->x) { + if (!upload->map_persistent && (int) upload->offset > box->x) { pipe_buffer_flush_mapped_range(upload->pipe, upload->transfer, box->x, upload->offset - box->x); } + pipe_transfer_unmap(upload->pipe, upload->transfer); upload->transfer = NULL; upload->map = NULL; @@ -88,12 +108,17 @@ void u_upload_unmap( struct u_upload_mgr *upload ) } +void u_upload_unmap( struct u_upload_mgr *upload ) +{ + upload_unmap_internal(upload, FALSE); +} + + static void u_upload_release_buffer(struct u_upload_mgr *upload) { /* Unmap and unreference the upload buffer. */ - u_upload_unmap(upload); + upload_unmap_internal(upload, TRUE); pipe_resource_reference( &upload->buffer, NULL ); - upload->size = 0; } @@ -108,6 +133,8 @@ static enum pipe_error u_upload_alloc_buffer( struct u_upload_mgr *upload, unsigned min_size ) { + struct pipe_screen *screen = upload->pipe->screen; + struct pipe_resource buffer; unsigned size; /* Release the old buffer, if present: @@ -118,28 +145,36 @@ u_upload_alloc_buffer( struct u_upload_mgr *upload, */ size = align(MAX2(upload->default_size, min_size), 4096); - upload->buffer = pipe_buffer_create( upload->pipe->screen, - upload->bind, - PIPE_USAGE_STREAM, - size ); + memset(&buffer, 0, sizeof buffer); + buffer.target = PIPE_BUFFER; + buffer.format = PIPE_FORMAT_R8_UNORM; /* want TYPELESS or similar */ + buffer.bind = upload->bind; + buffer.usage = PIPE_USAGE_STREAM; + buffer.width0 = size; + buffer.height0 = 1; + buffer.depth0 = 1; + buffer.array_size = 1; + + if (upload->map_persistent) { + buffer.flags = PIPE_RESOURCE_FLAG_MAP_PERSISTENT | + PIPE_RESOURCE_FLAG_MAP_COHERENT; + } + + upload->buffer = screen->resource_create(screen, &buffer); if (upload->buffer == NULL) { return PIPE_ERROR_OUT_OF_MEMORY; } /* Map the new buffer. */ upload->map = pipe_buffer_map_range(upload->pipe, upload->buffer, - 0, size, - PIPE_TRANSFER_WRITE | - PIPE_TRANSFER_FLUSH_EXPLICIT, + 0, size, upload->map_flags, &upload->transfer); if (upload->map == NULL) { upload->transfer = NULL; - upload->size = 0; pipe_resource_reference(&upload->buffer, NULL); return PIPE_ERROR_OUT_OF_MEMORY; } - upload->size = size; upload->offset = 0; return PIPE_OK; } @@ -164,7 +199,8 @@ enum pipe_error u_upload_alloc( struct u_upload_mgr *upload, /* Make sure we have enough space in the upload buffer * for the sub-allocation. */ - if (MAX2(upload->offset, alloc_offset) + alloc_size > upload->size) { + if (!upload->buffer || + MAX2(upload->offset, alloc_offset) + alloc_size > upload->buffer->width0) { enum pipe_error ret = u_upload_alloc_buffer(upload, alloc_offset + alloc_size); if (ret != PIPE_OK) @@ -175,10 +211,9 @@ enum pipe_error u_upload_alloc( struct u_upload_mgr *upload, if (!upload->map) { upload->map = pipe_buffer_map_range(upload->pipe, upload->buffer, - offset, upload->size - offset, - PIPE_TRANSFER_WRITE | - PIPE_TRANSFER_FLUSH_EXPLICIT | - PIPE_TRANSFER_UNSYNCHRONIZED, + offset, + upload->buffer->width0 - offset, + upload->map_flags, &upload->transfer); if (!upload->map) { upload->transfer = NULL; diff --git a/mesalib/src/glsl/Makefile.sources b/mesalib/src/glsl/Makefile.sources index e69c1ac61..5945590a5 100644 --- a/mesalib/src/glsl/Makefile.sources +++ b/mesalib/src/glsl/Makefile.sources @@ -67,6 +67,7 @@ LIBGLSL_FILES = \ $(GLSL_SRCDIR)/lower_jumps.cpp \ $(GLSL_SRCDIR)/lower_mat_op_to_vec.cpp \ $(GLSL_SRCDIR)/lower_noise.cpp \ + $(GLSL_SRCDIR)/lower_offset_array.cpp \ $(GLSL_SRCDIR)/lower_packed_varyings.cpp \ $(GLSL_SRCDIR)/lower_named_interface_blocks.cpp \ $(GLSL_SRCDIR)/lower_packing_builtins.cpp \ diff --git a/mesalib/src/glsl/ast.h b/mesalib/src/glsl/ast.h index 61fd923bc..1efb30679 100644 --- a/mesalib/src/glsl/ast.h +++ b/mesalib/src/glsl/ast.h @@ -280,14 +280,14 @@ class ast_array_specifier : public ast_node { public: /** Unsized array specifier ([]) */ explicit ast_array_specifier(const struct YYLTYPE &locp) - : dimension_count(1), is_unsized_array(true) + : is_unsized_array(true) { set_location(locp); } /** Sized array specifier ([dim]) */ ast_array_specifier(const struct YYLTYPE &locp, ast_expression *dim) - : dimension_count(1), is_unsized_array(false) + : is_unsized_array(false) { set_location(locp); array_dimensions.push_tail(&dim->link); @@ -296,14 +296,10 @@ public: void add_dimension(ast_expression *dim) { array_dimensions.push_tail(&dim->link); - dimension_count++; } virtual void print(void) const; - /* Count including sized and unsized dimensions */ - unsigned dimension_count; - /* If true, this means that the array has an unsized outermost dimension. */ bool is_unsized_array; @@ -466,17 +462,36 @@ struct ast_type_qualifier { * local_size_x, and so on. */ unsigned local_size:3; + + /** \name Layout and memory qualifiers for ARB_shader_image_load_store. */ + /** \{ */ + unsigned early_fragment_tests:1; + unsigned explicit_image_format:1; + unsigned coherent:1; + unsigned _volatile:1; + unsigned restrict_flag:1; + unsigned read_only:1; /**< "readonly" qualifier. */ + unsigned write_only:1; /**< "writeonly" qualifier. */ + /** \} */ + + /** \name Layout qualifiers for GL_ARB_gpu_shader5 */ + /** \{ */ + unsigned invocations:1; + /** \} */ } /** \brief Set of flags, accessed by name. */ q; /** \brief Set of flags, accessed as a bitmask. */ - unsigned i; + uint64_t i; } flags; /** Precision of the type (highp/medium/lowp). */ unsigned precision:2; + /** Geometry shader invocations for GL_ARB_gpu_shader5. */ + int invocations; + /** * Location specified via GL_ARB_explicit_attrib_location layout * @@ -523,6 +538,25 @@ struct ast_type_qualifier { int local_size[3]; /** + * Image format specified with an ARB_shader_image_load_store + * layout qualifier. + * + * \note + * This field is only valid if \c explicit_image_format is set. + */ + GLenum image_format; + + /** + * Base type of the data read from or written to this image. Only + * the following enumerants are allowed: GLSL_TYPE_UINT, + * GLSL_TYPE_INT, GLSL_TYPE_FLOAT. + * + * \note + * This field is only valid if \c explicit_image_format is set. + */ + glsl_base_type image_base_type; + + /** * Return true if and only if an interpolation qualifier is present. */ bool has_interpolation() const; @@ -557,6 +591,12 @@ struct ast_type_qualifier { bool merge_qualifier(YYLTYPE *loc, _mesa_glsl_parse_state *state, ast_type_qualifier q); + + bool merge_in_qualifier(YYLTYPE *loc, + _mesa_glsl_parse_state *state, + ast_type_qualifier q, + ast_node* &node); + }; class ast_declarator_list; diff --git a/mesalib/src/glsl/ast_function.cpp b/mesalib/src/glsl/ast_function.cpp index 4c5b0e4aa..4b8447067 100644 --- a/mesalib/src/glsl/ast_function.cpp +++ b/mesalib/src/glsl/ast_function.cpp @@ -93,6 +93,57 @@ prototype_string(const glsl_type *return_type, const char *name, return str; } +static bool +verify_image_parameter(YYLTYPE *loc, _mesa_glsl_parse_state *state, + const ir_variable *formal, const ir_variable *actual) +{ + /** + * From the ARB_shader_image_load_store specification: + * + * "The values of image variables qualified with coherent, + * volatile, restrict, readonly, or writeonly may not be passed + * to functions whose formal parameters lack such + * qualifiers. [...] It is legal to have additional qualifiers + * on a formal parameter, but not to have fewer." + */ + if (actual->data.image.coherent && !formal->data.image.coherent) { + _mesa_glsl_error(loc, state, + "function call parameter `%s' drops " + "`coherent' qualifier", formal->name); + return false; + } + + if (actual->data.image._volatile && !formal->data.image._volatile) { + _mesa_glsl_error(loc, state, + "function call parameter `%s' drops " + "`volatile' qualifier", formal->name); + return false; + } + + if (actual->data.image.restrict_flag && !formal->data.image.restrict_flag) { + _mesa_glsl_error(loc, state, + "function call parameter `%s' drops " + "`restrict' qualifier", formal->name); + return false; + } + + if (actual->data.image.read_only && !formal->data.image.read_only) { + _mesa_glsl_error(loc, state, + "function call parameter `%s' drops " + "`readonly' qualifier", formal->name); + return false; + } + + if (actual->data.image.write_only && !formal->data.image.write_only) { + _mesa_glsl_error(loc, state, + "function call parameter `%s' drops " + "`writeonly' qualifier", formal->name); + return false; + } + + return true; +} + /** * Verify that 'out' and 'inout' actual parameters are lvalues. Also, verify * that 'const_in' formal parameters (an extension in our IR) correspond to @@ -180,6 +231,13 @@ verify_parameter_modes(_mesa_glsl_parse_state *state, } } + if (formal->type->is_image() && + actual->variable_referenced()) { + if (!verify_image_parameter(&loc, state, formal, + actual->variable_referenced())) + return false; + } + actual_ir_node = actual_ir_node->next; actual_ast_node = actual_ast_node->next; } diff --git a/mesalib/src/glsl/ast_to_hir.cpp b/mesalib/src/glsl/ast_to_hir.cpp index c89a26bf9..8f6e90174 100644 --- a/mesalib/src/glsl/ast_to_hir.cpp +++ b/mesalib/src/glsl/ast_to_hir.cpp @@ -969,6 +969,7 @@ do_comparison(void *mem_ctx, int operation, ir_rvalue *op0, ir_rvalue *op1) case GLSL_TYPE_ERROR: case GLSL_TYPE_VOID: case GLSL_TYPE_SAMPLER: + case GLSL_TYPE_IMAGE: case GLSL_TYPE_INTERFACE: case GLSL_TYPE_ATOMIC_UINT: /* I assume a comparison of a struct containing a sampler just @@ -1796,7 +1797,7 @@ ast_compound_statement::hir(exec_list *instructions, * Evaluate the given exec_node (which should be an ast_node representing * a single array dimension) and return its integer value. */ -static const unsigned +static unsigned process_array_size(exec_node *node, struct _mesa_glsl_parse_state *state) { @@ -2122,11 +2123,16 @@ validate_explicit_location(const struct ast_type_qualifier *qual, { bool fail = false; - /* In the vertex shader only shader inputs can be given explicit - * locations. + /* Between GL_ARB_explicit_attrib_location an + * GL_ARB_separate_shader_objects, the inputs and outputs of any shader + * stage can be assigned explicit locations. The checking here associates + * the correct extension with the correct stage's input / output: * - * In the fragment shader only shader outputs can be given explicit - * locations. + * input output + * ----- ------ + * vertex explicit_loc sso + * geometry sso sso + * fragment sso explicit_loc */ switch (state->stage) { case MESA_SHADER_VERTEX: @@ -2137,16 +2143,35 @@ validate_explicit_location(const struct ast_type_qualifier *qual, break; } + if (var->data.mode == ir_var_shader_out) { + if (!state->check_separate_shader_objects_allowed(loc, var)) + return; + + break; + } + fail = true; break; case MESA_SHADER_GEOMETRY: - _mesa_glsl_error(loc, state, - "geometry shader variables cannot be given " - "explicit locations"); - return; + if (var->data.mode == ir_var_shader_in || var->data.mode == ir_var_shader_out) { + if (!state->check_separate_shader_objects_allowed(loc, var)) + return; + + break; + } + + fail = true; + break; case MESA_SHADER_FRAGMENT: + if (var->data.mode == ir_var_shader_in) { + if (!state->check_separate_shader_objects_allowed(loc, var)) + return; + + break; + } + if (var->data.mode == ir_var_shader_out) { if (!state->check_explicit_attrib_location_allowed(loc, var)) return; @@ -2180,9 +2205,26 @@ validate_explicit_location(const struct ast_type_qualifier *qual, * ensures that negative values stay negative. */ if (qual->location >= 0) { - var->data.location = (state->stage == MESA_SHADER_VERTEX) - ? (qual->location + VERT_ATTRIB_GENERIC0) - : (qual->location + FRAG_RESULT_DATA0); + switch (state->stage) { + case MESA_SHADER_VERTEX: + var->data.location = (var->data.mode == ir_var_shader_in) + ? (qual->location + VERT_ATTRIB_GENERIC0) + : (qual->location + VARYING_SLOT_VAR0); + break; + + case MESA_SHADER_GEOMETRY: + var->data.location = qual->location + VARYING_SLOT_VAR0; + break; + + case MESA_SHADER_FRAGMENT: + var->data.location = (var->data.mode == ir_var_shader_out) + ? (qual->location + FRAG_RESULT_DATA0) + : (qual->location + VARYING_SLOT_VAR0); + break; + case MESA_SHADER_COMPUTE: + assert(!"Unexpected shader type"); + break; + } } else { var->data.location = qual->location; } @@ -2206,8 +2248,54 @@ validate_explicit_location(const struct ast_type_qualifier *qual, } } } +} + +static void +apply_image_qualifier_to_variable(const struct ast_type_qualifier *qual, + ir_variable *var, + struct _mesa_glsl_parse_state *state, + YYLTYPE *loc) +{ + const glsl_type *base_type = + (var->type->is_array() ? var->type->element_type() : var->type); + + if (base_type->is_image()) { + if (var->data.mode != ir_var_uniform && + var->data.mode != ir_var_function_in) { + _mesa_glsl_error(loc, state, "image variables may only be declared as " + "function parameters or uniform-qualified " + "global variables"); + } + + var->data.image.read_only |= qual->flags.q.read_only; + var->data.image.write_only |= qual->flags.q.write_only; + var->data.image.coherent |= qual->flags.q.coherent; + var->data.image._volatile |= qual->flags.q._volatile; + var->data.image.restrict_flag |= qual->flags.q.restrict_flag; + var->data.read_only = true; + + if (qual->flags.q.explicit_image_format) { + if (var->data.mode == ir_var_function_in) { + _mesa_glsl_error(loc, state, "format qualifiers cannot be " + "used on image function parameters"); + } + + if (qual->image_base_type != base_type->sampler_type) { + _mesa_glsl_error(loc, state, "format qualifier doesn't match the " + "base data type of the image"); + } + + var->data.image.format = qual->image_format; + } else { + if (var->data.mode == ir_var_uniform && !qual->flags.q.write_only) { + _mesa_glsl_error(loc, state, "uniforms not qualified with " + "`writeonly' must have a format layout " + "qualifier"); + } - return; + var->data.image.format = GL_NONE; + } + } } static void @@ -2500,6 +2588,9 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual, if (qual->flags.q.row_major || qual->flags.q.column_major) { validate_matrix_layout_for_type(state, loc, var->type, var); } + + if (var->type->contains_image()) + apply_image_qualifier_to_variable(qual, var, state, loc); } /** @@ -2659,9 +2750,15 @@ process_initializer(ir_variable *var, ast_declaration *decl, "cannot initialize uniforms"); } - if (var->type->is_sampler()) { + /* From section 4.1.7 of the GLSL 4.40 spec: + * + * "Opaque variables [...] are initialized only through the + * OpenGL API; they cannot be declared with an initializer in a + * shader." + */ + if (var->type->contains_opaque()) { _mesa_glsl_error(& initializer_loc, state, - "cannot initialize samplers"); + "cannot initialize opaque variable"); } if ((var->data.mode == ir_var_shader_in) && (state->current_function == NULL)) { @@ -2784,7 +2881,7 @@ handle_geometry_shader_input_decl(struct _mesa_glsl_parse_state *state, { unsigned num_vertices = 0; if (state->gs_input_prim_type_specified) { - num_vertices = vertices_per_prim(state->gs_input_prim_type); + num_vertices = vertices_per_prim(state->in_qualifier->prim_type); } /* Geometry shader input variables must be arrays. Caller should have @@ -2870,10 +2967,17 @@ validate_identifier(const char *identifier, YYLTYPE loc, * "In addition, all identifiers containing two * consecutive underscores (__) are reserved as * possible future keywords." + * + * The intention is that names containing __ are reserved for internal + * use by the implementation, and names prefixed with GL_ are reserved + * for use by Khronos. Names simply containing __ are dangerous to use, + * but should be allowed. + * + * A future version of the GLSL specification will clarify this. */ - _mesa_glsl_error(&loc, state, - "identifier `%s' uses reserved `__' string", - identifier); + _mesa_glsl_warning(&loc, state, + "identifier `%s' uses reserved `__' string", + identifier); } } @@ -3082,6 +3186,7 @@ ast_declarator_list::hir(exec_list *instructions, */ if (!state->is_version(130, 300) && !state->has_explicit_attrib_location() + && !state->has_separate_shader_objects() && !state->ARB_fragment_coord_conventions_enable) { if (this->type->qualifier.flags.q.out) { _mesa_glsl_error(& loc, state, @@ -3421,15 +3526,15 @@ ast_declarator_list::hir(exec_list *instructions, ", integer and sampler types"); } - /* From page 17 (page 23 of the PDF) of the GLSL 1.20 spec: + /* From section 4.1.7 of the GLSL 4.40 spec: * - * "[Sampler types] can only be declared as function - * parameters or uniform variables (see Section 4.3.5 - * "Uniform")". + * "[Opaque types] can only be declared as function + * parameters or uniform-qualified variables." */ - if (var_type->contains_sampler() && + if (var_type->contains_opaque() && !this->type->qualifier.flags.q.uniform) { - _mesa_glsl_error(&loc, state, "samplers must be declared uniform"); + _mesa_glsl_error(&loc, state, + "opaque variables must be declared uniform"); } /* Process the initializer and add its instructions to a temporary @@ -3621,15 +3726,16 @@ ast_parameter_declarator::hir(exec_list *instructions, apply_type_qualifier_to_variable(& this->type->qualifier, var, state, & loc, true); - /* From page 17 (page 23 of the PDF) of the GLSL 1.20 spec: + /* From section 4.1.7 of the GLSL 4.40 spec: * - * "Samplers cannot be treated as l-values; hence cannot be used - * as out or inout function parameters, nor can they be assigned - * into." + * "Opaque variables cannot be treated as l-values; hence cannot + * be used as out or inout function parameters, nor can they be + * assigned into." */ if ((var->data.mode == ir_var_function_inout || var->data.mode == ir_var_function_out) - && type->contains_sampler()) { - _mesa_glsl_error(&loc, state, "out and inout parameters cannot contain samplers"); + && type->contains_opaque()) { + _mesa_glsl_error(&loc, state, "out and inout parameters cannot " + "contain opaque variables"); type = glsl_type::error_type; } @@ -3784,15 +3890,15 @@ ast_function::hir(exec_list *instructions, "sized", name); } - /* From page 17 (page 23 of the PDF) of the GLSL 1.20 spec: + /* From section 4.1.7 of the GLSL 4.40 spec: * - * "[Sampler types] can only be declared as function parameters - * or uniform variables (see Section 4.3.5 "Uniform")". + * "[Opaque types] can only be declared as function parameters + * or uniform-qualified variables." */ - if (return_type->contains_sampler()) { + if (return_type->contains_opaque()) { YYLTYPE loc = this->get_location(); _mesa_glsl_error(&loc, state, - "function `%s' return type can't contain a sampler", + "function `%s' return type can't contain an opaque type", name); } @@ -4693,12 +4799,9 @@ ast_process_structure_or_interface_block(exec_list *instructions, if (!allow_reserved_names) validate_identifier(decl->identifier, loc, state); - /* From the GL_ARB_uniform_buffer_object spec: + /* From section 4.3.9 of the GLSL 4.40 spec: * - * "Sampler types are not allowed inside of uniform - * blocks. All other types, arrays, and structures - * allowed for uniforms are allowed within a uniform - * block." + * "[In interface blocks] opaque types are not allowed." * * It should be impossible for decl_type to be NULL here. Cases that * might naturally lead to decl_type being NULL, especially for the @@ -4708,10 +4811,11 @@ ast_process_structure_or_interface_block(exec_list *instructions, const struct glsl_type *field_type = decl_type != NULL ? decl_type : glsl_type::error_type; - if (is_interface && field_type->contains_sampler()) { + if (is_interface && field_type->contains_opaque()) { YYLTYPE loc = decl_list->get_location(); _mesa_glsl_error(&loc, state, - "uniform in non-default uniform block contains sampler"); + "uniform in non-default uniform block contains " + "opaque variable"); } if (field_type->contains_atomic()) { @@ -4725,6 +4829,16 @@ ast_process_structure_or_interface_block(exec_list *instructions, "uniform block"); } + if (field_type->contains_image()) { + /* FINISHME: Same problem as with atomic counters. + * FINISHME: Request clarification from Khronos and add + * FINISHME: spec quotation here. + */ + YYLTYPE loc = decl_list->get_location(); + _mesa_glsl_error(&loc, state, + "image in structure or uniform block"); + } + const struct ast_type_qualifier *const qual = & decl_list->type->qualifier; if (qual->flags.q.std140 || @@ -5258,7 +5372,7 @@ ast_gs_input_layout::hir(exec_list *instructions, * was consistent with this one. */ if (state->gs_input_prim_type_specified && - state->gs_input_prim_type != this->prim_type) { + state->in_qualifier->prim_type != this->prim_type) { _mesa_glsl_error(&loc, state, "geometry shader input layout does not match" " previous declaration"); @@ -5279,7 +5393,6 @@ ast_gs_input_layout::hir(exec_list *instructions, } state->gs_input_prim_type_specified = true; - state->gs_input_prim_type = this->prim_type; /* If any shader inputs occurred before this declaration and did not * specify an array size, their size is determined now. diff --git a/mesalib/src/glsl/ast_type.cpp b/mesalib/src/glsl/ast_type.cpp index bbc430808..0ee2c495a 100644 --- a/mesalib/src/glsl/ast_type.cpp +++ b/mesalib/src/glsl/ast_type.cpp @@ -190,6 +190,117 @@ ast_type_qualifier::merge_qualifier(YYLTYPE *loc, if (q.precision != ast_precision_none) this->precision = q.precision; + if (q.flags.q.explicit_image_format) { + this->image_format = q.image_format; + this->image_base_type = q.image_base_type; + } + return true; } +bool +ast_type_qualifier::merge_in_qualifier(YYLTYPE *loc, + _mesa_glsl_parse_state *state, + ast_type_qualifier q, + ast_node* &node) +{ + void *mem_ctx = state; + bool create_gs_ast = false; + bool create_cs_ast = false; + ast_type_qualifier valid_in_mask; + valid_in_mask.flags.i = 0; + + switch (state->stage) { + case MESA_SHADER_GEOMETRY: + if (q.flags.q.prim_type) { + /* Make sure this is a valid input primitive type. */ + switch (q.prim_type) { + case GL_POINTS: + case GL_LINES: + case GL_LINES_ADJACENCY: + case GL_TRIANGLES: + case GL_TRIANGLES_ADJACENCY: + break; + default: + _mesa_glsl_error(loc, state, + "invalid geometry shader input primitive type"); + break; + } + } + + create_gs_ast |= + q.flags.q.prim_type && + !state->in_qualifier->flags.q.prim_type; + + valid_in_mask.flags.q.prim_type = 1; + valid_in_mask.flags.q.invocations = 1; + break; + case MESA_SHADER_FRAGMENT: + if (q.flags.q.early_fragment_tests) { + state->early_fragment_tests = true; + } else { + _mesa_glsl_error(loc, state, "invalid input layout qualifier"); + } + break; + case MESA_SHADER_COMPUTE: + create_cs_ast |= + q.flags.q.local_size != 0 && + state->in_qualifier->flags.q.local_size == 0; + + valid_in_mask.flags.q.local_size = 1; + break; + default: + _mesa_glsl_error(loc, state, + "input layout qualifiers only valid in " + "geometry, fragment and compute shaders"); + break; + } + + /* Generate an error when invalid input layout qualifiers are used. */ + if ((q.flags.i & ~valid_in_mask.flags.i) != 0) { + _mesa_glsl_error(loc, state, + "invalid input layout qualifiers used"); + return false; + } + + /* Input layout qualifiers can be specified multiple + * times in separate declarations, as long as they match. + */ + if (this->flags.q.prim_type) { + if (q.flags.q.prim_type && + this->prim_type != q.prim_type) { + _mesa_glsl_error(loc, state, + "conflicting input primitive types specified"); + } + } else if (q.flags.q.prim_type) { + state->in_qualifier->flags.q.prim_type = 1; + state->in_qualifier->prim_type = q.prim_type; + } + + if (this->flags.q.invocations && + q.flags.q.invocations && + this->invocations != q.invocations) { + _mesa_glsl_error(loc, state, + "conflicting invocations counts specified"); + return false; + } else if (q.flags.q.invocations) { + this->flags.q.invocations = 1; + this->invocations = q.invocations; + } + + if (create_gs_ast) { + node = new(mem_ctx) ast_gs_input_layout(*loc, q.prim_type); + } else if (create_cs_ast) { + /* Infer a local_size of 1 for every unspecified dimension */ + unsigned local_size[3]; + for (int i = 0; i < 3; i++) { + if (q.flags.q.local_size & (1 << i)) + local_size[i] = q.local_size[i]; + else + local_size[i] = 1; + } + node = new(mem_ctx) ast_cs_input_layout(*loc, local_size); + } + + return true; +} diff --git a/mesalib/src/glsl/builtin_functions.cpp b/mesalib/src/glsl/builtin_functions.cpp index aeb8e5d94..a52077d06 100644 --- a/mesalib/src/glsl/builtin_functions.cpp +++ b/mesalib/src/glsl/builtin_functions.cpp @@ -340,6 +340,13 @@ shader_trinary_minmax(const _mesa_glsl_parse_state *state) return state->AMD_shader_trinary_minmax_enable; } +static bool +shader_image_load_store(const _mesa_glsl_parse_state *state) +{ + return (state->is_version(420, 0) || + state->ARB_shader_image_load_store_enable); +} + /** @} */ /******************************************************************************/ @@ -413,6 +420,33 @@ private: /** Create a new function and add the given signatures. */ void add_function(const char *name, ...); + enum image_function_flags { + IMAGE_FUNCTION_EMIT_STUB = (1 << 0), + IMAGE_FUNCTION_RETURNS_VOID = (1 << 1), + IMAGE_FUNCTION_HAS_VECTOR_DATA_TYPE = (1 << 2), + IMAGE_FUNCTION_SUPPORTS_FLOAT_DATA_TYPE = (1 << 3), + IMAGE_FUNCTION_READ_ONLY = (1 << 4), + IMAGE_FUNCTION_WRITE_ONLY = (1 << 5) + }; + + /** + * Create a new image built-in function for all known image types. + * \p flags is a bitfield of \c image_function_flags flags. + */ + void add_image_function(const char *name, + const char *intrinsic_name, + unsigned num_arguments, + unsigned flags); + + /** + * Create new functions for all known image built-ins and types. + * If \p glsl is \c true, use the GLSL built-in names and emit code + * to call into the actual compiler intrinsic. If \p glsl is + * false, emit a function prototype with no body for each image + * intrinsic name. + */ + void add_image_functions(bool glsl); + ir_function_signature *new_sig(const glsl_type *return_type, builtin_available_predicate avail, int num_params, ...); @@ -580,6 +614,20 @@ private: B1(max3) B1(mid3) + ir_function_signature *_image_prototype(const glsl_type *image_type, + const char *intrinsic_name, + unsigned num_arguments, + unsigned flags); + ir_function_signature *_image(const glsl_type *image_type, + const char *intrinsic_name, + unsigned num_arguments, + unsigned flags); + + ir_function_signature *_memory_barrier_intrinsic( + builtin_available_predicate avail); + ir_function_signature *_memory_barrier( + builtin_available_predicate avail); + #undef B0 #undef B1 #undef B2 @@ -694,6 +742,12 @@ builtin_builder::create_intrinsics() add_function("__intrinsic_atomic_predecrement", _atomic_intrinsic(shader_atomic_counters), NULL); + + add_image_functions(false); + + add_function("__intrinsic_memory_barrier", + _memory_barrier_intrinsic(shader_image_load_store), + NULL); } /** @@ -2167,6 +2221,12 @@ builtin_builder::create_builtins() _mid3(glsl_type::uvec4_type), NULL); + add_image_functions(true); + + add_function("memoryBarrier", + _memory_barrier(shader_image_load_store), + NULL); + #undef F #undef FI #undef FIU @@ -2200,6 +2260,104 @@ builtin_builder::add_function(const char *name, ...) shader->symbols->add_function(f); } +void +builtin_builder::add_image_function(const char *name, + const char *intrinsic_name, + unsigned num_arguments, + unsigned flags) +{ + static const glsl_type *const types[] = { + glsl_type::image1D_type, + glsl_type::image2D_type, + glsl_type::image3D_type, + glsl_type::image2DRect_type, + glsl_type::imageCube_type, + glsl_type::imageBuffer_type, + glsl_type::image1DArray_type, + glsl_type::image2DArray_type, + glsl_type::imageCubeArray_type, + glsl_type::image2DMS_type, + glsl_type::image2DMSArray_type, + glsl_type::iimage1D_type, + glsl_type::iimage2D_type, + glsl_type::iimage3D_type, + glsl_type::iimage2DRect_type, + glsl_type::iimageCube_type, + glsl_type::iimageBuffer_type, + glsl_type::iimage1DArray_type, + glsl_type::iimage2DArray_type, + glsl_type::iimageCubeArray_type, + glsl_type::iimage2DMS_type, + glsl_type::iimage2DMSArray_type, + glsl_type::uimage1D_type, + glsl_type::uimage2D_type, + glsl_type::uimage3D_type, + glsl_type::uimage2DRect_type, + glsl_type::uimageCube_type, + glsl_type::uimageBuffer_type, + glsl_type::uimage1DArray_type, + glsl_type::uimage2DArray_type, + glsl_type::uimageCubeArray_type, + glsl_type::uimage2DMS_type, + glsl_type::uimage2DMSArray_type + }; + ir_function *f = new(mem_ctx) ir_function(name); + + for (unsigned i = 0; i < Elements(types); ++i) { + if (types[i]->sampler_type != GLSL_TYPE_FLOAT || + (flags & IMAGE_FUNCTION_SUPPORTS_FLOAT_DATA_TYPE)) + f->add_signature(_image(types[i], intrinsic_name, + num_arguments, flags)); + } + + shader->symbols->add_function(f); +} + +void +builtin_builder::add_image_functions(bool glsl) +{ + const unsigned flags = (glsl ? IMAGE_FUNCTION_EMIT_STUB : 0); + + add_image_function(glsl ? "imageLoad" : "__intrinsic_image_load", + "__intrinsic_image_load", 0, + (flags | IMAGE_FUNCTION_HAS_VECTOR_DATA_TYPE | + IMAGE_FUNCTION_SUPPORTS_FLOAT_DATA_TYPE | + IMAGE_FUNCTION_READ_ONLY)); + + add_image_function(glsl ? "imageStore" : "__intrinsic_image_store", + "__intrinsic_image_store", 1, + (flags | IMAGE_FUNCTION_RETURNS_VOID | + IMAGE_FUNCTION_HAS_VECTOR_DATA_TYPE | + IMAGE_FUNCTION_SUPPORTS_FLOAT_DATA_TYPE | + IMAGE_FUNCTION_WRITE_ONLY)); + + add_image_function(glsl ? "imageAtomicAdd" : "__intrinsic_image_atomic_add", + "__intrinsic_image_atomic_add", 1, flags); + + add_image_function(glsl ? "imageAtomicMin" : "__intrinsic_image_atomic_min", + "__intrinsic_image_atomic_min", 1, flags); + + add_image_function(glsl ? "imageAtomicMax" : "__intrinsic_image_atomic_max", + "__intrinsic_image_atomic_max", 1, flags); + + add_image_function(glsl ? "imageAtomicAnd" : "__intrinsic_image_atomic_and", + "__intrinsic_image_atomic_and", 1, flags); + + add_image_function(glsl ? "imageAtomicOr" : "__intrinsic_image_atomic_or", + "__intrinsic_image_atomic_or", 1, flags); + + add_image_function(glsl ? "imageAtomicXor" : "__intrinsic_image_atomic_xor", + "__intrinsic_image_atomic_xor", 1, flags); + + add_image_function((glsl ? "imageAtomicExchange" : + "__intrinsic_image_atomic_exchange"), + "__intrinsic_image_atomic_exchange", 1, flags); + + add_image_function((glsl ? "imageAtomicCompSwap" : + "__intrinsic_image_atomic_comp_swap"), + "__intrinsic_image_atomic_comp_swap", 2, flags); +} + ir_variable * builtin_builder::in_var(const glsl_type *type, const char *name) { @@ -3549,7 +3707,7 @@ builtin_builder::_texture(ir_texture_opcode opcode, ir_texture *tex = new(mem_ctx) ir_texture(opcode); tex->set_sampler(var_ref(s), return_type); - const int coord_size = sampler_type->sampler_coordinate_components(); + const int coord_size = sampler_type->coordinate_components(); if (coord_size == coord_type->vector_elements) { tex->coordinate = var_ref(P); @@ -4094,12 +4252,106 @@ builtin_builder::_mid3(const glsl_type *type) return sig; } +ir_function_signature * +builtin_builder::_image_prototype(const glsl_type *image_type, + const char *intrinsic_name, + unsigned num_arguments, + unsigned flags) +{ + const glsl_type *data_type = glsl_type::get_instance( + image_type->sampler_type, + (flags & IMAGE_FUNCTION_HAS_VECTOR_DATA_TYPE ? 4 : 1), + 1); + const glsl_type *ret_type = (flags & IMAGE_FUNCTION_RETURNS_VOID ? + glsl_type::void_type : data_type); + + /* Addressing arguments that are always present. */ + ir_variable *image = in_var(image_type, "image"); + ir_variable *coord = in_var( + glsl_type::ivec(image_type->coordinate_components()), "coord"); + + ir_function_signature *sig = new_sig( + ret_type, shader_image_load_store, 2, image, coord); + + /* Sample index for multisample images. */ + if (image_type->sampler_dimensionality == GLSL_SAMPLER_DIM_MS) + sig->parameters.push_tail(in_var(glsl_type::int_type, "sample")); + + /* Data arguments. */ + for (unsigned i = 0; i < num_arguments; ++i) + sig->parameters.push_tail(in_var(data_type, + ralloc_asprintf(NULL, "arg%d", i))); + + /* Set the maximal set of qualifiers allowed for this image + * built-in. Function calls with arguments having fewer + * qualifiers than present in the prototype are allowed by the + * spec, but not with more, i.e. this will make the compiler + * accept everything that needs to be accepted, and reject cases + * like loads from write-only or stores to read-only images. + */ + image->data.image.read_only = flags & IMAGE_FUNCTION_READ_ONLY; + image->data.image.write_only = flags & IMAGE_FUNCTION_WRITE_ONLY; + image->data.image.coherent = true; + image->data.image._volatile = true; + image->data.image.restrict_flag = true; + + return sig; +} + +ir_function_signature * +builtin_builder::_image(const glsl_type *image_type, + const char *intrinsic_name, + unsigned num_arguments, + unsigned flags) +{ + ir_function_signature *sig = _image_prototype(image_type, intrinsic_name, + num_arguments, flags); + + if (flags & IMAGE_FUNCTION_EMIT_STUB) { + ir_factory body(&sig->body, mem_ctx); + ir_function *f = shader->symbols->get_function(intrinsic_name); + + if (flags & IMAGE_FUNCTION_RETURNS_VOID) { + body.emit(call(f, NULL, sig->parameters)); + } else { + ir_variable *ret_val = + body.make_temp(sig->return_type, "_ret_val"); + body.emit(call(f, ret_val, sig->parameters)); + body.emit(ret(ret_val)); + } + + sig->is_defined = true; + + } else { + sig->is_intrinsic = true; + } + + return sig; +} + +ir_function_signature * +builtin_builder::_memory_barrier_intrinsic(builtin_available_predicate avail) +{ + MAKE_INTRINSIC(glsl_type::void_type, avail, 0); + return sig; +} + +ir_function_signature * +builtin_builder::_memory_barrier(builtin_available_predicate avail) +{ + MAKE_SIG(glsl_type::void_type, avail, 0); + body.emit(call(shader->symbols->get_function("__intrinsic_memory_barrier"), + NULL, sig->parameters)); + return sig; +} + /** @} */ /******************************************************************************/ /* The singleton instance of builtin_builder. */ static builtin_builder builtins; +static mtx_t builtins_lock = _MTX_INITIALIZER_NP; /** * External API (exposing the built-in module to the rest of the compiler): @@ -4108,20 +4360,28 @@ static builtin_builder builtins; void _mesa_glsl_initialize_builtin_functions() { + mtx_lock(&builtins_lock); builtins.initialize(); + mtx_unlock(&builtins_lock); } void _mesa_glsl_release_builtin_functions() { + mtx_lock(&builtins_lock); builtins.release(); + mtx_unlock(&builtins_lock); } ir_function_signature * _mesa_glsl_find_builtin_function(_mesa_glsl_parse_state *state, const char *name, exec_list *actual_parameters) { - return builtins.find(state, name, actual_parameters); + ir_function_signature * s; + mtx_lock(&builtins_lock); + s = builtins.find(state, name, actual_parameters); + mtx_unlock(&builtins_lock); + return s; } gl_shader * diff --git a/mesalib/src/glsl/builtin_type_macros.h b/mesalib/src/glsl/builtin_type_macros.h index 06b4dbd0f..236e1ce8c 100644 --- a/mesalib/src/glsl/builtin_type_macros.h +++ b/mesalib/src/glsl/builtin_type_macros.h @@ -64,51 +64,85 @@ DECL_TYPE(mat3x4, GL_FLOAT_MAT3x4, GLSL_TYPE_FLOAT, 4, 3) DECL_TYPE(mat4x2, GL_FLOAT_MAT4x2, GLSL_TYPE_FLOAT, 2, 4) DECL_TYPE(mat4x3, GL_FLOAT_MAT4x3, GLSL_TYPE_FLOAT, 3, 4) -DECL_TYPE(sampler1D, GL_SAMPLER_1D, GLSL_SAMPLER_DIM_1D, 0, 0, GLSL_TYPE_FLOAT) -DECL_TYPE(sampler2D, GL_SAMPLER_2D, GLSL_SAMPLER_DIM_2D, 0, 0, GLSL_TYPE_FLOAT) -DECL_TYPE(sampler3D, GL_SAMPLER_3D, GLSL_SAMPLER_DIM_3D, 0, 0, GLSL_TYPE_FLOAT) -DECL_TYPE(samplerCube, GL_SAMPLER_CUBE, GLSL_SAMPLER_DIM_CUBE, 0, 0, GLSL_TYPE_FLOAT) -DECL_TYPE(sampler1DArray, GL_SAMPLER_1D_ARRAY, GLSL_SAMPLER_DIM_1D, 0, 1, GLSL_TYPE_FLOAT) -DECL_TYPE(sampler2DArray, GL_SAMPLER_2D_ARRAY, GLSL_SAMPLER_DIM_2D, 0, 1, GLSL_TYPE_FLOAT) -DECL_TYPE(samplerCubeArray, GL_SAMPLER_CUBE_MAP_ARRAY, GLSL_SAMPLER_DIM_CUBE, 0, 1, GLSL_TYPE_FLOAT) -DECL_TYPE(sampler2DRect, GL_SAMPLER_2D_RECT, GLSL_SAMPLER_DIM_RECT, 0, 0, GLSL_TYPE_FLOAT) -DECL_TYPE(samplerBuffer, GL_SAMPLER_BUFFER, GLSL_SAMPLER_DIM_BUF, 0, 0, GLSL_TYPE_FLOAT) -DECL_TYPE(sampler2DMS, GL_SAMPLER_2D_MULTISAMPLE, GLSL_SAMPLER_DIM_MS, 0, 0, GLSL_TYPE_FLOAT) -DECL_TYPE(sampler2DMSArray, GL_SAMPLER_2D_MULTISAMPLE_ARRAY, GLSL_SAMPLER_DIM_MS, 0, 1, GLSL_TYPE_FLOAT) - -DECL_TYPE(isampler1D, GL_INT_SAMPLER_1D, GLSL_SAMPLER_DIM_1D, 0, 0, GLSL_TYPE_INT) -DECL_TYPE(isampler2D, GL_INT_SAMPLER_2D, GLSL_SAMPLER_DIM_2D, 0, 0, GLSL_TYPE_INT) -DECL_TYPE(isampler3D, GL_INT_SAMPLER_3D, GLSL_SAMPLER_DIM_3D, 0, 0, GLSL_TYPE_INT) -DECL_TYPE(isamplerCube, GL_INT_SAMPLER_CUBE, GLSL_SAMPLER_DIM_CUBE, 0, 0, GLSL_TYPE_INT) -DECL_TYPE(isampler1DArray, GL_INT_SAMPLER_1D_ARRAY, GLSL_SAMPLER_DIM_1D, 0, 1, GLSL_TYPE_INT) -DECL_TYPE(isampler2DArray, GL_INT_SAMPLER_2D_ARRAY, GLSL_SAMPLER_DIM_2D, 0, 1, GLSL_TYPE_INT) -DECL_TYPE(isamplerCubeArray, GL_INT_SAMPLER_CUBE_MAP_ARRAY, GLSL_SAMPLER_DIM_CUBE, 0, 1, GLSL_TYPE_INT) -DECL_TYPE(isampler2DRect, GL_INT_SAMPLER_2D_RECT, GLSL_SAMPLER_DIM_RECT, 0, 0, GLSL_TYPE_INT) -DECL_TYPE(isamplerBuffer, GL_INT_SAMPLER_BUFFER, GLSL_SAMPLER_DIM_BUF, 0, 0, GLSL_TYPE_INT) -DECL_TYPE(isampler2DMS, GL_INT_SAMPLER_2D_MULTISAMPLE, GLSL_SAMPLER_DIM_MS, 0, 0, GLSL_TYPE_INT) -DECL_TYPE(isampler2DMSArray, GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY, GLSL_SAMPLER_DIM_MS, 0, 1, GLSL_TYPE_INT) - -DECL_TYPE(usampler1D, GL_UNSIGNED_INT_SAMPLER_1D, GLSL_SAMPLER_DIM_1D, 0, 0, GLSL_TYPE_UINT) -DECL_TYPE(usampler2D, GL_UNSIGNED_INT_SAMPLER_2D, GLSL_SAMPLER_DIM_2D, 0, 0, GLSL_TYPE_UINT) -DECL_TYPE(usampler3D, GL_UNSIGNED_INT_SAMPLER_3D, GLSL_SAMPLER_DIM_3D, 0, 0, GLSL_TYPE_UINT) -DECL_TYPE(usamplerCube, GL_UNSIGNED_INT_SAMPLER_CUBE, GLSL_SAMPLER_DIM_CUBE, 0, 0, GLSL_TYPE_UINT) -DECL_TYPE(usampler1DArray, GL_UNSIGNED_INT_SAMPLER_1D_ARRAY, GLSL_SAMPLER_DIM_1D, 0, 1, GLSL_TYPE_UINT) -DECL_TYPE(usampler2DArray, GL_UNSIGNED_INT_SAMPLER_2D_ARRAY, GLSL_SAMPLER_DIM_2D, 0, 1, GLSL_TYPE_UINT) -DECL_TYPE(usamplerCubeArray, GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY, GLSL_SAMPLER_DIM_CUBE, 0, 1, GLSL_TYPE_UINT) -DECL_TYPE(usampler2DRect, GL_UNSIGNED_INT_SAMPLER_2D_RECT, GLSL_SAMPLER_DIM_RECT, 0, 0, GLSL_TYPE_UINT) -DECL_TYPE(usamplerBuffer, GL_UNSIGNED_INT_SAMPLER_BUFFER, GLSL_SAMPLER_DIM_BUF, 0, 0, GLSL_TYPE_UINT) -DECL_TYPE(usampler2DMS, GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE, GLSL_SAMPLER_DIM_MS, 0, 0, GLSL_TYPE_UINT) -DECL_TYPE(usampler2DMSArray, GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY, GLSL_SAMPLER_DIM_MS, 0, 1, GLSL_TYPE_UINT) - -DECL_TYPE(sampler1DShadow, GL_SAMPLER_1D_SHADOW, GLSL_SAMPLER_DIM_1D, 1, 0, GLSL_TYPE_FLOAT) -DECL_TYPE(sampler2DShadow, GL_SAMPLER_2D_SHADOW, GLSL_SAMPLER_DIM_2D, 1, 0, GLSL_TYPE_FLOAT) -DECL_TYPE(samplerCubeShadow, GL_SAMPLER_CUBE_SHADOW, GLSL_SAMPLER_DIM_CUBE, 1, 0, GLSL_TYPE_FLOAT) -DECL_TYPE(sampler1DArrayShadow, GL_SAMPLER_1D_ARRAY_SHADOW, GLSL_SAMPLER_DIM_1D, 1, 1, GLSL_TYPE_FLOAT) -DECL_TYPE(sampler2DArrayShadow, GL_SAMPLER_2D_ARRAY_SHADOW, GLSL_SAMPLER_DIM_2D, 1, 1, GLSL_TYPE_FLOAT) -DECL_TYPE(samplerCubeArrayShadow, GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW, GLSL_SAMPLER_DIM_CUBE, 1, 1, GLSL_TYPE_FLOAT) -DECL_TYPE(sampler2DRectShadow, GL_SAMPLER_2D_RECT_SHADOW, GLSL_SAMPLER_DIM_RECT, 1, 0, GLSL_TYPE_FLOAT) - -DECL_TYPE(samplerExternalOES, GL_SAMPLER_EXTERNAL_OES, GLSL_SAMPLER_DIM_EXTERNAL, 0, 0, GLSL_TYPE_FLOAT) +DECL_TYPE(sampler1D, GL_SAMPLER_1D, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_1D, 0, 0, GLSL_TYPE_FLOAT) +DECL_TYPE(sampler2D, GL_SAMPLER_2D, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_2D, 0, 0, GLSL_TYPE_FLOAT) +DECL_TYPE(sampler3D, GL_SAMPLER_3D, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_3D, 0, 0, GLSL_TYPE_FLOAT) +DECL_TYPE(samplerCube, GL_SAMPLER_CUBE, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_CUBE, 0, 0, GLSL_TYPE_FLOAT) +DECL_TYPE(sampler1DArray, GL_SAMPLER_1D_ARRAY, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_1D, 0, 1, GLSL_TYPE_FLOAT) +DECL_TYPE(sampler2DArray, GL_SAMPLER_2D_ARRAY, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_2D, 0, 1, GLSL_TYPE_FLOAT) +DECL_TYPE(samplerCubeArray, GL_SAMPLER_CUBE_MAP_ARRAY, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_CUBE, 0, 1, GLSL_TYPE_FLOAT) +DECL_TYPE(sampler2DRect, GL_SAMPLER_2D_RECT, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_RECT, 0, 0, GLSL_TYPE_FLOAT) +DECL_TYPE(samplerBuffer, GL_SAMPLER_BUFFER, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_BUF, 0, 0, GLSL_TYPE_FLOAT) +DECL_TYPE(sampler2DMS, GL_SAMPLER_2D_MULTISAMPLE, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_MS, 0, 0, GLSL_TYPE_FLOAT) +DECL_TYPE(sampler2DMSArray, GL_SAMPLER_2D_MULTISAMPLE_ARRAY, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_MS, 0, 1, GLSL_TYPE_FLOAT) + +DECL_TYPE(isampler1D, GL_INT_SAMPLER_1D, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_1D, 0, 0, GLSL_TYPE_INT) +DECL_TYPE(isampler2D, GL_INT_SAMPLER_2D, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_2D, 0, 0, GLSL_TYPE_INT) +DECL_TYPE(isampler3D, GL_INT_SAMPLER_3D, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_3D, 0, 0, GLSL_TYPE_INT) +DECL_TYPE(isamplerCube, GL_INT_SAMPLER_CUBE, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_CUBE, 0, 0, GLSL_TYPE_INT) +DECL_TYPE(isampler1DArray, GL_INT_SAMPLER_1D_ARRAY, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_1D, 0, 1, GLSL_TYPE_INT) +DECL_TYPE(isampler2DArray, GL_INT_SAMPLER_2D_ARRAY, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_2D, 0, 1, GLSL_TYPE_INT) +DECL_TYPE(isamplerCubeArray, GL_INT_SAMPLER_CUBE_MAP_ARRAY, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_CUBE, 0, 1, GLSL_TYPE_INT) +DECL_TYPE(isampler2DRect, GL_INT_SAMPLER_2D_RECT, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_RECT, 0, 0, GLSL_TYPE_INT) +DECL_TYPE(isamplerBuffer, GL_INT_SAMPLER_BUFFER, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_BUF, 0, 0, GLSL_TYPE_INT) +DECL_TYPE(isampler2DMS, GL_INT_SAMPLER_2D_MULTISAMPLE, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_MS, 0, 0, GLSL_TYPE_INT) +DECL_TYPE(isampler2DMSArray, GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_MS, 0, 1, GLSL_TYPE_INT) + +DECL_TYPE(usampler1D, GL_UNSIGNED_INT_SAMPLER_1D, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_1D, 0, 0, GLSL_TYPE_UINT) +DECL_TYPE(usampler2D, GL_UNSIGNED_INT_SAMPLER_2D, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_2D, 0, 0, GLSL_TYPE_UINT) +DECL_TYPE(usampler3D, GL_UNSIGNED_INT_SAMPLER_3D, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_3D, 0, 0, GLSL_TYPE_UINT) +DECL_TYPE(usamplerCube, GL_UNSIGNED_INT_SAMPLER_CUBE, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_CUBE, 0, 0, GLSL_TYPE_UINT) +DECL_TYPE(usampler1DArray, GL_UNSIGNED_INT_SAMPLER_1D_ARRAY, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_1D, 0, 1, GLSL_TYPE_UINT) +DECL_TYPE(usampler2DArray, GL_UNSIGNED_INT_SAMPLER_2D_ARRAY, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_2D, 0, 1, GLSL_TYPE_UINT) +DECL_TYPE(usamplerCubeArray, GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_CUBE, 0, 1, GLSL_TYPE_UINT) +DECL_TYPE(usampler2DRect, GL_UNSIGNED_INT_SAMPLER_2D_RECT, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_RECT, 0, 0, GLSL_TYPE_UINT) +DECL_TYPE(usamplerBuffer, GL_UNSIGNED_INT_SAMPLER_BUFFER, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_BUF, 0, 0, GLSL_TYPE_UINT) +DECL_TYPE(usampler2DMS, GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_MS, 0, 0, GLSL_TYPE_UINT) +DECL_TYPE(usampler2DMSArray, GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_MS, 0, 1, GLSL_TYPE_UINT) + +DECL_TYPE(sampler1DShadow, GL_SAMPLER_1D_SHADOW, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_1D, 1, 0, GLSL_TYPE_FLOAT) +DECL_TYPE(sampler2DShadow, GL_SAMPLER_2D_SHADOW, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_2D, 1, 0, GLSL_TYPE_FLOAT) +DECL_TYPE(samplerCubeShadow, GL_SAMPLER_CUBE_SHADOW, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_CUBE, 1, 0, GLSL_TYPE_FLOAT) +DECL_TYPE(sampler1DArrayShadow, GL_SAMPLER_1D_ARRAY_SHADOW, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_1D, 1, 1, GLSL_TYPE_FLOAT) +DECL_TYPE(sampler2DArrayShadow, GL_SAMPLER_2D_ARRAY_SHADOW, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_2D, 1, 1, GLSL_TYPE_FLOAT) +DECL_TYPE(samplerCubeArrayShadow, GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_CUBE, 1, 1, GLSL_TYPE_FLOAT) +DECL_TYPE(sampler2DRectShadow, GL_SAMPLER_2D_RECT_SHADOW, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_RECT, 1, 0, GLSL_TYPE_FLOAT) + +DECL_TYPE(samplerExternalOES, GL_SAMPLER_EXTERNAL_OES, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_EXTERNAL, 0, 0, GLSL_TYPE_FLOAT) + +DECL_TYPE(image1D, GL_IMAGE_1D, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_1D, 0, 0, GLSL_TYPE_FLOAT); +DECL_TYPE(image2D, GL_IMAGE_2D, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_2D, 0, 0, GLSL_TYPE_FLOAT); +DECL_TYPE(image3D, GL_IMAGE_3D, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_3D, 0, 0, GLSL_TYPE_FLOAT); +DECL_TYPE(image2DRect, GL_IMAGE_2D_RECT, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_RECT, 0, 0, GLSL_TYPE_FLOAT); +DECL_TYPE(imageCube, GL_IMAGE_CUBE, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_CUBE, 0, 0, GLSL_TYPE_FLOAT); +DECL_TYPE(imageBuffer, GL_IMAGE_BUFFER, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_BUF, 0, 0, GLSL_TYPE_FLOAT); +DECL_TYPE(image1DArray, GL_IMAGE_1D_ARRAY, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_1D, 0, 1, GLSL_TYPE_FLOAT); +DECL_TYPE(image2DArray, GL_IMAGE_2D_ARRAY, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_2D, 0, 1, GLSL_TYPE_FLOAT); +DECL_TYPE(imageCubeArray, GL_IMAGE_CUBE_MAP_ARRAY, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_CUBE, 0, 1, GLSL_TYPE_FLOAT); +DECL_TYPE(image2DMS, GL_IMAGE_2D_MULTISAMPLE, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_MS, 0, 0, GLSL_TYPE_FLOAT); +DECL_TYPE(image2DMSArray, GL_IMAGE_2D_MULTISAMPLE_ARRAY, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_MS, 0, 1, GLSL_TYPE_FLOAT); +DECL_TYPE(iimage1D, GL_INT_IMAGE_1D, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_1D, 0, 0, GLSL_TYPE_INT); +DECL_TYPE(iimage2D, GL_INT_IMAGE_2D, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_2D, 0, 0, GLSL_TYPE_INT); +DECL_TYPE(iimage3D, GL_INT_IMAGE_3D, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_3D, 0, 0, GLSL_TYPE_INT); +DECL_TYPE(iimage2DRect, GL_INT_IMAGE_2D_RECT, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_RECT, 0, 0, GLSL_TYPE_INT); +DECL_TYPE(iimageCube, GL_INT_IMAGE_CUBE, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_CUBE, 0, 0, GLSL_TYPE_INT); +DECL_TYPE(iimageBuffer, GL_INT_IMAGE_BUFFER, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_BUF, 0, 0, GLSL_TYPE_INT); +DECL_TYPE(iimage1DArray, GL_INT_IMAGE_1D_ARRAY, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_1D, 0, 1, GLSL_TYPE_INT); +DECL_TYPE(iimage2DArray, GL_INT_IMAGE_2D_ARRAY, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_2D, 0, 1, GLSL_TYPE_INT); +DECL_TYPE(iimageCubeArray, GL_INT_IMAGE_CUBE_MAP_ARRAY, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_CUBE, 0, 1, GLSL_TYPE_INT); +DECL_TYPE(iimage2DMS, GL_INT_IMAGE_2D_MULTISAMPLE, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_MS, 0, 0, GLSL_TYPE_INT); +DECL_TYPE(iimage2DMSArray, GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_MS, 0, 1, GLSL_TYPE_INT); +DECL_TYPE(uimage1D, GL_UNSIGNED_INT_IMAGE_1D, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_1D, 0, 0, GLSL_TYPE_UINT); +DECL_TYPE(uimage2D, GL_UNSIGNED_INT_IMAGE_2D, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_2D, 0, 0, GLSL_TYPE_UINT); +DECL_TYPE(uimage3D, GL_UNSIGNED_INT_IMAGE_3D, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_3D, 0, 0, GLSL_TYPE_UINT); +DECL_TYPE(uimage2DRect, GL_UNSIGNED_INT_IMAGE_2D_RECT, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_RECT, 0, 0, GLSL_TYPE_UINT); +DECL_TYPE(uimageCube, GL_UNSIGNED_INT_IMAGE_CUBE, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_CUBE, 0, 0, GLSL_TYPE_UINT); +DECL_TYPE(uimageBuffer, GL_UNSIGNED_INT_IMAGE_BUFFER, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_BUF, 0, 0, GLSL_TYPE_UINT); +DECL_TYPE(uimage1DArray, GL_UNSIGNED_INT_IMAGE_1D_ARRAY, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_1D, 0, 1, GLSL_TYPE_UINT); +DECL_TYPE(uimage2DArray, GL_UNSIGNED_INT_IMAGE_2D_ARRAY, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_2D, 0, 1, GLSL_TYPE_UINT); +DECL_TYPE(uimageCubeArray, GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_CUBE, 0, 1, GLSL_TYPE_UINT); +DECL_TYPE(uimage2DMS, GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_MS, 0, 0, GLSL_TYPE_UINT); +DECL_TYPE(uimage2DMSArray, GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_MS, 0, 1, GLSL_TYPE_UINT); DECL_TYPE(atomic_uint, GL_UNSIGNED_INT_ATOMIC_COUNTER, GLSL_TYPE_ATOMIC_UINT, 1, 1) diff --git a/mesalib/src/glsl/builtin_types.cpp b/mesalib/src/glsl/builtin_types.cpp index 92e386057..dd42ecb05 100644 --- a/mesalib/src/glsl/builtin_types.cpp +++ b/mesalib/src/glsl/builtin_types.cpp @@ -204,6 +204,40 @@ const static struct builtin_type_versions { T(struct_gl_DepthRangeParameters, 110, 100) + T(image1D, 420, 999) + T(image2D, 420, 999) + T(image3D, 420, 999) + T(image2DRect, 420, 999) + T(imageCube, 420, 999) + T(imageBuffer, 420, 999) + T(image1DArray, 420, 999) + T(image2DArray, 420, 999) + T(imageCubeArray, 420, 999) + T(image2DMS, 420, 999) + T(image2DMSArray, 420, 999) + T(iimage1D, 420, 999) + T(iimage2D, 420, 999) + T(iimage3D, 420, 999) + T(iimage2DRect, 420, 999) + T(iimageCube, 420, 999) + T(iimageBuffer, 420, 999) + T(iimage1DArray, 420, 999) + T(iimage2DArray, 420, 999) + T(iimageCubeArray, 420, 999) + T(iimage2DMS, 420, 999) + T(iimage2DMSArray, 420, 999) + T(uimage1D, 420, 999) + T(uimage2D, 420, 999) + T(uimage3D, 420, 999) + T(uimage2DRect, 420, 999) + T(uimageCube, 420, 999) + T(uimageBuffer, 420, 999) + T(uimage1DArray, 420, 999) + T(uimage2DArray, 420, 999) + T(uimageCubeArray, 420, 999) + T(uimage2DMS, 420, 999) + T(uimage2DMSArray, 420, 999) + T(atomic_uint, 420, 999) }; @@ -287,6 +321,42 @@ _mesa_glsl_initialize_types(struct _mesa_glsl_parse_state *state) add_type(symbols, glsl_type::sampler3D_type); } + if (state->ARB_shader_image_load_store_enable) { + add_type(symbols, glsl_type::image1D_type); + add_type(symbols, glsl_type::image2D_type); + add_type(symbols, glsl_type::image3D_type); + add_type(symbols, glsl_type::image2DRect_type); + add_type(symbols, glsl_type::imageCube_type); + add_type(symbols, glsl_type::imageBuffer_type); + add_type(symbols, glsl_type::image1DArray_type); + add_type(symbols, glsl_type::image2DArray_type); + add_type(symbols, glsl_type::imageCubeArray_type); + add_type(symbols, glsl_type::image2DMS_type); + add_type(symbols, glsl_type::image2DMSArray_type); + add_type(symbols, glsl_type::iimage1D_type); + add_type(symbols, glsl_type::iimage2D_type); + add_type(symbols, glsl_type::iimage3D_type); + add_type(symbols, glsl_type::iimage2DRect_type); + add_type(symbols, glsl_type::iimageCube_type); + add_type(symbols, glsl_type::iimageBuffer_type); + add_type(symbols, glsl_type::iimage1DArray_type); + add_type(symbols, glsl_type::iimage2DArray_type); + add_type(symbols, glsl_type::iimageCubeArray_type); + add_type(symbols, glsl_type::iimage2DMS_type); + add_type(symbols, glsl_type::iimage2DMSArray_type); + add_type(symbols, glsl_type::uimage1D_type); + add_type(symbols, glsl_type::uimage2D_type); + add_type(symbols, glsl_type::uimage3D_type); + add_type(symbols, glsl_type::uimage2DRect_type); + add_type(symbols, glsl_type::uimageCube_type); + add_type(symbols, glsl_type::uimageBuffer_type); + add_type(symbols, glsl_type::uimage1DArray_type); + add_type(symbols, glsl_type::uimage2DArray_type); + add_type(symbols, glsl_type::uimageCubeArray_type); + add_type(symbols, glsl_type::uimage2DMS_type); + add_type(symbols, glsl_type::uimage2DMSArray_type); + } + if (state->ARB_shader_atomic_counters_enable) { add_type(symbols, glsl_type::atomic_uint_type); } diff --git a/mesalib/src/glsl/builtin_variables.cpp b/mesalib/src/glsl/builtin_variables.cpp index cc423383d..4176ae6e6 100644 --- a/mesalib/src/glsl/builtin_variables.cpp +++ b/mesalib/src/glsl/builtin_variables.cpp @@ -711,6 +711,26 @@ builtin_variable_generator::generate_constants() * in ast_cs_input_layout::hir(). */ } + + if (state->is_version(420, 0) || + state->ARB_shader_image_load_store_enable) { + add_const("gl_MaxImageUnits", + state->Const.MaxImageUnits); + add_const("gl_MaxCombinedImageUnitsAndFragmentOutputs", + state->Const.MaxCombinedImageUnitsAndFragmentOutputs); + add_const("gl_MaxImageSamples", + state->Const.MaxImageSamples); + add_const("gl_MaxVertexImageUniforms", + state->Const.MaxVertexImageUniforms); + add_const("gl_MaxTessControlImageUniforms", 0); + add_const("gl_MaxTessEvaluationImageUniforms", 0); + add_const("gl_MaxGeometryImageUniforms", + state->Const.MaxGeometryImageUniforms); + add_const("gl_MaxFragmentImageUniforms", + state->Const.MaxFragmentImageUniforms); + add_const("gl_MaxCombinedImageUniforms", + state->Const.MaxCombinedImageUniforms); + } } @@ -834,6 +854,8 @@ builtin_variable_generator::generate_gs_special_vars() add_output(VARYING_SLOT_LAYER, int_t, "gl_Layer"); if (state->ARB_viewport_array_enable) add_output(VARYING_SLOT_VIEWPORT, int_t, "gl_ViewportIndex"); + if (state->ARB_gpu_shader5_enable) + add_system_value(SYSTEM_VALUE_INVOCATION_ID, int_t, "gl_InvocationID"); /* Although gl_PrimitiveID appears in tessellation control and tessellation * evaluation shaders, it has a different function there than it has in diff --git a/mesalib/src/glsl/glcpp/glcpp-parse.y b/mesalib/src/glsl/glcpp/glcpp-parse.y index eeafa4d39..f28d8531e 100644 --- a/mesalib/src/glsl/glcpp/glcpp-parse.y +++ b/mesalib/src/glsl/glcpp/glcpp-parse.y @@ -1770,11 +1770,27 @@ static void _check_for_reserved_macro_name (glcpp_parser_t *parser, YYLTYPE *loc, const char *identifier) { - /* According to the GLSL specification, macro names starting with "__" - * or "GL_" are reserved for future use. So, don't allow them. + /* Section 3.3 (Preprocessor) of the GLSL 1.30 spec (and later) and + * the GLSL ES spec (all versions) say: + * + * "All macro names containing two consecutive underscores ( __ ) + * are reserved for future use as predefined macro names. All + * macro names prefixed with "GL_" ("GL" followed by a single + * underscore) are also reserved." + * + * The intention is that names containing __ are reserved for internal + * use by the implementation, and names prefixed with GL_ are reserved + * for use by Khronos. Since every extension adds a name prefixed + * with GL_ (i.e., the name of the extension), that should be an + * error. Names simply containing __ are dangerous to use, but should + * be allowed. + * + * A future version of the GLSL specification will clarify this. */ if (strstr(identifier, "__")) { - glcpp_error (loc, parser, "Macro names containing \"__\" are reserved.\n"); + glcpp_warning(loc, parser, + "Macro names containing \"__\" are reserved " + "for use by the implementation.\n"); } if (strncmp(identifier, "GL_", 3) == 0) { glcpp_error (loc, parser, "Macro names starting with \"GL_\" are reserved.\n"); @@ -2118,6 +2134,9 @@ _glcpp_parser_handle_version_declaration(glcpp_parser_t *parser, intmax_t versio if (extensions->ARB_texture_gather) add_builtin_define(parser, "GL_ARB_texture_gather", 1); + if (extensions->ARB_separate_shader_objects) + add_builtin_define(parser, "GL_ARB_separate_shader_objects", 1); + if (extensions->ARB_shader_atomic_counters) add_builtin_define(parser, "GL_ARB_shader_atomic_counters", 1); @@ -2126,6 +2145,9 @@ _glcpp_parser_handle_version_declaration(glcpp_parser_t *parser, intmax_t versio if (extensions->ARB_compute_shader) add_builtin_define(parser, "GL_ARB_compute_shader", 1); + + if (extensions->ARB_shader_image_load_store) + add_builtin_define(parser, "GL_ARB_shader_image_load_store", 1); } } diff --git a/mesalib/src/glsl/glsl_lexer.ll b/mesalib/src/glsl/glsl_lexer.ll index 3208b32da..9fd9b80d3 100644 --- a/mesalib/src/glsl/glsl_lexer.ll +++ b/mesalib/src/glsl/glsl_lexer.ll @@ -337,6 +337,51 @@ samplerExternalOES { return IDENTIFIER; } + /* keywords available with ARB_shader_image_load_store */ +image1D KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IMAGE1D); +image2D KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IMAGE2D); +image3D KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IMAGE3D); +image2DRect KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IMAGE2DRECT); +imageCube KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IMAGECUBE); +imageBuffer KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IMAGEBUFFER); +image1DArray KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IMAGE1DARRAY); +image2DArray KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IMAGE2DARRAY); +imageCubeArray KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IMAGECUBEARRAY); +image2DMS KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IMAGE2DMS); +image2DMSArray KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IMAGE2DMSARRAY); +iimage1D KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IIMAGE1D); +iimage2D KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IIMAGE2D); +iimage3D KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IIMAGE3D); +iimage2DRect KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IIMAGE2DRECT); +iimageCube KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IIMAGECUBE); +iimageBuffer KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IIMAGEBUFFER); +iimage1DArray KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IIMAGE1DARRAY); +iimage2DArray KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IIMAGE2DARRAY); +iimageCubeArray KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IIMAGECUBEARRAY); +iimage2DMS KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IIMAGE2DMS); +iimage2DMSArray KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IIMAGE2DMSARRAY); +uimage1D KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, UIMAGE1D); +uimage2D KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, UIMAGE2D); +uimage3D KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, UIMAGE3D); +uimage2DRect KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, UIMAGE2DRECT); +uimageCube KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, UIMAGECUBE); +uimageBuffer KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, UIMAGEBUFFER); +uimage1DArray KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, UIMAGE1DARRAY); +uimage2DArray KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, UIMAGE2DARRAY); +uimageCubeArray KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, UIMAGECUBEARRAY); +uimage2DMS KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, UIMAGE2DMS); +uimage2DMSArray KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, UIMAGE2DMSARRAY); +image1DShadow KEYWORD(130, 300, 0, 0, IMAGE1DSHADOW); +image2DShadow KEYWORD(130, 300, 0, 0, IMAGE2DSHADOW); +image1DArrayShadow KEYWORD(130, 300, 0, 0, IMAGE1DARRAYSHADOW); +image2DArrayShadow KEYWORD(130, 300, 0, 0, IMAGE2DARRAYSHADOW); + +coherent KEYWORD_WITH_ALT(420, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, COHERENT); +volatile KEYWORD_WITH_ALT(110, 100, 420, 0, yyextra->ARB_shader_image_load_store_enable, VOLATILE); +restrict KEYWORD_WITH_ALT(420, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, RESTRICT); +readonly KEYWORD_WITH_ALT(420, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, READONLY); +writeonly KEYWORD_WITH_ALT(420, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, WRITEONLY); + atomic_uint KEYWORD_WITH_ALT(420, 300, 420, 0, yyextra->ARB_shader_atomic_counters_enable, ATOMIC_UINT); struct return STRUCT; @@ -347,6 +392,7 @@ layout { || yyextra->AMD_conservative_depth_enable || yyextra->ARB_conservative_depth_enable || yyextra->ARB_explicit_attrib_location_enable + || yyextra->has_separate_shader_objects() || yyextra->ARB_uniform_buffer_object_enable || yyextra->ARB_fragment_coord_conventions_enable || yyextra->ARB_shading_language_420pack_enable @@ -436,7 +482,6 @@ switch KEYWORD(110, 100, 130, 300, SWITCH); default KEYWORD(110, 100, 130, 300, DEFAULT); inline KEYWORD(110, 100, 0, 0, INLINE_TOK); noinline KEYWORD(110, 100, 0, 0, NOINLINE); -volatile KEYWORD(110, 100, 0, 0, VOLATILE); public KEYWORD(110, 100, 0, 0, PUBLIC_TOK); static KEYWORD(110, 100, 0, 0, STATIC); extern KEYWORD(110, 100, 0, 0, EXTERN); @@ -481,31 +526,6 @@ active KEYWORD(130, 300, 0, 0, ACTIVE); superp KEYWORD(130, 100, 0, 0, SUPERP); samplerBuffer KEYWORD(130, 300, 140, 0, SAMPLERBUFFER); filter KEYWORD(130, 300, 0, 0, FILTER); -image1D KEYWORD(130, 300, 0, 0, IMAGE1D); -image2D KEYWORD(130, 300, 0, 0, IMAGE2D); -image3D KEYWORD(130, 300, 0, 0, IMAGE3D); -imageCube KEYWORD(130, 300, 0, 0, IMAGECUBE); -iimage1D KEYWORD(130, 300, 0, 0, IIMAGE1D); -iimage2D KEYWORD(130, 300, 0, 0, IIMAGE2D); -iimage3D KEYWORD(130, 300, 0, 0, IIMAGE3D); -iimageCube KEYWORD(130, 300, 0, 0, IIMAGECUBE); -uimage1D KEYWORD(130, 300, 0, 0, UIMAGE1D); -uimage2D KEYWORD(130, 300, 0, 0, UIMAGE2D); -uimage3D KEYWORD(130, 300, 0, 0, UIMAGE3D); -uimageCube KEYWORD(130, 300, 0, 0, UIMAGECUBE); -image1DArray KEYWORD(130, 300, 0, 0, IMAGE1DARRAY); -image2DArray KEYWORD(130, 300, 0, 0, IMAGE2DARRAY); -iimage1DArray KEYWORD(130, 300, 0, 0, IIMAGE1DARRAY); -iimage2DArray KEYWORD(130, 300, 0, 0, IIMAGE2DARRAY); -uimage1DArray KEYWORD(130, 300, 0, 0, UIMAGE1DARRAY); -uimage2DArray KEYWORD(130, 300, 0, 0, UIMAGE2DARRAY); -image1DShadow KEYWORD(130, 300, 0, 0, IMAGE1DSHADOW); -image2DShadow KEYWORD(130, 300, 0, 0, IMAGE2DSHADOW); -image1DArrayShadow KEYWORD(130, 300, 0, 0, IMAGE1DARRAYSHADOW); -image2DArrayShadow KEYWORD(130, 300, 0, 0, IMAGE2DARRAYSHADOW); -imageBuffer KEYWORD(130, 300, 0, 0, IMAGEBUFFER); -iimageBuffer KEYWORD(130, 300, 0, 0, IIMAGEBUFFER); -uimageBuffer KEYWORD(130, 300, 0, 0, UIMAGEBUFFER); row_major KEYWORD_WITH_ALT(130, 0, 140, 0, yyextra->ARB_uniform_buffer_object_enable && !yyextra->es_shader, ROW_MAJOR); /* Additional reserved words in GLSL 1.40 */ @@ -515,10 +535,6 @@ isamplerBuffer KEYWORD(140, 300, 140, 0, ISAMPLERBUFFER); usamplerBuffer KEYWORD(140, 300, 140, 0, USAMPLERBUFFER); /* Additional reserved words in GLSL ES 3.00 */ -coherent KEYWORD(0, 300, 0, 0, COHERENT); -restrict KEYWORD(0, 300, 0, 0, RESTRICT); -readonly KEYWORD(0, 300, 0, 0, READONLY); -writeonly KEYWORD(0, 300, 0, 0, WRITEONLY); resource KEYWORD(0, 300, 0, 0, RESOURCE); patch KEYWORD(0, 300, 0, 0, PATCH); sample KEYWORD_WITH_ALT(400, 300, 400, 0, yyextra->ARB_gpu_shader5_enable, SAMPLE); diff --git a/mesalib/src/glsl/glsl_parser.yy b/mesalib/src/glsl/glsl_parser.yy index dc35c1a51..1df572254 100644 --- a/mesalib/src/glsl/glsl_parser.yy +++ b/mesalib/src/glsl/glsl_parser.yy @@ -145,6 +145,14 @@ static bool match_layout_qualifier(const char *s1, const char *s2, %token SAMPLER2DMS ISAMPLER2DMS USAMPLER2DMS %token SAMPLER2DMSARRAY ISAMPLER2DMSARRAY USAMPLER2DMSARRAY %token SAMPLEREXTERNALOES +%token IMAGE1D IMAGE2D IMAGE3D IMAGE2DRECT IMAGECUBE IMAGEBUFFER +%token IMAGE1DARRAY IMAGE2DARRAY IMAGECUBEARRAY IMAGE2DMS IMAGE2DMSARRAY +%token IIMAGE1D IIMAGE2D IIMAGE3D IIMAGE2DRECT IIMAGECUBE IIMAGEBUFFER +%token IIMAGE1DARRAY IIMAGE2DARRAY IIMAGECUBEARRAY IIMAGE2DMS IIMAGE2DMSARRAY +%token UIMAGE1D UIMAGE2D UIMAGE3D UIMAGE2DRECT UIMAGECUBE UIMAGEBUFFER +%token UIMAGE1DARRAY UIMAGE2DARRAY UIMAGECUBEARRAY UIMAGE2DMS UIMAGE2DMSARRAY +%token IMAGE1DSHADOW IMAGE2DSHADOW IMAGE1DARRAYSHADOW IMAGE2DARRAYSHADOW +%token COHERENT VOLATILE RESTRICT READONLY WRITEONLY %token ATOMIC_UINT %token STRUCT VOID_TOK WHILE %token <identifier> IDENTIFIER TYPE_IDENTIFIER NEW_IDENTIFIER @@ -170,23 +178,17 @@ static bool match_layout_qualifier(const char *s1, const char *s2, /* Reserved words that are not actually used in the grammar. */ %token ASM CLASS UNION ENUM TYPEDEF TEMPLATE THIS PACKED_TOK GOTO -%token INLINE_TOK NOINLINE VOLATILE PUBLIC_TOK STATIC EXTERN EXTERNAL +%token INLINE_TOK NOINLINE PUBLIC_TOK STATIC EXTERN EXTERNAL %token LONG_TOK SHORT_TOK DOUBLE_TOK HALF FIXED_TOK UNSIGNED INPUT_TOK OUPTUT %token HVEC2 HVEC3 HVEC4 DVEC2 DVEC3 DVEC4 FVEC2 FVEC3 FVEC4 %token SAMPLER3DRECT %token SIZEOF CAST NAMESPACE USING -%token COHERENT RESTRICT READONLY WRITEONLY RESOURCE PATCH SAMPLE +%token RESOURCE PATCH SAMPLE %token SUBROUTINE %token ERROR_TOK -%token COMMON PARTITION ACTIVE FILTER -%token IMAGE1D IMAGE2D IMAGE3D IMAGECUBE IMAGE1DARRAY IMAGE2DARRAY -%token IIMAGE1D IIMAGE2D IIMAGE3D IIMAGECUBE IIMAGE1DARRAY IIMAGE2DARRAY -%token UIMAGE1D UIMAGE2D UIMAGE3D UIMAGECUBE UIMAGE1DARRAY UIMAGE2DARRAY -%token IMAGE1DSHADOW IMAGE2DSHADOW IMAGEBUFFER IIMAGEBUFFER UIMAGEBUFFER -%token IMAGE1DARRAYSHADOW IMAGE2DARRAYSHADOW -%token ROW_MAJOR +%token COMMON PARTITION ACTIVE FILTER ROW_MAJOR %type <identifier> variable_identifier %type <node> statement @@ -1229,6 +1231,72 @@ layout_qualifier_id: } } + /* Layout qualifiers for ARB_shader_image_load_store. */ + if (state->ARB_shader_image_load_store_enable || + state->is_version(420, 0)) { + if (!$$.flags.i) { + static const struct { + const char *name; + GLenum format; + glsl_base_type base_type; + } map[] = { + { "rgba32f", GL_RGBA32F, GLSL_TYPE_FLOAT }, + { "rgba16f", GL_RGBA16F, GLSL_TYPE_FLOAT }, + { "rg32f", GL_RG32F, GLSL_TYPE_FLOAT }, + { "rg16f", GL_RG16F, GLSL_TYPE_FLOAT }, + { "r11f_g11f_b10f", GL_R11F_G11F_B10F, GLSL_TYPE_FLOAT }, + { "r32f", GL_R32F, GLSL_TYPE_FLOAT }, + { "r16f", GL_R16F, GLSL_TYPE_FLOAT }, + { "rgba32ui", GL_RGBA32UI, GLSL_TYPE_UINT }, + { "rgba16ui", GL_RGBA16UI, GLSL_TYPE_UINT }, + { "rgb10_a2ui", GL_RGB10_A2UI, GLSL_TYPE_UINT }, + { "rgba8ui", GL_RGBA8UI, GLSL_TYPE_UINT }, + { "rg32ui", GL_RG32UI, GLSL_TYPE_UINT }, + { "rg16ui", GL_RG16UI, GLSL_TYPE_UINT }, + { "rg8ui", GL_RG8UI, GLSL_TYPE_UINT }, + { "r32ui", GL_R32UI, GLSL_TYPE_UINT }, + { "r16ui", GL_R16UI, GLSL_TYPE_UINT }, + { "r8ui", GL_R8UI, GLSL_TYPE_UINT }, + { "rgba32i", GL_RGBA32I, GLSL_TYPE_INT }, + { "rgba16i", GL_RGBA16I, GLSL_TYPE_INT }, + { "rgba8i", GL_RGBA8I, GLSL_TYPE_INT }, + { "rg32i", GL_RG32I, GLSL_TYPE_INT }, + { "rg16i", GL_RG16I, GLSL_TYPE_INT }, + { "rg8i", GL_RG8I, GLSL_TYPE_INT }, + { "r32i", GL_R32I, GLSL_TYPE_INT }, + { "r16i", GL_R16I, GLSL_TYPE_INT }, + { "r8i", GL_R8I, GLSL_TYPE_INT }, + { "rgba16", GL_RGBA16, GLSL_TYPE_FLOAT }, + { "rgb10_a2", GL_RGB10_A2, GLSL_TYPE_FLOAT }, + { "rgba8", GL_RGBA8, GLSL_TYPE_FLOAT }, + { "rg16", GL_RG16, GLSL_TYPE_FLOAT }, + { "rg8", GL_RG8, GLSL_TYPE_FLOAT }, + { "r16", GL_R16, GLSL_TYPE_FLOAT }, + { "r8", GL_R8, GLSL_TYPE_FLOAT }, + { "rgba16_snorm", GL_RGBA16_SNORM, GLSL_TYPE_FLOAT }, + { "rgba8_snorm", GL_RGBA8_SNORM, GLSL_TYPE_FLOAT }, + { "rg16_snorm", GL_RG16_SNORM, GLSL_TYPE_FLOAT }, + { "rg8_snorm", GL_RG8_SNORM, GLSL_TYPE_FLOAT }, + { "r16_snorm", GL_R16_SNORM, GLSL_TYPE_FLOAT }, + { "r8_snorm", GL_R8_SNORM, GLSL_TYPE_FLOAT } + }; + + for (unsigned i = 0; i < Elements(map); i++) { + if (match_layout_qualifier($1, map[i].name, state) == 0) { + $$.flags.q.explicit_image_format = 1; + $$.image_format = map[i].format; + $$.image_base_type = map[i].base_type; + break; + } + } + } + + if (!$$.flags.i && + match_layout_qualifier($1, "early_fragment_tests", state) == 0) { + $$.flags.q.early_fragment_tests = 1; + } + } + if (!$$.flags.i) { _mesa_glsl_error(& @1, state, "unrecognized layout identifier " "`%s'", $1); @@ -1319,6 +1387,29 @@ layout_qualifier_id: } } + if (match_layout_qualifier("invocations", $1, state) == 0) { + $$.flags.q.invocations = 1; + + if ($3 <= 0) { + _mesa_glsl_error(& @3, state, + "invalid invocations %d specified", $3); + YYERROR; + } else if ($3 > MAX_GEOMETRY_SHADER_INVOCATIONS) { + _mesa_glsl_error(& @3, state, + "invocations (%d) exceeds " + "GL_MAX_GEOMETRY_SHADER_INVOCATIONS", $3); + YYERROR; + } else { + $$.invocations = $3; + if (!state->is_version(400, 0) && + !state->ARB_gpu_shader5_enable) { + _mesa_glsl_error(& @3, state, + "GL_ARB_gpu_shader5 invocations " + "qualifier specified", $3); + } + } + } + /* If the identifier didn't match any known layout identifiers, * emit an error. */ @@ -1573,6 +1664,32 @@ storage_qualifier: memset(& $$, 0, sizeof($$)); $$.flags.q.uniform = 1; } + | COHERENT + { + memset(& $$, 0, sizeof($$)); + $$.flags.q.coherent = 1; + } + | VOLATILE + { + memset(& $$, 0, sizeof($$)); + $$.flags.q._volatile = 1; + } + | RESTRICT + { + STATIC_ASSERT(sizeof($$.flags.q) <= sizeof($$.flags.i)); + memset(& $$, 0, sizeof($$)); + $$.flags.q.restrict_flag = 1; + } + | READONLY + { + memset(& $$, 0, sizeof($$)); + $$.flags.q.read_only = 1; + } + | WRITEONLY + { + memset(& $$, 0, sizeof($$)); + $$.flags.q.write_only = 1; + } ; array_specifier: @@ -1712,6 +1829,39 @@ basic_type_specifier_nonarray: | SAMPLER2DMSARRAY { $$ = "sampler2DMSArray"; } | ISAMPLER2DMSARRAY { $$ = "isampler2DMSArray"; } | USAMPLER2DMSARRAY { $$ = "usampler2DMSArray"; } + | IMAGE1D { $$ = "image1D"; } + | IMAGE2D { $$ = "image2D"; } + | IMAGE3D { $$ = "image3D"; } + | IMAGE2DRECT { $$ = "image2DRect"; } + | IMAGECUBE { $$ = "imageCube"; } + | IMAGEBUFFER { $$ = "imageBuffer"; } + | IMAGE1DARRAY { $$ = "image1DArray"; } + | IMAGE2DARRAY { $$ = "image2DArray"; } + | IMAGECUBEARRAY { $$ = "imageCubeArray"; } + | IMAGE2DMS { $$ = "image2DMS"; } + | IMAGE2DMSARRAY { $$ = "image2DMSArray"; } + | IIMAGE1D { $$ = "iimage1D"; } + | IIMAGE2D { $$ = "iimage2D"; } + | IIMAGE3D { $$ = "iimage3D"; } + | IIMAGE2DRECT { $$ = "iimage2DRect"; } + | IIMAGECUBE { $$ = "iimageCube"; } + | IIMAGEBUFFER { $$ = "iimageBuffer"; } + | IIMAGE1DARRAY { $$ = "iimage1DArray"; } + | IIMAGE2DARRAY { $$ = "iimage2DArray"; } + | IIMAGECUBEARRAY { $$ = "iimageCubeArray"; } + | IIMAGE2DMS { $$ = "iimage2DMS"; } + | IIMAGE2DMSARRAY { $$ = "iimage2DMSArray"; } + | UIMAGE1D { $$ = "uimage1D"; } + | UIMAGE2D { $$ = "uimage2D"; } + | UIMAGE3D { $$ = "uimage3D"; } + | UIMAGE2DRECT { $$ = "uimage2DRect"; } + | UIMAGECUBE { $$ = "uimageCube"; } + | UIMAGEBUFFER { $$ = "uimageBuffer"; } + | UIMAGE1DARRAY { $$ = "uimage1DArray"; } + | UIMAGE2DARRAY { $$ = "uimage2DArray"; } + | UIMAGECUBEARRAY { $$ = "uimageCubeArray"; } + | UIMAGE2DMS { $$ = "uimage2DMS"; } + | UIMAGE2DMSARRAY { $$ = "uimage2DMSArray"; } | ATOMIC_UINT { $$ = "atomic_uint"; } ; @@ -2228,7 +2378,7 @@ basic_interface_block: "an instance name are not allowed"); } - unsigned interface_type_mask; + uint64_t interface_type_mask; struct ast_type_qualifier temp_type_qualifier; /* Get a bitmask containing only the in/out/uniform flags, allowing us @@ -2244,7 +2394,7 @@ basic_interface_block: * production rule guarantees that only one bit will be set (and * it will be in/out/uniform). */ - unsigned block_interface_qualifier = $1.flags.i; + uint64_t block_interface_qualifier = $1.flags.i; block->layout.flags.i |= block_interface_qualifier; @@ -2360,55 +2510,9 @@ layout_defaults: | layout_qualifier IN_TOK ';' { - void *ctx = state; $$ = NULL; - switch (state->stage) { - case MESA_SHADER_GEOMETRY: { - if (!$1.flags.q.prim_type) { - _mesa_glsl_error(& @1, state, - "input layout qualifiers must specify a primitive" - " type"); - } else { - /* Make sure this is a valid input primitive type. */ - switch ($1.prim_type) { - case GL_POINTS: - case GL_LINES: - case GL_LINES_ADJACENCY: - case GL_TRIANGLES: - case GL_TRIANGLES_ADJACENCY: - $$ = new(ctx) ast_gs_input_layout(@1, $1.prim_type); - break; - default: - _mesa_glsl_error(&@1, state, - "invalid geometry shader input primitive type"); - break; - } - } - } - break; - case MESA_SHADER_COMPUTE: { - if ($1.flags.q.local_size == 0) { - _mesa_glsl_error(& @1, state, - "input layout qualifiers must specify a local " - "size"); - } else { - /* Infer a local_size of 1 for every unspecified dimension */ - unsigned local_size[3]; - for (int i = 0; i < 3; i++) { - if ($1.flags.q.local_size & (1 << i)) - local_size[i] = $1.local_size[i]; - else - local_size[i] = 1; - } - $$ = new(ctx) ast_cs_input_layout(@1, local_size); - } - } - break; - default: - _mesa_glsl_error(& @1, state, - "input layout qualifiers only valid in " - "geometry and compute shaders"); - break; + if (!state->in_qualifier->merge_in_qualifier(& @1, state, $1, $$)) { + YYERROR; } } diff --git a/mesalib/src/glsl/glsl_parser_extras.cpp b/mesalib/src/glsl/glsl_parser_extras.cpp index b822d2292..d7f5202fe 100644 --- a/mesalib/src/glsl/glsl_parser_extras.cpp +++ b/mesalib/src/glsl/glsl_parser_extras.cpp @@ -130,6 +130,14 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx, for (unsigned i = 0; i < Elements(this->Const.MaxComputeWorkGroupSize); i++) this->Const.MaxComputeWorkGroupSize[i] = ctx->Const.MaxComputeWorkGroupSize[i]; + this->Const.MaxImageUnits = ctx->Const.MaxImageUnits; + this->Const.MaxCombinedImageUnitsAndFragmentOutputs = ctx->Const.MaxCombinedImageUnitsAndFragmentOutputs; + this->Const.MaxImageSamples = ctx->Const.MaxImageSamples; + this->Const.MaxVertexImageUniforms = ctx->Const.Program[MESA_SHADER_VERTEX].MaxImageUniforms; + this->Const.MaxGeometryImageUniforms = ctx->Const.Program[MESA_SHADER_GEOMETRY].MaxImageUniforms; + this->Const.MaxFragmentImageUniforms = ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxImageUniforms; + this->Const.MaxCombinedImageUniforms = ctx->Const.MaxCombinedImageUniforms; + this->current_function = NULL; this->toplevel_ir = NULL; this->found_return = false; @@ -194,9 +202,10 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx, this->default_uniform_qualifier->flags.q.column_major = 1; this->gs_input_prim_type_specified = false; - this->gs_input_prim_type = GL_POINTS; this->gs_input_size = 0; + this->in_qualifier = new(this) ast_type_qualifier(); this->out_qualifier = new(this) ast_type_qualifier(); + this->early_fragment_tests = false; memset(this->atomic_counter_offsets, 0, sizeof(this->atomic_counter_offsets)); } @@ -503,6 +512,7 @@ static const _mesa_glsl_extension _mesa_glsl_supported_extensions[] = { EXT(ARB_fragment_coord_conventions, true, false, ARB_fragment_coord_conventions), EXT(ARB_texture_rectangle, true, false, dummy_true), EXT(EXT_texture_array, true, false, EXT_texture_array), + EXT(ARB_separate_shader_objects, true, false, ARB_separate_shader_objects), EXT(ARB_shader_texture_lod, true, false, ARB_shader_texture_lod), EXT(ARB_shader_stencil_export, true, false, ARB_shader_stencil_export), EXT(AMD_conservative_depth, true, false, ARB_conservative_depth), @@ -527,6 +537,7 @@ static const _mesa_glsl_extension _mesa_glsl_supported_extensions[] = { EXT(AMD_shader_trinary_minmax, true, false, dummy_true), EXT(ARB_viewport_array, true, false, ARB_viewport_array), EXT(ARB_compute_shader, true, false, ARB_compute_shader), + EXT(ARB_shader_image_load_store, true, false, ARB_shader_image_load_store), }; #undef EXT @@ -1338,7 +1349,7 @@ set_shader_inout_layout(struct gl_shader *shader, { if (shader->Stage != MESA_SHADER_GEOMETRY) { /* Should have been prevented by the parser. */ - assert(!state->gs_input_prim_type_specified); + assert(!state->in_qualifier->flags.i); assert(!state->out_qualifier->flags.i); } @@ -1354,7 +1365,7 @@ set_shader_inout_layout(struct gl_shader *shader, shader->Geom.VerticesOut = state->out_qualifier->max_vertices; if (state->gs_input_prim_type_specified) { - shader->Geom.InputType = state->gs_input_prim_type; + shader->Geom.InputType = state->in_qualifier->prim_type; } else { shader->Geom.InputType = PRIM_UNKNOWN; } @@ -1364,6 +1375,10 @@ set_shader_inout_layout(struct gl_shader *shader, } else { shader->Geom.OutputType = PRIM_UNKNOWN; } + + shader->Geom.Invocations = 0; + if (state->in_qualifier->flags.q.invocations) + shader->Geom.Invocations = state->in_qualifier->invocations; break; case MESA_SHADER_COMPUTE: @@ -1419,7 +1434,7 @@ _mesa_glsl_compile_shader(struct gl_context *ctx, struct gl_shader *shader, /* Print out the unoptimized IR. */ if (dump_hir) { - _mesa_print_ir(shader->ir, state); + _mesa_print_ir(stdout, shader->ir, state); } } diff --git a/mesalib/src/glsl/glsl_parser_extras.h b/mesalib/src/glsl/glsl_parser_extras.h index 7d661473d..300d90051 100644 --- a/mesalib/src/glsl/glsl_parser_extras.h +++ b/mesalib/src/glsl/glsl_parser_extras.h @@ -135,6 +135,23 @@ struct _mesa_glsl_parse_state { return true; } + bool check_separate_shader_objects_allowed(YYLTYPE *locp, + const ir_variable *var) + { + if (!this->has_separate_shader_objects()) { + const char *const requirement = this->es_shader + ? "GL_EXT_separate_shader_objects (not supported by this " + "implementation)" + : "GL_ARB_separate_shader_objects extension or GLSL 420"; + + _mesa_glsl_error(locp, this, "%s explicit location requires %s", + mode_string(var), requirement); + return false; + } + + return true; + } + bool has_explicit_attrib_location() const { return ARB_explicit_attrib_location_enable || is_version(330, 300); @@ -145,6 +162,11 @@ struct _mesa_glsl_parse_state { return ARB_uniform_buffer_object_enable || is_version(140, 300); } + bool has_separate_shader_objects() const + { + return ARB_separate_shader_objects_enable || is_version(410, 0); + } + void process_version_directive(YYLTYPE *locp, int version, const char *ident); @@ -190,11 +212,8 @@ struct _mesa_glsl_parse_state { */ bool gs_input_prim_type_specified; - /** - * If gs_input_prim_type_specified is true, the primitive type that was - * specified. Otherwise ignored. - */ - GLenum gs_input_prim_type; + /** Input layout qualifiers from GLSL 1.50. (geometry shader controls)*/ + struct ast_type_qualifier *in_qualifier; /** * True if a compute shader input local size was specified using a layout @@ -269,6 +288,15 @@ struct _mesa_glsl_parse_state { /* ARB_compute_shader */ unsigned MaxComputeWorkGroupCount[3]; unsigned MaxComputeWorkGroupSize[3]; + + /* ARB_shader_image_load_store */ + unsigned MaxImageUnits; + unsigned MaxCombinedImageUnitsAndFragmentOutputs; + unsigned MaxImageSamples; + unsigned MaxVertexImageUniforms; + unsigned MaxGeometryImageUniforms; + unsigned MaxFragmentImageUniforms; + unsigned MaxCombinedImageUniforms; } Const; /** @@ -329,6 +357,8 @@ struct _mesa_glsl_parse_state { bool ARB_texture_gather_warn; bool EXT_texture_array_enable; bool EXT_texture_array_warn; + bool ARB_separate_shader_objects_enable; + bool ARB_separate_shader_objects_warn; bool ARB_shader_texture_lod_enable; bool ARB_shader_texture_lod_warn; bool ARB_shader_stencil_export_enable; @@ -377,6 +407,8 @@ struct _mesa_glsl_parse_state { bool ARB_viewport_array_warn; bool ARB_compute_shader_enable; bool ARB_compute_shader_warn; + bool ARB_shader_image_load_store_enable; + bool ARB_shader_image_load_store_warn; /*@}*/ /** Extensions supported by the OpenGL implementation. */ @@ -393,6 +425,8 @@ struct _mesa_glsl_parse_state { */ unsigned gs_input_size; + bool early_fragment_tests; + /** Atomic counter offsets by binding */ unsigned atomic_counter_offsets[MAX_COMBINED_ATOMIC_BUFFERS]; }; diff --git a/mesalib/src/glsl/glsl_types.cpp b/mesalib/src/glsl/glsl_types.cpp index 1b0b3ef88..849a79af4 100644 --- a/mesalib/src/glsl/glsl_types.cpp +++ b/mesalib/src/glsl/glsl_types.cpp @@ -64,20 +64,26 @@ glsl_type::glsl_type(GLenum gl_type, memset(& fields, 0, sizeof(fields)); } -glsl_type::glsl_type(GLenum gl_type, +glsl_type::glsl_type(GLenum gl_type, glsl_base_type base_type, enum glsl_sampler_dim dim, bool shadow, bool array, unsigned type, const char *name) : gl_type(gl_type), - base_type(GLSL_TYPE_SAMPLER), + base_type(base_type), sampler_dimensionality(dim), sampler_shadow(shadow), sampler_array(array), sampler_type(type), interface_packing(0), - vector_elements(0), matrix_columns(0), length(0) { init_ralloc_type_ctx(); assert(name != NULL); this->name = ralloc_strdup(this->mem_ctx, name); memset(& fields, 0, sizeof(fields)); + + if (base_type == GLSL_TYPE_SAMPLER) { + /* Samplers take no storage whatsoever. */ + matrix_columns = vector_elements = 0; + } else { + matrix_columns = vector_elements = 1; + } } glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields, @@ -174,6 +180,7 @@ bool glsl_type::contains_opaque() const { switch (base_type) { case GLSL_TYPE_SAMPLER: + case GLSL_TYPE_IMAGE: case GLSL_TYPE_ATOMIC_UINT: return true; case GLSL_TYPE_ARRAY: @@ -219,6 +226,21 @@ glsl_type::sampler_index() const } } +bool +glsl_type::contains_image() const +{ + if (this->is_array()) { + return this->fields.array->contains_image(); + } else if (this->is_record()) { + for (unsigned int i = 0; i < this->length; i++) { + if (this->fields.structure[i].type->contains_image()) + return true; + } + return false; + } else { + return this->is_image(); + } +} const glsl_type *glsl_type::get_base_type() const { @@ -642,6 +664,9 @@ glsl_type::component_slots() const case GLSL_TYPE_ARRAY: return this->length * this->fields.array->component_slots(); + case GLSL_TYPE_IMAGE: + return 1; + case GLSL_TYPE_SAMPLER: case GLSL_TYPE_ATOMIC_UINT: case GLSL_TYPE_VOID: @@ -932,6 +957,7 @@ glsl_type::count_attribute_slots() const return this->length * this->fields.array->count_attribute_slots(); case GLSL_TYPE_SAMPLER: + case GLSL_TYPE_IMAGE: case GLSL_TYPE_ATOMIC_UINT: case GLSL_TYPE_VOID: case GLSL_TYPE_ERROR: @@ -944,10 +970,8 @@ glsl_type::count_attribute_slots() const } int -glsl_type::sampler_coordinate_components() const +glsl_type::coordinate_components() const { - assert(is_sampler()); - int size; switch (sampler_dimensionality) { diff --git a/mesalib/src/glsl/glsl_types.h b/mesalib/src/glsl/glsl_types.h index f88758a9a..ae3829f30 100644 --- a/mesalib/src/glsl/glsl_types.h +++ b/mesalib/src/glsl/glsl_types.h @@ -53,6 +53,7 @@ enum glsl_base_type { GLSL_TYPE_FLOAT, GLSL_TYPE_BOOL, GLSL_TYPE_SAMPLER, + GLSL_TYPE_IMAGE, GLSL_TYPE_ATOMIC_UINT, GLSL_TYPE_STRUCT, GLSL_TYPE_INTERFACE, @@ -89,8 +90,9 @@ struct glsl_type { unsigned sampler_dimensionality:3; /**< \see glsl_sampler_dim */ unsigned sampler_shadow:1; unsigned sampler_array:1; - unsigned sampler_type:2; /**< Type of data returned using this sampler. - * only \c GLSL_TYPE_FLOAT, \c GLSL_TYPE_INT, + unsigned sampler_type:2; /**< Type of data returned using this + * sampler or image. Only \c + * GLSL_TYPE_FLOAT, \c GLSL_TYPE_INT, * and \c GLSL_TYPE_UINT are valid. */ unsigned interface_packing:2; @@ -402,6 +404,20 @@ struct glsl_type { gl_texture_index sampler_index() const; /** + * Query whether or not type is an image, or for struct and array + * types, contains an image. + */ + bool contains_image() const; + + /** + * Query whether or not a type is an image + */ + bool is_image() const + { + return base_type == GLSL_TYPE_IMAGE; + } + + /** * Query whether or not a type is an array */ bool is_array() const @@ -531,7 +547,8 @@ struct glsl_type { } /** - * Return the number of coordinate components needed for this sampler type. + * Return the number of coordinate components needed for this + * sampler or image type. * * This is based purely on the sampler's dimensionality. For example, this * returns 1 for sampler1D, and 3 for sampler2DArray. @@ -540,7 +557,7 @@ struct glsl_type { * a texturing built-in function, since those pack additional values (such * as the shadow comparitor or projector) into the coordinate type. */ - int sampler_coordinate_components() const; + int coordinate_components() const; /** * Compare a record type against another record type. @@ -564,8 +581,8 @@ private: glsl_base_type base_type, unsigned vector_elements, unsigned matrix_columns, const char *name); - /** Constructor for sampler types */ - glsl_type(GLenum gl_type, + /** Constructor for sampler or image types */ + glsl_type(GLenum gl_type, glsl_base_type base_type, enum glsl_sampler_dim dim, bool shadow, bool array, unsigned type, const char *name); diff --git a/mesalib/src/glsl/ir.cpp b/mesalib/src/glsl/ir.cpp index 1a36bd631..a41eddfcb 100644 --- a/mesalib/src/glsl/ir.cpp +++ b/mesalib/src/glsl/ir.cpp @@ -1311,13 +1311,13 @@ ir_dereference::is_lvalue() const if ((var == NULL) || var->data.read_only) return false; - /* From page 17 (page 23 of the PDF) of the GLSL 1.20 spec: + /* From section 4.1.7 of the GLSL 4.40 spec: * - * "Samplers cannot be treated as l-values; hence cannot be used - * as out or inout function parameters, nor can they be - * assigned into." + * "Opaque variables cannot be treated as l-values; hence cannot + * be used as out or inout function parameters, nor can they be + * assigned into." */ - if (this->type->contains_sampler()) + if (this->type->contains_opaque()) return false; return true; @@ -1554,6 +1554,11 @@ ir_variable::ir_variable(const struct glsl_type *type, const char *name, this->data.max_array_access = 0; this->data.atomic.buffer_index = 0; this->data.atomic.offset = 0; + this->data.image.read_only = false; + this->data.image.write_only = false; + this->data.image.coherent = false; + this->data.image._volatile = false; + this->data.image.restrict_flag = false; if (type != NULL) { if (type->base_type == GLSL_TYPE_SAMPLER) @@ -1658,7 +1663,12 @@ ir_function_signature::qualifiers_match(exec_list *params) !modes_match(a->data.mode, b->data.mode) || a->data.interpolation != b->data.interpolation || a->data.centroid != b->data.centroid || - a->data.sample != b->data.sample) { + a->data.sample != b->data.sample || + a->data.image.read_only != b->data.image.read_only || + a->data.image.write_only != b->data.image.write_only || + a->data.image.coherent != b->data.image.coherent || + a->data.image._volatile != b->data.image._volatile || + a->data.image.restrict_flag != b->data.image.restrict_flag) { /* parameter a's qualifiers don't match */ return a->name; diff --git a/mesalib/src/glsl/ir.h b/mesalib/src/glsl/ir.h index e266328b2..ed3f086ce 100644 --- a/mesalib/src/glsl/ir.h +++ b/mesalib/src/glsl/ir.h @@ -106,6 +106,7 @@ public: /** ir_print_visitor helper for debugging. */ void print(void) const; + void fprint(FILE *f) const; virtual void accept(ir_visitor *) = 0; virtual ir_visitor_status accept(ir_hierarchical_visitor *) = 0; @@ -691,6 +692,20 @@ public: } atomic; /** + * ARB_shader_image_load_store qualifiers. + */ + struct { + bool read_only; /**< "readonly" qualifier. */ + bool write_only; /**< "writeonly" qualifier. */ + bool coherent; + bool _volatile; + bool restrict_flag; + + /** Image internal format if specified explicitly, otherwise GL_NONE. */ + GLenum format; + } image; + + /** * Highest element accessed with a constant expression array index * * Not used for non-array variables. @@ -1444,6 +1459,18 @@ public: } /** + * Return whether the expression operates on vectors horizontally. + */ + bool is_horizontal() const + { + return operation == ir_binop_all_equal || + operation == ir_binop_any_nequal || + operation == ir_unop_any || + operation == ir_binop_dot || + operation == ir_quadop_vector; + } + + /** * Return a string representing this expression's operator. */ const char *operator_string(); @@ -2339,7 +2366,7 @@ mode_string(const ir_variable *var); extern "C" { #endif /* __cplusplus */ -extern void _mesa_print_ir(struct exec_list *instructions, +extern void _mesa_print_ir(FILE *f, struct exec_list *instructions, struct _mesa_glsl_parse_state *state); #ifdef __cplusplus diff --git a/mesalib/src/glsl/ir_clone.cpp b/mesalib/src/glsl/ir_clone.cpp index cb732a51a..311c992be 100644 --- a/mesalib/src/glsl/ir_clone.cpp +++ b/mesalib/src/glsl/ir_clone.cpp @@ -373,6 +373,7 @@ ir_constant::clone(void *mem_ctx, struct hash_table *ht) const } case GLSL_TYPE_SAMPLER: + case GLSL_TYPE_IMAGE: case GLSL_TYPE_ATOMIC_UINT: case GLSL_TYPE_VOID: case GLSL_TYPE_ERROR: diff --git a/mesalib/src/glsl/ir_optimization.h b/mesalib/src/glsl/ir_optimization.h index 055d65547..5f4a2f405 100644 --- a/mesalib/src/glsl/ir_optimization.h +++ b/mesalib/src/glsl/ir_optimization.h @@ -36,9 +36,8 @@ #define LOG_TO_LOG2 0x10 #define MOD_TO_FRACT 0x20 #define INT_DIV_TO_MUL_RCP 0x40 -#define LRP_TO_ARITH 0x80 -#define BITFIELD_INSERT_TO_BFM_BFI 0x100 -#define LDEXP_TO_ARITH 0x200 +#define BITFIELD_INSERT_TO_BFM_BFI 0x80 +#define LDEXP_TO_ARITH 0x100 /** * \see class lower_packing_builtins_visitor @@ -120,6 +119,7 @@ bool lower_vector_insert(exec_list *instructions, bool lower_nonconstant_index); void lower_named_interface_blocks(void *mem_ctx, gl_shader *shader); bool optimize_redundant_jumps(exec_list *instructions); bool optimize_split_arrays(exec_list *instructions, bool linked); +bool lower_offset_arrays(exec_list *instructions); ir_rvalue * compare_index_block(exec_list *instructions, ir_variable *index, diff --git a/mesalib/src/glsl/ir_print_visitor.cpp b/mesalib/src/glsl/ir_print_visitor.cpp index 935782184..c7786ba9f 100644 --- a/mesalib/src/glsl/ir_print_visitor.cpp +++ b/mesalib/src/glsl/ir_print_visitor.cpp @@ -27,52 +27,59 @@ #include "main/macros.h" #include "program/hash_table.h" -static void print_type(const glsl_type *t); +static void print_type(FILE *f, const glsl_type *t); void ir_instruction::print(void) const { + this->fprint(stdout); +} + +void +ir_instruction::fprint(FILE *f) const +{ ir_instruction *deconsted = const_cast<ir_instruction *>(this); - ir_print_visitor v; + ir_print_visitor v(f); deconsted->accept(&v); } extern "C" { void -_mesa_print_ir(exec_list *instructions, +_mesa_print_ir(FILE *f, exec_list *instructions, struct _mesa_glsl_parse_state *state) { if (state) { for (unsigned i = 0; i < state->num_user_structures; i++) { const glsl_type *const s = state->user_structures[i]; - printf("(structure (%s) (%s@%p) (%u) (\n", - s->name, s->name, (void *) s, s->length); + fprintf(f, "(structure (%s) (%s@%p) (%u) (\n", + s->name, s->name, (void *) s, s->length); for (unsigned j = 0; j < s->length; j++) { - printf("\t(("); - print_type(s->fields.structure[j].type); - printf(")(%s))\n", s->fields.structure[j].name); + fprintf(f, "\t(("); + print_type(f, s->fields.structure[j].type); + fprintf(f, ")(%s))\n", s->fields.structure[j].name); } - printf(")\n"); + fprintf(f, ")\n"); } } - printf("(\n"); + fprintf(f, "(\n"); foreach_list(n, instructions) { ir_instruction *ir = (ir_instruction *) n; - ir->print(); + ir->fprint(f); if (ir->ir_type != ir_type_function) - printf("\n"); + fprintf(f, "\n"); } - printf("\n)"); + fprintf(f, "\n)"); } } /* extern "C" */ -ir_print_visitor::ir_print_visitor() +ir_print_visitor::ir_print_visitor(FILE *f) + : f(f) { indentation = 0; printable_names = @@ -91,7 +98,7 @@ ir_print_visitor::~ir_print_visitor() void ir_print_visitor::indent(void) { for (int i = 0; i < indentation; i++) - printf(" "); + fprintf(f, " "); } const char * @@ -125,28 +132,28 @@ ir_print_visitor::unique_name(ir_variable *var) } static void -print_type(const glsl_type *t) +print_type(FILE *f, const glsl_type *t) { if (t->base_type == GLSL_TYPE_ARRAY) { - printf("(array "); - print_type(t->fields.array); - printf(" %u)", t->length); + fprintf(f, "(array "); + print_type(f, t->fields.array); + fprintf(f, " %u)", t->length); } else if ((t->base_type == GLSL_TYPE_STRUCT) && (strncmp("gl_", t->name, 3) != 0)) { - printf("%s@%p", t->name, (void *) t); + fprintf(f, "%s@%p", t->name, (void *) t); } else { - printf("%s", t->name); + fprintf(f, "%s", t->name); } } void ir_print_visitor::visit(ir_rvalue *ir) { - printf("error"); + fprintf(f, "error"); } void ir_print_visitor::visit(ir_variable *ir) { - printf("(declare "); + fprintf(f, "(declare "); const char *const cent = (ir->data.centroid) ? "centroid " : ""; const char *const samp = (ir->data.sample) ? "sample " : ""; @@ -158,25 +165,25 @@ void ir_print_visitor::visit(ir_variable *ir) const char *const interp[] = { "", "smooth", "flat", "noperspective" }; STATIC_ASSERT(ARRAY_SIZE(interp) == INTERP_QUALIFIER_COUNT); - printf("(%s%s%s%s%s) ", + fprintf(f, "(%s%s%s%s%s) ", cent, samp, inv, mode[ir->data.mode], interp[ir->data.interpolation]); - print_type(ir->type); - printf(" %s)", unique_name(ir)); + print_type(f, ir->type); + fprintf(f, " %s)", unique_name(ir)); } void ir_print_visitor::visit(ir_function_signature *ir) { _mesa_symbol_table_push_scope(symbols); - printf("(signature "); + fprintf(f, "(signature "); indentation++; - print_type(ir->return_type); - printf("\n"); + print_type(f, ir->return_type); + fprintf(f, "\n"); indent(); - printf("(parameters\n"); + fprintf(f, "(parameters\n"); indentation++; foreach_list(n, &ir->parameters) { @@ -184,16 +191,16 @@ void ir_print_visitor::visit(ir_function_signature *ir) indent(); inst->accept(this); - printf("\n"); + fprintf(f, "\n"); } indentation--; indent(); - printf(")\n"); + fprintf(f, ")\n"); indent(); - printf("(\n"); + fprintf(f, "(\n"); indentation++; foreach_list(n, &ir->body) { @@ -201,11 +208,11 @@ void ir_print_visitor::visit(ir_function_signature *ir) indent(); inst->accept(this); - printf("\n"); + fprintf(f, "\n"); } indentation--; indent(); - printf("))\n"); + fprintf(f, "))\n"); indentation--; _mesa_symbol_table_pop_scope(symbols); } @@ -213,58 +220,58 @@ void ir_print_visitor::visit(ir_function_signature *ir) void ir_print_visitor::visit(ir_function *ir) { - printf("(function %s\n", ir->name); + fprintf(f, "(function %s\n", ir->name); indentation++; foreach_list(n, &ir->signatures) { ir_function_signature *const sig = (ir_function_signature *) n; indent(); sig->accept(this); - printf("\n"); + fprintf(f, "\n"); } indentation--; indent(); - printf(")\n\n"); + fprintf(f, ")\n\n"); } void ir_print_visitor::visit(ir_expression *ir) { - printf("(expression "); + fprintf(f, "(expression "); - print_type(ir->type); + print_type(f, ir->type); - printf(" %s ", ir->operator_string()); + fprintf(f, " %s ", ir->operator_string()); for (unsigned i = 0; i < ir->get_num_operands(); i++) { ir->operands[i]->accept(this); } - printf(") "); + fprintf(f, ") "); } void ir_print_visitor::visit(ir_texture *ir) { - printf("(%s ", ir->opcode_string()); + fprintf(f, "(%s ", ir->opcode_string()); - print_type(ir->type); - printf(" "); + print_type(f, ir->type); + fprintf(f, " "); ir->sampler->accept(this); - printf(" "); + fprintf(f, " "); if (ir->op != ir_txs && ir->op != ir_query_levels) { ir->coordinate->accept(this); - printf(" "); + fprintf(f, " "); if (ir->offset != NULL) { ir->offset->accept(this); } else { - printf("0"); + fprintf(f, "0"); } - printf(" "); + fprintf(f, " "); } if (ir->op != ir_txf && ir->op != ir_txf_ms && @@ -273,17 +280,17 @@ void ir_print_visitor::visit(ir_texture *ir) if (ir->projector) ir->projector->accept(this); else - printf("1"); + fprintf(f, "1"); if (ir->shadow_comparitor) { - printf(" "); + fprintf(f, " "); ir->shadow_comparitor->accept(this); } else { - printf(" ()"); + fprintf(f, " ()"); } } - printf(" "); + fprintf(f, " "); switch (ir->op) { case ir_tex: @@ -302,17 +309,17 @@ void ir_print_visitor::visit(ir_texture *ir) ir->lod_info.sample_index->accept(this); break; case ir_txd: - printf("("); + fprintf(f, "("); ir->lod_info.grad.dPdx->accept(this); - printf(" "); + fprintf(f, " "); ir->lod_info.grad.dPdy->accept(this); - printf(")"); + fprintf(f, ")"); break; case ir_tg4: ir->lod_info.component->accept(this); break; }; - printf(")"); + fprintf(f, ")"); } @@ -325,43 +332,43 @@ void ir_print_visitor::visit(ir_swizzle *ir) ir->mask.w, }; - printf("(swiz "); + fprintf(f, "(swiz "); for (unsigned i = 0; i < ir->mask.num_components; i++) { - printf("%c", "xyzw"[swiz[i]]); + fprintf(f, "%c", "xyzw"[swiz[i]]); } - printf(" "); + fprintf(f, " "); ir->val->accept(this); - printf(")"); + fprintf(f, ")"); } void ir_print_visitor::visit(ir_dereference_variable *ir) { ir_variable *var = ir->variable_referenced(); - printf("(var_ref %s) ", unique_name(var)); + fprintf(f, "(var_ref %s) ", unique_name(var)); } void ir_print_visitor::visit(ir_dereference_array *ir) { - printf("(array_ref "); + fprintf(f, "(array_ref "); ir->array->accept(this); ir->array_index->accept(this); - printf(") "); + fprintf(f, ") "); } void ir_print_visitor::visit(ir_dereference_record *ir) { - printf("(record_ref "); + fprintf(f, "(record_ref "); ir->record->accept(this); - printf(" %s) ", ir->field); + fprintf(f, " %s) ", ir->field); } void ir_print_visitor::visit(ir_assignment *ir) { - printf("(assign "); + fprintf(f, "(assign "); if (ir->condition) ir->condition->accept(this); @@ -377,22 +384,22 @@ void ir_print_visitor::visit(ir_assignment *ir) } mask[j] = '\0'; - printf(" (%s) ", mask); + fprintf(f, " (%s) ", mask); ir->lhs->accept(this); - printf(" "); + fprintf(f, " "); ir->rhs->accept(this); - printf(") "); + fprintf(f, ") "); } void ir_print_visitor::visit(ir_constant *ir) { - printf("(constant "); - print_type(ir->type); - printf(" ("); + fprintf(f, "(constant "); + print_type(f, ir->type); + fprintf(f, " ("); if (ir->type->is_array()) { for (unsigned i = 0; i < ir->type->length; i++) @@ -400,91 +407,91 @@ void ir_print_visitor::visit(ir_constant *ir) } else if (ir->type->is_record()) { ir_constant *value = (ir_constant *) ir->components.get_head(); for (unsigned i = 0; i < ir->type->length; i++) { - printf("(%s ", ir->type->fields.structure[i].name); + fprintf(f, "(%s ", ir->type->fields.structure[i].name); value->accept(this); - printf(")"); + fprintf(f, ")"); value = (ir_constant *) value->next; } } else { for (unsigned i = 0; i < ir->type->components(); i++) { if (i != 0) - printf(" "); + fprintf(f, " "); switch (ir->type->base_type) { - case GLSL_TYPE_UINT: printf("%u", ir->value.u[i]); break; - case GLSL_TYPE_INT: printf("%d", ir->value.i[i]); break; + case GLSL_TYPE_UINT: fprintf(f, "%u", ir->value.u[i]); break; + case GLSL_TYPE_INT: fprintf(f, "%d", ir->value.i[i]); break; case GLSL_TYPE_FLOAT: if (ir->value.f[i] == 0.0f) /* 0.0 == -0.0, so print with %f to get the proper sign. */ - printf("%.1f", ir->value.f[i]); + fprintf(f, "%.1f", ir->value.f[i]); else if (fabs(ir->value.f[i]) < 0.000001f) - printf("%a", ir->value.f[i]); + fprintf(f, "%a", ir->value.f[i]); else if (fabs(ir->value.f[i]) > 1000000.0f) - printf("%e", ir->value.f[i]); + fprintf(f, "%e", ir->value.f[i]); else - printf("%f", ir->value.f[i]); + fprintf(f, "%f", ir->value.f[i]); break; - case GLSL_TYPE_BOOL: printf("%d", ir->value.b[i]); break; + case GLSL_TYPE_BOOL: fprintf(f, "%d", ir->value.b[i]); break; default: assert(0); } } } - printf(")) "); + fprintf(f, ")) "); } void ir_print_visitor::visit(ir_call *ir) { - printf("(call %s ", ir->callee_name()); + fprintf(f, "(call %s ", ir->callee_name()); if (ir->return_deref) ir->return_deref->accept(this); - printf(" ("); + fprintf(f, " ("); foreach_list(n, &ir->actual_parameters) { ir_rvalue *const param = (ir_rvalue *) n; param->accept(this); } - printf("))\n"); + fprintf(f, "))\n"); } void ir_print_visitor::visit(ir_return *ir) { - printf("(return"); + fprintf(f, "(return"); ir_rvalue *const value = ir->get_value(); if (value) { - printf(" "); + fprintf(f, " "); value->accept(this); } - printf(")"); + fprintf(f, ")"); } void ir_print_visitor::visit(ir_discard *ir) { - printf("(discard "); + fprintf(f, "(discard "); if (ir->condition != NULL) { - printf(" "); + fprintf(f, " "); ir->condition->accept(this); } - printf(")"); + fprintf(f, ")"); } void ir_print_visitor::visit(ir_if *ir) { - printf("(if "); + fprintf(f, "(if "); ir->condition->accept(this); - printf("(\n"); + fprintf(f, "(\n"); indentation++; foreach_list(n, &ir->then_instructions) { @@ -492,16 +499,16 @@ ir_print_visitor::visit(ir_if *ir) indent(); inst->accept(this); - printf("\n"); + fprintf(f, "\n"); } indentation--; indent(); - printf(")\n"); + fprintf(f, ")\n"); indent(); if (!ir->else_instructions.is_empty()) { - printf("(\n"); + fprintf(f, "(\n"); indentation++; foreach_list(n, &ir->else_instructions) { @@ -509,13 +516,13 @@ ir_print_visitor::visit(ir_if *ir) indent(); inst->accept(this); - printf("\n"); + fprintf(f, "\n"); } indentation--; indent(); - printf("))\n"); + fprintf(f, "))\n"); } else { - printf("())\n"); + fprintf(f, "())\n"); } } @@ -523,7 +530,7 @@ ir_print_visitor::visit(ir_if *ir) void ir_print_visitor::visit(ir_loop *ir) { - printf("(loop (\n"); + fprintf(f, "(loop (\n"); indentation++; foreach_list(n, &ir->body_instructions) { @@ -531,28 +538,28 @@ ir_print_visitor::visit(ir_loop *ir) indent(); inst->accept(this); - printf("\n"); + fprintf(f, "\n"); } indentation--; indent(); - printf("))\n"); + fprintf(f, "))\n"); } void ir_print_visitor::visit(ir_loop_jump *ir) { - printf("%s", ir->is_break() ? "break" : "continue"); + fprintf(f, "%s", ir->is_break() ? "break" : "continue"); } void ir_print_visitor::visit(ir_emit_vertex *ir) { - printf("(emit-vertex)"); + fprintf(f, "(emit-vertex)"); } void ir_print_visitor::visit(ir_end_primitive *ir) { - printf("(end-primitive)"); + fprintf(f, "(end-primitive)"); } diff --git a/mesalib/src/glsl/ir_print_visitor.h b/mesalib/src/glsl/ir_print_visitor.h index 865376fe0..98f041d1a 100644 --- a/mesalib/src/glsl/ir_print_visitor.h +++ b/mesalib/src/glsl/ir_print_visitor.h @@ -38,7 +38,7 @@ extern "C" { */ class ir_print_visitor : public ir_visitor { public: - ir_print_visitor(); + ir_print_visitor(FILE *f); virtual ~ir_print_visitor(); void indent(void); @@ -87,6 +87,7 @@ private: _mesa_symbol_table *symbols; void *mem_ctx; + FILE *f; int indentation; }; diff --git a/mesalib/src/glsl/ir_uniform.h b/mesalib/src/glsl/ir_uniform.h index f678c2c5c..7508f795d 100644 --- a/mesalib/src/glsl/ir_uniform.h +++ b/mesalib/src/glsl/ir_uniform.h @@ -78,6 +78,26 @@ struct gl_uniform_driver_storage { void *data; }; +struct gl_opaque_uniform_index { + /** + * Base opaque uniform index + * + * If \c gl_uniform_storage::base_type is an opaque type, this + * represents its uniform index. If \c + * gl_uniform_storage::array_elements is not zero, the array will + * use opaque uniform indices \c index through \c index + \c + * gl_uniform_storage::array_elements - 1, inclusive. + * + * Note that the index may be different in each shader stage. + */ + uint8_t index; + + /** + * Whether this opaque uniform is used in this shader stage. + */ + bool active; +}; + struct gl_uniform_storage { char *name; /** Type of this uniform data stored. @@ -99,24 +119,9 @@ struct gl_uniform_storage { */ bool initialized; - struct { - /** - * Base sampler index - * - * If \c ::base_type is \c GLSL_TYPE_SAMPLER, this represents the index - * of this sampler. If \c ::array_elements is not zero, the array will - * use sampler indices \c ::sampler through \c ::sampler + - * \c ::array_elements - 1, inclusive. - * - * Note that the index may be different in each shader stage. - */ - uint8_t index; - - /** - * Whether this sampler is used in this shader stage. - */ - bool active; - } sampler[MESA_SHADER_STAGES]; + struct gl_opaque_uniform_index sampler[MESA_SHADER_STAGES]; + + struct gl_opaque_uniform_index image[MESA_SHADER_STAGES]; /** * Storage used by the driver for the uniform diff --git a/mesalib/src/glsl/link_uniform_initializers.cpp b/mesalib/src/glsl/link_uniform_initializers.cpp index 7d5c1472d..9d6977d57 100644 --- a/mesalib/src/glsl/link_uniform_initializers.cpp +++ b/mesalib/src/glsl/link_uniform_initializers.cpp @@ -69,6 +69,7 @@ copy_constant_to_storage(union gl_constant_value *storage, break; case GLSL_TYPE_ARRAY: case GLSL_TYPE_STRUCT: + case GLSL_TYPE_IMAGE: case GLSL_TYPE_ATOMIC_UINT: case GLSL_TYPE_INTERFACE: case GLSL_TYPE_VOID: diff --git a/mesalib/src/glsl/link_uniforms.cpp b/mesalib/src/glsl/link_uniforms.cpp index 1c97e1957..1cf376d5d 100644 --- a/mesalib/src/glsl/link_uniforms.cpp +++ b/mesalib/src/glsl/link_uniforms.cpp @@ -240,7 +240,8 @@ class count_uniform_size : public program_resource_visitor { public: count_uniform_size(struct string_to_uint_map *map) : num_active_uniforms(0), num_values(0), num_shader_samplers(0), - num_shader_uniform_components(0), is_ubo_var(false), map(map) + num_shader_images(0), num_shader_uniform_components(0), + is_ubo_var(false), map(map) { /* empty */ } @@ -248,6 +249,7 @@ public: void start_shader() { this->num_shader_samplers = 0; + this->num_shader_images = 0; this->num_shader_uniform_components = 0; } @@ -277,6 +279,11 @@ public: unsigned num_shader_samplers; /** + * Number of images used + */ + unsigned num_shader_images; + + /** * Number of uniforms used in the current shader */ unsigned num_shader_uniform_components; @@ -303,6 +310,15 @@ private: if (type->contains_sampler()) { this->num_shader_samplers += type->is_array() ? type->array_size() : 1; + } else if (type->contains_image()) { + this->num_shader_images += values; + + /* As drivers are likely to represent image uniforms as + * scalar indices, count them against the limit of uniform + * components in the default block. The spec allows image + * uniforms to use up no more than one scalar slot. + */ + this->num_shader_uniform_components += values; } else { /* Accumulate the total number of uniform slots used by this shader. * Note that samplers do not count against this limit because they @@ -364,6 +380,7 @@ public: this->shader_samplers_used = 0; this->shader_shadow_samplers = 0; this->next_sampler = 0; + this->next_image = 0; memset(this->targets, 0, sizeof(this->targets)); } @@ -460,6 +477,24 @@ private: } } + void handle_images(const glsl_type *base_type, + struct gl_uniform_storage *uniform) + { + if (base_type->is_image()) { + uniform->image[shader_type].index = this->next_image; + uniform->image[shader_type].active = true; + + /* Increment the image index by 1 for non-arrays and by the + * number of array elements for arrays. + */ + this->next_image += MAX2(1, uniform->array_elements); + + } else { + uniform->image[shader_type].index = ~0; + uniform->image[shader_type].active = false; + } + } + virtual void visit_field(const glsl_type *type, const char *name, bool row_major) { @@ -495,8 +530,9 @@ private: base_type = type; } - /* This assigns sampler uniforms to sampler units. */ + /* This assigns uniform indices to sampler and image uniforms. */ handle_samplers(base_type, &this->uniforms[id]); + handle_images(base_type, &this->uniforms[id]); /* If there is already storage associated with this uniform, it means * that it was set while processing an earlier shader stage. For @@ -554,6 +590,7 @@ private: struct gl_uniform_storage *uniforms; unsigned next_sampler; + unsigned next_image; public: union gl_constant_value *values; @@ -720,6 +757,40 @@ link_assign_uniform_block_offsets(struct gl_shader *shader) } } +/** + * Scan the program for image uniforms and store image unit access + * information into the gl_shader data structure. + */ +static void +link_set_image_access_qualifiers(struct gl_shader_program *prog) +{ + for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) { + gl_shader *sh = prog->_LinkedShaders[i]; + + if (sh == NULL) + continue; + + foreach_list(node, sh->ir) { + ir_variable *var = ((ir_instruction *) node)->as_variable(); + + if (var && var->data.mode == ir_var_uniform && + var->type->contains_image()) { + unsigned id; + bool found = prog->UniformHash->get(id, var->name); + assert(found); + const gl_uniform_storage *storage = &prog->UniformStorage[id]; + const unsigned index = storage->image[i].index; + const GLenum access = (var->data.image.read_only ? GL_READ_ONLY : + var->data.image.write_only ? GL_WRITE_ONLY : + GL_READ_WRITE); + + for (unsigned j = 0; j < MAX2(1, storage->array_elements); ++j) + sh->ImageAccess[index + j] = access; + } + } + } +} + void link_assign_uniform_locations(struct gl_shader_program *prog) { @@ -757,6 +828,7 @@ link_assign_uniform_locations(struct gl_shader_program *prog) * types cannot have initializers." */ memset(sh->SamplerUnits, 0, sizeof(sh->SamplerUnits)); + memset(sh->ImageUnits, 0, sizeof(sh->ImageUnits)); link_update_uniform_buffer_variables(sh); @@ -782,6 +854,7 @@ link_assign_uniform_locations(struct gl_shader_program *prog) } sh->num_samplers = uniform_size.num_shader_samplers; + sh->NumImages = uniform_size.num_shader_images; sh->num_uniform_components = uniform_size.num_shader_uniform_components; sh->num_combined_uniform_components = sh->num_uniform_components; @@ -862,6 +935,7 @@ link_assign_uniform_locations(struct gl_shader_program *prog) prog->NumUserUniformStorage = num_user_uniforms; prog->UniformStorage = uniforms; + link_set_image_access_qualifiers(prog); link_set_uniform_initializers(prog); return; diff --git a/mesalib/src/glsl/linker.cpp b/mesalib/src/glsl/linker.cpp index bcd739476..f6b266185 100644 --- a/mesalib/src/glsl/linker.cpp +++ b/mesalib/src/glsl/linker.cpp @@ -1206,6 +1206,7 @@ link_gs_inout_layout_qualifiers(struct gl_shader_program *prog, unsigned num_shaders) { linked_shader->Geom.VerticesOut = 0; + linked_shader->Geom.Invocations = 0; linked_shader->Geom.InputType = PRIM_UNKNOWN; linked_shader->Geom.OutputType = PRIM_UNKNOWN; @@ -1259,6 +1260,18 @@ link_gs_inout_layout_qualifiers(struct gl_shader_program *prog, } linked_shader->Geom.VerticesOut = shader->Geom.VerticesOut; } + + if (shader->Geom.Invocations != 0) { + if (linked_shader->Geom.Invocations != 0 && + linked_shader->Geom.Invocations != shader->Geom.Invocations) { + linker_error(prog, "geometry shader defined with conflicting " + "invocation count (%d and %d)\n", + linked_shader->Geom.Invocations, + shader->Geom.Invocations); + return; + } + linked_shader->Geom.Invocations = shader->Geom.Invocations; + } } /* Just do the intrastage -> interstage propagation right now, @@ -1285,6 +1298,11 @@ link_gs_inout_layout_qualifiers(struct gl_shader_program *prog, return; } prog->Geom.VerticesOut = linked_shader->Geom.VerticesOut; + + if (linked_shader->Geom.Invocations == 0) + linked_shader->Geom.Invocations = 1; + + prog->Geom.Invocations = linked_shader->Geom.Invocations; } @@ -2031,6 +2049,46 @@ check_resources(struct gl_context *ctx, struct gl_shader_program *prog) } } +/** + * Validate shader image resources. + */ +static void +check_image_resources(struct gl_context *ctx, struct gl_shader_program *prog) +{ + unsigned total_image_units = 0; + unsigned fragment_outputs = 0; + + if (!ctx->Extensions.ARB_shader_image_load_store) + return; + + for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) { + struct gl_shader *sh = prog->_LinkedShaders[i]; + + if (sh) { + if (sh->NumImages > ctx->Const.Program[i].MaxImageUniforms) + linker_error(prog, "Too many %s shader image uniforms", + _mesa_shader_stage_to_string(i)); + + total_image_units += sh->NumImages; + + if (i == MESA_SHADER_FRAGMENT) { + foreach_list(node, sh->ir) { + ir_variable *var = ((ir_instruction *)node)->as_variable(); + if (var && var->data.mode == ir_var_shader_out) + fragment_outputs += var->type->count_attribute_slots(); + } + } + } + } + + if (total_image_units > ctx->Const.MaxCombinedImageUniforms) + linker_error(prog, "Too many combined image uniforms"); + + if (total_image_units + fragment_outputs > + ctx->Const.MaxCombinedImageUnitsAndFragmentOutputs) + linker_error(prog, "Too many combined image uniforms and fragment outputs"); +} + void link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) { @@ -2394,17 +2452,19 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) store_fragdepth_layout(prog); check_resources(ctx, prog); + check_image_resources(ctx, prog); link_check_atomic_counter_resources(ctx, prog); if (!prog->LinkStatus) goto done; /* OpenGL ES requires that a vertex shader and a fragment shader both be - * present in a linked program. By checking prog->IsES, we also - * catch the GL_ARB_ES2_compatibility case. + * present in a linked program. GL_ARB_ES2_compatibility doesn't say + * anything about shader linking when one of the shaders (vertex or + * fragment shader) is absent. So, the extension shouldn't change the + * behavior specified in GLSL specification. */ - if (!prog->InternalSeparateShader && - (ctx->API == API_OPENGLES2 || prog->IsES)) { + if (!prog->InternalSeparateShader && ctx->API == API_OPENGLES2) { if (prog->_LinkedShaders[MESA_SHADER_VERTEX] == NULL) { linker_error(prog, "program lacks a vertex shader\n"); } else if (prog->_LinkedShaders[MESA_SHADER_FRAGMENT] == NULL) { diff --git a/mesalib/src/glsl/lower_instructions.cpp b/mesalib/src/glsl/lower_instructions.cpp index 44a6e8021..01ea0f01f 100644 --- a/mesalib/src/glsl/lower_instructions.cpp +++ b/mesalib/src/glsl/lower_instructions.cpp @@ -38,7 +38,6 @@ * - LOG_TO_LOG2 * - MOD_TO_FRACT * - LDEXP_TO_ARITH - * - LRP_TO_ARITH * - BITFIELD_INSERT_TO_BFM_BFI * * SUB_TO_ADD_NEG: @@ -87,10 +86,6 @@ * ------------- * Converts ir_binop_ldexp to arithmetic and bit operations. * - * LRP_TO_ARITH: - * ------------- - * Converts ir_triop_lrp to (op0 * (1.0f - op2)) + (op1 * op2). - * * BITFIELD_INSERT_TO_BFM_BFI: * --------------------------- * Breaks ir_quadop_bitfield_insert into ir_binop_bfm (bitfield mask) and @@ -130,7 +125,6 @@ private: void exp_to_exp2(ir_expression *); void pow_to_exp2(ir_expression *); void log_to_log2(ir_expression *); - void lrp_to_arith(ir_expression *); void bitfield_insert_to_bfm_bfi(ir_expression *); void ldexp_to_arith(ir_expression *); }; @@ -299,27 +293,6 @@ lower_instructions_visitor::mod_to_fract(ir_expression *ir) } void -lower_instructions_visitor::lrp_to_arith(ir_expression *ir) -{ - /* (lrp x y a) -> x*(1-a) + y*a */ - - /* Save op2 */ - ir_variable *temp = new(ir) ir_variable(ir->operands[2]->type, "lrp_factor", - ir_var_temporary); - this->base_ir->insert_before(temp); - this->base_ir->insert_before(assign(temp, ir->operands[2])); - - ir_constant *one = new(ir) ir_constant(1.0f); - - ir->operation = ir_binop_add; - ir->operands[0] = mul(ir->operands[0], sub(one, temp)); - ir->operands[1] = mul(ir->operands[1], temp); - ir->operands[2] = NULL; - - this->progress = true; -} - -void lower_instructions_visitor::bitfield_insert_to_bfm_bfi(ir_expression *ir) { /* Translates @@ -499,11 +472,6 @@ lower_instructions_visitor::visit_leave(ir_expression *ir) pow_to_exp2(ir); break; - case ir_triop_lrp: - if (lowering(LRP_TO_ARITH)) - lrp_to_arith(ir); - break; - case ir_quadop_bitfield_insert: if (lowering(BITFIELD_INSERT_TO_BFM_BFI)) bitfield_insert_to_bfm_bfi(ir); diff --git a/mesalib/src/glsl/lower_offset_array.cpp b/mesalib/src/glsl/lower_offset_array.cpp new file mode 100644 index 000000000..0c235eda3 --- /dev/null +++ b/mesalib/src/glsl/lower_offset_array.cpp @@ -0,0 +1,90 @@ +/* + * Copyright © 2013 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +/** + * \file brw_lower_offset_array.cpp + * + * IR lower pass to decompose ir_texture ir_tg4 with an array of offsets + * into four ir_tg4s with a single ivec2 offset, select the .w component of each, + * and return those four values packed into a gvec4. + * + * \author Chris Forbes <chrisf@ijw.co.nz> + */ + +#include "glsl_types.h" +#include "ir.h" +#include "ir_builder.h" +#include "ir_optimization.h" +#include "ir_rvalue_visitor.h" + +using namespace ir_builder; + +class brw_lower_offset_array_visitor : public ir_rvalue_visitor { +public: + brw_lower_offset_array_visitor() + { + progress = false; + } + + void handle_rvalue(ir_rvalue **rv); + + bool progress; +}; + +void +brw_lower_offset_array_visitor::handle_rvalue(ir_rvalue **rv) +{ + if (*rv == NULL || (*rv)->ir_type != ir_type_texture) + return; + + ir_texture *ir = (ir_texture *) *rv; + if (ir->op != ir_tg4 || !ir->offset || !ir->offset->type->is_array()) + return; + + void *mem_ctx = ralloc_parent(ir); + + ir_variable *var = new (mem_ctx) ir_variable(ir->type, "result", ir_var_auto); + base_ir->insert_before(var); + + for (int i = 0; i < 4; i++) { + ir_texture *tex = ir->clone(mem_ctx, NULL); + tex->offset = new (mem_ctx) ir_dereference_array(tex->offset, + new (mem_ctx) ir_constant(i)); + + base_ir->insert_before(assign(var, swizzle_w(tex), 1 << i)); + } + + *rv = new (mem_ctx) ir_dereference_variable(var); + + progress = true; +} + +bool +lower_offset_arrays(exec_list *instructions) +{ + brw_lower_offset_array_visitor v; + + visit_list_elements(&v, instructions); + + return v.progress; +} diff --git a/mesalib/src/glsl/main.cpp b/mesalib/src/glsl/main.cpp index 3a0f812f2..4ae8f0987 100644 --- a/mesalib/src/glsl/main.cpp +++ b/mesalib/src/glsl/main.cpp @@ -294,7 +294,7 @@ compile_shader(struct gl_context *ctx, struct gl_shader *shader) /* Print out the resulting IR */ if (!state->error && dump_lir) { - _mesa_print_ir(shader->ir, state); + _mesa_print_ir(stdout, shader->ir, state); } return; diff --git a/mesalib/src/glsl/opt_algebraic.cpp b/mesalib/src/glsl/opt_algebraic.cpp index 1b4d31936..5c49a785c 100644 --- a/mesalib/src/glsl/opt_algebraic.cpp +++ b/mesalib/src/glsl/opt_algebraic.cpp @@ -568,6 +568,12 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir) return ir->operands[1]; } else if (ir->operands[0]->equals(ir->operands[1])) { return ir->operands[0]; + } else if (is_vec_zero(op_const[0])) { + return mul(ir->operands[1], ir->operands[2]); + } else if (is_vec_zero(op_const[1])) { + unsigned op2_components = ir->operands[2]->type->vector_elements; + ir_constant *one = new(mem_ctx) ir_constant(1.0f, op2_components); + return mul(ir->operands[0], add(one, neg(ir->operands[2]))); } break; diff --git a/mesalib/src/glsl/opt_array_splitting.cpp b/mesalib/src/glsl/opt_array_splitting.cpp index f37d09022..97d3a57e9 100644 --- a/mesalib/src/glsl/opt_array_splitting.cpp +++ b/mesalib/src/glsl/opt_array_splitting.cpp @@ -400,7 +400,7 @@ optimize_split_arrays(exec_list *instructions, bool linked) visit_list_elements(&split, instructions); if (debug) - _mesa_print_ir(instructions, NULL); + _mesa_print_ir(stdout, instructions, NULL); ralloc_free(mem_ctx); diff --git a/mesalib/src/glsl/opt_vectorize.cpp b/mesalib/src/glsl/opt_vectorize.cpp index 8ee81f1a3..13faac05e 100644 --- a/mesalib/src/glsl/opt_vectorize.cpp +++ b/mesalib/src/glsl/opt_vectorize.cpp @@ -82,6 +82,8 @@ public: virtual ir_visitor_status visit_enter(ir_assignment *); virtual ir_visitor_status visit_enter(ir_swizzle *); + virtual ir_visitor_status visit_enter(ir_dereference_array *); + virtual ir_visitor_status visit_enter(ir_expression *); virtual ir_visitor_status visit_enter(ir_if *); virtual ir_visitor_status visit_enter(ir_loop *); @@ -289,6 +291,33 @@ ir_vectorize_visitor::visit_enter(ir_swizzle *ir) return visit_continue; } +/* Upon entering an ir_array_dereference, remove the current assignment from + * further consideration. Since the index of an array dereference must scalar, + * we are not able to vectorize it. + * + * FINISHME: If all of scalar indices are identical we could vectorize. + */ +ir_visitor_status +ir_vectorize_visitor::visit_enter(ir_dereference_array *ir) +{ + this->current_assignment = NULL; + return visit_continue_with_parent; +} + +/** + * Upon entering an ir_expression, remove the current assignment from further + * consideration if the expression operates horizontally on vectors. + */ +ir_visitor_status +ir_vectorize_visitor::visit_enter(ir_expression *ir) +{ + if (ir->is_horizontal()) { + this->current_assignment = NULL; + return visit_continue_with_parent; + } + return visit_continue; +} + /* Since there is no statement to visit between the "then" and "else" * instructions try to vectorize before, in between, and after them to avoid * combining statements from different basic blocks. diff --git a/mesalib/src/glsl/test_optpass.cpp b/mesalib/src/glsl/test_optpass.cpp index 1a15f3c63..f1b9579cd 100644 --- a/mesalib/src/glsl/test_optpass.cpp +++ b/mesalib/src/glsl/test_optpass.cpp @@ -235,7 +235,7 @@ int test_optpass(int argc, char **argv) /* Print out the initial IR */ if (!state->error && !quiet) { printf("*** pre-optimization IR:\n"); - _mesa_print_ir(shader->ir, state); + _mesa_print_ir(stdout, shader->ir, state); printf("\n--\n"); } @@ -255,7 +255,7 @@ int test_optpass(int argc, char **argv) if (!quiet) { printf("*** resulting IR:\n"); } - _mesa_print_ir(shader->ir, state); + _mesa_print_ir(stdout, shader->ir, state); if (!quiet) { printf("\n--\n"); } diff --git a/mesalib/src/mapi/glapi/Makefile.am b/mesalib/src/mapi/glapi/Makefile.am index bf653a305..e425bacea 100644 --- a/mesalib/src/mapi/glapi/Makefile.am +++ b/mesalib/src/mapi/glapi/Makefile.am @@ -27,6 +27,7 @@ include ../Makefile.sources AM_CPPFLAGS = \ $(DEFINES) \ + $(SELINUX_CFLAGS) \ -I$(top_srcdir)/include \ -I$(top_srcdir)/src/mapi \ -I$(top_builddir)/src/mapi \ diff --git a/mesalib/src/mapi/glapi/Makefile.sources b/mesalib/src/mapi/glapi/Makefile.sources index 58d28c52c..100e6347e 100644 --- a/mesalib/src/mapi/glapi/Makefile.sources +++ b/mesalib/src/mapi/glapi/Makefile.sources @@ -6,7 +6,6 @@ GLAPI_SOURCES = \ glapi_gentable.c \ glapi_getproc.c \ glapi_nop.c \ - glthread.c \ glapi.c X86_API = \ diff --git a/mesalib/src/mapi/glapi/SConscript b/mesalib/src/mapi/glapi/SConscript index 152818d22..bc1c43aa8 100644 --- a/mesalib/src/mapi/glapi/SConscript +++ b/mesalib/src/mapi/glapi/SConscript @@ -34,7 +34,6 @@ glapi_sources = [ 'glapi_entrypoint.c', 'glapi_getproc.c', 'glapi_nop.c', - 'glthread.c', 'glapi.c', ] diff --git a/mesalib/src/mapi/glapi/gen/ARB_separate_shader_objects.xml b/mesalib/src/mapi/glapi/gen/ARB_separate_shader_objects.xml new file mode 100644 index 000000000..80234ea5e --- /dev/null +++ b/mesalib/src/mapi/glapi/gen/ARB_separate_shader_objects.xml @@ -0,0 +1,401 @@ +<?xml version="1.0"?> +<!DOCTYPE OpenGLAPI SYSTEM "gl_API.dtd"> + +<!-- Note: no GLX protocol info yet. --> + +<OpenGLAPI> + <category name="ARB_separate_shader_objects" number="97"> + <enum name="ACTIVE_PROGRAM" value="0x8259"/> + <enum name="PROGRAM_PIPELINE_BINDING" value="0x825A"/> + <enum name="VERTEX_SHADER_BIT" value="0x00000001"/> + <enum name="FRAGMENT_SHADER_BIT" value="0x00000002"/> + <enum name="GEOMETRY_SHADER_BIT" value="0x00000004"/> + <enum name="TESS_CONTROL_SHADER_BIT" value="0x00000008"/> + <enum name="TESS_EVALUATION_SHADER_BIT" value="0x00000010"/> + <enum name="ALL_SHADER_BITS" value="0xFFFFFFFF"/> + <enum name="PROGRAM_SEPARABLE" value="0x8258"/> + + <function name="UseProgramStages" offset="assign"> + <param name="pipeline" type="GLuint" /> + <param name="stages" type="GLbitfield" /> + <param name="program" type="GLuint" /> + </function> + <function name="ActiveShaderProgram" offset="assign"> + <param name="pipeline" type="GLuint" /> + <param name="program" type="GLuint" /> + </function> + <function name="CreateShaderProgramv" offset="assign"> + <param name="type" type="GLenum" /> + <param name="count" type="GLsizei" /> + <param name="strings" type="const GLchar * const *" /> + <return type="GLuint"/> + </function> + <function name="BindProgramPipeline" offset="assign"> + <param name="pipeline" type="GLuint" /> + </function> + <function name="DeleteProgramPipelines" offset="assign"> + <param name="n" type="GLsizei" /> + <param name="pipelines" type="const GLuint *" /> + </function> + <function name="GenProgramPipelines" offset="assign"> + <param name="n" type="GLsizei" /> + <param name="pipelines" type="GLuint *" /> + </function> + <function name="IsProgramPipeline" offset="assign"> + <param name="pipeline" type="GLuint" /> + <return type="GLboolean"/> + </function> + <!-- Function already included on ARB_get_program_binary.xml. Keep a commented + version here for completeness --> + <!-- + <function name="ProgramParameteri" offset="assign" es2="3.0"> + <param name="program" type="GLuint"/> + <param name="pname" type="GLenum"/> + <param name="value" type="GLint"/> + </function> + --> + <function name="GetProgramPipelineiv" offset="assign"> + <param name="pipeline" type="GLuint" /> + <param name="pname" type="GLenum" /> + <param name="params" type="GLint *" /> + </function> + <function name="ProgramUniform1i" offset="assign"> + <param name="program" type="GLuint" /> + <param name="location" type="GLint" /> + <param name="x" type="GLint" /> + </function> + <function name="ProgramUniform2i" offset="assign"> + <param name="program" type="GLuint" /> + <param name="location" type="GLint" /> + <param name="x" type="GLint" /> + <param name="y" type="GLint" /> + </function> + <function name="ProgramUniform3i" offset="assign"> + <param name="program" type="GLuint" /> + <param name="location" type="GLint" /> + <param name="x" type="GLint" /> + <param name="y" type="GLint" /> + <param name="z" type="GLint" /> + </function> + <function name="ProgramUniform4i" offset="assign"> + <param name="program" type="GLuint" /> + <param name="location" type="GLint" /> + <param name="x" type="GLint" /> + <param name="y" type="GLint" /> + <param name="z" type="GLint" /> + <param name="w" type="GLint" /> + </function> + <function name="ProgramUniform1ui" offset="assign"> + <param name="program" type="GLuint" /> + <param name="location" type="GLint" /> + <param name="x" type="GLuint" /> + </function> + <function name="ProgramUniform2ui" offset="assign"> + <param name="program" type="GLuint" /> + <param name="location" type="GLint" /> + <param name="x" type="GLuint" /> + <param name="y" type="GLuint" /> + </function> + <function name="ProgramUniform3ui" offset="assign"> + <param name="program" type="GLuint" /> + <param name="location" type="GLint" /> + <param name="x" type="GLuint" /> + <param name="y" type="GLuint" /> + <param name="z" type="GLuint" /> + </function> + <function name="ProgramUniform4ui" offset="assign"> + <param name="program" type="GLuint" /> + <param name="location" type="GLint" /> + <param name="x" type="GLuint" /> + <param name="y" type="GLuint" /> + <param name="z" type="GLuint" /> + <param name="w" type="GLuint" /> + </function> + <function name="ProgramUniform1f" offset="assign"> + <param name="program" type="GLuint" /> + <param name="location" type="GLint" /> + <param name="x" type="GLfloat" /> + </function> + <function name="ProgramUniform2f" offset="assign"> + <param name="program" type="GLuint" /> + <param name="location" type="GLint" /> + <param name="x" type="GLfloat" /> + <param name="y" type="GLfloat" /> + </function> + <function name="ProgramUniform3f" offset="assign"> + <param name="program" type="GLuint" /> + <param name="location" type="GLint" /> + <param name="x" type="GLfloat" /> + <param name="y" type="GLfloat" /> + <param name="z" type="GLfloat" /> + </function> + <function name="ProgramUniform4f" offset="assign"> + <param name="program" type="GLuint" /> + <param name="location" type="GLint" /> + <param name="x" type="GLfloat" /> + <param name="y" type="GLfloat" /> + <param name="z" type="GLfloat" /> + <param name="w" type="GLfloat" /> + </function> + <function name="ProgramUniform1iv" offset="assign"> + <param name="program" type="GLuint" /> + <param name="location" type="GLint" /> + <param name="count" type="GLsizei" /> + <param name="value" type="const GLint *" /> + </function> + <function name="ProgramUniform2iv" offset="assign"> + <param name="program" type="GLuint" /> + <param name="location" type="GLint" /> + <param name="count" type="GLsizei" /> + <param name="value" type="const GLint *" /> + </function> + <function name="ProgramUniform3iv" offset="assign"> + <param name="program" type="GLuint" /> + <param name="location" type="GLint" /> + <param name="count" type="GLsizei" /> + <param name="value" type="const GLint *" /> + </function> + <function name="ProgramUniform4iv" offset="assign"> + <param name="program" type="GLuint" /> + <param name="location" type="GLint" /> + <param name="count" type="GLsizei" /> + <param name="value" type="const GLint *" /> + </function> + <function name="ProgramUniform1uiv" offset="assign"> + <param name="program" type="GLuint" /> + <param name="location" type="GLint" /> + <param name="count" type="GLsizei" /> + <param name="value" type="const GLuint *" /> + </function> + <function name="ProgramUniform2uiv" offset="assign"> + <param name="program" type="GLuint" /> + <param name="location" type="GLint" /> + <param name="count" type="GLsizei" /> + <param name="value" type="const GLuint *" /> + </function> + <function name="ProgramUniform3uiv" offset="assign"> + <param name="program" type="GLuint" /> + <param name="location" type="GLint" /> + <param name="count" type="GLsizei" /> + <param name="value" type="const GLuint *" /> + </function> + <function name="ProgramUniform4uiv" offset="assign"> + <param name="program" type="GLuint" /> + <param name="location" type="GLint" /> + <param name="count" type="GLsizei" /> + <param name="value" type="const GLuint *" /> + </function> + <function name="ProgramUniform1fv" offset="assign"> + <param name="program" type="GLuint" /> + <param name="location" type="GLint" /> + <param name="count" type="GLsizei" /> + <param name="value" type="const GLfloat *" /> + </function> + <function name="ProgramUniform2fv" offset="assign"> + <param name="program" type="GLuint" /> + <param name="location" type="GLint" /> + <param name="count" type="GLsizei" /> + <param name="value" type="const GLfloat *" /> + </function> + <function name="ProgramUniform3fv" offset="assign"> + <param name="program" type="GLuint" /> + <param name="location" type="GLint" /> + <param name="count" type="GLsizei" /> + <param name="value" type="const GLfloat *" /> + </function> + <function name="ProgramUniform4fv" offset="assign"> + <param name="program" type="GLuint" /> + <param name="location" type="GLint" /> + <param name="count" type="GLsizei" /> + <param name="value" type="const GLfloat *" /> + </function> + <function name="ProgramUniformMatrix2fv" offset="assign"> + <param name="program" type="GLuint" /> + <param name="location" type="GLint" /> + <param name="count" type="GLsizei" /> + <param name="transpose" type="GLboolean" /> + <param name="value" type="const GLfloat *" /> + </function> + <function name="ProgramUniformMatrix3fv" offset="assign"> + <param name="program" type="GLuint" /> + <param name="location" type="GLint" /> + <param name="count" type="GLsizei" /> + <param name="transpose" type="GLboolean" /> + <param name="value" type="const GLfloat *" /> + </function> + <function name="ProgramUniformMatrix4fv" offset="assign"> + <param name="program" type="GLuint" /> + <param name="location" type="GLint" /> + <param name="count" type="GLsizei" /> + <param name="transpose" type="GLboolean" /> + <param name="value" type="const GLfloat *" /> + </function> + <function name="ProgramUniformMatrix2x3fv" offset="assign"> + <param name="program" type="GLuint" /> + <param name="location" type="GLint" /> + <param name="count" type="GLsizei" /> + <param name="transpose" type="GLboolean" /> + <param name="value" type="const GLfloat *" /> + </function> + <function name="ProgramUniformMatrix3x2fv" offset="assign"> + <param name="program" type="GLuint" /> + <param name="location" type="GLint" /> + <param name="count" type="GLsizei" /> + <param name="transpose" type="GLboolean" /> + <param name="value" type="const GLfloat *" /> + </function> + <function name="ProgramUniformMatrix2x4fv" offset="assign"> + <param name="program" type="GLuint" /> + <param name="location" type="GLint" /> + <param name="count" type="GLsizei" /> + <param name="transpose" type="GLboolean" /> + <param name="value" type="const GLfloat *" /> + </function> + <function name="ProgramUniformMatrix4x2fv" offset="assign"> + <param name="program" type="GLuint" /> + <param name="location" type="GLint" /> + <param name="count" type="GLsizei" /> + <param name="transpose" type="GLboolean" /> + <param name="value" type="const GLfloat *" /> + </function> + <function name="ProgramUniformMatrix3x4fv" offset="assign"> + <param name="program" type="GLuint" /> + <param name="location" type="GLint" /> + <param name="count" type="GLsizei" /> + <param name="transpose" type="GLboolean" /> + <param name="value" type="const GLfloat *" /> + </function> + <function name="ProgramUniformMatrix4x3fv" offset="assign"> + <param name="program" type="GLuint" /> + <param name="location" type="GLint" /> + <param name="count" type="GLsizei" /> + <param name="transpose" type="GLboolean" /> + <param name="value" type="const GLfloat *" /> + </function> + <function name="ValidateProgramPipeline" offset="assign"> + <param name="pipeline" type="GLuint" /> + </function> + <function name="GetProgramPipelineInfoLog" offset="assign"> + <param name="pipeline" type="GLuint" /> + <param name="bufSize" type="GLsizei" /> + <param name="length" type="GLsizei *" /> + <param name="infoLog" type="GLchar *" /> + </function> + + <!-- depends on GL_ARB_gpu_shader_fp64 + <function name="ProgramUniform1d" offset="assign"> + <param name="program" type="GLuint" /> + <param name="location" type="GLint" /> + <param name="x" type="GLdouble" /> + </function> + <function name="ProgramUniform2d" offset="assign"> + <param name="program" type="GLuint" /> + <param name="location" type="GLint" /> + <param name="x" type="GLdouble" /> + <param name="y" type="GLdouble" /> + </function> + <function name="ProgramUniform3d" offset="assign"> + <param name="program" type="GLuint" /> + <param name="location" type="GLint" /> + <param name="x" type="GLdouble" /> + <param name="y" type="GLdouble" /> + <param name="z" type="GLdouble" /> + </function> + <function name="ProgramUniform4d" offset="assign"> + <param name="program" type="GLuint" /> + <param name="location" type="GLint" /> + <param name="x" type="GLdouble" /> + <param name="y" type="GLdouble" /> + <param name="z" type="GLdouble" /> + <param name="w" type="GLdouble" /> + </function> + <function name="ProgramUniformMatrix2x3dv" offset="assign"> + <param name="program" type="GLuint" /> + <param name="location" type="GLint" /> + <param name="count" type="GLsizei" /> + <param name="transpose" type="GLboolean" /> + <param name="value" type="const GLdouble *" /> + </function> + <function name="ProgramUniformMatrix3x2dv" offset="assign"> + <param name="program" type="GLuint" /> + <param name="location" type="GLint" /> + <param name="count" type="GLsizei" /> + <param name="transpose" type="GLboolean" /> + <param name="value" type="const GLdouble *" /> + </function> + <function name="ProgramUniformMatrix2x4dv" offset="assign"> + <param name="program" type="GLuint" /> + <param name="location" type="GLint" /> + <param name="count" type="GLsizei" /> + <param name="transpose" type="GLboolean" /> + <param name="value" type="const GLdouble *" /> + </function> + <function name="ProgramUniformMatrix4x2dv" offset="assign"> + <param name="program" type="GLuint" /> + <param name="location" type="GLint" /> + <param name="count" type="GLsizei" /> + <param name="transpose" type="GLboolean" /> + <param name="value" type="const GLdouble *" /> + </function> + <function name="ProgramUniformMatrix3x4dv" offset="assign"> + <param name="program" type="GLuint" /> + <param name="location" type="GLint" /> + <param name="count" type="GLsizei" /> + <param name="transpose" type="GLboolean" /> + <param name="value" type="const GLdouble *" /> + </function> + <function name="ProgramUniformMatrix4x3dv" offset="assign"> + <param name="program" type="GLuint" /> + <param name="location" type="GLint" /> + <param name="count" type="GLsizei" /> + <param name="transpose" type="GLboolean" /> + <param name="value" type="const GLdouble *" /> + </function> + <function name="ProgramUniformMatrix2dv" offset="assign"> + <param name="program" type="GLuint" /> + <param name="location" type="GLint" /> + <param name="count" type="GLsizei" /> + <param name="transpose" type="GLboolean" /> + <param name="value" type="const GLdouble *" /> + </function> + <function name="ProgramUniformMatrix3dv" offset="assign"> + <param name="program" type="GLuint" /> + <param name="location" type="GLint" /> + <param name="count" type="GLsizei" /> + <param name="transpose" type="GLboolean" /> + <param name="value" type="const GLdouble *" /> + </function> + <function name="ProgramUniformMatrix4dv" offset="assign"> + <param name="program" type="GLuint" /> + <param name="location" type="GLint" /> + <param name="count" type="GLsizei" /> + <param name="transpose" type="GLboolean" /> + <param name="value" type="const GLdouble *" /> + </function> + <function name="ProgramUniform1dv" offset="assign"> + <param name="program" type="GLuint" /> + <param name="location" type="GLint" /> + <param name="count" type="GLsizei" /> + <param name="value" type="const GLdouble *" /> + </function> + <function name="ProgramUniform2dv" offset="assign"> + <param name="program" type="GLuint" /> + <param name="location" type="GLint" /> + <param name="count" type="GLsizei" /> + <param name="value" type="const GLdouble *" /> + </function> + <function name="ProgramUniform3dv" offset="assign"> + <param name="program" type="GLuint" /> + <param name="location" type="GLint" /> + <param name="count" type="GLsizei" /> + <param name="value" type="const GLdouble *" /> + </function> + <function name="ProgramUniform4dv" offset="assign"> + <param name="program" type="GLuint" /> + <param name="location" type="GLint" /> + <param name="count" type="GLsizei" /> + <param name="value" type="const GLdouble *" /> + </function> + --> + </category> +</OpenGLAPI> diff --git a/mesalib/src/mapi/glapi/gen/Makefile.am b/mesalib/src/mapi/glapi/gen/Makefile.am index 9e6fe5261..7b3c118f0 100644 --- a/mesalib/src/mapi/glapi/gen/Makefile.am +++ b/mesalib/src/mapi/glapi/gen/Makefile.am @@ -113,6 +113,7 @@ API_XML = \ ARB_sample_shading.xml \ ARB_sampler_objects.xml \ ARB_seamless_cube_map.xml \ + ARB_separate_shader_objects.xml \ ARB_shader_atomic_counters.xml \ ARB_shader_image_load_store.xml \ ARB_sync.xml \ diff --git a/mesalib/src/mapi/glapi/gen/NV_vdpau_interop.xml b/mesalib/src/mapi/glapi/gen/NV_vdpau_interop.xml index cf5f0eddd..0b19e1a85 100644 --- a/mesalib/src/mapi/glapi/gen/NV_vdpau_interop.xml +++ b/mesalib/src/mapi/glapi/gen/NV_vdpau_interop.xml @@ -29,6 +29,7 @@ </function> <function name="VDPAUIsSurfaceNV" offset="assign"> + <return type="GLboolean"/> <param name="surface" type="GLintptr"/> </function> diff --git a/mesalib/src/mapi/glapi/gen/glX_proto_recv.py b/mesalib/src/mapi/glapi/gen/glX_proto_recv.py index 42b85a525..d076409c2 100644 --- a/mesalib/src/mapi/glapi/gen/glX_proto_recv.py +++ b/mesalib/src/mapi/glapi/gen/glX_proto_recv.py @@ -92,7 +92,6 @@ class PrintGlxDispatchFunctions(glX_proto_common.glx_print_proto): print '#include "singlesize.h"' print '#include "glapi.h"' print '#include "glapitable.h"' - print '#include "glthread.h"' print '#include "dispatch.h"' print '' print '#define __GLX_PAD(x) (((x) + 3) & ~3)' diff --git a/mesalib/src/mapi/glapi/gen/glX_proto_send.py b/mesalib/src/mapi/glapi/gen/glX_proto_send.py index 8b804418b..a98f63e99 100644 --- a/mesalib/src/mapi/glapi/gen/glX_proto_send.py +++ b/mesalib/src/mapi/glapi/gen/glX_proto_send.py @@ -167,7 +167,6 @@ class PrintGlxProtoStubs(glX_proto_common.glx_print_proto): print '#include "glxclient.h"' print '#include "indirect_size.h"' print '#include "glapi.h"' - print '#include "glthread.h"' print '#include <GL/glxproto.h>' print '#include <X11/Xlib-xcb.h>' print '#include <xcb/xcb.h>' diff --git a/mesalib/src/mapi/glapi/gen/gl_API.xml b/mesalib/src/mapi/glapi/gen/gl_API.xml index 4ef754d5c..7e1946e22 100644 --- a/mesalib/src/mapi/glapi/gen/gl_API.xml +++ b/mesalib/src/mapi/glapi/gen/gl_API.xml @@ -8275,7 +8275,11 @@ </function> </category> -<!-- ARB extensions #95...#108 --> +<!-- ARB extensions #95...#96 --> + +<xi:include href="ARB_separate_shader_objects.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/> + +<!-- ARB extensions #98...#108 --> <xi:include href="ARB_ES2_compatibility.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/> @@ -8492,6 +8496,25 @@ <xi:include href="ARB_texture_storage_multisample.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/> +<!-- ARB extension 142 - 143. --> + +<category name="GL_ARB_buffer_storage" number="144"> + <enum name="MAP_PERSISTENT_BIT" value="0x40" /> + <enum name="MAP_COHERENT_BIT" value="0x80" /> + <enum name="DYNAMIC_STORAGE_BIT" value="0x100" /> + <enum name="CLIENT_STORAGE_BIT" value="0x200" /> + <enum name="BUFFER_IMMUTABLE_STORAGE" value="0x821F" /> + <enum name="BUFFER_STORAGE_FLAGS" value="0x8220" /> + <enum name="CLIENT_MAPPED_BUFFER_BARRIER_BIT" value="0x4000" /> + + <function name="BufferStorage" offset="assign"> + <param name="target" type="GLenum"/> + <param name="size" type="GLsizeiptr"/> + <param name="data" type="const GLvoid *"/> + <param name="flags" type="GLbitfield"/> + </function> +</category> + <!-- Non-ARB extensions sorted by extension number. --> <category name="GL_EXT_blend_color" number="2"> diff --git a/mesalib/src/mapi/glapi/gen/gl_genexec.py b/mesalib/src/mapi/glapi/gen/gl_genexec.py index 1765a51ad..460919397 100644 --- a/mesalib/src/mapi/glapi/gen/gl_genexec.py +++ b/mesalib/src/mapi/glapi/gen/gl_genexec.py @@ -86,6 +86,7 @@ header = """/** #include "main/multisample.h" #include "main/objectlabel.h" #include "main/performance_monitor.h" +#include "main/pipelineobj.h" #include "main/pixel.h" #include "main/pixelstore.h" #include "main/points.h" diff --git a/mesalib/src/mapi/glapi/glapi.h b/mesalib/src/mapi/glapi/glapi.h index c764271b0..dcf91a7f3 100644 --- a/mesalib/src/mapi/glapi/glapi.h +++ b/mesalib/src/mapi/glapi/glapi.h @@ -44,7 +44,7 @@ #ifndef _GLAPI_H #define _GLAPI_H -#include "glapi/glthread.h" +#include "u_thread.h" #ifdef __cplusplus diff --git a/mesalib/src/mapi/glapi/glthread.c b/mesalib/src/mapi/glapi/glthread.c deleted file mode 100644 index 00915380f..000000000 --- a/mesalib/src/mapi/glapi/glthread.c +++ /dev/null @@ -1,7 +0,0 @@ -#include "glapi/glapi.h" - -unsigned long -_glthread_GetID(void) -{ - return u_thread_self(); -} diff --git a/mesalib/src/mapi/glapi/glthread.h b/mesalib/src/mapi/glapi/glthread.h deleted file mode 100644 index 2399abb2b..000000000 --- a/mesalib/src/mapi/glapi/glthread.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef GLTHREAD_H -#define GLTHREAD_H - -#include "u_thread.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define _glthread_DECLARE_STATIC_MUTEX(name) u_mutex_declare_static(name) -#define _glthread_INIT_MUTEX(name) u_mutex_init(name) -#define _glthread_DESTROY_MUTEX(name) u_mutex_destroy(name) -#define _glthread_LOCK_MUTEX(name) u_mutex_lock(name) -#define _glthread_UNLOCK_MUTEX(name) u_mutex_unlock(name) - -#define _glthread_InitTSD(tsd) u_tsd_init(tsd); -#define _glthread_DestroyTSD(tsd) u_tsd_destroy(tsd); -#define _glthread_GetTSD(tsd) u_tsd_get(tsd); -#define _glthread_SetTSD(tsd, ptr) u_tsd_set(tsd, ptr); - -typedef struct u_tsd _glthread_TSD; -typedef u_mutex _glthread_Mutex; - -#ifdef __cplusplus -} -#endif - -#endif /* GLTHREAD_H */ diff --git a/mesalib/src/mesa/Makefile.sources b/mesalib/src/mesa/Makefile.sources index bd02d3ee8..f6f4062a4 100644 --- a/mesalib/src/mesa/Makefile.sources +++ b/mesalib/src/mesa/Makefile.sources @@ -69,6 +69,7 @@ MAIN_FILES = \ $(SRCDIR)main/pack.c \ $(SRCDIR)main/pbo.c \ $(SRCDIR)main/performance_monitor.c \ + $(SRCDIR)main/pipelineobj.c \ $(SRCDIR)main/pixel.c \ $(SRCDIR)main/pixelstore.c \ $(SRCDIR)main/pixeltransfer.c \ @@ -319,6 +320,7 @@ SPARC_FILES = \ COMMON_DRIVER_FILES = \ $(SRCDIR)drivers/common/driverfuncs.c \ + $(SRCDIR)drivers/common/meta_blit.c \ $(SRCDIR)drivers/common/meta.c diff --git a/mesalib/src/mesa/SConscript b/mesalib/src/mesa/SConscript index b52bbdc23..7f4e41983 100644 --- a/mesalib/src/mesa/SConscript +++ b/mesalib/src/mesa/SConscript @@ -98,6 +98,7 @@ main_sources = [ 'main/pack.c', 'main/pbo.c', 'main/performance_monitor.c', + 'main/pipelineobj.c', 'main/pixel.c', 'main/pixelstore.c', 'main/pixeltransfer.c', @@ -325,6 +326,7 @@ program_sources = [ common_driver_sources = [ 'drivers/common/driverfuncs.c', 'drivers/common/meta.c', + 'drivers/common/meta_blit.c' ] mesa_sources = ( diff --git a/mesalib/src/mesa/drivers/common/meta.c b/mesalib/src/mesa/drivers/common/meta.c index f12bcaab1..cde34f99f 100644 --- a/mesalib/src/mesa/drivers/common/meta.c +++ b/mesalib/src/mesa/drivers/common/meta.c @@ -51,6 +51,8 @@ #include "main/macros.h" #include "main/matrix.h" #include "main/mipmap.h" +#include "main/multisample.h" +#include "main/objectlabel.h" #include "main/pixel.h" #include "main/pbo.h" #include "main/polygon.h" @@ -82,283 +84,18 @@ /** Return offset in bytes of the field within a vertex struct */ #define OFFSET(FIELD) ((void *) offsetof(struct vertex, FIELD)) -/** - * State which we may save/restore across meta ops. - * XXX this may be incomplete... - */ -struct save_state -{ - GLbitfield SavedState; /**< bitmask of MESA_META_* flags */ - - /** MESA_META_CLEAR (and others?) */ - struct gl_query_object *CurrentOcclusionObject; - - /** MESA_META_ALPHA_TEST */ - GLboolean AlphaEnabled; - GLenum AlphaFunc; - GLclampf AlphaRef; - - /** MESA_META_BLEND */ - GLbitfield BlendEnabled; - GLboolean ColorLogicOpEnabled; - - /** MESA_META_COLOR_MASK */ - GLubyte ColorMask[MAX_DRAW_BUFFERS][4]; - - /** MESA_META_DEPTH_TEST */ - struct gl_depthbuffer_attrib Depth; - - /** MESA_META_FOG */ - GLboolean Fog; - - /** MESA_META_PIXEL_STORE */ - struct gl_pixelstore_attrib Pack, Unpack; - - /** MESA_META_PIXEL_TRANSFER */ - GLfloat RedBias, RedScale; - GLfloat GreenBias, GreenScale; - GLfloat BlueBias, BlueScale; - GLfloat AlphaBias, AlphaScale; - GLfloat DepthBias, DepthScale; - GLboolean MapColorFlag; - - /** MESA_META_RASTERIZATION */ - GLenum FrontPolygonMode, BackPolygonMode; - GLboolean PolygonOffset; - GLboolean PolygonSmooth; - GLboolean PolygonStipple; - GLboolean PolygonCull; - - /** MESA_META_SCISSOR */ - struct gl_scissor_attrib Scissor; - - /** MESA_META_SHADER */ - GLboolean VertexProgramEnabled; - struct gl_vertex_program *VertexProgram; - GLboolean FragmentProgramEnabled; - struct gl_fragment_program *FragmentProgram; - GLboolean ATIFragmentShaderEnabled; - struct gl_shader_program *Shader[MESA_SHADER_STAGES]; - struct gl_shader_program *ActiveShader; - - /** MESA_META_STENCIL_TEST */ - struct gl_stencil_attrib Stencil; - - /** MESA_META_TRANSFORM */ - GLenum MatrixMode; - GLfloat ModelviewMatrix[16]; - GLfloat ProjectionMatrix[16]; - GLfloat TextureMatrix[16]; - - /** MESA_META_CLIP */ - GLbitfield ClipPlanesEnabled; - - /** MESA_META_TEXTURE */ - GLuint ActiveUnit; - GLuint ClientActiveUnit; - /** for unit[0] only */ - struct gl_texture_object *CurrentTexture[NUM_TEXTURE_TARGETS]; - /** mask of TEXTURE_2D_BIT, etc */ - GLbitfield TexEnabled[MAX_TEXTURE_UNITS]; - GLbitfield TexGenEnabled[MAX_TEXTURE_UNITS]; - GLuint EnvMode; /* unit[0] only */ - - /** MESA_META_VERTEX */ - struct gl_vertex_array_object *VAO; - struct gl_buffer_object *ArrayBufferObj; - - /** MESA_META_VIEWPORT */ - GLfloat ViewportX, ViewportY, ViewportW, ViewportH; - GLclampd DepthNear, DepthFar; - - /** MESA_META_CLAMP_FRAGMENT_COLOR */ - GLenum ClampFragmentColor; - - /** MESA_META_CLAMP_VERTEX_COLOR */ - GLenum ClampVertexColor; - - /** MESA_META_CONDITIONAL_RENDER */ - struct gl_query_object *CondRenderQuery; - GLenum CondRenderMode; - - /** MESA_META_SELECT_FEEDBACK */ - GLenum RenderMode; - struct gl_selection Select; - struct gl_feedback Feedback; - - /** MESA_META_MULTISAMPLE */ - GLboolean MultisampleEnabled; - - /** MESA_META_FRAMEBUFFER_SRGB */ - GLboolean sRGBEnabled; - - /** Miscellaneous (always disabled) */ - GLboolean Lighting; - GLboolean RasterDiscard; - GLboolean TransformFeedbackNeedsResume; -}; - -/** - * Temporary texture used for glBlitFramebuffer, glDrawPixels, etc. - * This is currently shared by all the meta ops. But we could create a - * separate one for each of glDrawPixel, glBlitFramebuffer, glCopyPixels, etc. - */ -struct temp_texture -{ - GLuint TexObj; - GLenum Target; /**< GL_TEXTURE_2D or GL_TEXTURE_RECTANGLE */ - GLsizei MinSize; /**< Min texture size to allocate */ - GLsizei MaxSize; /**< Max possible texture size */ - GLboolean NPOT; /**< Non-power of two size OK? */ - GLsizei Width, Height; /**< Current texture size */ - GLenum IntFormat; - GLfloat Sright, Ttop; /**< right, top texcoords */ -}; - - -/** - * State for glBlitFramebufer() - */ -struct blit_state -{ - GLuint VAO; - GLuint VBO; - GLuint DepthFP; - GLuint ShaderProg; - GLuint RectShaderProg; - struct temp_texture depthTex; -}; - - -/** - * State for glClear() - */ -struct clear_state -{ - GLuint VAO; - GLuint VBO; - GLuint ShaderProg; - GLint ColorLocation; - GLint LayerLocation; - - GLuint IntegerShaderProg; - GLint IntegerColorLocation; - GLint IntegerLayerLocation; -}; +static struct blit_shader * +choose_blit_shader(GLenum target, struct blit_shader_table *table); - -/** - * State for glCopyPixels() - */ -struct copypix_state -{ - GLuint VAO; - GLuint VBO; -}; - - -/** - * State for glDrawPixels() - */ -struct drawpix_state -{ - GLuint VAO; - - GLuint StencilFP; /**< Fragment program for drawing stencil images */ - GLuint DepthFP; /**< Fragment program for drawing depth images */ -}; - - -/** - * State for glBitmap() - */ -struct bitmap_state -{ - GLuint VAO; - GLuint VBO; - struct temp_texture Tex; /**< separate texture from other meta ops */ -}; - -/** - * State for GLSL texture sampler which is used to generate fragment - * shader in _mesa_meta_generate_mipmap(). - */ -struct glsl_sampler { - const char *type; - const char *func; - const char *texcoords; - GLuint shader_prog; -}; - -/** - * State for _mesa_meta_generate_mipmap() - */ -struct gen_mipmap_state -{ - GLuint VAO; - GLuint VBO; - GLuint FBO; - GLuint Sampler; - GLuint ShaderProg; - struct glsl_sampler sampler_1d; - struct glsl_sampler sampler_2d; - struct glsl_sampler sampler_3d; - struct glsl_sampler sampler_cubemap; - struct glsl_sampler sampler_1d_array; - struct glsl_sampler sampler_2d_array; -}; - -/** - * State for texture decompression - */ -struct decompress_state -{ - GLuint VAO; - GLuint VBO, FBO, RBO, Sampler; - GLint Width, Height; -}; - -/** - * State for glDrawTex() - */ -struct drawtex_state -{ - GLuint VAO; - GLuint VBO; -}; - -#define MAX_META_OPS_DEPTH 8 -/** - * All per-context meta state. - */ -struct gl_meta_state -{ - /** Stack of state saved during meta-ops */ - struct save_state Save[MAX_META_OPS_DEPTH]; - /** Save stack depth */ - GLuint SaveStackDepth; - - struct temp_texture TempTex; - - struct blit_state Blit; /**< For _mesa_meta_BlitFramebuffer() */ - struct clear_state Clear; /**< For _mesa_meta_Clear() */ - struct copypix_state CopyPix; /**< For _mesa_meta_CopyPixels() */ - struct drawpix_state DrawPix; /**< For _mesa_meta_DrawPixels() */ - struct bitmap_state Bitmap; /**< For _mesa_meta_Bitmap() */ - struct gen_mipmap_state Mipmap; /**< For _mesa_meta_GenerateMipmap() */ - struct decompress_state Decompress; /**< For texture decompression */ - struct drawtex_state DrawTex; /**< For _mesa_meta_DrawTex() */ -}; - -static void meta_glsl_blit_cleanup(struct blit_state *blit); static void cleanup_temp_texture(struct temp_texture *tex); static void meta_glsl_clear_cleanup(struct clear_state *clear); static void meta_glsl_generate_mipmap_cleanup(struct gen_mipmap_state *mipmap); static void meta_decompress_cleanup(struct decompress_state *decompress); static void meta_drawpix_cleanup(struct drawpix_state *drawpix); -static GLuint -compile_shader_with_debug(struct gl_context *ctx, GLenum target, const GLcharARB *source) +GLuint +_mesa_meta_compile_shader_with_debug(struct gl_context *ctx, GLenum target, + const GLcharARB *source) { GLuint shader; GLint ok, size; @@ -384,7 +121,7 @@ compile_shader_with_debug(struct gl_context *ctx, GLenum target, const GLcharARB return 0; } - _mesa_GetProgramInfoLog(shader, size, NULL, info); + _mesa_GetShaderInfoLog(shader, size, NULL, info); _mesa_problem(ctx, "meta program compile failed:\n%s\n" "source:\n%s\n", @@ -396,8 +133,8 @@ compile_shader_with_debug(struct gl_context *ctx, GLenum target, const GLcharARB return 0; } -static GLuint -link_program_with_debug(struct gl_context *ctx, GLuint program) +GLuint +_mesa_meta_link_program_with_debug(struct gl_context *ctx, GLuint program) { GLint ok, size; GLchar *info; @@ -425,6 +162,182 @@ link_program_with_debug(struct gl_context *ctx, GLuint program) } /** + * Generate a generic shader to blit from a texture to a framebuffer + * + * \param ctx Current GL context + * \param texTarget Texture target that will be the source of the blit + * + * \returns a handle to a shader program on success or zero on failure. + */ +void +_mesa_meta_setup_blit_shader(struct gl_context *ctx, + GLenum target, + struct blit_shader_table *table) +{ + const char *vs_source; + char *fs_source; + GLuint vs, fs; + void *const mem_ctx = ralloc_context(NULL); + struct blit_shader *shader = choose_blit_shader(target, table); + char *name; + + assert(shader != NULL); + + if (shader->shader_prog != 0) { + _mesa_UseProgram(shader->shader_prog); + return; + } + + if (ctx->Const.GLSLVersion < 130) { + vs_source = + "attribute vec2 position;\n" + "attribute vec4 textureCoords;\n" + "varying vec4 texCoords;\n" + "void main()\n" + "{\n" + " texCoords = textureCoords;\n" + " gl_Position = vec4(position, 0.0, 1.0);\n" + "}\n"; + + fs_source = ralloc_asprintf(mem_ctx, + "#extension GL_EXT_texture_array : enable\n" + "#extension GL_ARB_texture_cube_map_array: enable\n" + "uniform %s texSampler;\n" + "varying vec4 texCoords;\n" + "void main()\n" + "{\n" + " gl_FragColor = %s(texSampler, %s);\n" + " gl_FragDepth = gl_FragColor.x;\n" + "}\n", + shader->type, + shader->func, shader->texcoords); + } + else { + vs_source = ralloc_asprintf(mem_ctx, + "#version 130\n" + "in vec2 position;\n" + "in vec4 textureCoords;\n" + "out vec4 texCoords;\n" + "void main()\n" + "{\n" + " texCoords = textureCoords;\n" + " gl_Position = vec4(position, 0.0, 1.0);\n" + "}\n"); + fs_source = ralloc_asprintf(mem_ctx, + "#version 130\n" + "#extension GL_ARB_texture_cube_map_array: enable\n" + "uniform %s texSampler;\n" + "in vec4 texCoords;\n" + "out vec4 out_color;\n" + "\n" + "void main()\n" + "{\n" + " out_color = texture(texSampler, %s);\n" + " gl_FragDepth = out_color.x;\n" + "}\n", + shader->type, + shader->texcoords); + } + + vs = _mesa_meta_compile_shader_with_debug(ctx, GL_VERTEX_SHADER, vs_source); + fs = _mesa_meta_compile_shader_with_debug(ctx, GL_FRAGMENT_SHADER, fs_source); + + shader->shader_prog = _mesa_CreateProgramObjectARB(); + _mesa_AttachShader(shader->shader_prog, fs); + _mesa_DeleteObjectARB(fs); + _mesa_AttachShader(shader->shader_prog, vs); + _mesa_DeleteObjectARB(vs); + _mesa_BindAttribLocation(shader->shader_prog, 0, "position"); + _mesa_BindAttribLocation(shader->shader_prog, 1, "texcoords"); + _mesa_meta_link_program_with_debug(ctx, shader->shader_prog); + name = ralloc_asprintf(mem_ctx, "%s blit", shader->type); + _mesa_ObjectLabel(GL_PROGRAM, shader->shader_prog, -1, name); + ralloc_free(mem_ctx); + + _mesa_UseProgram(shader->shader_prog); +} + +/** + * Configure vertex buffer and vertex array objects for tests + * + * Regardless of whether a new VAO and new VBO are created, the objects + * referenced by \c VAO and \c VBO will be bound into the GL state vector + * when this function terminates. + * + * \param VAO Storage for vertex array object handle. If 0, a new VAO + * will be created. + * \param VBO Storage for vertex buffer object handle. If 0, a new VBO + * will be created. The new VBO will have storage for 4 + * \c vertex structures. + * \param use_generic_attributes Should generic attributes 0 and 1 be used, + * or should traditional, fixed-function color and texture + * coordinate be used? + * \param vertex_size Number of components for attribute 0 / vertex. + * \param texcoord_size Number of components for attribute 1 / texture + * coordinate. If this is 0, attribute 1 will not be set or + * enabled. + * \param color_size Number of components for attribute 1 / primary color. + * If this is 0, attribute 1 will not be set or enabled. + * + * \note If \c use_generic_attributes is \c true, \c color_size must be zero. + * Use \c texcoord_size instead. + */ +void +_mesa_meta_setup_vertex_objects(GLuint *VAO, GLuint *VBO, + bool use_generic_attributes, + unsigned vertex_size, unsigned texcoord_size, + unsigned color_size) +{ + if (*VAO == 0) { + assert(*VBO == 0); + + /* create vertex array object */ + _mesa_GenVertexArrays(1, VAO); + _mesa_BindVertexArray(*VAO); + + /* create vertex array buffer */ + _mesa_GenBuffers(1, VBO); + _mesa_BindBuffer(GL_ARRAY_BUFFER, *VBO); + _mesa_BufferData(GL_ARRAY_BUFFER, 4 * sizeof(struct vertex), NULL, + GL_DYNAMIC_DRAW); + + /* setup vertex arrays */ + if (use_generic_attributes) { + assert(color_size == 0); + + _mesa_VertexAttribPointer(0, vertex_size, GL_FLOAT, GL_FALSE, + sizeof(struct vertex), OFFSET(x)); + _mesa_EnableVertexAttribArray(0); + + if (texcoord_size > 0) { + _mesa_VertexAttribPointer(1, texcoord_size, GL_FLOAT, GL_FALSE, + sizeof(struct vertex), OFFSET(tex)); + _mesa_EnableVertexAttribArray(1); + } + } else { + _mesa_VertexPointer(vertex_size, GL_FLOAT, sizeof(struct vertex), + OFFSET(x)); + _mesa_EnableClientState(GL_VERTEX_ARRAY); + + if (texcoord_size > 0) { + _mesa_TexCoordPointer(texcoord_size, GL_FLOAT, + sizeof(struct vertex), OFFSET(tex)); + _mesa_EnableClientState(GL_TEXTURE_COORD_ARRAY); + } + + if (color_size > 0) { + _mesa_ColorPointer(color_size, GL_FLOAT, + sizeof(struct vertex), OFFSET(r)); + _mesa_EnableClientState(GL_COLOR_ARRAY); + } + } + } else { + _mesa_BindVertexArray(*VAO); + _mesa_BindBuffer(GL_ARRAY_BUFFER, *VBO); + } +} + +/** * Initialize meta-ops for a context. * To be called once during context creation. */ @@ -446,7 +359,7 @@ _mesa_meta_free(struct gl_context *ctx) { GET_CURRENT_CONTEXT(old_context); _mesa_make_current(ctx, NULL, NULL); - meta_glsl_blit_cleanup(&ctx->Meta->Blit); + _mesa_meta_glsl_blit_cleanup(&ctx->Meta->Blit); meta_glsl_clear_cleanup(&ctx->Meta->Clear); meta_glsl_generate_mipmap_cleanup(&ctx->Meta->Mipmap); cleanup_temp_texture(&ctx->Meta->TempTex); @@ -480,6 +393,13 @@ _mesa_meta_begin(struct gl_context *ctx, GLbitfield state) memset(save, 0, sizeof(*save)); save->SavedState = state; + /* We always push into desktop GL mode and pop out at the end. No sense in + * writing our shaders varying based on the user's context choice, when + * Mesa can handle either. + */ + save->API = ctx->API; + ctx->API = API_OPENGL_COMPAT; + /* Pausing transform feedback needs to be done early, or else we won't be * able to change other state. */ @@ -539,9 +459,7 @@ _mesa_meta_begin(struct gl_context *ctx, GLbitfield state) _mesa_set_enable(ctx, GL_DEPTH_TEST, GL_FALSE); } - if ((state & MESA_META_FOG) - && ctx->API != API_OPENGL_CORE - && ctx->API != API_OPENGLES2) { + if (state & MESA_META_FOG) { save->Fog = ctx->Fog.Enabled; if (ctx->Fog.Enabled) _mesa_set_enable(ctx, GL_FOG, GL_FALSE); @@ -586,10 +504,8 @@ _mesa_meta_begin(struct gl_context *ctx, GLbitfield state) save->PolygonCull = ctx->Polygon.CullFlag; _mesa_PolygonMode(GL_FRONT_AND_BACK, GL_FILL); _mesa_set_enable(ctx, GL_POLYGON_OFFSET_FILL, GL_FALSE); - if (ctx->API == API_OPENGL_COMPAT) { - _mesa_set_enable(ctx, GL_POLYGON_SMOOTH, GL_FALSE); - _mesa_set_enable(ctx, GL_POLYGON_STIPPLE, GL_FALSE); - } + _mesa_set_enable(ctx, GL_POLYGON_SMOOTH, GL_FALSE); + _mesa_set_enable(ctx, GL_POLYGON_STIPPLE, GL_FALSE); _mesa_set_enable(ctx, GL_CULL_FACE, GL_FALSE); } @@ -601,21 +517,21 @@ _mesa_meta_begin(struct gl_context *ctx, GLbitfield state) if (state & MESA_META_SHADER) { int i; - if (ctx->API == API_OPENGL_COMPAT && ctx->Extensions.ARB_vertex_program) { + if (ctx->Extensions.ARB_vertex_program) { save->VertexProgramEnabled = ctx->VertexProgram.Enabled; _mesa_reference_vertprog(ctx, &save->VertexProgram, ctx->VertexProgram.Current); _mesa_set_enable(ctx, GL_VERTEX_PROGRAM_ARB, GL_FALSE); } - if (ctx->API == API_OPENGL_COMPAT && ctx->Extensions.ARB_fragment_program) { + if (ctx->Extensions.ARB_fragment_program) { save->FragmentProgramEnabled = ctx->FragmentProgram.Enabled; _mesa_reference_fragprog(ctx, &save->FragmentProgram, ctx->FragmentProgram.Current); _mesa_set_enable(ctx, GL_FRAGMENT_PROGRAM_ARB, GL_FALSE); } - if (ctx->API == API_OPENGL_COMPAT && ctx->Extensions.ATI_fragment_shader) { + if (ctx->Extensions.ATI_fragment_shader) { save->ATIFragmentShaderEnabled = ctx->ATIFragmentShader.Enabled; _mesa_set_enable(ctx, GL_FRAGMENT_SHADER_ATI, GL_FALSE); } @@ -645,33 +561,24 @@ _mesa_meta_begin(struct gl_context *ctx, GLbitfield state) save->EnvMode = ctx->Texture.Unit[0].EnvMode; /* Disable all texture units */ - if (ctx->API == API_OPENGL_COMPAT || ctx->API == API_OPENGLES) { - for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { - save->TexEnabled[u] = ctx->Texture.Unit[u].Enabled; - save->TexGenEnabled[u] = ctx->Texture.Unit[u].TexGenEnabled; - if (ctx->Texture.Unit[u].Enabled || - ctx->Texture.Unit[u].TexGenEnabled) { - _mesa_ActiveTexture(GL_TEXTURE0 + u); - _mesa_set_enable(ctx, GL_TEXTURE_2D, GL_FALSE); - if (ctx->Extensions.ARB_texture_cube_map) - _mesa_set_enable(ctx, GL_TEXTURE_CUBE_MAP, GL_FALSE); - if (_mesa_is_gles(ctx) && - ctx->Extensions.OES_EGL_image_external) - _mesa_set_enable(ctx, GL_TEXTURE_EXTERNAL_OES, GL_FALSE); - - if (ctx->API == API_OPENGL_COMPAT) { - _mesa_set_enable(ctx, GL_TEXTURE_1D, GL_FALSE); - _mesa_set_enable(ctx, GL_TEXTURE_3D, GL_FALSE); - if (ctx->Extensions.NV_texture_rectangle) - _mesa_set_enable(ctx, GL_TEXTURE_RECTANGLE, GL_FALSE); - _mesa_set_enable(ctx, GL_TEXTURE_GEN_S, GL_FALSE); - _mesa_set_enable(ctx, GL_TEXTURE_GEN_T, GL_FALSE); - _mesa_set_enable(ctx, GL_TEXTURE_GEN_R, GL_FALSE); - _mesa_set_enable(ctx, GL_TEXTURE_GEN_Q, GL_FALSE); - } else { - _mesa_set_enable(ctx, GL_TEXTURE_GEN_STR_OES, GL_FALSE); - } - } + for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { + save->TexEnabled[u] = ctx->Texture.Unit[u].Enabled; + save->TexGenEnabled[u] = ctx->Texture.Unit[u].TexGenEnabled; + if (ctx->Texture.Unit[u].Enabled || + ctx->Texture.Unit[u].TexGenEnabled) { + _mesa_ActiveTexture(GL_TEXTURE0 + u); + _mesa_set_enable(ctx, GL_TEXTURE_2D, GL_FALSE); + if (ctx->Extensions.ARB_texture_cube_map) + _mesa_set_enable(ctx, GL_TEXTURE_CUBE_MAP, GL_FALSE); + + _mesa_set_enable(ctx, GL_TEXTURE_1D, GL_FALSE); + _mesa_set_enable(ctx, GL_TEXTURE_3D, GL_FALSE); + if (ctx->Extensions.NV_texture_rectangle) + _mesa_set_enable(ctx, GL_TEXTURE_RECTANGLE, GL_FALSE); + _mesa_set_enable(ctx, GL_TEXTURE_GEN_S, GL_FALSE); + _mesa_set_enable(ctx, GL_TEXTURE_GEN_T, GL_FALSE); + _mesa_set_enable(ctx, GL_TEXTURE_GEN_R, GL_FALSE); + _mesa_set_enable(ctx, GL_TEXTURE_GEN_Q, GL_FALSE); } } @@ -684,9 +591,7 @@ _mesa_meta_begin(struct gl_context *ctx, GLbitfield state) /* set defaults for unit[0] */ _mesa_ActiveTexture(GL_TEXTURE0); _mesa_ClientActiveTexture(GL_TEXTURE0); - if (ctx->API == API_OPENGL_COMPAT || ctx->API == API_OPENGLES) { - _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - } + _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); } if (state & MESA_META_TRANSFORM) { @@ -799,9 +704,20 @@ _mesa_meta_begin(struct gl_context *ctx, GLbitfield state) } if (state & MESA_META_MULTISAMPLE) { - save->MultisampleEnabled = ctx->Multisample.Enabled; + save->Multisample = ctx->Multisample; /* struct copy */ + if (ctx->Multisample.Enabled) _mesa_set_multisample(ctx, GL_FALSE); + if (ctx->Multisample.SampleCoverage) + _mesa_set_enable(ctx, GL_SAMPLE_COVERAGE, GL_FALSE); + if (ctx->Multisample.SampleAlphaToCoverage) + _mesa_set_enable(ctx, GL_SAMPLE_ALPHA_TO_COVERAGE, GL_FALSE); + if (ctx->Multisample.SampleAlphaToOne) + _mesa_set_enable(ctx, GL_SAMPLE_ALPHA_TO_ONE, GL_FALSE); + if (ctx->Multisample.SampleShading) + _mesa_set_enable(ctx, GL_SAMPLE_SHADING, GL_FALSE); + if (ctx->Multisample.SampleMask) + _mesa_set_enable(ctx, GL_SAMPLE_MASK, GL_FALSE); } if (state & MESA_META_FRAMEBUFFER_SRGB) { @@ -892,9 +808,7 @@ _mesa_meta_end(struct gl_context *ctx) _mesa_DepthMask(save->Depth.Mask); } - if ((state & MESA_META_FOG) - && ctx->API != API_OPENGL_CORE - && ctx->API != API_OPENGLES2) { + if (state & MESA_META_FOG) { _mesa_set_enable(ctx, GL_FOG, save->Fog); } @@ -918,18 +832,10 @@ _mesa_meta_end(struct gl_context *ctx) } if (state & MESA_META_RASTERIZATION) { - /* Core context requires that front and back mode be the same. - */ - if (ctx->API == API_OPENGL_CORE) { - _mesa_PolygonMode(GL_FRONT_AND_BACK, save->FrontPolygonMode); - } else { - _mesa_PolygonMode(GL_FRONT, save->FrontPolygonMode); - _mesa_PolygonMode(GL_BACK, save->BackPolygonMode); - } - if (ctx->API == API_OPENGL_COMPAT) { - _mesa_set_enable(ctx, GL_POLYGON_STIPPLE, save->PolygonStipple); - _mesa_set_enable(ctx, GL_POLYGON_SMOOTH, save->PolygonSmooth); - } + _mesa_PolygonMode(GL_FRONT, save->FrontPolygonMode); + _mesa_PolygonMode(GL_BACK, save->BackPolygonMode); + _mesa_set_enable(ctx, GL_POLYGON_STIPPLE, save->PolygonStipple); + _mesa_set_enable(ctx, GL_POLYGON_SMOOTH, save->PolygonSmooth); _mesa_set_enable(ctx, GL_POLYGON_OFFSET_FILL, save->PolygonOffset); _mesa_set_enable(ctx, GL_CULL_FACE, save->PolygonCull); } @@ -949,7 +855,7 @@ _mesa_meta_end(struct gl_context *ctx) } if (state & MESA_META_SHADER) { - if (ctx->API == API_OPENGL_COMPAT && ctx->Extensions.ARB_vertex_program) { + if (ctx->Extensions.ARB_vertex_program) { _mesa_set_enable(ctx, GL_VERTEX_PROGRAM_ARB, save->VertexProgramEnabled); _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current, @@ -957,7 +863,7 @@ _mesa_meta_end(struct gl_context *ctx) _mesa_reference_vertprog(ctx, &save->VertexProgram, NULL); } - if (ctx->API == API_OPENGL_COMPAT && ctx->Extensions.ARB_fragment_program) { + if (ctx->Extensions.ARB_fragment_program) { _mesa_set_enable(ctx, GL_FRAGMENT_PROGRAM_ARB, save->FragmentProgramEnabled); _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current, @@ -965,7 +871,7 @@ _mesa_meta_end(struct gl_context *ctx) _mesa_reference_fragprog(ctx, &save->FragmentProgram, NULL); } - if (ctx->API == API_OPENGL_COMPAT && ctx->Extensions.ATI_fragment_shader) { + if (ctx->Extensions.ATI_fragment_shader) { _mesa_set_enable(ctx, GL_FRAGMENT_SHADER_ATI, save->ATIFragmentShaderEnabled); } @@ -996,7 +902,7 @@ _mesa_meta_end(struct gl_context *ctx) _mesa_set_enable(ctx, GL_STENCIL_TEST, stencil->Enabled); _mesa_ClearStencil(stencil->Clear); - if (ctx->API == API_OPENGL_COMPAT && ctx->Extensions.EXT_stencil_two_side) { + if (ctx->Extensions.EXT_stencil_two_side) { _mesa_set_enable(ctx, GL_STENCIL_TEST_TWO_SIDE_EXT, stencil->TestTwoSide); _mesa_ActiveStencilFaceEXT(stencil->ActiveFace @@ -1028,9 +934,7 @@ _mesa_meta_end(struct gl_context *ctx) ASSERT(ctx->Texture.CurrentUnit == 0); /* restore texenv for unit[0] */ - if (ctx->API == API_OPENGL_COMPAT || ctx->API == API_OPENGLES) { - _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, save->EnvMode); - } + _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, save->EnvMode); /* restore texture objects for unit[0] only */ for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++) { @@ -1043,17 +947,15 @@ _mesa_meta_end(struct gl_context *ctx) } /* Restore fixed function texture enables, texgen */ - if (ctx->API == API_OPENGL_COMPAT || ctx->API == API_OPENGLES) { - for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { - if (ctx->Texture.Unit[u].Enabled != save->TexEnabled[u]) { - FLUSH_VERTICES(ctx, _NEW_TEXTURE); - ctx->Texture.Unit[u].Enabled = save->TexEnabled[u]; - } + for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { + if (ctx->Texture.Unit[u].Enabled != save->TexEnabled[u]) { + FLUSH_VERTICES(ctx, _NEW_TEXTURE); + ctx->Texture.Unit[u].Enabled = save->TexEnabled[u]; + } - if (ctx->Texture.Unit[u].TexGenEnabled != save->TexGenEnabled[u]) { - FLUSH_VERTICES(ctx, _NEW_TEXTURE); - ctx->Texture.Unit[u].TexGenEnabled = save->TexGenEnabled[u]; - } + if (ctx->Texture.Unit[u].TexGenEnabled != save->TexGenEnabled[u]) { + FLUSH_VERTICES(ctx, _NEW_TEXTURE); + ctx->Texture.Unit[u].TexGenEnabled = save->TexGenEnabled[u]; } } @@ -1137,8 +1039,30 @@ _mesa_meta_end(struct gl_context *ctx) } if (state & MESA_META_MULTISAMPLE) { - if (ctx->Multisample.Enabled != save->MultisampleEnabled) - _mesa_set_multisample(ctx, save->MultisampleEnabled); + struct gl_multisample_attrib *ctx_ms = &ctx->Multisample; + struct gl_multisample_attrib *save_ms = &save->Multisample; + + if (ctx_ms->Enabled != save_ms->Enabled) + _mesa_set_multisample(ctx, save_ms->Enabled); + if (ctx_ms->SampleCoverage != save_ms->SampleCoverage) + _mesa_set_enable(ctx, GL_SAMPLE_COVERAGE, save_ms->SampleCoverage); + if (ctx_ms->SampleAlphaToCoverage != save_ms->SampleAlphaToCoverage) + _mesa_set_enable(ctx, GL_SAMPLE_ALPHA_TO_COVERAGE, save_ms->SampleAlphaToCoverage); + if (ctx_ms->SampleAlphaToOne != save_ms->SampleAlphaToOne) + _mesa_set_enable(ctx, GL_SAMPLE_ALPHA_TO_ONE, save_ms->SampleAlphaToOne); + if (ctx_ms->SampleCoverageValue != save_ms->SampleCoverageValue || + ctx_ms->SampleCoverageInvert != save_ms->SampleCoverageInvert) { + _mesa_SampleCoverage(save_ms->SampleCoverageValue, + save_ms->SampleCoverageInvert); + } + if (ctx_ms->SampleShading != save_ms->SampleShading) + _mesa_set_enable(ctx, GL_SAMPLE_SHADING, save_ms->SampleShading); + if (ctx_ms->SampleMask != save_ms->SampleMask) + _mesa_set_enable(ctx, GL_SAMPLE_MASK, save_ms->SampleMask); + if (ctx_ms->SampleMaskValue != save_ms->SampleMaskValue) + _mesa_SampleMaski(0, save_ms->SampleMaskValue); + if (ctx_ms->MinSampleShadingValue != save_ms->MinSampleShadingValue) + _mesa_MinSampleShading(save_ms->MinSampleShadingValue); } if (state & MESA_META_FRAMEBUFFER_SRGB) { @@ -1157,6 +1081,8 @@ _mesa_meta_end(struct gl_context *ctx) _mesa_ResumeTransformFeedback(); ctx->Meta->SaveStackDepth--; + + ctx->API = save->API; } @@ -1224,8 +1150,8 @@ cleanup_temp_texture(struct temp_texture *tex) * Return pointer to temp_texture info for non-bitmap ops. * This does some one-time init if needed. */ -static struct temp_texture * -get_temp_texture(struct gl_context *ctx) +struct temp_texture * +_mesa_meta_get_temp_texture(struct gl_context *ctx) { struct temp_texture *tex = &ctx->Meta->TempTex; @@ -1258,8 +1184,8 @@ get_bitmap_temp_texture(struct gl_context *ctx) * Return pointer to depth temp_texture. * This does some one-time init if needed. */ -static struct temp_texture * -get_temp_depth_texture(struct gl_context *ctx) +struct temp_texture * +_mesa_meta_get_temp_depth_texture(struct gl_context *ctx) { struct temp_texture *tex = &ctx->Meta->Blit.depthTex; @@ -1279,9 +1205,9 @@ get_temp_depth_texture(struct gl_context *ctx) * * \return GL_TRUE if new texture is needed, GL_FALSE otherwise */ -static GLboolean -alloc_texture(struct temp_texture *tex, - GLsizei width, GLsizei height, GLenum intFormat) +GLboolean +_mesa_meta_alloc_texture(struct temp_texture *tex, + GLsizei width, GLsizei height, GLenum intFormat) { GLboolean newTex = GL_FALSE; @@ -1332,19 +1258,22 @@ alloc_texture(struct temp_texture *tex, /** * Setup/load texture for glCopyPixels or glBlitFramebuffer. */ -static void -setup_copypix_texture(struct gl_context *ctx, - struct temp_texture *tex, - GLboolean newTex, - GLint srcX, GLint srcY, - GLsizei width, GLsizei height, GLenum intFormat, - GLenum filter) +void +_mesa_meta_setup_copypix_texture(struct gl_context *ctx, + struct temp_texture *tex, + GLint srcX, GLint srcY, + GLsizei width, GLsizei height, + GLenum intFormat, + GLenum filter) { + bool newTex; + _mesa_BindTexture(tex->Target, tex->TexObj); _mesa_TexParameteri(tex->Target, GL_TEXTURE_MIN_FILTER, filter); _mesa_TexParameteri(tex->Target, GL_TEXTURE_MAG_FILTER, filter); - if (ctx->API == API_OPENGL_COMPAT || ctx->API == API_OPENGLES) - _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + + newTex = _mesa_meta_alloc_texture(tex, width, height, intFormat); /* copy framebuffer image to texture */ if (newTex) { @@ -1375,20 +1304,18 @@ setup_copypix_texture(struct gl_context *ctx, /** * Setup/load texture for glDrawPixels. */ -static void -setup_drawpix_texture(struct gl_context *ctx, - struct temp_texture *tex, - GLboolean newTex, - GLenum texIntFormat, - GLsizei width, GLsizei height, - GLenum format, GLenum type, - const GLvoid *pixels) +void +_mesa_meta_setup_drawpix_texture(struct gl_context *ctx, + struct temp_texture *tex, + GLboolean newTex, + GLsizei width, GLsizei height, + GLenum format, GLenum type, + const GLvoid *pixels) { _mesa_BindTexture(tex->Target, tex->TexObj); _mesa_TexParameteri(tex->Target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); _mesa_TexParameteri(tex->Target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - if (ctx->API == API_OPENGL_COMPAT || ctx->API == API_OPENGLES) - _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); /* copy pixel data to texture */ if (newTex) { @@ -1422,617 +1349,24 @@ setup_drawpix_texture(struct gl_context *ctx, } } - - -/** - * One-time init for drawing depth pixels. - */ -static void -init_blit_depth_pixels(struct gl_context *ctx) -{ - static const char *program = - "!!ARBfp1.0\n" - "TEX result.depth, fragment.texcoord[0], texture[0], %s; \n" - "END \n"; - char program2[200]; - struct blit_state *blit = &ctx->Meta->Blit; - struct temp_texture *tex = get_temp_texture(ctx); - const char *texTarget; - - assert(blit->DepthFP == 0); - - /* replace %s with "RECT" or "2D" */ - assert(strlen(program) + 4 < sizeof(program2)); - if (tex->Target == GL_TEXTURE_RECTANGLE) - texTarget = "RECT"; - else - texTarget = "2D"; - _mesa_snprintf(program2, sizeof(program2), program, texTarget); - - _mesa_GenProgramsARB(1, &blit->DepthFP); - _mesa_BindProgramARB(GL_FRAGMENT_PROGRAM_ARB, blit->DepthFP); - _mesa_ProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, - strlen(program2), (const GLubyte *) program2); -} - -static void -setup_ff_blit_framebuffer(struct blit_state *blit) +void +_mesa_meta_setup_ff_tnl_for_blit(GLuint *VAO, GLuint *VBO, + unsigned texcoord_size) { - struct vertex { - GLfloat x, y, s, t; - }; - struct vertex verts[4]; - - if (blit->VAO == 0) { - /* one-time setup */ - - /* create vertex array object */ - _mesa_GenVertexArrays(1, &blit->VAO); - _mesa_BindVertexArray(blit->VAO); - - /* create vertex array buffer */ - _mesa_GenBuffers(1, &blit->VBO); - _mesa_BindBuffer(GL_ARRAY_BUFFER_ARB, blit->VBO); - _mesa_BufferData(GL_ARRAY_BUFFER_ARB, sizeof(verts), - NULL, GL_DYNAMIC_DRAW_ARB); - - /* setup vertex arrays */ - _mesa_VertexPointer(2, GL_FLOAT, sizeof(struct vertex), OFFSET(x)); - _mesa_TexCoordPointer(2, GL_FLOAT, sizeof(struct vertex), OFFSET(s)); - _mesa_EnableClientState(GL_VERTEX_ARRAY); - _mesa_EnableClientState(GL_TEXTURE_COORD_ARRAY); - } + _mesa_meta_setup_vertex_objects(VAO, VBO, false, 2, texcoord_size, 0); /* setup projection matrix */ _mesa_MatrixMode(GL_PROJECTION); _mesa_LoadIdentity(); - _mesa_Ortho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0); - -} - -static void -setup_glsl_blit_framebuffer(struct gl_context *ctx, - struct blit_state *blit, - GLenum target) -{ - struct vertex { - GLfloat x, y, s, t; - }; - struct vertex verts[4]; - const char *vs_source; - char *fs_source; - GLuint vs, fs; - void *mem_ctx; - GLuint ShaderProg; - GLboolean texture_2d = (target == GL_TEXTURE_2D); - - /* target = GL_TEXTURE_RECTANGLE is not supported in GLES 3.0 */ - assert(_mesa_is_desktop_gl(ctx) || texture_2d); - - /* Check if already initialized */ - if (blit->VAO == 0) { - - /* create vertex array object */ - _mesa_GenVertexArrays(1, &blit->VAO); - _mesa_BindVertexArray(blit->VAO); - - /* create vertex array buffer */ - _mesa_GenBuffers(1, &blit->VBO); - _mesa_BindBuffer(GL_ARRAY_BUFFER_ARB, blit->VBO); - _mesa_BufferData(GL_ARRAY_BUFFER_ARB, sizeof(verts), - NULL, GL_DYNAMIC_DRAW_ARB); - - /* setup vertex arrays */ - _mesa_VertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, - sizeof(struct vertex), OFFSET(x)); - _mesa_VertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, - sizeof(struct vertex), OFFSET(s)); - - _mesa_EnableVertexAttribArray(0); - _mesa_EnableVertexAttribArray(1); - } - - /* Generate a relevant fragment shader program for the texture target */ - if ((target == GL_TEXTURE_2D && blit->ShaderProg != 0) || - (target == GL_TEXTURE_RECTANGLE && blit->RectShaderProg != 0)) { - return; - } - - mem_ctx = ralloc_context(NULL); - - if (ctx->Const.GLSLVersion < 130) { - vs_source = - "attribute vec2 position;\n" - "attribute vec2 textureCoords;\n" - "varying vec2 texCoords;\n" - "void main()\n" - "{\n" - " texCoords = textureCoords;\n" - " gl_Position = vec4(position, 0.0, 1.0);\n" - "}\n"; - - fs_source = ralloc_asprintf(mem_ctx, - "#ifdef GL_ES\n" - "precision highp float;\n" - "#endif\n" - "uniform %s texSampler;\n" - "varying vec2 texCoords;\n" - "void main()\n" - "{\n" - " gl_FragColor = %s(texSampler, texCoords);\n" - " gl_FragDepth = gl_FragColor.r;\n" - "}\n", - texture_2d ? "sampler2D" : "sampler2DRect", - texture_2d ? "texture2D" : "texture2DRect"); - } - else { - vs_source = ralloc_asprintf(mem_ctx, - "#version %s\n" - "in vec2 position;\n" - "in vec2 textureCoords;\n" - "out vec2 texCoords;\n" - "void main()\n" - "{\n" - " texCoords = textureCoords;\n" - " gl_Position = vec4(position, 0.0, 1.0);\n" - "}\n", - _mesa_is_desktop_gl(ctx) ? "130" : "300 es"); - fs_source = ralloc_asprintf(mem_ctx, - "#version %s\n" - "#ifdef GL_ES\n" - "precision highp float;\n" - "#endif\n" - "uniform %s texSampler;\n" - "in vec2 texCoords;\n" - "out vec4 out_color;\n" - "\n" - "void main()\n" - "{\n" - " out_color = %s(texSampler, texCoords);\n" - " gl_FragDepth = out_color.r;\n" - "}\n", - _mesa_is_desktop_gl(ctx) ? "130" : "300 es", - texture_2d ? "sampler2D" : "sampler2DRect", - texture_2d ? "texture" : "texture2DRect"); - } - - vs = compile_shader_with_debug(ctx, GL_VERTEX_SHADER, vs_source); - fs = compile_shader_with_debug(ctx, GL_FRAGMENT_SHADER, fs_source); - - ShaderProg = _mesa_CreateProgramObjectARB(); - _mesa_AttachShader(ShaderProg, fs); - _mesa_DeleteObjectARB(fs); - _mesa_AttachShader(ShaderProg, vs); - _mesa_DeleteObjectARB(vs); - _mesa_BindAttribLocation(ShaderProg, 0, "position"); - _mesa_BindAttribLocation(ShaderProg, 1, "texcoords"); - link_program_with_debug(ctx, ShaderProg); - ralloc_free(mem_ctx); - if (texture_2d) - blit->ShaderProg = ShaderProg; - else - blit->RectShaderProg = ShaderProg; } /** - * Try to do a glBlitFramebuffer using no-copy texturing. - * We can do this when the src renderbuffer is actually a texture. - * But if the src buffer == dst buffer we cannot do this. - * - * \return new buffer mask indicating the buffers left to blit using the - * normal path. - */ -static GLbitfield -blitframebuffer_texture(struct gl_context *ctx, - GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, - GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, - GLbitfield mask, GLenum filter, GLint flipX, - GLint flipY, GLboolean glsl_version) -{ - if (mask & GL_COLOR_BUFFER_BIT) { - const struct gl_framebuffer *drawFb = ctx->DrawBuffer; - const struct gl_framebuffer *readFb = ctx->ReadBuffer; - const struct gl_renderbuffer_attachment *drawAtt; - const struct gl_renderbuffer_attachment *readAtt = - &readFb->Attachment[readFb->_ColorReadBufferIndex]; - - if (readAtt && readAtt->Texture) { - struct blit_state *blit = &ctx->Meta->Blit; - const GLint dstX = MIN2(dstX0, dstX1); - const GLint dstY = MIN2(dstY0, dstY1); - const GLint dstW = abs(dstX1 - dstX0); - const GLint dstH = abs(dstY1 - dstY0); - const struct gl_texture_object *texObj = readAtt->Texture; - const GLuint srcLevel = readAtt->TextureLevel; - const GLint baseLevelSave = texObj->BaseLevel; - const GLint maxLevelSave = texObj->MaxLevel; - const GLenum target = texObj->Target; - GLuint sampler, samplerSave = - ctx->Texture.Unit[ctx->Texture.CurrentUnit].Sampler ? - ctx->Texture.Unit[ctx->Texture.CurrentUnit].Sampler->Name : 0; - int i; - - /* Iterate through all draw buffers */ - for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) { - int idx = ctx->DrawBuffer->_ColorDrawBufferIndexes[i]; - if (idx == -1) - continue; - drawAtt = &drawFb->Attachment[idx]; - - if (drawAtt->Texture == readAtt->Texture) { - /* Can't use same texture as both the source and dest. We need - * to handle overlapping blits and besides, some hw may not - * support this. - */ - return mask; - } - } - - if (target != GL_TEXTURE_2D && target != GL_TEXTURE_RECTANGLE_ARB) { - /* Can't handle other texture types at this time */ - return mask; - } - - /* Choose between glsl version and fixed function version of - * BlitFramebuffer function. - */ - if (glsl_version) { - setup_glsl_blit_framebuffer(ctx, blit, target); - if (target == GL_TEXTURE_2D) - _mesa_UseProgram(blit->ShaderProg); - else - _mesa_UseProgram(blit->RectShaderProg); - } - else { - setup_ff_blit_framebuffer(&ctx->Meta->Blit); - } - - _mesa_BindVertexArray(blit->VAO); - _mesa_BindBuffer(GL_ARRAY_BUFFER_ARB, blit->VBO); - - _mesa_GenSamplers(1, &sampler); - _mesa_BindSampler(ctx->Texture.CurrentUnit, sampler); - - /* - printf("Blit from texture!\n"); - printf(" srcAtt %p dstAtt %p\n", readAtt, drawAtt); - printf(" srcTex %p dstText %p\n", texObj, drawAtt->Texture); - */ - - /* Prepare src texture state */ - _mesa_BindTexture(target, texObj->Name); - _mesa_SamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, filter); - _mesa_SamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, filter); - if (target != GL_TEXTURE_RECTANGLE_ARB) { - _mesa_TexParameteri(target, GL_TEXTURE_BASE_LEVEL, srcLevel); - _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, srcLevel); - } - _mesa_SamplerParameteri(sampler, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - _mesa_SamplerParameteri(sampler, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - /* Always do our blits with no sRGB decode or encode. Note that - * GL_FRAMEBUFFER_SRGB has already been disabled by - * _mesa_meta_begin(). - */ - if (ctx->Extensions.EXT_texture_sRGB_decode) { - _mesa_SamplerParameteri(sampler, GL_TEXTURE_SRGB_DECODE_EXT, - GL_SKIP_DECODE_EXT); - } - - if (ctx->API == API_OPENGL_COMPAT || ctx->API == API_OPENGLES) { - _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - _mesa_set_enable(ctx, target, GL_TRUE); - } - - /* Prepare vertex data (the VBO was previously created and bound) */ - { - struct vertex { - GLfloat x, y, s, t; - }; - struct vertex verts[4]; - GLfloat s0, t0, s1, t1; - - if (target == GL_TEXTURE_2D) { - const struct gl_texture_image *texImage - = _mesa_select_tex_image(ctx, texObj, target, srcLevel); - s0 = srcX0 / (float) texImage->Width; - s1 = srcX1 / (float) texImage->Width; - t0 = srcY0 / (float) texImage->Height; - t1 = srcY1 / (float) texImage->Height; - } - else { - assert(target == GL_TEXTURE_RECTANGLE_ARB); - s0 = (float) srcX0; - s1 = (float) srcX1; - t0 = (float) srcY0; - t1 = (float) srcY1; - } - - /* setup vertex positions */ - verts[0].x = -1.0F * flipX; - verts[0].y = -1.0F * flipY; - verts[1].x = 1.0F * flipX; - verts[1].y = -1.0F * flipY; - verts[2].x = 1.0F * flipX; - verts[2].y = 1.0F * flipY; - verts[3].x = -1.0F * flipX; - verts[3].y = 1.0F * flipY; - - verts[0].s = s0; - verts[0].t = t0; - verts[1].s = s1; - verts[1].t = t0; - verts[2].s = s1; - verts[2].t = t1; - verts[3].s = s0; - verts[3].t = t1; - - _mesa_BufferSubData(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts); - } - - /* setup viewport */ - _mesa_set_viewport(ctx, 0, dstX, dstY, dstW, dstH); - _mesa_ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - _mesa_DepthMask(GL_FALSE); - _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4); - - /* Restore texture object state, the texture binding will - * be restored by _mesa_meta_end(). - */ - if (target != GL_TEXTURE_RECTANGLE_ARB) { - _mesa_TexParameteri(target, GL_TEXTURE_BASE_LEVEL, baseLevelSave); - _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, maxLevelSave); - } - - _mesa_BindSampler(ctx->Texture.CurrentUnit, samplerSave); - _mesa_DeleteSamplers(1, &sampler); - - /* Done with color buffer */ - mask &= ~GL_COLOR_BUFFER_BIT; - } - } - - return mask; -} - - -/** - * Meta implementation of ctx->Driver.BlitFramebuffer() in terms - * of texture mapping and polygon rendering. - */ -void -_mesa_meta_BlitFramebuffer(struct gl_context *ctx, - GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, - GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, - GLbitfield mask, GLenum filter) -{ - struct blit_state *blit = &ctx->Meta->Blit; - struct temp_texture *tex = get_temp_texture(ctx); - struct temp_texture *depthTex = get_temp_depth_texture(ctx); - const GLsizei maxTexSize = tex->MaxSize; - const GLint srcX = MIN2(srcX0, srcX1); - const GLint srcY = MIN2(srcY0, srcY1); - const GLint srcW = abs(srcX1 - srcX0); - const GLint srcH = abs(srcY1 - srcY0); - const GLint dstX = MIN2(dstX0, dstX1); - const GLint dstY = MIN2(dstY0, dstY1); - const GLint dstW = abs(dstX1 - dstX0); - const GLint dstH = abs(dstY1 - dstY0); - const GLint srcFlipX = (srcX1 - srcX0) / srcW; - const GLint srcFlipY = (srcY1 - srcY0) / srcH; - const GLint dstFlipX = (dstX1 - dstX0) / dstW; - const GLint dstFlipY = (dstY1 - dstY0) / dstH; - const GLint flipX = srcFlipX * dstFlipX; - const GLint flipY = srcFlipY * dstFlipY; - - struct vertex { - GLfloat x, y, s, t; - }; - struct vertex verts[4]; - GLboolean newTex; - const GLboolean use_glsl_version = ctx->Extensions.ARB_vertex_shader && - ctx->Extensions.ARB_fragment_shader && - (ctx->API != API_OPENGLES); - - /* In addition to falling back if the blit size is larger than the maximum - * texture size, fallback if the source is multisampled. This fallback can - * be removed once Mesa gets support ARB_texture_multisample. - */ - if (srcW > maxTexSize || srcH > maxTexSize - || ctx->ReadBuffer->Visual.samples > 0) { - /* XXX avoid this fallback */ - _swrast_BlitFramebuffer(ctx, srcX0, srcY0, srcX1, srcY1, - dstX0, dstY0, dstX1, dstY1, mask, filter); - return; - } - - /* only scissor effects blit so save/clear all other relevant state */ - _mesa_meta_begin(ctx, ~MESA_META_SCISSOR); - - /* Try faster, direct texture approach first */ - mask = blitframebuffer_texture(ctx, srcX0, srcY0, srcX1, srcY1, - dstX0, dstY0, dstX1, dstY1, mask, filter, - dstFlipX, dstFlipY, use_glsl_version); - if (mask == 0x0) { - _mesa_meta_end(ctx); - return; - } - - /* Choose between glsl version and fixed function version of - * BlitFramebuffer function. - */ - if (use_glsl_version) { - setup_glsl_blit_framebuffer(ctx, blit, tex->Target); - if (tex->Target == GL_TEXTURE_2D) - _mesa_UseProgram(blit->ShaderProg); - else - _mesa_UseProgram(blit->RectShaderProg); - } - else { - setup_ff_blit_framebuffer(blit); - } - - _mesa_BindVertexArray(blit->VAO); - _mesa_BindBuffer(GL_ARRAY_BUFFER_ARB, blit->VBO); - - /* Continue with "normal" approach which involves copying the src rect - * into a temporary texture and is "blitted" by drawing a textured quad. - */ - { - /* setup vertex positions */ - verts[0].x = -1.0F * flipX; - verts[0].y = -1.0F * flipY; - verts[1].x = 1.0F * flipX; - verts[1].y = -1.0F * flipY; - verts[2].x = 1.0F * flipX; - verts[2].y = 1.0F * flipY; - verts[3].x = -1.0F * flipX; - verts[3].y = 1.0F * flipY; - - } - - /* glEnable() in gles2 and gles3 doesn't allow GL_TEXTURE_{1D, 2D, etc.} - * tokens. - */ - if (_mesa_is_desktop_gl(ctx) || ctx->API == API_OPENGLES) - _mesa_set_enable(ctx, tex->Target, GL_TRUE); - - if (mask & GL_COLOR_BUFFER_BIT) { - const struct gl_framebuffer *readFb = ctx->ReadBuffer; - const struct gl_renderbuffer *colorReadRb = readFb->_ColorReadBuffer; - const GLenum rb_base_format = - _mesa_base_tex_format(ctx, colorReadRb->InternalFormat); - - /* Using the exact source rectangle to create the texture does incorrect - * linear filtering along the edges. So, allocate the texture extended along - * edges by one pixel in x, y directions. - */ - newTex = alloc_texture(tex, srcW + 2, srcH + 2, rb_base_format); - setup_copypix_texture(ctx, tex, newTex, - srcX - 1, srcY - 1, srcW + 2, srcH + 2, - rb_base_format, filter); - /* texcoords (after texture allocation!) */ - { - verts[0].s = 1.0F; - verts[0].t = 1.0F; - verts[1].s = tex->Sright - 1.0F; - verts[1].t = 1.0F; - verts[2].s = tex->Sright - 1.0F; - verts[2].t = tex->Ttop - 1.0F; - verts[3].s = 1.0F; - verts[3].t = tex->Ttop - 1.0F; - - /* upload new vertex data */ - _mesa_BufferSubData(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts); - } - - _mesa_set_viewport(ctx, 0, dstX, dstY, dstW, dstH); - _mesa_ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - _mesa_set_enable(ctx, GL_DEPTH_TEST, GL_FALSE); - _mesa_DepthMask(GL_FALSE); - _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4); - mask &= ~GL_COLOR_BUFFER_BIT; - } - - if ((mask & GL_DEPTH_BUFFER_BIT) && - _mesa_is_desktop_gl(ctx) && - ctx->Extensions.ARB_depth_texture && - ctx->Extensions.ARB_fragment_program) { - - GLuint *tmp = malloc(srcW * srcH * sizeof(GLuint)); - - if (tmp) { - - newTex = alloc_texture(depthTex, srcW, srcH, GL_DEPTH_COMPONENT); - _mesa_ReadPixels(srcX, srcY, srcW, srcH, GL_DEPTH_COMPONENT, - GL_UNSIGNED_INT, tmp); - setup_drawpix_texture(ctx, depthTex, newTex, GL_DEPTH_COMPONENT, - srcW, srcH, GL_DEPTH_COMPONENT, - GL_UNSIGNED_INT, tmp); - - /* texcoords (after texture allocation!) */ - { - verts[0].s = 0.0F; - verts[0].t = 0.0F; - verts[1].s = depthTex->Sright; - verts[1].t = 0.0F; - verts[2].s = depthTex->Sright; - verts[2].t = depthTex->Ttop; - verts[3].s = 0.0F; - verts[3].t = depthTex->Ttop; - - /* upload new vertex data */ - _mesa_BufferSubData(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts); - } - - if (!blit->DepthFP) - init_blit_depth_pixels(ctx); - - _mesa_BindProgramARB(GL_FRAGMENT_PROGRAM_ARB, blit->DepthFP); - _mesa_set_enable(ctx, GL_FRAGMENT_PROGRAM_ARB, GL_TRUE); - _mesa_ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); - _mesa_set_enable(ctx, GL_DEPTH_TEST, GL_TRUE); - _mesa_DepthFunc(GL_ALWAYS); - _mesa_DepthMask(GL_TRUE); - - _mesa_set_viewport(ctx, 0, dstX, dstY, dstW, dstH); - _mesa_BufferSubData(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts); - _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4); - mask &= ~GL_DEPTH_BUFFER_BIT; - - free(tmp); - } - } - - if (mask & GL_STENCIL_BUFFER_BIT) { - /* XXX can't easily do stencil */ - } - - if (_mesa_is_desktop_gl(ctx) || ctx->API == API_OPENGLES) - _mesa_set_enable(ctx, tex->Target, GL_FALSE); - - _mesa_meta_end(ctx); - - if (mask) { - _swrast_BlitFramebuffer(ctx, srcX0, srcY0, srcX1, srcY1, - dstX0, dstY0, dstX1, dstY1, mask, filter); - } -} - -static void -meta_glsl_blit_cleanup(struct blit_state *blit) -{ - if (blit->VAO) { - _mesa_DeleteVertexArrays(1, &blit->VAO); - blit->VAO = 0; - _mesa_DeleteBuffers(1, &blit->VBO); - blit->VBO = 0; - } - if (blit->DepthFP) { - _mesa_DeleteProgramsARB(1, &blit->DepthFP); - blit->DepthFP = 0; - } - - _mesa_DeleteObjectARB(blit->ShaderProg); - blit->ShaderProg = 0; - _mesa_DeleteObjectARB(blit->RectShaderProg); - blit->RectShaderProg = 0; - - _mesa_DeleteTextures(1, &blit->depthTex.TexObj); - blit->depthTex.TexObj = 0; -} - - -/** * Meta implementation of ctx->Driver.Clear() in terms of polygon rendering. */ void _mesa_meta_Clear(struct gl_context *ctx, GLbitfield buffers) { struct clear_state *clear = &ctx->Meta->Clear; - struct vertex { - GLfloat x, y, z, r, g, b, a; - }; struct vertex verts[4]; /* save all state but scissor, pixel pack/unpack */ GLbitfield metaSave = (MESA_META_ALL - @@ -2049,27 +1383,7 @@ _mesa_meta_Clear(struct gl_context *ctx, GLbitfield buffers) _mesa_meta_begin(ctx, metaSave); - if (clear->VAO == 0) { - /* one-time setup */ - - /* create vertex array object */ - _mesa_GenVertexArrays(1, &clear->VAO); - _mesa_BindVertexArray(clear->VAO); - - /* create vertex array buffer */ - _mesa_GenBuffers(1, &clear->VBO); - _mesa_BindBuffer(GL_ARRAY_BUFFER_ARB, clear->VBO); - - /* setup vertex arrays */ - _mesa_VertexPointer(3, GL_FLOAT, sizeof(struct vertex), OFFSET(x)); - _mesa_ColorPointer(4, GL_FLOAT, sizeof(struct vertex), OFFSET(r)); - _mesa_EnableClientState(GL_VERTEX_ARRAY); - _mesa_EnableClientState(GL_COLOR_ARRAY); - } - else { - _mesa_BindVertexArray(clear->VAO); - _mesa_BindBuffer(GL_ARRAY_BUFFER_ARB, clear->VBO); - } + _mesa_meta_setup_vertex_objects(&clear->VAO, &clear->VBO, false, 3, 0, 4); /* GL_COLOR_BUFFER_BIT */ if (buffers & BUFFER_BITS_COLOR) { @@ -2171,9 +1485,6 @@ meta_glsl_clear_init(struct gl_context *ctx, struct clear_state *clear) " }\n" "}\n"; const char *fs_source = - "#ifdef GL_ES\n" - "precision highp float;\n" - "#endif\n" "uniform vec4 color;\n" "void main()\n" "{\n" @@ -2182,20 +1493,10 @@ meta_glsl_clear_init(struct gl_context *ctx, struct clear_state *clear) GLuint vs, gs = 0, fs; bool has_integer_textures; - if (clear->VAO != 0) - return; - - /* create vertex array object */ - _mesa_GenVertexArrays(1, &clear->VAO); - _mesa_BindVertexArray(clear->VAO); - - /* create vertex array buffer */ - _mesa_GenBuffers(1, &clear->VBO); - _mesa_BindBuffer(GL_ARRAY_BUFFER_ARB, clear->VBO); + _mesa_meta_setup_vertex_objects(&clear->VAO, &clear->VBO, true, 3, 0, 0); - /* setup vertex arrays */ - _mesa_VertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void *)0); - _mesa_EnableVertexAttribArray(0); + if (clear->ShaderProg != 0) + return; vs = _mesa_CreateShaderObjectARB(GL_VERTEX_SHADER); _mesa_ShaderSource(vs, 1, &vs_source, NULL); @@ -2235,30 +1536,27 @@ meta_glsl_clear_init(struct gl_context *ctx, struct clear_state *clear) void *shader_source_mem_ctx = ralloc_context(NULL); const char *vs_int_source = ralloc_asprintf(shader_source_mem_ctx, - "#version %s\n" + "#version 130\n" "in vec4 position;\n" "void main()\n" "{\n" " gl_Position = position;\n" - "}\n", - _mesa_is_desktop_gl(ctx) ? "130" : "300 es"); + "}\n"); const char *fs_int_source = ralloc_asprintf(shader_source_mem_ctx, - "#version %s\n" - "#ifdef GL_ES\n" - "precision highp float;\n" - "#endif\n" + "#version 130\n" "uniform ivec4 color;\n" "out ivec4 out_color;\n" "\n" "void main()\n" "{\n" " out_color = color;\n" - "}\n", - _mesa_is_desktop_gl(ctx) ? "130" : "300 es"); + "}\n"); - vs = compile_shader_with_debug(ctx, GL_VERTEX_SHADER, vs_int_source); - fs = compile_shader_with_debug(ctx, GL_FRAGMENT_SHADER, fs_int_source); + vs = _mesa_meta_compile_shader_with_debug(ctx, GL_VERTEX_SHADER, + vs_int_source); + fs = _mesa_meta_compile_shader_with_debug(ctx, GL_FRAGMENT_SHADER, + fs_int_source); ralloc_free(shader_source_mem_ctx); clear->IntegerShaderProg = _mesa_CreateProgramObjectARB(); @@ -2275,7 +1573,9 @@ meta_glsl_clear_init(struct gl_context *ctx, struct clear_state *clear) * BindFragDataLocation to 0. */ - link_program_with_debug(ctx, clear->IntegerShaderProg); + _mesa_ObjectLabel(GL_PROGRAM, clear->IntegerShaderProg, -1, + "integer clear"); + _mesa_meta_link_program_with_debug(ctx, clear->IntegerShaderProg); clear->IntegerColorLocation = _mesa_GetUniformLocation(clear->IntegerShaderProg, "color"); @@ -2321,9 +1621,7 @@ _mesa_meta_glsl_Clear(struct gl_context *ctx, GLbitfield buffers) const float x1 = ((float)fb->_Xmax / fb->Width) * 2.0f - 1.0f; const float y1 = ((float)fb->_Ymax / fb->Height) * 2.0f - 1.0f; const float z = -invert_z(ctx->Depth.Clear); - struct vertex { - GLfloat x, y, z; - } verts[4]; + struct vertex verts[4]; metaSave = (MESA_META_ALPHA_TEST | MESA_META_BLEND | @@ -2359,9 +1657,6 @@ _mesa_meta_glsl_Clear(struct gl_context *ctx, GLbitfield buffers) ctx->Color.ClearColor.f); } - _mesa_BindVertexArray(clear->VAO); - _mesa_BindBuffer(GL_ARRAY_BUFFER_ARB, clear->VBO); - /* GL_COLOR_BUFFER_BIT */ if (buffers & BUFFER_BITS_COLOR) { /* leave colormask, glDrawBuffer state as-is */ @@ -2443,13 +1738,8 @@ _mesa_meta_CopyPixels(struct gl_context *ctx, GLint srcX, GLint srcY, GLint dstX, GLint dstY, GLenum type) { struct copypix_state *copypix = &ctx->Meta->CopyPix; - struct temp_texture *tex = get_temp_texture(ctx); - struct vertex { - GLfloat x, y, z, s, t; - }; + struct temp_texture *tex = _mesa_meta_get_temp_texture(ctx); struct vertex verts[4]; - GLboolean newTex; - GLenum intFormat = GL_RGBA; if (type != GL_COLOR || ctx->_ImageTransferState || @@ -2472,31 +1762,15 @@ _mesa_meta_CopyPixels(struct gl_context *ctx, GLint srcX, GLint srcY, MESA_META_VERTEX | MESA_META_VIEWPORT)); - if (copypix->VAO == 0) { - /* one-time setup */ + _mesa_meta_setup_vertex_objects(©pix->VAO, ©pix->VBO, false, + 3, 2, 0); - /* create vertex array object */ - _mesa_GenVertexArrays(1, ©pix->VAO); - _mesa_BindVertexArray(copypix->VAO); - - /* create vertex array buffer */ - _mesa_GenBuffers(1, ©pix->VBO); - _mesa_BindBuffer(GL_ARRAY_BUFFER_ARB, copypix->VBO); - _mesa_BufferData(GL_ARRAY_BUFFER_ARB, sizeof(verts), - NULL, GL_DYNAMIC_DRAW_ARB); + /* Silence valgrind warnings about reading uninitialized stack. */ + memset(verts, 0, sizeof(verts)); - /* setup vertex arrays */ - _mesa_VertexPointer(3, GL_FLOAT, sizeof(struct vertex), OFFSET(x)); - _mesa_TexCoordPointer(2, GL_FLOAT, sizeof(struct vertex), OFFSET(s)); - _mesa_EnableClientState(GL_VERTEX_ARRAY); - _mesa_EnableClientState(GL_TEXTURE_COORD_ARRAY); - } - else { - _mesa_BindVertexArray(copypix->VAO); - _mesa_BindBuffer(GL_ARRAY_BUFFER_ARB, copypix->VBO); - } - - newTex = alloc_texture(tex, width, height, intFormat); + /* Alloc/setup texture */ + _mesa_meta_setup_copypix_texture(ctx, tex, srcX, srcY, width, height, + GL_RGBA, GL_NEAREST); /* vertex positions, texcoords (after texture allocation!) */ { @@ -2509,32 +1783,28 @@ _mesa_meta_CopyPixels(struct gl_context *ctx, GLint srcX, GLint srcY, verts[0].x = dstX0; verts[0].y = dstY0; verts[0].z = z; - verts[0].s = 0.0F; - verts[0].t = 0.0F; + verts[0].tex[0] = 0.0F; + verts[0].tex[1] = 0.0F; verts[1].x = dstX1; verts[1].y = dstY0; verts[1].z = z; - verts[1].s = tex->Sright; - verts[1].t = 0.0F; + verts[1].tex[0] = tex->Sright; + verts[1].tex[1] = 0.0F; verts[2].x = dstX1; verts[2].y = dstY1; verts[2].z = z; - verts[2].s = tex->Sright; - verts[2].t = tex->Ttop; + verts[2].tex[0] = tex->Sright; + verts[2].tex[1] = tex->Ttop; verts[3].x = dstX0; verts[3].y = dstY1; verts[3].z = z; - verts[3].s = 0.0F; - verts[3].t = tex->Ttop; + verts[3].tex[0] = 0.0F; + verts[3].tex[1] = tex->Ttop; /* upload new vertex data */ _mesa_BufferSubData(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts); } - /* Alloc/setup texture */ - setup_copypix_texture(ctx, tex, newTex, srcX, srcY, width, height, - GL_RGBA, GL_NEAREST); - _mesa_set_enable(ctx, tex->Target, GL_TRUE); /* draw textured quad */ @@ -2551,6 +1821,9 @@ meta_drawpix_cleanup(struct drawpix_state *drawpix) if (drawpix->VAO != 0) { _mesa_DeleteVertexArrays(1, &drawpix->VAO); drawpix->VAO = 0; + + _mesa_DeleteBuffers(1, &drawpix->VBO); + drawpix->VBO = 0; } if (drawpix->StencilFP != 0) { @@ -2646,7 +1919,7 @@ init_draw_stencil_pixels(struct gl_context *ctx) "END \n"; char program2[1000]; struct drawpix_state *drawpix = &ctx->Meta->DrawPix; - struct temp_texture *tex = get_temp_texture(ctx); + struct temp_texture *tex = _mesa_meta_get_temp_texture(ctx); const char *texTarget; assert(drawpix->StencilFP == 0); @@ -2680,7 +1953,7 @@ init_draw_depth_pixels(struct gl_context *ctx) "END \n"; char program2[200]; struct drawpix_state *drawpix = &ctx->Meta->DrawPix; - struct temp_texture *tex = get_temp_texture(ctx); + struct temp_texture *tex = _mesa_meta_get_temp_texture(ctx); const char *texTarget; assert(drawpix->DepthFP == 0); @@ -2712,17 +1985,13 @@ _mesa_meta_DrawPixels(struct gl_context *ctx, const GLvoid *pixels) { struct drawpix_state *drawpix = &ctx->Meta->DrawPix; - struct temp_texture *tex = get_temp_texture(ctx); + struct temp_texture *tex = _mesa_meta_get_temp_texture(ctx); const struct gl_pixelstore_attrib unpackSave = ctx->Unpack; const GLuint origStencilMask = ctx->Stencil.WriteMask[0]; - struct vertex { - GLfloat x, y, z, s, t; - }; struct vertex verts[4]; GLenum texIntFormat; GLboolean fallback, newTex; GLbitfield metaExtraSave = 0x0; - GLuint vbo; /* * Determine if we can do the glDrawPixels with texture mapping. @@ -2812,7 +2081,13 @@ _mesa_meta_DrawPixels(struct gl_context *ctx, MESA_META_VIEWPORT | metaExtraSave)); - newTex = alloc_texture(tex, width, height, texIntFormat); + newTex = _mesa_meta_alloc_texture(tex, width, height, texIntFormat); + + _mesa_meta_setup_vertex_objects(&drawpix->VAO, &drawpix->VBO, false, + 3, 2, 0); + + /* Silence valgrind warnings about reading uninitialized stack. */ + memset(verts, 0, sizeof(verts)); /* vertex positions, texcoords (after texture allocation!) */ { @@ -2825,43 +2100,29 @@ _mesa_meta_DrawPixels(struct gl_context *ctx, verts[0].x = x0; verts[0].y = y0; verts[0].z = z; - verts[0].s = 0.0F; - verts[0].t = 0.0F; + verts[0].tex[0] = 0.0F; + verts[0].tex[1] = 0.0F; verts[1].x = x1; verts[1].y = y0; verts[1].z = z; - verts[1].s = tex->Sright; - verts[1].t = 0.0F; + verts[1].tex[0] = tex->Sright; + verts[1].tex[1] = 0.0F; verts[2].x = x1; verts[2].y = y1; verts[2].z = z; - verts[2].s = tex->Sright; - verts[2].t = tex->Ttop; + verts[2].tex[0] = tex->Sright; + verts[2].tex[1] = tex->Ttop; verts[3].x = x0; verts[3].y = y1; verts[3].z = z; - verts[3].s = 0.0F; - verts[3].t = tex->Ttop; - } - - if (drawpix->VAO == 0) { - /* one-time setup: create vertex array object */ - _mesa_GenVertexArrays(1, &drawpix->VAO); + verts[3].tex[0] = 0.0F; + verts[3].tex[1] = tex->Ttop; } - _mesa_BindVertexArray(drawpix->VAO); - /* create vertex array buffer */ - _mesa_GenBuffers(1, &vbo); - _mesa_BindBuffer(GL_ARRAY_BUFFER_ARB, vbo); + /* upload new vertex data */ _mesa_BufferData(GL_ARRAY_BUFFER_ARB, sizeof(verts), verts, GL_DYNAMIC_DRAW_ARB); - /* setup vertex arrays */ - _mesa_VertexPointer(3, GL_FLOAT, sizeof(struct vertex), OFFSET(x)); - _mesa_TexCoordPointer(2, GL_FLOAT, sizeof(struct vertex), OFFSET(s)); - _mesa_EnableClientState(GL_VERTEX_ARRAY); - _mesa_EnableClientState(GL_TEXTURE_COORD_ARRAY); - /* set given unpack params */ ctx->Unpack = *unpack; @@ -2874,8 +2135,8 @@ _mesa_meta_DrawPixels(struct gl_context *ctx, if (!drawpix->StencilFP) init_draw_stencil_pixels(ctx); - setup_drawpix_texture(ctx, tex, newTex, texIntFormat, width, height, - GL_ALPHA, type, pixels); + _mesa_meta_setup_drawpix_texture(ctx, tex, newTex, width, height, + GL_ALPHA, type, pixels); _mesa_ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); @@ -2917,22 +2178,20 @@ _mesa_meta_DrawPixels(struct gl_context *ctx, _mesa_ProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, 0, ctx->Current.RasterColor); - setup_drawpix_texture(ctx, tex, newTex, texIntFormat, width, height, - format, type, pixels); + _mesa_meta_setup_drawpix_texture(ctx, tex, newTex, width, height, + format, type, pixels); _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4); } else { /* Drawing RGBA */ - setup_drawpix_texture(ctx, tex, newTex, texIntFormat, width, height, - format, type, pixels); + _mesa_meta_setup_drawpix_texture(ctx, tex, newTex, width, height, + format, type, pixels); _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4); } _mesa_set_enable(ctx, tex->Target, GL_FALSE); - _mesa_DeleteBuffers(1, &vbo); - /* restore unpack params */ ctx->Unpack = unpackSave; @@ -2984,9 +2243,6 @@ _mesa_meta_Bitmap(struct gl_context *ctx, const GLenum texIntFormat = GL_ALPHA; const struct gl_pixelstore_attrib unpackSave = *unpack; GLubyte fg, bg; - struct vertex { - GLfloat x, y, z, s, t, r, g, b, a; - }; struct vertex verts[4]; GLboolean newTex; GLubyte *bitmap8; @@ -3020,33 +2276,12 @@ _mesa_meta_Bitmap(struct gl_context *ctx, MESA_META_VERTEX | MESA_META_VIEWPORT)); - if (bitmap->VAO == 0) { - /* one-time setup */ + _mesa_meta_setup_vertex_objects(&bitmap->VAO, &bitmap->VBO, false, 3, 2, 4); - /* create vertex array object */ - _mesa_GenVertexArrays(1, &bitmap->VAO); - _mesa_BindVertexArray(bitmap->VAO); + newTex = _mesa_meta_alloc_texture(tex, width, height, texIntFormat); - /* create vertex array buffer */ - _mesa_GenBuffers(1, &bitmap->VBO); - _mesa_BindBuffer(GL_ARRAY_BUFFER_ARB, bitmap->VBO); - _mesa_BufferData(GL_ARRAY_BUFFER_ARB, sizeof(verts), - NULL, GL_DYNAMIC_DRAW_ARB); - - /* setup vertex arrays */ - _mesa_VertexPointer(3, GL_FLOAT, sizeof(struct vertex), OFFSET(x)); - _mesa_TexCoordPointer(2, GL_FLOAT, sizeof(struct vertex), OFFSET(s)); - _mesa_ColorPointer(4, GL_FLOAT, sizeof(struct vertex), OFFSET(r)); - _mesa_EnableClientState(GL_VERTEX_ARRAY); - _mesa_EnableClientState(GL_TEXTURE_COORD_ARRAY); - _mesa_EnableClientState(GL_COLOR_ARRAY); - } - else { - _mesa_BindVertexArray(bitmap->VAO); - _mesa_BindBuffer(GL_ARRAY_BUFFER_ARB, bitmap->VBO); - } - - newTex = alloc_texture(tex, width, height, texIntFormat); + /* Silence valgrind warnings about reading uninitialized stack. */ + memset(verts, 0, sizeof(verts)); /* vertex positions, texcoords, colors (after texture allocation!) */ { @@ -3060,23 +2295,23 @@ _mesa_meta_Bitmap(struct gl_context *ctx, verts[0].x = x0; verts[0].y = y0; verts[0].z = z; - verts[0].s = 0.0F; - verts[0].t = 0.0F; + verts[0].tex[0] = 0.0F; + verts[0].tex[1] = 0.0F; verts[1].x = x1; verts[1].y = y0; verts[1].z = z; - verts[1].s = tex->Sright; - verts[1].t = 0.0F; + verts[1].tex[0] = tex->Sright; + verts[1].tex[1] = 0.0F; verts[2].x = x1; verts[2].y = y1; verts[2].z = z; - verts[2].s = tex->Sright; - verts[2].t = tex->Ttop; + verts[2].tex[0] = tex->Sright; + verts[2].tex[1] = tex->Ttop; verts[3].x = x0; verts[3].y = y1; verts[3].z = z; - verts[3].s = 0.0F; - verts[3].t = tex->Ttop; + verts[3].tex[0] = 0.0F; + verts[3].tex[1] = tex->Ttop; for (i = 0; i < 4; i++) { verts[i].r = ctx->Current.RasterColor[0]; @@ -3110,8 +2345,8 @@ _mesa_meta_Bitmap(struct gl_context *ctx, _mesa_set_enable(ctx, GL_ALPHA_TEST, GL_TRUE); _mesa_AlphaFunc(GL_NOTEQUAL, UBYTE_TO_FLOAT(bg)); - setup_drawpix_texture(ctx, tex, newTex, texIntFormat, width, height, - GL_ALPHA, GL_UNSIGNED_BYTE, bitmap8); + _mesa_meta_setup_drawpix_texture(ctx, tex, newTex, width, height, + GL_ALPHA, GL_UNSIGNED_BYTE, bitmap8); _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4); @@ -3236,10 +2471,10 @@ setup_texture_coords(GLenum faceTarget, GLint width, GLint height, GLint depth, - GLfloat coords0[3], - GLfloat coords1[3], - GLfloat coords2[3], - GLfloat coords3[3]) + GLfloat coords0[4], + GLfloat coords1[4], + GLfloat coords2[4], + GLfloat coords3[4]) { static const GLfloat st[4][2] = { {0.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 1.0f} @@ -3247,6 +2482,13 @@ setup_texture_coords(GLenum faceTarget, GLuint i; GLfloat r; + /* Currently all texture targets want the W component to be 1.0. + */ + coords0[3] = 1.0F; + coords1[3] = 1.0F; + coords2[3] = 1.0F; + coords3[3] = 1.0F; + switch (faceTarget) { case GL_TEXTURE_1D: case GL_TEXTURE_2D: @@ -3337,6 +2579,8 @@ setup_texture_coords(GLenum faceTarget, assert(0); } + coord[3] = (float) (slice / 6); + switch (faceTarget) { case GL_TEXTURE_CUBE_MAP_POSITIVE_X: coord[0] = 1.0f; @@ -3378,74 +2622,53 @@ setup_texture_coords(GLenum faceTarget, } } - -static void -setup_ff_generate_mipmap(struct gen_mipmap_state *mipmap) -{ - struct vertex { - GLfloat x, y, tex[3]; - }; - - if (mipmap->VAO == 0) { - /* one-time setup */ - /* create vertex array object */ - _mesa_GenVertexArrays(1, &mipmap->VAO); - _mesa_BindVertexArray(mipmap->VAO); - - /* create vertex array buffer */ - _mesa_GenBuffers(1, &mipmap->VBO); - _mesa_BindBuffer(GL_ARRAY_BUFFER_ARB, mipmap->VBO); - /* setup vertex arrays */ - _mesa_VertexPointer(2, GL_FLOAT, sizeof(struct vertex), OFFSET(x)); - _mesa_TexCoordPointer(3, GL_FLOAT, sizeof(struct vertex), OFFSET(tex)); - _mesa_EnableClientState(GL_VERTEX_ARRAY); - _mesa_EnableClientState(GL_TEXTURE_COORD_ARRAY); - } - - /* setup projection matrix */ - _mesa_MatrixMode(GL_PROJECTION); - _mesa_LoadIdentity(); - _mesa_Ortho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0); -} - - -static struct glsl_sampler * -setup_texture_sampler(GLenum target, struct gen_mipmap_state *mipmap) +static struct blit_shader * +choose_blit_shader(GLenum target, struct blit_shader_table *table) { switch(target) { case GL_TEXTURE_1D: - mipmap->sampler_1d.type = "sampler1D"; - mipmap->sampler_1d.func = "texture1D"; - mipmap->sampler_1d.texcoords = "texCoords.x"; - return &mipmap->sampler_1d; + table->sampler_1d.type = "sampler1D"; + table->sampler_1d.func = "texture1D"; + table->sampler_1d.texcoords = "texCoords.x"; + return &table->sampler_1d; case GL_TEXTURE_2D: - mipmap->sampler_2d.type = "sampler2D"; - mipmap->sampler_2d.func = "texture2D"; - mipmap->sampler_2d.texcoords = "texCoords.xy"; - return &mipmap->sampler_2d; + table->sampler_2d.type = "sampler2D"; + table->sampler_2d.func = "texture2D"; + table->sampler_2d.texcoords = "texCoords.xy"; + return &table->sampler_2d; + case GL_TEXTURE_RECTANGLE: + table->sampler_rect.type = "sampler2DRect"; + table->sampler_rect.func = "texture2DRect"; + table->sampler_rect.texcoords = "texCoords.xy"; + return &table->sampler_rect; case GL_TEXTURE_3D: /* Code for mipmap generation with 3D textures is not used yet. * It's a sw fallback. */ - mipmap->sampler_3d.type = "sampler3D"; - mipmap->sampler_3d.func = "texture3D"; - mipmap->sampler_3d.texcoords = "texCoords"; - return &mipmap->sampler_3d; + table->sampler_3d.type = "sampler3D"; + table->sampler_3d.func = "texture3D"; + table->sampler_3d.texcoords = "texCoords.xyz"; + return &table->sampler_3d; case GL_TEXTURE_CUBE_MAP: - mipmap->sampler_cubemap.type = "samplerCube"; - mipmap->sampler_cubemap.func = "textureCube"; - mipmap->sampler_cubemap.texcoords = "texCoords"; - return &mipmap->sampler_cubemap; + table->sampler_cubemap.type = "samplerCube"; + table->sampler_cubemap.func = "textureCube"; + table->sampler_cubemap.texcoords = "texCoords.xyz"; + return &table->sampler_cubemap; case GL_TEXTURE_1D_ARRAY: - mipmap->sampler_1d_array.type = "sampler1DArray"; - mipmap->sampler_1d_array.func = "texture1DArray"; - mipmap->sampler_1d_array.texcoords = "texCoords.xy"; - return &mipmap->sampler_1d_array; + table->sampler_1d_array.type = "sampler1DArray"; + table->sampler_1d_array.func = "texture1DArray"; + table->sampler_1d_array.texcoords = "texCoords.xy"; + return &table->sampler_1d_array; case GL_TEXTURE_2D_ARRAY: - mipmap->sampler_2d_array.type = "sampler2DArray"; - mipmap->sampler_2d_array.func = "texture2DArray"; - mipmap->sampler_2d_array.texcoords = "texCoords"; - return &mipmap->sampler_2d_array; + table->sampler_2d_array.type = "sampler2DArray"; + table->sampler_2d_array.func = "texture2DArray"; + table->sampler_2d_array.texcoords = "texCoords.xyz"; + return &table->sampler_2d_array; + case GL_TEXTURE_CUBE_MAP_ARRAY: + table->sampler_cubemap_array.type = "samplerCubeArray"; + table->sampler_cubemap_array.func = "textureCubeArray"; + table->sampler_cubemap_array.texcoords = "texCoords.xyzw"; + return &table->sampler_cubemap_array; default: _mesa_problem(NULL, "Unexpected texture target 0x%x in" " setup_texture_sampler()\n", target); @@ -3453,122 +2676,28 @@ setup_texture_sampler(GLenum target, struct gen_mipmap_state *mipmap) } } - -static void -setup_glsl_generate_mipmap(struct gl_context *ctx, - struct gen_mipmap_state *mipmap, - GLenum target) +void +_mesa_meta_blit_shader_table_cleanup(struct blit_shader_table *table) { - struct vertex { - GLfloat x, y, tex[3]; - }; - struct glsl_sampler *sampler; - const char *vs_source; - char *fs_source; - GLuint vs, fs; - void *mem_ctx; - - /* Check if already initialized */ - if (mipmap->VAO == 0) { - - /* create vertex array object */ - _mesa_GenVertexArrays(1, &mipmap->VAO); - _mesa_BindVertexArray(mipmap->VAO); - - /* create vertex array buffer */ - _mesa_GenBuffers(1, &mipmap->VBO); - _mesa_BindBuffer(GL_ARRAY_BUFFER_ARB, mipmap->VBO); - - /* setup vertex arrays */ - _mesa_VertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, - sizeof(struct vertex), OFFSET(x)); - _mesa_VertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, - sizeof(struct vertex), OFFSET(tex)); - _mesa_EnableVertexAttribArray(0); - _mesa_EnableVertexAttribArray(1); - } - - /* Generate a fragment shader program appropriate for the texture target */ - sampler = setup_texture_sampler(target, mipmap); - assert(sampler != NULL); - if (sampler->shader_prog != 0) { - mipmap->ShaderProg = sampler->shader_prog; - return; - } - - mem_ctx = ralloc_context(NULL); - - if (ctx->API == API_OPENGLES2 || ctx->Const.GLSLVersion < 130) { - vs_source = - "attribute vec2 position;\n" - "attribute vec3 textureCoords;\n" - "varying vec3 texCoords;\n" - "void main()\n" - "{\n" - " texCoords = textureCoords;\n" - " gl_Position = vec4(position, 0.0, 1.0);\n" - "}\n"; - - fs_source = ralloc_asprintf(mem_ctx, - "#extension GL_EXT_texture_array : enable\n" - "#ifdef GL_ES\n" - "precision highp float;\n" - "#endif\n" - "uniform %s texSampler;\n" - "varying vec3 texCoords;\n" - "void main()\n" - "{\n" - " gl_FragColor = %s(texSampler, %s);\n" - "}\n", - sampler->type, - sampler->func, sampler->texcoords); - } - else { - vs_source = ralloc_asprintf(mem_ctx, - "#version %s\n" - "in vec2 position;\n" - "in vec3 textureCoords;\n" - "out vec3 texCoords;\n" - "void main()\n" - "{\n" - " texCoords = textureCoords;\n" - " gl_Position = vec4(position, 0.0, 1.0);\n" - "}\n", - _mesa_is_desktop_gl(ctx) ? "130" : "300 es"); - fs_source = ralloc_asprintf(mem_ctx, - "#version %s\n" - "#ifdef GL_ES\n" - "precision highp float;\n" - "#endif\n" - "uniform %s texSampler;\n" - "in vec3 texCoords;\n" - "out vec4 out_color;\n" - "\n" - "void main()\n" - "{\n" - " out_color = texture(texSampler, %s);\n" - "}\n", - _mesa_is_desktop_gl(ctx) ? "130" : "300 es", - sampler->type, - sampler->texcoords); - } - - vs = compile_shader_with_debug(ctx, GL_VERTEX_SHADER, vs_source); - fs = compile_shader_with_debug(ctx, GL_FRAGMENT_SHADER, fs_source); - - mipmap->ShaderProg = _mesa_CreateProgramObjectARB(); - _mesa_AttachShader(mipmap->ShaderProg, fs); - _mesa_DeleteObjectARB(fs); - _mesa_AttachShader(mipmap->ShaderProg, vs); - _mesa_DeleteObjectARB(vs); - _mesa_BindAttribLocation(mipmap->ShaderProg, 0, "position"); - _mesa_BindAttribLocation(mipmap->ShaderProg, 1, "texcoords"); - link_program_with_debug(ctx, mipmap->ShaderProg); - sampler->shader_prog = mipmap->ShaderProg; - ralloc_free(mem_ctx); + _mesa_DeleteObjectARB(table->sampler_1d.shader_prog); + _mesa_DeleteObjectARB(table->sampler_2d.shader_prog); + _mesa_DeleteObjectARB(table->sampler_3d.shader_prog); + _mesa_DeleteObjectARB(table->sampler_rect.shader_prog); + _mesa_DeleteObjectARB(table->sampler_cubemap.shader_prog); + _mesa_DeleteObjectARB(table->sampler_1d_array.shader_prog); + _mesa_DeleteObjectARB(table->sampler_2d_array.shader_prog); + _mesa_DeleteObjectARB(table->sampler_cubemap_array.shader_prog); + + table->sampler_1d.shader_prog = 0; + table->sampler_2d.shader_prog = 0; + table->sampler_3d.shader_prog = 0; + table->sampler_rect.shader_prog = 0; + table->sampler_cubemap.shader_prog = 0; + table->sampler_1d_array.shader_prog = 0; + table->sampler_2d_array.shader_prog = 0; + table->sampler_cubemap_array.shader_prog = 0; } - static void meta_glsl_generate_mipmap_cleanup(struct gen_mipmap_state *mipmap) { @@ -3579,19 +2708,7 @@ meta_glsl_generate_mipmap_cleanup(struct gen_mipmap_state *mipmap) _mesa_DeleteBuffers(1, &mipmap->VBO); mipmap->VBO = 0; - _mesa_DeleteObjectARB(mipmap->sampler_1d.shader_prog); - _mesa_DeleteObjectARB(mipmap->sampler_2d.shader_prog); - _mesa_DeleteObjectARB(mipmap->sampler_3d.shader_prog); - _mesa_DeleteObjectARB(mipmap->sampler_cubemap.shader_prog); - _mesa_DeleteObjectARB(mipmap->sampler_1d_array.shader_prog); - _mesa_DeleteObjectARB(mipmap->sampler_2d_array.shader_prog); - - mipmap->sampler_1d.shader_prog = 0; - mipmap->sampler_2d.shader_prog = 0; - mipmap->sampler_3d.shader_prog = 0; - mipmap->sampler_cubemap.shader_prog = 0; - mipmap->sampler_1d_array.shader_prog = 0; - mipmap->sampler_2d_array.shader_prog = 0; + _mesa_meta_blit_shader_table_cleanup(&mipmap->shaders); } @@ -3605,9 +2722,6 @@ _mesa_meta_GenerateMipmap(struct gl_context *ctx, GLenum target, struct gl_texture_object *texObj) { struct gen_mipmap_state *mipmap = &ctx->Meta->Mipmap; - struct vertex { - GLfloat x, y, tex[3]; - }; struct vertex verts[4]; const GLuint baseLevel = texObj->BaseLevel; const GLuint maxLevel = texObj->MaxLevel; @@ -3616,8 +2730,7 @@ _mesa_meta_GenerateMipmap(struct gl_context *ctx, GLenum target, const GLuint fboSave = ctx->DrawBuffer->Name; const GLuint currentTexUnitSave = ctx->Texture.CurrentUnit; const GLboolean use_glsl_version = ctx->Extensions.ARB_vertex_shader && - ctx->Extensions.ARB_fragment_shader && - (ctx->API != API_OPENGLES); + ctx->Extensions.ARB_fragment_shader; GLenum faceTarget; GLuint dstLevel; const GLint slice = 0; @@ -3643,17 +2756,15 @@ _mesa_meta_GenerateMipmap(struct gl_context *ctx, GLenum target, * GenerateMipmap function. */ if (use_glsl_version) { - setup_glsl_generate_mipmap(ctx, mipmap, target); - _mesa_UseProgram(mipmap->ShaderProg); + _mesa_meta_setup_vertex_objects(&mipmap->VAO, &mipmap->VBO, true, + 2, 3, 0); + _mesa_meta_setup_blit_shader(ctx, target, &mipmap->shaders); } else { - setup_ff_generate_mipmap(mipmap); + _mesa_meta_setup_ff_tnl_for_blit(&mipmap->VAO, &mipmap->VBO, 3); _mesa_set_enable(ctx, target, GL_TRUE); } - _mesa_BindVertexArray(mipmap->VAO); - _mesa_BindBuffer(GL_ARRAY_BUFFER_ARB, mipmap->VBO); - samplerSave = ctx->Texture.Unit[ctx->Texture.CurrentUnit].Sampler ? ctx->Texture.Unit[ctx->Texture.CurrentUnit].Sampler->Name : 0; @@ -3691,10 +2802,10 @@ _mesa_meta_GenerateMipmap(struct gl_context *ctx, GLenum target, _mesa_BindFramebuffer(GL_FRAMEBUFFER_EXT, mipmap->FBO); - if (ctx->API == API_OPENGL_COMPAT || ctx->API == API_OPENGLES) - _mesa_TexParameteri(target, GL_GENERATE_MIPMAP, GL_FALSE); - else - assert(!genMipmapSave); + _mesa_TexParameteri(target, GL_GENERATE_MIPMAP, GL_FALSE); + + /* Silence valgrind warnings about reading uninitialized stack. */ + memset(verts, 0, sizeof(verts)); /* Setup texture coordinates */ setup_texture_coords(faceTarget, @@ -3895,6 +3006,12 @@ _mesa_meta_CopyTexSubImage(struct gl_context *ctx, GLuint dims, GLint bpp; void *buf; + /* The gl_renderbuffer is part of the interface for + * dd_function_table::CopyTexSubImage, but this implementation does not use + * it. + */ + (void) rb; + /* Choose format/type for temporary image buffer */ format = _mesa_get_format_base_format(texImage->TexFormat); if (format == GL_LUMINANCE || @@ -4004,17 +3121,17 @@ decompress_texture_image(struct gl_context *ctx, const GLint depth = texImage->Height; const GLenum target = texObj->Target; GLenum faceTarget; - struct vertex { - GLfloat x, y, tex[3]; - }; struct vertex verts[4]; GLuint fboDrawSave, fboReadSave; GLuint rbSave; GLuint samplerSave; + const bool use_glsl_version = ctx->Extensions.ARB_vertex_shader && + ctx->Extensions.ARB_fragment_shader; if (slice > 0) { assert(target == GL_TEXTURE_3D || - target == GL_TEXTURE_2D_ARRAY); + target == GL_TEXTURE_2D_ARRAY || + target == GL_TEXTURE_CUBE_MAP_ARRAY); } switch (target) { @@ -4027,10 +3144,9 @@ decompress_texture_image(struct gl_context *ctx, assert(!"No compressed 3D textures."); return; - case GL_TEXTURE_2D_ARRAY: case GL_TEXTURE_CUBE_MAP_ARRAY: - /* These targets are just broken currently. */ - return; + faceTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + (slice % 6); + break; case GL_TEXTURE_CUBE_MAP: faceTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + texImage->Face; @@ -4075,27 +3191,13 @@ decompress_texture_image(struct gl_context *ctx, decompress->Height = height; } - /* setup VBO data */ - if (decompress->VAO == 0) { - /* create vertex array object */ - _mesa_GenVertexArrays(1, &decompress->VAO); - _mesa_BindVertexArray(decompress->VAO); - - /* create vertex array buffer */ - _mesa_GenBuffers(1, &decompress->VBO); - _mesa_BindBuffer(GL_ARRAY_BUFFER_ARB, decompress->VBO); - _mesa_BufferData(GL_ARRAY_BUFFER_ARB, sizeof(verts), - NULL, GL_DYNAMIC_DRAW_ARB); + if (use_glsl_version) { + _mesa_meta_setup_vertex_objects(&decompress->VAO, &decompress->VBO, true, + 2, 4, 0); - /* setup vertex arrays */ - _mesa_VertexPointer(2, GL_FLOAT, sizeof(struct vertex), OFFSET(x)); - _mesa_TexCoordPointer(3, GL_FLOAT, sizeof(struct vertex), OFFSET(tex)); - _mesa_EnableClientState(GL_VERTEX_ARRAY); - _mesa_EnableClientState(GL_TEXTURE_COORD_ARRAY); - } - else { - _mesa_BindVertexArray(decompress->VAO); - _mesa_BindBuffer(GL_ARRAY_BUFFER_ARB, decompress->VBO); + _mesa_meta_setup_blit_shader(ctx, target, &decompress->shaders); + } else { + _mesa_meta_setup_ff_tnl_for_blit(&decompress->VAO, &decompress->VBO, 3); } if (!decompress->Sampler) { @@ -4114,6 +3216,9 @@ decompress_texture_image(struct gl_context *ctx, _mesa_BindSampler(ctx->Texture.CurrentUnit, decompress->Sampler); } + /* Silence valgrind warnings about reading uninitialized stack. */ + memset(verts, 0, sizeof(verts)); + setup_texture_coords(faceTarget, slice, width, height, depth, verts[0].tex, verts[1].tex, @@ -4130,8 +3235,6 @@ decompress_texture_image(struct gl_context *ctx, verts[3].x = -1.0F; verts[3].y = 1.0F; - _mesa_MatrixMode(GL_PROJECTION); - _mesa_LoadIdentity(); _mesa_set_viewport(ctx, 0, 0, 0, width, height); /* upload new vertex data */ @@ -4139,7 +3242,9 @@ decompress_texture_image(struct gl_context *ctx, /* setup texture state */ _mesa_BindTexture(target, texObj->Name); - _mesa_set_enable(ctx, target, GL_TRUE); + + if (!use_glsl_version) + _mesa_set_enable(ctx, target, GL_TRUE); { /* save texture object state */ @@ -4199,7 +3304,8 @@ decompress_texture_image(struct gl_context *ctx, } /* disable texture unit */ - _mesa_set_enable(ctx, target, GL_FALSE); + if (!use_glsl_version) + _mesa_set_enable(ctx, target, GL_FALSE); _mesa_BindSampler(ctx->Texture.CurrentUnit, samplerSave); @@ -4231,8 +3337,7 @@ _mesa_meta_GetTexImage(struct gl_context *ctx, * unsigned, normalized values. We could handle signed and unnormalized * with floating point renderbuffers... */ - if (texImage->TexObject->Target != GL_TEXTURE_CUBE_MAP_ARRAY - && _mesa_is_format_compressed(texImage->TexFormat) && + if (_mesa_is_format_compressed(texImage->TexFormat) && _mesa_get_format_datatype(texImage->TexFormat) == GL_UNSIGNED_NORMALIZED) { struct gl_texture_object *texObj = texImage->TexObject; @@ -4241,7 +3346,8 @@ _mesa_meta_GetTexImage(struct gl_context *ctx, _mesa_unlock_texture(ctx, texObj); for (slice = 0; slice < texImage->Depth; slice++) { void *dst; - if (texImage->TexObject->Target == GL_TEXTURE_2D_ARRAY) { + if (texImage->TexObject->Target == GL_TEXTURE_2D_ARRAY + || texImage->TexObject->Target == GL_TEXTURE_CUBE_MAP_ARRAY) { /* Setup pixel packing. SkipPixels and SkipRows will be applied * in the decompress_texture_image() function's call to * glReadPixels but we need to compute the dest slice's address diff --git a/mesalib/src/mesa/drivers/common/meta.h b/mesalib/src/mesa/drivers/common/meta.h index 53d7b8ab5..fcf45c403 100644 --- a/mesalib/src/mesa/drivers/common/meta.h +++ b/mesalib/src/mesa/drivers/common/meta.h @@ -60,6 +60,311 @@ #define MESA_META_OCCLUSION_QUERY 0x400000 /**\}*/ +/** + * State which we may save/restore across meta ops. + * XXX this may be incomplete... + */ +struct save_state +{ + GLbitfield SavedState; /**< bitmask of MESA_META_* flags */ + + /* Always saved/restored with meta. */ + gl_api API; + + /** MESA_META_CLEAR (and others?) */ + struct gl_query_object *CurrentOcclusionObject; + + /** MESA_META_ALPHA_TEST */ + GLboolean AlphaEnabled; + GLenum AlphaFunc; + GLclampf AlphaRef; + + /** MESA_META_BLEND */ + GLbitfield BlendEnabled; + GLboolean ColorLogicOpEnabled; + + /** MESA_META_COLOR_MASK */ + GLubyte ColorMask[MAX_DRAW_BUFFERS][4]; + + /** MESA_META_DEPTH_TEST */ + struct gl_depthbuffer_attrib Depth; + + /** MESA_META_FOG */ + GLboolean Fog; + + /** MESA_META_PIXEL_STORE */ + struct gl_pixelstore_attrib Pack, Unpack; + + /** MESA_META_PIXEL_TRANSFER */ + GLfloat RedBias, RedScale; + GLfloat GreenBias, GreenScale; + GLfloat BlueBias, BlueScale; + GLfloat AlphaBias, AlphaScale; + GLfloat DepthBias, DepthScale; + GLboolean MapColorFlag; + + /** MESA_META_RASTERIZATION */ + GLenum FrontPolygonMode, BackPolygonMode; + GLboolean PolygonOffset; + GLboolean PolygonSmooth; + GLboolean PolygonStipple; + GLboolean PolygonCull; + + /** MESA_META_SCISSOR */ + struct gl_scissor_attrib Scissor; + + /** MESA_META_SHADER */ + GLboolean VertexProgramEnabled; + struct gl_vertex_program *VertexProgram; + GLboolean FragmentProgramEnabled; + struct gl_fragment_program *FragmentProgram; + GLboolean ATIFragmentShaderEnabled; + struct gl_shader_program *Shader[MESA_SHADER_STAGES]; + struct gl_shader_program *ActiveShader; + + /** MESA_META_STENCIL_TEST */ + struct gl_stencil_attrib Stencil; + + /** MESA_META_TRANSFORM */ + GLenum MatrixMode; + GLfloat ModelviewMatrix[16]; + GLfloat ProjectionMatrix[16]; + GLfloat TextureMatrix[16]; + + /** MESA_META_CLIP */ + GLbitfield ClipPlanesEnabled; + + /** MESA_META_TEXTURE */ + GLuint ActiveUnit; + GLuint ClientActiveUnit; + /** for unit[0] only */ + struct gl_texture_object *CurrentTexture[NUM_TEXTURE_TARGETS]; + /** mask of TEXTURE_2D_BIT, etc */ + GLbitfield TexEnabled[MAX_TEXTURE_UNITS]; + GLbitfield TexGenEnabled[MAX_TEXTURE_UNITS]; + GLuint EnvMode; /* unit[0] only */ + + /** MESA_META_VERTEX */ + struct gl_vertex_array_object *VAO; + struct gl_buffer_object *ArrayBufferObj; + + /** MESA_META_VIEWPORT */ + GLfloat ViewportX, ViewportY, ViewportW, ViewportH; + GLclampd DepthNear, DepthFar; + + /** MESA_META_CLAMP_FRAGMENT_COLOR */ + GLenum ClampFragmentColor; + + /** MESA_META_CLAMP_VERTEX_COLOR */ + GLenum ClampVertexColor; + + /** MESA_META_CONDITIONAL_RENDER */ + struct gl_query_object *CondRenderQuery; + GLenum CondRenderMode; + + /** MESA_META_SELECT_FEEDBACK */ + GLenum RenderMode; + struct gl_selection Select; + struct gl_feedback Feedback; + + /** MESA_META_MULTISAMPLE */ + struct gl_multisample_attrib Multisample; + + /** MESA_META_FRAMEBUFFER_SRGB */ + GLboolean sRGBEnabled; + + /** Miscellaneous (always disabled) */ + GLboolean Lighting; + GLboolean RasterDiscard; + GLboolean TransformFeedbackNeedsResume; +}; + +/** + * Temporary texture used for glBlitFramebuffer, glDrawPixels, etc. + * This is currently shared by all the meta ops. But we could create a + * separate one for each of glDrawPixel, glBlitFramebuffer, glCopyPixels, etc. + */ +struct temp_texture +{ + GLuint TexObj; + GLenum Target; /**< GL_TEXTURE_2D or GL_TEXTURE_RECTANGLE */ + GLsizei MinSize; /**< Min texture size to allocate */ + GLsizei MaxSize; /**< Max possible texture size */ + GLboolean NPOT; /**< Non-power of two size OK? */ + GLsizei Width, Height; /**< Current texture size */ + GLenum IntFormat; + GLfloat Sright, Ttop; /**< right, top texcoords */ +}; + +/** + * State for GLSL texture sampler which is used to generate fragment + * shader in _mesa_meta_generate_mipmap(). + */ +struct blit_shader { + const char *type; + const char *func; + const char *texcoords; + GLuint shader_prog; +}; + +/** + * Table of all sampler types and shaders for accessing them. + */ +struct blit_shader_table { + struct blit_shader sampler_1d; + struct blit_shader sampler_2d; + struct blit_shader sampler_3d; + struct blit_shader sampler_rect; + struct blit_shader sampler_cubemap; + struct blit_shader sampler_1d_array; + struct blit_shader sampler_2d_array; + struct blit_shader sampler_cubemap_array; +}; + +/** + * Indices in the blit_state->msaa_shaders[] array + * + * Note that setup_glsl_msaa_blit_shader() assumes that the _INT enums are one + * more than the non-_INT version and _UINT is one beyond that. + */ +enum blit_msaa_shader { + BLIT_MSAA_SHADER_2D_MULTISAMPLE_RESOLVE, + BLIT_MSAA_SHADER_2D_MULTISAMPLE_RESOLVE_INT, + BLIT_MSAA_SHADER_2D_MULTISAMPLE_RESOLVE_UINT, + BLIT_MSAA_SHADER_2D_MULTISAMPLE_COPY, + BLIT_MSAA_SHADER_2D_MULTISAMPLE_COPY_INT, + BLIT_MSAA_SHADER_2D_MULTISAMPLE_COPY_UINT, + BLIT_MSAA_SHADER_2D_MULTISAMPLE_DEPTH_RESOLVE, + BLIT_MSAA_SHADER_2D_MULTISAMPLE_DEPTH_COPY, + BLIT_MSAA_SHADER_COUNT, +}; + +/** + * State for glBlitFramebufer() + */ +struct blit_state +{ + GLuint VAO; + GLuint VBO; + GLuint DepthFP; + struct blit_shader_table shaders; + GLuint msaa_shaders[BLIT_MSAA_SHADER_COUNT]; + struct temp_texture depthTex; +}; + + +/** + * State for glClear() + */ +struct clear_state +{ + GLuint VAO; + GLuint VBO; + GLuint ShaderProg; + GLint ColorLocation; + GLint LayerLocation; + + GLuint IntegerShaderProg; + GLint IntegerColorLocation; + GLint IntegerLayerLocation; +}; + + +/** + * State for glCopyPixels() + */ +struct copypix_state +{ + GLuint VAO; + GLuint VBO; +}; + + +/** + * State for glDrawPixels() + */ +struct drawpix_state +{ + GLuint VAO; + GLuint VBO; + + GLuint StencilFP; /**< Fragment program for drawing stencil images */ + GLuint DepthFP; /**< Fragment program for drawing depth images */ +}; + + +/** + * State for glBitmap() + */ +struct bitmap_state +{ + GLuint VAO; + GLuint VBO; + struct temp_texture Tex; /**< separate texture from other meta ops */ +}; + +/** + * State for _mesa_meta_generate_mipmap() + */ +struct gen_mipmap_state +{ + GLuint VAO; + GLuint VBO; + GLuint FBO; + GLuint Sampler; + + struct blit_shader_table shaders; +}; + +/** + * State for texture decompression + */ +struct decompress_state +{ + GLuint VAO; + GLuint VBO, FBO, RBO, Sampler; + GLint Width, Height; + + struct blit_shader_table shaders; +}; + +/** + * State for glDrawTex() + */ +struct drawtex_state +{ + GLuint VAO; + GLuint VBO; +}; + +#define MAX_META_OPS_DEPTH 8 +/** + * All per-context meta state. + */ +struct gl_meta_state +{ + /** Stack of state saved during meta-ops */ + struct save_state Save[MAX_META_OPS_DEPTH]; + /** Save stack depth */ + GLuint SaveStackDepth; + + struct temp_texture TempTex; + + struct blit_state Blit; /**< For _mesa_meta_BlitFramebuffer() */ + struct clear_state Clear; /**< For _mesa_meta_Clear() */ + struct copypix_state CopyPix; /**< For _mesa_meta_CopyPixels() */ + struct drawpix_state DrawPix; /**< For _mesa_meta_DrawPixels() */ + struct bitmap_state Bitmap; /**< For _mesa_meta_Bitmap() */ + struct gen_mipmap_state Mipmap; /**< For _mesa_meta_GenerateMipmap() */ + struct decompress_state Decompress; /**< For texture decompression */ + struct drawtex_state DrawTex; /**< For _mesa_meta_DrawTex() */ +}; + +struct vertex { + GLfloat x, y, z, tex[4]; + GLfloat r, g, b, a; +}; + extern void _mesa_meta_init(struct gl_context *ctx); @@ -130,4 +435,60 @@ extern void _mesa_meta_DrawTex(struct gl_context *ctx, GLfloat x, GLfloat y, GLfloat z, GLfloat width, GLfloat height); +/* meta-internal functions */ +GLuint +_mesa_meta_compile_shader_with_debug(struct gl_context *ctx, GLenum target, + const GLcharARB *source); + + +GLuint +_mesa_meta_link_program_with_debug(struct gl_context *ctx, GLuint program); + +GLboolean +_mesa_meta_alloc_texture(struct temp_texture *tex, + GLsizei width, GLsizei height, GLenum intFormat); + +struct temp_texture * +_mesa_meta_get_temp_texture(struct gl_context *ctx); + +struct temp_texture * +_mesa_meta_get_temp_depth_texture(struct gl_context *ctx); + +void +_mesa_meta_setup_vertex_objects(GLuint *VAO, GLuint *VBO, + bool use_generic_attributes, + unsigned vertex_size, unsigned texcoord_size, + unsigned color_size); + +void +_mesa_meta_setup_ff_tnl_for_blit(GLuint *VAO, GLuint *VBO, + unsigned texcoord_size); + +void +_mesa_meta_setup_drawpix_texture(struct gl_context *ctx, + struct temp_texture *tex, + GLboolean newTex, + GLsizei width, GLsizei height, + GLenum format, GLenum type, + const GLvoid *pixels); + +void +_mesa_meta_setup_copypix_texture(struct gl_context *ctx, + struct temp_texture *tex, + GLint srcX, GLint srcY, + GLsizei width, GLsizei height, + GLenum intFormat, + GLenum filter); + +void +_mesa_meta_setup_blit_shader(struct gl_context *ctx, + GLenum target, + struct blit_shader_table *table); + +void +_mesa_meta_glsl_blit_cleanup(struct blit_state *blit); + +void +_mesa_meta_blit_shader_table_cleanup(struct blit_shader_table *table); + #endif /* META_H */ diff --git a/mesalib/src/mesa/drivers/common/meta_blit.c b/mesalib/src/mesa/drivers/common/meta_blit.c new file mode 100644 index 000000000..907c2cdf3 --- /dev/null +++ b/mesalib/src/mesa/drivers/common/meta_blit.c @@ -0,0 +1,825 @@ +/* + * Mesa 3-D graphics library + * + * Copyright (C) 2009 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, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "main/glheader.h" +#include "main/mtypes.h" +#include "main/imports.h" +#include "main/arbprogram.h" +#include "main/arrayobj.h" +#include "main/blend.h" +#include "main/condrender.h" +#include "main/depth.h" +#include "main/enable.h" +#include "main/enums.h" +#include "main/fbobject.h" +#include "main/macros.h" +#include "main/matrix.h" +#include "main/multisample.h" +#include "main/objectlabel.h" +#include "main/readpix.h" +#include "main/shaderapi.h" +#include "main/texobj.h" +#include "main/texenv.h" +#include "main/teximage.h" +#include "main/texparam.h" +#include "main/varray.h" +#include "main/viewport.h" +#include "swrast/swrast.h" +#include "drivers/common/meta.h" +#include "../glsl/ralloc.h" + +/** Return offset in bytes of the field within a vertex struct */ +#define OFFSET(FIELD) ((void *) offsetof(struct vertex, FIELD)) + +/** + * One-time init for drawing depth pixels. + */ +static void +init_blit_depth_pixels(struct gl_context *ctx) +{ + static const char *program = + "!!ARBfp1.0\n" + "TEX result.depth, fragment.texcoord[0], texture[0], %s; \n" + "END \n"; + char program2[200]; + struct blit_state *blit = &ctx->Meta->Blit; + struct temp_texture *tex = _mesa_meta_get_temp_texture(ctx); + const char *texTarget; + + assert(blit->DepthFP == 0); + + /* replace %s with "RECT" or "2D" */ + assert(strlen(program) + 4 < sizeof(program2)); + if (tex->Target == GL_TEXTURE_RECTANGLE) + texTarget = "RECT"; + else + texTarget = "2D"; + _mesa_snprintf(program2, sizeof(program2), program, texTarget); + + _mesa_GenProgramsARB(1, &blit->DepthFP); + _mesa_BindProgramARB(GL_FRAGMENT_PROGRAM_ARB, blit->DepthFP); + _mesa_ProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, + strlen(program2), (const GLubyte *) program2); +} + +static void +setup_glsl_msaa_blit_shader(struct gl_context *ctx, + struct blit_state *blit, + struct gl_renderbuffer *src_rb, + GLenum target) +{ + const char *vs_source; + char *fs_source; + GLuint vs, fs; + void *mem_ctx; + enum blit_msaa_shader shader_index; + bool dst_is_msaa = false; + GLenum src_datatype; + const char *vec4_prefix; + char *name; + + if (src_rb) { + src_datatype = _mesa_get_format_datatype(src_rb->Format); + } else { + /* depth-or-color glCopyTexImage fallback path that passes a NULL rb and + * doesn't handle integer. + */ + src_datatype = GL_UNSIGNED_NORMALIZED; + } + + if (ctx->DrawBuffer->Visual.samples > 1) { + /* If you're calling meta_BlitFramebuffer with the destination + * multisampled, this is the only path that will work -- swrast and + * CopyTexImage won't work on it either. + */ + assert(ctx->Extensions.ARB_sample_shading); + + dst_is_msaa = true; + + /* We need shader invocation per sample, not per pixel */ + _mesa_set_enable(ctx, GL_MULTISAMPLE, GL_TRUE); + _mesa_set_enable(ctx, GL_SAMPLE_SHADING, GL_TRUE); + _mesa_MinSampleShading(1.0); + } + + switch (target) { + case GL_TEXTURE_2D_MULTISAMPLE: + if (src_rb->_BaseFormat == GL_DEPTH_COMPONENT || + src_rb->_BaseFormat == GL_DEPTH_STENCIL) { + if (dst_is_msaa) + shader_index = BLIT_MSAA_SHADER_2D_MULTISAMPLE_DEPTH_COPY; + else + shader_index = BLIT_MSAA_SHADER_2D_MULTISAMPLE_DEPTH_RESOLVE; + } else { + if (dst_is_msaa) + shader_index = BLIT_MSAA_SHADER_2D_MULTISAMPLE_COPY; + else + shader_index = BLIT_MSAA_SHADER_2D_MULTISAMPLE_RESOLVE; + } + break; + default: + _mesa_problem(ctx, "Unkown texture target %s\n", + _mesa_lookup_enum_by_nr(target)); + shader_index = BLIT_MSAA_SHADER_2D_MULTISAMPLE_RESOLVE; + } + + /* We rely on the enum being sorted this way. */ + STATIC_ASSERT(BLIT_MSAA_SHADER_2D_MULTISAMPLE_RESOLVE_INT == + BLIT_MSAA_SHADER_2D_MULTISAMPLE_RESOLVE + 1); + STATIC_ASSERT(BLIT_MSAA_SHADER_2D_MULTISAMPLE_RESOLVE_UINT == + BLIT_MSAA_SHADER_2D_MULTISAMPLE_RESOLVE + 2); + if (src_datatype == GL_INT) { + shader_index++; + vec4_prefix = "i"; + } else if (src_datatype == GL_UNSIGNED_INT) { + shader_index += 2; + vec4_prefix = "u"; + } else { + vec4_prefix = ""; + } + + if (blit->msaa_shaders[shader_index]) { + _mesa_UseProgram(blit->msaa_shaders[shader_index]); + return; + } + + mem_ctx = ralloc_context(NULL); + + if (shader_index == BLIT_MSAA_SHADER_2D_MULTISAMPLE_DEPTH_RESOLVE || + shader_index == BLIT_MSAA_SHADER_2D_MULTISAMPLE_DEPTH_COPY) { + char *sample_index; + const char *arb_sample_shading_extension_string; + + if (dst_is_msaa) { + arb_sample_shading_extension_string = "#extension GL_ARB_sample_shading : enable"; + sample_index = "gl_SampleID"; + name = "depth MSAA copy"; + } else { + /* Don't need that extension, since we're drawing to a single-sampled + * destination. + */ + arb_sample_shading_extension_string = ""; + /* From the GL 4.3 spec: + * + * "If there is a multisample buffer (the value of SAMPLE_BUFFERS + * is one), then values are obtained from the depth samples in + * this buffer. It is recommended that the depth value of the + * centermost sample be used, though implementations may choose + * any function of the depth sample values at each pixel. + * + * We're slacking and instead of choosing centermost, we've got 0. + */ + sample_index = "0"; + name = "depth MSAA resolve"; + } + + vs_source = ralloc_asprintf(mem_ctx, + "#version 130\n" + "in vec2 position;\n" + "in vec2 textureCoords;\n" + "out vec2 texCoords;\n" + "void main()\n" + "{\n" + " texCoords = textureCoords;\n" + " gl_Position = vec4(position, 0.0, 1.0);\n" + "}\n"); + fs_source = ralloc_asprintf(mem_ctx, + "#version 130\n" + "#extension GL_ARB_texture_multisample : enable\n" + "%s\n" + "uniform sampler2DMS texSampler;\n" + "in vec2 texCoords;\n" + "out vec4 out_color;\n" + "\n" + "void main()\n" + "{\n" + " gl_FragDepth = texelFetch(texSampler, ivec2(texCoords), %s).r;\n" + "}\n", + arb_sample_shading_extension_string, + sample_index); + } else { + /* You can create 2D_MULTISAMPLE textures with 0 sample count (meaning 1 + * sample). Yes, this is ridiculous. + */ + int samples; + char *sample_resolve; + const char *arb_sample_shading_extension_string; + const char *merge_function; + name = ralloc_asprintf(mem_ctx, "%svec4 MSAA %s", + vec4_prefix, + dst_is_msaa ? "copy" : "resolve"); + + samples = MAX2(src_rb->NumSamples, 1); + + if (dst_is_msaa) { + arb_sample_shading_extension_string = "#extension GL_ARB_sample_shading : enable"; + sample_resolve = ralloc_asprintf(mem_ctx, " out_color = texelFetch(texSampler, ivec2(texCoords), gl_SampleID);"); + merge_function = ""; + } else { + int i; + int step; + + if (src_datatype == GL_INT || src_datatype == GL_UNSIGNED_INT) { + merge_function = + "gvec4 merge(gvec4 a, gvec4 b) { return (a >> gvec4(1)) + (b >> gvec4(1)) + (a & b & gvec4(1)); }\n"; + } else { + /* The divide will happen at the end for floats. */ + merge_function = + "vec4 merge(vec4 a, vec4 b) { return (a + b); }\n"; + } + + arb_sample_shading_extension_string = ""; + + /* We're assuming power of two samples for this resolution procedure. + * + * To avoid losing any floating point precision if the samples all + * happen to have the same value, we merge pairs of values at a time + * (so the floating point exponent just gets increased), rather than + * doing a naive sum and dividing. + */ + assert((samples & (samples - 1)) == 0); + /* Fetch each individual sample. */ + sample_resolve = rzalloc_size(mem_ctx, 1); + for (i = 0; i < samples; i++) { + ralloc_asprintf_append(&sample_resolve, + " gvec4 sample_1_%d = texelFetch(texSampler, ivec2(texCoords), %d);\n", + i, i); + } + /* Now, merge each pair of samples, then merge each pair of those, + * etc. + */ + for (step = 2; step <= samples; step *= 2) { + for (i = 0; i < samples; i += step) { + ralloc_asprintf_append(&sample_resolve, + " gvec4 sample_%d_%d = merge(sample_%d_%d, sample_%d_%d);\n", + step, i, + step / 2, i, + step / 2, i + step / 2); + } + } + + /* Scale the final result. */ + if (src_datatype == GL_UNSIGNED_INT || src_datatype == GL_INT) { + ralloc_asprintf_append(&sample_resolve, + " out_color = sample_%d_0;\n", + samples); + } else { + ralloc_asprintf_append(&sample_resolve, + " out_color = sample_%d_0 / %f;\n", + samples, (float)samples); + } + } + + vs_source = ralloc_asprintf(mem_ctx, + "#version 130\n" + "in vec2 position;\n" + "in vec2 textureCoords;\n" + "out vec2 texCoords;\n" + "void main()\n" + "{\n" + " texCoords = textureCoords;\n" + " gl_Position = vec4(position, 0.0, 1.0);\n" + "}\n"); + fs_source = ralloc_asprintf(mem_ctx, + "#version 130\n" + "#extension GL_ARB_texture_multisample : enable\n" + "%s\n" + "#define gvec4 %svec4\n" + "uniform %ssampler2DMS texSampler;\n" + "in vec2 texCoords;\n" + "out gvec4 out_color;\n" + "\n" + "%s" /* merge_function */ + "void main()\n" + "{\n" + "%s\n" /* sample_resolve */ + "}\n", + arb_sample_shading_extension_string, + vec4_prefix, + vec4_prefix, + merge_function, + sample_resolve); + } + + vs = _mesa_meta_compile_shader_with_debug(ctx, GL_VERTEX_SHADER, vs_source); + fs = _mesa_meta_compile_shader_with_debug(ctx, GL_FRAGMENT_SHADER, fs_source); + + blit->msaa_shaders[shader_index] = _mesa_CreateProgramObjectARB(); + _mesa_AttachShader(blit->msaa_shaders[shader_index], fs); + _mesa_DeleteObjectARB(fs); + _mesa_AttachShader(blit->msaa_shaders[shader_index], vs); + _mesa_DeleteObjectARB(vs); + _mesa_BindAttribLocation(blit->msaa_shaders[shader_index], 0, "position"); + _mesa_BindAttribLocation(blit->msaa_shaders[shader_index], 1, "texcoords"); + _mesa_meta_link_program_with_debug(ctx, blit->msaa_shaders[shader_index]); + _mesa_ObjectLabel(GL_PROGRAM, blit->msaa_shaders[shader_index], -1, name); + ralloc_free(mem_ctx); + + _mesa_UseProgram(blit->msaa_shaders[shader_index]); +} + +static void +setup_glsl_blit_framebuffer(struct gl_context *ctx, + struct blit_state *blit, + struct gl_renderbuffer *src_rb, + GLenum target) +{ + /* target = GL_TEXTURE_RECTANGLE is not supported in GLES 3.0 */ + assert(_mesa_is_desktop_gl(ctx) || target == GL_TEXTURE_2D); + + _mesa_meta_setup_vertex_objects(&blit->VAO, &blit->VBO, true, 2, 2, 0); + + if (target == GL_TEXTURE_2D_MULTISAMPLE) { + setup_glsl_msaa_blit_shader(ctx, blit, src_rb, target); + } else { + _mesa_meta_setup_blit_shader(ctx, target, &blit->shaders); + } +} + +/** + * Try to do a color or depth glBlitFramebuffer using texturing. + * + * We can do this when the src renderbuffer is actually a texture, or when the + * driver exposes BindRenderbufferTexImage(). + */ +static bool +blitframebuffer_texture(struct gl_context *ctx, + GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, + GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, + GLenum filter, GLint flipX, GLint flipY, + GLboolean glsl_version, GLboolean do_depth) +{ + const struct gl_framebuffer *readFb = ctx->ReadBuffer; + int att_index = do_depth ? BUFFER_DEPTH : readFb->_ColorReadBufferIndex; + const struct gl_renderbuffer_attachment *readAtt = + &readFb->Attachment[att_index]; + struct blit_state *blit = &ctx->Meta->Blit; + const GLint dstX = MIN2(dstX0, dstX1); + const GLint dstY = MIN2(dstY0, dstY1); + const GLint dstW = abs(dstX1 - dstX0); + const GLint dstH = abs(dstY1 - dstY0); + struct gl_texture_object *texObj; + GLuint srcLevel; + GLint baseLevelSave; + GLint maxLevelSave; + GLenum target; + GLuint sampler, samplerSave = + ctx->Texture.Unit[ctx->Texture.CurrentUnit].Sampler ? + ctx->Texture.Unit[ctx->Texture.CurrentUnit].Sampler->Name : 0; + GLuint tempTex = 0; + struct gl_renderbuffer *rb = readAtt->Renderbuffer; + + if (rb->NumSamples && !ctx->Extensions.ARB_texture_multisample) + return false; + + if (filter == GL_SCALED_RESOLVE_FASTEST_EXT || + filter == GL_SCALED_RESOLVE_NICEST_EXT) { + filter = GL_LINEAR; + } + + if (readAtt->Texture) { + /* If there's a texture attached of a type we can handle, then just use + * it directly. + */ + srcLevel = readAtt->TextureLevel; + texObj = readAtt->Texture; + target = texObj->Target; + + switch (target) { + case GL_TEXTURE_2D: + case GL_TEXTURE_RECTANGLE: + case GL_TEXTURE_2D_MULTISAMPLE: + break; + default: + return false; + } + } else if (ctx->Driver.BindRenderbufferTexImage) { + /* Otherwise, we need the driver to be able to bind a renderbuffer as + * a texture image. + */ + struct gl_texture_image *texImage; + + if (rb->NumSamples > 1) + target = GL_TEXTURE_2D_MULTISAMPLE; + else + target = GL_TEXTURE_2D; + + _mesa_GenTextures(1, &tempTex); + _mesa_BindTexture(target, tempTex); + srcLevel = 0; + texObj = _mesa_lookup_texture(ctx, tempTex); + texImage = _mesa_get_tex_image(ctx, texObj, target, srcLevel); + + if (!ctx->Driver.BindRenderbufferTexImage(ctx, rb, texImage)) { + _mesa_DeleteTextures(1, &tempTex); + return false; + } else { + if (ctx->Driver.FinishRenderTexture && + !rb->NeedsFinishRenderTexture) { + rb->NeedsFinishRenderTexture = true; + ctx->Driver.FinishRenderTexture(ctx, rb); + } + + if (_mesa_is_winsys_fbo(readFb)) { + GLint temp = srcY0; + srcY0 = rb->Height - srcY1; + srcY1 = rb->Height - temp; + flipY = -flipY; + } + } + } else { + return false; + } + + baseLevelSave = texObj->BaseLevel; + maxLevelSave = texObj->MaxLevel; + + if (glsl_version) { + setup_glsl_blit_framebuffer(ctx, blit, rb, target); + } + else { + _mesa_meta_setup_ff_tnl_for_blit(&ctx->Meta->Blit.VAO, + &ctx->Meta->Blit.VBO, + 2); + } + + _mesa_GenSamplers(1, &sampler); + _mesa_BindSampler(ctx->Texture.CurrentUnit, sampler); + + /* + printf("Blit from texture!\n"); + printf(" srcAtt %p dstAtt %p\n", readAtt, drawAtt); + printf(" srcTex %p dstText %p\n", texObj, drawAtt->Texture); + */ + + /* Prepare src texture state */ + _mesa_BindTexture(target, texObj->Name); + _mesa_SamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, filter); + _mesa_SamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, filter); + if (target != GL_TEXTURE_RECTANGLE_ARB) { + _mesa_TexParameteri(target, GL_TEXTURE_BASE_LEVEL, srcLevel); + _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, srcLevel); + } + _mesa_SamplerParameteri(sampler, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + _mesa_SamplerParameteri(sampler, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + /* Always do our blits with no net sRGB decode or encode. + * + * However, if both the src and dst can be srgb decode/encoded, enable them + * so that we do any blending (from scaling or from MSAA resolves) in the + * right colorspace. + * + * Our choice of not doing any net encode/decode is from the GL 3.0 + * specification: + * + * "Blit operations bypass the fragment pipeline. The only fragment + * operations which affect a blit are the pixel ownership test and the + * scissor test." + * + * The GL 4.4 specification disagrees and says that the sRGB part of the + * fragment pipeline applies, but this was found to break applications. + */ + if (ctx->Extensions.EXT_texture_sRGB_decode) { + if (_mesa_get_format_color_encoding(rb->Format) == GL_SRGB && + ctx->DrawBuffer->Visual.sRGBCapable) { + _mesa_SamplerParameteri(sampler, GL_TEXTURE_SRGB_DECODE_EXT, + GL_DECODE_EXT); + _mesa_set_framebuffer_srgb(ctx, GL_TRUE); + } else { + _mesa_SamplerParameteri(sampler, GL_TEXTURE_SRGB_DECODE_EXT, + GL_SKIP_DECODE_EXT); + /* set_framebuffer_srgb was set by _mesa_meta_begin(). */ + } + } + + if (!glsl_version) { + _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + _mesa_set_enable(ctx, target, GL_TRUE); + } + + /* Prepare vertex data (the VBO was previously created and bound) */ + { + struct vertex verts[4]; + GLfloat s0, t0, s1, t1; + + if (target == GL_TEXTURE_2D) { + const struct gl_texture_image *texImage + = _mesa_select_tex_image(ctx, texObj, target, srcLevel); + s0 = srcX0 / (float) texImage->Width; + s1 = srcX1 / (float) texImage->Width; + t0 = srcY0 / (float) texImage->Height; + t1 = srcY1 / (float) texImage->Height; + } + else { + assert(target == GL_TEXTURE_RECTANGLE_ARB || + target == GL_TEXTURE_2D_MULTISAMPLE); + s0 = (float) srcX0; + s1 = (float) srcX1; + t0 = (float) srcY0; + t1 = (float) srcY1; + } + + /* Silence valgrind warnings about reading uninitialized stack. */ + memset(verts, 0, sizeof(verts)); + + /* setup vertex positions */ + verts[0].x = -1.0F * flipX; + verts[0].y = -1.0F * flipY; + verts[1].x = 1.0F * flipX; + verts[1].y = -1.0F * flipY; + verts[2].x = 1.0F * flipX; + verts[2].y = 1.0F * flipY; + verts[3].x = -1.0F * flipX; + verts[3].y = 1.0F * flipY; + + verts[0].tex[0] = s0; + verts[0].tex[1] = t0; + verts[1].tex[0] = s1; + verts[1].tex[1] = t0; + verts[2].tex[0] = s1; + verts[2].tex[1] = t1; + verts[3].tex[0] = s0; + verts[3].tex[1] = t1; + + _mesa_BufferSubData(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts); + } + + /* setup viewport */ + _mesa_set_viewport(ctx, 0, dstX, dstY, dstW, dstH); + _mesa_ColorMask(!do_depth, !do_depth, !do_depth, !do_depth); + _mesa_set_enable(ctx, GL_DEPTH_TEST, do_depth); + _mesa_DepthMask(do_depth); + _mesa_DepthFunc(GL_ALWAYS); + + _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4); + + /* Restore texture object state, the texture binding will + * be restored by _mesa_meta_end(). + */ + if (target != GL_TEXTURE_RECTANGLE_ARB) { + _mesa_TexParameteri(target, GL_TEXTURE_BASE_LEVEL, baseLevelSave); + _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, maxLevelSave); + } + + _mesa_BindSampler(ctx->Texture.CurrentUnit, samplerSave); + _mesa_DeleteSamplers(1, &sampler); + if (tempTex) + _mesa_DeleteTextures(1, &tempTex); + + return true; +} + +/** + * Meta implementation of ctx->Driver.BlitFramebuffer() in terms + * of texture mapping and polygon rendering. + */ +void +_mesa_meta_BlitFramebuffer(struct gl_context *ctx, + GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, + GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, + GLbitfield mask, GLenum filter) +{ + struct blit_state *blit = &ctx->Meta->Blit; + struct temp_texture *tex = _mesa_meta_get_temp_texture(ctx); + struct temp_texture *depthTex = _mesa_meta_get_temp_depth_texture(ctx); + const GLsizei maxTexSize = tex->MaxSize; + const GLint srcX = MIN2(srcX0, srcX1); + const GLint srcY = MIN2(srcY0, srcY1); + const GLint srcW = abs(srcX1 - srcX0); + const GLint srcH = abs(srcY1 - srcY0); + const GLint dstX = MIN2(dstX0, dstX1); + const GLint dstY = MIN2(dstY0, dstY1); + const GLint dstW = abs(dstX1 - dstX0); + const GLint dstH = abs(dstY1 - dstY0); + const GLint srcFlipX = (srcX1 - srcX0) / srcW; + const GLint srcFlipY = (srcY1 - srcY0) / srcH; + const GLint dstFlipX = (dstX1 - dstX0) / dstW; + const GLint dstFlipY = (dstY1 - dstY0) / dstH; + const GLint flipX = srcFlipX * dstFlipX; + const GLint flipY = srcFlipY * dstFlipY; + + struct vertex verts[4]; + GLboolean newTex; + const GLboolean use_glsl_version = ctx->Extensions.ARB_vertex_shader && + ctx->Extensions.ARB_fragment_shader; + + /* In addition to falling back if the blit size is larger than the maximum + * texture size, fallback if the source is multisampled. This fallback can + * be removed once Mesa gets support ARB_texture_multisample. + */ + if (srcW > maxTexSize || srcH > maxTexSize) { + /* XXX avoid this fallback */ + goto fallback; + } + + /* Multisample texture blit support requires texture multisample. */ + if (ctx->ReadBuffer->Visual.samples > 0 && + !ctx->Extensions.ARB_texture_multisample) { + goto fallback; + } + + /* only scissor effects blit so save/clear all other relevant state */ + _mesa_meta_begin(ctx, ~MESA_META_SCISSOR); + + /* Try faster, direct texture approach first */ + if (mask & GL_COLOR_BUFFER_BIT) { + if (blitframebuffer_texture(ctx, srcX0, srcY0, srcX1, srcY1, + dstX0, dstY0, dstX1, dstY1, + filter, dstFlipX, dstFlipY, + use_glsl_version, false)) { + mask &= ~GL_COLOR_BUFFER_BIT; + if (mask == 0x0) { + _mesa_meta_end(ctx); + return; + } + } + } + + if (mask & GL_DEPTH_BUFFER_BIT && use_glsl_version) { + if (blitframebuffer_texture(ctx, srcX0, srcY0, srcX1, srcY1, + dstX0, dstY0, dstX1, dstY1, + filter, dstFlipX, dstFlipY, + use_glsl_version, true)) { + mask &= ~GL_DEPTH_BUFFER_BIT; + if (mask == 0x0) { + _mesa_meta_end(ctx); + return; + } + } + } + + /* Choose between glsl version and fixed function version of + * BlitFramebuffer function. + */ + if (use_glsl_version) { + setup_glsl_blit_framebuffer(ctx, blit, NULL, tex->Target); + } + else { + _mesa_meta_setup_ff_tnl_for_blit(&blit->VAO, &blit->VBO, 2); + } + + /* Silence valgrind warnings about reading uninitialized stack. */ + memset(verts, 0, sizeof(verts)); + + /* Continue with "normal" approach which involves copying the src rect + * into a temporary texture and is "blitted" by drawing a textured quad. + */ + { + /* setup vertex positions */ + verts[0].x = -1.0F * flipX; + verts[0].y = -1.0F * flipY; + verts[1].x = 1.0F * flipX; + verts[1].y = -1.0F * flipY; + verts[2].x = 1.0F * flipX; + verts[2].y = 1.0F * flipY; + verts[3].x = -1.0F * flipX; + verts[3].y = 1.0F * flipY; + + } + + if (!use_glsl_version) + _mesa_set_enable(ctx, tex->Target, GL_TRUE); + + if (mask & GL_COLOR_BUFFER_BIT) { + const struct gl_framebuffer *readFb = ctx->ReadBuffer; + const struct gl_renderbuffer *colorReadRb = readFb->_ColorReadBuffer; + const GLenum rb_base_format = + _mesa_base_tex_format(ctx, colorReadRb->InternalFormat); + + /* Using the exact source rectangle to create the texture does incorrect + * linear filtering along the edges. So, allocate the texture extended along + * edges by one pixel in x, y directions. + */ + _mesa_meta_setup_copypix_texture(ctx, tex, + srcX - 1, srcY - 1, srcW + 2, srcH + 2, + rb_base_format, filter); + /* texcoords (after texture allocation!) */ + { + verts[0].tex[0] = 1.0F; + verts[0].tex[1] = 1.0F; + verts[1].tex[0] = tex->Sright - 1.0F; + verts[1].tex[1] = 1.0F; + verts[2].tex[0] = tex->Sright - 1.0F; + verts[2].tex[1] = tex->Ttop - 1.0F; + verts[3].tex[0] = 1.0F; + verts[3].tex[1] = tex->Ttop - 1.0F; + + /* upload new vertex data */ + _mesa_BufferSubData(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts); + } + + _mesa_set_viewport(ctx, 0, dstX, dstY, dstW, dstH); + _mesa_ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + _mesa_set_enable(ctx, GL_DEPTH_TEST, GL_FALSE); + _mesa_DepthMask(GL_FALSE); + _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4); + mask &= ~GL_COLOR_BUFFER_BIT; + } + + if ((mask & GL_DEPTH_BUFFER_BIT) && + _mesa_is_desktop_gl(ctx) && + ctx->Extensions.ARB_depth_texture && + ctx->Extensions.ARB_fragment_program) { + + GLuint *tmp = malloc(srcW * srcH * sizeof(GLuint)); + + if (tmp) { + + newTex = _mesa_meta_alloc_texture(depthTex, srcW, srcH, + GL_DEPTH_COMPONENT); + _mesa_ReadPixels(srcX, srcY, srcW, srcH, GL_DEPTH_COMPONENT, + GL_UNSIGNED_INT, tmp); + _mesa_meta_setup_drawpix_texture(ctx, depthTex, newTex, + srcW, srcH, GL_DEPTH_COMPONENT, + GL_UNSIGNED_INT, tmp); + + /* texcoords (after texture allocation!) */ + { + verts[0].tex[0] = 0.0F; + verts[0].tex[1] = 0.0F; + verts[1].tex[0] = depthTex->Sright; + verts[1].tex[1] = 0.0F; + verts[2].tex[0] = depthTex->Sright; + verts[2].tex[1] = depthTex->Ttop; + verts[3].tex[0] = 0.0F; + verts[3].tex[1] = depthTex->Ttop; + + /* upload new vertex data */ + _mesa_BufferSubData(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts); + } + + if (!blit->DepthFP) + init_blit_depth_pixels(ctx); + + _mesa_BindProgramARB(GL_FRAGMENT_PROGRAM_ARB, blit->DepthFP); + _mesa_set_enable(ctx, GL_FRAGMENT_PROGRAM_ARB, GL_TRUE); + _mesa_ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); + _mesa_set_enable(ctx, GL_DEPTH_TEST, GL_TRUE); + _mesa_DepthFunc(GL_ALWAYS); + _mesa_DepthMask(GL_TRUE); + + _mesa_set_viewport(ctx, 0, dstX, dstY, dstW, dstH); + _mesa_BufferSubData(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts); + _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4); + mask &= ~GL_DEPTH_BUFFER_BIT; + + free(tmp); + } + } + + if (mask & GL_STENCIL_BUFFER_BIT) { + /* XXX can't easily do stencil */ + } + + if (!use_glsl_version) + _mesa_set_enable(ctx, tex->Target, GL_FALSE); + + _mesa_meta_end(ctx); + +fallback: + if (mask) { + _swrast_BlitFramebuffer(ctx, srcX0, srcY0, srcX1, srcY1, + dstX0, dstY0, dstX1, dstY1, mask, filter); + } +} + +void +_mesa_meta_glsl_blit_cleanup(struct blit_state *blit) +{ + if (blit->VAO) { + _mesa_DeleteVertexArrays(1, &blit->VAO); + blit->VAO = 0; + _mesa_DeleteBuffers(1, &blit->VBO); + blit->VBO = 0; + } + if (blit->DepthFP) { + _mesa_DeleteProgramsARB(1, &blit->DepthFP); + blit->DepthFP = 0; + } + + _mesa_meta_blit_shader_table_cleanup(&blit->shaders); + + _mesa_DeleteTextures(1, &blit->depthTex.TexObj); + blit->depthTex.TexObj = 0; +} diff --git a/mesalib/src/mesa/drivers/dri/common/dri_util.c b/mesalib/src/mesa/drivers/dri/common/dri_util.c index 83841def5..aed73c73f 100644 --- a/mesalib/src/mesa/drivers/dri/common/dri_util.c +++ b/mesalib/src/mesa/drivers/dri/common/dri_util.c @@ -49,6 +49,7 @@ #include "../glsl/glsl_parser_extras.h" #include "main/mtypes.h" #include "main/version.h" +#include "main/errors.h" #include "main/macros.h" PUBLIC const char __dri2ConfigOptions[] = @@ -448,8 +449,11 @@ driContextSetFlags(struct gl_context *ctx, uint32_t flags) if ((flags & __DRI_CTX_FLAG_FORWARD_COMPATIBLE) != 0) ctx->Const.ContextFlags |= GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT; if ((flags & __DRI_CTX_FLAG_DEBUG) != 0) { + struct gl_debug_state *debug = _mesa_get_debug_state(ctx); + if (debug) { + debug->DebugOutput = GL_TRUE; + } ctx->Const.ContextFlags |= GL_CONTEXT_FLAG_DEBUG_BIT; - ctx->Debug.DebugOutput = GL_TRUE; } } @@ -764,12 +768,13 @@ const __DRIdri2Extension driDRI2Extension = { }; const __DRIswrastExtension driSWRastExtension = { - { __DRI_SWRAST, 4 }, - driSWRastCreateNewScreen, - driCreateNewDrawable, - driCreateNewContextForAPI, - driCreateContextAttribs, - driSWRastCreateNewScreen2, + .base = { __DRI_SWRAST, 4 }, + + .createNewScreen = driSWRastCreateNewScreen, + .createNewDrawable = driCreateNewDrawable, + .createNewContextForAPI = driCreateNewContextForAPI, + .createContextAttribs = driCreateContextAttribs, + .createNewScreen2 = driSWRastCreateNewScreen2, }; const __DRI2configQueryExtension dri2ConfigQueryExtension = { @@ -869,7 +874,7 @@ driImageFormatToGLFormat(uint32_t image_format) /** Image driver interface */ const __DRIimageDriverExtension driImageDriverExtension = { - .base = { __DRI_IMAGE_DRIVER, __DRI_IMAGE_DRIVER_VERSION }, + .base = { __DRI_IMAGE_DRIVER, 1 }, .createNewScreen2 = driCreateNewScreen2, .createNewDrawable = driCreateNewDrawable, @@ -888,6 +893,7 @@ static void driCopySubBuffer(__DRIdrawable *pdp, int x, int y, /* for swrast only */ const __DRIcopySubBufferExtension driCopySubBufferExtension = { - { __DRI_COPY_SUB_BUFFER, 1 }, - .copySubBuffer = driCopySubBuffer, + .base = { __DRI_COPY_SUB_BUFFER, 1 }, + + .copySubBuffer = driCopySubBuffer, }; diff --git a/mesalib/src/mesa/main/api_arrayelt.c b/mesalib/src/mesa/main/api_arrayelt.c index 29a57c8e5..05cbc0f1f 100644 --- a/mesalib/src/mesa/main/api_arrayelt.c +++ b/mesalib/src/mesa/main/api_arrayelt.c @@ -1458,7 +1458,8 @@ _ae_destroy_context(struct gl_context *ctx) static void check_vbo(AEcontext *actx, struct gl_buffer_object *vbo) { - if (_mesa_is_bufferobj(vbo) && !_mesa_bufferobj_mapped(vbo)) { + if (_mesa_is_bufferobj(vbo) && + !_mesa_bufferobj_mapped(vbo, MAP_INTERNAL)) { GLuint i; for (i = 0; i < actx->nr_vbos; i++) if (actx->vbo[i] == vbo) @@ -1633,7 +1634,8 @@ _ae_map_vbos(struct gl_context *ctx) ctx->Driver.MapBufferRange(ctx, 0, actx->vbo[i]->Size, GL_MAP_READ_BIT, - actx->vbo[i]); + actx->vbo[i], + MAP_INTERNAL); if (actx->nr_vbos) actx->mapped_vbos = GL_TRUE; @@ -1655,7 +1657,7 @@ _ae_unmap_vbos(struct gl_context *ctx) assert (!actx->NewState); for (i = 0; i < actx->nr_vbos; i++) - ctx->Driver.UnmapBuffer(ctx, actx->vbo[i]); + ctx->Driver.UnmapBuffer(ctx, actx->vbo[i], MAP_INTERNAL); actx->mapped_vbos = GL_FALSE; } @@ -1701,7 +1703,8 @@ _ae_ArrayElement(GLint elt) /* emit generic attribute elements */ for (at = actx->attribs; at->func; at++) { const GLubyte *src - = ADD_POINTERS(at->array->BufferObj->Pointer, at->array->Ptr) + = ADD_POINTERS(at->array->BufferObj->Mappings[MAP_INTERNAL].Pointer, + at->array->Ptr) + elt * at->array->StrideB; at->func(at->index, src); } @@ -1709,7 +1712,8 @@ _ae_ArrayElement(GLint elt) /* emit conventional arrays elements */ for (aa = actx->arrays; aa->offset != -1 ; aa++) { const GLubyte *src - = ADD_POINTERS(aa->array->BufferObj->Pointer, aa->array->Ptr) + = ADD_POINTERS(aa->array->BufferObj->Mappings[MAP_INTERNAL].Pointer, + aa->array->Ptr) + elt * aa->array->StrideB; CALL_by_offset(disp, (array_func), aa->offset, ((const void *) src)); } diff --git a/mesalib/src/mesa/main/api_loopback.c b/mesalib/src/mesa/main/api_loopback.c index 8a04174c7..d10ae15ea 100644 --- a/mesalib/src/mesa/main/api_loopback.c +++ b/mesalib/src/mesa/main/api_loopback.c @@ -34,7 +34,6 @@ #include "api_loopback.h" #include "mtypes.h" #include "glapi/glapi.h" -#include "glapi/glthread.h" #include "main/dispatch.h" #include "main/context.h" diff --git a/mesalib/src/mesa/main/api_loopback.h b/mesalib/src/mesa/main/api_loopback.h index 0b014ad5a..2195e01e3 100644 --- a/mesalib/src/mesa/main/api_loopback.h +++ b/mesalib/src/mesa/main/api_loopback.h @@ -32,7 +32,6 @@ #include "main/macros.h" // ? #include "main/mtypes.h" // ? #include "glapi/glapi.h" // ? -#include "glapi/glthread.h" // ? #include "main/dispatch.h" // ? #include "main/context.h" // ? diff --git a/mesalib/src/mesa/main/api_validate.c b/mesalib/src/mesa/main/api_validate.c index af469e046..f3fd1a475 100644 --- a/mesalib/src/mesa/main/api_validate.c +++ b/mesalib/src/mesa/main/api_validate.c @@ -69,7 +69,8 @@ _mesa_max_buffer_index(struct gl_context *ctx, GLuint count, GLenum type, if (_mesa_is_bufferobj(elementBuf)) { /* elements are in a user-defined buffer object. need to map it */ map = ctx->Driver.MapBufferRange(ctx, 0, elementBuf->Size, - GL_MAP_READ_BIT, elementBuf); + GL_MAP_READ_BIT, elementBuf, + MAP_INTERNAL); /* Actual address is the sum of pointers */ indices = (const GLvoid *) ADD_POINTERS(map, (const GLubyte *) indices); } @@ -92,7 +93,7 @@ _mesa_max_buffer_index(struct gl_context *ctx, GLuint count, GLenum type, } if (map) { - ctx->Driver.UnmapBuffer(ctx, elementBuf); + ctx->Driver.UnmapBuffer(ctx, elementBuf, MAP_INTERNAL); } return max; @@ -865,7 +866,7 @@ valid_draw_indirect(struct gl_context *ctx, return GL_FALSE; } - if (_mesa_bufferobj_mapped(ctx->DrawIndirectBuffer)) { + if (_mesa_check_disallowed_mapping(ctx->DrawIndirectBuffer)) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(DRAW_INDIRECT_BUFFER is mapped)", name); return GL_FALSE; diff --git a/mesalib/src/mesa/main/arrayobj.c b/mesalib/src/mesa/main/arrayobj.c index b33ba8016..efb993012 100644 --- a/mesalib/src/mesa/main/arrayobj.c +++ b/mesalib/src/mesa/main/arrayobj.c @@ -119,7 +119,7 @@ _mesa_delete_vao(struct gl_context *ctx, struct gl_vertex_array_object *obj) { unbind_array_object_vbos(ctx, obj); _mesa_reference_buffer_object(ctx, &obj->IndexBufferObj, NULL); - _glthread_DESTROY_MUTEX(obj->Mutex); + mtx_destroy(&obj->Mutex); free(obj->Label); free(obj); } @@ -142,7 +142,7 @@ _mesa_reference_vao_(struct gl_context *ctx, GLboolean deleteFlag = GL_FALSE; struct gl_vertex_array_object *oldObj = *ptr; - _glthread_LOCK_MUTEX(oldObj->Mutex); + mtx_lock(&oldObj->Mutex); ASSERT(oldObj->RefCount > 0); oldObj->RefCount--; #if 0 @@ -150,7 +150,7 @@ _mesa_reference_vao_(struct gl_context *ctx, (void *) oldObj, oldObj->Name, oldObj->RefCount); #endif deleteFlag = (oldObj->RefCount == 0); - _glthread_UNLOCK_MUTEX(oldObj->Mutex); + mtx_unlock(&oldObj->Mutex); if (deleteFlag) { ASSERT(ctx->Driver.DeleteArrayObject); @@ -163,7 +163,7 @@ _mesa_reference_vao_(struct gl_context *ctx, if (vao) { /* reference new array object */ - _glthread_LOCK_MUTEX(vao->Mutex); + mtx_lock(&vao->Mutex); if (vao->RefCount == 0) { /* this array's being deleted (look just above) */ /* Not sure this can every really happen. Warn if it does. */ @@ -178,7 +178,7 @@ _mesa_reference_vao_(struct gl_context *ctx, #endif *ptr = vao; } - _glthread_UNLOCK_MUTEX(vao->Mutex); + mtx_unlock(&vao->Mutex); } } @@ -226,7 +226,7 @@ _mesa_initialize_vao(struct gl_context *ctx, obj->Name = name; - _glthread_INIT_MUTEX(obj->Mutex); + mtx_init(&obj->Mutex, mtx_plain); obj->RefCount = 1; /* Init the individual arrays */ diff --git a/mesalib/src/mesa/main/attrib.c b/mesalib/src/mesa/main/attrib.c index 004528044..5a626f2f4 100644 --- a/mesalib/src/mesa/main/attrib.c +++ b/mesalib/src/mesa/main/attrib.c @@ -1457,6 +1457,7 @@ copy_array_object(struct gl_context *ctx, /* _Enabled must be the same than on push */ dest->_Enabled = src->_Enabled; + dest->NewArrays = src->NewArrays; dest->_MaxElement = src->_MaxElement; } diff --git a/mesalib/src/mesa/main/bufferobj.c b/mesalib/src/mesa/main/bufferobj.c index ca55ef969..2e9e05918 100644 --- a/mesalib/src/mesa/main/bufferobj.c +++ b/mesalib/src/mesa/main/bufferobj.c @@ -207,11 +207,12 @@ static bool bufferobj_range_mapped(const struct gl_buffer_object *obj, GLintptr offset, GLsizeiptr size) { - if (_mesa_bufferobj_mapped(obj)) { + if (_mesa_bufferobj_mapped(obj, MAP_USER)) { const GLintptr end = offset + size; - const GLintptr mapEnd = obj->Offset + obj->Length; + const GLintptr mapEnd = obj->Mappings[MAP_USER].Offset + + obj->Mappings[MAP_USER].Length; - if (!(end <= obj->Offset || offset >= mapEnd)) { + if (!(end <= obj->Mappings[MAP_USER].Offset || offset >= mapEnd)) { return true; } } @@ -269,6 +270,9 @@ buffer_object_subdata_range_good(struct gl_context * ctx, GLenum target, return NULL; } + if (bufObj->Mappings[MAP_USER].AccessFlags & GL_MAP_PERSISTENT_BIT) + return bufObj; + if (mappedRange) { if (bufferobj_range_mapped(bufObj, offset, size)) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s", caller); @@ -276,7 +280,7 @@ buffer_object_subdata_range_good(struct gl_context * ctx, GLenum target, } } else { - if (_mesa_bufferobj_mapped(bufObj)) { + if (_mesa_bufferobj_mapped(bufObj, MAP_USER)) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s", caller); return NULL; } @@ -413,7 +417,7 @@ _mesa_delete_buffer_object(struct gl_context *ctx, bufObj->RefCount = -1000; bufObj->Name = ~0; - _glthread_DESTROY_MUTEX(bufObj->Mutex); + mtx_destroy(&bufObj->Mutex); free(bufObj->Label); free(bufObj); } @@ -435,7 +439,7 @@ _mesa_reference_buffer_object_(struct gl_context *ctx, GLboolean deleteFlag = GL_FALSE; struct gl_buffer_object *oldObj = *ptr; - _glthread_LOCK_MUTEX(oldObj->Mutex); + mtx_lock(&oldObj->Mutex); ASSERT(oldObj->RefCount > 0); oldObj->RefCount--; #if 0 @@ -443,7 +447,7 @@ _mesa_reference_buffer_object_(struct gl_context *ctx, (void *) oldObj, oldObj->Name, oldObj->RefCount); #endif deleteFlag = (oldObj->RefCount == 0); - _glthread_UNLOCK_MUTEX(oldObj->Mutex); + mtx_unlock(&oldObj->Mutex); if (deleteFlag) { @@ -465,7 +469,7 @@ _mesa_reference_buffer_object_(struct gl_context *ctx, if (bufObj) { /* reference new buffer */ - _glthread_LOCK_MUTEX(bufObj->Mutex); + mtx_lock(&bufObj->Mutex); if (bufObj->RefCount == 0) { /* this buffer's being deleted (look just above) */ /* Not sure this can every really happen. Warn if it does. */ @@ -480,7 +484,7 @@ _mesa_reference_buffer_object_(struct gl_context *ctx, #endif *ptr = bufObj; } - _glthread_UNLOCK_MUTEX(bufObj->Mutex); + mtx_unlock(&bufObj->Mutex); } } @@ -496,11 +500,10 @@ _mesa_initialize_buffer_object( struct gl_context *ctx, (void) target; memset(obj, 0, sizeof(struct gl_buffer_object)); - _glthread_INIT_MUTEX(obj->Mutex); + mtx_init(&obj->Mutex, mtx_plain); obj->RefCount = 1; obj->Name = name; obj->Usage = GL_STATIC_DRAW_ARB; - obj->AccessFlags = 0; } @@ -555,21 +558,21 @@ _mesa_total_buffer_object_memory(struct gl_context *ctx) */ static GLboolean _mesa_buffer_data( struct gl_context *ctx, GLenum target, GLsizeiptrARB size, - const GLvoid * data, GLenum usage, + const GLvoid * data, GLenum usage, GLenum storageFlags, struct gl_buffer_object * bufObj ) { void * new_data; (void) target; - if (bufObj->Data) - _mesa_align_free( bufObj->Data ); + _mesa_align_free( bufObj->Data ); new_data = _mesa_align_malloc( size, ctx->Const.MinMapBufferAlignment ); if (new_data) { bufObj->Data = (GLubyte *) new_data; bufObj->Size = size; bufObj->Usage = usage; + bufObj->StorageFlags = storageFlags; if (data) { memcpy( bufObj->Data, data, size ); @@ -672,33 +675,11 @@ _mesa_buffer_clear_subdata(struct gl_context *ctx, GLsizeiptr i; GLubyte *dest; - if (_mesa_bufferobj_mapped(bufObj)) { - GLubyte *data = malloc(size); - GLubyte *dataStart = data; - if (data == NULL) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glClearBuffer[Sub]Data"); - return; - } - - if (clearValue == NULL) { - /* Clear with zeros, per the spec */ - memset(data, 0, size); - } - else { - for (i = 0; i < size/clearValueSize; ++i) { - memcpy(data, clearValue, clearValueSize); - data += clearValueSize; - } - } - ctx->Driver.BufferSubData(ctx, offset, size, dataStart, bufObj); - return; - } - ASSERT(ctx->Driver.MapBufferRange); dest = ctx->Driver.MapBufferRange(ctx, offset, size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT, - bufObj); + bufObj, MAP_INTERNAL); if (!dest) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glClearBuffer[Sub]Data"); @@ -708,7 +689,7 @@ _mesa_buffer_clear_subdata(struct gl_context *ctx, if (clearValue == NULL) { /* Clear with zeros, per the spec */ memset(dest, 0, size); - ctx->Driver.UnmapBuffer(ctx, bufObj); + ctx->Driver.UnmapBuffer(ctx, bufObj, MAP_INTERNAL); return; } @@ -717,7 +698,7 @@ _mesa_buffer_clear_subdata(struct gl_context *ctx, dest += clearValueSize; } - ctx->Driver.UnmapBuffer(ctx, bufObj); + ctx->Driver.UnmapBuffer(ctx, bufObj, MAP_INTERNAL); } @@ -728,16 +709,17 @@ _mesa_buffer_clear_subdata(struct gl_context *ctx, static void * _mesa_buffer_map_range( struct gl_context *ctx, GLintptr offset, GLsizeiptr length, GLbitfield access, - struct gl_buffer_object *bufObj ) + struct gl_buffer_object *bufObj, + gl_map_buffer_index index) { (void) ctx; - assert(!_mesa_bufferobj_mapped(bufObj)); + assert(!_mesa_bufferobj_mapped(bufObj, index)); /* Just return a direct pointer to the data */ - bufObj->Pointer = bufObj->Data + offset; - bufObj->Length = length; - bufObj->Offset = offset; - bufObj->AccessFlags = access; - return bufObj->Pointer; + bufObj->Mappings[index].Pointer = bufObj->Data + offset; + bufObj->Mappings[index].Length = length; + bufObj->Mappings[index].Offset = offset; + bufObj->Mappings[index].AccessFlags = access; + return bufObj->Mappings[index].Pointer; } @@ -748,7 +730,8 @@ _mesa_buffer_map_range( struct gl_context *ctx, GLintptr offset, static void _mesa_buffer_flush_mapped_range( struct gl_context *ctx, GLintptr offset, GLsizeiptr length, - struct gl_buffer_object *obj ) + struct gl_buffer_object *obj, + gl_map_buffer_index index) { (void) ctx; (void) offset; @@ -766,14 +749,15 @@ _mesa_buffer_flush_mapped_range( struct gl_context *ctx, * \sa glUnmapBufferARB, dd_function_table::UnmapBuffer */ static GLboolean -_mesa_buffer_unmap( struct gl_context *ctx, struct gl_buffer_object *bufObj ) +_mesa_buffer_unmap(struct gl_context *ctx, struct gl_buffer_object *bufObj, + gl_map_buffer_index index) { (void) ctx; /* XXX we might assert here that bufObj->Pointer is non-null */ - bufObj->Pointer = NULL; - bufObj->Length = 0; - bufObj->Offset = 0; - bufObj->AccessFlags = 0x0; + bufObj->Mappings[index].Pointer = NULL; + bufObj->Mappings[index].Length = 0; + bufObj->Mappings[index].Offset = 0; + bufObj->Mappings[index].AccessFlags = 0x0; return GL_TRUE; } @@ -791,14 +775,11 @@ _mesa_copy_buffer_subdata(struct gl_context *ctx, { GLubyte *srcPtr, *dstPtr; - /* the buffers should not be mapped */ - assert(!_mesa_bufferobj_mapped(src)); - assert(!_mesa_bufferobj_mapped(dst)); - if (src == dst) { srcPtr = dstPtr = ctx->Driver.MapBufferRange(ctx, 0, src->Size, GL_MAP_READ_BIT | - GL_MAP_WRITE_BIT, src); + GL_MAP_WRITE_BIT, src, + MAP_INTERNAL); if (!srcPtr) return; @@ -807,10 +788,12 @@ _mesa_copy_buffer_subdata(struct gl_context *ctx, dstPtr += writeOffset; } else { srcPtr = ctx->Driver.MapBufferRange(ctx, readOffset, size, - GL_MAP_READ_BIT, src); + GL_MAP_READ_BIT, src, + MAP_INTERNAL); dstPtr = ctx->Driver.MapBufferRange(ctx, writeOffset, size, (GL_MAP_WRITE_BIT | - GL_MAP_INVALIDATE_RANGE_BIT), dst); + GL_MAP_INVALIDATE_RANGE_BIT), dst, + MAP_INTERNAL); } /* Note: the src and dst regions will never overlap. Trying to do so @@ -819,9 +802,9 @@ _mesa_copy_buffer_subdata(struct gl_context *ctx, if (srcPtr && dstPtr) memcpy(dstPtr, srcPtr, size); - ctx->Driver.UnmapBuffer(ctx, src); + ctx->Driver.UnmapBuffer(ctx, src, MAP_INTERNAL); if (dst != src) - ctx->Driver.UnmapBuffer(ctx, dst); + ctx->Driver.UnmapBuffer(ctx, dst, MAP_INTERNAL); } @@ -835,7 +818,7 @@ _mesa_init_buffer_objects( struct gl_context *ctx ) GLuint i; memset(&DummyBufferObject, 0, sizeof(DummyBufferObject)); - _glthread_INIT_MUTEX(DummyBufferObject.Mutex); + mtx_init(&DummyBufferObject.Mutex, mtx_plain); DummyBufferObject.RefCount = 1000*1000*1000; /* never delete */ _mesa_reference_buffer_object(ctx, &ctx->Array.ArrayBufferObj, @@ -955,10 +938,6 @@ bind_buffer_object(struct gl_context *ctx, GLenum target, GLuint buffer) /* bind new buffer */ _mesa_reference_buffer_object(ctx, bindTarget, newBufObj); - - /* Pass BindBuffer call to device driver */ - if (ctx->Driver.BindBuffer) - ctx->Driver.BindBuffer( ctx, target, newBufObj ); } @@ -1023,7 +1002,6 @@ _mesa_init_buffer_object_functions(struct dd_function_table *driver) /* GL_ARB_vertex/pixel_buffer_object */ driver->NewBufferObject = _mesa_new_buffer_object; driver->DeleteBuffer = _mesa_delete_buffer_object; - driver->BindBuffer = NULL; driver->BufferData = _mesa_buffer_data; driver->BufferSubData = _mesa_buffer_subdata; driver->GetBufferSubData = _mesa_buffer_get_subdata; @@ -1041,6 +1019,21 @@ _mesa_init_buffer_object_functions(struct dd_function_table *driver) } +void +_mesa_buffer_unmap_all_mappings(struct gl_context *ctx, + struct gl_buffer_object *bufObj) +{ + int i; + + for (i = 0; i < MAP_COUNT; i++) { + if (_mesa_bufferobj_mapped(bufObj, i)) { + ctx->Driver.UnmapBuffer(ctx, bufObj, i); + ASSERT(bufObj->Mappings[i].Pointer == NULL); + bufObj->Mappings[i].AccessFlags = 0; + } + } +} + /**********************************************************************/ /* API Functions */ @@ -1077,7 +1070,7 @@ _mesa_DeleteBuffers(GLsizei n, const GLuint *ids) return; } - _glthread_LOCK_MUTEX(ctx->Shared->Mutex); + mtx_lock(&ctx->Shared->Mutex); for (i = 0; i < n; i++) { struct gl_buffer_object *bufObj = _mesa_lookup_bufferobj(ctx, ids[i]); @@ -1087,12 +1080,7 @@ _mesa_DeleteBuffers(GLsizei n, const GLuint *ids) ASSERT(bufObj->Name == ids[i] || bufObj == &DummyBufferObject); - if (_mesa_bufferobj_mapped(bufObj)) { - /* if mapped, unmap it now */ - ctx->Driver.UnmapBuffer(ctx, bufObj); - bufObj->AccessFlags = 0; - bufObj->Pointer = NULL; - } + _mesa_buffer_unmap_all_mappings(ctx, bufObj); /* unbind any vertex pointers bound to this buffer */ for (j = 0; j < Elements(vao->VertexBinding); j++) { @@ -1169,7 +1157,7 @@ _mesa_DeleteBuffers(GLsizei n, const GLuint *ids) } } - _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); + mtx_unlock(&ctx->Shared->Mutex); } @@ -1201,7 +1189,7 @@ _mesa_GenBuffers(GLsizei n, GLuint *buffer) /* * This must be atomic (generation and allocation of buffer object IDs) */ - _glthread_LOCK_MUTEX(ctx->Shared->Mutex); + mtx_lock(&ctx->Shared->Mutex); first = _mesa_HashFindFreeKeyBlock(ctx->Shared->BufferObjects, n); @@ -1212,7 +1200,7 @@ _mesa_GenBuffers(GLsizei n, GLuint *buffer) buffer[i] = first + i; } - _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); + mtx_unlock(&ctx->Shared->Mutex); } @@ -1230,15 +1218,73 @@ _mesa_IsBuffer(GLuint id) GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); - _glthread_LOCK_MUTEX(ctx->Shared->Mutex); + mtx_lock(&ctx->Shared->Mutex); bufObj = _mesa_lookup_bufferobj(ctx, id); - _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); + mtx_unlock(&ctx->Shared->Mutex); return bufObj && bufObj != &DummyBufferObject; } void GLAPIENTRY +_mesa_BufferStorage(GLenum target, GLsizeiptr size, const GLvoid *data, + GLbitfield flags) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_buffer_object *bufObj; + + if (size <= 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "glBufferStorage(size <= 0)"); + return; + } + + if (flags & ~(GL_MAP_READ_BIT | + GL_MAP_WRITE_BIT | + GL_MAP_PERSISTENT_BIT | + GL_MAP_COHERENT_BIT | + GL_DYNAMIC_STORAGE_BIT | + GL_CLIENT_STORAGE_BIT)) { + _mesa_error(ctx, GL_INVALID_VALUE, "glBufferStorage(flags)"); + return; + } + + if (flags & GL_MAP_PERSISTENT_BIT && + !(flags & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT))) { + _mesa_error(ctx, GL_INVALID_VALUE, "glBufferStorage(flags!=READ/WRITE)"); + return; + } + + if (flags & GL_MAP_COHERENT_BIT && !(flags & GL_MAP_PERSISTENT_BIT)) { + _mesa_error(ctx, GL_INVALID_VALUE, "glBufferStorage(flags!=PERSISTENT)"); + return; + } + + bufObj = get_buffer(ctx, "glBufferStorage", target, GL_INVALID_OPERATION); + if (!bufObj) + return; + + if (bufObj->Immutable) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glBufferStorage(immutable)"); + return; + } + + /* Unmap the existing buffer. We'll replace it now. Not an error. */ + _mesa_buffer_unmap_all_mappings(ctx, bufObj); + + FLUSH_VERTICES(ctx, _NEW_BUFFER_OBJECT); + + bufObj->Written = GL_TRUE; + bufObj->Immutable = GL_TRUE; + + ASSERT(ctx->Driver.BufferData); + if (!ctx->Driver.BufferData(ctx, target, size, data, GL_DYNAMIC_DRAW, + flags, bufObj)) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBufferStorage()"); + } +} + + +void GLAPIENTRY _mesa_BufferData(GLenum target, GLsizeiptrARB size, const GLvoid * data, GLenum usage) { @@ -1290,12 +1336,13 @@ _mesa_BufferData(GLenum target, GLsizeiptrARB size, if (!bufObj) return; - if (_mesa_bufferobj_mapped(bufObj)) { - /* Unmap the existing buffer. We'll replace it now. Not an error. */ - ctx->Driver.UnmapBuffer(ctx, bufObj); - bufObj->AccessFlags = 0; - ASSERT(bufObj->Pointer == NULL); - } + if (bufObj->Immutable) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glBufferData(immutable)"); + return; + } + + /* Unmap the existing buffer. We'll replace it now. Not an error. */ + _mesa_buffer_unmap_all_mappings(ctx, bufObj); FLUSH_VERTICES(ctx, _NEW_BUFFER_OBJECT); @@ -1311,7 +1358,11 @@ _mesa_BufferData(GLenum target, GLsizeiptrARB size, #endif ASSERT(ctx->Driver.BufferData); - if (!ctx->Driver.BufferData( ctx, target, size, data, usage, bufObj )) { + if (!ctx->Driver.BufferData(ctx, target, size, data, usage, + GL_MAP_READ_BIT | + GL_MAP_WRITE_BIT | + GL_DYNAMIC_STORAGE_BIT, + bufObj)) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBufferDataARB()"); } } @@ -1332,6 +1383,12 @@ _mesa_BufferSubData(GLenum target, GLintptrARB offset, return; } + if (bufObj->Immutable && + !(bufObj->StorageFlags & GL_DYNAMIC_STORAGE_BIT)) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glBufferSubData"); + return; + } + if (size == 0) return; @@ -1377,7 +1434,7 @@ _mesa_ClearBufferData(GLenum target, GLenum internalformat, GLenum format, return; } - if (_mesa_bufferobj_mapped(bufObj)) { + if (_mesa_check_disallowed_mapping(bufObj)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glClearBufferData(buffer currently mapped)"); return; @@ -1451,8 +1508,10 @@ _mesa_ClearBufferSubData(GLenum target, GLenum internalformat, if (data == NULL) { /* clear to zeros, per the spec */ - ctx->Driver.ClearBufferSubData(ctx, offset, size, - NULL, 0, bufObj); + if (size > 0) { + ctx->Driver.ClearBufferSubData(ctx, offset, size, + NULL, 0, bufObj); + } return; } @@ -1462,8 +1521,10 @@ _mesa_ClearBufferSubData(GLenum target, GLenum internalformat, return; } - ctx->Driver.ClearBufferSubData(ctx, offset, size, - clearValue, clearValueSize, bufObj); + if (size > 0) { + ctx->Driver.ClearBufferSubData(ctx, offset, size, + clearValue, clearValueSize, bufObj); + } } @@ -1505,7 +1566,21 @@ _mesa_MapBuffer(GLenum target, GLenum access) if (!bufObj) return NULL; - if (_mesa_bufferobj_mapped(bufObj)) { + if (accessFlags & GL_MAP_READ_BIT && + !(bufObj->StorageFlags & GL_MAP_READ_BIT)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glMapBuffer(invalid read flag)"); + return NULL; + } + + if (accessFlags & GL_MAP_WRITE_BIT && + !(bufObj->StorageFlags & GL_MAP_WRITE_BIT)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glMapBuffer(invalid write flag)"); + return NULL; + } + + if (_mesa_bufferobj_mapped(bufObj, MAP_USER)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glMapBufferARB(already mapped)"); return NULL; } @@ -1517,7 +1592,8 @@ _mesa_MapBuffer(GLenum target, GLenum access) } ASSERT(ctx->Driver.MapBufferRange); - map = ctx->Driver.MapBufferRange(ctx, 0, bufObj->Size, accessFlags, bufObj); + map = ctx->Driver.MapBufferRange(ctx, 0, bufObj->Size, accessFlags, bufObj, + MAP_USER); if (!map) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMapBufferARB(map failed)"); return NULL; @@ -1527,10 +1603,10 @@ _mesa_MapBuffer(GLenum target, GLenum access) * This is important because other modules (like VBO) might call * the driver function directly. */ - ASSERT(bufObj->Pointer == map); - ASSERT(bufObj->Length == bufObj->Size); - ASSERT(bufObj->Offset == 0); - bufObj->AccessFlags = accessFlags; + ASSERT(bufObj->Mappings[MAP_USER].Pointer == map); + ASSERT(bufObj->Mappings[MAP_USER].Length == bufObj->Size); + ASSERT(bufObj->Mappings[MAP_USER].Offset == 0); + bufObj->Mappings[MAP_USER].AccessFlags = accessFlags; } if (access == GL_WRITE_ONLY_ARB || access == GL_READ_WRITE_ARB) @@ -1558,7 +1634,7 @@ _mesa_MapBuffer(GLenum target, GLenum access) } #endif - return bufObj->Pointer; + return bufObj->Mappings[MAP_USER].Pointer; } @@ -1574,7 +1650,7 @@ _mesa_UnmapBuffer(GLenum target) if (!bufObj) return GL_FALSE; - if (!_mesa_bufferobj_mapped(bufObj)) { + if (!_mesa_bufferobj_mapped(bufObj, MAP_USER)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glUnmapBufferARB"); return GL_FALSE; } @@ -1615,11 +1691,11 @@ _mesa_UnmapBuffer(GLenum target) } #endif - status = ctx->Driver.UnmapBuffer( ctx, bufObj ); - bufObj->AccessFlags = 0; - ASSERT(bufObj->Pointer == NULL); - ASSERT(bufObj->Offset == 0); - ASSERT(bufObj->Length == 0); + status = ctx->Driver.UnmapBuffer(ctx, bufObj, MAP_USER); + bufObj->Mappings[MAP_USER].AccessFlags = 0; + ASSERT(bufObj->Mappings[MAP_USER].Pointer == NULL); + ASSERT(bufObj->Mappings[MAP_USER].Offset == 0); + ASSERT(bufObj->Mappings[MAP_USER].Length == 0); return status; } @@ -1644,25 +1720,36 @@ _mesa_GetBufferParameteriv(GLenum target, GLenum pname, GLint *params) *params = bufObj->Usage; return; case GL_BUFFER_ACCESS_ARB: - *params = simplified_access_mode(ctx, bufObj->AccessFlags); + *params = simplified_access_mode(ctx, + bufObj->Mappings[MAP_USER].AccessFlags); return; case GL_BUFFER_MAPPED_ARB: - *params = _mesa_bufferobj_mapped(bufObj); + *params = _mesa_bufferobj_mapped(bufObj, MAP_USER); return; case GL_BUFFER_ACCESS_FLAGS: if (!ctx->Extensions.ARB_map_buffer_range) goto invalid_pname; - *params = bufObj->AccessFlags; + *params = bufObj->Mappings[MAP_USER].AccessFlags; return; case GL_BUFFER_MAP_OFFSET: if (!ctx->Extensions.ARB_map_buffer_range) goto invalid_pname; - *params = (GLint) bufObj->Offset; + *params = (GLint) bufObj->Mappings[MAP_USER].Offset; return; case GL_BUFFER_MAP_LENGTH: if (!ctx->Extensions.ARB_map_buffer_range) goto invalid_pname; - *params = (GLint) bufObj->Length; + *params = (GLint) bufObj->Mappings[MAP_USER].Length; + return; + case GL_BUFFER_IMMUTABLE_STORAGE: + if (!ctx->Extensions.ARB_buffer_storage) + goto invalid_pname; + *params = bufObj->Immutable; + return; + case GL_BUFFER_STORAGE_FLAGS: + if (!ctx->Extensions.ARB_buffer_storage) + goto invalid_pname; + *params = bufObj->StorageFlags; return; default: ; /* fall-through */ @@ -1698,25 +1785,36 @@ _mesa_GetBufferParameteri64v(GLenum target, GLenum pname, GLint64 *params) *params = bufObj->Usage; return; case GL_BUFFER_ACCESS_ARB: - *params = simplified_access_mode(ctx, bufObj->AccessFlags); + *params = simplified_access_mode(ctx, + bufObj->Mappings[MAP_USER].AccessFlags); return; case GL_BUFFER_ACCESS_FLAGS: if (!ctx->Extensions.ARB_map_buffer_range) goto invalid_pname; - *params = bufObj->AccessFlags; + *params = bufObj->Mappings[MAP_USER].AccessFlags; return; case GL_BUFFER_MAPPED_ARB: - *params = _mesa_bufferobj_mapped(bufObj); + *params = _mesa_bufferobj_mapped(bufObj, MAP_USER); return; case GL_BUFFER_MAP_OFFSET: if (!ctx->Extensions.ARB_map_buffer_range) goto invalid_pname; - *params = bufObj->Offset; + *params = bufObj->Mappings[MAP_USER].Offset; return; case GL_BUFFER_MAP_LENGTH: if (!ctx->Extensions.ARB_map_buffer_range) goto invalid_pname; - *params = bufObj->Length; + *params = bufObj->Mappings[MAP_USER].Length; + return; + case GL_BUFFER_IMMUTABLE_STORAGE: + if (!ctx->Extensions.ARB_buffer_storage) + goto invalid_pname; + *params = bufObj->Immutable; + return; + case GL_BUFFER_STORAGE_FLAGS: + if (!ctx->Extensions.ARB_buffer_storage) + goto invalid_pname; + *params = bufObj->StorageFlags; return; default: ; /* fall-through */ @@ -1744,7 +1842,7 @@ _mesa_GetBufferPointerv(GLenum target, GLenum pname, GLvoid **params) if (!bufObj) return; - *params = bufObj->Pointer; + *params = bufObj->Mappings[MAP_USER].Pointer; } @@ -1766,13 +1864,13 @@ _mesa_CopyBufferSubData(GLenum readTarget, GLenum writeTarget, if (!dst) return; - if (_mesa_bufferobj_mapped(src)) { + if (_mesa_check_disallowed_mapping(src)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glCopyBufferSubData(readBuffer is mapped)"); return; } - if (_mesa_bufferobj_mapped(dst)) { + if (_mesa_check_disallowed_mapping(dst)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glCopyBufferSubData(writeBuffer is mapped)"); return; @@ -1839,6 +1937,7 @@ _mesa_MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, GET_CURRENT_CONTEXT(ctx); struct gl_buffer_object *bufObj; void *map; + GLbitfield allowed_access; ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, NULL); @@ -1873,13 +1972,20 @@ _mesa_MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, return NULL; } - if (access & ~(GL_MAP_READ_BIT | - GL_MAP_WRITE_BIT | - GL_MAP_INVALIDATE_RANGE_BIT | - GL_MAP_INVALIDATE_BUFFER_BIT | - GL_MAP_FLUSH_EXPLICIT_BIT | - GL_MAP_UNSYNCHRONIZED_BIT)) { - /* generate an error if any undefind bit is set */ + allowed_access = GL_MAP_READ_BIT | + GL_MAP_WRITE_BIT | + GL_MAP_INVALIDATE_RANGE_BIT | + GL_MAP_INVALIDATE_BUFFER_BIT | + GL_MAP_FLUSH_EXPLICIT_BIT | + GL_MAP_UNSYNCHRONIZED_BIT; + + if (ctx->Extensions.ARB_buffer_storage) { + allowed_access |= GL_MAP_PERSISTENT_BIT | + GL_MAP_COHERENT_BIT; + } + + if (access & ~allowed_access) { + /* generate an error if any other than allowed bit is set */ _mesa_error(ctx, GL_INVALID_VALUE, "glMapBufferRange(access)"); return NULL; } @@ -1910,13 +2016,41 @@ _mesa_MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, if (!bufObj) return NULL; + if (access & GL_MAP_READ_BIT && + !(bufObj->StorageFlags & GL_MAP_READ_BIT)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glMapBufferRange(invalid read flag)"); + return NULL; + } + + if (access & GL_MAP_WRITE_BIT && + !(bufObj->StorageFlags & GL_MAP_WRITE_BIT)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glMapBufferRange(invalid write flag)"); + return NULL; + } + + if (access & GL_MAP_COHERENT_BIT && + !(bufObj->StorageFlags & GL_MAP_COHERENT_BIT)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glMapBufferRange(invalid coherent flag)"); + return NULL; + } + + if (access & GL_MAP_PERSISTENT_BIT && + !(bufObj->StorageFlags & GL_MAP_PERSISTENT_BIT)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glMapBufferRange(invalid persistent flag)"); + return NULL; + } + if (offset + length > bufObj->Size) { _mesa_error(ctx, GL_INVALID_VALUE, "glMapBufferRange(offset + length > size)"); return NULL; } - if (_mesa_bufferobj_mapped(bufObj)) { + if (_mesa_bufferobj_mapped(bufObj, MAP_USER)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glMapBufferRange(buffer already mapped)"); return NULL; @@ -1931,15 +2065,16 @@ _mesa_MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, /* Mapping zero bytes should return a non-null pointer. */ if (!length) { static long dummy = 0; - bufObj->Pointer = &dummy; - bufObj->Length = length; - bufObj->Offset = offset; - bufObj->AccessFlags = access; - return bufObj->Pointer; + bufObj->Mappings[MAP_USER].Pointer = &dummy; + bufObj->Mappings[MAP_USER].Length = length; + bufObj->Mappings[MAP_USER].Offset = offset; + bufObj->Mappings[MAP_USER].AccessFlags = access; + return bufObj->Mappings[MAP_USER].Pointer; } ASSERT(ctx->Driver.MapBufferRange); - map = ctx->Driver.MapBufferRange(ctx, offset, length, access, bufObj); + map = ctx->Driver.MapBufferRange(ctx, offset, length, access, bufObj, + MAP_USER); if (!map) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMapBufferARB(map failed)"); } @@ -1948,10 +2083,10 @@ _mesa_MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, * This is important because other modules (like VBO) might call * the driver function directly. */ - ASSERT(bufObj->Pointer == map); - ASSERT(bufObj->Length == length); - ASSERT(bufObj->Offset == offset); - ASSERT(bufObj->AccessFlags == access); + ASSERT(bufObj->Mappings[MAP_USER].Pointer == map); + ASSERT(bufObj->Mappings[MAP_USER].Length == length); + ASSERT(bufObj->Mappings[MAP_USER].Offset == offset); + ASSERT(bufObj->Mappings[MAP_USER].AccessFlags == access); } return map; @@ -1990,30 +2125,33 @@ _mesa_FlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length) if (!bufObj) return; - if (!_mesa_bufferobj_mapped(bufObj)) { + if (!_mesa_bufferobj_mapped(bufObj, MAP_USER)) { /* buffer is not mapped */ _mesa_error(ctx, GL_INVALID_OPERATION, "glFlushMappedBufferRange(buffer is not mapped)"); return; } - if ((bufObj->AccessFlags & GL_MAP_FLUSH_EXPLICIT_BIT) == 0) { + if ((bufObj->Mappings[MAP_USER].AccessFlags & + GL_MAP_FLUSH_EXPLICIT_BIT) == 0) { _mesa_error(ctx, GL_INVALID_OPERATION, "glFlushMappedBufferRange(GL_MAP_FLUSH_EXPLICIT_BIT not set)"); return; } - if (offset + length > bufObj->Length) { + if (offset + length > bufObj->Mappings[MAP_USER].Length) { _mesa_error(ctx, GL_INVALID_VALUE, "glFlushMappedBufferRange(offset %ld + length %ld > mapped length %ld)", - (long)offset, (long)length, (long)bufObj->Length); + (long)offset, (long)length, + (long)bufObj->Mappings[MAP_USER].Length); return; } - ASSERT(bufObj->AccessFlags & GL_MAP_WRITE_BIT); + ASSERT(bufObj->Mappings[MAP_USER].AccessFlags & GL_MAP_WRITE_BIT); if (ctx->Driver.FlushMappedBufferRange) - ctx->Driver.FlushMappedBufferRange(ctx, offset, length, bufObj); + ctx->Driver.FlushMappedBufferRange(ctx, offset, length, bufObj, + MAP_USER); } @@ -2660,13 +2798,15 @@ _mesa_InvalidateBufferSubData(GLuint buffer, GLintptr offset, return; } - /* The GL_ARB_invalidate_subdata spec says: + /* The OpenGL 4.4 (Core Profile) spec says: * - * "An INVALID_OPERATION error is generated if the buffer is currently - * mapped by MapBuffer, or if the invalidate range intersects the range - * currently mapped by MapBufferRange." + * "An INVALID_OPERATION error is generated if buffer is currently + * mapped by MapBuffer or if the invalidate range intersects the range + * currently mapped by MapBufferRange, unless it was mapped + * with MAP_PERSISTENT_BIT set in the MapBufferRange access flags." */ - if (bufferobj_range_mapped(bufObj, offset, length)) { + if (!(bufObj->Mappings[MAP_USER].AccessFlags & GL_MAP_PERSISTENT_BIT) && + bufferobj_range_mapped(bufObj, offset, length)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glInvalidateBufferSubData(intersection with mapped " "range)"); @@ -2693,13 +2833,14 @@ _mesa_InvalidateBufferData(GLuint buffer) return; } - /* The GL_ARB_invalidate_subdata spec says: + /* The OpenGL 4.4 (Core Profile) spec says: * - * "An INVALID_OPERATION error is generated if the buffer is currently - * mapped by MapBuffer, or if the invalidate range intersects the range - * currently mapped by MapBufferRange." + * "An INVALID_OPERATION error is generated if buffer is currently + * mapped by MapBuffer or if the invalidate range intersects the range + * currently mapped by MapBufferRange, unless it was mapped + * with MAP_PERSISTENT_BIT set in the MapBufferRange access flags." */ - if (_mesa_bufferobj_mapped(bufObj)) { + if (_mesa_check_disallowed_mapping(bufObj)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glInvalidateBufferData(intersection with mapped " "range)"); diff --git a/mesalib/src/mesa/main/bufferobj.h b/mesalib/src/mesa/main/bufferobj.h index 71988b0d9..9814552eb 100644 --- a/mesalib/src/mesa/main/bufferobj.h +++ b/mesalib/src/mesa/main/bufferobj.h @@ -37,11 +37,21 @@ */ -/** Is the given buffer object currently mapped? */ +/** Is the given buffer object currently mapped by the GL user? */ static inline GLboolean -_mesa_bufferobj_mapped(const struct gl_buffer_object *obj) +_mesa_bufferobj_mapped(const struct gl_buffer_object *obj, + gl_map_buffer_index index) { - return obj->Pointer != NULL; + return obj->Mappings[index].Pointer != NULL; +} + +/** Can we not use this buffer while mapped? */ +static inline GLboolean +_mesa_check_disallowed_mapping(const struct gl_buffer_object *obj) +{ + return _mesa_bufferobj_mapped(obj, MAP_USER) && + !(obj->Mappings[MAP_USER].AccessFlags & + GL_MAP_PERSISTENT_BIT); } /** @@ -101,6 +111,9 @@ _mesa_total_buffer_object_memory(struct gl_context *ctx); extern void _mesa_init_buffer_object_functions(struct dd_function_table *driver); +extern void +_mesa_buffer_unmap_all_mappings(struct gl_context *ctx, + struct gl_buffer_object *bufObj); /* * API functions @@ -118,6 +131,10 @@ GLboolean GLAPIENTRY _mesa_IsBuffer(GLuint buffer); void GLAPIENTRY +_mesa_BufferStorage(GLenum target, GLsizeiptr size, const GLvoid *data, + GLbitfield flags); + +void GLAPIENTRY _mesa_BufferData(GLenum target, GLsizeiptrARB size, const GLvoid * data, GLenum usage); diff --git a/mesalib/src/mesa/main/context.c b/mesalib/src/mesa/main/context.c index 458d8e59b..5b77ce103 100644 --- a/mesalib/src/mesa/main/context.c +++ b/mesalib/src/mesa/main/context.c @@ -106,6 +106,7 @@ #include "matrix.h" #include "multisample.h" #include "performance_monitor.h" +#include "pipelineobj.h" #include "pixel.h" #include "pixelstore.h" #include "points.h" @@ -363,7 +364,7 @@ dummy_enum_func(void) * * \sa Used by one_time_init(). */ -_glthread_DECLARE_STATIC_MUTEX(OneTimeLock); +mtx_t OneTimeLock = _MTX_INITIALIZER_NP; @@ -381,7 +382,7 @@ one_time_init( struct gl_context *ctx ) { static GLbitfield api_init_mask = 0x0; - _glthread_LOCK_MUTEX(OneTimeLock); + mtx_lock(&OneTimeLock); /* truly one-time init */ if (!api_init_mask) { @@ -422,7 +423,7 @@ one_time_init( struct gl_context *ctx ) api_init_mask |= 1 << ctx->API; - _glthread_UNLOCK_MUTEX(OneTimeLock); + mtx_unlock(&OneTimeLock); /* Hopefully atexit() is widely available. If not, we may need some * #ifdef tests here. @@ -603,9 +604,6 @@ _mesa_init_constants(struct gl_context *ctx) ctx->Const.ViewportBounds.Min = 0; ctx->Const.ViewportBounds.Max = 0; - /* Driver must override if it supports ARB_viewport_array */ - ctx->Const.MaxViewports = 1; - /** GL_ARB_uniform_buffer_object */ ctx->Const.MaxCombinedUniformBlocks = 36; ctx->Const.MaxUniformBufferBindings = 36; @@ -814,6 +812,7 @@ init_attrib_groups(struct gl_context *ctx) _mesa_init_matrix( ctx ); _mesa_init_multisample( ctx ); _mesa_init_performance_monitors( ctx ); + _mesa_init_pipeline( ctx ); _mesa_init_pixel( ctx ); _mesa_init_pixelstore( ctx ); _mesa_init_point( ctx ); @@ -1219,6 +1218,7 @@ _mesa_free_context_data( struct gl_context *ctx ) _mesa_free_texture_data( ctx ); _mesa_free_matrix_data( ctx ); _mesa_free_viewport_data( ctx ); + _mesa_free_pipeline_data(ctx); _mesa_free_program_data(ctx); _mesa_free_shader_state(ctx); _mesa_free_queryobj_data(ctx); @@ -1769,93 +1769,59 @@ _mesa_check_blend_func_error(struct gl_context *ctx) return GL_TRUE; } -/** - * Prior to drawing anything with glBegin, glDrawArrays, etc. this function - * is called to see if it's valid to render. This involves checking that - * the current shader is valid and the framebuffer is complete. - * If an error is detected it'll be recorded here. - * \return GL_TRUE if OK to render, GL_FALSE if not - */ -GLboolean -_mesa_valid_to_render(struct gl_context *ctx, const char *where) +static bool +shader_linked_or_absent(struct gl_context *ctx, + const struct gl_shader_program *shProg, + bool *shader_present, const char *where) { - bool vert_from_glsl_shader = false; - bool geom_from_glsl_shader = false; - bool frag_from_glsl_shader = false; - - /* This depends on having up to date derived state (shaders) */ - if (ctx->NewState) - _mesa_update_state(ctx); + if (shProg) { + *shader_present = true; - if (ctx->Shader.CurrentProgram[MESA_SHADER_VERTEX]) { - vert_from_glsl_shader = true; - - if (!ctx->Shader.CurrentProgram[MESA_SHADER_VERTEX]->LinkStatus) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "%s(shader not linked)", where); - return GL_FALSE; + if (!shProg->LinkStatus) { + _mesa_error(ctx, GL_INVALID_OPERATION, "%s(shader not linked)", where); + return false; } #if 0 /* not normally enabled */ { char errMsg[100]; - if (!_mesa_validate_shader_program(ctx, - ctx->Shader.CurrentProgram[MESA_SHADER_VERTEX], - errMsg)) { + if (!_mesa_validate_shader_program(ctx, shProg, errMsg)) { _mesa_warning(ctx, "Shader program %u is invalid: %s", - ctx->Shader.CurrentProgram[MESA_SHADER_VERTEX]->Name, errMsg); + shProg->Name, errMsg); } } #endif } - if (ctx->Shader.CurrentProgram[MESA_SHADER_GEOMETRY]) { - geom_from_glsl_shader = true; + return true; +} - if (!ctx->Shader.CurrentProgram[MESA_SHADER_GEOMETRY]->LinkStatus) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "%s(shader not linked)", where); - return GL_FALSE; - } -#if 0 /* not normally enabled */ - { - char errMsg[100]; - if (!_mesa_validate_shader_program(ctx, - ctx->Shader.CurrentProgram[MESA_SHADER_GEOMETRY], - errMsg)) { - _mesa_warning(ctx, "Shader program %u is invalid: %s", - ctx->Shader.CurrentProgram[MESA_SHADER_GEOMETRY]->Name, - errMsg); - } - } -#endif - } +/** + * Prior to drawing anything with glBegin, glDrawArrays, etc. this function + * is called to see if it's valid to render. This involves checking that + * the current shader is valid and the framebuffer is complete. + * If an error is detected it'll be recorded here. + * \return GL_TRUE if OK to render, GL_FALSE if not + */ +GLboolean +_mesa_valid_to_render(struct gl_context *ctx, const char *where) +{ + bool from_glsl_shader[MESA_SHADER_COMPUTE] = { false }; + unsigned i; - if (ctx->Shader.CurrentProgram[MESA_SHADER_FRAGMENT]) { - frag_from_glsl_shader = true; + /* This depends on having up to date derived state (shaders) */ + if (ctx->NewState) + _mesa_update_state(ctx); - if (!ctx->Shader.CurrentProgram[MESA_SHADER_FRAGMENT]->LinkStatus) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "%s(shader not linked)", where); + for (i = 0; i < MESA_SHADER_COMPUTE; i++) { + if (!shader_linked_or_absent(ctx, ctx->Shader.CurrentProgram[i], + &from_glsl_shader[i], where)) return GL_FALSE; - } -#if 0 /* not normally enabled */ - { - char errMsg[100]; - if (!_mesa_validate_shader_program(ctx, - ctx->Shader.CurrentProgram[MESA_SHADER_FRAGMENT], - errMsg)) { - _mesa_warning(ctx, "Shader program %u is invalid: %s", - ctx->Shader.CurrentProgram[MESA_SHADER_FRAGMENT]->Name, - errMsg); - } - } -#endif } /* Any shader stages that are not supplied by the GLSL shader and have * assembly shaders enabled must now be validated. */ - if (!vert_from_glsl_shader + if (!from_glsl_shader[MESA_SHADER_VERTEX] && ctx->VertexProgram.Enabled && !ctx->VertexProgram._Enabled) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(vertex program not valid)", where); @@ -1865,9 +1831,9 @@ _mesa_valid_to_render(struct gl_context *ctx, const char *where) /* FINISHME: If GL_NV_geometry_program4 is ever supported, the current * FINISHME: geometry program should validated here. */ - (void) geom_from_glsl_shader; + (void) from_glsl_shader[MESA_SHADER_GEOMETRY]; - if (!frag_from_glsl_shader) { + if (!from_glsl_shader[MESA_SHADER_FRAGMENT]) { if (ctx->FragmentProgram.Enabled && !ctx->FragmentProgram._Enabled) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(fragment program not valid)", where); diff --git a/mesalib/src/mesa/main/dd.h b/mesalib/src/mesa/main/dd.h index ac317e399..971524135 100644 --- a/mesalib/src/mesa/main/dd.h +++ b/mesalib/src/mesa/main/dd.h @@ -399,6 +399,13 @@ struct dd_function_table { void (*UnmapRenderbuffer)(struct gl_context *ctx, struct gl_renderbuffer *rb); + /** + * Optional driver entrypoint that binds a non-texture renderbuffer's + * contents to a texture image. + */ + GLboolean (*BindRenderbufferTexImage)(struct gl_context *ctx, + struct gl_renderbuffer *rb, + struct gl_texture_image *texImage); /*@}*/ @@ -564,9 +571,6 @@ struct dd_function_table { * \name Vertex/pixel buffer object functions */ /*@{*/ - void (*BindBuffer)( struct gl_context *ctx, GLenum target, - struct gl_buffer_object *obj ); - struct gl_buffer_object * (*NewBufferObject)(struct gl_context *ctx, GLuint buffer, GLenum target); @@ -574,7 +578,7 @@ struct dd_function_table { GLboolean (*BufferData)(struct gl_context *ctx, GLenum target, GLsizeiptrARB size, const GLvoid *data, GLenum usage, - struct gl_buffer_object *obj); + GLenum storageFlags, struct gl_buffer_object *obj); void (*BufferSubData)( struct gl_context *ctx, GLintptrARB offset, GLsizeiptrARB size, const GLvoid *data, @@ -601,14 +605,17 @@ struct dd_function_table { */ void * (*MapBufferRange)( struct gl_context *ctx, GLintptr offset, GLsizeiptr length, GLbitfield access, - struct gl_buffer_object *obj); + struct gl_buffer_object *obj, + gl_map_buffer_index index); void (*FlushMappedBufferRange)(struct gl_context *ctx, GLintptr offset, GLsizeiptr length, - struct gl_buffer_object *obj); + struct gl_buffer_object *obj, + gl_map_buffer_index index); GLboolean (*UnmapBuffer)( struct gl_context *ctx, - struct gl_buffer_object *obj ); + struct gl_buffer_object *obj, + gl_map_buffer_index index); /*@}*/ /** diff --git a/mesalib/src/mesa/main/dlist.c b/mesalib/src/mesa/main/dlist.c index 08943c9f9..d431fd221 100644 --- a/mesalib/src/mesa/main/dlist.c +++ b/mesalib/src/mesa/main/dlist.c @@ -914,7 +914,8 @@ unpack_image(struct gl_context *ctx, GLuint dimensions, map = (GLubyte *) ctx->Driver.MapBufferRange(ctx, 0, unpack->BufferObj->Size, - GL_MAP_READ_BIT, unpack->BufferObj); + GL_MAP_READ_BIT, unpack->BufferObj, + MAP_INTERNAL); if (!map) { /* unable to map src buffer! */ _mesa_error(ctx, GL_INVALID_OPERATION, "unable to map PBO"); @@ -928,7 +929,7 @@ unpack_image(struct gl_context *ctx, GLuint dimensions, image = _mesa_unpack_image(dimensions, width, height, depth, format, type, src, unpack); - ctx->Driver.UnmapBuffer(ctx, unpack->BufferObj); + ctx->Driver.UnmapBuffer(ctx, unpack->BufferObj, MAP_INTERNAL); if (!image) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "display list construction"); @@ -8176,7 +8177,7 @@ _mesa_GenLists(GLsizei range) /* * Make this an atomic operation */ - _glthread_LOCK_MUTEX(ctx->Shared->Mutex); + mtx_lock(&ctx->Shared->Mutex); base = _mesa_HashFindFreeKeyBlock(ctx->Shared->DisplayList, range); if (base) { @@ -8188,7 +8189,7 @@ _mesa_GenLists(GLsizei range) } } - _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); + mtx_unlock(&ctx->Shared->Mutex); return base; } diff --git a/mesalib/src/mesa/main/drawpix.c b/mesalib/src/mesa/main/drawpix.c index 096615c05..63e5870e6 100644 --- a/mesalib/src/mesa/main/drawpix.c +++ b/mesalib/src/mesa/main/drawpix.c @@ -151,7 +151,7 @@ _mesa_DrawPixels( GLsizei width, GLsizei height, "glDrawPixels(invalid PBO access)"); goto end; } - if (_mesa_bufferobj_mapped(ctx->Unpack.BufferObj)) { + if (_mesa_check_disallowed_mapping(ctx->Unpack.BufferObj)) { /* buffer is mapped - that's an error */ _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawPixels(PBO is mapped)"); @@ -335,7 +335,7 @@ _mesa_Bitmap( GLsizei width, GLsizei height, "glBitmap(invalid PBO access)"); return; } - if (_mesa_bufferobj_mapped(ctx->Unpack.BufferObj)) { + if (_mesa_check_disallowed_mapping(ctx->Unpack.BufferObj)) { /* buffer is mapped - that's an error */ _mesa_error(ctx, GL_INVALID_OPERATION, "glBitmap(PBO is mapped)"); diff --git a/mesalib/src/mesa/main/enable.c b/mesalib/src/mesa/main/enable.c index 40508a456..edd4751e1 100644 --- a/mesalib/src/mesa/main/enable.c +++ b/mesalib/src/mesa/main/enable.c @@ -32,6 +32,7 @@ #include "clip.h" #include "context.h" #include "enable.h" +#include "errors.h" #include "light.h" #include "simple_list.h" #include "mtypes.h" @@ -367,14 +368,26 @@ _mesa_set_enable(struct gl_context *ctx, GLenum cap, GLboolean state) ctx->Depth.Test = state; break; case GL_DEBUG_OUTPUT: - if (!_mesa_is_desktop_gl(ctx)) + if (!_mesa_is_desktop_gl(ctx)) { goto invalid_enum_error; - ctx->Debug.DebugOutput = state; + } + else { + struct gl_debug_state *debug = _mesa_get_debug_state(ctx); + if (debug) { + debug->DebugOutput = state; + } + } break; case GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB: - if (!_mesa_is_desktop_gl(ctx)) + if (!_mesa_is_desktop_gl(ctx)) { goto invalid_enum_error; - ctx->Debug.SyncOutput = state; + } + else { + struct gl_debug_state *debug = _mesa_get_debug_state(ctx); + if (debug) { + debug->SyncOutput = state; + } + } break; case GL_DITHER: if (ctx->Color.DitherFlag == state) @@ -1228,11 +1241,19 @@ _mesa_IsEnabled( GLenum cap ) case GL_DEBUG_OUTPUT: if (!_mesa_is_desktop_gl(ctx)) goto invalid_enum_error; - return ctx->Debug.DebugOutput; + if (ctx->Debug) { + return ctx->Debug->DebugOutput; + } else { + return GL_FALSE; + } case GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB: if (!_mesa_is_desktop_gl(ctx)) goto invalid_enum_error; - return ctx->Debug.SyncOutput; + if (ctx->Debug) { + return ctx->Debug->SyncOutput; + } else { + return GL_FALSE; + } case GL_DEPTH_TEST: return ctx->Depth.Test; case GL_DITHER: diff --git a/mesalib/src/mesa/main/errors.c b/mesalib/src/mesa/main/errors.c index 28357e0e8..ca73a6686 100644 --- a/mesalib/src/mesa/main/errors.c +++ b/mesalib/src/mesa/main/errors.c @@ -37,12 +37,11 @@ #include "mtypes.h" #include "version.h" #include "hash_table.h" -#include "glapi/glthread.h" #define MESSAGE_LOG 1 #define MESSAGE_LOG_ARB 2 -_glthread_DECLARE_STATIC_MUTEX(DynamicIDMutex); +static mtx_t DynamicIDMutex = _MTX_INITIALIZER_NP; static GLuint NextDynamicID = 1; struct gl_debug_severity @@ -81,6 +80,7 @@ static const GLenum debug_severity_enums[] = { GL_DEBUG_SEVERITY_NOTIFICATION, }; + static enum mesa_debug_source gl_enum_to_debug_source(GLenum e) { @@ -117,6 +117,7 @@ gl_enum_to_debug_severity(GLenum e) return i; } + /** * Handles generating a GL_ARB_debug_output message ID generated by the GL or * GLSL compiler. @@ -134,13 +135,14 @@ static void debug_get_id(GLuint *id) { if (!(*id)) { - _glthread_LOCK_MUTEX(DynamicIDMutex); + mtx_lock(&DynamicIDMutex); if (!(*id)) *id = NextDynamicID++; - _glthread_UNLOCK_MUTEX(DynamicIDMutex); + mtx_unlock(&DynamicIDMutex); } } + /* * We store a bitfield in the hash table, with five possible values total. * @@ -182,6 +184,50 @@ enum { ENABLED = ENABLED_BIT | FOUND_BIT }; + +/** + * Return debug state for the context. The debug state will be allocated + * and initialized upon the first call. + */ +struct gl_debug_state * +_mesa_get_debug_state(struct gl_context *ctx) +{ + if (!ctx->Debug) { + ctx->Debug = CALLOC_STRUCT(gl_debug_state); + if (!ctx->Debug) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "allocating debug state"); + } + else { + struct gl_debug_state *debug = ctx->Debug; + int s, t, sev; + + /* Enable all the messages with severity HIGH or MEDIUM by default. */ + memset(debug->Defaults[0][MESA_DEBUG_SEVERITY_HIGH], GL_TRUE, + sizeof debug->Defaults[0][MESA_DEBUG_SEVERITY_HIGH]); + memset(debug->Defaults[0][MESA_DEBUG_SEVERITY_MEDIUM], GL_TRUE, + sizeof debug->Defaults[0][MESA_DEBUG_SEVERITY_MEDIUM]); + memset(debug->Defaults[0][MESA_DEBUG_SEVERITY_LOW], GL_FALSE, + sizeof debug->Defaults[0][MESA_DEBUG_SEVERITY_LOW]); + + /* Initialize state for filtering known debug messages. */ + for (s = 0; s < MESA_DEBUG_SOURCE_COUNT; s++) { + for (t = 0; t < MESA_DEBUG_TYPE_COUNT; t++) { + debug->Namespaces[0][s][t].IDs = _mesa_NewHashTable(); + assert(debug->Namespaces[0][s][t].IDs); + + for (sev = 0; sev < MESA_DEBUG_SEVERITY_COUNT; sev++) { + make_empty_list(&debug->Namespaces[0][s][t].Severity[sev]); + } + } + } + } + } + + return ctx->Debug; +} + + + /** * Returns the state of the given message source/type/ID tuple. */ @@ -192,52 +238,64 @@ should_log(struct gl_context *ctx, GLuint id, enum mesa_debug_severity severity) { - GLint gstack = ctx->Debug.GroupStackDepth; - struct gl_debug_namespace *nspace = - &ctx->Debug.Namespaces[gstack][source][type]; - uintptr_t state; + struct gl_debug_state *debug; + uintptr_t state = 0; - if (!ctx->Debug.DebugOutput) + if (!ctx->Debug) { + /* no debug state set so far */ return GL_FALSE; + } - /* In addition to not being able to store zero as a value, HashTable also - can't use zero as a key. */ - if (id) - state = (uintptr_t)_mesa_HashLookup(nspace->IDs, id); - else - state = nspace->ZeroID; - - /* Only do this once for each ID. This makes sure the ID exists in, - at most, one list, and does not pointlessly appear multiple times. */ - if (!(state & KNOWN_SEVERITY)) { - struct gl_debug_severity *entry; - - if (state == NOT_FOUND) { - if (ctx->Debug.Defaults[gstack][severity][source][type]) - state = ENABLED; - else - state = DISABLED; - } - - entry = malloc(sizeof *entry); - if (!entry) - goto out; + debug = _mesa_get_debug_state(ctx); + if (debug) { + const GLint gstack = debug->GroupStackDepth; + struct gl_debug_namespace *nspace = + &debug->Namespaces[gstack][source][type]; - state |= KNOWN_SEVERITY; + if (!debug->DebugOutput) + return GL_FALSE; + /* In addition to not being able to store zero as a value, HashTable also + * can't use zero as a key. + */ if (id) - _mesa_HashInsert(nspace->IDs, id, (void*)state); + state = (uintptr_t)_mesa_HashLookup(nspace->IDs, id); else - nspace->ZeroID = state; + state = nspace->ZeroID; - entry->ID = id; - insert_at_tail(&nspace->Severity[severity], &entry->link); - } + /* Only do this once for each ID. This makes sure the ID exists in, + * at most, one list, and does not pointlessly appear multiple times. + */ + if (!(state & KNOWN_SEVERITY)) { + struct gl_debug_severity *entry; + + if (state == NOT_FOUND) { + if (debug->Defaults[gstack][severity][source][type]) + state = ENABLED; + else + state = DISABLED; + } + + entry = malloc(sizeof *entry); + if (!entry) + goto out; + + state |= KNOWN_SEVERITY; + if (id) + _mesa_HashInsert(nspace->IDs, id, (void*)state); + else + nspace->ZeroID = state; + + entry->ID = id; + insert_at_tail(&nspace->Severity[severity], &entry->link); + } + } out: return !!(state & ENABLED_BIT); } + /** * Sets the state of the given message source/type/ID tuple. */ @@ -247,33 +305,39 @@ set_message_state(struct gl_context *ctx, enum mesa_debug_type type, GLuint id, GLboolean enabled) { - GLint gstack = ctx->Debug.GroupStackDepth; - struct gl_debug_namespace *nspace = - &ctx->Debug.Namespaces[gstack][source][type]; - uintptr_t state; - - /* In addition to not being able to store zero as a value, HashTable also - can't use zero as a key. */ - if (id) - state = (uintptr_t)_mesa_HashLookup(nspace->IDs, id); - else - state = nspace->ZeroID; - - if (state == NOT_FOUND) - state = enabled ? ENABLED : DISABLED; - else { - if (enabled) - state |= ENABLED_BIT; + struct gl_debug_state *debug = _mesa_get_debug_state(ctx); + + if (debug) { + GLint gstack = debug->GroupStackDepth; + struct gl_debug_namespace *nspace = + &debug->Namespaces[gstack][source][type]; + uintptr_t state; + + /* In addition to not being able to store zero as a value, HashTable also + * can't use zero as a key. + */ + if (id) + state = (uintptr_t)_mesa_HashLookup(nspace->IDs, id); else - state &= ~ENABLED_BIT; - } + state = nspace->ZeroID; - if (id) - _mesa_HashInsert(nspace->IDs, id, (void*)state); - else - nspace->ZeroID = state; + if (state == NOT_FOUND) + state = enabled ? ENABLED : DISABLED; + else { + if (enabled) + state |= ENABLED_BIT; + else + state &= ~ENABLED_BIT; + } + + if (id) + _mesa_HashInsert(nspace->IDs, id, (void*)state); + else + nspace->ZeroID = state; + } } + static void store_message_details(struct gl_debug_msg *emptySlot, enum mesa_debug_source source, @@ -307,7 +371,8 @@ store_message_details(struct gl_debug_msg *emptySlot, } } - /** + +/** * Remap any type exclusive to KHR_debug to something suitable * for ARB_debug_output */ @@ -326,6 +391,7 @@ remap_type(GLenum type) { return type; } + /** * Remap severity exclusive to KHR_debug to something suitable * for ARB_debug_output @@ -339,6 +405,7 @@ remap_severity(GLenum severity) { return severity; } + /** * 'buf' is not necessarily a null-terminated string. When logging, copy * 'len' characters from it, store them in a new, null-terminated string, @@ -346,49 +413,51 @@ remap_severity(GLenum severity) { * the null terminator this time. */ static void -_mesa_log_msg(struct gl_context *ctx, enum mesa_debug_source source, - enum mesa_debug_type type, GLuint id, - enum mesa_debug_severity severity, GLint len, const char *buf) +log_msg(struct gl_context *ctx, enum mesa_debug_source source, + enum mesa_debug_type type, GLuint id, + enum mesa_debug_severity severity, GLint len, const char *buf) { + struct gl_debug_state *debug = _mesa_get_debug_state(ctx); GLint nextEmpty; struct gl_debug_msg *emptySlot; + if (!debug) + return; + assert(len >= 0 && len < MAX_DEBUG_MESSAGE_LENGTH); if (!should_log(ctx, source, type, id, severity)) return; - if (ctx->Debug.Callback) { + if (debug->Callback) { GLenum gl_type = debug_type_enums[type]; GLenum gl_severity = debug_severity_enums[severity]; - if (ctx->Debug.ARBCallback) { + if (debug->ARBCallback) { gl_severity = remap_severity(gl_severity); gl_type = remap_type(gl_type); } - ctx->Debug.Callback(debug_source_enums[source], - gl_type, - id, - gl_severity, - len, buf, ctx->Debug.CallbackData); + debug->Callback(debug_source_enums[source], gl_type, id, gl_severity, + len, buf, debug->CallbackData); return; } - if (ctx->Debug.NumMessages == MAX_DEBUG_LOGGED_MESSAGES) + if (debug->NumMessages == MAX_DEBUG_LOGGED_MESSAGES) return; - nextEmpty = (ctx->Debug.NextMsg + ctx->Debug.NumMessages) + nextEmpty = (debug->NextMsg + debug->NumMessages) % MAX_DEBUG_LOGGED_MESSAGES; - emptySlot = &ctx->Debug.Log[nextEmpty]; + emptySlot = &debug->Log[nextEmpty]; store_message_details(emptySlot, source, type, id, severity, len, buf); - if (ctx->Debug.NumMessages == 0) - ctx->Debug.NextMsgLength = ctx->Debug.Log[ctx->Debug.NextMsg].length; + if (debug->NumMessages == 0) + debug->NextMsgLength = debug->Log[debug->NextMsg].length; - ctx->Debug.NumMessages++; + debug->NumMessages++; } + /** * Pop the oldest debug message out of the log. * Writes the message string, including the null terminator, into 'buf', @@ -400,20 +469,21 @@ _mesa_log_msg(struct gl_context *ctx, enum mesa_debug_source source, * indicates failure. */ static GLsizei -_mesa_get_msg(struct gl_context *ctx, GLenum *source, GLenum *type, - GLuint *id, GLenum *severity, GLsizei bufSize, char *buf, - unsigned caller) +get_msg(struct gl_context *ctx, GLenum *source, GLenum *type, + GLuint *id, GLenum *severity, GLsizei bufSize, char *buf, + unsigned caller) { + struct gl_debug_state *debug = _mesa_get_debug_state(ctx); struct gl_debug_msg *msg; GLsizei length; - if (ctx->Debug.NumMessages == 0) + if (!debug || debug->NumMessages == 0) return 0; - msg = &ctx->Debug.Log[ctx->Debug.NextMsg]; + msg = &debug->Log[debug->NextMsg]; length = msg->length; - assert(length > 0 && length == ctx->Debug.NextMsgLength); + assert(length > 0 && length == debug->NextMsgLength); if (bufSize < length && buf != NULL) return 0; @@ -423,15 +493,20 @@ _mesa_get_msg(struct gl_context *ctx, GLenum *source, GLenum *type, if (caller == MESSAGE_LOG_ARB) *severity = remap_severity(*severity); } - if (source) + + if (source) { *source = debug_source_enums[msg->source]; + } + if (type) { *type = debug_type_enums[msg->type]; if (caller == MESSAGE_LOG_ARB) *type = remap_type(*type); } - if (id) + + if (id) { *id = msg->id; + } if (buf) { assert(msg->message[length-1] == '\0'); @@ -443,14 +518,15 @@ _mesa_get_msg(struct gl_context *ctx, GLenum *source, GLenum *type, msg->message = NULL; msg->length = 0; - ctx->Debug.NumMessages--; - ctx->Debug.NextMsg++; - ctx->Debug.NextMsg %= MAX_DEBUG_LOGGED_MESSAGES; - ctx->Debug.NextMsgLength = ctx->Debug.Log[ctx->Debug.NextMsg].length; + debug->NumMessages--; + debug->NextMsg++; + debug->NextMsg %= MAX_DEBUG_LOGGED_MESSAGES; + debug->NextMsgLength = debug->Log[debug->NextMsg].length; return length; } + /** * Verify that source, type, and severity are valid enums. * glDebugMessageInsertARB only accepts two values for 'source', @@ -523,14 +599,14 @@ validate_params(struct gl_context *ctx, unsigned caller, return GL_TRUE; error: - { - _mesa_error(ctx, GL_INVALID_ENUM, "bad values passed to %s" - "(source=0x%x, type=0x%x, severity=0x%x)", callerstr, - source, type, severity); - } + _mesa_error(ctx, GL_INVALID_ENUM, "bad values passed to %s" + "(source=0x%x, type=0x%x, severity=0x%x)", callerstr, + source, type, severity); + return GL_FALSE; } + /** * Set the state of all message IDs found in the given intersection of * 'source', 'type', and 'severity'. The _COUNT enum can be used for @@ -549,8 +625,12 @@ control_messages(struct gl_context *ctx, enum mesa_debug_severity severity, GLboolean enabled) { + struct gl_debug_state *debug = _mesa_get_debug_state(ctx); int s, t, sev, smax, tmax, sevmax; - GLint gstack = ctx->Debug.GroupStackDepth; + const GLint gstack = debug ? debug->GroupStackDepth : 0; + + if (!debug) + return; if (source == MESA_DEBUG_SOURCE_COUNT) { source = 0; @@ -573,23 +653,26 @@ control_messages(struct gl_context *ctx, sevmax = severity+1; } - for (sev = severity; sev < sevmax; sev++) - for (s = source; s < smax; s++) + for (sev = severity; sev < sevmax; sev++) { + for (s = source; s < smax; s++) { for (t = type; t < tmax; t++) { struct simple_node *node; struct gl_debug_severity *entry; /* change the default for IDs we've never seen before. */ - ctx->Debug.Defaults[gstack][sev][s][t] = enabled; + debug->Defaults[gstack][sev][s][t] = enabled; /* Now change the state of IDs we *have* seen... */ - foreach(node, &ctx->Debug.Namespaces[gstack][s][t].Severity[sev]) { + foreach(node, &debug->Namespaces[gstack][s][t].Severity[sev]) { entry = (struct gl_debug_severity *)node; set_message_state(ctx, s, t, entry->ID, enabled); } } + } + } } + /** * Debugging-message namespaces with the source APPLICATION or THIRD_PARTY * require special handling, since the IDs in them are controlled by clients, @@ -621,6 +704,7 @@ control_app_messages(struct gl_context *ctx, GLenum esource, GLenum etype, control_messages(ctx, source, type, severity, enabled); } + /** * This is a generic message control function for use by both * glDebugMessageControlARB and glDebugMessageControl. @@ -658,6 +742,7 @@ message_control(GLenum gl_source, GLenum gl_type, count, ids, enabled); } + /** * This is a generic message insert function. * Validation of source, type and severity parameters should be done @@ -665,7 +750,7 @@ message_control(GLenum gl_source, GLenum gl_type, */ static void message_insert(GLenum source, GLenum type, GLuint id, - GLenum severity, GLint length, const GLchar* buf, + GLenum severity, GLint length, const GLchar *buf, const char *callerstr) { GET_CURRENT_CONTEXT(ctx); @@ -681,20 +766,21 @@ message_insert(GLenum source, GLenum type, GLuint id, return; } - _mesa_log_msg(ctx, - gl_enum_to_debug_source(source), - gl_enum_to_debug_type(type), id, - gl_enum_to_debug_severity(severity), length, buf); + log_msg(ctx, + gl_enum_to_debug_source(source), + gl_enum_to_debug_type(type), id, + gl_enum_to_debug_severity(severity), length, buf); } + /** * This is a generic message insert function for use by both * glGetDebugMessageLogARB and glGetDebugMessageLog. */ static GLuint -get_message_log(GLuint count, GLsizei logSize, GLenum* sources, - GLenum* types, GLenum* ids, GLenum* severities, - GLsizei* lengths, GLchar* messageLog, +get_message_log(GLuint count, GLsizei logSize, GLenum *sources, + GLenum *types, GLenum *ids, GLenum *severities, + GLsizei *lengths, GLchar *messageLog, unsigned caller, const char *callerstr) { GET_CURRENT_CONTEXT(ctx); @@ -711,8 +797,8 @@ get_message_log(GLuint count, GLsizei logSize, GLenum* sources, } for (ret = 0; ret < count; ret++) { - GLsizei written = _mesa_get_msg(ctx, sources, types, ids, severities, - logSize, messageLog, caller); + GLsizei written = get_msg(ctx, sources, types, ids, severities, + logSize, messageLog, caller); if (!written) break; @@ -738,41 +824,52 @@ get_message_log(GLuint count, GLsizei logSize, GLenum* sources, return ret; } + static void do_nothing(GLuint key, void *data, void *userData) { } + +/** + * Free context state pertaining to error/debug state for the given stack + * depth. + */ static void free_errors_data(struct gl_context *ctx, GLint gstack) { + struct gl_debug_state *debug = ctx->Debug; enum mesa_debug_type t; enum mesa_debug_source s; enum mesa_debug_severity sev; + assert(debug); + /* Tear down state for filtering debug messages. */ - for (s = 0; s < MESA_DEBUG_SOURCE_COUNT; s++) + for (s = 0; s < MESA_DEBUG_SOURCE_COUNT; s++) { for (t = 0; t < MESA_DEBUG_TYPE_COUNT; t++) { - _mesa_HashDeleteAll(ctx->Debug.Namespaces[gstack][s][t].IDs, + _mesa_HashDeleteAll(debug->Namespaces[gstack][s][t].IDs, do_nothing, NULL); - _mesa_DeleteHashTable(ctx->Debug.Namespaces[gstack][s][t].IDs); + _mesa_DeleteHashTable(debug->Namespaces[gstack][s][t].IDs); for (sev = 0; sev < MESA_DEBUG_SEVERITY_COUNT; sev++) { struct simple_node *node, *tmp; struct gl_debug_severity *entry; foreach_s(node, tmp, - &ctx->Debug.Namespaces[gstack][s][t].Severity[sev]) { + &debug->Namespaces[gstack][s][t].Severity[sev]) { entry = (struct gl_debug_severity *)node; free(entry); } } } + } } + void GLAPIENTRY _mesa_DebugMessageInsert(GLenum source, GLenum type, GLuint id, GLenum severity, GLint length, - const GLchar* buf) + const GLchar *buf) { const char *callerstr = "glDebugMessageInsert"; @@ -781,14 +878,14 @@ _mesa_DebugMessageInsert(GLenum source, GLenum type, GLuint id, if (!validate_params(ctx, INSERT, callerstr, source, type, severity)) return; /* GL_INVALID_ENUM */ - message_insert(source, type, id, severity, length, buf, - callerstr); + message_insert(source, type, id, severity, length, buf, callerstr); } + GLuint GLAPIENTRY -_mesa_GetDebugMessageLog(GLuint count, GLsizei logSize, GLenum* sources, - GLenum* types, GLenum* ids, GLenum* severities, - GLsizei* lengths, GLchar* messageLog) +_mesa_GetDebugMessageLog(GLuint count, GLsizei logSize, GLenum *sources, + GLenum *types, GLenum *ids, GLenum *severities, + GLsizei *lengths, GLchar *messageLog) { const char *callerstr = "glGetDebugMessageLog"; @@ -796,6 +893,7 @@ _mesa_GetDebugMessageLog(GLuint count, GLsizei logSize, GLenum* sources, lengths, messageLog, MESSAGE_LOG, callerstr); } + void GLAPIENTRY _mesa_DebugMessageControl(GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, @@ -807,28 +905,36 @@ _mesa_DebugMessageControl(GLenum source, GLenum type, GLenum severity, enabled, CONTROL, callerstr); } + void GLAPIENTRY _mesa_DebugMessageCallback(GLDEBUGPROC callback, const void *userParam) { GET_CURRENT_CONTEXT(ctx); - ctx->Debug.Callback = callback; - ctx->Debug.CallbackData = userParam; - ctx->Debug.ARBCallback = GL_FALSE; + struct gl_debug_state *debug = _mesa_get_debug_state(ctx); + if (debug) { + debug->Callback = callback; + debug->CallbackData = userParam; + debug->ARBCallback = GL_FALSE; + } } + void GLAPIENTRY _mesa_PushDebugGroup(GLenum source, GLuint id, GLsizei length, const GLchar *message) { + GET_CURRENT_CONTEXT(ctx); + struct gl_debug_state *debug = _mesa_get_debug_state(ctx); const char *callerstr = "glPushDebugGroup"; int s, t, sev; GLint prevStackDepth; GLint currStackDepth; struct gl_debug_msg *emptySlot; - GET_CURRENT_CONTEXT(ctx); + if (!debug) + return; - if (ctx->Debug.GroupStackDepth >= MAX_DEBUG_GROUP_STACK_DEPTH-1) { + if (debug->GroupStackDepth >= MAX_DEBUG_GROUP_STACK_DEPTH-1) { _mesa_error(ctx, GL_STACK_OVERFLOW, "%s", callerstr); return; } @@ -847,14 +953,14 @@ _mesa_PushDebugGroup(GLenum source, GLuint id, GLsizei length, GL_DEBUG_SEVERITY_NOTIFICATION, length, message, callerstr); - prevStackDepth = ctx->Debug.GroupStackDepth; - ctx->Debug.GroupStackDepth++; - currStackDepth = ctx->Debug.GroupStackDepth; + prevStackDepth = debug->GroupStackDepth; + debug->GroupStackDepth++; + currStackDepth = debug->GroupStackDepth; /* pop reuses the message details from push so we store this */ if (length < 0) length = strlen(message); - emptySlot = &ctx->Debug.DebugGroupMsgs[ctx->Debug.GroupStackDepth]; + emptySlot = &debug->DebugGroupMsgs[debug->GroupStackDepth]; store_message_details(emptySlot, gl_enum_to_debug_source(source), gl_enum_to_debug_type(GL_DEBUG_TYPE_PUSH_GROUP), id, @@ -864,60 +970,66 @@ _mesa_PushDebugGroup(GLenum source, GLuint id, GLsizei length, /* inherit the control volume of the debug group previously residing on * the top of the debug group stack */ - for (s = 0; s < MESA_DEBUG_SOURCE_COUNT; s++) + for (s = 0; s < MESA_DEBUG_SOURCE_COUNT; s++) { for (t = 0; t < MESA_DEBUG_TYPE_COUNT; t++) { /* copy id settings */ - ctx->Debug.Namespaces[currStackDepth][s][t].IDs = - _mesa_HashClone(ctx->Debug.Namespaces[prevStackDepth][s][t].IDs); + debug->Namespaces[currStackDepth][s][t].IDs = + _mesa_HashClone(debug->Namespaces[prevStackDepth][s][t].IDs); for (sev = 0; sev < MESA_DEBUG_SEVERITY_COUNT; sev++) { struct gl_debug_severity *entry, *prevEntry; struct simple_node *node; /* copy default settings for unknown ids */ - ctx->Debug.Defaults[currStackDepth][sev][s][t] = ctx->Debug.Defaults[prevStackDepth][sev][s][t]; + debug->Defaults[currStackDepth][sev][s][t] = + debug->Defaults[prevStackDepth][sev][s][t]; /* copy known id severity settings */ - make_empty_list(&ctx->Debug.Namespaces[currStackDepth][s][t].Severity[sev]); - foreach(node, &ctx->Debug.Namespaces[prevStackDepth][s][t].Severity[sev]) { + make_empty_list(&debug->Namespaces[currStackDepth][s][t].Severity[sev]); + foreach(node, &debug->Namespaces[prevStackDepth][s][t].Severity[sev]) { prevEntry = (struct gl_debug_severity *)node; entry = malloc(sizeof *entry); if (!entry) return; entry->ID = prevEntry->ID; - insert_at_tail(&ctx->Debug.Namespaces[currStackDepth][s][t].Severity[sev], &entry->link); + insert_at_tail(&debug->Namespaces[currStackDepth][s][t].Severity[sev], &entry->link); } } } + } } + void GLAPIENTRY -_mesa_PopDebugGroup() +_mesa_PopDebugGroup(void) { + GET_CURRENT_CONTEXT(ctx); + struct gl_debug_state *debug = _mesa_get_debug_state(ctx); const char *callerstr = "glPopDebugGroup"; struct gl_debug_msg *gdmessage; GLint prevStackDepth; - GET_CURRENT_CONTEXT(ctx); + if (!debug) + return; - if (ctx->Debug.GroupStackDepth <= 0) { + if (debug->GroupStackDepth <= 0) { _mesa_error(ctx, GL_STACK_UNDERFLOW, "%s", callerstr); return; } - prevStackDepth = ctx->Debug.GroupStackDepth; - ctx->Debug.GroupStackDepth--; + prevStackDepth = debug->GroupStackDepth; + debug->GroupStackDepth--; - gdmessage = &ctx->Debug.DebugGroupMsgs[prevStackDepth]; - /* using _mesa_log_msg() directly here as verification of parameters + gdmessage = &debug->DebugGroupMsgs[prevStackDepth]; + /* using log_msg() directly here as verification of parameters * already done in push */ - _mesa_log_msg(ctx, gdmessage->source, - gl_enum_to_debug_type(GL_DEBUG_TYPE_POP_GROUP), - gdmessage->id, - gl_enum_to_debug_severity(GL_DEBUG_SEVERITY_NOTIFICATION), - gdmessage->length, gdmessage->message); + log_msg(ctx, gdmessage->source, + gl_enum_to_debug_type(GL_DEBUG_TYPE_POP_GROUP), + gdmessage->id, + gl_enum_to_debug_severity(GL_DEBUG_SEVERITY_NOTIFICATION), + gdmessage->length, gdmessage->message); if (gdmessage->message != (char*)out_of_memory) free(gdmessage->message); @@ -928,10 +1040,11 @@ _mesa_PopDebugGroup() free_errors_data(ctx, prevStackDepth); } + void GLAPIENTRY _mesa_DebugMessageInsertARB(GLenum source, GLenum type, GLuint id, GLenum severity, GLint length, - const GLcharARB* buf) + const GLcharARB *buf) { const char *callerstr = "glDebugMessageInsertARB"; @@ -940,14 +1053,14 @@ _mesa_DebugMessageInsertARB(GLenum source, GLenum type, GLuint id, if (!validate_params(ctx, INSERT_ARB, callerstr, source, type, severity)) return; /* GL_INVALID_ENUM */ - message_insert(source, type, id, severity, length, buf, - callerstr); + message_insert(source, type, id, severity, length, buf, callerstr); } + GLuint GLAPIENTRY -_mesa_GetDebugMessageLogARB(GLuint count, GLsizei logSize, GLenum* sources, - GLenum* types, GLenum* ids, GLenum* severities, - GLsizei* lengths, GLcharARB* messageLog) +_mesa_GetDebugMessageLogARB(GLuint count, GLsizei logSize, GLenum *sources, + GLenum *types, GLenum *ids, GLenum *severities, + GLsizei *lengths, GLcharARB *messageLog) { const char *callerstr = "glGetDebugMessageLogARB"; @@ -955,6 +1068,7 @@ _mesa_GetDebugMessageLogARB(GLuint count, GLsizei logSize, GLenum* sources, lengths, messageLog, MESSAGE_LOG_ARB, callerstr); } + void GLAPIENTRY _mesa_DebugMessageControlARB(GLenum gl_source, GLenum gl_type, GLenum gl_severity, @@ -967,47 +1081,27 @@ _mesa_DebugMessageControlARB(GLenum gl_source, GLenum gl_type, enabled, CONTROL_ARB, callerstr); } + void GLAPIENTRY _mesa_DebugMessageCallbackARB(GLDEBUGPROCARB callback, const void *userParam) { GET_CURRENT_CONTEXT(ctx); - ctx->Debug.Callback = callback; - ctx->Debug.CallbackData = userParam; - ctx->Debug.ARBCallback = GL_TRUE; + struct gl_debug_state *debug = _mesa_get_debug_state(ctx); + if (debug) { + debug->Callback = callback; + debug->CallbackData = userParam; + debug->ARBCallback = GL_TRUE; + } } + void _mesa_init_errors(struct gl_context *ctx) { - int s, t, sev; - - ctx->Debug.Callback = NULL; - ctx->Debug.SyncOutput = GL_FALSE; - ctx->Debug.Log[0].length = 0; - ctx->Debug.NumMessages = 0; - ctx->Debug.NextMsg = 0; - ctx->Debug.NextMsgLength = 0; - ctx->Debug.GroupStackDepth = 0; - - /* Enable all the messages with severity HIGH or MEDIUM by default. */ - memset(ctx->Debug.Defaults[0][MESA_DEBUG_SEVERITY_HIGH], GL_TRUE, - sizeof ctx->Debug.Defaults[0][MESA_DEBUG_SEVERITY_HIGH]); - memset(ctx->Debug.Defaults[0][MESA_DEBUG_SEVERITY_MEDIUM], GL_TRUE, - sizeof ctx->Debug.Defaults[0][MESA_DEBUG_SEVERITY_MEDIUM]); - memset(ctx->Debug.Defaults[0][MESA_DEBUG_SEVERITY_LOW], GL_FALSE, - sizeof ctx->Debug.Defaults[0][MESA_DEBUG_SEVERITY_LOW]); - - /* Initialize state for filtering known debug messages. */ - for (s = 0; s < MESA_DEBUG_SOURCE_COUNT; s++) - for (t = 0; t < MESA_DEBUG_TYPE_COUNT; t++) { - ctx->Debug.Namespaces[0][s][t].IDs = _mesa_NewHashTable(); - assert(ctx->Debug.Namespaces[0][s][t].IDs); - - for (sev = 0; sev < MESA_DEBUG_SEVERITY_COUNT; sev++) - make_empty_list(&ctx->Debug.Namespaces[0][s][t].Severity[sev]); - } + /* no-op */ } + /** * Loop through debug group stack tearing down states for * filtering debug messages. @@ -1015,13 +1109,16 @@ _mesa_init_errors(struct gl_context *ctx) void _mesa_free_errors_data(struct gl_context *ctx) { - GLint i; + if (ctx->Debug) { + GLint i; - for (i = 0; i <= ctx->Debug.GroupStackDepth; i++) { - free_errors_data(ctx, i); + for (i = 0; i <= ctx->Debug->GroupStackDepth; i++) { + free_errors_data(ctx, i); + } } } + /**********************************************************************/ /** \name Diagnostics */ /*@{*/ @@ -1077,6 +1174,7 @@ output_if_debug(const char *prefixString, const char *outputString, } } + /** * When a new type of error is recorded, print a message describing * previous errors which were accumulated. @@ -1149,6 +1247,7 @@ _mesa_problem( const struct gl_context *ctx, const char *fmtString, ... ) } } + static GLboolean should_output(struct gl_context *ctx, GLenum error, const char *fmtString) { @@ -1185,6 +1284,7 @@ should_output(struct gl_context *ctx, GLenum error, const char *fmtString) return GL_FALSE; } + void _mesa_gl_debug(struct gl_context *ctx, GLuint *id, @@ -1202,8 +1302,7 @@ _mesa_gl_debug(struct gl_context *ctx, len = _mesa_vsnprintf(s, MAX_DEBUG_MESSAGE_LENGTH, fmtString, args); va_end(args); - _mesa_log_msg(ctx, MESA_DEBUG_SOURCE_API, type, - *id, severity, len, s); + log_msg(ctx, MESA_DEBUG_SOURCE_API, type, *id, severity, len, s); } @@ -1248,7 +1347,8 @@ _mesa_error( struct gl_context *ctx, GLenum error, const char *fmtString, ... ) if (len >= MAX_DEBUG_MESSAGE_LENGTH) { /* Too long error message. Whoever calls _mesa_error should use - * shorter strings. */ + * shorter strings. + */ ASSERT(0); return; } @@ -1268,11 +1368,8 @@ _mesa_error( struct gl_context *ctx, GLenum error, const char *fmtString, ... ) /* Log the error via ARB_debug_output if needed.*/ if (do_log) { - _mesa_log_msg(ctx, - MESA_DEBUG_SOURCE_API, - MESA_DEBUG_TYPE_ERROR, - error_msg_id, - MESA_DEBUG_SEVERITY_HIGH, len, s2); + log_msg(ctx, MESA_DEBUG_SOURCE_API, MESA_DEBUG_TYPE_ERROR, + error_msg_id, MESA_DEBUG_SEVERITY_HIGH, len, s2); } } @@ -1329,7 +1426,7 @@ _mesa_shader_debug( struct gl_context *ctx, GLenum type, GLuint *id, if (len >= MAX_DEBUG_MESSAGE_LENGTH) len = MAX_DEBUG_MESSAGE_LENGTH - 1; - _mesa_log_msg(ctx, source, type, *id, severity, len, msg); + log_msg(ctx, source, type, *id, severity, len, msg); } /*@}*/ diff --git a/mesalib/src/mesa/main/errors.h b/mesalib/src/mesa/main/errors.h index a837dc8e1..cd414e6b6 100644 --- a/mesalib/src/mesa/main/errors.h +++ b/mesalib/src/mesa/main/errors.h @@ -83,6 +83,9 @@ _mesa_gl_debug(struct gl_context *ctx, } \ } while (0) +struct gl_debug_state * +_mesa_get_debug_state(struct gl_context *ctx); + extern void _mesa_shader_debug(struct gl_context *ctx, GLenum type, GLuint *id, const char *msg, int len); diff --git a/mesalib/src/mesa/main/execmem.c b/mesalib/src/mesa/main/execmem.c index d63bb4a4e..7267cf85f 100644 --- a/mesalib/src/mesa/main/execmem.c +++ b/mesalib/src/mesa/main/execmem.c @@ -32,7 +32,6 @@ #include "imports.h" -#include "glapi/glthread.h" @@ -59,7 +58,7 @@ #define EXEC_HEAP_SIZE (10*1024*1024) -_glthread_DECLARE_STATIC_MUTEX(exec_mutex); +static mtx_t exec_mutex = _MTX_INITIALIZER_NP; static struct mem_block *exec_heap = NULL; static unsigned char *exec_mem = NULL; @@ -93,7 +92,7 @@ _mesa_exec_malloc(GLuint size) struct mem_block *block = NULL; void *addr = NULL; - _glthread_LOCK_MUTEX(exec_mutex); + mtx_lock(&exec_mutex); if (!init_heap()) goto bail; @@ -109,7 +108,7 @@ _mesa_exec_malloc(GLuint size) printf("_mesa_exec_malloc failed\n"); bail: - _glthread_UNLOCK_MUTEX(exec_mutex); + mtx_unlock(&exec_mutex); return addr; } @@ -118,7 +117,7 @@ bail: void _mesa_exec_free(void *addr) { - _glthread_LOCK_MUTEX(exec_mutex); + mtx_lock(&exec_mutex); if (exec_heap) { struct mem_block *block = mmFindBlock(exec_heap, (unsigned char *)addr - exec_mem); @@ -127,7 +126,7 @@ _mesa_exec_free(void *addr) mmFreeMem(block); } - _glthread_UNLOCK_MUTEX(exec_mutex); + mtx_unlock(&exec_mutex); } diff --git a/mesalib/src/mesa/main/extensions.c b/mesalib/src/mesa/main/extensions.c index 5f741fbd2..c46d70b20 100644 --- a/mesalib/src/mesa/main/extensions.c +++ b/mesalib/src/mesa/main/extensions.c @@ -83,6 +83,7 @@ static const struct extension extension_table[] = { { "GL_ARB_arrays_of_arrays", o(ARB_arrays_of_arrays), GL, 2012 }, { "GL_ARB_base_instance", o(ARB_base_instance), GL, 2011 }, { "GL_ARB_blend_func_extended", o(ARB_blend_func_extended), GL, 2009 }, + { "GL_ARB_buffer_storage", o(ARB_buffer_storage), GL, 2013 }, { "GL_ARB_clear_buffer_object", o(dummy_true), GL, 2012 }, { "GL_ARB_color_buffer_float", o(ARB_color_buffer_float), GL, 2004 }, { "GL_ARB_compute_shader", o(ARB_compute_shader), GL, 2012 }, @@ -106,7 +107,7 @@ static const struct extension extension_table[] = { { "GL_ARB_framebuffer_sRGB", o(EXT_framebuffer_sRGB), GL, 1998 }, { "GL_ARB_get_program_binary", o(dummy_true), GL, 2010 }, { "GL_ARB_gpu_shader5", o(ARB_gpu_shader5), GL, 2010 }, - { "GL_ARB_half_float_pixel", o(ARB_half_float_pixel), GL, 2003 }, + { "GL_ARB_half_float_pixel", o(dummy_true), GL, 2003 }, { "GL_ARB_half_float_vertex", o(ARB_half_float_vertex), GL, 2008 }, { "GL_ARB_instanced_arrays", o(ARB_instanced_arrays), GL, 2008 }, { "GL_ARB_internalformat_query", o(ARB_internalformat_query), GL, 2011 }, @@ -126,6 +127,7 @@ static const struct extension extension_table[] = { { "GL_ARB_sample_shading", o(ARB_sample_shading), GL, 2009 }, { "GL_ARB_sampler_objects", o(dummy_true), GL, 2009 }, { "GL_ARB_seamless_cube_map", o(ARB_seamless_cube_map), GL, 2009 }, + { "GL_ARB_separate_shader_objects", o(ARB_separate_shader_objects), GL, 2010 }, { "GL_ARB_shader_atomic_counters", o(ARB_shader_atomic_counters), GL, 2011 }, { "GL_ARB_shader_bit_encoding", o(ARB_shader_bit_encoding), GL, 2010 }, { "GL_ARB_shader_image_load_store", o(ARB_shader_image_load_store), GL, 2011 }, @@ -401,7 +403,6 @@ _mesa_enable_sw_extensions(struct gl_context *ctx) ctx->Extensions.ARB_fragment_program_shadow = GL_TRUE; ctx->Extensions.ARB_fragment_shader = GL_TRUE; ctx->Extensions.ARB_framebuffer_object = GL_TRUE; - ctx->Extensions.ARB_half_float_pixel = GL_TRUE; ctx->Extensions.ARB_half_float_vertex = GL_TRUE; ctx->Extensions.ARB_map_buffer_range = GL_TRUE; ctx->Extensions.ARB_occlusion_query = GL_TRUE; diff --git a/mesalib/src/mesa/main/fbobject.c b/mesalib/src/mesa/main/fbobject.c index e459e0c63..a9dcc5144 100644 --- a/mesalib/src/mesa/main/fbobject.c +++ b/mesalib/src/mesa/main/fbobject.c @@ -89,9 +89,9 @@ delete_dummy_framebuffer(struct gl_framebuffer *fb) void _mesa_init_fbobjects(struct gl_context *ctx) { - _glthread_INIT_MUTEX(DummyFramebuffer.Mutex); - _glthread_INIT_MUTEX(DummyRenderbuffer.Mutex); - _glthread_INIT_MUTEX(IncompleteFramebuffer.Mutex); + mtx_init(&DummyFramebuffer.Mutex, mtx_plain); + mtx_init(&DummyRenderbuffer.Mutex, mtx_plain); + mtx_init(&IncompleteFramebuffer.Mutex, mtx_plain); DummyFramebuffer.Delete = delete_dummy_framebuffer; DummyRenderbuffer.Delete = delete_dummy_renderbuffer; IncompleteFramebuffer.Delete = delete_dummy_framebuffer; @@ -484,7 +484,7 @@ _mesa_framebuffer_renderbuffer(struct gl_context *ctx, { struct gl_renderbuffer_attachment *att; - _glthread_LOCK_MUTEX(fb->Mutex); + mtx_lock(&fb->Mutex); att = get_attachment(ctx, fb, attachment); ASSERT(att); @@ -504,7 +504,7 @@ _mesa_framebuffer_renderbuffer(struct gl_context *ctx, invalidate_framebuffer(fb); - _glthread_UNLOCK_MUTEX(fb->Mutex); + mtx_unlock(&fb->Mutex); } @@ -1352,9 +1352,9 @@ _mesa_GenRenderbuffers(GLsizei n, GLuint *renderbuffers) GLuint name = first + i; renderbuffers[i] = name; /* insert dummy placeholder into hash table */ - _glthread_LOCK_MUTEX(ctx->Shared->Mutex); + mtx_lock(&ctx->Shared->Mutex); _mesa_HashInsert(ctx->Shared->RenderBuffers, name, &DummyRenderbuffer); - _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); + mtx_unlock(&ctx->Shared->Mutex); } } @@ -2218,9 +2218,9 @@ _mesa_GenFramebuffers(GLsizei n, GLuint *framebuffers) GLuint name = first + i; framebuffers[i] = name; /* insert dummy placeholder into hash table */ - _glthread_LOCK_MUTEX(ctx->Shared->Mutex); + mtx_lock(&ctx->Shared->Mutex); _mesa_HashInsert(ctx->Shared->FrameBuffers, name, &DummyFramebuffer); - _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); + mtx_unlock(&ctx->Shared->Mutex); } } @@ -2433,7 +2433,7 @@ framebuffer_texture(struct gl_context *ctx, const char *caller, GLenum target, FLUSH_VERTICES(ctx, _NEW_BUFFERS); - _glthread_LOCK_MUTEX(fb->Mutex); + mtx_lock(&fb->Mutex); if (texObj) { if (attachment == GL_DEPTH_ATTACHMENT && texObj == fb->Attachment[BUFFER_STENCIL].Texture && @@ -2491,7 +2491,7 @@ framebuffer_texture(struct gl_context *ctx, const char *caller, GLenum target, invalidate_framebuffer(fb); - _glthread_UNLOCK_MUTEX(fb->Mutex); + mtx_unlock(&fb->Mutex); } diff --git a/mesalib/src/mesa/main/format_pack.c b/mesalib/src/mesa/main/format_pack.c index dee253c40..2772ff2d3 100644 --- a/mesalib/src/mesa/main/format_pack.c +++ b/mesalib/src/mesa/main/format_pack.c @@ -1936,9 +1936,9 @@ _mesa_get_pack_ubyte_rgba_function(mesa_format format) /* should never convert RGBA to these formats */ table[MESA_FORMAT_S8_UINT_Z24_UNORM] = NULL; - table[MESA_FORMAT_Z24_UNORM_X8_UINT] = NULL; - table[MESA_FORMAT_Z_UNORM16] = NULL; table[MESA_FORMAT_Z24_UNORM_S8_UINT] = NULL; + table[MESA_FORMAT_Z_UNORM16] = NULL; + table[MESA_FORMAT_Z24_UNORM_X8_UINT] = NULL; table[MESA_FORMAT_X8Z24_UNORM] = NULL; table[MESA_FORMAT_Z_UNORM32] = NULL; table[MESA_FORMAT_S_UINT8] = NULL; @@ -2099,9 +2099,9 @@ _mesa_get_pack_float_rgba_function(mesa_format format) /* should never convert RGBA to these formats */ table[MESA_FORMAT_S8_UINT_Z24_UNORM] = NULL; - table[MESA_FORMAT_Z24_UNORM_X8_UINT] = NULL; - table[MESA_FORMAT_Z_UNORM16] = NULL; table[MESA_FORMAT_Z24_UNORM_S8_UINT] = NULL; + table[MESA_FORMAT_Z_UNORM16] = NULL; + table[MESA_FORMAT_Z24_UNORM_X8_UINT] = NULL; table[MESA_FORMAT_X8Z24_UNORM] = NULL; table[MESA_FORMAT_Z_UNORM32] = NULL; table[MESA_FORMAT_S_UINT8] = NULL; @@ -2433,8 +2433,8 @@ _mesa_get_pack_float_z_func(mesa_format format) case MESA_FORMAT_S8_UINT_Z24_UNORM: case MESA_FORMAT_X8Z24_UNORM: return pack_float_z_Z24_S8; - case MESA_FORMAT_Z24_UNORM_X8_UINT: case MESA_FORMAT_Z24_UNORM_S8_UINT: + case MESA_FORMAT_Z24_UNORM_X8_UINT: return pack_float_z_S8_Z24; case MESA_FORMAT_Z_UNORM16: return pack_float_z_Z16; @@ -2518,8 +2518,8 @@ _mesa_get_pack_uint_z_func(mesa_format format) case MESA_FORMAT_S8_UINT_Z24_UNORM: case MESA_FORMAT_X8Z24_UNORM: return pack_uint_z_Z24_S8; - case MESA_FORMAT_Z24_UNORM_X8_UINT: case MESA_FORMAT_Z24_UNORM_S8_UINT: + case MESA_FORMAT_Z24_UNORM_X8_UINT: return pack_uint_z_S8_Z24; case MESA_FORMAT_Z_UNORM16: return pack_uint_z_Z16; @@ -2581,7 +2581,7 @@ _mesa_get_pack_ubyte_stencil_func(mesa_format format) switch (format) { case MESA_FORMAT_S8_UINT_Z24_UNORM: return pack_ubyte_stencil_Z24_S8; - case MESA_FORMAT_Z24_UNORM_X8_UINT: + case MESA_FORMAT_Z24_UNORM_S8_UINT: return pack_ubyte_stencil_S8_Z24; case MESA_FORMAT_S_UINT8: return pack_ubyte_stencil_S8; @@ -2616,8 +2616,8 @@ _mesa_pack_float_z_row(mesa_format format, GLuint n, } } break; - case MESA_FORMAT_Z24_UNORM_X8_UINT: case MESA_FORMAT_Z24_UNORM_S8_UINT: + case MESA_FORMAT_Z24_UNORM_X8_UINT: { /* don't disturb the stencil values */ GLuint *d = ((GLuint *) dst); @@ -2690,8 +2690,8 @@ _mesa_pack_uint_z_row(mesa_format format, GLuint n, } } break; - case MESA_FORMAT_Z24_UNORM_X8_UINT: case MESA_FORMAT_Z24_UNORM_S8_UINT: + case MESA_FORMAT_Z24_UNORM_X8_UINT: { /* don't disturb the stencil values */ GLuint *d = ((GLuint *) dst); @@ -2762,7 +2762,7 @@ _mesa_pack_ubyte_stencil_row(mesa_format format, GLuint n, } } break; - case MESA_FORMAT_Z24_UNORM_X8_UINT: + case MESA_FORMAT_Z24_UNORM_S8_UINT: { /* don't disturb the Z values */ GLuint *d = ((GLuint *) dst); @@ -2803,7 +2803,7 @@ _mesa_pack_uint_24_8_depth_stencil_row(mesa_format format, GLuint n, case MESA_FORMAT_S8_UINT_Z24_UNORM: memcpy(dst, src, n * sizeof(GLuint)); break; - case MESA_FORMAT_Z24_UNORM_X8_UINT: + case MESA_FORMAT_Z24_UNORM_S8_UINT: { GLuint *d = ((GLuint *) dst); GLuint i; diff --git a/mesalib/src/mesa/main/format_unpack.c b/mesalib/src/mesa/main/format_unpack.c index 02ad00a9d..276ba556a 100644 --- a/mesalib/src/mesa/main/format_unpack.c +++ b/mesalib/src/mesa/main/format_unpack.c @@ -2366,9 +2366,9 @@ get_unpack_rgba_function(mesa_format format) table[MESA_FORMAT_B10G10R10A2_UINT] = unpack_ARGB2101010_UINT; table[MESA_FORMAT_R10G10B10A2_UINT] = unpack_ABGR2101010_UINT; table[MESA_FORMAT_S8_UINT_Z24_UNORM] = unpack_Z24_S8; - table[MESA_FORMAT_Z24_UNORM_X8_UINT] = unpack_S8_Z24; + table[MESA_FORMAT_Z24_UNORM_S8_UINT] = unpack_S8_Z24; table[MESA_FORMAT_Z_UNORM16] = unpack_Z16; - table[MESA_FORMAT_Z24_UNORM_S8_UINT] = unpack_X8_Z24; + table[MESA_FORMAT_Z24_UNORM_X8_UINT] = unpack_X8_Z24; table[MESA_FORMAT_X8Z24_UNORM] = unpack_Z24_X8; table[MESA_FORMAT_Z_UNORM32] = unpack_Z32; table[MESA_FORMAT_S_UINT8] = unpack_S8; @@ -3986,8 +3986,8 @@ _mesa_unpack_float_z_row(mesa_format format, GLuint n, case MESA_FORMAT_X8Z24_UNORM: unpack = unpack_float_z_Z24_X8; break; - case MESA_FORMAT_Z24_UNORM_X8_UINT: case MESA_FORMAT_Z24_UNORM_S8_UINT: + case MESA_FORMAT_Z24_UNORM_X8_UINT: unpack = unpack_float_z_X8_Z24; break; case MESA_FORMAT_Z_UNORM16: @@ -4091,8 +4091,8 @@ _mesa_unpack_uint_z_row(mesa_format format, GLuint n, case MESA_FORMAT_X8Z24_UNORM: unpack = unpack_uint_z_Z24_X8; break; - case MESA_FORMAT_Z24_UNORM_X8_UINT: case MESA_FORMAT_Z24_UNORM_S8_UINT: + case MESA_FORMAT_Z24_UNORM_X8_UINT: unpack = unpack_uint_z_X8_Z24; break; case MESA_FORMAT_Z_UNORM16: @@ -4164,7 +4164,7 @@ _mesa_unpack_ubyte_stencil_row(mesa_format format, GLuint n, case MESA_FORMAT_S8_UINT_Z24_UNORM: unpack_ubyte_s_Z24_S8(src, dst, n); break; - case MESA_FORMAT_Z24_UNORM_X8_UINT: + case MESA_FORMAT_Z24_UNORM_S8_UINT: unpack_ubyte_s_S8_Z24(src, dst, n); break; case MESA_FORMAT_Z32_FLOAT_S8X24_UINT: @@ -4189,11 +4189,30 @@ unpack_uint_24_8_depth_stencil_S8_Z24(const GLuint *src, GLuint *dst, GLuint n) } static void +unpack_uint_24_8_depth_stencil_Z32_S8X24(const GLuint *src, + GLuint *dst, GLuint n) +{ + GLuint i; + + for (i = 0; i < n; i++) { + /* 8 bytes per pixel (float + uint32) */ + GLfloat zf = ((GLfloat *) src)[i * 2 + 0]; + GLuint z24 = (GLuint) (zf * (GLfloat) 0xffffff); + GLuint s = src[i * 2 + 1] & 0xff; + dst[i] = (z24 << 8) | s; + } +} + +static void unpack_uint_24_8_depth_stencil_Z24_S8(const GLuint *src, GLuint *dst, GLuint n) { memcpy(dst, src, n * 4); } +/** + * Unpack depth/stencil returning as GL_UNSIGNED_INT_24_8. + * \param format the source data format + */ void _mesa_unpack_uint_24_8_depth_stencil_row(mesa_format format, GLuint n, const void *src, GLuint *dst) @@ -4202,9 +4221,12 @@ _mesa_unpack_uint_24_8_depth_stencil_row(mesa_format format, GLuint n, case MESA_FORMAT_S8_UINT_Z24_UNORM: unpack_uint_24_8_depth_stencil_Z24_S8(src, dst, n); break; - case MESA_FORMAT_Z24_UNORM_X8_UINT: + case MESA_FORMAT_Z24_UNORM_S8_UINT: unpack_uint_24_8_depth_stencil_S8_Z24(src, dst, n); break; + case MESA_FORMAT_Z32_FLOAT_S8X24_UINT: + unpack_uint_24_8_depth_stencil_Z32_S8X24(src, dst, n); + break; default: _mesa_problem(NULL, "bad format %s in _mesa_unpack_uint_24_8_depth_stencil_row", diff --git a/mesalib/src/mesa/main/formats.c b/mesalib/src/mesa/main/formats.c index 10731d5a4..f6c399ede 100644 --- a/mesalib/src/mesa/main/formats.c +++ b/mesalib/src/mesa/main/formats.c @@ -439,8 +439,8 @@ static struct gl_format_info format_info[MESA_FORMAT_COUNT] = 1, 1, 4 /* BlockWidth/Height,Bytes */ }, { - MESA_FORMAT_Z24_UNORM_X8_UINT, /* Name */ - "MESA_FORMAT_Z24_UNORM_X8_UINT", /* StrName */ + MESA_FORMAT_Z24_UNORM_S8_UINT, /* Name */ + "MESA_FORMAT_Z24_UNORM_S8_UINT", /* StrName */ GL_DEPTH_STENCIL, /* BaseFormat */ GL_UNSIGNED_NORMALIZED, /* DataType */ 0, 0, 0, 0, /* Red/Green/Blue/AlphaBits */ @@ -457,8 +457,8 @@ static struct gl_format_info format_info[MESA_FORMAT_COUNT] = 1, 1, 2 /* BlockWidth/Height,Bytes */ }, { - MESA_FORMAT_Z24_UNORM_S8_UINT, /* Name */ - "MESA_FORMAT_Z24_UNORM_S8_UINT", /* StrName */ + MESA_FORMAT_Z24_UNORM_X8_UINT, /* Name */ + "MESA_FORMAT_Z24_UNORM_X8_UINT", /* StrName */ GL_DEPTH_COMPONENT, /* BaseFormat */ GL_UNSIGNED_NORMALIZED, /* DataType */ 0, 0, 0, 0, /* Red/Green/Blue/AlphaBits */ @@ -2472,7 +2472,7 @@ _mesa_format_to_type_and_comps(mesa_format format, *comps = 2; return; - case MESA_FORMAT_Z24_UNORM_X8_UINT: + case MESA_FORMAT_Z24_UNORM_S8_UINT: *datatype = GL_UNSIGNED_INT_8_24_REV_MESA; *comps = 2; return; @@ -2482,7 +2482,7 @@ _mesa_format_to_type_and_comps(mesa_format format, *comps = 1; return; - case MESA_FORMAT_Z24_UNORM_S8_UINT: + case MESA_FORMAT_Z24_UNORM_X8_UINT: *datatype = GL_UNSIGNED_INT; *comps = 1; return; @@ -3123,14 +3123,14 @@ _mesa_format_matches_format_and_type(mesa_format mesa_format, return format == GL_DEPTH_STENCIL && type == GL_UNSIGNED_INT_24_8 && !swapBytes; case MESA_FORMAT_X8Z24_UNORM: - case MESA_FORMAT_Z24_UNORM_X8_UINT: + case MESA_FORMAT_Z24_UNORM_S8_UINT: return GL_FALSE; case MESA_FORMAT_Z_UNORM16: return format == GL_DEPTH_COMPONENT && type == GL_UNSIGNED_SHORT && !swapBytes; - case MESA_FORMAT_Z24_UNORM_S8_UINT: + case MESA_FORMAT_Z24_UNORM_X8_UINT: return GL_FALSE; case MESA_FORMAT_Z_UNORM32: diff --git a/mesalib/src/mesa/main/formats.h b/mesalib/src/mesa/main/formats.h index 63d9565e3..3102584b6 100644 --- a/mesalib/src/mesa/main/formats.h +++ b/mesalib/src/mesa/main/formats.h @@ -339,33 +339,33 @@ typedef enum /* Type P formats */ /* msb <------ TEXEL BITS -----------> lsb */ /* ---- ---- ---- ---- ---- ---- ---- ---- */ - MESA_FORMAT_A8B8G8R8_UNORM, /* AAAA AAAA BBBB BBBB GGGG GGGG RRRR RRRR */ - MESA_FORMAT_R8G8B8A8_UNORM, /* RRRR RRRR GGGG GGGG BBBB BBBB AAAA AAAA */ - MESA_FORMAT_B8G8R8A8_UNORM, /* BBBB BBBB GGGG GGGG RRRR RRRR AAAA AAAA */ - MESA_FORMAT_A8R8G8B8_UNORM, /* AAAA AAAA RRRR RRRR GGGG GGGG BBBB BBBB */ - MESA_FORMAT_X8B8G8R8_UNORM, /* xxxx xxxx BBBB BBBB GGGG GGGG RRRR RRRR */ - MESA_FORMAT_R8G8B8X8_UNORM, /* RRRR RRRR GGGG GGGG BBBB BBBB xxxx xxxx */ - MESA_FORMAT_B8G8R8X8_UNORM, /* BBBB BBBB GGGG GGGG RRRR RRRR xxxx xxxx */ - MESA_FORMAT_X8R8G8B8_UNORM, /* xxxx xxxx RRRR RRRR GGGG GGGG BBBB BBBB */ + MESA_FORMAT_A8B8G8R8_UNORM, /* RRRR RRRR GGGG GGGG BBBB BBBB AAAA AAAA */ + MESA_FORMAT_R8G8B8A8_UNORM, /* AAAA AAAA BBBB BBBB GGGG GGGG RRRR RRRR */ + MESA_FORMAT_B8G8R8A8_UNORM, /* AAAA AAAA RRRR RRRR GGGG GGGG BBBB BBBB */ + MESA_FORMAT_A8R8G8B8_UNORM, /* BBBB BBBB GGGG GGGG RRRR RRRR AAAA AAAA */ + MESA_FORMAT_X8B8G8R8_UNORM, /* RRRR RRRR GGGG GGGG BBBB BBBB xxxx xxxx */ + MESA_FORMAT_R8G8B8X8_UNORM, /* xxxx xxxx BBBB BBBB GGGG GGGG RRRR RRRR */ + MESA_FORMAT_B8G8R8X8_UNORM, /* xxxx xxxx RRRR RRRR GGGG GGGG BBBB BBBB */ + MESA_FORMAT_X8R8G8B8_UNORM, /* BBBB BBBB GGGG GGGG RRRR RRRR xxxx xxxx */ /* Type A formats */ MESA_FORMAT_BGR_UNORM8, /* uchar[i * 3] = B, [i * 3 + 1] = G, [i *3 + 2] = R */ MESA_FORMAT_RGB_UNORM8, /* uchar[i * 3] = R, [i * 3 + 1] = G, [i *3 + 2] = B */ /* Type P formats */ - MESA_FORMAT_B5G6R5_UNORM, /* BBBB BGGG GGGR RRRR */ - MESA_FORMAT_R5G6B5_UNORM, /* RRRR RGGG GGGB BBBB */ - MESA_FORMAT_B4G4R4A4_UNORM, /* BBBB GGGG RRRR AAAA */ - MESA_FORMAT_A4R4G4B4_UNORM, /* AAAA RRRR GGGG BBBB */ - MESA_FORMAT_A1B5G5R5_UNORM, /* ABBB BBGG GGGR RRRR */ - MESA_FORMAT_B5G5R5A1_UNORM, /* BBBB BGGG GGRR RRRA */ - MESA_FORMAT_A1R5G5B5_UNORM, /* ARRR RRGG GGGB BBBB */ - MESA_FORMAT_L4A4_UNORM, /* LLLL AAAA */ - MESA_FORMAT_L8A8_UNORM, /* LLLL LLLL AAAA AAAA */ - MESA_FORMAT_A8L8_UNORM, /* AAAA AAAA LLLL LLLL */ - MESA_FORMAT_L16A16_UNORM, /* LLLL LLLL LLLL LLLL AAAA AAAA AAAA AAAA */ - MESA_FORMAT_A16L16_UNORM, /* AAAA AAAA AAAA AAAA LLLL LLLL LLLL LLLL */ - MESA_FORMAT_B2G3R3_UNORM, /* BBGG GRRR */ + MESA_FORMAT_B5G6R5_UNORM, /* RRRR RGGG GGGB BBBB */ + MESA_FORMAT_R5G6B5_UNORM, /* BBBB BGGG GGGR RRRR */ + MESA_FORMAT_B4G4R4A4_UNORM, /* AAAA RRRR GGGG BBBB */ + MESA_FORMAT_A4R4G4B4_UNORM, /* BBBB GGGG RRRR AAAA */ + MESA_FORMAT_A1B5G5R5_UNORM, /* RRRR RGGG GGBB BBBA */ + MESA_FORMAT_B5G5R5A1_UNORM, /* ARRR RRGG GGGB BBBB */ + MESA_FORMAT_A1R5G5B5_UNORM, /* BBBB BGGG GGRR RRRA */ + MESA_FORMAT_L4A4_UNORM, /* AAAA LLLL */ + MESA_FORMAT_L8A8_UNORM, /* AAAA AAAA LLLL LLLL */ + MESA_FORMAT_A8L8_UNORM, /* LLLL LLLL AAAA AAAA */ + MESA_FORMAT_L16A16_UNORM, /* AAAA AAAA AAAA AAAA LLLL LLLL LLLL LLLL */ + MESA_FORMAT_A16L16_UNORM, /* LLLL LLLL LLLL LLLL AAAA AAAA AAAA AAAA */ + MESA_FORMAT_B2G3R3_UNORM, /* RRRG GGBB */ /* Type A formats */ MESA_FORMAT_A_UNORM8, /* uchar[i] = A */ @@ -383,25 +383,25 @@ typedef enum MESA_FORMAT_R_UNORM8, /* uchar[i] = R */ /* Type P formats */ - MESA_FORMAT_R8G8_UNORM, /* RRRR RRRR GGGG GGGG */ - MESA_FORMAT_G8R8_UNORM, /* GGGG GGGG RRRR RRRR */ + MESA_FORMAT_R8G8_UNORM, /* GGGG GGGG RRRR RRRR */ + MESA_FORMAT_G8R8_UNORM, /* RRRR RRRR GGGG GGGG */ /* Type A format(s) */ MESA_FORMAT_R_UNORM16, /* ushort[i] = R */ /* Type P formats */ - MESA_FORMAT_R16G16_UNORM, /* RRRR RRRR RRRR RRRR GGGG GGGG GGGG GGGG */ - MESA_FORMAT_G16R16_UNORM, /* GGGG GGGG GGGG GGGG RRRR RRRR RRRR RRRR */ - MESA_FORMAT_B10G10R10A2_UNORM,/* BBBB BBBB BBGG GGGG GGGG RRRR RRRR RRAA */ - MESA_FORMAT_S8_UINT_Z24_UNORM,/* SSSS SSSS ZZZZ ZZZZ ZZZZ ZZZZ ZZZZ ZZZZ */ - MESA_FORMAT_Z24_UNORM_X8_UINT,/* ZZZZ ZZZZ ZZZZ ZZZZ ZZZZ ZZZZ xxxx xxxx */ + MESA_FORMAT_R16G16_UNORM, /* GGGG GGGG GGGG GGGG RRRR RRRR RRRR RRRR */ + MESA_FORMAT_G16R16_UNORM, /* RRRR RRRR RRRR RRRR GGGG GGGG GGGG GGGG */ + MESA_FORMAT_B10G10R10A2_UNORM,/* AARR RRRR RRRR GGGG GGGG GGBB BBBB BBBB */ + MESA_FORMAT_S8_UINT_Z24_UNORM,/* ZZZZ ZZZZ ZZZZ ZZZZ ZZZZ ZZZZ SSSS SSSS */ + MESA_FORMAT_Z24_UNORM_S8_UINT,/* SSSS SSSS ZZZZ ZZZZ ZZZZ ZZZZ ZZZZ ZZZZ */ /* Type A format(s) */ MESA_FORMAT_Z_UNORM16, /* ushort[i] = Z */ /* Type P formats */ - MESA_FORMAT_Z24_UNORM_S8_UINT,/* ZZZZ ZZZZ ZZZZ ZZZZ ZZZZ ZZZZ SSSS SSSS */ - MESA_FORMAT_X8Z24_UNORM, /* xxxx xxxx ZZZZ ZZZZ ZZZZ ZZZZ ZZZZ ZZZZ */ + MESA_FORMAT_Z24_UNORM_X8_UINT,/* xxxx xxxx ZZZZ ZZZZ ZZZZ ZZZZ ZZZZ ZZZZ */ + MESA_FORMAT_X8Z24_UNORM, /* ZZZZ ZZZZ ZZZZ ZZZZ ZZZZ ZZZZ xxxx xxxx */ /* Type A formats */ MESA_FORMAT_Z_UNORM32, /* uint[i] = Z */ @@ -416,14 +416,14 @@ typedef enum MESA_FORMAT_BGR_SRGB8, /* uchar[i * 3] = B, [i * 3 + 1] = G, [i *3 + 2] = R */ /* Type P formats */ - MESA_FORMAT_A8B8G8R8_SRGB, /* AAAA AAAA BBBB BBBB GGGG GGGG RRRR RRRR*/ - MESA_FORMAT_B8G8R8A8_SRGB, /* BBBB BBBB GGGG GGGG RRRR RRRR AAAA AAAA */ + MESA_FORMAT_A8B8G8R8_SRGB, /* RRRR RRRR GGGG GGGG BBBB BBBB AAAA AAAA */ + MESA_FORMAT_B8G8R8A8_SRGB, /* AAAA AAAA RRRR RRRR GGGG GGGG BBBB BBBB */ /* Type A format(s) */ MESA_FORMAT_L_SRGB8, /* uchar[i] = L */ /* Type P formats */ - MESA_FORMAT_L8A8_SRGB, /* LLLL LLLL AAAA AAAA */ + MESA_FORMAT_L8A8_SRGB, /* AAAA AAAA LLLL LLLL */ /* Type C formats */ MESA_FORMAT_SRGB_DXT1, @@ -548,16 +548,16 @@ typedef enum MESA_FORMAT_R_SNORM8, /* char[i] = R */ /* Type P formats */ - MESA_FORMAT_R8G8_SNORM, /* RRRR RRRR GGGG GGGG */ - MESA_FORMAT_X8B8G8R8_SNORM, /* xxxx xxxx BBBB BBBB GGGG GGGG RRRR RRRR */ - MESA_FORMAT_A8B8G8R8_SNORM, /* AAAA AAAA BBBB BBBB GGGG GGGG RRRR RRRR */ - MESA_FORMAT_R8G8B8A8_SNORM, /* RRRR RRRR GGGG GGGG BBBB BBBB AAAA AAAA */ + MESA_FORMAT_R8G8_SNORM, /* GGGG GGGG RRRR RRRR */ + MESA_FORMAT_X8B8G8R8_SNORM, /* RRRR RRRR GGGG GGGG BBBB BBBB xxxx xxxx */ + MESA_FORMAT_A8B8G8R8_SNORM, /* RRRR RRRR GGGG GGGG BBBB BBBB AAAA AAAA */ + MESA_FORMAT_R8G8B8A8_SNORM, /* AAAA AAAA BBBB BBBB GGGG GGGG RRRR RRRR */ /* Type A format(s) */ MESA_FORMAT_R_SNORM16, /* short[i] = R */ /* Type P format(s) */ - MESA_FORMAT_R16G16_SNORM, /* RRRR RRRR RRRR RRRR GGGG GGGG GGGG GGGG */ + MESA_FORMAT_R16G16_SNORM, /* GGGG GGGG GGGG GGGG RRRR RRRR RRRR RRRR */ /* Type A format(s) */ MESA_FORMAT_RGB_SNORM16, /* short[i * 3] = R, [i * 3 + 1] = G, [i *3 + 2] = B */ @@ -597,7 +597,7 @@ typedef enum MESA_FORMAT_L_SNORM8, /* char[i] = L */ /* Type P format(s) */ - MESA_FORMAT_L8A8_SNORM, /* LLLL LLLL AAAA AAAA */ + MESA_FORMAT_L8A8_SNORM, /* AAAA AAAA LLLL LLLL */ /* Type A format(s) */ MESA_FORMAT_I_SNORM8, /* char[i] = I */ @@ -608,21 +608,21 @@ typedef enum /* Type P format(s) */ MESA_FORMAT_R9G9B9E5_FLOAT, - MESA_FORMAT_R11G11B10_FLOAT, + MESA_FORMAT_R11G11B10_FLOAT, /* BBBB BBBB BBGG GGGG GGGG GRRR RRRR RRRR */ /* Type A format(s) */ MESA_FORMAT_Z_FLOAT32, /* Type P formats */ - MESA_FORMAT_Z32_FLOAT_S8X24_UINT, + MESA_FORMAT_Z32_FLOAT_S8X24_UINT, /* (float, x24s8) */ - MESA_FORMAT_B10G10R10A2_UINT, - MESA_FORMAT_R10G10B10A2_UINT, + MESA_FORMAT_B10G10R10A2_UINT, /* AARR RRRR RRRR GGGG GGGG GGBB BBBB BBBB */ + MESA_FORMAT_R10G10B10A2_UINT, /* AABB BBBB BBBB GGGG GGGG GGRR RRRR RRRR */ - MESA_FORMAT_B4G4R4X4_UNORM, /* BBBB GGGG RRRR xxxx */ - MESA_FORMAT_B5G5R5X1_UNORM, /* BBBB BGGG GGRR RRRx */ - MESA_FORMAT_R8G8B8X8_SNORM, /* RRRR RRRR GGGG GGGG BBBB BBBB xxxx xxxx */ - MESA_FORMAT_R8G8B8X8_SRGB, /* RRRR RRRR GGGG GGGG BBBB BBBB xxxx xxxx */ + MESA_FORMAT_B4G4R4X4_UNORM, /* xxxx RRRR GGGG BBBB */ + MESA_FORMAT_B5G5R5X1_UNORM, /* xRRR RRGG GGGB BBBB */ + MESA_FORMAT_R8G8B8X8_SNORM, /* xxxx xxxx BBBB BBBB GGGG GGGG RRRR RRRR */ + MESA_FORMAT_R8G8B8X8_SRGB, /* xxxx xxxx BBBB BBBB GGGG GGGG RRRR RRRR */ /* Type A formats */ MESA_FORMAT_RGBX_UINT8, /* uchar[i * 4] = R, [i * 4 + 1] = G, [i * 4 + 2] = B, [i * 4 + 3] = x */ @@ -643,9 +643,9 @@ typedef enum MESA_FORMAT_RGBX_SINT32, /* ... */ /* Type P formats */ - MESA_FORMAT_R10G10B10A2_UNORM, - MESA_FORMAT_G8R8_SNORM, - MESA_FORMAT_G16R16_SNORM, + MESA_FORMAT_R10G10B10A2_UNORM, /* AABB BBBB BBBB GGGG GGGG GGRR RRRR RRRR */ + MESA_FORMAT_G8R8_SNORM, /* RRRR RRRR GGGG GGGG */ + MESA_FORMAT_G16R16_SNORM, /* RRRR RRRR RRRR RRRR GGGG GGGG GGGG GGGG */ MESA_FORMAT_COUNT } mesa_format; diff --git a/mesalib/src/mesa/main/framebuffer.c b/mesalib/src/mesa/main/framebuffer.c index 54eeda2b2..7416bb118 100644 --- a/mesalib/src/mesa/main/framebuffer.c +++ b/mesalib/src/mesa/main/framebuffer.c @@ -130,7 +130,7 @@ _mesa_initialize_window_framebuffer(struct gl_framebuffer *fb, memset(fb, 0, sizeof(struct gl_framebuffer)); - _glthread_INIT_MUTEX(fb->Mutex); + mtx_init(&fb->Mutex, mtx_plain); fb->RefCount = 1; @@ -182,7 +182,7 @@ _mesa_initialize_user_framebuffer(struct gl_framebuffer *fb, GLuint name) fb->ColorReadBuffer = GL_COLOR_ATTACHMENT0_EXT; fb->_ColorReadBufferIndex = BUFFER_COLOR0; fb->Delete = _mesa_destroy_framebuffer; - _glthread_INIT_MUTEX(fb->Mutex); + mtx_init(&fb->Mutex, mtx_plain); } @@ -213,7 +213,7 @@ _mesa_free_framebuffer_data(struct gl_framebuffer *fb) assert(fb); assert(fb->RefCount == 0); - _glthread_DESTROY_MUTEX(fb->Mutex); + mtx_destroy(&fb->Mutex); for (i = 0; i < BUFFER_COUNT; i++) { struct gl_renderbuffer_attachment *att = &fb->Attachment[i]; @@ -244,11 +244,11 @@ _mesa_reference_framebuffer_(struct gl_framebuffer **ptr, GLboolean deleteFlag = GL_FALSE; struct gl_framebuffer *oldFb = *ptr; - _glthread_LOCK_MUTEX(oldFb->Mutex); + mtx_lock(&oldFb->Mutex); ASSERT(oldFb->RefCount > 0); oldFb->RefCount--; deleteFlag = (oldFb->RefCount == 0); - _glthread_UNLOCK_MUTEX(oldFb->Mutex); + mtx_unlock(&oldFb->Mutex); if (deleteFlag) oldFb->Delete(oldFb); @@ -258,9 +258,9 @@ _mesa_reference_framebuffer_(struct gl_framebuffer **ptr, assert(!*ptr); if (fb) { - _glthread_LOCK_MUTEX(fb->Mutex); + mtx_lock(&fb->Mutex); fb->RefCount++; - _glthread_UNLOCK_MUTEX(fb->Mutex); + mtx_unlock(&fb->Mutex); *ptr = fb; } } diff --git a/mesalib/src/mesa/main/get.c b/mesalib/src/mesa/main/get.c index 54f7d7745..b1908515c 100644 --- a/mesalib/src/mesa/main/get.c +++ b/mesalib/src/mesa/main/get.c @@ -28,6 +28,7 @@ #include "blend.h" #include "enable.h" #include "enums.h" +#include "errors.h" #include "extensions.h" #include "get.h" #include "macros.h" @@ -973,6 +974,26 @@ find_custom_value(struct gl_context *ctx, const struct value_desc *d, union valu _mesa_problem(ctx, "driver doesn't implement GetTimestamp"); } break; + /* GL_KHR_DEBUG */ + case GL_DEBUG_LOGGED_MESSAGES: + { + struct gl_debug_state *debug = _mesa_get_debug_state(ctx); + v->value_int = debug ? debug->NumMessages : 0; + } + break; + case GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH: + { + struct gl_debug_state *debug = _mesa_get_debug_state(ctx); + v->value_int = debug ? debug->NextMsgLength : 0; + } + break; + case GL_DEBUG_GROUP_STACK_DEPTH: + { + struct gl_debug_state *debug = _mesa_get_debug_state(ctx); + v->value_int = debug ? debug->GroupStackDepth : 0; + } + break; + /* GL_ARB_shader_atomic_counters */ case GL_ATOMIC_COUNTER_BUFFER_BINDING: v->value_int = ctx->AtomicBuffer->Name; diff --git a/mesalib/src/mesa/main/get_hash_params.py b/mesalib/src/mesa/main/get_hash_params.py index f47cbd881..674d0032a 100644 --- a/mesalib/src/mesa/main/get_hash_params.py +++ b/mesalib/src/mesa/main/get_hash_params.py @@ -698,13 +698,13 @@ descriptor=[ [ "RESET_NOTIFICATION_STRATEGY_ARB", "CONTEXT_ENUM(Const.ResetStrategy), NO_EXTRA" ], # GL_KHR_debug (GL 4.3)/ GL_ARB_debug_output - [ "DEBUG_LOGGED_MESSAGES", "CONTEXT_INT(Debug.NumMessages), NO_EXTRA" ], - [ "DEBUG_NEXT_LOGGED_MESSAGE_LENGTH", "CONTEXT_INT(Debug.NextMsgLength), NO_EXTRA" ], + [ "DEBUG_LOGGED_MESSAGES", "LOC_CUSTOM, TYPE_INT, 0, NO_EXTRA" ], + [ "DEBUG_NEXT_LOGGED_MESSAGE_LENGTH", "LOC_CUSTOM, TYPE_INT, 0, NO_EXTRA" ], [ "MAX_DEBUG_LOGGED_MESSAGES", "CONST(MAX_DEBUG_LOGGED_MESSAGES), NO_EXTRA" ], [ "MAX_DEBUG_MESSAGE_LENGTH", "CONST(MAX_DEBUG_MESSAGE_LENGTH), NO_EXTRA" ], [ "MAX_LABEL_LENGTH", "CONST(MAX_LABEL_LENGTH), NO_EXTRA" ], [ "MAX_DEBUG_GROUP_STACK_DEPTH", "CONST(MAX_DEBUG_GROUP_STACK_DEPTH), NO_EXTRA" ], - [ "DEBUG_GROUP_STACK_DEPTH", "CONTEXT_INT(Debug.GroupStackDepth), NO_EXTRA" ], + [ "DEBUG_GROUP_STACK_DEPTH", "LOC_CUSTOM, TYPE_INT, 0, NO_EXTRA" ], [ "MAX_DUAL_SOURCE_DRAW_BUFFERS", "CONTEXT_INT(Const.MaxDualSourceDrawBuffers), extra_ARB_blend_func_extended" ], diff --git a/mesalib/src/mesa/main/getstring.c b/mesalib/src/mesa/main/getstring.c index 674126702..3ac62d402 100644 --- a/mesalib/src/mesa/main/getstring.c +++ b/mesalib/src/mesa/main/getstring.c @@ -253,14 +253,22 @@ _mesa_GetPointerv( GLenum pname, GLvoid **params ) *params = (GLvoid *) ctx->Array.VAO->VertexAttrib[VERT_ATTRIB_POINT_SIZE].Ptr; break; case GL_DEBUG_CALLBACK_FUNCTION_ARB: - if (!_mesa_is_desktop_gl(ctx)) + if (!_mesa_is_desktop_gl(ctx)) { goto invalid_pname; - *params = (GLvoid *) ctx->Debug.Callback; + } + else { + struct gl_debug_state *debug = _mesa_get_debug_state(ctx); + *params = debug ? (void *) debug->Callback : NULL; + } break; case GL_DEBUG_CALLBACK_USER_PARAM_ARB: - if (!_mesa_is_desktop_gl(ctx)) + if (!_mesa_is_desktop_gl(ctx)) { goto invalid_pname; - *params = (GLvoid *) ctx->Debug.CallbackData; + } + else { + struct gl_debug_state *debug = _mesa_get_debug_state(ctx); + *params = debug ? (void *) debug->CallbackData : NULL; + } break; default: goto invalid_pname; @@ -326,7 +334,7 @@ _mesa_GetGraphicsResetStatusARB( void ) */ status = ctx->Driver.GetGraphicsResetStatus(ctx); - _glthread_LOCK_MUTEX(ctx->Shared->Mutex); + mtx_lock(&ctx->Shared->Mutex); /* If this context has not been affected by a GPU reset, check to see if * some other context in the share group has been affected by a reset. @@ -340,7 +348,7 @@ _mesa_GetGraphicsResetStatusARB( void ) } ctx->ShareGroupReset = ctx->Shared->ShareGroupReset; - _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); + mtx_unlock(&ctx->Shared->Mutex); } if (!ctx->Driver.GetGraphicsResetStatus && (MESA_VERBOSE & VERBOSE_API)) diff --git a/mesalib/src/mesa/main/glformats.c b/mesalib/src/mesa/main/glformats.c index 7d4a31057..77cf26337 100644 --- a/mesalib/src/mesa/main/glformats.c +++ b/mesalib/src/mesa/main/glformats.c @@ -1323,10 +1323,8 @@ _mesa_error_check_format_and_type(const struct gl_context *ctx, case GL_INT: case GL_UNSIGNED_INT: case GL_FLOAT: - return GL_NO_ERROR; case GL_HALF_FLOAT: - return ctx->Extensions.ARB_half_float_pixel - ? GL_NO_ERROR : GL_INVALID_ENUM; + return GL_NO_ERROR; default: return GL_INVALID_ENUM; } @@ -1349,10 +1347,8 @@ _mesa_error_check_format_and_type(const struct gl_context *ctx, case GL_INT: case GL_UNSIGNED_INT: case GL_FLOAT: - return GL_NO_ERROR; case GL_HALF_FLOAT: - return ctx->Extensions.ARB_half_float_pixel - ? GL_NO_ERROR : GL_INVALID_ENUM; + return GL_NO_ERROR; default: return GL_INVALID_ENUM; } @@ -1368,10 +1364,8 @@ _mesa_error_check_format_and_type(const struct gl_context *ctx, case GL_INT: case GL_UNSIGNED_INT: case GL_FLOAT: - return GL_NO_ERROR; case GL_HALF_FLOAT: - return ctx->Extensions.ARB_half_float_pixel - ? GL_NO_ERROR : GL_INVALID_ENUM; + return GL_NO_ERROR; default: return GL_INVALID_ENUM; } @@ -1389,14 +1383,12 @@ _mesa_error_check_format_and_type(const struct gl_context *ctx, case GL_UNSIGNED_BYTE_2_3_3_REV: case GL_UNSIGNED_SHORT_5_6_5: case GL_UNSIGNED_SHORT_5_6_5_REV: + case GL_HALF_FLOAT: return GL_NO_ERROR; case GL_UNSIGNED_INT_2_10_10_10_REV: /* OK by GL_EXT_texture_type_2_10_10_10_REV */ return (ctx->API == API_OPENGLES2) ? GL_NO_ERROR : GL_INVALID_ENUM; - case GL_HALF_FLOAT: - return ctx->Extensions.ARB_half_float_pixel - ? GL_NO_ERROR : GL_INVALID_ENUM; case GL_UNSIGNED_INT_5_9_9_9_REV: return ctx->Extensions.EXT_texture_shared_exponent ? GL_NO_ERROR : GL_INVALID_ENUM; @@ -1419,10 +1411,8 @@ _mesa_error_check_format_and_type(const struct gl_context *ctx, case GL_INT: case GL_UNSIGNED_INT: case GL_FLOAT: - return GL_NO_ERROR; case GL_HALF_FLOAT: - return ctx->Extensions.ARB_half_float_pixel - ? GL_NO_ERROR : GL_INVALID_ENUM; + return GL_NO_ERROR; default: return GL_INVALID_ENUM; } @@ -1446,10 +1436,8 @@ _mesa_error_check_format_and_type(const struct gl_context *ctx, case GL_UNSIGNED_INT_8_8_8_8_REV: case GL_UNSIGNED_INT_10_10_10_2: case GL_UNSIGNED_INT_2_10_10_10_REV: - return GL_NO_ERROR; case GL_HALF_FLOAT: - return ctx->Extensions.ARB_half_float_pixel - ? GL_NO_ERROR : GL_INVALID_ENUM; + return GL_NO_ERROR; default: return GL_INVALID_ENUM; } diff --git a/mesalib/src/mesa/main/hash.c b/mesalib/src/mesa/main/hash.c index b31fd4839..4c92005e0 100644 --- a/mesalib/src/mesa/main/hash.c +++ b/mesalib/src/mesa/main/hash.c @@ -36,7 +36,6 @@ #include "glheader.h" #include "imports.h" -#include "glapi/glthread.h" #include "hash.h" #include "hash_table.h" @@ -59,8 +58,8 @@ struct _mesa_HashTable { struct hash_table *ht; GLuint MaxKey; /**< highest key inserted so far */ - _glthread_Mutex Mutex; /**< mutual exclusion lock */ - _glthread_Mutex WalkMutex; /**< for _mesa_HashWalk() */ + mtx_t Mutex; /**< mutual exclusion lock */ + mtx_t WalkMutex; /**< for _mesa_HashWalk() */ GLboolean InDeleteAll; /**< Debug check */ /** Value that would be in the table for DELETED_KEY_VALUE. */ void *deleted_key_data; @@ -117,8 +116,8 @@ _mesa_NewHashTable(void) if (table) { table->ht = _mesa_hash_table_create(NULL, uint_key_compare); _mesa_hash_table_set_deleted_key(table->ht, uint_key(DELETED_KEY_VALUE)); - _glthread_INIT_MUTEX(table->Mutex); - _glthread_INIT_MUTEX(table->WalkMutex); + mtx_init(&table->Mutex, mtx_plain); + mtx_init(&table->WalkMutex, mtx_plain); } return table; } @@ -144,8 +143,8 @@ _mesa_DeleteHashTable(struct _mesa_HashTable *table) _mesa_hash_table_destroy(table->ht, NULL); - _glthread_DESTROY_MUTEX(table->Mutex); - _glthread_DESTROY_MUTEX(table->WalkMutex); + mtx_destroy(&table->Mutex); + mtx_destroy(&table->WalkMutex); free(table); } @@ -187,9 +186,9 @@ _mesa_HashLookup(struct _mesa_HashTable *table, GLuint key) { void *res; assert(table); - _glthread_LOCK_MUTEX(table->Mutex); + mtx_lock(&table->Mutex); res = _mesa_HashLookup_unlocked(table, key); - _glthread_UNLOCK_MUTEX(table->Mutex); + mtx_unlock(&table->Mutex); return res; } @@ -211,7 +210,7 @@ _mesa_HashInsert(struct _mesa_HashTable *table, GLuint key, void *data) assert(table); assert(key); - _glthread_LOCK_MUTEX(table->Mutex); + mtx_lock(&table->Mutex); if (key > table->MaxKey) table->MaxKey = key; @@ -227,7 +226,7 @@ _mesa_HashInsert(struct _mesa_HashTable *table, GLuint key, void *data) } } - _glthread_UNLOCK_MUTEX(table->Mutex); + mtx_unlock(&table->Mutex); } @@ -256,14 +255,14 @@ _mesa_HashRemove(struct _mesa_HashTable *table, GLuint key) return; } - _glthread_LOCK_MUTEX(table->Mutex); + mtx_lock(&table->Mutex); if (key == DELETED_KEY_VALUE) { table->deleted_key_data = NULL; } else { entry = _mesa_hash_table_search(table->ht, uint_hash(key), uint_key(key)); _mesa_hash_table_remove(table->ht, entry); } - _glthread_UNLOCK_MUTEX(table->Mutex); + mtx_unlock(&table->Mutex); } @@ -286,7 +285,7 @@ _mesa_HashDeleteAll(struct _mesa_HashTable *table, ASSERT(table); ASSERT(callback); - _glthread_LOCK_MUTEX(table->Mutex); + mtx_lock(&table->Mutex); table->InDeleteAll = GL_TRUE; hash_table_foreach(table->ht, entry) { callback((uintptr_t)entry->key, entry->data, userData); @@ -297,7 +296,7 @@ _mesa_HashDeleteAll(struct _mesa_HashTable *table, table->deleted_key_data = NULL; } table->InDeleteAll = GL_FALSE; - _glthread_UNLOCK_MUTEX(table->Mutex); + mtx_unlock(&table->Mutex); } @@ -315,7 +314,7 @@ _mesa_HashClone(const struct _mesa_HashTable *table) struct _mesa_HashTable *clonetable; ASSERT(table); - _glthread_LOCK_MUTEX(table2->Mutex); + mtx_lock(&table2->Mutex); clonetable = _mesa_NewHashTable(); assert(clonetable); @@ -323,7 +322,7 @@ _mesa_HashClone(const struct _mesa_HashTable *table) _mesa_HashInsert(clonetable, (GLint)(uintptr_t)entry->key, entry->data); } - _glthread_UNLOCK_MUTEX(table2->Mutex); + mtx_unlock(&table2->Mutex); return clonetable; } @@ -352,13 +351,13 @@ _mesa_HashWalk(const struct _mesa_HashTable *table, ASSERT(table); ASSERT(callback); - _glthread_LOCK_MUTEX(table2->WalkMutex); + mtx_lock(&table2->WalkMutex); hash_table_foreach(table->ht, entry) { callback((uintptr_t)entry->key, entry->data, userData); } if (table->deleted_key_data) callback(DELETED_KEY_VALUE, table->deleted_key_data, userData); - _glthread_UNLOCK_MUTEX(table2->WalkMutex); + mtx_unlock(&table2->WalkMutex); } static void @@ -398,10 +397,10 @@ GLuint _mesa_HashFindFreeKeyBlock(struct _mesa_HashTable *table, GLuint numKeys) { const GLuint maxKey = ~((GLuint) 0) - 1; - _glthread_LOCK_MUTEX(table->Mutex); + mtx_lock(&table->Mutex); if (maxKey - numKeys > table->MaxKey) { /* the quick solution */ - _glthread_UNLOCK_MUTEX(table->Mutex); + mtx_unlock(&table->Mutex); return table->MaxKey + 1; } else { @@ -419,13 +418,13 @@ _mesa_HashFindFreeKeyBlock(struct _mesa_HashTable *table, GLuint numKeys) /* this key not in use, check if we've found enough */ freeCount++; if (freeCount == numKeys) { - _glthread_UNLOCK_MUTEX(table->Mutex); + mtx_unlock(&table->Mutex); return freeStart; } } } /* cannot allocate a block of numKeys consecutive keys */ - _glthread_UNLOCK_MUTEX(table->Mutex); + mtx_unlock(&table->Mutex); return 0; } } diff --git a/mesalib/src/mesa/main/imports.h b/mesalib/src/mesa/main/imports.h index d79e2a339..9e221cccb 100644 --- a/mesalib/src/mesa/main/imports.h +++ b/mesalib/src/mesa/main/imports.h @@ -132,7 +132,7 @@ typedef union { GLfloat f; GLint i; GLuint u; } fi_type; #define atanhf(f) ((float) atanh(f)) #endif -#if defined(_MSC_VER) +#if defined(_MSC_VER) && (_MSC_VER < 1800) /* Not req'd on VS2013 and above */ static inline float truncf(float x) { return x < 0.0f ? ceilf(x) : floorf(x); } static inline float exp2f(float x) { return powf(2.0f, x); } static inline float log2f(float x) { return logf(x) * 1.442695041f; } diff --git a/mesalib/src/mesa/main/mtypes.h b/mesalib/src/mesa/main/mtypes.h index ceabd9df7..bbc377280 100644 --- a/mesalib/src/mesa/main/mtypes.h +++ b/mesalib/src/mesa/main/mtypes.h @@ -1190,7 +1190,7 @@ struct gl_sampler_object */ struct gl_texture_object { - _glthread_Mutex Mutex; /**< for thread safety */ + mtx_t Mutex; /**< for thread safety */ GLint RefCount; /**< reference count */ GLuint Name; /**< the user-visible texture object ID */ GLchar *Label; /**< GL_KHR_debug */ @@ -1439,28 +1439,44 @@ struct gl_viewport_attrib }; +typedef enum { + MAP_USER, + MAP_INTERNAL, + + MAP_COUNT +} gl_map_buffer_index; + + +/** + * Fields describing a mapped buffer range. + */ +struct gl_buffer_mapping { + GLbitfield AccessFlags; /**< Mask of GL_MAP_x_BIT flags */ + GLvoid *Pointer; /**< User-space address of mapping */ + GLintptr Offset; /**< Mapped offset */ + GLsizeiptr Length; /**< Mapped length */ +}; + + /** * GL_ARB_vertex/pixel_buffer_object buffer object */ struct gl_buffer_object { - _glthread_Mutex Mutex; + mtx_t Mutex; GLint RefCount; GLuint Name; GLchar *Label; /**< GL_KHR_debug */ GLenum Usage; /**< GL_STREAM_DRAW_ARB, GL_STREAM_READ_ARB, etc. */ + GLbitfield StorageFlags; /**< GL_MAP_PERSISTENT_BIT, etc. */ GLsizeiptrARB Size; /**< Size of buffer storage in bytes */ GLubyte *Data; /**< Location of storage either in RAM or VRAM. */ - /** Fields describing a mapped buffer */ - /*@{*/ - GLbitfield AccessFlags; /**< Mask of GL_MAP_x_BIT flags */ - GLvoid *Pointer; /**< User-space address of mapping */ - GLintptr Offset; /**< Mapped offset */ - GLsizeiptr Length; /**< Mapped length */ - /*@}*/ GLboolean DeletePending; /**< true if buffer object is removed from the hash */ GLboolean Written; /**< Ever written to? (for debugging) */ GLboolean Purgeable; /**< Is the buffer purgeable under memory pressure? */ + GLboolean Immutable; /**< GL_ARB_buffer_storage */ + + struct gl_buffer_mapping Mappings[MAP_COUNT]; }; @@ -1560,7 +1576,7 @@ struct gl_vertex_array_object GLchar *Label; /**< GL_KHR_debug */ GLint RefCount; - _glthread_Mutex Mutex; + mtx_t Mutex; /** * Does the VAO use ARB semantics or Apple semantics? @@ -2013,6 +2029,7 @@ typedef enum SYSTEM_VALUE_SAMPLE_ID, /**< Fragment shader only */ SYSTEM_VALUE_SAMPLE_POS, /**< Fragment shader only */ SYSTEM_VALUE_SAMPLE_MASK_IN, /**< Fragment shader only */ + SYSTEM_VALUE_INVOCATION_ID, /**< Geometry shader only */ SYSTEM_VALUE_MAX /**< Number of values */ } gl_system_value; @@ -2143,6 +2160,7 @@ struct gl_geometry_program GLint VerticesIn; GLint VerticesOut; + GLint Invocations; GLenum InputType; /**< GL_POINTS, GL_LINES, GL_LINES_ADJACENCY_ARB, GL_TRIANGLES, or GL_TRIANGLES_ADJACENCY_ARB */ GLenum OutputType; /**< GL_POINTS, GL_LINE_STRIP or GL_TRIANGLE_STRIP */ @@ -2419,6 +2437,11 @@ struct gl_shader struct { GLint VerticesOut; /** + * 0 - Invocations count not declared in shader, or + * 1 .. MAX_GEOMETRY_SHADER_INVOCATIONS + */ + GLint Invocations; + /** * GL_POINTS, GL_LINES, GL_LINES_ADJACENCY, GL_TRIANGLES, or * GL_TRIANGLES_ADJACENCY, or PRIM_UNKNOWN if it's not set in this * shader. @@ -2579,6 +2602,12 @@ struct gl_shader_program */ GLboolean InternalSeparateShader; + /** + * Indicates whether program can be bound for individual pipeline stages + * using UseProgramStages after it is next linked. + */ + GLboolean SeparateShader; + GLuint NumShaders; /**< number of attached shaders */ struct gl_shader **Shaders; /**< List of attached the shaders */ @@ -2627,6 +2656,10 @@ struct gl_shader_program struct { GLint VerticesIn; GLint VerticesOut; + /** + * 1 .. MAX_GEOMETRY_SHADER_INVOCATIONS + */ + GLint Invocations; GLenum InputType; /**< GL_POINTS, GL_LINES, GL_LINES_ADJACENCY_ARB, GL_TRIANGLES, or GL_TRIANGLES_ADJACENCY_ARB */ GLenum OutputType; /**< GL_POINTS, GL_LINE_STRIP or GL_TRIANGLE_STRIP */ @@ -2746,9 +2779,19 @@ struct gl_shader_program /** * Context state for GLSL vertex/fragment shaders. + * Extended to support pipeline object */ -struct gl_shader_state +struct gl_pipeline_object { + /** Name of the pipeline object as received from glGenProgramPipelines. + * It would be 0 for shaders without separate shader objects. + */ + GLuint Name; + + GLint RefCount; + + mtx_t Mutex; + /** * Programs used for rendering * @@ -2768,8 +2811,21 @@ struct gl_shader_state struct gl_shader_program *ActiveProgram; GLbitfield Flags; /**< Mask of GLSL_x flags */ + + GLboolean EverBound; /**< Has the pipeline object been created */ }; +/** + * Context state for GLSL pipeline shaders. + */ +struct gl_pipeline_shader_state +{ + /** Currently bound pipeline object. See _mesa_BindProgramPipeline() */ + struct gl_pipeline_object *Current; + + /** Pipeline objects */ + struct _mesa_HashTable *Objects; +}; /** * Compiler options for a single GLSL shaders type @@ -2871,7 +2927,7 @@ struct gl_sync_object */ struct gl_shared_state { - _glthread_Mutex Mutex; /**< for thread safety */ + mtx_t Mutex; /**< for thread safety */ GLint RefCount; /**< Reference count */ struct _mesa_HashTable *DisplayList; /**< Display lists hash table */ struct _mesa_HashTable *TexObjects; /**< Texture objects hash table */ @@ -2889,7 +2945,7 @@ struct gl_shared_state * \todo Improve the granularity of locking. */ /*@{*/ - _glthread_Mutex TexMutex; /**< texobj thread safety */ + mtx_t TexMutex; /**< texobj thread safety */ GLuint TextureStateStamp; /**< state notification for shared tex */ /*@}*/ @@ -2946,7 +3002,7 @@ struct gl_shared_state */ struct gl_renderbuffer { - _glthread_Mutex Mutex; /**< for thread safety */ + mtx_t Mutex; /**< for thread safety */ GLuint ClassID; /**< Useful for drivers */ GLuint Name; GLchar *Label; /**< GL_KHR_debug */ @@ -3024,7 +3080,7 @@ struct gl_renderbuffer_attachment */ struct gl_framebuffer { - _glthread_Mutex Mutex; /**< for thread safety */ + mtx_t Mutex; /**< for thread safety */ /** * If zero, this is a window system framebuffer. If non-zero, this * is a FBO framebuffer; note that for some devices (i.e. those with @@ -3433,6 +3489,7 @@ struct gl_extensions GLboolean ARB_arrays_of_arrays; GLboolean ARB_base_instance; GLboolean ARB_blend_func_extended; + GLboolean ARB_buffer_storage; GLboolean ARB_color_buffer_float; GLboolean ARB_compute_shader; GLboolean ARB_conservative_depth; @@ -3451,7 +3508,6 @@ struct gl_extensions GLboolean ARB_explicit_attrib_location; GLboolean ARB_geometry_shader4; GLboolean ARB_gpu_shader5; - GLboolean ARB_half_float_pixel; GLboolean ARB_half_float_vertex; GLboolean ARB_instanced_arrays; GLboolean ARB_internalformat_query; @@ -3461,6 +3517,7 @@ struct gl_extensions GLboolean ARB_point_sprite; GLboolean ARB_sample_shading; GLboolean ARB_seamless_cube_map; + GLboolean ARB_separate_shader_objects; GLboolean ARB_shader_atomic_counters; GLboolean ARB_shader_bit_encoding; GLboolean ARB_shader_image_load_store; @@ -4070,7 +4127,8 @@ struct gl_context struct gl_geometry_program_state GeometryProgram; struct gl_ati_fragment_shader_state ATIFragmentShader; - struct gl_shader_state Shader; /**< GLSL shader object state */ + struct gl_pipeline_shader_state Pipeline; /**< GLSL pipeline shader object state */ + struct gl_pipeline_object Shader; /**< GLSL shader object state */ struct gl_shader_compiler_options ShaderCompilerOptions[MESA_SHADER_STAGES]; struct gl_query_state Query; /**< occlusion, timer queries */ @@ -4132,7 +4190,7 @@ struct gl_context GLuint ErrorDebugCount; /* GL_ARB_debug_output/GL_KHR_debug */ - struct gl_debug_state Debug; + struct gl_debug_state *Debug; GLenum RenderMode; /**< either GL_RENDER, GL_SELECT, GL_FEEDBACK */ GLbitfield NewState; /**< bitwise-or of _NEW_* flags */ diff --git a/mesalib/src/mesa/main/pbo.c b/mesalib/src/mesa/main/pbo.c index 400cec3f0..a0d61a643 100644 --- a/mesalib/src/mesa/main/pbo.c +++ b/mesalib/src/mesa/main/pbo.c @@ -149,7 +149,8 @@ _mesa_map_pbo_source(struct gl_context *ctx, buf = (GLubyte *) ctx->Driver.MapBufferRange(ctx, 0, unpack->BufferObj->Size, GL_MAP_READ_BIT, - unpack->BufferObj); + unpack->BufferObj, + MAP_INTERNAL); if (!buf) return NULL; @@ -201,7 +202,7 @@ _mesa_map_validate_pbo_source(struct gl_context *ctx, return ptr; } - if (_mesa_bufferobj_mapped(unpack->BufferObj)) { + if (_mesa_check_disallowed_mapping(unpack->BufferObj)) { /* buffer is already mapped - that's an error */ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(PBO is mapped)", where); return NULL; @@ -221,7 +222,7 @@ _mesa_unmap_pbo_source(struct gl_context *ctx, { ASSERT(unpack != &ctx->Pack); /* catch pack/unpack mismatch */ if (_mesa_is_bufferobj(unpack->BufferObj)) { - ctx->Driver.UnmapBuffer(ctx, unpack->BufferObj); + ctx->Driver.UnmapBuffer(ctx, unpack->BufferObj, MAP_INTERNAL); } } @@ -246,7 +247,8 @@ _mesa_map_pbo_dest(struct gl_context *ctx, buf = (GLubyte *) ctx->Driver.MapBufferRange(ctx, 0, pack->BufferObj->Size, GL_MAP_WRITE_BIT, - pack->BufferObj); + pack->BufferObj, + MAP_INTERNAL); if (!buf) return NULL; @@ -297,7 +299,7 @@ _mesa_map_validate_pbo_dest(struct gl_context *ctx, return ptr; } - if (_mesa_bufferobj_mapped(unpack->BufferObj)) { + if (_mesa_check_disallowed_mapping(unpack->BufferObj)) { /* buffer is already mapped - that's an error */ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(PBO is mapped)", where); return NULL; @@ -317,7 +319,7 @@ _mesa_unmap_pbo_dest(struct gl_context *ctx, { ASSERT(pack != &ctx->Unpack); /* catch pack/unpack mismatch */ if (_mesa_is_bufferobj(pack->BufferObj)) { - ctx->Driver.UnmapBuffer(ctx, pack->BufferObj); + ctx->Driver.UnmapBuffer(ctx, pack->BufferObj, MAP_INTERNAL); } } @@ -351,7 +353,8 @@ _mesa_validate_pbo_teximage(struct gl_context *ctx, GLuint dimensions, buf = (GLubyte *) ctx->Driver.MapBufferRange(ctx, 0, unpack->BufferObj->Size, GL_MAP_READ_BIT, - unpack->BufferObj); + unpack->BufferObj, + MAP_INTERNAL); if (!buf) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s%uD(PBO is mapped)", funcName, dimensions); @@ -393,7 +396,8 @@ _mesa_validate_pbo_compressed_teximage(struct gl_context *ctx, buf = (GLubyte*) ctx->Driver.MapBufferRange(ctx, 0, packing->BufferObj->Size, GL_MAP_READ_BIT, - packing->BufferObj); + packing->BufferObj, + MAP_INTERNAL); if (!buf) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s%uD(PBO is mapped)", funcName, dimensions); @@ -413,6 +417,6 @@ _mesa_unmap_teximage_pbo(struct gl_context *ctx, const struct gl_pixelstore_attrib *unpack) { if (_mesa_is_bufferobj(unpack->BufferObj)) { - ctx->Driver.UnmapBuffer(ctx, unpack->BufferObj); + ctx->Driver.UnmapBuffer(ctx, unpack->BufferObj, MAP_INTERNAL); } } diff --git a/mesalib/src/mesa/main/pipelineobj.c b/mesalib/src/mesa/main/pipelineobj.c new file mode 100644 index 000000000..27012df72 --- /dev/null +++ b/mesalib/src/mesa/main/pipelineobj.c @@ -0,0 +1,445 @@ +/* + * Mesa 3-D graphics library + * + * Copyright © 2013 Gregory Hainaut <gregory.hainaut@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, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +/** + * \file pipelineobj.c + * \author Hainaut Gregory <gregory.hainaut@gmail.com> + * + * Implementation of pipeline object related API functions. Based on + * GL_ARB_separate_shader_objects extension. + */ + +#include "main/glheader.h" +#include "main/context.h" +#include "main/dispatch.h" +#include "main/enums.h" +#include "main/hash.h" +#include "main/mtypes.h" +#include "main/pipelineobj.h" +#include "main/shaderapi.h" +#include "main/shaderobj.h" +#include "main/transformfeedback.h" +#include "main/uniforms.h" +#include "program/program.h" +#include "program/prog_parameter.h" +#include "ralloc.h" +#include <stdbool.h> +#include "../glsl/glsl_parser_extras.h" +#include "../glsl/ir_uniform.h" + +/** + * Delete a pipeline object. + */ +void +_mesa_delete_pipeline_object(struct gl_context *ctx, + struct gl_pipeline_object *obj) +{ + unsigned i; + + _mesa_reference_shader_program(ctx, &obj->_CurrentFragmentProgram, NULL); + + for (i = 0; i < MESA_SHADER_STAGES; i++) + _mesa_reference_shader_program(ctx, &obj->CurrentProgram[i], NULL); + + _mesa_reference_shader_program(ctx, &obj->ActiveProgram, NULL); + mtx_destroy(&obj->Mutex); + ralloc_free(obj); +} + +/** + * Allocate and initialize a new pipeline object. + */ +static struct gl_pipeline_object * +_mesa_new_pipeline_object(struct gl_context *ctx, GLuint name) +{ + struct gl_pipeline_object *obj = rzalloc(NULL, struct gl_pipeline_object); + if (obj) { + obj->Name = name; + mtx_init(&obj->Mutex, mtx_plain); + obj->RefCount = 1; + obj->Flags = _mesa_get_shader_flags(); + } + + return obj; +} + +/** + * Initialize pipeline object state for given context. + */ +void +_mesa_init_pipeline(struct gl_context *ctx) +{ + ctx->Pipeline.Objects = _mesa_NewHashTable(); + + ctx->Pipeline.Current = NULL; +} + + +/** + * Callback for deleting a pipeline object. Called by _mesa_HashDeleteAll(). + */ +static void +delete_pipelineobj_cb(GLuint id, void *data, void *userData) +{ + struct gl_pipeline_object *obj = (struct gl_pipeline_object *) data; + struct gl_context *ctx = (struct gl_context *) userData; + _mesa_delete_pipeline_object(ctx, obj); +} + + +/** + * Free pipeline state for given context. + */ +void +_mesa_free_pipeline_data(struct gl_context *ctx) +{ + _mesa_HashDeleteAll(ctx->Pipeline.Objects, delete_pipelineobj_cb, ctx); + _mesa_DeleteHashTable(ctx->Pipeline.Objects); +} + +/** + * Look up the pipeline object for the given ID. + * + * \returns + * Either a pointer to the pipeline object with the specified ID or \c NULL for + * a non-existent ID. The spec defines ID 0 as being technically + * non-existent. + */ +static inline struct gl_pipeline_object * +lookup_pipeline_object(struct gl_context *ctx, GLuint id) +{ + if (id == 0) + return NULL; + else + return (struct gl_pipeline_object *) + _mesa_HashLookup(ctx->Pipeline.Objects, id); +} + +/** + * Add the given pipeline object to the pipeline object pool. + */ +static void +save_pipeline_object(struct gl_context *ctx, struct gl_pipeline_object *obj) +{ + if (obj->Name > 0) { + _mesa_HashInsert(ctx->Pipeline.Objects, obj->Name, obj); + } +} + +/** + * Remove the given pipeline object from the pipeline object pool. + * Do not deallocate the pipeline object though. + */ +static void +remove_pipeline_object(struct gl_context *ctx, struct gl_pipeline_object *obj) +{ + if (obj->Name > 0) { + _mesa_HashRemove(ctx->Pipeline.Objects, obj->Name); + } +} + +/** + * Set ptr to obj w/ reference counting. + * Note: this should only be called from the _mesa_reference_pipeline_object() + * inline function. + */ +void +_mesa_reference_pipeline_object_(struct gl_context *ctx, + struct gl_pipeline_object **ptr, + struct gl_pipeline_object *obj) +{ + assert(*ptr != obj); + + if (*ptr) { + /* Unreference the old pipeline object */ + GLboolean deleteFlag = GL_FALSE; + struct gl_pipeline_object *oldObj = *ptr; + + mtx_lock(&oldObj->Mutex); + ASSERT(oldObj->RefCount > 0); + oldObj->RefCount--; + deleteFlag = (oldObj->RefCount == 0); + mtx_unlock(&oldObj->Mutex); + + if (deleteFlag) { + _mesa_delete_pipeline_object(ctx, oldObj); + } + + *ptr = NULL; + } + ASSERT(!*ptr); + + if (obj) { + /* reference new pipeline object */ + mtx_lock(&obj->Mutex); + if (obj->RefCount == 0) { + /* this pipeline's being deleted (look just above) */ + /* Not sure this can ever really happen. Warn if it does. */ + _mesa_problem(NULL, "referencing deleted pipeline object"); + *ptr = NULL; + } + else { + obj->RefCount++; + *ptr = obj; + } + mtx_unlock(&obj->Mutex); + } +} + +/** + * Bound program to severals stages of the pipeline + */ +void GLAPIENTRY +_mesa_UseProgramStages(GLuint pipeline, GLbitfield stages, GLuint program) +{ +} + +/** + * Use the named shader program for subsequent glUniform calls (if pipeline + * bound) + */ +void GLAPIENTRY +_mesa_ActiveShaderProgram(GLuint pipeline, GLuint program) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_shader_program *shProg = NULL; + struct gl_pipeline_object *pipe = lookup_pipeline_object(ctx, pipeline); + + if (program != 0) { + shProg = _mesa_lookup_shader_program_err(ctx, program, + "glActiveShaderProgram(program)"); + if (shProg == NULL) + return; + } + + if (!pipe) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glActiveShaderProgram(pipeline)"); + return; + } + + /* Object is created by any Pipeline call but glGenProgramPipelines, + * glIsProgramPipeline and GetProgramPipelineInfoLog + */ + pipe->EverBound = GL_TRUE; + + if ((shProg != NULL) && !shProg->LinkStatus) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glActiveShaderProgram(program %u not linked)", shProg->Name); + return; + } + + _mesa_reference_shader_program(ctx, &pipe->ActiveProgram, shProg); +} + +/** + * Make program of the pipeline current + */ +void GLAPIENTRY +_mesa_BindProgramPipeline(GLuint pipeline) +{ +} + +/** + * Delete a set of pipeline objects. + * + * \param n Number of pipeline objects to delete. + * \param ids pipeline of \c n pipeline object IDs. + */ +void GLAPIENTRY +_mesa_DeleteProgramPipelines(GLsizei n, const GLuint *pipelines) +{ + GET_CURRENT_CONTEXT(ctx); + GLsizei i; + + if (n < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteProgramPipelines(n<0)"); + return; + } + + for (i = 0; i < n; i++) { + struct gl_pipeline_object *obj = + lookup_pipeline_object(ctx, pipelines[i]); + + if (obj) { + ASSERT(obj->Name == pipelines[i]); + + /* If the pipeline object is currently bound, the spec says "If an + * object that is currently bound is deleted, the binding for that + * object reverts to zero and no program pipeline object becomes + * current." + */ + if (obj == ctx->Pipeline.Current) { + _mesa_BindProgramPipeline(0); + } + + /* The ID is immediately freed for re-use */ + remove_pipeline_object(ctx, obj); + + /* Unreference the pipeline object. + * If refcount hits zero, the object will be deleted. + */ + _mesa_reference_pipeline_object(ctx, &obj, NULL); + } + } +} + +/** + * Generate a set of unique pipeline object IDs and store them in \c pipelines. + * \param n Number of IDs to generate. + * \param pipelines pipeline of \c n locations to store the IDs. + */ +void GLAPIENTRY +_mesa_GenProgramPipelines(GLsizei n, GLuint *pipelines) +{ + GET_CURRENT_CONTEXT(ctx); + + GLuint first; + GLint i; + + if (n < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "glGenProgramPipelines(n<0)"); + return; + } + + if (!pipelines) { + return; + } + + first = _mesa_HashFindFreeKeyBlock(ctx->Pipeline.Objects, n); + + for (i = 0; i < n; i++) { + struct gl_pipeline_object *obj; + GLuint name = first + i; + + obj = _mesa_new_pipeline_object(ctx, name); + if (!obj) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenProgramPipelines"); + return; + } + + save_pipeline_object(ctx, obj); + pipelines[i] = first + i; + } + +} + +/** + * Determine if ID is the name of an pipeline object. + * + * \param id ID of the potential pipeline object. + * \return \c GL_TRUE if \c id is the name of a pipeline object, + * \c GL_FALSE otherwise. + */ +GLboolean GLAPIENTRY +_mesa_IsProgramPipeline(GLuint pipeline) +{ + GET_CURRENT_CONTEXT(ctx); + + struct gl_pipeline_object *obj = lookup_pipeline_object(ctx, pipeline); + if (obj == NULL) + return GL_FALSE; + + return obj->EverBound; +} + +/** + * glGetProgramPipelineiv() - get pipeline shader state. + */ +void GLAPIENTRY +_mesa_GetProgramPipelineiv(GLuint pipeline, GLenum pname, GLint *params) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_pipeline_object *pipe = lookup_pipeline_object(ctx, pipeline); + + /* Are geometry shaders available in this context? + */ + const bool has_gs = _mesa_has_geometry_shaders(ctx); + + if (!pipe) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetProgramPipelineiv(pipeline)"); + return; + } + + /* Object is created by any Pipeline call but glGenProgramPipelines, + * glIsProgramPipeline and GetProgramPipelineInfoLog + */ + pipe->EverBound = GL_TRUE; + + switch (pname) { + case GL_ACTIVE_PROGRAM: + *params = pipe->ActiveProgram ? pipe->ActiveProgram->Name : 0; + return; + case GL_INFO_LOG_LENGTH: + /* FINISHME: Implement the info log. + */ + *params = 0; + return; + case GL_VALIDATE_STATUS: + /* FINISHME: Implement validation status. + */ + *params = 0; + return; + case GL_VERTEX_SHADER: + *params = pipe->CurrentProgram[MESA_SHADER_VERTEX] + ? pipe->CurrentProgram[MESA_SHADER_VERTEX]->Name : 0; + return; + case GL_TESS_EVALUATION_SHADER: + /* NOT YET SUPPORTED */ + break; + case GL_TESS_CONTROL_SHADER: + /* NOT YET SUPPORTED */ + break; + case GL_GEOMETRY_SHADER: + if (!has_gs) + break; + *params = pipe->CurrentProgram[MESA_SHADER_GEOMETRY] + ? pipe->CurrentProgram[MESA_SHADER_GEOMETRY]->Name : 0; + return; + case GL_FRAGMENT_SHADER: + *params = pipe->CurrentProgram[MESA_SHADER_FRAGMENT] + ? pipe->CurrentProgram[MESA_SHADER_FRAGMENT]->Name : 0; + return; + default: + break; + } + + _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramPipelineiv(pname=%s)", + _mesa_lookup_enum_by_nr(pname)); +} + +/** + * Check compatibility of pipeline's program + */ +void GLAPIENTRY +_mesa_ValidateProgramPipeline(GLuint pipeline) +{ +} + +void GLAPIENTRY +_mesa_GetProgramPipelineInfoLog(GLuint pipeline, GLsizei bufSize, + GLsizei *length, GLchar *infoLog) +{ +} diff --git a/mesalib/src/mesa/main/pipelineobj.h b/mesalib/src/mesa/main/pipelineobj.h new file mode 100644 index 000000000..46d5fab42 --- /dev/null +++ b/mesalib/src/mesa/main/pipelineobj.h @@ -0,0 +1,95 @@ +/* + * Mesa 3-D graphics library + * + * Copyright © 2013 Gregory Hainaut <gregory.hainaut@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, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef PIPELINEOBJ_H +#define PIPELINEOBJ_H + +#include "glheader.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct _glapi_table; +struct gl_context; +struct gl_pipeline_object; + +extern void +_mesa_delete_pipeline_object(struct gl_context *ctx, struct gl_pipeline_object *obj); + +extern void +_mesa_init_pipeline(struct gl_context *ctx); + +extern void +_mesa_free_pipeline_data(struct gl_context *ctx); + +extern void +_mesa_reference_pipeline_object_(struct gl_context *ctx, + struct gl_pipeline_object **ptr, + struct gl_pipeline_object *obj); + +static inline void +_mesa_reference_pipeline_object(struct gl_context *ctx, + struct gl_pipeline_object **ptr, + struct gl_pipeline_object *obj) +{ + if (*ptr != obj) + _mesa_reference_pipeline_object_(ctx, ptr, obj); +} + + +extern void GLAPIENTRY +_mesa_UseProgramStages(GLuint pipeline, GLbitfield stages, GLuint program); + +extern void GLAPIENTRY +_mesa_ActiveShaderProgram(GLuint pipeline, GLuint program); + +extern void GLAPIENTRY +_mesa_BindProgramPipeline(GLuint pipeline); + +extern void GLAPIENTRY +_mesa_DeleteProgramPipelines(GLsizei n, const GLuint *pipelines); + +extern void GLAPIENTRY +_mesa_GenProgramPipelines(GLsizei n, GLuint *pipelines); + +extern GLboolean GLAPIENTRY +_mesa_IsProgramPipeline(GLuint pipeline); + +extern void GLAPIENTRY +_mesa_GetProgramPipelineiv(GLuint pipeline, GLenum pname, GLint *params); + +extern void GLAPIENTRY +_mesa_ValidateProgramPipeline(GLuint pipeline); + +extern void GLAPIENTRY +_mesa_GetProgramPipelineInfoLog(GLuint pipeline, GLsizei bufSize, + GLsizei *length, GLchar *infoLog); + +#ifdef __cplusplus +} +#endif + +#endif /* PIPELINEOBJ_H */ diff --git a/mesalib/src/mesa/main/readpix.c b/mesalib/src/mesa/main/readpix.c index e16346896..b09cf5499 100644 --- a/mesalib/src/mesa/main/readpix.c +++ b/mesalib/src/mesa/main/readpix.c @@ -595,7 +595,7 @@ fast_read_depth_stencil_pixels(struct gl_context *ctx, return GL_FALSE; if (rb->Format != MESA_FORMAT_S8_UINT_Z24_UNORM && - rb->Format != MESA_FORMAT_Z24_UNORM_X8_UINT) + rb->Format != MESA_FORMAT_Z24_UNORM_S8_UINT) return GL_FALSE; ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT, @@ -1033,7 +1033,7 @@ _mesa_ReadnPixelsARB( GLint x, GLint y, GLsizei width, GLsizei height, } if (_mesa_is_bufferobj(ctx->Pack.BufferObj) && - _mesa_bufferobj_mapped(ctx->Pack.BufferObj)) { + _mesa_check_disallowed_mapping(ctx->Pack.BufferObj)) { /* buffer is mapped - that's an error */ _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(PBO is mapped)"); return; diff --git a/mesalib/src/mesa/main/renderbuffer.c b/mesalib/src/mesa/main/renderbuffer.c index 2ff96e548..0bc7f2b96 100644 --- a/mesalib/src/mesa/main/renderbuffer.c +++ b/mesalib/src/mesa/main/renderbuffer.c @@ -38,7 +38,7 @@ void _mesa_init_renderbuffer(struct gl_renderbuffer *rb, GLuint name) { - _glthread_INIT_MUTEX(rb->Mutex); + mtx_init(&rb->Mutex, mtx_plain); rb->ClassID = 0; rb->Name = name; @@ -83,7 +83,7 @@ _mesa_new_renderbuffer(struct gl_context *ctx, GLuint name) void _mesa_delete_renderbuffer(struct gl_context *ctx, struct gl_renderbuffer *rb) { - _glthread_DESTROY_MUTEX(rb->Mutex); + mtx_destroy(&rb->Mutex); free(rb->Label); free(rb); } @@ -153,12 +153,12 @@ _mesa_reference_renderbuffer_(struct gl_renderbuffer **ptr, GLboolean deleteFlag = GL_FALSE; struct gl_renderbuffer *oldRb = *ptr; - _glthread_LOCK_MUTEX(oldRb->Mutex); + mtx_lock(&oldRb->Mutex); ASSERT(oldRb->RefCount > 0); oldRb->RefCount--; /*printf("RB DECR %p (%d) to %d\n", (void*) oldRb, oldRb->Name, oldRb->RefCount);*/ deleteFlag = (oldRb->RefCount == 0); - _glthread_UNLOCK_MUTEX(oldRb->Mutex); + mtx_unlock(&oldRb->Mutex); if (deleteFlag) { GET_CURRENT_CONTEXT(ctx); @@ -171,10 +171,10 @@ _mesa_reference_renderbuffer_(struct gl_renderbuffer **ptr, if (rb) { /* reference new renderbuffer */ - _glthread_LOCK_MUTEX(rb->Mutex); + mtx_lock(&rb->Mutex); rb->RefCount++; /*printf("RB INCR %p (%d) to %d\n", (void*) rb, rb->Name, rb->RefCount);*/ - _glthread_UNLOCK_MUTEX(rb->Mutex); + mtx_unlock(&rb->Mutex); *ptr = rb; } } diff --git a/mesalib/src/mesa/main/samplerobj.c b/mesalib/src/mesa/main/samplerobj.c index 7285ef5ed..4900d5256 100644 --- a/mesalib/src/mesa/main/samplerobj.c +++ b/mesalib/src/mesa/main/samplerobj.c @@ -66,7 +66,7 @@ _mesa_reference_sampler_object_(struct gl_context *ctx, GLboolean deleteFlag = GL_FALSE; struct gl_sampler_object *oldSamp = *ptr; - /*_glthread_LOCK_MUTEX(oldSamp->Mutex);*/ + /*mtx_lock(&oldSamp->Mutex);*/ ASSERT(oldSamp->RefCount > 0); oldSamp->RefCount--; #if 0 @@ -74,7 +74,7 @@ _mesa_reference_sampler_object_(struct gl_context *ctx, (void *) oldSamp, oldSamp->Name, oldSamp->RefCount); #endif deleteFlag = (oldSamp->RefCount == 0); - /*_glthread_UNLOCK_MUTEX(oldSamp->Mutex);*/ + /*mtx_unlock(&oldSamp->Mutex);*/ if (deleteFlag) { ASSERT(ctx->Driver.DeleteSamplerObject); @@ -87,7 +87,7 @@ _mesa_reference_sampler_object_(struct gl_context *ctx, if (samp) { /* reference new sampler */ - /*_glthread_LOCK_MUTEX(samp->Mutex);*/ + /*mtx_lock(&samp->Mutex);*/ if (samp->RefCount == 0) { /* this sampler's being deleted (look just above) */ /* Not sure this can every really happen. Warn if it does. */ @@ -102,7 +102,7 @@ _mesa_reference_sampler_object_(struct gl_context *ctx, #endif *ptr = samp; } - /*_glthread_UNLOCK_MUTEX(samp->Mutex);*/ + /*mtx_unlock(&samp->Mutex);*/ } } @@ -203,7 +203,7 @@ _mesa_DeleteSamplers(GLsizei count, const GLuint *samplers) return; } - _glthread_LOCK_MUTEX(ctx->Shared->Mutex); + mtx_lock(&ctx->Shared->Mutex); for (i = 0; i < count; i++) { if (samplers[i]) { @@ -228,7 +228,7 @@ _mesa_DeleteSamplers(GLsizei count, const GLuint *samplers) } } - _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); + mtx_unlock(&ctx->Shared->Mutex); } diff --git a/mesalib/src/mesa/main/shaderapi.c b/mesalib/src/mesa/main/shaderapi.c index 65b6b16bb..5060cbb0b 100644 --- a/mesalib/src/mesa/main/shaderapi.c +++ b/mesalib/src/mesa/main/shaderapi.c @@ -65,8 +65,8 @@ /** * Return mask of GLSL_x flags by examining the MESA_GLSL env var. */ -static GLbitfield -get_shader_flags(void) +GLbitfield +_mesa_get_shader_flags(void) { GLbitfield flags = 0x0; const char *env = _mesa_getenv("MESA_GLSL"); @@ -120,7 +120,11 @@ _mesa_init_shader_state(struct gl_context *ctx) for (sh = 0; sh < MESA_SHADER_STAGES; ++sh) memcpy(&ctx->ShaderCompilerOptions[sh], &options, sizeof(options)); - ctx->Shader.Flags = get_shader_flags(); + ctx->Shader.Flags = _mesa_get_shader_flags(); + + /* Extended for ARB_separate_shader_objects */ + ctx->Shader.RefCount = 1; + mtx_init(&ctx->Shader.Mutex, mtx_plain); } @@ -138,6 +142,10 @@ _mesa_free_shader_state(struct gl_context *ctx) _mesa_reference_shader_program(ctx, &ctx->Shader._CurrentFragmentProgram, NULL); _mesa_reference_shader_program(ctx, &ctx->Shader.ActiveProgram, NULL); + + /* Extended for ARB_separate_shader_objects */ + assert(ctx->Shader.RefCount == 1); + mtx_destroy(&ctx->Shader.Mutex); } @@ -383,30 +391,31 @@ detach_shader(struct gl_context *ctx, GLuint program, GLuint shader) _mesa_reference_shader(ctx, &shProg->Shaders[i], NULL); /* alloc new, smaller array */ - newList = - malloc((n - 1) * sizeof(struct gl_shader *)); + newList = malloc((n - 1) * sizeof(struct gl_shader *)); if (!newList) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDetachShader"); return; } + /* Copy old list entries to new list, skipping removed entry at [i] */ for (j = 0; j < i; j++) { newList[j] = shProg->Shaders[j]; } - while (++i < n) + while (++i < n) { newList[j++] = shProg->Shaders[i]; - free(shProg->Shaders); + } + /* Free old list and install new one */ + free(shProg->Shaders); shProg->Shaders = newList; shProg->NumShaders = n - 1; #ifdef DEBUG - /* sanity check */ - { - for (j = 0; j < shProg->NumShaders; j++) { - assert(shProg->Shaders[j]->Type == GL_VERTEX_SHADER || - shProg->Shaders[j]->Type == GL_FRAGMENT_SHADER); - assert(shProg->Shaders[j]->RefCount > 0); - } + /* sanity check - make sure the new list's entries are sensible */ + for (j = 0; j < shProg->NumShaders; j++) { + assert(shProg->Shaders[j]->Type == GL_VERTEX_SHADER || + shProg->Shaders[j]->Type == GL_GEOMETRY_SHADER || + shProg->Shaders[j]->Type == GL_FRAGMENT_SHADER); + assert(shProg->Shaders[j]->RefCount > 0); } #endif @@ -605,6 +614,12 @@ get_programiv(struct gl_context *ctx, GLuint program, GLenum pname, GLint *param if (check_gs_query(ctx, shProg)) *params = shProg->Geom.VerticesOut; return; + case GL_GEOMETRY_SHADER_INVOCATIONS: + if (!has_core_gs || !ctx->Extensions.ARB_gpu_shader5) + break; + if (check_gs_query(ctx, shProg)) + *params = shProg->Geom.Invocations; + return; case GL_GEOMETRY_INPUT_TYPE: if (!has_core_gs) break; @@ -681,6 +696,12 @@ get_programiv(struct gl_context *ctx, GLuint program, GLenum pname, GLint *param params[i] = shProg->Comp.LocalSize[i]; return; } + case GL_PROGRAM_SEPARABLE: + if (!ctx->Extensions.ARB_separate_shader_objects) + break; + + *params = shProg->SeparateShader; + return; default: break; } @@ -817,9 +838,10 @@ compile_shader(struct gl_context *ctx, GLuint shaderObj) sh->CompileStatus = GL_FALSE; } else { if (ctx->Shader.Flags & GLSL_DUMP) { - printf("GLSL source for %s shader %d:\n", - _mesa_shader_stage_to_string(sh->Stage), sh->Name); - printf("%s\n", sh->Source); + fprintf(stderr, "GLSL source for %s shader %d:\n", + _mesa_shader_stage_to_string(sh->Stage), sh->Name); + fprintf(stderr, "%s\n", sh->Source); + fflush(stderr); } /* this call will set the shader->CompileStatus field to indicate if @@ -833,16 +855,17 @@ compile_shader(struct gl_context *ctx, GLuint shaderObj) if (ctx->Shader.Flags & GLSL_DUMP) { if (sh->CompileStatus) { - printf("GLSL IR for shader %d:\n", sh->Name); - _mesa_print_ir(sh->ir, NULL); - printf("\n\n"); + fprintf(stderr, "GLSL IR for shader %d:\n", sh->Name); + _mesa_print_ir(stderr, sh->ir, NULL); + fprintf(stderr, "\n\n"); } else { - printf("GLSL shader %d failed to compile.\n", sh->Name); + fprintf(stderr, "GLSL shader %d failed to compile.\n", sh->Name); } if (sh->InfoLog && sh->InfoLog[0] != 0) { - printf("GLSL shader %d info log:\n", sh->Name); - printf("%s\n", sh->InfoLog); + fprintf(stderr, "GLSL shader %d info log:\n", sh->Name); + fprintf(stderr, "%s\n", sh->InfoLog); } + fflush(stderr); } } @@ -1721,6 +1744,25 @@ _mesa_ProgramParameteri(GLuint program, GLenum pname, GLint value) */ shProg->BinaryRetreivableHint = value; return; + + case GL_PROGRAM_SEPARABLE: + if (!ctx->Extensions.ARB_separate_shader_objects) + break; + + /* Spec imply that the behavior is the same as ARB_get_program_binary + * Chapter 7.3 Program Objects + */ + if (value != GL_TRUE && value != GL_FALSE) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glProgramParameteri(pname=%s, value=%d): " + "value must be 0 or 1.", + _mesa_lookup_enum_by_nr(pname), + value); + return; + } + shProg->SeparateShader = value; + return; + default: break; } @@ -1792,19 +1834,16 @@ _mesa_ActiveProgramEXT(GLuint program) return; } - -/** - * For GL_EXT_separate_shader_objects - */ -GLuint GLAPIENTRY -_mesa_CreateShaderProgramEXT(GLenum type, const GLchar *string) +static GLuint +_mesa_create_shader_program(struct gl_context* ctx, GLboolean separate, + GLenum type, GLsizei count, const GLchar* const *strings) { - GET_CURRENT_CONTEXT(ctx); const GLuint shader = create_shader(ctx, type); GLuint program = 0; if (shader) { - shader_source(ctx, shader, _mesa_strdup(string)); + _mesa_ShaderSource(shader, count, strings, NULL); + compile_shader(ctx, shader); program = create_shader_program(ctx); @@ -1816,6 +1855,8 @@ _mesa_CreateShaderProgramEXT(GLenum type, const GLchar *string) shProg = _mesa_lookup_shader_program(ctx, program); sh = _mesa_lookup_shader(ctx, shader); + shProg->SeparateShader = separate; + get_shaderiv(ctx, shader, GL_COMPILE_STATUS, &compiled); if (compiled) { attach_shader(ctx, program, shader); @@ -1858,6 +1899,7 @@ _mesa_copy_linked_program_data(gl_shader_stage type, struct gl_geometry_program *dst_gp = (struct gl_geometry_program *) dst; dst_gp->VerticesIn = src->Geom.VerticesIn; dst_gp->VerticesOut = src->Geom.VerticesOut; + dst_gp->Invocations = src->Geom.Invocations; dst_gp->InputType = src->Geom.InputType; dst_gp->OutputType = src->Geom.OutputType; dst->UsesClipDistanceOut = src->Geom.UsesClipDistance; @@ -1875,3 +1917,30 @@ _mesa_copy_linked_program_data(gl_shader_stage type, break; } } + + +/** + * For GL_EXT_separate_shader_objects + */ +GLuint GLAPIENTRY +_mesa_CreateShaderProgramEXT(GLenum type, const GLchar *string) +{ + GET_CURRENT_CONTEXT(ctx); + + return _mesa_create_shader_program(ctx, GL_FALSE, type, 1, &string); +} + +/** + * ARB_separate_shader_objects: Compile & Link Program + * + * Basically the same as _mesa_CreateShaderProgramEXT but with support of + * multiple strings and sets the SeparateShader flag to true. + */ +GLuint GLAPIENTRY +_mesa_CreateShaderProgramv(GLenum type, GLsizei count, + const GLchar* const *strings) +{ + GET_CURRENT_CONTEXT(ctx); + + return _mesa_create_shader_program(ctx, GL_TRUE, type, count, strings); +} diff --git a/mesalib/src/mesa/main/shaderapi.h b/mesalib/src/mesa/main/shaderapi.h index 10f810caf..44426cc65 100644 --- a/mesalib/src/mesa/main/shaderapi.h +++ b/mesalib/src/mesa/main/shaderapi.h @@ -40,6 +40,9 @@ struct _glapi_table; struct gl_context; struct gl_shader_program; +extern GLbitfield +_mesa_get_shader_flags(void); + extern void _mesa_copy_string(GLchar *dst, GLsizei maxLength, GLsizei *length, const GLchar *src); @@ -219,6 +222,11 @@ extern bool _mesa_validate_shader_target(const struct gl_context *ctx, GLenum type); +/* GL_ARB_separate_shader_objects */ +extern GLuint GLAPIENTRY +_mesa_CreateShaderProgramv(GLenum type, GLsizei count, + const GLchar* const *strings); + #ifdef __cplusplus } #endif diff --git a/mesalib/src/mesa/main/shaderobj.c b/mesalib/src/mesa/main/shaderobj.c index 4f4bb69a8..d5c3d8099 100644 --- a/mesalib/src/mesa/main/shaderobj.c +++ b/mesalib/src/mesa/main/shaderobj.c @@ -355,6 +355,7 @@ _mesa_free_shader_program_data(struct gl_context *ctx, } free(shProg->Label); + shProg->Label = NULL; } diff --git a/mesalib/src/mesa/main/shared.c b/mesalib/src/mesa/main/shared.c index c11c7f9e9..dc22025c2 100644 --- a/mesalib/src/mesa/main/shared.c +++ b/mesalib/src/mesa/main/shared.c @@ -62,7 +62,7 @@ _mesa_alloc_shared_state(struct gl_context *ctx) if (!shared) return NULL; - _glthread_INIT_MUTEX(shared->Mutex); + mtx_init(&shared->Mutex, mtx_plain); shared->DisplayList = _mesa_NewHashTable(); shared->TexObjects = _mesa_NewHashTable(); @@ -113,7 +113,7 @@ _mesa_alloc_shared_state(struct gl_context *ctx) assert(shared->DefaultTex[TEXTURE_1D_INDEX]->RefCount == 1); /* Mutex and timestamp for texobj state validation */ - _glthread_INIT_MUTEX(shared->TexMutex); + mtx_init(&shared->TexMutex, mtx_plain); shared->TextureStateStamp = 0; shared->FrameBuffers = _mesa_NewHashTable(); @@ -186,10 +186,8 @@ delete_bufferobj_cb(GLuint id, void *data, void *userData) { struct gl_buffer_object *bufObj = (struct gl_buffer_object *) data; struct gl_context *ctx = (struct gl_context *) userData; - if (_mesa_bufferobj_mapped(bufObj)) { - ctx->Driver.UnmapBuffer(ctx, bufObj); - bufObj->Pointer = NULL; - } + + _mesa_buffer_unmap_all_mappings(ctx, bufObj); _mesa_reference_buffer_object(ctx, &bufObj, NULL); } @@ -356,8 +354,8 @@ free_shared_state(struct gl_context *ctx, struct gl_shared_state *shared) _mesa_HashDeleteAll(shared->TexObjects, delete_texture_cb, ctx); _mesa_DeleteHashTable(shared->TexObjects); - _glthread_DESTROY_MUTEX(shared->Mutex); - _glthread_DESTROY_MUTEX(shared->TexMutex); + mtx_destroy(&shared->Mutex); + mtx_destroy(&shared->TexMutex); free(shared); } @@ -380,11 +378,11 @@ _mesa_reference_shared_state(struct gl_context *ctx, struct gl_shared_state *old = *ptr; GLboolean delete; - _glthread_LOCK_MUTEX(old->Mutex); + mtx_lock(&old->Mutex); assert(old->RefCount >= 1); old->RefCount--; delete = (old->RefCount == 0); - _glthread_UNLOCK_MUTEX(old->Mutex); + mtx_unlock(&old->Mutex); if (delete) { free_shared_state(ctx, old); @@ -395,9 +393,9 @@ _mesa_reference_shared_state(struct gl_context *ctx, if (state) { /* reference new state */ - _glthread_LOCK_MUTEX(state->Mutex); + mtx_lock(&state->Mutex); state->RefCount++; *ptr = state; - _glthread_UNLOCK_MUTEX(state->Mutex); + mtx_unlock(&state->Mutex); } } diff --git a/mesalib/src/mesa/main/syncobj.c b/mesalib/src/mesa/main/syncobj.c index ad21f3b67..a88d7e469 100644 --- a/mesalib/src/mesa/main/syncobj.c +++ b/mesalib/src/mesa/main/syncobj.c @@ -184,9 +184,9 @@ _mesa_validate_sync(struct gl_context *ctx, void _mesa_ref_sync_object(struct gl_context *ctx, struct gl_sync_object *syncObj) { - _glthread_LOCK_MUTEX(ctx->Shared->Mutex); + mtx_lock(&ctx->Shared->Mutex); syncObj->RefCount++; - _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); + mtx_unlock(&ctx->Shared->Mutex); } @@ -195,7 +195,7 @@ _mesa_unref_sync_object(struct gl_context *ctx, struct gl_sync_object *syncObj) { struct set_entry *entry; - _glthread_LOCK_MUTEX(ctx->Shared->Mutex); + mtx_lock(&ctx->Shared->Mutex); syncObj->RefCount--; if (syncObj->RefCount == 0) { entry = _mesa_set_search(ctx->Shared->SyncObjects, @@ -203,11 +203,11 @@ _mesa_unref_sync_object(struct gl_context *ctx, struct gl_sync_object *syncObj) syncObj); assert (entry != NULL); _mesa_set_remove(ctx->Shared->SyncObjects, entry); - _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); + mtx_unlock(&ctx->Shared->Mutex); ctx->Driver.DeleteSyncObject(ctx, syncObj); } else { - _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); + mtx_unlock(&ctx->Shared->Mutex); } } @@ -288,11 +288,11 @@ _mesa_FenceSync(GLenum condition, GLbitfield flags) ctx->Driver.FenceSync(ctx, syncObj, condition, flags); - _glthread_LOCK_MUTEX(ctx->Shared->Mutex); + mtx_lock(&ctx->Shared->Mutex); _mesa_set_add(ctx->Shared->SyncObjects, _mesa_hash_pointer(syncObj), syncObj); - _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); + mtx_unlock(&ctx->Shared->Mutex); return (GLsync) syncObj; } diff --git a/mesalib/src/mesa/main/texcompress_etc.c b/mesalib/src/mesa/main/texcompress_etc.c index e3862be45..cbda68940 100644 --- a/mesalib/src/mesa/main/texcompress_etc.c +++ b/mesalib/src/mesa/main/texcompress_etc.c @@ -429,8 +429,7 @@ etc2_rgb8_parse_block(struct etc2_block *block, block->is_planar_mode = true; /* opaque bit must be set in planar mode */ - if (!block->opaque) - block->opaque = true; + block->opaque = true; for (i = 0; i < 3; i++) { block->base_colors[0][i] = etc2_base_color_o_planar(src, i); diff --git a/mesalib/src/mesa/main/texformat.c b/mesalib/src/mesa/main/texformat.c index bda2d8e17..004e7ebac 100644 --- a/mesalib/src/mesa/main/texformat.c +++ b/mesalib/src/mesa/main/texformat.c @@ -209,13 +209,13 @@ _mesa_choose_tex_format(struct gl_context *ctx, GLenum target, case GL_DEPTH_COMPONENT24: case GL_DEPTH_COMPONENT32: RETURN_IF_SUPPORTED(MESA_FORMAT_Z_UNORM32); - RETURN_IF_SUPPORTED(MESA_FORMAT_Z24_UNORM_S8_UINT); RETURN_IF_SUPPORTED(MESA_FORMAT_Z24_UNORM_X8_UINT); + RETURN_IF_SUPPORTED(MESA_FORMAT_Z24_UNORM_S8_UINT); break; case GL_DEPTH_COMPONENT16: RETURN_IF_SUPPORTED(MESA_FORMAT_Z_UNORM16); - RETURN_IF_SUPPORTED(MESA_FORMAT_Z24_UNORM_S8_UINT); RETURN_IF_SUPPORTED(MESA_FORMAT_Z24_UNORM_X8_UINT); + RETURN_IF_SUPPORTED(MESA_FORMAT_Z24_UNORM_S8_UINT); break; case GL_COMPRESSED_ALPHA_ARB: @@ -426,7 +426,7 @@ _mesa_choose_tex_format(struct gl_context *ctx, GLenum target, case GL_DEPTH_STENCIL_EXT: case GL_DEPTH24_STENCIL8_EXT: RETURN_IF_SUPPORTED(MESA_FORMAT_S8_UINT_Z24_UNORM); - RETURN_IF_SUPPORTED(MESA_FORMAT_Z24_UNORM_X8_UINT); + RETURN_IF_SUPPORTED(MESA_FORMAT_Z24_UNORM_S8_UINT); break; case GL_DEPTH_COMPONENT32F: diff --git a/mesalib/src/mesa/main/texgetimage.c b/mesalib/src/mesa/main/texgetimage.c index 133fa5376..daabf2e81 100644 --- a/mesalib/src/mesa/main/texgetimage.c +++ b/mesalib/src/mesa/main/texgetimage.c @@ -130,6 +130,10 @@ get_tex_depth_stencil(struct gl_context *ctx, GLuint dimensions, const GLint depth = texImage->Depth; GLint img, row; + assert(format == GL_DEPTH_STENCIL); + assert(type == GL_UNSIGNED_INT_24_8); + /* XXX type == GL_FLOAT_32_UNSIGNED_INT_24_8_REV is not handled yet */ + for (img = 0; img < depth; img++) { GLubyte *srcMap; GLint rowstride; @@ -145,8 +149,11 @@ get_tex_depth_stencil(struct gl_context *ctx, GLuint dimensions, void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels, width, height, format, type, img, row, 0); - /* XXX Z24_S8 vs. S8_Z24??? */ - memcpy(dest, src, width * sizeof(GLuint)); + /* Unpack from texture's format to GL's z24_s8 layout */ + _mesa_unpack_uint_24_8_depth_stencil_row(texImage->TexFormat, + width, + (const GLuint *) src, + dest); if (ctx->Pack.SwapBytes) { _mesa_swap4((GLuint *) dest, width); } @@ -635,7 +642,8 @@ _mesa_get_teximage(struct gl_context *ctx, */ GLubyte *buf = (GLubyte *) ctx->Driver.MapBufferRange(ctx, 0, ctx->Pack.BufferObj->Size, - GL_MAP_WRITE_BIT, ctx->Pack.BufferObj); + GL_MAP_WRITE_BIT, ctx->Pack.BufferObj, + MAP_INTERNAL); if (!buf) { /* out of memory or other unexpected error */ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage(map PBO failed)"); @@ -664,7 +672,7 @@ _mesa_get_teximage(struct gl_context *ctx, } if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { - ctx->Driver.UnmapBuffer(ctx, ctx->Pack.BufferObj); + ctx->Driver.UnmapBuffer(ctx, ctx->Pack.BufferObj, MAP_INTERNAL); } } @@ -689,7 +697,8 @@ _mesa_get_compressed_teximage(struct gl_context *ctx, /* pack texture image into a PBO */ GLubyte *buf = (GLubyte *) ctx->Driver.MapBufferRange(ctx, 0, ctx->Pack.BufferObj->Size, - GL_MAP_WRITE_BIT, ctx->Pack.BufferObj); + GL_MAP_WRITE_BIT, ctx->Pack.BufferObj, + MAP_INTERNAL); if (!buf) { /* out of memory or other unexpected error */ _mesa_error(ctx, GL_OUT_OF_MEMORY, @@ -731,7 +740,7 @@ _mesa_get_compressed_teximage(struct gl_context *ctx, } if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { - ctx->Driver.UnmapBuffer(ctx, ctx->Pack.BufferObj); + ctx->Driver.UnmapBuffer(ctx, ctx->Pack.BufferObj, MAP_INTERNAL); } } @@ -861,7 +870,7 @@ getteximage_error_check(struct gl_context *ctx, GLenum target, GLint level, if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { /* PBO should not be mapped */ - if (_mesa_bufferobj_mapped(ctx->Pack.BufferObj)) { + if (_mesa_check_disallowed_mapping(ctx->Pack.BufferObj)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(PBO is mapped)"); return GL_TRUE; @@ -1004,7 +1013,7 @@ getcompressedteximage_error_check(struct gl_context *ctx, GLenum target, } /* make sure PBO is not mapped */ - if (_mesa_bufferobj_mapped(ctx->Pack.BufferObj)) { + if (_mesa_check_disallowed_mapping(ctx->Pack.BufferObj)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetCompressedTexImage(PBO is mapped)"); return GL_TRUE; diff --git a/mesalib/src/mesa/main/teximage.c b/mesalib/src/mesa/main/teximage.c index 4d635fe7f..0519d221f 100644 --- a/mesalib/src/mesa/main/teximage.c +++ b/mesalib/src/mesa/main/teximage.c @@ -397,11 +397,6 @@ _mesa_base_tex_format( struct gl_context *ctx, GLint internalFormat ) if (ctx->Extensions.ARB_texture_rg) { switch (internalFormat) { case GL_R16F: - /* R16F depends on both ARB_half_float_pixel and ARB_texture_float. - */ - if (!ctx->Extensions.ARB_half_float_pixel) - break; - /* FALLTHROUGH */ case GL_R32F: if (!ctx->Extensions.ARB_texture_float) break; @@ -422,11 +417,6 @@ _mesa_base_tex_format( struct gl_context *ctx, GLint internalFormat ) return GL_RED; case GL_RG16F: - /* RG16F depends on both ARB_half_float_pixel and ARB_texture_float. - */ - if (!ctx->Extensions.ARB_half_float_pixel) - break; - /* FALLTHROUGH */ case GL_RG32F: if (!ctx->Extensions.ARB_texture_float) break; @@ -2254,9 +2244,10 @@ compressed_texture_error_check(struct gl_context *ctx, GLint dimensions, /* This will detect any invalid internalFormat value */ if (!_mesa_is_compressed_format(ctx, internalFormat)) { - reason = "internalFormat"; - error = GL_INVALID_ENUM; - goto error; + _mesa_error(ctx, GL_INVALID_ENUM, + "glCompressedTexImage%dD(internalFormat=%s)", + dimensions, _mesa_lookup_enum_by_nr(internalFormat)); + return GL_TRUE; } switch (internalFormat) { @@ -2348,6 +2339,7 @@ compressed_texture_error_check(struct gl_context *ctx, GLint dimensions, return GL_FALSE; error: + /* Note: not all error paths exit through here. */ _mesa_error(ctx, error, "glCompressedTexImage%dD(%s)", dimensions, reason); return GL_TRUE; } @@ -2563,7 +2555,8 @@ copytexture_error_check( struct gl_context *ctx, GLuint dimensions, break; default: _mesa_error(ctx, GL_INVALID_VALUE, - "glCopyTexImage%dD(internalFormat)", dimensions); + "glCopyTexImage%dD(internalFormat=%s)", dimensions, + _mesa_lookup_enum_by_nr(internalFormat)); return GL_TRUE; } } @@ -2571,7 +2564,8 @@ copytexture_error_check( struct gl_context *ctx, GLuint dimensions, baseFormat = _mesa_base_tex_format(ctx, internalFormat); if (baseFormat < 0) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glCopyTexImage%dD(internalFormat)", dimensions); + "glCopyTexImage%dD(internalFormat=%s)", dimensions, + _mesa_lookup_enum_by_nr(internalFormat)); return GL_TRUE; } @@ -2580,7 +2574,8 @@ copytexture_error_check( struct gl_context *ctx, GLuint dimensions, if (_mesa_is_color_format(internalFormat)) { if (rb_base_format < 0) { _mesa_error(ctx, GL_INVALID_VALUE, - "glCopyTexImage%dD(internalFormat)", dimensions); + "glCopyTexImage%dD(internalFormat=%s)", dimensions, + _mesa_lookup_enum_by_nr(internalFormat)); return GL_TRUE; } } @@ -2606,7 +2601,8 @@ copytexture_error_check( struct gl_context *ctx, GLuint dimensions, } if (!valid) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glCopyTexImage%dD(internalFormat)", dimensions); + "glCopyTexImage%dD(internalFormat=%s)", dimensions, + _mesa_lookup_enum_by_nr(internalFormat)); return GL_TRUE; } } @@ -4183,10 +4179,18 @@ _mesa_validate_texbuffer_format(const struct gl_context *ctx, return MESA_FORMAT_NONE; datatype = _mesa_get_format_datatype(format); - if (datatype == GL_FLOAT && !ctx->Extensions.ARB_texture_float) - return MESA_FORMAT_NONE; - if (datatype == GL_HALF_FLOAT && !ctx->Extensions.ARB_half_float_pixel) + /* The GL_ARB_texture_buffer_object spec says: + * + * "If ARB_texture_float is not supported, references to the + * floating-point internal formats provided by that extension should be + * removed, and such formats may not be passed to TexBufferARB." + * + * As a result, GL_HALF_FLOAT internal format depends on both + * GL_ARB_texture_float and GL_ARB_half_float_pixel. + */ + if ((datatype == GL_FLOAT || datatype == GL_HALF_FLOAT) && + !ctx->Extensions.ARB_texture_float) return MESA_FORMAT_NONE; if (!ctx->Extensions.ARB_texture_rg) { diff --git a/mesalib/src/mesa/main/teximage.h b/mesalib/src/mesa/main/teximage.h index 5f8a47776..51d94d17e 100644 --- a/mesalib/src/mesa/main/teximage.h +++ b/mesalib/src/mesa/main/teximage.h @@ -163,7 +163,7 @@ _mesa_legal_texture_base_format_for_target(struct gl_context *ctx, static inline void _mesa_lock_texture(struct gl_context *ctx, struct gl_texture_object *texObj) { - _glthread_LOCK_MUTEX(ctx->Shared->TexMutex); + mtx_lock(&ctx->Shared->TexMutex); ctx->Shared->TextureStateStamp++; (void) texObj; } @@ -172,7 +172,7 @@ static inline void _mesa_unlock_texture(struct gl_context *ctx, struct gl_texture_object *texObj) { (void) texObj; - _glthread_UNLOCK_MUTEX(ctx->Shared->TexMutex); + mtx_unlock(&ctx->Shared->TexMutex); } /*@}*/ diff --git a/mesalib/src/mesa/main/texobj.c b/mesalib/src/mesa/main/texobj.c index 6adc0ae84..3375fe36b 100644 --- a/mesalib/src/mesa/main/texobj.c +++ b/mesalib/src/mesa/main/texobj.c @@ -115,7 +115,7 @@ _mesa_initialize_texture_object( struct gl_context *ctx, memset(obj, 0, sizeof(*obj)); /* init the non-zero fields */ - _glthread_INIT_MUTEX(obj->Mutex); + mtx_init(&obj->Mutex, mtx_plain); obj->RefCount = 1; obj->Name = name; obj->Target = target; @@ -237,7 +237,7 @@ _mesa_delete_texture_object(struct gl_context *ctx, _mesa_reference_buffer_object(ctx, &texObj->BufferObject, NULL); /* destroy the mutex -- it may have allocated memory (eg on bsd) */ - _glthread_DESTROY_MUTEX(texObj->Mutex); + mtx_destroy(&texObj->Mutex); free(texObj->Label); @@ -374,12 +374,12 @@ _mesa_reference_texobj_(struct gl_texture_object **ptr, ASSERT(valid_texture_object(oldTex)); (void) valid_texture_object; /* silence warning in release builds */ - _glthread_LOCK_MUTEX(oldTex->Mutex); + mtx_lock(&oldTex->Mutex); ASSERT(oldTex->RefCount > 0); oldTex->RefCount--; deleteFlag = (oldTex->RefCount == 0); - _glthread_UNLOCK_MUTEX(oldTex->Mutex); + mtx_unlock(&oldTex->Mutex); if (deleteFlag) { GET_CURRENT_CONTEXT(ctx); @@ -396,7 +396,7 @@ _mesa_reference_texobj_(struct gl_texture_object **ptr, if (tex) { /* reference new texture */ ASSERT(valid_texture_object(tex)); - _glthread_LOCK_MUTEX(tex->Mutex); + mtx_lock(&tex->Mutex); if (tex->RefCount == 0) { /* this texture's being deleted (look just above) */ /* Not sure this can every really happen. Warn if it does. */ @@ -407,7 +407,7 @@ _mesa_reference_texobj_(struct gl_texture_object **ptr, tex->RefCount++; *ptr = tex; } - _glthread_UNLOCK_MUTEX(tex->Mutex); + mtx_unlock(&tex->Mutex); } } @@ -1009,7 +1009,7 @@ _mesa_GenTextures( GLsizei n, GLuint *textures ) /* * This must be atomic (generation and allocation of texture IDs) */ - _glthread_LOCK_MUTEX(ctx->Shared->Mutex); + mtx_lock(&ctx->Shared->Mutex); first = _mesa_HashFindFreeKeyBlock(ctx->Shared->TexObjects, n); @@ -1020,7 +1020,7 @@ _mesa_GenTextures( GLsizei n, GLuint *textures ) GLenum target = 0; texObj = ctx->Driver.NewTextureObject(ctx, name, target); if (!texObj) { - _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); + mtx_unlock(&ctx->Shared->Mutex); _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenTextures"); return; } @@ -1031,7 +1031,7 @@ _mesa_GenTextures( GLsizei n, GLuint *textures ) textures[i] = name; } - _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); + mtx_unlock(&ctx->Shared->Mutex); } @@ -1178,9 +1178,9 @@ _mesa_DeleteTextures( GLsizei n, const GLuint *textures) /* The texture _name_ is now free for re-use. * Remove it from the hash table now. */ - _glthread_LOCK_MUTEX(ctx->Shared->Mutex); + mtx_lock(&ctx->Shared->Mutex); _mesa_HashRemove(ctx->Shared->TexObjects, delObj->Name); - _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); + mtx_unlock(&ctx->Shared->Mutex); /* Unreference the texobj. If refcount hits zero, the texture * will be deleted. @@ -1313,9 +1313,9 @@ _mesa_BindTexture( GLenum target, GLuint texName ) } /* and insert it into hash table */ - _glthread_LOCK_MUTEX(ctx->Shared->Mutex); + mtx_lock(&ctx->Shared->Mutex); _mesa_HashInsert(ctx->Shared->TexObjects, texName, newTexObj); - _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); + mtx_unlock(&ctx->Shared->Mutex); } newTexObj->Target = target; } @@ -1327,10 +1327,10 @@ _mesa_BindTexture( GLenum target, GLuint texName ) */ { GLboolean early_out; - _glthread_LOCK_MUTEX(ctx->Shared->Mutex); + mtx_lock(&ctx->Shared->Mutex); early_out = ((ctx->Shared->RefCount == 1) && (newTexObj == texUnit->CurrentTex[targetIndex])); - _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); + mtx_unlock(&ctx->Shared->Mutex); if (early_out) { return; } @@ -1493,7 +1493,7 @@ _mesa_IsTexture( GLuint texture ) void _mesa_lock_context_textures( struct gl_context *ctx ) { - _glthread_LOCK_MUTEX(ctx->Shared->TexMutex); + mtx_lock(&ctx->Shared->TexMutex); if (ctx->Shared->TextureStateStamp != ctx->TextureStateTimestamp) { ctx->NewState |= _NEW_TEXTURE; @@ -1506,7 +1506,7 @@ void _mesa_unlock_context_textures( struct gl_context *ctx ) { assert(ctx->Shared->TextureStateStamp == ctx->TextureStateTimestamp); - _glthread_UNLOCK_MUTEX(ctx->Shared->TexMutex); + mtx_unlock(&ctx->Shared->TexMutex); } void GLAPIENTRY diff --git a/mesalib/src/mesa/main/texparam.c b/mesalib/src/mesa/main/texparam.c index b7ed50dd5..bbdbc2763 100644 --- a/mesalib/src/mesa/main/texparam.c +++ b/mesalib/src/mesa/main/texparam.c @@ -986,6 +986,9 @@ legal_get_tex_level_parameter_target(struct gl_context *ctx, GLenum target) case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: case GL_PROXY_TEXTURE_CUBE_MAP_ARB: return ctx->Extensions.ARB_texture_cube_map; + case GL_TEXTURE_CUBE_MAP_ARRAY_ARB: + case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY_ARB: + return ctx->Extensions.ARB_texture_cube_map_array; case GL_TEXTURE_RECTANGLE_NV: case GL_PROXY_TEXTURE_RECTANGLE_NV: return ctx->Extensions.NV_texture_rectangle; diff --git a/mesalib/src/mesa/main/texstore.c b/mesalib/src/mesa/main/texstore.c index 1e4308a04..3e22a0b46 100644 --- a/mesalib/src/mesa/main/texstore.c +++ b/mesalib/src/mesa/main/texstore.c @@ -1049,7 +1049,7 @@ _mesa_texstore_x8_z24(TEXSTORE_PARAMS) const GLuint depthScale = 0xffffff; (void) dims; - ASSERT(dstFormat == MESA_FORMAT_Z24_UNORM_S8_UINT); + ASSERT(dstFormat == MESA_FORMAT_Z24_UNORM_X8_UINT); { /* general path */ @@ -2558,7 +2558,7 @@ _mesa_texstore_s8_z24(TEXSTORE_PARAMS) GLuint *depth; GLubyte *stencil; - ASSERT(dstFormat == MESA_FORMAT_Z24_UNORM_X8_UINT); + ASSERT(dstFormat == MESA_FORMAT_Z24_UNORM_S8_UINT); ASSERT(srcFormat == GL_DEPTH_STENCIL_EXT || srcFormat == GL_DEPTH_COMPONENT || srcFormat == GL_STENCIL_INDEX); @@ -3699,9 +3699,9 @@ _mesa_get_texstore_func(mesa_format format) table[MESA_FORMAT_G16R16_UNORM] = _mesa_texstore_unorm1616; table[MESA_FORMAT_B10G10R10A2_UNORM] = _mesa_texstore_argb2101010; table[MESA_FORMAT_S8_UINT_Z24_UNORM] = _mesa_texstore_z24_s8; - table[MESA_FORMAT_Z24_UNORM_X8_UINT] = _mesa_texstore_s8_z24; + table[MESA_FORMAT_Z24_UNORM_S8_UINT] = _mesa_texstore_s8_z24; table[MESA_FORMAT_Z_UNORM16] = _mesa_texstore_z16; - table[MESA_FORMAT_Z24_UNORM_S8_UINT] = _mesa_texstore_x8_z24; + table[MESA_FORMAT_Z24_UNORM_X8_UINT] = _mesa_texstore_x8_z24; table[MESA_FORMAT_X8Z24_UNORM] = _mesa_texstore_z24_x8; table[MESA_FORMAT_Z_UNORM32] = _mesa_texstore_z32; table[MESA_FORMAT_S_UINT8] = _mesa_texstore_s8; diff --git a/mesalib/src/mesa/main/uniform_query.cpp b/mesalib/src/mesa/main/uniform_query.cpp index 82d7628e8..8cc5da752 100644 --- a/mesalib/src/mesa/main/uniform_query.cpp +++ b/mesalib/src/mesa/main/uniform_query.cpp @@ -684,6 +684,7 @@ _mesa_uniform(struct gl_context *ctx, struct gl_shader_program *shProg, match = true; break; case GLSL_TYPE_SAMPLER: + case GLSL_TYPE_IMAGE: match = (basicType == GLSL_TYPE_INT); break; default: @@ -735,6 +736,22 @@ _mesa_uniform(struct gl_context *ctx, struct gl_shader_program *shProg, } } + if (uni->type->is_image()) { + int i; + + for (i = 0; i < count; i++) { + const int unit = ((GLint *) values)[i]; + + /* check that the image unit is legal */ + if (unit < 0 || unit >= (int)ctx->Const.MaxImageUnits) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glUniform1i(invalid image unit index for uniform %d)", + location); + return; + } + } + } + /* Page 82 (page 96 of the PDF) of the OpenGL 2.1 spec says: * * "When loading N elements starting at an arbitrary position k in a @@ -830,6 +847,25 @@ _mesa_uniform(struct gl_context *ctx, struct gl_shader_program *shProg, } } } + + /* If the uniform is an image, update the mapping from image + * uniforms to image units present in the shader data structure. + */ + if (uni->type->is_image()) { + int i, j; + + for (i = 0; i < MESA_SHADER_STAGES; i++) { + if (uni->image[i].active) { + struct gl_shader *sh = shProg->_LinkedShaders[i]; + + for (j = 0; j < count; j++) + sh->ImageUnits[uni->image[i].index + offset + j] = + ((GLint *) values)[j]; + } + } + + ctx->NewDriverState |= ctx->DriverFlags.NewImageUnits; + } } /** diff --git a/mesalib/src/mesa/main/uniforms.c b/mesalib/src/mesa/main/uniforms.c index 071d668f3..c25c2df7e 100644 --- a/mesalib/src/mesa/main/uniforms.c +++ b/mesalib/src/mesa/main/uniforms.c @@ -270,6 +270,197 @@ _mesa_Uniform4iv(GLint location, GLsizei count, const GLint * value) _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_INT_VEC4); } +/** Same as above with direct state access **/ +void GLAPIENTRY +_mesa_ProgramUniform1f(GLuint program, GLint location, GLfloat v0) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_shader_program *shProg = + _mesa_lookup_shader_program_err(ctx, program, + "glProgramUniform1f"); + _mesa_uniform(ctx, shProg, location, 1, &v0, GL_FLOAT); +} + +void GLAPIENTRY +_mesa_ProgramUniform2f(GLuint program, GLint location, GLfloat v0, GLfloat v1) +{ + GET_CURRENT_CONTEXT(ctx); + GLfloat v[2]; + struct gl_shader_program *shProg; + v[0] = v0; + v[1] = v1; + shProg = _mesa_lookup_shader_program_err(ctx, program, "glProgramUniform2f"); + _mesa_uniform(ctx, shProg, location, 1, v, GL_FLOAT_VEC2); +} + +void GLAPIENTRY +_mesa_ProgramUniform3f(GLuint program, GLint location, GLfloat v0, GLfloat v1, + GLfloat v2) +{ + GET_CURRENT_CONTEXT(ctx); + GLfloat v[3]; + struct gl_shader_program *shProg; + v[0] = v0; + v[1] = v1; + v[2] = v2; + shProg = _mesa_lookup_shader_program_err(ctx, program, "glProgramUniform3f"); + _mesa_uniform(ctx, shProg, location, 1, v, GL_FLOAT_VEC3); +} + +void GLAPIENTRY +_mesa_ProgramUniform4f(GLuint program, GLint location, GLfloat v0, GLfloat v1, + GLfloat v2, GLfloat v3) +{ + GET_CURRENT_CONTEXT(ctx); + GLfloat v[4]; + struct gl_shader_program *shProg; + v[0] = v0; + v[1] = v1; + v[2] = v2; + v[3] = v3; + shProg = _mesa_lookup_shader_program_err(ctx, program, "glProgramUniform4f"); + _mesa_uniform(ctx, shProg, location, 1, v, GL_FLOAT_VEC4); +} + +void GLAPIENTRY +_mesa_ProgramUniform1i(GLuint program, GLint location, GLint v0) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_shader_program *shProg = + _mesa_lookup_shader_program_err(ctx, program, + "glProgramUniform1i"); + _mesa_uniform(ctx, shProg, location, 1, &v0, GL_INT); +} + +void GLAPIENTRY +_mesa_ProgramUniform2i(GLuint program, GLint location, GLint v0, GLint v1) +{ + GET_CURRENT_CONTEXT(ctx); + GLint v[2]; + struct gl_shader_program *shProg; + v[0] = v0; + v[1] = v1; + shProg = _mesa_lookup_shader_program_err(ctx, program, "glProgramUniform2i"); + _mesa_uniform(ctx, shProg, location, 1, v, GL_INT_VEC2); +} + +void GLAPIENTRY +_mesa_ProgramUniform3i(GLuint program, GLint location, GLint v0, GLint v1, + GLint v2) +{ + GET_CURRENT_CONTEXT(ctx); + GLint v[3]; + struct gl_shader_program *shProg; + v[0] = v0; + v[1] = v1; + v[2] = v2; + shProg = _mesa_lookup_shader_program_err(ctx, program, "glProgramUniform3i"); + _mesa_uniform(ctx, shProg, location, 1, v, GL_INT_VEC3); +} + +void GLAPIENTRY +_mesa_ProgramUniform4i(GLuint program, GLint location, GLint v0, GLint v1, + GLint v2, GLint v3) +{ + GET_CURRENT_CONTEXT(ctx); + GLint v[4]; + struct gl_shader_program *shProg; + v[0] = v0; + v[1] = v1; + v[2] = v2; + v[3] = v3; + shProg = _mesa_lookup_shader_program_err(ctx, program, "glProgramUniform4i"); + _mesa_uniform(ctx, shProg, location, 1, v, GL_INT_VEC4); +} + +void GLAPIENTRY +_mesa_ProgramUniform1fv(GLuint program, GLint location, GLsizei count, + const GLfloat * value) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_shader_program *shProg = + _mesa_lookup_shader_program_err(ctx, program, + "glProgramUniform1fv"); + _mesa_uniform(ctx, shProg, location, count, value, GL_FLOAT); +} + +void GLAPIENTRY +_mesa_ProgramUniform2fv(GLuint program, GLint location, GLsizei count, + const GLfloat * value) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_shader_program *shProg = + _mesa_lookup_shader_program_err(ctx, program, + "glProgramUniform2fv"); + _mesa_uniform(ctx, shProg, location, count, value, GL_FLOAT_VEC2); +} + +void GLAPIENTRY +_mesa_ProgramUniform3fv(GLuint program, GLint location, GLsizei count, + const GLfloat * value) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_shader_program *shProg = + _mesa_lookup_shader_program_err(ctx, program, + "glProgramUniform3fv"); + _mesa_uniform(ctx, shProg, location, count, value, GL_FLOAT_VEC3); +} + +void GLAPIENTRY +_mesa_ProgramUniform4fv(GLuint program, GLint location, GLsizei count, + const GLfloat * value) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_shader_program *shProg = + _mesa_lookup_shader_program_err(ctx, program, + "glProgramUniform4fv"); + _mesa_uniform(ctx, shProg, location, count, value, GL_FLOAT_VEC4); +} + +void GLAPIENTRY +_mesa_ProgramUniform1iv(GLuint program, GLint location, GLsizei count, + const GLint * value) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_shader_program *shProg = + _mesa_lookup_shader_program_err(ctx, program, + "glProgramUniform1iv"); + _mesa_uniform(ctx, shProg, location, count, value, GL_INT); +} + +void GLAPIENTRY +_mesa_ProgramUniform2iv(GLuint program, GLint location, GLsizei count, + const GLint * value) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_shader_program *shProg = + _mesa_lookup_shader_program_err(ctx, program, + "glProgramUniform2iv"); + _mesa_uniform(ctx, shProg, location, count, value, GL_INT_VEC2); +} + +void GLAPIENTRY +_mesa_ProgramUniform3iv(GLuint program, GLint location, GLsizei count, + const GLint * value) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_shader_program *shProg = + _mesa_lookup_shader_program_err(ctx, program, + "glProgramUniform3iv"); + _mesa_uniform(ctx, shProg, location, count, value, GL_INT_VEC3); +} + +void GLAPIENTRY +_mesa_ProgramUniform4iv(GLuint program, GLint location, GLsizei count, + const GLint * value) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_shader_program *shProg = + _mesa_lookup_shader_program_err(ctx, program, + "glProgramUniform4iv"); + _mesa_uniform(ctx, shProg, location, count, value, GL_INT_VEC4); +} + /** OpenGL 3.0 GLuint-valued functions **/ void GLAPIENTRY @@ -369,6 +560,140 @@ _mesa_UniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, 4, 4, location, count, transpose, value); } +/** Same as above with direct state access **/ + +void GLAPIENTRY +_mesa_ProgramUniform1ui(GLuint program, GLint location, GLuint v0) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_shader_program *shProg = + _mesa_lookup_shader_program_err(ctx, program, + "glProgramUniform1ui"); + _mesa_uniform(ctx, shProg, location, 1, &v0, GL_UNSIGNED_INT); +} + +void GLAPIENTRY +_mesa_ProgramUniform2ui(GLuint program, GLint location, GLuint v0, GLuint v1) +{ + GET_CURRENT_CONTEXT(ctx); + GLuint v[2]; + struct gl_shader_program *shProg; + v[0] = v0; + v[1] = v1; + shProg = _mesa_lookup_shader_program_err(ctx, program, + "glProgramUniform2ui"); + _mesa_uniform(ctx, shProg, location, 1, v, GL_UNSIGNED_INT_VEC2); +} + +void GLAPIENTRY +_mesa_ProgramUniform3ui(GLuint program, GLint location, GLuint v0, GLuint v1, + GLuint v2) +{ + GET_CURRENT_CONTEXT(ctx); + GLuint v[3]; + struct gl_shader_program *shProg; + v[0] = v0; + v[1] = v1; + v[2] = v2; + shProg = _mesa_lookup_shader_program_err(ctx, program, + "glProgramUniform3ui"); + _mesa_uniform(ctx, shProg, location, 1, v, GL_UNSIGNED_INT_VEC3); +} + +void GLAPIENTRY +_mesa_ProgramUniform4ui(GLuint program, GLint location, GLuint v0, GLuint v1, + GLuint v2, GLuint v3) +{ + GET_CURRENT_CONTEXT(ctx); + GLuint v[4]; + struct gl_shader_program *shProg; + v[0] = v0; + v[1] = v1; + v[2] = v2; + v[3] = v3; + shProg = _mesa_lookup_shader_program_err(ctx, program, "glProgramUniform4ui"); + _mesa_uniform(ctx, shProg, location, 1, v, GL_UNSIGNED_INT_VEC4); +} + +void GLAPIENTRY +_mesa_ProgramUniform1uiv(GLuint program, GLint location, GLsizei count, + const GLuint *value) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_shader_program *shProg = + _mesa_lookup_shader_program_err(ctx, program, + "glProgramUniform1uiv"); + _mesa_uniform(ctx, shProg, location, count, value, GL_UNSIGNED_INT); +} + +void GLAPIENTRY +_mesa_ProgramUniform2uiv(GLuint program, GLint location, GLsizei count, + const GLuint *value) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_shader_program *shProg = + _mesa_lookup_shader_program_err(ctx, program, + "glProgramUniform2uiv"); + _mesa_uniform(ctx, shProg, location, count, value, GL_UNSIGNED_INT_VEC2); +} + +void GLAPIENTRY +_mesa_ProgramUniform3uiv(GLuint program, GLint location, GLsizei count, + const GLuint *value) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_shader_program *shProg = + _mesa_lookup_shader_program_err(ctx, program, + "glProgramUniform3uiv"); + _mesa_uniform(ctx, shProg, location, count, value, GL_UNSIGNED_INT_VEC3); +} + +void GLAPIENTRY +_mesa_ProgramUniform4uiv(GLuint program, GLint location, GLsizei count, + const GLuint *value) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_shader_program *shProg = + _mesa_lookup_shader_program_err(ctx, program, + "glProgramUniform4uiv"); + _mesa_uniform(ctx, shProg, location, count, value, GL_UNSIGNED_INT_VEC4); +} + + + +void GLAPIENTRY +_mesa_ProgramUniformMatrix2fv(GLuint program, GLint location, GLsizei count, + GLboolean transpose, const GLfloat * value) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_shader_program *shProg = + _mesa_lookup_shader_program_err(ctx, program, + "glProgramUniformMatrix2fv"); + _mesa_uniform_matrix(ctx, shProg, 2, 2, location, count, transpose, value); +} + +void GLAPIENTRY +_mesa_ProgramUniformMatrix3fv(GLuint program, GLint location, GLsizei count, + GLboolean transpose, const GLfloat * value) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_shader_program *shProg = + _mesa_lookup_shader_program_err(ctx, program, + "glProgramUniformMatrix3fv"); + _mesa_uniform_matrix(ctx, shProg, 3, 3, location, count, transpose, value); +} + +void GLAPIENTRY +_mesa_ProgramUniformMatrix4fv(GLuint program, GLint location, GLsizei count, + GLboolean transpose, const GLfloat * value) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_shader_program *shProg = + _mesa_lookup_shader_program_err(ctx, program, + "glProgramUniformMatrix4fv"); + _mesa_uniform_matrix(ctx, shProg, 4, 4, location, count, transpose, value); +} + /** * Non-square UniformMatrix are OpenGL 2.1 @@ -427,6 +752,74 @@ _mesa_UniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, 4, 3, location, count, transpose, value); } +/** Same as above with direct state access **/ + +void GLAPIENTRY +_mesa_ProgramUniformMatrix2x3fv(GLuint program, GLint location, GLsizei count, + GLboolean transpose, const GLfloat * value) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_shader_program *shProg = + _mesa_lookup_shader_program_err(ctx, program, + "glProgramUniformMatrix2x3fv"); + _mesa_uniform_matrix(ctx, shProg, 2, 3, location, count, transpose, value); +} + +void GLAPIENTRY +_mesa_ProgramUniformMatrix3x2fv(GLuint program, GLint location, GLsizei count, + GLboolean transpose, const GLfloat * value) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_shader_program *shProg = + _mesa_lookup_shader_program_err(ctx, program, + "glProgramUniformMatrix3x2fv"); + _mesa_uniform_matrix(ctx, shProg, 3, 2, location, count, transpose, value); +} + +void GLAPIENTRY +_mesa_ProgramUniformMatrix2x4fv(GLuint program, GLint location, GLsizei count, + GLboolean transpose, const GLfloat * value) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_shader_program *shProg = + _mesa_lookup_shader_program_err(ctx, program, + "glProgramUniformMatrix2x4fv"); + _mesa_uniform_matrix(ctx, shProg, 2, 4, location, count, transpose, value); +} + +void GLAPIENTRY +_mesa_ProgramUniformMatrix4x2fv(GLuint program, GLint location, GLsizei count, + GLboolean transpose, const GLfloat * value) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_shader_program *shProg = + _mesa_lookup_shader_program_err(ctx, program, + "glProgramUniformMatrix4x2fv"); + _mesa_uniform_matrix(ctx, shProg, 4, 2, location, count, transpose, value); +} + +void GLAPIENTRY +_mesa_ProgramUniformMatrix3x4fv(GLuint program, GLint location, GLsizei count, + GLboolean transpose, const GLfloat * value) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_shader_program *shProg = + _mesa_lookup_shader_program_err(ctx, program, + "glProgramUniformMatrix3x4fv"); + _mesa_uniform_matrix(ctx, shProg, 3, 4, location, count, transpose, value); +} + +void GLAPIENTRY +_mesa_ProgramUniformMatrix4x3fv(GLuint program, GLint location, GLsizei count, + GLboolean transpose, const GLfloat * value) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_shader_program *shProg = + _mesa_lookup_shader_program_err(ctx, program, + "glProgramUniformMatrix4x3fv"); + _mesa_uniform_matrix(ctx, shProg, 4, 3, location, count, transpose, value); +} + void GLAPIENTRY _mesa_GetnUniformfvARB(GLhandleARB program, GLint location, diff --git a/mesalib/src/mesa/main/uniforms.h b/mesalib/src/mesa/main/uniforms.h index f7cac6328..bd50fd9b8 100644 --- a/mesalib/src/mesa/main/uniforms.h +++ b/mesalib/src/mesa/main/uniforms.h @@ -111,6 +111,89 @@ _mesa_UniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, void GLAPIENTRY _mesa_UniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); + +void GLAPIENTRY +_mesa_ProgramUniform1f(GLuint program, GLint, GLfloat); +void GLAPIENTRY +_mesa_ProgramUniform2f(GLuint program, GLint, GLfloat, GLfloat); +void GLAPIENTRY +_mesa_ProgramUniform3f(GLuint program, GLint, GLfloat, GLfloat, GLfloat); +void GLAPIENTRY +_mesa_ProgramUniform4f(GLuint program, GLint, GLfloat, GLfloat, GLfloat, GLfloat); +void GLAPIENTRY +_mesa_ProgramUniform1i(GLuint program, GLint, GLint); +void GLAPIENTRY +_mesa_ProgramUniform2i(GLuint program, GLint, GLint, GLint); +void GLAPIENTRY +_mesa_ProgramUniform3i(GLuint program, GLint, GLint, GLint, GLint); +void GLAPIENTRY +_mesa_ProgramUniform4i(GLuint program, GLint, GLint, GLint, GLint, GLint); +void GLAPIENTRY +_mesa_ProgramUniform1fv(GLuint program, GLint, GLsizei, const GLfloat *); +void GLAPIENTRY +_mesa_ProgramUniform2fv(GLuint program, GLint, GLsizei, const GLfloat *); +void GLAPIENTRY +_mesa_ProgramUniform3fv(GLuint program, GLint, GLsizei, const GLfloat *); +void GLAPIENTRY +_mesa_ProgramUniform4fv(GLuint program, GLint, GLsizei, const GLfloat *); +void GLAPIENTRY +_mesa_ProgramUniform1iv(GLuint program, GLint, GLsizei, const GLint *); +void GLAPIENTRY +_mesa_ProgramUniform2iv(GLuint program, GLint, GLsizei, const GLint *); +void GLAPIENTRY +_mesa_ProgramUniform3iv(GLuint program, GLint, GLsizei, const GLint *); +void GLAPIENTRY +_mesa_ProgramUniform4iv(GLuint program, GLint, GLsizei, const GLint *); +void GLAPIENTRY +_mesa_ProgramUniform1ui(GLuint program, GLint location, GLuint v0); +void GLAPIENTRY +_mesa_ProgramUniform2ui(GLuint program, GLint location, GLuint v0, GLuint v1); +void GLAPIENTRY +_mesa_ProgramUniform3ui(GLuint program, GLint location, GLuint v0, GLuint v1, + GLuint v2); +void GLAPIENTRY +_mesa_ProgramUniform4ui(GLuint program, GLint location, GLuint v0, GLuint v1, + GLuint v2, GLuint v3); +void GLAPIENTRY +_mesa_ProgramUniform1uiv(GLuint program, GLint location, GLsizei count, + const GLuint *value); +void GLAPIENTRY +_mesa_ProgramUniform2uiv(GLuint program, GLint location, GLsizei count, + const GLuint *value); +void GLAPIENTRY +_mesa_ProgramUniform3uiv(GLuint program, GLint location, GLsizei count, + const GLuint *value); +void GLAPIENTRY +_mesa_ProgramUniform4uiv(GLuint program, GLint location, GLsizei count, + const GLuint *value); +void GLAPIENTRY +_mesa_ProgramUniformMatrix2fv(GLuint program, GLint, GLsizei, GLboolean, + const GLfloat *); +void GLAPIENTRY +_mesa_ProgramUniformMatrix3fv(GLuint program, GLint, GLsizei, GLboolean, + const GLfloat *); +void GLAPIENTRY +_mesa_ProgramUniformMatrix4fv(GLuint program, GLint, GLsizei, GLboolean, + const GLfloat *); +void GLAPIENTRY +_mesa_ProgramUniformMatrix2x3fv(GLuint program, GLint location, GLsizei count, + GLboolean transpose, const GLfloat *value); +void GLAPIENTRY +_mesa_ProgramUniformMatrix3x2fv(GLuint program, GLint location, GLsizei count, + GLboolean transpose, const GLfloat *value); +void GLAPIENTRY +_mesa_ProgramUniformMatrix2x4fv(GLuint program, GLint location, GLsizei count, + GLboolean transpose, const GLfloat *value); +void GLAPIENTRY +_mesa_ProgramUniformMatrix4x2fv(GLuint program, GLint location, GLsizei count, + GLboolean transpose, const GLfloat *value); +void GLAPIENTRY +_mesa_ProgramUniformMatrix3x4fv(GLuint program, GLint location, GLsizei count, + GLboolean transpose, const GLfloat *value); +void GLAPIENTRY +_mesa_ProgramUniformMatrix4x3fv(GLuint program, GLint location, GLsizei count, + GLboolean transpose, const GLfloat *value); + void GLAPIENTRY _mesa_GetnUniformfvARB(GLhandleARB, GLint, GLsizei, GLfloat *); void GLAPIENTRY diff --git a/mesalib/src/mesa/main/vdpau.c b/mesalib/src/mesa/main/vdpau.c index 359757607..c2cf20664 100644 --- a/mesalib/src/mesa/main/vdpau.c +++ b/mesalib/src/mesa/main/vdpau.c @@ -205,7 +205,7 @@ _mesa_VDPAURegisterOutputSurfaceNV(const GLvoid *vdpSurface, GLenum target, numTextureNames, textureNames); } -void GLAPIENTRY +GLboolean GLAPIENTRY _mesa_VDPAUIsSurfaceNV(GLintptr surface) { struct vdp_surface *surf = (struct vdp_surface *)surface; @@ -213,13 +213,14 @@ _mesa_VDPAUIsSurfaceNV(GLintptr surface) if (!ctx->vdpDevice || !ctx->vdpGetProcAddress || !ctx->vdpSurfaces) { _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUIsSurfaceNV"); - return; + return false; } if (!_mesa_set_search(ctx->vdpSurfaces, _mesa_hash_pointer(surf), surf)) { - _mesa_error(ctx, GL_INVALID_VALUE, "VDPAUIsSurfaceNV"); - return; + return false; } + + return true; } void GLAPIENTRY diff --git a/mesalib/src/mesa/main/vdpau.h b/mesalib/src/mesa/main/vdpau.h index f32d6dacb..627609c50 100644 --- a/mesalib/src/mesa/main/vdpau.h +++ b/mesalib/src/mesa/main/vdpau.h @@ -50,7 +50,7 @@ _mesa_VDPAURegisterOutputSurfaceNV(const GLvoid *vdpSurface, GLenum target, GLsizei numTextureNames, const GLuint *textureNames); -extern void GLAPIENTRY +extern GLboolean GLAPIENTRY _mesa_VDPAUIsSurfaceNV(GLintptr surface); extern void GLAPIENTRY diff --git a/mesalib/src/mesa/main/version.c b/mesalib/src/mesa/main/version.c index 9af5f091e..1c0bedf4b 100644 --- a/mesalib/src/mesa/main/version.c +++ b/mesalib/src/mesa/main/version.c @@ -232,7 +232,6 @@ compute_version(struct gl_context *ctx) (ctx->API == API_OPENGL_CORE || ctx->Extensions.ARB_color_buffer_float) && ctx->Extensions.ARB_depth_buffer_float && - ctx->Extensions.ARB_half_float_pixel && ctx->Extensions.ARB_half_float_vertex && ctx->Extensions.ARB_map_buffer_range && ctx->Extensions.ARB_shader_texture_lod && diff --git a/mesalib/src/mesa/program/ir_to_mesa.cpp b/mesalib/src/mesa/program/ir_to_mesa.cpp index 74c512b33..9919874a6 100644 --- a/mesalib/src/mesa/program/ir_to_mesa.cpp +++ b/mesalib/src/mesa/program/ir_to_mesa.cpp @@ -618,6 +618,7 @@ type_size(const struct glsl_type *type) } return size; case GLSL_TYPE_SAMPLER: + case GLSL_TYPE_IMAGE: /* Samplers take up one slot in UNIFORMS[], but they're baked in * at link time. */ @@ -2559,6 +2560,7 @@ _mesa_associate_uniform_storage(struct gl_context *ctx, columns = 1; break; case GLSL_TYPE_SAMPLER: + case GLSL_TYPE_IMAGE: format = uniform_native; columns = 1; break; @@ -2916,16 +2918,17 @@ get_mesa_program(struct gl_context *ctx, set_branchtargets(&v, mesa_instructions, num_instructions); if (ctx->Shader.Flags & GLSL_DUMP) { - printf("\n"); - printf("GLSL IR for linked %s program %d:\n", target_string, - shader_program->Name); - _mesa_print_ir(shader->ir, NULL); - printf("\n"); - printf("\n"); - printf("Mesa IR for linked %s program %d:\n", target_string, - shader_program->Name); + fprintf(stderr, "\n"); + fprintf(stderr, "GLSL IR for linked %s program %d:\n", target_string, + shader_program->Name); + _mesa_print_ir(stderr, shader->ir, NULL); + fprintf(stderr, "\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "Mesa IR for linked %s program %d:\n", target_string, + shader_program->Name); print_program(mesa_instructions, mesa_instruction_annotation, num_instructions); + fflush(stderr); } prog->Instructions = mesa_instructions; @@ -3095,12 +3098,12 @@ _mesa_glsl_link_shader(struct gl_context *ctx, struct gl_shader_program *prog) if (ctx->Shader.Flags & GLSL_DUMP) { if (!prog->LinkStatus) { - printf("GLSL shader program %d failed to link\n", prog->Name); + fprintf(stderr, "GLSL shader program %d failed to link\n", prog->Name); } if (prog->InfoLog && prog->InfoLog[0] != 0) { - printf("GLSL shader program %d info log:\n", prog->Name); - printf("%s\n", prog->InfoLog); + fprintf(stderr, "GLSL shader program %d info log:\n", prog->Name); + fprintf(stderr, "%s\n", prog->InfoLog); } } } diff --git a/mesalib/src/mesa/program/program.c b/mesalib/src/mesa/program/program.c index fa80bc58c..b7332fccf 100644 --- a/mesalib/src/mesa/program/program.c +++ b/mesalib/src/mesa/program/program.c @@ -424,7 +424,7 @@ _mesa_reference_program_(struct gl_context *ctx, if (*ptr) { GLboolean deleteFlag; - /*_glthread_LOCK_MUTEX((*ptr)->Mutex);*/ + /*mtx_lock(&(*ptr)->Mutex);*/ #if 0 printf("Program %p ID=%u Target=%s Refcount-- to %d\n", *ptr, (*ptr)->Id, @@ -436,7 +436,7 @@ _mesa_reference_program_(struct gl_context *ctx, (*ptr)->RefCount--; deleteFlag = ((*ptr)->RefCount == 0); - /*_glthread_UNLOCK_MUTEX((*ptr)->Mutex);*/ + /*mtx_lock(&(*ptr)->Mutex);*/ if (deleteFlag) { ASSERT(ctx); @@ -448,7 +448,7 @@ _mesa_reference_program_(struct gl_context *ctx, assert(!*ptr); if (prog) { - /*_glthread_LOCK_MUTEX(prog->Mutex);*/ + /*mtx_lock(&prog->Mutex);*/ prog->RefCount++; #if 0 printf("Program %p ID=%u Target=%s Refcount++ to %d\n", @@ -457,7 +457,7 @@ _mesa_reference_program_(struct gl_context *ctx, (prog->Target == MESA_GEOMETRY_PROGRAM ? "GP" : "FP")), prog->RefCount); #endif - /*_glthread_UNLOCK_MUTEX(prog->Mutex);*/ + /*mtx_unlock(&prog->Mutex);*/ } *ptr = prog; @@ -550,6 +550,7 @@ _mesa_clone_program(struct gl_context *ctx, const struct gl_program *prog) struct gl_geometry_program *gpc = gl_geometry_program(clone); gpc->VerticesOut = gp->VerticesOut; gpc->InputType = gp->InputType; + gpc->Invocations = gp->Invocations; gpc->OutputType = gp->OutputType; } break; diff --git a/mesalib/src/mesa/state_tracker/st_atom_scissor.c b/mesalib/src/mesa/state_tracker/st_atom_scissor.c index a1f72da47..a19ade1fa 100644 --- a/mesalib/src/mesa/state_tracker/st_atom_scissor.c +++ b/mesalib/src/mesa/state_tracker/st_atom_scissor.c @@ -43,51 +43,56 @@ static void update_scissor( struct st_context *st ) { - struct pipe_scissor_state scissor; + struct pipe_scissor_state scissor[PIPE_MAX_VIEWPORTS]; const struct gl_context *ctx = st->ctx; const struct gl_framebuffer *fb = ctx->DrawBuffer; GLint miny, maxy; + int i; + bool changed = false; + for (i = 0 ; i < ctx->Const.MaxViewports; i++) { + scissor[i].minx = 0; + scissor[i].miny = 0; + scissor[i].maxx = fb->Width; + scissor[i].maxy = fb->Height; - scissor.minx = 0; - scissor.miny = 0; - scissor.maxx = fb->Width; - scissor.maxy = fb->Height; + if (ctx->Scissor.EnableFlags & (1 << i)) { + /* need to be careful here with xmax or ymax < 0 */ + GLint xmax = MAX2(0, ctx->Scissor.ScissorArray[i].X + ctx->Scissor.ScissorArray[i].Width); + GLint ymax = MAX2(0, ctx->Scissor.ScissorArray[i].Y + ctx->Scissor.ScissorArray[i].Height); - if (ctx->Scissor.EnableFlags & 1) { - /* need to be careful here with xmax or ymax < 0 */ - GLint xmax = MAX2(0, ctx->Scissor.ScissorArray[0].X + ctx->Scissor.ScissorArray[0].Width); - GLint ymax = MAX2(0, ctx->Scissor.ScissorArray[0].Y + ctx->Scissor.ScissorArray[0].Height); + if (ctx->Scissor.ScissorArray[i].X > (GLint)scissor[i].minx) + scissor[i].minx = ctx->Scissor.ScissorArray[i].X; + if (ctx->Scissor.ScissorArray[i].Y > (GLint)scissor[i].miny) + scissor[i].miny = ctx->Scissor.ScissorArray[i].Y; - if (ctx->Scissor.ScissorArray[0].X > (GLint)scissor.minx) - scissor.minx = ctx->Scissor.ScissorArray[0].X; - if (ctx->Scissor.ScissorArray[0].Y > (GLint)scissor.miny) - scissor.miny = ctx->Scissor.ScissorArray[0].Y; + if (xmax < (GLint) scissor[i].maxx) + scissor[i].maxx = xmax; + if (ymax < (GLint) scissor[i].maxy) + scissor[i].maxy = ymax; + + /* check for null space */ + if (scissor[i].minx >= scissor[i].maxx || scissor[i].miny >= scissor[i].maxy) + scissor[i].minx = scissor[i].miny = scissor[i].maxx = scissor[i].maxy = 0; + } - if (xmax < (GLint) scissor.maxx) - scissor.maxx = xmax; - if (ymax < (GLint) scissor.maxy) - scissor.maxy = ymax; + /* Now invert Y if needed. + * Gallium drivers use the convention Y=0=top for surfaces. + */ + if (st_fb_orientation(fb) == Y_0_TOP) { + miny = fb->Height - scissor[i].maxy; + maxy = fb->Height - scissor[i].miny; + scissor[i].miny = miny; + scissor[i].maxy = maxy; + } - /* check for null space */ - if (scissor.minx >= scissor.maxx || scissor.miny >= scissor.maxy) - scissor.minx = scissor.miny = scissor.maxx = scissor.maxy = 0; - } - - /* Now invert Y if needed. - * Gallium drivers use the convention Y=0=top for surfaces. - */ - if (st_fb_orientation(fb) == Y_0_TOP) { - miny = fb->Height - scissor.maxy; - maxy = fb->Height - scissor.miny; - scissor.miny = miny; - scissor.maxy = maxy; - } - - if (memcmp(&scissor, &st->state.scissor, sizeof(scissor)) != 0) { - /* state has changed */ - st->state.scissor = scissor; /* struct copy */ - st->pipe->set_scissor_states(st->pipe, 0, 1, &scissor); /* activate */ + if (memcmp(&scissor[i], &st->state.scissor[i], sizeof(scissor)) != 0) { + /* state has changed */ + st->state.scissor[i] = scissor[i]; /* struct copy */ + changed = true; + } } + if (changed) + st->pipe->set_scissor_states(st->pipe, 0, ctx->Const.MaxViewports, scissor); /* activate */ } diff --git a/mesalib/src/mesa/state_tracker/st_atom_viewport.c b/mesalib/src/mesa/state_tracker/st_atom_viewport.c index 8c6d679a0..7584f9b3d 100644 --- a/mesalib/src/mesa/state_tracker/st_atom_viewport.c +++ b/mesalib/src/mesa/state_tracker/st_atom_viewport.c @@ -43,7 +43,7 @@ update_viewport( struct st_context *st ) { struct gl_context *ctx = st->ctx; GLfloat yScale, yBias; - + int i; /* _NEW_BUFFERS */ if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) { @@ -61,26 +61,29 @@ update_viewport( struct st_context *st ) /* _NEW_VIEWPORT */ + for (i = 0; i < ctx->Const.MaxViewports; i++) { - GLfloat x = ctx->ViewportArray[0].X; - GLfloat y = ctx->ViewportArray[0].Y; - GLfloat z = ctx->ViewportArray[0].Near; - GLfloat half_width = ctx->ViewportArray[0].Width * 0.5f; - GLfloat half_height = ctx->ViewportArray[0].Height * 0.5f; - GLfloat half_depth = (GLfloat)(ctx->ViewportArray[0].Far - ctx->ViewportArray[0].Near) * 0.5f; + GLfloat x = ctx->ViewportArray[i].X; + GLfloat y = ctx->ViewportArray[i].Y; + GLfloat z = ctx->ViewportArray[i].Near; + GLfloat half_width = ctx->ViewportArray[i].Width * 0.5f; + GLfloat half_height = ctx->ViewportArray[i].Height * 0.5f; + GLfloat half_depth = (GLfloat)(ctx->ViewportArray[i].Far - ctx->ViewportArray[i].Near) * 0.5f; - st->state.viewport.scale[0] = half_width; - st->state.viewport.scale[1] = half_height * yScale; - st->state.viewport.scale[2] = half_depth; - st->state.viewport.scale[3] = 1.0; - - st->state.viewport.translate[0] = half_width + x; - st->state.viewport.translate[1] = (half_height + y) * yScale + yBias; - st->state.viewport.translate[2] = half_depth + z; - st->state.viewport.translate[3] = 0.0; + st->state.viewport[i].scale[0] = half_width; + st->state.viewport[i].scale[1] = half_height * yScale; + st->state.viewport[i].scale[2] = half_depth; + st->state.viewport[i].scale[3] = 1.0; - cso_set_viewport(st->cso_context, &st->state.viewport); + st->state.viewport[i].translate[0] = half_width + x; + st->state.viewport[i].translate[1] = (half_height + y) * yScale + yBias; + st->state.viewport[i].translate[2] = half_depth + z; + st->state.viewport[i].translate[3] = 0.0; } + + cso_set_viewport(st->cso_context, &st->state.viewport[0]); + if (ctx->Const.MaxViewports > 1) + st->pipe->set_viewport_states(st->pipe, 1, ctx->Const.MaxViewports - 1, &st->state.viewport[1]); } diff --git a/mesalib/src/mesa/state_tracker/st_cb_bufferobjects.c b/mesalib/src/mesa/state_tracker/st_cb_bufferobjects.c index c8f088dc8..49c4b903e 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_bufferobjects.c +++ b/mesalib/src/mesa/state_tracker/st_cb_bufferobjects.c @@ -76,7 +76,7 @@ st_bufferobj_free(struct gl_context *ctx, struct gl_buffer_object *obj) struct st_buffer_object *st_obj = st_buffer_object(obj); assert(obj->RefCount == 0); - assert(st_obj->transfer == NULL); + _mesa_buffer_unmap_all_mappings(ctx, obj); if (st_obj->buffer) pipe_resource_reference(&st_obj->buffer, NULL); @@ -176,15 +176,18 @@ st_bufferobj_data(struct gl_context *ctx, GLsizeiptrARB size, const GLvoid * data, GLenum usage, + GLbitfield storageFlags, struct gl_buffer_object *obj) { struct st_context *st = st_context(ctx); struct pipe_context *pipe = st->pipe; struct st_buffer_object *st_obj = st_buffer_object(obj); - unsigned bind, pipe_usage; + unsigned bind, pipe_usage, pipe_flags = 0; if (size && data && st_obj->buffer && - st_obj->Base.Size == size && st_obj->Base.Usage == usage) { + st_obj->Base.Size == size && + st_obj->Base.Usage == usage && + st_obj->Base.StorageFlags == storageFlags) { /* Just discard the old contents and write new data. * This should be the same as creating a new buffer, but we avoid * a lot of validation in Mesa. @@ -200,6 +203,7 @@ st_bufferobj_data(struct gl_context *ctx, st_obj->Base.Size = size; st_obj->Base.Usage = usage; + st_obj->Base.StorageFlags = storageFlags; switch (target) { case GL_PIXEL_PACK_BUFFER_ARB: @@ -225,24 +229,41 @@ st_bufferobj_data(struct gl_context *ctx, bind = 0; } - switch (usage) { - case GL_STATIC_DRAW: - case GL_STATIC_READ: - case GL_STATIC_COPY: - default: - pipe_usage = PIPE_USAGE_DEFAULT; - break; - case GL_DYNAMIC_DRAW: - case GL_DYNAMIC_READ: - case GL_DYNAMIC_COPY: - pipe_usage = PIPE_USAGE_DYNAMIC; - break; - case GL_STREAM_DRAW: - case GL_STREAM_READ: - case GL_STREAM_COPY: - pipe_usage = PIPE_USAGE_STREAM; - break; + /* Set usage. */ + if (st_obj->Base.Immutable) { + /* BufferStorage */ + if (storageFlags & GL_CLIENT_STORAGE_BIT) + pipe_usage = PIPE_USAGE_STAGING; + else + pipe_usage = PIPE_USAGE_DEFAULT; } + else { + /* BufferData */ + switch (usage) { + case GL_STATIC_DRAW: + case GL_STATIC_READ: + case GL_STATIC_COPY: + default: + pipe_usage = PIPE_USAGE_DEFAULT; + break; + case GL_DYNAMIC_DRAW: + case GL_DYNAMIC_READ: + case GL_DYNAMIC_COPY: + pipe_usage = PIPE_USAGE_DYNAMIC; + break; + case GL_STREAM_DRAW: + case GL_STREAM_READ: + case GL_STREAM_COPY: + pipe_usage = PIPE_USAGE_STREAM; + break; + } + } + + /* Set flags. */ + if (storageFlags & GL_MAP_PERSISTENT_BIT) + pipe_flags |= PIPE_RESOURCE_FLAG_MAP_PERSISTENT; + if (storageFlags & GL_MAP_COHERENT_BIT) + pipe_flags |= PIPE_RESOURCE_FLAG_MAP_COHERENT; pipe_resource_reference( &st_obj->buffer, NULL ); @@ -251,8 +272,20 @@ st_bufferobj_data(struct gl_context *ctx, } if (size != 0) { - st_obj->buffer = pipe_buffer_create(pipe->screen, bind, - pipe_usage, 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 = pipe_usage; + buffer.flags = pipe_flags; + buffer.width0 = size; + buffer.height0 = 1; + buffer.depth0 = 1; + buffer.array_size = 1; + + st_obj->buffer = pipe->screen->resource_create(pipe->screen, &buffer); if (!st_obj->buffer) { /* out of memory */ @@ -277,7 +310,8 @@ st_bufferobj_data(struct gl_context *ctx, static void * st_bufferobj_map_range(struct gl_context *ctx, GLintptr offset, GLsizeiptr length, GLbitfield access, - struct gl_buffer_object *obj) + struct gl_buffer_object *obj, + gl_map_buffer_index index) { struct pipe_context *pipe = st_context(ctx)->pipe; struct st_buffer_object *st_obj = st_buffer_object(obj); @@ -305,6 +339,12 @@ st_bufferobj_map_range(struct gl_context *ctx, if (access & GL_MAP_UNSYNCHRONIZED_BIT) flags |= PIPE_TRANSFER_UNSYNCHRONIZED; + if (access & GL_MAP_PERSISTENT_BIT) + flags |= PIPE_TRANSFER_PERSISTENT; + + if (access & GL_MAP_COHERENT_BIT) + flags |= PIPE_TRANSFER_COHERENT; + /* ... other flags ... */ @@ -316,28 +356,29 @@ st_bufferobj_map_range(struct gl_context *ctx, assert(offset < obj->Size); assert(offset + length <= obj->Size); - obj->Pointer = pipe_buffer_map_range(pipe, + obj->Mappings[index].Pointer = pipe_buffer_map_range(pipe, st_obj->buffer, offset, length, flags, - &st_obj->transfer); - if (obj->Pointer) { - obj->Offset = offset; - obj->Length = length; - obj->AccessFlags = access; + &st_obj->transfer[index]); + if (obj->Mappings[index].Pointer) { + obj->Mappings[index].Offset = offset; + obj->Mappings[index].Length = length; + obj->Mappings[index].AccessFlags = access; } else { - st_obj->transfer = NULL; + st_obj->transfer[index] = NULL; } - return obj->Pointer; + return obj->Mappings[index].Pointer; } static void st_bufferobj_flush_mapped_range(struct gl_context *ctx, GLintptr offset, GLsizeiptr length, - struct gl_buffer_object *obj) + struct gl_buffer_object *obj, + gl_map_buffer_index index) { struct pipe_context *pipe = st_context(ctx)->pipe; struct st_buffer_object *st_obj = st_buffer_object(obj); @@ -345,14 +386,15 @@ st_bufferobj_flush_mapped_range(struct gl_context *ctx, /* Subrange is relative to mapped range */ assert(offset >= 0); assert(length >= 0); - assert(offset + length <= obj->Length); - assert(obj->Pointer); + assert(offset + length <= obj->Mappings[index].Length); + assert(obj->Mappings[index].Pointer); if (!length) return; - pipe_buffer_flush_mapped_range(pipe, st_obj->transfer, - obj->Offset + offset, length); + pipe_buffer_flush_mapped_range(pipe, st_obj->transfer[index], + obj->Mappings[index].Offset + offset, + length); } @@ -360,18 +402,19 @@ st_bufferobj_flush_mapped_range(struct gl_context *ctx, * Called via glUnmapBufferARB(). */ static GLboolean -st_bufferobj_unmap(struct gl_context *ctx, struct gl_buffer_object *obj) +st_bufferobj_unmap(struct gl_context *ctx, struct gl_buffer_object *obj, + gl_map_buffer_index index) { struct pipe_context *pipe = st_context(ctx)->pipe; struct st_buffer_object *st_obj = st_buffer_object(obj); - if (obj->Length) - pipe_buffer_unmap(pipe, st_obj->transfer); + if (obj->Mappings[index].Length) + pipe_buffer_unmap(pipe, st_obj->transfer[index]); - st_obj->transfer = NULL; - obj->Pointer = NULL; - obj->Offset = 0; - obj->Length = 0; + st_obj->transfer[index] = NULL; + obj->Mappings[index].Pointer = NULL; + obj->Mappings[index].Offset = 0; + obj->Mappings[index].Length = 0; return GL_TRUE; } @@ -395,8 +438,8 @@ st_copy_buffer_subdata(struct gl_context *ctx, return; /* buffer should not already be mapped */ - assert(!src->Pointer); - assert(!dst->Pointer); + assert(!_mesa_check_disallowed_mapping(src)); + assert(!_mesa_check_disallowed_mapping(dst)); u_box_1d(readOffset, size, &box); diff --git a/mesalib/src/mesa/state_tracker/st_cb_bufferobjects.h b/mesalib/src/mesa/state_tracker/st_cb_bufferobjects.h index a039c0a50..a5ab12219 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_bufferobjects.h +++ b/mesalib/src/mesa/state_tracker/st_cb_bufferobjects.h @@ -43,7 +43,7 @@ struct st_buffer_object { struct gl_buffer_object Base; struct pipe_resource *buffer; /* GPU storage */ - struct pipe_transfer *transfer; /* In-progress map information */ + struct pipe_transfer *transfer[MAP_COUNT]; }; diff --git a/mesalib/src/mesa/state_tracker/st_cb_texturebarrier.c b/mesalib/src/mesa/state_tracker/st_cb_texturebarrier.c index 2f1a22b58..dd4dde74c 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_texturebarrier.c +++ b/mesalib/src/mesa/state_tracker/st_cb_texturebarrier.c @@ -54,7 +54,24 @@ st_TextureBarrier(struct gl_context *ctx) } +/** + * Called via ctx->Driver.MemoryBarrier() + */ +static void +st_MemoryBarrier(struct gl_context *ctx, GLbitfield barriers) +{ + struct pipe_context *pipe = st_context(ctx)->pipe; + unsigned flags = 0; + + if (barriers & GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT) + flags |= PIPE_BARRIER_MAPPED_BUFFER; + + if (flags && pipe->memory_barrier) + pipe->memory_barrier(pipe, flags); +} + void st_init_texture_barrier_functions(struct dd_function_table *functions) { functions->TextureBarrier = st_TextureBarrier; + functions->MemoryBarrier = st_MemoryBarrier; } diff --git a/mesalib/src/mesa/state_tracker/st_context.h b/mesalib/src/mesa/state_tracker/st_context.h index 996e0c6bc..9c699a015 100644 --- a/mesalib/src/mesa/state_tracker/st_context.h +++ b/mesalib/src/mesa/state_tracker/st_context.h @@ -115,8 +115,8 @@ struct st_context unsigned size; } constants[PIPE_SHADER_TYPES]; struct pipe_framebuffer_state framebuffer; - struct pipe_scissor_state scissor; - struct pipe_viewport_state viewport; + struct pipe_scissor_state scissor[PIPE_MAX_VIEWPORTS]; + struct pipe_viewport_state viewport[PIPE_MAX_VIEWPORTS]; unsigned sample_mask; GLuint poly_stipple[32]; /**< In OpenGL's bottom-to-top order */ diff --git a/mesalib/src/mesa/state_tracker/st_draw_feedback.c b/mesalib/src/mesa/state_tracker/st_draw_feedback.c index 09cd9511d..177f6b5ae 100644 --- a/mesalib/src/mesa/state_tracker/st_draw_feedback.c +++ b/mesalib/src/mesa/state_tracker/st_draw_feedback.c @@ -156,7 +156,7 @@ st_feedback_draw_vbo(struct gl_context *ctx, * code sends state updates to the pipe, not to our private draw module. */ assert(draw); - draw_set_viewport_states(draw, 0, 1, &st->state.viewport); + draw_set_viewport_states(draw, 0, 1, &st->state.viewport[0]); draw_set_clip_state(draw, &st->state.clip); draw_set_rasterizer_state(draw, &st->state.rasterizer, NULL); draw_bind_vertex_shader(draw, st->vp_variant->draw_shader); diff --git a/mesalib/src/mesa/state_tracker/st_extensions.c b/mesalib/src/mesa/state_tracker/st_extensions.c index 9829eb596..18ddd4e47 100644 --- a/mesalib/src/mesa/state_tracker/st_extensions.c +++ b/mesalib/src/mesa/state_tracker/st_extensions.c @@ -39,6 +39,12 @@ #include "st_extensions.h" #include "st_format.h" + +/* + * Note: we use these function rather than the MIN2, MAX2, CLAMP macros to + * avoid evaluating arguments (which are often function calls) more than once. + */ + static unsigned _min(unsigned a, unsigned b) { return (a < b) ? a : b; @@ -262,10 +268,13 @@ void st_init_limits(struct st_context *st) c->Program[MESA_SHADER_VERTEX].MaxOutputComponents = c->MaxVarying * 4; c->Program[MESA_SHADER_GEOMETRY].MaxInputComponents = c->MaxVarying * 4; c->Program[MESA_SHADER_GEOMETRY].MaxOutputComponents = c->MaxVarying * 4; + c->MaxGeometryOutputVertices = screen->get_param(screen, PIPE_CAP_MAX_GEOMETRY_OUTPUT_VERTICES); + c->MaxGeometryTotalOutputComponents = screen->get_param(screen, PIPE_CAP_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS); c->MinProgramTexelOffset = screen->get_param(screen, PIPE_CAP_MIN_TEXEL_OFFSET); c->MaxProgramTexelOffset = screen->get_param(screen, PIPE_CAP_MAX_TEXEL_OFFSET); + c->MaxProgramTextureGatherComponents = screen->get_param(screen, PIPE_CAP_MAX_TEXTURE_GATHER_COMPONENTS); c->UniformBooleanTrue = ~0; c->MaxTransformFeedbackBuffers = @@ -373,6 +382,7 @@ void st_init_extensions(struct st_context *st) static const struct st_extension_cap_mapping cap_mapping[] = { { o(ARB_base_instance), PIPE_CAP_START_INSTANCE }, + { o(ARB_buffer_storage), PIPE_CAP_BUFFER_MAP_PERSISTENT_COHERENT }, { o(ARB_depth_clamp), PIPE_CAP_DEPTH_CLIP_DISABLE }, { o(ARB_depth_texture), PIPE_CAP_TEXTURE_SHADOW_MAP }, { o(ARB_draw_buffers_blend), PIPE_CAP_INDEP_BLEND_FUNC }, @@ -526,7 +536,6 @@ void st_init_extensions(struct st_context *st) ctx->Extensions.ARB_fragment_coord_conventions = GL_TRUE; ctx->Extensions.ARB_fragment_program = GL_TRUE; ctx->Extensions.ARB_fragment_shader = GL_TRUE; - ctx->Extensions.ARB_half_float_pixel = GL_TRUE; ctx->Extensions.ARB_half_float_vertex = GL_TRUE; ctx->Extensions.ARB_internalformat_query = GL_TRUE; ctx->Extensions.ARB_map_buffer_range = GL_TRUE; @@ -777,4 +786,15 @@ void st_init_extensions(struct st_context *st) if (!ctx->Extensions.EXT_transform_feedback) ctx->Const.DisableVaryingPacking = GL_TRUE; } + + if (ctx->API == API_OPENGL_CORE) { + ctx->Const.MaxViewports = screen->get_param(screen, PIPE_CAP_MAX_VIEWPORTS); + if (ctx->Const.MaxViewports >= 16) { + ctx->Const.ViewportBounds.Min = -16384.0; + ctx->Const.ViewportBounds.Max = 16384.0; + ctx->Extensions.ARB_viewport_array = GL_TRUE; + } + } + if (ctx->Const.MaxProgramTextureGatherComponents > 0) + ctx->Extensions.ARB_texture_gather = GL_TRUE; } diff --git a/mesalib/src/mesa/state_tracker/st_format.c b/mesalib/src/mesa/state_tracker/st_format.c index 90e9f2f78..5f951eb02 100644 --- a/mesalib/src/mesa/state_tracker/st_format.c +++ b/mesalib/src/mesa/state_tracker/st_format.c @@ -107,11 +107,11 @@ st_mesa_format_to_pipe_format(mesa_format mesaFormat) return PIPE_FORMAT_Z32_UNORM; case MESA_FORMAT_S8_UINT_Z24_UNORM: return PIPE_FORMAT_S8_UINT_Z24_UNORM; - case MESA_FORMAT_Z24_UNORM_X8_UINT: + case MESA_FORMAT_Z24_UNORM_S8_UINT: return PIPE_FORMAT_Z24_UNORM_S8_UINT; case MESA_FORMAT_X8Z24_UNORM: return PIPE_FORMAT_X8Z24_UNORM; - case MESA_FORMAT_Z24_UNORM_S8_UINT: + case MESA_FORMAT_Z24_UNORM_X8_UINT: return PIPE_FORMAT_Z24X8_UNORM; case MESA_FORMAT_S_UINT8: return PIPE_FORMAT_S8_UINT; @@ -465,9 +465,9 @@ st_pipe_format_to_mesa_format(enum pipe_format format) case PIPE_FORMAT_X8Z24_UNORM: return MESA_FORMAT_X8Z24_UNORM; case PIPE_FORMAT_Z24X8_UNORM: - return MESA_FORMAT_Z24_UNORM_S8_UINT; - case PIPE_FORMAT_Z24_UNORM_S8_UINT: return MESA_FORMAT_Z24_UNORM_X8_UINT; + case PIPE_FORMAT_Z24_UNORM_S8_UINT: + return MESA_FORMAT_Z24_UNORM_S8_UINT; case PIPE_FORMAT_Z32_FLOAT: return MESA_FORMAT_Z_FLOAT32; case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT: 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 610fc68a8..a9e75d8a6 100644 --- a/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp +++ b/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp @@ -87,7 +87,7 @@ extern "C" { */ #define MAX_ARRAYS 256 -/* will be 4 for GLSL 4.00 */ +/* if we support a native gallium TG4 with the ability to take 4 texoffsets then bump this */ #define MAX_GLSL_TEXTURE_OFFSET 1 class st_src_reg; @@ -249,7 +249,8 @@ public: int sampler; /**< sampler index */ int tex_target; /**< One of TEXTURE_*_INDEX */ GLboolean tex_shadow; - struct tgsi_texture_offset tex_offsets[MAX_GLSL_TEXTURE_OFFSET]; + + st_src_reg tex_offsets[MAX_GLSL_TEXTURE_OFFSET]; unsigned tex_offset_num_offset; int dead_mask; /**< Used in dead code elimination */ @@ -983,6 +984,7 @@ type_size(const struct glsl_type *type) } return size; case GLSL_TYPE_SAMPLER: + case GLSL_TYPE_IMAGE: /* Samplers take up one slot in UNIFORMS[], but they're baked in * at link time. */ @@ -2685,7 +2687,7 @@ glsl_to_tgsi_visitor::visit(ir_call *ir) void glsl_to_tgsi_visitor::visit(ir_texture *ir) { - st_src_reg result_src, coord, cube_sc, lod_info, projector, dx, dy, offset, sample_index; + st_src_reg result_src, coord, cube_sc, lod_info, projector, dx, dy, offset, sample_index, component; st_dst_reg result_dst, coord_dst, cube_sc_dst; glsl_to_tgsi_instruction *inst = NULL; unsigned opcode = TGSI_OPCODE_NOP; @@ -2779,12 +2781,20 @@ glsl_to_tgsi_visitor::visit(ir_texture *ir) ir->lod_info.sample_index->accept(this); sample_index = this->result; break; + case ir_tg4: + opcode = TGSI_OPCODE_TG4; + ir->lod_info.component->accept(this); + component = this->result; + if (ir->offset) { + ir->offset->accept(this); + /* this should have been lowered */ + assert(ir->offset->type->base_type != GLSL_TYPE_ARRAY); + offset = this->result; + } + break; case ir_lod: assert(!"Unexpected ir_lod opcode"); break; - case ir_tg4: - assert(!"Unexpected ir_tg4 opcode"); - break; case ir_query_levels: assert(!"Unexpected ir_query_levels opcode"); break; @@ -2892,7 +2902,13 @@ glsl_to_tgsi_visitor::visit(ir_texture *ir) inst = emit(ir, opcode, result_dst, coord, lod_info); } else if (opcode == TGSI_OPCODE_TEX2) { inst = emit(ir, opcode, result_dst, coord, cube_sc); - } else + } else if (opcode == TGSI_OPCODE_TG4) { + if (is_cube_array && ir->shadow_comparitor) { + inst = emit(ir, opcode, result_dst, coord, cube_sc); + } else { + inst = emit(ir, opcode, result_dst, coord, component); + } + } else inst = emit(ir, opcode, result_dst, coord); if (ir->shadow_comparitor) @@ -2903,12 +2919,8 @@ glsl_to_tgsi_visitor::visit(ir_texture *ir) this->prog); if (ir->offset) { - inst->tex_offset_num_offset = 1; - inst->tex_offsets[0].Index = offset.index; - inst->tex_offsets[0].File = offset.file; - inst->tex_offsets[0].SwizzleX = GET_SWZ(offset.swizzle, 0); - inst->tex_offsets[0].SwizzleY = GET_SWZ(offset.swizzle, 1); - inst->tex_offsets[0].SwizzleZ = GET_SWZ(offset.swizzle, 2); + inst->tex_offset_num_offset = 1; + inst->tex_offsets[0] = offset; } switch (sampler_type->sampler_dimensionality) { @@ -3266,6 +3278,13 @@ glsl_to_tgsi_visitor::rename_temp_register(int index, int new_index) inst->src[j].index = new_index; } } + + for (j=0; j < inst->tex_offset_num_offset; j++) { + if (inst->tex_offsets[j].file == PROGRAM_TEMPORARY && + inst->tex_offsets[j].index == index) { + inst->tex_offsets[j].index = new_index; + } + } if (inst->dst.file == PROGRAM_TEMPORARY && inst->dst.index == index) { inst->dst.index = new_index; @@ -3289,6 +3308,12 @@ glsl_to_tgsi_visitor::get_first_temp_read(int index) return (depth == 0) ? i : loop_start; } } + for (j=0; j < inst->tex_offset_num_offset; j++) { + if (inst->tex_offsets[j].file == PROGRAM_TEMPORARY && + inst->tex_offsets[j].index == index) { + return (depth == 0) ? i : loop_start; + } + } if (inst->op == TGSI_OPCODE_BGNLOOP) { if(depth++ == 0) @@ -3350,6 +3375,11 @@ glsl_to_tgsi_visitor::get_last_temp_read(int index) last = (depth == 0) ? i : -2; } } + for (j=0; j < inst->tex_offset_num_offset; j++) { + if (inst->tex_offsets[j].file == PROGRAM_TEMPORARY && + inst->tex_offsets[j].index == index) + last = (depth == 0) ? i : -2; + } if (inst->op == TGSI_OPCODE_BGNLOOP) depth++; @@ -3726,6 +3756,26 @@ glsl_to_tgsi_visitor::eliminate_dead_code_advanced(void) } } } + for (unsigned i = 0; i < inst->tex_offset_num_offset; i++) { + if (inst->tex_offsets[i].file == PROGRAM_TEMPORARY && inst->tex_offsets[i].reladdr){ + /* Any temporary might be read, so no dead code elimination + * across this instruction. + */ + memset(writes, 0, sizeof(*writes) * this->next_temp * 4); + } else if (inst->tex_offsets[i].file == PROGRAM_TEMPORARY) { + /* Clear where it's used as src. */ + int src_chans = 1 << GET_SWZ(inst->tex_offsets[i].swizzle, 0); + src_chans |= 1 << GET_SWZ(inst->tex_offsets[i].swizzle, 1); + src_chans |= 1 << GET_SWZ(inst->tex_offsets[i].swizzle, 2); + src_chans |= 1 << GET_SWZ(inst->tex_offsets[i].swizzle, 3); + + for (int c = 0; c < 4; c++) { + if (src_chans & (1 << c)) { + writes[4 * inst->tex_offsets[i].index + c] = NULL; + } + } + } + } break; } @@ -4079,7 +4129,7 @@ struct st_translate { struct ureg_dst address[2]; struct ureg_src samplers[PIPE_MAX_SAMPLERS]; struct ureg_src systemValues[SYSTEM_VALUE_MAX]; - + struct tgsi_texture_offset tex_offsets[MAX_GLSL_TEXTURE_OFFSET]; unsigned array_sizes[MAX_ARRAYS]; const GLuint *inputMapping; @@ -4379,22 +4429,34 @@ translate_src(struct st_translate *t, const st_src_reg *src_reg) static struct tgsi_texture_offset translate_tex_offset(struct st_translate *t, - const struct tgsi_texture_offset *in_offset) + const st_src_reg *in_offset, int idx) { struct tgsi_texture_offset offset; struct ureg_src imm_src; - assert(in_offset->File == PROGRAM_IMMEDIATE); - imm_src = t->immediates[in_offset->Index]; - - offset.File = imm_src.File; - offset.Index = imm_src.Index; - offset.SwizzleX = imm_src.SwizzleX; - offset.SwizzleY = imm_src.SwizzleY; - offset.SwizzleZ = imm_src.SwizzleZ; - offset.File = TGSI_FILE_IMMEDIATE; - offset.Padding = 0; - + switch (in_offset->file) { + case PROGRAM_IMMEDIATE: + imm_src = t->immediates[in_offset->index]; + + offset.File = imm_src.File; + offset.Index = imm_src.Index; + offset.SwizzleX = imm_src.SwizzleX; + offset.SwizzleY = imm_src.SwizzleY; + offset.SwizzleZ = imm_src.SwizzleZ; + offset.Padding = 0; + break; + case PROGRAM_TEMPORARY: + imm_src = ureg_src(t->temps[in_offset->index]); + offset.File = imm_src.File; + offset.Index = imm_src.Index; + offset.SwizzleX = GET_SWZ(in_offset->swizzle, 0); + offset.SwizzleY = GET_SWZ(in_offset->swizzle, 1); + offset.SwizzleZ = GET_SWZ(in_offset->swizzle, 2); + offset.Padding = 0; + break; + default: + break; + } return offset; } @@ -4450,9 +4512,10 @@ compile_tgsi_instruction(struct st_translate *t, case TGSI_OPCODE_TEX2: case TGSI_OPCODE_TXB2: case TGSI_OPCODE_TXL2: + case TGSI_OPCODE_TG4: src[num_src++] = t->samplers[inst->sampler]; for (i = 0; i < inst->tex_offset_num_offset; i++) { - texoffsets[i] = translate_tex_offset(t, &inst->tex_offsets[i]); + texoffsets[i] = translate_tex_offset(t, &inst->tex_offsets[i], i); } tex_target = st_translate_texture_target(inst->tex_target, inst->tex_shadow); @@ -5140,7 +5203,7 @@ get_mesa_program(struct gl_context *ctx, printf("GLSL IR for linked %s program %d:\n", _mesa_shader_stage_to_string(shader->Stage), shader_program->Name); - _mesa_print_ir(shader->ir, NULL); + _mesa_print_ir(stdout, shader->ir, NULL); printf("\n"); printf("\n"); fflush(stdout); @@ -5182,6 +5245,7 @@ get_mesa_program(struct gl_context *ctx, stgp->Base.InputType = shader_program->Geom.InputType; stgp->Base.OutputType = shader_program->Geom.OutputType; stgp->Base.VerticesOut = shader_program->Geom.VerticesOut; + stgp->Base.Invocations = shader_program->Geom.Invocations; break; default: assert(!"should not be reached"); @@ -5268,6 +5332,7 @@ st_link_shader(struct gl_context *ctx, struct gl_shader_program *prog) lower_packing_builtins(ir, lower_inst); } + lower_offset_arrays(ir); do_mat_op_to_vec(ir); lower_instructions(ir, MOD_TO_FRACT | diff --git a/mesalib/src/mesa/state_tracker/st_manager.c b/mesalib/src/mesa/state_tracker/st_manager.c index 215b27634..6a776a8a2 100644 --- a/mesalib/src/mesa/state_tracker/st_manager.c +++ b/mesalib/src/mesa/state_tracker/st_manager.c @@ -30,6 +30,7 @@ #include "main/texobj.h" #include "main/teximage.h" #include "main/texstate.h" +#include "main/errors.h" #include "main/framebuffer.h" #include "main/fbobject.h" #include "main/renderbuffer.h" @@ -626,10 +627,14 @@ st_api_create_context(struct st_api *stapi, struct st_manager *smapi, return NULL; } - st->ctx->Debug.DebugOutput = GL_FALSE; if (attribs->flags & ST_CONTEXT_FLAG_DEBUG){ + struct gl_debug_state *debug = _mesa_get_debug_state(st->ctx); + if (!debug) { + *error = ST_CONTEXT_ERROR_NO_MEMORY; + return NULL; + } st->ctx->Const.ContextFlags |= GL_CONTEXT_FLAG_DEBUG_BIT; - st->ctx->Debug.DebugOutput = GL_TRUE; + debug->DebugOutput = GL_TRUE; } if (attribs->flags & ST_CONTEXT_FLAG_FORWARD_COMPATIBLE) diff --git a/mesalib/src/mesa/state_tracker/st_program.c b/mesalib/src/mesa/state_tracker/st_program.c index cadbe1705..e9074ac97 100644 --- a/mesalib/src/mesa/state_tracker/st_program.c +++ b/mesalib/src/mesa/state_tracker/st_program.c @@ -572,6 +572,11 @@ st_translate_fragment_program(struct st_context *st, input_semantic_index[slot] = 0; interpMode[slot] = TGSI_INTERPOLATE_CONSTANT; break; + case VARYING_SLOT_VIEWPORT: + input_semantic_name[slot] = TGSI_SEMANTIC_VIEWPORT_INDEX; + input_semantic_index[slot] = 0; + interpMode[slot] = TGSI_INTERPOLATE_CONSTANT; + break; case VARYING_SLOT_CLIP_DIST0: input_semantic_name[slot] = TGSI_SEMANTIC_CLIPDIST; input_semantic_index[slot] = 0; @@ -1027,6 +1032,10 @@ st_translate_geometry_program(struct st_context *st, gs_output_semantic_name[slot] = TGSI_SEMANTIC_PRIMID; gs_output_semantic_index[slot] = 0; break; + case VARYING_SLOT_VIEWPORT: + gs_output_semantic_name[slot] = TGSI_SEMANTIC_VIEWPORT_INDEX; + gs_output_semantic_index[slot] = 0; + break; case VARYING_SLOT_TEX0: case VARYING_SLOT_TEX1: case VARYING_SLOT_TEX2: @@ -1087,6 +1096,7 @@ st_translate_geometry_program(struct st_context *st, ureg_property_gs_input_prim(ureg, stgp->Base.InputType); ureg_property_gs_output_prim(ureg, stgp->Base.OutputType); ureg_property_gs_max_vertices(ureg, stgp->Base.VerticesOut); + ureg_property_gs_invocations(ureg, stgp->Base.Invocations); if (stgp->glsl_to_tgsi) st_translate_program(st->ctx, diff --git a/mesalib/src/mesa/swrast/s_depth.c b/mesalib/src/mesa/swrast/s_depth.c index 93aaffc57..8c225e111 100644 --- a/mesalib/src/mesa/swrast/s_depth.c +++ b/mesalib/src/mesa/swrast/s_depth.c @@ -552,8 +552,8 @@ _swrast_clear_depth_buffer(struct gl_context *ctx) height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin; mapMode = GL_MAP_WRITE_BIT; - if (rb->Format == MESA_FORMAT_Z24_UNORM_X8_UINT || - rb->Format == MESA_FORMAT_Z24_UNORM_S8_UINT || + if (rb->Format == MESA_FORMAT_Z24_UNORM_S8_UINT || + rb->Format == MESA_FORMAT_Z24_UNORM_X8_UINT || rb->Format == MESA_FORMAT_S8_UINT_Z24_UNORM || rb->Format == MESA_FORMAT_X8Z24_UNORM) { mapMode |= GL_MAP_READ_BIT; @@ -602,8 +602,8 @@ _swrast_clear_depth_buffer(struct gl_context *ctx) } } break; - case MESA_FORMAT_Z24_UNORM_X8_UINT: case MESA_FORMAT_Z24_UNORM_S8_UINT: + case MESA_FORMAT_Z24_UNORM_X8_UINT: case MESA_FORMAT_S8_UINT_Z24_UNORM: case MESA_FORMAT_X8Z24_UNORM: { @@ -611,8 +611,8 @@ _swrast_clear_depth_buffer(struct gl_context *ctx) GLuint clearVal = 0; GLuint mask; - if (rb->Format == MESA_FORMAT_Z24_UNORM_X8_UINT || - rb->Format == MESA_FORMAT_Z24_UNORM_S8_UINT) + if (rb->Format == MESA_FORMAT_Z24_UNORM_S8_UINT || + rb->Format == MESA_FORMAT_Z24_UNORM_X8_UINT) mask = 0xff000000; else mask = 0xff; @@ -692,7 +692,7 @@ _swrast_clear_depth_stencil_buffer(struct gl_context *ctx) } switch (rb->Format) { - case MESA_FORMAT_Z24_UNORM_X8_UINT: + case MESA_FORMAT_Z24_UNORM_S8_UINT: case MESA_FORMAT_S8_UINT_Z24_UNORM: { GLfloat zClear = (GLfloat) ctx->Depth.Clear; @@ -700,7 +700,7 @@ _swrast_clear_depth_stencil_buffer(struct gl_context *ctx) _mesa_pack_float_z_row(rb->Format, 1, &zClear, &clear); - if (rb->Format == MESA_FORMAT_Z24_UNORM_X8_UINT) { + if (rb->Format == MESA_FORMAT_Z24_UNORM_S8_UINT) { mask = ((~writeMask) & 0xff) << 24; clear |= (ctx->Stencil.Clear & writeMask & 0xff) << 24; } diff --git a/mesalib/src/mesa/swrast/s_drawpix.c b/mesalib/src/mesa/swrast/s_drawpix.c index ed4487f3e..f7926e426 100644 --- a/mesalib/src/mesa/swrast/s_drawpix.c +++ b/mesalib/src/mesa/swrast/s_drawpix.c @@ -500,7 +500,7 @@ draw_rgba_pixels( struct gl_context *ctx, GLint x, GLint y, /** - * Draw depth+stencil values into a MESA_FORAMT_Z24_S8 or MESA_FORMAT_Z24_UNORM_X8_UINT + * Draw depth+stencil values into a MESA_FORAMT_Z24_S8 or MESA_FORMAT_Z24_UNORM_S8_UINT * renderbuffer. No masking, zooming, scaling, etc. */ static void @@ -573,7 +573,7 @@ draw_depth_stencil_pixels(struct gl_context *ctx, GLint x, GLint y, if (depthRb == stencilRb && (depthRb->Format == MESA_FORMAT_S8_UINT_Z24_UNORM || - depthRb->Format == MESA_FORMAT_Z24_UNORM_X8_UINT) && + depthRb->Format == MESA_FORMAT_Z24_UNORM_S8_UINT) && type == GL_UNSIGNED_INT_24_8 && !scaleOrBias && !zoom && diff --git a/mesalib/src/mesa/swrast/s_renderbuffer.c b/mesalib/src/mesa/swrast/s_renderbuffer.c index cf5e2230d..dfd3a6057 100644 --- a/mesalib/src/mesa/swrast/s_renderbuffer.c +++ b/mesalib/src/mesa/swrast/s_renderbuffer.c @@ -102,7 +102,7 @@ soft_renderbuffer_storage(struct gl_context *ctx, struct gl_renderbuffer *rb, rb->Format = MESA_FORMAT_Z_UNORM16; break; case GL_DEPTH_COMPONENT24: - rb->Format = MESA_FORMAT_Z24_UNORM_S8_UINT; + rb->Format = MESA_FORMAT_Z24_UNORM_X8_UINT; break; case GL_DEPTH_COMPONENT32: rb->Format = MESA_FORMAT_Z_UNORM32; diff --git a/mesalib/src/mesa/swrast/s_stencil.c b/mesalib/src/mesa/swrast/s_stencil.c index e7c35ff69..eba9da863 100644 --- a/mesalib/src/mesa/swrast/s_stencil.c +++ b/mesalib/src/mesa/swrast/s_stencil.c @@ -614,7 +614,7 @@ _swrast_clear_stencil_buffer(struct gl_context *ctx) } } break; - case MESA_FORMAT_Z24_UNORM_X8_UINT: + case MESA_FORMAT_Z24_UNORM_S8_UINT: { GLuint clear = (ctx->Stencil.Clear & writeMask & 0xff) << 24; GLuint mask = (((~writeMask) & 0xff) << 24) | 0xffffff; diff --git a/mesalib/src/mesa/swrast/s_texfetch.c b/mesalib/src/mesa/swrast/s_texfetch.c index 7a3e76f85..b620748c9 100644 --- a/mesalib/src/mesa/swrast/s_texfetch.c +++ b/mesalib/src/mesa/swrast/s_texfetch.c @@ -383,7 +383,7 @@ texfetch_funcs[] = fetch_texel_3d_f_z24_s8 }, { - MESA_FORMAT_Z24_UNORM_X8_UINT, + MESA_FORMAT_Z24_UNORM_S8_UINT, fetch_texel_1d_f_s8_z24, fetch_texel_2d_f_s8_z24, fetch_texel_3d_f_s8_z24 @@ -395,7 +395,7 @@ texfetch_funcs[] = fetch_texel_3d_f_z16 }, { - MESA_FORMAT_Z24_UNORM_S8_UINT, + MESA_FORMAT_Z24_UNORM_X8_UINT, fetch_texel_1d_f_s8_z24, fetch_texel_2d_f_s8_z24, fetch_texel_3d_f_s8_z24 diff --git a/mesalib/src/mesa/swrast/s_texfetch_tmp.h b/mesalib/src/mesa/swrast/s_texfetch_tmp.h index f3048894e..806f0fd1a 100644 --- a/mesalib/src/mesa/swrast/s_texfetch_tmp.h +++ b/mesalib/src/mesa/swrast/s_texfetch_tmp.h @@ -1556,8 +1556,8 @@ static void FETCH(f_s8_z24)( const struct swrast_texture_image *texImage, const GLuint *src = TEXEL_ADDR(GLuint, texImage, i, j, k, 1); const GLdouble scale = 1.0 / (GLdouble) 0xffffff; texel[0] = (GLfloat) (((*src) & 0x00ffffff) * scale); - ASSERT(texImage->Base.TexFormat == MESA_FORMAT_Z24_UNORM_X8_UINT || - texImage->Base.TexFormat == MESA_FORMAT_Z24_UNORM_S8_UINT); + ASSERT(texImage->Base.TexFormat == MESA_FORMAT_Z24_UNORM_S8_UINT || + texImage->Base.TexFormat == MESA_FORMAT_Z24_UNORM_X8_UINT); ASSERT(texel[0] >= 0.0F); ASSERT(texel[0] <= 1.0F); } diff --git a/mesalib/src/mesa/tnl/t_draw.c b/mesalib/src/mesa/tnl/t_draw.c index 8e5af9627..2755ae62d 100644 --- a/mesalib/src/mesa/tnl/t_draw.c +++ b/mesalib/src/mesa/tnl/t_draw.c @@ -279,17 +279,18 @@ static void bind_inputs( struct gl_context *ctx, const void *ptr; if (inputs[i]->BufferObj->Name) { - if (!inputs[i]->BufferObj->Pointer) { + if (!inputs[i]->BufferObj->Mappings[MAP_INTERNAL].Pointer) { bo[*nr_bo] = inputs[i]->BufferObj; (*nr_bo)++; ctx->Driver.MapBufferRange(ctx, 0, inputs[i]->BufferObj->Size, GL_MAP_READ_BIT, - inputs[i]->BufferObj); + inputs[i]->BufferObj, + MAP_INTERNAL); - assert(inputs[i]->BufferObj->Pointer); + assert(inputs[i]->BufferObj->Mappings[MAP_INTERNAL].Pointer); } - ptr = ADD_POINTERS(inputs[i]->BufferObj->Pointer, + ptr = ADD_POINTERS(inputs[i]->BufferObj->Mappings[MAP_INTERNAL].Pointer, inputs[i]->Ptr); } else @@ -348,17 +349,19 @@ static void bind_indices( struct gl_context *ctx, return; } - if (_mesa_is_bufferobj(ib->obj) && !_mesa_bufferobj_mapped(ib->obj)) { + if (_mesa_is_bufferobj(ib->obj) && + !_mesa_bufferobj_mapped(ib->obj, MAP_INTERNAL)) { /* if the buffer object isn't mapped yet, map it now */ bo[*nr_bo] = ib->obj; (*nr_bo)++; ptr = ctx->Driver.MapBufferRange(ctx, (GLsizeiptr) ib->ptr, ib->count * vbo_sizeof_ib_type(ib->type), - GL_MAP_READ_BIT, ib->obj); - assert(ib->obj->Pointer); + GL_MAP_READ_BIT, ib->obj, + MAP_INTERNAL); + assert(ib->obj->Mappings[MAP_INTERNAL].Pointer); } else { /* user-space elements, or buffer already mapped */ - ptr = ADD_POINTERS(ib->obj->Pointer, ib->ptr); + ptr = ADD_POINTERS(ib->obj->Mappings[MAP_INTERNAL].Pointer, ib->ptr); } if (ib->type == GL_UNSIGNED_INT && VB->Primitive[0].basevertex == 0) { @@ -403,7 +406,7 @@ static void unmap_vbos( struct gl_context *ctx, { GLuint i; for (i = 0; i < nr_bo; i++) { - ctx->Driver.UnmapBuffer(ctx, bo[i]); + ctx->Driver.UnmapBuffer(ctx, bo[i], MAP_INTERNAL); } } diff --git a/mesalib/src/mesa/vbo/vbo_exec_api.c b/mesalib/src/mesa/vbo/vbo_exec_api.c index 810913645..74aec127c 100644 --- a/mesalib/src/mesa/vbo/vbo_exec_api.c +++ b/mesalib/src/mesa/vbo/vbo_exec_api.c @@ -998,7 +998,11 @@ void vbo_use_buffer_objects(struct gl_context *ctx) /* Allocate a real buffer object now */ _mesa_reference_buffer_object(ctx, &exec->vtx.bufferobj, NULL); exec->vtx.bufferobj = ctx->Driver.NewBufferObject(ctx, bufName, target); - if (!ctx->Driver.BufferData(ctx, target, size, NULL, usage, exec->vtx.bufferobj)) { + if (!ctx->Driver.BufferData(ctx, target, size, NULL, usage, + GL_MAP_WRITE_BIT | + GL_DYNAMIC_STORAGE_BIT | + GL_CLIENT_STORAGE_BIT, + exec->vtx.bufferobj)) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "VBO allocation"); } } @@ -1114,8 +1118,8 @@ void vbo_exec_vtx_destroy( struct vbo_exec_context *exec ) /* Free the vertex buffer. Unmap first if needed. */ - if (_mesa_bufferobj_mapped(exec->vtx.bufferobj)) { - ctx->Driver.UnmapBuffer(ctx, exec->vtx.bufferobj); + if (_mesa_bufferobj_mapped(exec->vtx.bufferobj, MAP_INTERNAL)) { + ctx->Driver.UnmapBuffer(ctx, exec->vtx.bufferobj, MAP_INTERNAL); } _mesa_reference_buffer_object(ctx, &exec->vtx.bufferobj, NULL); } diff --git a/mesalib/src/mesa/vbo/vbo_exec_array.c b/mesalib/src/mesa/vbo/vbo_exec_array.c index b316f097d..07ce08fef 100644 --- a/mesalib/src/mesa/vbo/vbo_exec_array.c +++ b/mesalib/src/mesa/vbo/vbo_exec_array.c @@ -53,7 +53,7 @@ check_buffers_are_unmapped(const struct gl_client_array **inputs) for (i = 0; i < VERT_ATTRIB_MAX; i++) { if (inputs[i]) { struct gl_buffer_object *obj = inputs[i]->BufferObj; - assert(!_mesa_bufferobj_mapped(obj)); + assert(!_mesa_check_disallowed_mapping(obj)); (void) obj; } } @@ -73,7 +73,7 @@ vbo_check_buffers_are_unmapped(struct gl_context *ctx) /* check the current vertex arrays */ check_buffers_are_unmapped(exec->array.inputs); /* check the current glBegin/glVertex/glEnd-style VBO */ - assert(!_mesa_bufferobj_mapped(exec->vtx.bufferobj)); + assert(!_mesa_check_disallowed_mapping(exec->vtx.bufferobj)); } @@ -101,7 +101,8 @@ vbo_get_minmax_index(struct gl_context *ctx, if (_mesa_is_bufferobj(ib->obj)) { GLsizeiptr size = MIN2(count * index_size, ib->obj->Size); indices = ctx->Driver.MapBufferRange(ctx, (GLintptr) indices, size, - GL_MAP_READ_BIT, ib->obj); + GL_MAP_READ_BIT, ib->obj, + MAP_INTERNAL); } switch (ib->type) { @@ -177,7 +178,7 @@ vbo_get_minmax_index(struct gl_context *ctx, } if (_mesa_is_bufferobj(ib->obj)) { - ctx->Driver.UnmapBuffer(ctx, ib->obj); + ctx->Driver.UnmapBuffer(ctx, ib->obj, MAP_INTERNAL); } } @@ -229,13 +230,15 @@ check_array_data(struct gl_context *ctx, struct gl_client_array *array, if (array->Enabled) { const void *data = array->Ptr; if (_mesa_is_bufferobj(array->BufferObj)) { - if (!array->BufferObj->Pointer) { + if (!array->BufferObj->Mappings[MAP_INTERNAL].Pointer) { /* need to map now */ - array->BufferObj->Pointer = + array->BufferObj->Mappings[MAP_INTERNAL].Pointer = ctx->Driver.MapBufferRange(ctx, 0, array->BufferObj->Size, - GL_MAP_READ_BIT, array->BufferObj); + GL_MAP_READ_BIT, array->BufferObj, + MAP_INTERNAL); } - data = ADD_POINTERS(data, array->BufferObj->Pointer); + data = ADD_POINTERS(data, + array->BufferObj->Mappings[MAP_INTERNAL].Pointer); } switch (array->Type) { case GL_FLOAT: @@ -273,8 +276,8 @@ unmap_array_buffer(struct gl_context *ctx, struct gl_client_array *array) { if (array->Enabled && _mesa_is_bufferobj(array->BufferObj) && - _mesa_bufferobj_mapped(array->BufferObj)) { - ctx->Driver.UnmapBuffer(ctx, array->BufferObj); + _mesa_bufferobj_mapped(array->BufferObj, MAP_INTERNAL)) { + ctx->Driver.UnmapBuffer(ctx, array->BufferObj, MAP_INTERNAL); } } @@ -295,7 +298,8 @@ check_draw_elements_data(struct gl_context *ctx, GLsizei count, GLenum elemType, elemMap = ctx->Driver.MapBufferRange(ctx, 0, ctx->Array.VAO->IndexBufferObj->Size, GL_MAP_READ_BIT, - ctx->Array.VAO->IndexBufferObj); + ctx->Array.VAO->IndexBufferObj, + MAP_INTERNAL); elements = ADD_POINTERS(elements, elemMap); } @@ -324,7 +328,8 @@ check_draw_elements_data(struct gl_context *ctx, GLsizei count, GLenum elemType, } if (_mesa_is_bufferobj(vao->IndexBufferObj)) { - ctx->Driver.UnmapBuffer(ctx, ctx->Array.VAO->IndexBufferObj); + ctx->Driver.UnmapBuffer(ctx, ctx->Array.VAO->IndexBufferObj, + MAP_INTERNAL); } for (k = 0; k < Elements(vao->_VertexAttrib); k++) { @@ -374,7 +379,8 @@ print_draw_arrays(struct gl_context *ctx, if (bufName) { GLubyte *p = ctx->Driver.MapBufferRange(ctx, 0, bufObj->Size, - GL_MAP_READ_BIT, bufObj); + GL_MAP_READ_BIT, bufObj, + MAP_INTERNAL); int offset = (int) (GLintptr) exec->array.inputs[i]->Ptr; float *f = (float *) (p + offset); int *k = (int *) f; @@ -386,7 +392,7 @@ print_draw_arrays(struct gl_context *ctx, for (i = 0; i < n; i++) { printf(" float[%d] = 0x%08x %f\n", i, k[i], f[i]); } - ctx->Driver.UnmapBuffer(ctx, bufObj); + ctx->Driver.UnmapBuffer(ctx, bufObj, MAP_INTERNAL); } } } @@ -885,7 +891,8 @@ dump_element_buffer(struct gl_context *ctx, GLenum type) ctx->Driver.MapBufferRange(ctx, 0, ctx->Array.VAO->IndexBufferObj->Size, GL_MAP_READ_BIT, - ctx->Array.VAO->IndexBufferObj); + ctx->Array.VAO->IndexBufferObj, + MAP_INTERNAL); switch (type) { case GL_UNSIGNED_BYTE: { @@ -927,7 +934,8 @@ dump_element_buffer(struct gl_context *ctx, GLenum type) ; } - ctx->Driver.UnmapBuffer(ctx, ctx->Array.VAO->IndexBufferObj); + ctx->Driver.UnmapBuffer(ctx, ctx->Array.VAO->IndexBufferObj, + MAP_INTERNAL); } #endif diff --git a/mesalib/src/mesa/vbo/vbo_exec_draw.c b/mesalib/src/mesa/vbo/vbo_exec_draw.c index 75115ce66..c454c6943 100644 --- a/mesalib/src/mesa/vbo/vbo_exec_draw.c +++ b/mesalib/src/mesa/vbo/vbo_exec_draw.c @@ -220,9 +220,10 @@ vbo_exec_bind_arrays( struct gl_context *ctx ) if (_mesa_is_bufferobj(exec->vtx.bufferobj)) { /* a real buffer obj: Ptr is an offset, not a pointer*/ - assert(exec->vtx.bufferobj->Pointer); /* buf should be mapped */ + assert(exec->vtx.bufferobj->Mappings[MAP_INTERNAL].Pointer); assert(offset >= 0); - arrays[attr].Ptr = (GLubyte *)exec->vtx.bufferobj->Offset + offset; + arrays[attr].Ptr = (GLubyte *) + exec->vtx.bufferobj->Mappings[MAP_INTERNAL].Offset + offset; } else { /* Ptr into ordinary app memory */ @@ -261,12 +262,15 @@ vbo_exec_vtx_unmap( struct vbo_exec_context *exec ) struct gl_context *ctx = exec->ctx; if (ctx->Driver.FlushMappedBufferRange) { - GLintptr offset = exec->vtx.buffer_used - exec->vtx.bufferobj->Offset; - GLsizeiptr length = (exec->vtx.buffer_ptr - exec->vtx.buffer_map) * sizeof(float); + GLintptr offset = exec->vtx.buffer_used - + exec->vtx.bufferobj->Mappings[MAP_INTERNAL].Offset; + GLsizeiptr length = (exec->vtx.buffer_ptr - exec->vtx.buffer_map) * + sizeof(float); if (length) ctx->Driver.FlushMappedBufferRange(ctx, offset, length, - exec->vtx.bufferobj); + exec->vtx.bufferobj, + MAP_INTERNAL); } exec->vtx.buffer_used += (exec->vtx.buffer_ptr - @@ -275,7 +279,7 @@ vbo_exec_vtx_unmap( struct vbo_exec_context *exec ) assert(exec->vtx.buffer_used <= VBO_VERT_BUFFER_SIZE); assert(exec->vtx.buffer_ptr != NULL); - ctx->Driver.UnmapBuffer(ctx, exec->vtx.bufferobj); + ctx->Driver.UnmapBuffer(ctx, exec->vtx.bufferobj, MAP_INTERNAL); exec->vtx.buffer_map = NULL; exec->vtx.buffer_ptr = NULL; exec->vtx.max_vert = 0; @@ -312,7 +316,8 @@ vbo_exec_vtx_map( struct vbo_exec_context *exec ) (VBO_VERT_BUFFER_SIZE - exec->vtx.buffer_used), accessRange, - exec->vtx.bufferobj); + exec->vtx.bufferobj, + MAP_INTERNAL); exec->vtx.buffer_ptr = exec->vtx.buffer_map; } else { @@ -325,14 +330,19 @@ vbo_exec_vtx_map( struct vbo_exec_context *exec ) exec->vtx.buffer_used = 0; if (ctx->Driver.BufferData(ctx, GL_ARRAY_BUFFER_ARB, - VBO_VERT_BUFFER_SIZE, - NULL, usage, exec->vtx.bufferobj)) { + VBO_VERT_BUFFER_SIZE, + NULL, usage, + GL_MAP_WRITE_BIT | + GL_DYNAMIC_STORAGE_BIT | + GL_CLIENT_STORAGE_BIT, + exec->vtx.bufferobj)) { /* buffer allocation worked, now map the buffer */ exec->vtx.buffer_map = (GLfloat *)ctx->Driver.MapBufferRange(ctx, 0, VBO_VERT_BUFFER_SIZE, accessRange, - exec->vtx.bufferobj); + exec->vtx.bufferobj, + MAP_INTERNAL); } else { _mesa_error(ctx, GL_OUT_OF_MEMORY, "VBO allocation"); diff --git a/mesalib/src/mesa/vbo/vbo_primitive_restart.c b/mesalib/src/mesa/vbo/vbo_primitive_restart.c index 9c3055431..25c89669c 100644 --- a/mesalib/src/mesa/vbo/vbo_primitive_restart.c +++ b/mesalib/src/mesa/vbo/vbo_primitive_restart.c @@ -177,7 +177,7 @@ vbo_sw_primitive_restart(struct gl_context *ctx, struct _mesa_prim temp_prim; struct vbo_context *vbo = vbo_context(ctx); vbo_draw_func draw_prims_func = vbo->draw_prims; - GLboolean map_ib = ib->obj->Name && !ib->obj->Pointer; + GLboolean map_ib = ib->obj->Name && !ib->obj->Mappings[MAP_INTERNAL].Pointer; void *ptr; /* If there is an indirect buffer, map it and extract the draw params */ @@ -186,7 +186,7 @@ vbo_sw_primitive_restart(struct gl_context *ctx, struct _mesa_index_buffer new_ib = *ib; const uint32_t *indirect_params; if (!ctx->Driver.MapBufferRange(ctx, 0, indirect->Size, GL_MAP_READ_BIT, - indirect)) { + indirect, MAP_INTERNAL)) { /* something went wrong with mapping, give up */ _mesa_error(ctx, GL_OUT_OF_MEMORY, @@ -195,8 +195,9 @@ vbo_sw_primitive_restart(struct gl_context *ctx, } assert(nr_prims == 1); - indirect_params = (const uint32_t *) ADD_POINTERS(indirect->Pointer, - new_prim.indirect_offset); + indirect_params = (const uint32_t *) + ADD_POINTERS(indirect->Mappings[MAP_INTERNAL].Pointer, + new_prim.indirect_offset); new_prim.is_indirect = 0; new_prim.count = indirect_params[0]; @@ -210,7 +211,7 @@ vbo_sw_primitive_restart(struct gl_context *ctx, prims = &new_prim; ib = &new_ib; - ctx->Driver.UnmapBuffer(ctx, indirect); + ctx->Driver.UnmapBuffer(ctx, indirect, MAP_INTERNAL); } /* Find the sub-primitives. These are regions in the index buffer which @@ -218,17 +219,17 @@ vbo_sw_primitive_restart(struct gl_context *ctx, */ if (map_ib) { ctx->Driver.MapBufferRange(ctx, 0, ib->obj->Size, GL_MAP_READ_BIT, - ib->obj); + ib->obj, MAP_INTERNAL); } - ptr = ADD_POINTERS(ib->obj->Pointer, ib->ptr); + ptr = ADD_POINTERS(ib->obj->Mappings[MAP_INTERNAL].Pointer, ib->ptr); sub_prims = find_sub_primitives(ptr, vbo_sizeof_ib_type(ib->type), 0, ib->count, restart_index, &num_sub_prims); if (map_ib) { - ctx->Driver.UnmapBuffer(ctx, ib->obj); + ctx->Driver.UnmapBuffer(ctx, ib->obj, MAP_INTERNAL); } /* Loop over the primitives, and use the located sub-primitives to draw diff --git a/mesalib/src/mesa/vbo/vbo_rebase.c b/mesalib/src/mesa/vbo/vbo_rebase.c index c700621ce..f3fe5f757 100644 --- a/mesalib/src/mesa/vbo/vbo_rebase.c +++ b/mesalib/src/mesa/vbo/vbo_rebase.c @@ -157,15 +157,16 @@ void vbo_rebase_prims( struct gl_context *ctx, } else if (ib) { /* Unfortunately need to adjust each index individually. */ - GLboolean map_ib = ib->obj->Name && !ib->obj->Pointer; + GLboolean map_ib = ib->obj->Name && + !ib->obj->Mappings[MAP_INTERNAL].Pointer; void *ptr; if (map_ib) ctx->Driver.MapBufferRange(ctx, 0, ib->obj->Size, GL_MAP_READ_BIT, - ib->obj); + ib->obj, MAP_INTERNAL); - ptr = ADD_POINTERS(ib->obj->Pointer, ib->ptr); + ptr = ADD_POINTERS(ib->obj->Mappings[MAP_INTERNAL].Pointer, ib->ptr); /* Some users might prefer it if we translated elements to * GLuints here. Others wouldn't... @@ -183,7 +184,7 @@ void vbo_rebase_prims( struct gl_context *ctx, } if (map_ib) - ctx->Driver.UnmapBuffer(ctx, ib->obj); + ctx->Driver.UnmapBuffer(ctx, ib->obj, MAP_INTERNAL); tmp_ib.obj = ctx->Shared->NullBufferObj; tmp_ib.ptr = tmp_indices; diff --git a/mesalib/src/mesa/vbo/vbo_save_api.c b/mesalib/src/mesa/vbo/vbo_save_api.c index 98ab68623..1c6b91942 100644 --- a/mesalib/src/mesa/vbo/vbo_save_api.c +++ b/mesalib/src/mesa/vbo/vbo_save_api.c @@ -200,6 +200,8 @@ alloc_vertex_store(struct gl_context *ctx) GL_ARRAY_BUFFER_ARB, VBO_SAVE_BUFFER_SIZE * sizeof(GLfloat), NULL, GL_STATIC_DRAW_ARB, + GL_MAP_WRITE_BIT | + GL_DYNAMIC_STORAGE_BIT, vertex_store->bufferobj); } else { @@ -251,7 +253,8 @@ vbo_save_map_vertex_store(struct gl_context *ctx, GLsizeiptr size = vertex_store->bufferobj->Size - offset; GLfloat *range = (GLfloat *) ctx->Driver.MapBufferRange(ctx, offset, size, access, - vertex_store->bufferobj); + vertex_store->bufferobj, + MAP_INTERNAL); if (range) { /* compute address of start of whole buffer (needed elsewhere) */ vertex_store->buffer = range - vertex_store->used; @@ -277,13 +280,14 @@ vbo_save_unmap_vertex_store(struct gl_context *ctx, if (vertex_store->bufferobj->Size > 0) { GLintptr offset = 0; GLsizeiptr length = vertex_store->used * sizeof(GLfloat) - - vertex_store->bufferobj->Offset; + - vertex_store->bufferobj->Mappings[MAP_INTERNAL].Offset; /* Explicitly flush the region we wrote to */ ctx->Driver.FlushMappedBufferRange(ctx, offset, length, - vertex_store->bufferobj); + vertex_store->bufferobj, + MAP_INTERNAL); - ctx->Driver.UnmapBuffer(ctx, vertex_store->bufferobj); + ctx->Driver.UnmapBuffer(ctx, vertex_store->bufferobj, MAP_INTERNAL); } vertex_store->buffer = NULL; } @@ -1116,6 +1120,7 @@ _save_OBE_DrawElements(GLenum mode, GLsizei count, GLenum type, { GET_CURRENT_CONTEXT(ctx); struct vbo_save_context *save = &vbo_context(ctx)->save; + struct gl_buffer_object *indexbuf = ctx->Array.VAO->IndexBufferObj; GLint i; if (!_mesa_is_valid_prim_mode(ctx, mode)) { @@ -1138,9 +1143,9 @@ _save_OBE_DrawElements(GLenum mode, GLsizei count, GLenum type, _ae_map_vbos(ctx); - if (_mesa_is_bufferobj(ctx->Array.VAO->IndexBufferObj)) + if (_mesa_is_bufferobj(indexbuf)) indices = - ADD_POINTERS(ctx->Array.VAO->IndexBufferObj->Pointer, indices); + ADD_POINTERS(indexbuf->Mappings[MAP_INTERNAL].Pointer, indices); vbo_save_NotifyBegin(ctx, (mode | VBO_SAVE_PRIM_WEAK | VBO_SAVE_PRIM_NO_CURRENT_UPDATE)); diff --git a/mesalib/src/mesa/vbo/vbo_save_draw.c b/mesalib/src/mesa/vbo/vbo_save_draw.c index 4b13cc4e5..89fd30e0f 100644 --- a/mesalib/src/mesa/vbo/vbo_save_draw.c +++ b/mesalib/src/mesa/vbo/vbo_save_draw.c @@ -225,7 +225,8 @@ vbo_save_loopback_vertex_list(struct gl_context *ctx, ctx->Driver.MapBufferRange(ctx, 0, list->vertex_store->bufferobj->Size, GL_MAP_READ_BIT, /* ? */ - list->vertex_store->bufferobj); + list->vertex_store->bufferobj, + MAP_INTERNAL); vbo_loopback_vertex_list(ctx, (const GLfloat *)(buffer + list->buffer_offset), @@ -235,7 +236,8 @@ vbo_save_loopback_vertex_list(struct gl_context *ctx, list->wrap_count, list->vertex_size); - ctx->Driver.UnmapBuffer(ctx, list->vertex_store->bufferobj); + ctx->Driver.UnmapBuffer(ctx, list->vertex_store->bufferobj, + MAP_INTERNAL); } diff --git a/mesalib/src/mesa/vbo/vbo_split_copy.c b/mesalib/src/mesa/vbo/vbo_split_copy.c index 4332ef2e6..719ad651a 100644 --- a/mesalib/src/mesa/vbo/vbo_split_copy.c +++ b/mesalib/src/mesa/vbo/vbo_split_copy.c @@ -451,11 +451,14 @@ replay_init( struct copy_context *copy ) copy->varying[j].size = attr_size(copy->array[i]); copy->vertex_size += attr_size(copy->array[i]); - if (_mesa_is_bufferobj(vbo) && !_mesa_bufferobj_mapped(vbo)) - ctx->Driver.MapBufferRange(ctx, 0, vbo->Size, GL_MAP_READ_BIT, vbo); + if (_mesa_is_bufferobj(vbo) && + !_mesa_bufferobj_mapped(vbo, MAP_INTERNAL)) + ctx->Driver.MapBufferRange(ctx, 0, vbo->Size, GL_MAP_READ_BIT, vbo, + MAP_INTERNAL); - copy->varying[j].src_ptr = ADD_POINTERS(vbo->Pointer, - copy->array[i]->Ptr); + copy->varying[j].src_ptr = + ADD_POINTERS(vbo->Mappings[MAP_INTERNAL].Pointer, + copy->array[i]->Ptr); copy->dstarray_ptr[i] = ©->varying[j].dstarray; } @@ -466,12 +469,13 @@ replay_init( struct copy_context *copy ) * do it internally. */ if (_mesa_is_bufferobj(copy->ib->obj) && - !_mesa_bufferobj_mapped(copy->ib->obj)) + !_mesa_bufferobj_mapped(copy->ib->obj, MAP_INTERNAL)) ctx->Driver.MapBufferRange(ctx, 0, copy->ib->obj->Size, GL_MAP_READ_BIT, - copy->ib->obj); + copy->ib->obj, MAP_INTERNAL); - srcptr = (const GLubyte *) ADD_POINTERS(copy->ib->obj->Pointer, - copy->ib->ptr); + srcptr = (const GLubyte *) + ADD_POINTERS(copy->ib->obj->Mappings[MAP_INTERNAL].Pointer, + copy->ib->ptr); switch (copy->ib->type) { case GL_UNSIGNED_BYTE: @@ -572,15 +576,15 @@ replay_finish( struct copy_context *copy ) */ for (i = 0; i < copy->nr_varying; i++) { struct gl_buffer_object *vbo = copy->varying[i].array->BufferObj; - if (_mesa_is_bufferobj(vbo) && _mesa_bufferobj_mapped(vbo)) - ctx->Driver.UnmapBuffer(ctx, vbo); + if (_mesa_is_bufferobj(vbo) && _mesa_bufferobj_mapped(vbo, MAP_INTERNAL)) + ctx->Driver.UnmapBuffer(ctx, vbo, MAP_INTERNAL); } /* Unmap index buffer: */ if (_mesa_is_bufferobj(copy->ib->obj) && - _mesa_bufferobj_mapped(copy->ib->obj)) { - ctx->Driver.UnmapBuffer(ctx, copy->ib->obj); + _mesa_bufferobj_mapped(copy->ib->obj, MAP_INTERNAL)) { + ctx->Driver.UnmapBuffer(ctx, copy->ib->obj, MAP_INTERNAL); } } |