diff options
Diffstat (limited to 'mesalib/src/mesa')
126 files changed, 3681 insertions, 1451 deletions
diff --git a/mesalib/src/mesa/Makefile.am b/mesalib/src/mesa/Makefile.am index 3dab8f03f..60114e4f6 100644 --- a/mesalib/src/mesa/Makefile.am +++ b/mesalib/src/mesa/Makefile.am @@ -174,6 +174,7 @@ endif libmesa_la_SOURCES = \ $(MESA_FILES) \ $(PROGRAM_FILES) \ + $(PROGRAM_NIR_FILES) \ $(MESA_ASM_FILES_FOR_ARCH) libmesa_la_LIBADD = \ @@ -183,6 +184,7 @@ libmesa_la_LIBADD = \ libmesagallium_la_SOURCES = \ $(MESA_GALLIUM_FILES) \ $(PROGRAM_FILES) \ + $(PROGRAM_NIR_FILES) \ $(MESA_ASM_FILES_FOR_ARCH) libmesagallium_la_LIBADD = \ diff --git a/mesalib/src/mesa/Makefile.sources b/mesalib/src/mesa/Makefile.sources index 217be9ab3..1293d4135 100644 --- a/mesalib/src/mesa/Makefile.sources +++ b/mesalib/src/mesa/Makefile.sources @@ -152,6 +152,8 @@ MAIN_FILES = \ main/points.h \ main/polygon.c \ main/polygon.h \ + main/program_resource.c \ + main/program_resource.h \ main/querymatrix.c \ main/querymatrix.h \ main/queryobj.c \ @@ -520,6 +522,10 @@ PROGRAM_FILES = \ program/symbol_table.c \ program/symbol_table.h +PROGRAM_NIR_FILES = \ + program/prog_to_nir.c \ + program/prog_to_nir.h + ASM_C_FILES = \ x86/common_x86.c \ x86/x86_xform.c \ @@ -608,6 +614,7 @@ INCLUDE_DIRS = \ -I$(top_srcdir)/src \ -I$(top_srcdir)/src/glsl \ -I$(top_builddir)/src/glsl \ + -I$(top_builddir)/src/glsl/nir \ -I$(top_srcdir)/src/glsl/glcpp \ -I$(top_srcdir)/src/mesa \ -I$(top_builddir)/src/mesa \ diff --git a/mesalib/src/mesa/SConscript b/mesalib/src/mesa/SConscript index a563fd2ff..5b80a216f 100644 --- a/mesalib/src/mesa/SConscript +++ b/mesalib/src/mesa/SConscript @@ -130,9 +130,10 @@ def write_git_sha1_h_file(filename): (commit, foo) = subprocess.Popen(args, stdout=subprocess.PIPE).communicate() except: # git log command didn't work - dirname = os.path.dirname(filename) - if not os.path.exists(dirname): - os.makedirs(dirname) + if not os.path.exists(filename): + dirname = os.path.dirname(filename) + if not os.path.exists(dirname): + os.makedirs(dirname) # create an empty file if none already exists f = open(filename, "w") f.close() diff --git a/mesalib/src/mesa/drivers/SConscript b/mesalib/src/mesa/drivers/SConscript index 17813da96..db656780c 100644 --- a/mesalib/src/mesa/drivers/SConscript +++ b/mesalib/src/mesa/drivers/SConscript @@ -1,7 +1,5 @@ Import('*') -SConscript('osmesa/SConscript') - if env['x11']: SConscript('x11/SConscript') diff --git a/mesalib/src/mesa/drivers/dri/common/utils.c b/mesalib/src/mesa/drivers/dri/common/utils.c index bb22107e9..70d34e8ce 100644 --- a/mesalib/src/mesa/drivers/dri/common/utils.c +++ b/mesalib/src/mesa/drivers/dri/common/utils.c @@ -227,7 +227,7 @@ driCreateConfigs(mesa_format format, break; default: fprintf(stderr, "[%s:%u] Unknown framebuffer type %s (%d).\n", - __FUNCTION__, __LINE__, + __func__, __LINE__, _mesa_get_format_name(format), format); return NULL; } diff --git a/mesalib/src/mesa/drivers/dri/common/xmlconfig.c b/mesalib/src/mesa/drivers/dri/common/xmlconfig.c index 2b284ccf2..f17693e73 100644 --- a/mesalib/src/mesa/drivers/dri/common/xmlconfig.c +++ b/mesalib/src/mesa/drivers/dri/common/xmlconfig.c @@ -56,7 +56,7 @@ extern char *program_invocation_name, *program_invocation_short_name; # include <stdlib.h> # define GET_PROGRAM_NAME() getprogname() # endif -#elif defined(__NetBSD__) && defined(__NetBSD_Version) && (__NetBSD_Version >= 106000100) +#elif defined(__NetBSD__) && defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 106000100) # include <stdlib.h> # define GET_PROGRAM_NAME() getprogname() #elif defined(__APPLE__) diff --git a/mesalib/src/mesa/drivers/dri/common/xmlpool/Makefile.am b/mesalib/src/mesa/drivers/dri/common/xmlpool/Makefile.am index 555771685..a6f1652d1 100644 --- a/mesalib/src/mesa/drivers/dri/common/xmlpool/Makefile.am +++ b/mesalib/src/mesa/drivers/dri/common/xmlpool/Makefile.am @@ -52,14 +52,19 @@ POT=xmlpool.pot .PHONY: all clean pot po mo -EXTRA_DIST = gen_xmlpool.py options.h t_options.h $(POS) SConscript -BUILT_SOURCES = options.h -CLEANFILES = $(MOS) options.h +EXTRA_DIST = \ + gen_xmlpool.py \ + options.h \ + t_options.h \ + $(POS) \ + $(MOS) \ + SConscript -# All generated files are cleaned up. -clean: - -rm -f $(POT) options.h *~ - -rm -rf $(LANGS) +BUILT_SOURCES = options.h +CLEANFILES = \ + options.h + $(POS) \ + $(MOS) # Default target options.h options.h: LOCALEDIR := . diff --git a/mesalib/src/mesa/drivers/dri/swrast/swrast.c b/mesalib/src/mesa/drivers/dri/swrast/swrast.c index fb29078b6..d1bb72139 100644 --- a/mesalib/src/mesa/drivers/dri/swrast/swrast.c +++ b/mesalib/src/mesa/drivers/dri/swrast/swrast.c @@ -326,7 +326,7 @@ choose_pixel_format(const struct gl_config *v) && v->blueMask == 0xc0) return PF_R3G3B2; - _mesa_problem( NULL, "unexpected format in %s", __FUNCTION__ ); + _mesa_problem( NULL, "unexpected format in %s", __func__ ); return 0; } diff --git a/mesalib/src/mesa/drivers/dri/swrast/swrast_priv.h b/mesalib/src/mesa/drivers/dri/swrast/swrast_priv.h index 1f3a48f38..a6ab53529 100644 --- a/mesalib/src/mesa/drivers/dri/swrast/swrast_priv.h +++ b/mesalib/src/mesa/drivers/dri/swrast/swrast_priv.h @@ -41,13 +41,13 @@ #define DEBUG_SPAN 0 #if DEBUG_CORE -#define TRACE printf("--> %s\n", __FUNCTION__) +#define TRACE printf("--> %s\n", __func__) #else #define TRACE #endif #if DEBUG_SPAN -#define TRACE_SPAN printf("--> %s\n", __FUNCTION__) +#define TRACE_SPAN printf("--> %s\n", __func__) #else #define TRACE_SPAN #endif diff --git a/mesalib/src/mesa/main/.gitignore b/mesalib/src/mesa/main/.gitignore index 8256ad792..355b426e2 100644 --- a/mesalib/src/mesa/main/.gitignore +++ b/mesalib/src/mesa/main/.gitignore @@ -7,5 +7,6 @@ remap_helper.h get_hash.h get_hash.h.tmp format_info.h +format_info.c format_pack.c format_unpack.c diff --git a/mesalib/src/mesa/main/atifragshader.c b/mesalib/src/mesa/main/atifragshader.c index 9d967b9e6..9fc35520a 100644 --- a/mesalib/src/mesa/main/atifragshader.c +++ b/mesalib/src/mesa/main/atifragshader.c @@ -476,7 +476,7 @@ _mesa_PassTexCoordATI(GLuint dst, GLuint coord, GLenum swizzle) curI->swizzle = swizzle; #if MESA_DEBUG_ATI_FS - _mesa_debug(ctx, "%s(%s, %s, %s)\n", __FUNCTION__, + _mesa_debug(ctx, "%s(%s, %s, %s)\n", __func__, _mesa_lookup_enum_by_nr(dst), _mesa_lookup_enum_by_nr(coord), _mesa_lookup_enum_by_nr(swizzle)); #endif @@ -549,7 +549,7 @@ _mesa_SampleMapATI(GLuint dst, GLuint interp, GLenum swizzle) curI->swizzle = swizzle; #if MESA_DEBUG_ATI_FS - _mesa_debug(ctx, "%s(%s, %s, %s)\n", __FUNCTION__, + _mesa_debug(ctx, "%s(%s, %s, %s)\n", __func__, _mesa_lookup_enum_by_nr(dst), _mesa_lookup_enum_by_nr(interp), _mesa_lookup_enum_by_nr(swizzle)); #endif diff --git a/mesalib/src/mesa/main/attrib.c b/mesalib/src/mesa/main/attrib.c index 20216a87d..b163c0aa6 100644 --- a/mesalib/src/mesa/main/attrib.c +++ b/mesalib/src/mesa/main/attrib.c @@ -32,7 +32,6 @@ #include "buffers.h" #include "bufferobj.h" #include "clear.h" -#include "colormac.h" #include "context.h" #include "depth.h" #include "enable.h" diff --git a/mesalib/src/mesa/main/bufferobj.c b/mesalib/src/mesa/main/bufferobj.c index 965877084..66dee6802 100644 --- a/mesalib/src/mesa/main/bufferobj.c +++ b/mesalib/src/mesa/main/bufferobj.c @@ -1333,6 +1333,7 @@ create_buffers(GLsizei n, GLuint *buffers, bool dsa) buf = ctx->Driver.NewBufferObject(ctx, buffers[i]); if (!buf) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func); + mtx_unlock(&ctx->Shared->Mutex); return; } } @@ -3885,8 +3886,10 @@ _mesa_BindBufferRange(GLenum target, GLuint index, switch (target) { case GL_TRANSFORM_FEEDBACK_BUFFER: - _mesa_bind_buffer_range_transform_feedback(ctx, index, bufObj, - offset, size); + _mesa_bind_buffer_range_transform_feedback(ctx, + ctx->TransformFeedback.CurrentObject, + index, bufObj, offset, size, + false); return; case GL_UNIFORM_BUFFER: bind_buffer_range_uniform_buffer(ctx, index, bufObj, offset, size); @@ -3950,7 +3953,9 @@ _mesa_BindBufferBase(GLenum target, GLuint index, GLuint buffer) switch (target) { case GL_TRANSFORM_FEEDBACK_BUFFER: - _mesa_bind_buffer_base_transform_feedback(ctx, index, bufObj); + _mesa_bind_buffer_base_transform_feedback(ctx, + ctx->TransformFeedback.CurrentObject, + index, bufObj, false); return; case GL_UNIFORM_BUFFER: bind_buffer_base_uniform_buffer(ctx, index, bufObj); diff --git a/mesalib/src/mesa/main/colormac.h b/mesalib/src/mesa/main/colormac.h index bc69f4673..33ca5af07 100644 --- a/mesalib/src/mesa/main/colormac.h +++ b/mesalib/src/mesa/main/colormac.h @@ -52,70 +52,25 @@ _mesa_unclamped_float_rgba_to_ubyte(GLubyte dst[4], const GLfloat src[4]) /** * \name Generic color packing macros. All inputs should be GLubytes. - * - * \todo We may move these into texstore.h at some point. */ /*@{*/ #define PACK_COLOR_8888( X, Y, Z, W ) \ (((X) << 24) | ((Y) << 16) | ((Z) << 8) | (W)) -#define PACK_COLOR_8888_REV( X, Y, Z, W ) \ - (((W) << 24) | ((Z) << 16) | ((Y) << 8) | (X)) - -#define PACK_COLOR_888( X, Y, Z ) \ - (((X) << 16) | ((Y) << 8) | (Z)) - #define PACK_COLOR_565( X, Y, Z ) \ ((((X) & 0xf8) << 8) | (((Y) & 0xfc) << 3) | (((Z) & 0xf8) >> 3)) -#define PACK_COLOR_5551( R, G, B, A ) \ - ((((R) & 0xf8) << 8) | (((G) & 0xf8) << 3) | (((B) & 0xf8) >> 2) | \ - ((A) >> 7)) - #define PACK_COLOR_1555( A, B, G, R ) \ ((((B) & 0xf8) << 7) | (((G) & 0xf8) << 2) | (((R) & 0xf8) >> 3) | \ (((A) & 0x80) << 8)) -#define PACK_COLOR_1555_REV( A, B, G, R ) \ - ((((B) & 0xf8) >> 1) | (((G) & 0xc0) >> 6) | (((G) & 0x38) << 10) | (((R) & 0xf8) << 5) | \ - ((A) ? 0x80 : 0)) - -#define PACK_COLOR_2101010_UB( A, B, G, R ) \ - (((B) << 22) | ((G) << 12) | ((R) << 2) | \ - (((A) & 0xc0) << 24)) - -#define PACK_COLOR_2101010_US( A, B, G, R ) \ - ((((B) >> 6) << 20) | (((G) >> 6) << 10) | ((R) >> 6) | \ - (((A) >> 14) << 30)) - #define PACK_COLOR_4444( R, G, B, A ) \ ((((R) & 0xf0) << 8) | (((G) & 0xf0) << 4) | ((B) & 0xf0) | ((A) >> 4)) -#define PACK_COLOR_4444_REV( R, G, B, A ) \ - ((((B) & 0xf0) << 8) | (((A) & 0xf0) << 4) | ((R) & 0xf0) | ((G) >> 4)) - -#define PACK_COLOR_44( L, A ) \ - (((L) & 0xf0) | (((A) & 0xf0) >> 4)) - #define PACK_COLOR_88( L, A ) \ (((L) << 8) | (A)) -#define PACK_COLOR_88_REV( L, A ) \ - (((A) << 8) | (L)) - -#define PACK_COLOR_1616( L, A ) \ - (((L) << 16) | (A)) - -#define PACK_COLOR_1616_REV( L, A ) \ - (((A) << 16) | (L)) - -#define PACK_COLOR_332( R, G, B ) \ - (((R) & 0xe0) | (((G) & 0xe0) >> 3) | (((B) & 0xc0) >> 6)) - -#define PACK_COLOR_233( B, G, R ) \ - (((B) & 0xc0) | (((G) & 0xe0) >> 2) | (((R) & 0xe0) >> 5)) - /*@}*/ diff --git a/mesalib/src/mesa/main/context.c b/mesalib/src/mesa/main/context.c index c1acda980..adf64976e 100644 --- a/mesalib/src/mesa/main/context.c +++ b/mesalib/src/mesa/main/context.c @@ -1288,7 +1288,6 @@ _mesa_free_context_data( struct gl_context *ctx ) _mesa_free_eval_data( 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); @@ -1449,17 +1448,10 @@ _mesa_copy_context( const struct gl_context *src, struct gl_context *dst, dst->Transform = src->Transform; } if (mask & GL_VIEWPORT_BIT) { - /* Cannot use memcpy, because of pointers in GLmatrix _WindowMap */ unsigned i; for (i = 0; i < src->Const.MaxViewports; i++) { - dst->ViewportArray[i].X = src->ViewportArray[i].X; - dst->ViewportArray[i].Y = src->ViewportArray[i].Y; - dst->ViewportArray[i].Width = src->ViewportArray[i].Width; - dst->ViewportArray[i].Height = src->ViewportArray[i].Height; - dst->ViewportArray[i].Near = src->ViewportArray[i].Near; - dst->ViewportArray[i].Far = src->ViewportArray[i].Far; - _math_matrix_copy(&dst->ViewportArray[i]._WindowMap, - &src->ViewportArray[i]._WindowMap); + /* OK to memcpy */ + dst->ViewportArray[i] = src->ViewportArray[i]; } } diff --git a/mesalib/src/mesa/main/debug.c b/mesalib/src/mesa/main/debug.c index b50d79e0c..c93e84a04 100644 --- a/mesalib/src/mesa/main/debug.c +++ b/mesalib/src/mesa/main/debug.c @@ -26,11 +26,11 @@ #include <stdio.h> #include "mtypes.h" #include "attrib.h" -#include "colormac.h" #include "enums.h" #include "formats.h" #include "hash.h" #include "imports.h" +#include "macros.h" #include "debug.h" #include "get.h" #include "pixelstore.h" diff --git a/mesalib/src/mesa/main/dlopen.h b/mesalib/src/mesa/main/dlopen.h index 1e7784914..4d20ff2c7 100644 --- a/mesalib/src/mesa/main/dlopen.h +++ b/mesalib/src/mesa/main/dlopen.h @@ -50,7 +50,7 @@ _mesa_dlopen(const char *libname, int flags) #if defined(HAVE_DLOPEN) flags = RTLD_LAZY | RTLD_GLOBAL; /* Overriding flags at this time */ return dlopen(libname, flags); -#elif defined(__MINGW32__) +#elif defined(_WIN32) return LoadLibraryA(libname); #else return NULL; @@ -71,7 +71,7 @@ _mesa_dlsym(void *handle, const char *fname) } u; #if defined(HAVE_DLOPEN) u.v = dlsym(handle, fname); -#elif defined(__MINGW32__) +#elif defined(_WIN32) u.v = (void *) GetProcAddress(handle, fname); #else u.v = NULL; @@ -87,7 +87,7 @@ _mesa_dlclose(void *handle) { #if defined(HAVE_DLOPEN) dlclose(handle); -#elif defined(__MINGW32__) +#elif defined(_WIN32) FreeLibrary(handle); #else (void) handle; diff --git a/mesalib/src/mesa/main/errors.c b/mesalib/src/mesa/main/errors.c index 8ffbf413c..2aa1deb63 100644 --- a/mesalib/src/mesa/main/errors.c +++ b/mesalib/src/mesa/main/errors.c @@ -1232,12 +1232,14 @@ _mesa_free_errors_data(struct gl_context *ctx) /** \name Diagnostics */ /*@{*/ +static FILE *LogFile = NULL; + + static void output_if_debug(const char *prefixString, const char *outputString, GLboolean newline) { static int debug = -1; - static FILE *fout = NULL; /* Init the local 'debug' var once. * Note: the _mesa_init_debug() function should have been called @@ -1249,9 +1251,9 @@ output_if_debug(const char *prefixString, const char *outputString, */ const char *logFile = getenv("MESA_LOG_FILE"); if (logFile) - fout = fopen(logFile, "w"); - if (!fout) - fout = stderr; + LogFile = fopen(logFile, "w"); + if (!LogFile) + LogFile = stderr; #ifdef DEBUG /* in debug builds, print messages unless MESA_DEBUG="silent" */ if (MESA_DEBUG_FLAGS & DEBUG_SILENT) @@ -1266,10 +1268,13 @@ output_if_debug(const char *prefixString, const char *outputString, /* Now only print the string if we're required to do so. */ if (debug) { - fprintf(fout, "%s: %s", prefixString, outputString); + if (prefixString) + fprintf(LogFile, "%s: %s", prefixString, outputString); + else + fprintf(LogFile, "%s", outputString); if (newline) - fprintf(fout, "\n"); - fflush(fout); + fprintf(LogFile, "\n"); + fflush(LogFile); #if defined(_WIN32) /* stderr from windows applications without console is not usually @@ -1285,6 +1290,18 @@ output_if_debug(const char *prefixString, const char *outputString, /** + * Return the file handle to use for debug/logging. Defaults to stderr + * unless MESA_LOG_FILE is defined. + */ +FILE * +_mesa_get_log_file(void) +{ + assert(LogFile); + return LogFile; +} + + +/** * When a new type of error is recorded, print a message describing * previous errors which were accumulated. */ @@ -1525,6 +1542,18 @@ _mesa_debug( const struct gl_context *ctx, const char *fmtString, ... ) } +void +_mesa_log(const char *fmtString, ...) +{ + char s[MAX_DEBUG_MESSAGE_LENGTH]; + va_list args; + va_start(args, fmtString); + _mesa_vsnprintf(s, MAX_DEBUG_MESSAGE_LENGTH, fmtString, args); + va_end(args); + output_if_debug("", s, GL_FALSE); +} + + /** * Report debug information from the shader compiler via GL_ARB_debug_output. * diff --git a/mesalib/src/mesa/main/errors.h b/mesalib/src/mesa/main/errors.h index 0c521c0d0..e6dc9b5f1 100644 --- a/mesalib/src/mesa/main/errors.h +++ b/mesalib/src/mesa/main/errors.h @@ -36,6 +36,7 @@ #define ERRORS_H +#include <stdio.h> #include "compiler.h" #include "glheader.h" #include "mtypes.h" @@ -69,6 +70,12 @@ extern void _mesa_debug( const struct gl_context *ctx, const char *fmtString, ... ) PRINTFLIKE(2, 3); extern void +_mesa_log(const char *fmtString, ...) PRINTFLIKE(1, 2); + +extern FILE * +_mesa_get_log_file(void); + +extern void _mesa_gl_debug(struct gl_context *ctx, GLuint *id, enum mesa_debug_source source, diff --git a/mesalib/src/mesa/main/extensions.c b/mesalib/src/mesa/main/extensions.c index f21201538..861b15006 100644 --- a/mesalib/src/mesa/main/extensions.c +++ b/mesalib/src/mesa/main/extensions.c @@ -139,6 +139,7 @@ static const struct extension extension_table[] = { { "GL_ARB_pixel_buffer_object", o(EXT_pixel_buffer_object), GL, 2004 }, { "GL_ARB_point_parameters", o(EXT_point_parameters), GLL, 1997 }, { "GL_ARB_point_sprite", o(ARB_point_sprite), GL, 2003 }, + { "GL_ARB_program_interface_query", o(dummy_true), GL, 2012 }, { "GL_ARB_provoking_vertex", o(EXT_provoking_vertex), GL, 2009 }, { "GL_ARB_robustness", o(dummy_true), GL, 2010 }, { "GL_ARB_sample_shading", o(ARB_sample_shading), GL, 2009 }, diff --git a/mesalib/src/mesa/main/fbobject.c b/mesalib/src/mesa/main/fbobject.c index f8d0d92bf..8032585ab 100644 --- a/mesalib/src/mesa/main/fbobject.c +++ b/mesalib/src/mesa/main/fbobject.c @@ -212,13 +212,13 @@ get_attachment(struct gl_context *ctx, struct gl_framebuffer *fb, */ i = attachment - GL_COLOR_ATTACHMENT0_EXT; if (i >= ctx->Const.MaxColorAttachments - || (i > 0 && ctx->API == API_OPENGLES)) { - return NULL; + || (i > 0 && ctx->API == API_OPENGLES)) { + return NULL; } return &fb->Attachment[BUFFER_COLOR0 + i]; case GL_DEPTH_STENCIL_ATTACHMENT: if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx)) - return NULL; + return NULL; /* fall-through */ case GL_DEPTH_ATTACHMENT_EXT: return &fb->Attachment[BUFFER_DEPTH]; @@ -1122,28 +1122,28 @@ _mesa_test_framebuffer_completeness(struct gl_context *ctx, if (_mesa_is_desktop_gl(ctx) && !ctx->Extensions.ARB_ES2_compatibility) { /* Check that all DrawBuffers are present */ for (j = 0; j < ctx->Const.MaxDrawBuffers; j++) { - if (fb->ColorDrawBuffer[j] != GL_NONE) { - const struct gl_renderbuffer_attachment *att - = get_attachment(ctx, fb, fb->ColorDrawBuffer[j]); - assert(att); - if (att->Type == GL_NONE) { - fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT; - fbo_incomplete(ctx, "missing drawbuffer", j); - return; - } - } + if (fb->ColorDrawBuffer[j] != GL_NONE) { + const struct gl_renderbuffer_attachment *att + = get_attachment(ctx, fb, fb->ColorDrawBuffer[j]); + assert(att); + if (att->Type == GL_NONE) { + fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT; + fbo_incomplete(ctx, "missing drawbuffer", j); + return; + } + } } /* Check that the ReadBuffer is present */ if (fb->ColorReadBuffer != GL_NONE) { - const struct gl_renderbuffer_attachment *att - = get_attachment(ctx, fb, fb->ColorReadBuffer); - assert(att); - if (att->Type == GL_NONE) { - fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT; + const struct gl_renderbuffer_attachment *att + = get_attachment(ctx, fb, fb->ColorReadBuffer); + assert(att); + if (att->Type == GL_NONE) { + fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT; fbo_incomplete(ctx, "missing readbuffer", -1); - return; - } + return; + } } } @@ -1205,6 +1205,28 @@ _mesa_IsRenderbuffer(GLuint renderbuffer) } +static struct gl_renderbuffer * +allocate_renderbuffer(struct gl_context *ctx, GLuint renderbuffer, + const char *func) +{ + struct gl_renderbuffer *newRb; + + /* create new renderbuffer object */ + newRb = ctx->Driver.NewRenderbuffer(ctx, renderbuffer); + if (!newRb) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func); + return NULL; + } + assert(newRb->AllocStorage); + mtx_lock(&ctx->Shared->Mutex); + _mesa_HashInsert(ctx->Shared->RenderBuffers, renderbuffer, newRb); + newRb->RefCount = 1; /* referenced by hash table */ + mtx_unlock(&ctx->Shared->Mutex); + + return newRb; +} + + static void bind_renderbuffer(GLenum target, GLuint renderbuffer, bool allow_user_names) { @@ -1233,15 +1255,7 @@ bind_renderbuffer(GLenum target, GLuint renderbuffer, bool allow_user_names) } if (!newRb) { - /* create new renderbuffer object */ - newRb = ctx->Driver.NewRenderbuffer(ctx, renderbuffer); - if (!newRb) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindRenderbufferEXT"); - return; - } - assert(newRb->AllocStorage); - _mesa_HashInsert(ctx->Shared->RenderBuffers, renderbuffer, newRb); - newRb->RefCount = 1; /* referenced by hash table */ + newRb = allocate_renderbuffer(ctx, renderbuffer, "glBindRenderbufferEXT"); } } else { @@ -1333,9 +1347,9 @@ _mesa_DeleteRenderbuffers(GLsizei n, const GLuint *renderbuffers) for (i = 0; i < n; i++) { if (renderbuffers[i] > 0) { - struct gl_renderbuffer *rb; - rb = _mesa_lookup_renderbuffer(ctx, renderbuffers[i]); - if (rb) { + struct gl_renderbuffer *rb; + rb = _mesa_lookup_renderbuffer(ctx, renderbuffers[i]); + if (rb) { /* check if deleting currently bound renderbuffer object */ if (rb == ctx->CurrentRenderbuffer) { /* bind default */ @@ -1368,31 +1382,31 @@ _mesa_DeleteRenderbuffers(GLsizei n, const GLuint *renderbuffers) _mesa_detach_renderbuffer(ctx, ctx->ReadBuffer, rb); } - /* Remove from hash table immediately, to free the ID. + /* Remove from hash table immediately, to free the ID. * But the object will not be freed until it's no longer * referenced anywhere else. */ - _mesa_HashRemove(ctx->Shared->RenderBuffers, renderbuffers[i]); + _mesa_HashRemove(ctx->Shared->RenderBuffers, renderbuffers[i]); if (rb != &DummyRenderbuffer) { /* no longer referenced by hash table */ _mesa_reference_renderbuffer(&rb, NULL); - } - } + } + } } } } - -void GLAPIENTRY -_mesa_GenRenderbuffers(GLsizei n, GLuint *renderbuffers) +static void +create_render_buffers(struct gl_context *ctx, GLsizei n, GLuint *renderbuffers, + bool dsa) { - GET_CURRENT_CONTEXT(ctx); + const char *func = dsa ? "glCreateRenderbuffers" : "glGenRenderbuffers"; GLuint first; GLint i; if (n < 0) { - _mesa_error(ctx, GL_INVALID_VALUE, "glGenRenderbuffersEXT(n)"); + _mesa_error(ctx, GL_INVALID_VALUE, "%s(n<0)", func); return; } @@ -1404,14 +1418,35 @@ _mesa_GenRenderbuffers(GLsizei n, GLuint *renderbuffers) for (i = 0; i < n; i++) { GLuint name = first + i; renderbuffers[i] = name; - /* insert dummy placeholder into hash table */ - mtx_lock(&ctx->Shared->Mutex); - _mesa_HashInsert(ctx->Shared->RenderBuffers, name, &DummyRenderbuffer); - mtx_unlock(&ctx->Shared->Mutex); + + if (dsa) { + allocate_renderbuffer(ctx, name, func); + } else { + /* insert a dummy renderbuffer into the hash table */ + mtx_lock(&ctx->Shared->Mutex); + _mesa_HashInsert(ctx->Shared->RenderBuffers, name, &DummyRenderbuffer); + mtx_unlock(&ctx->Shared->Mutex); + } } } +void GLAPIENTRY +_mesa_GenRenderbuffers(GLsizei n, GLuint *renderbuffers) +{ + GET_CURRENT_CONTEXT(ctx); + create_render_buffers(ctx, n, renderbuffers, false); +} + + +void GLAPIENTRY +_mesa_CreateRenderbuffers(GLsizei n, GLuint *renderbuffers) +{ + GET_CURRENT_CONTEXT(ctx); + create_render_buffers(ctx, n, renderbuffers, true); +} + + /** * Given an internal format token for a render buffer, return the * corresponding base format (one of GL_RGB, GL_RGBA, GL_STENCIL_INDEX, @@ -1749,40 +1784,17 @@ invalidate_rb(GLuint key, void *data, void *userData) /** - * Helper function used by _mesa_RenderbufferStorage() and - * _mesa_RenderbufferStorageMultisample(). - * samples will be NO_SAMPLES if called by _mesa_RenderbufferStorage(). + * Helper function used by renderbuffer_storage_direct() and + * renderbuffer_storage_target(). + * samples will be NO_SAMPLES if called by a non-multisample function. */ static void -renderbuffer_storage(GLenum target, GLenum internalFormat, - GLsizei width, GLsizei height, GLsizei samples) +renderbuffer_storage(struct gl_context *ctx, struct gl_renderbuffer *rb, + GLenum internalFormat, GLsizei width, + GLsizei height, GLsizei samples, const char *func) { - const char *func = samples == NO_SAMPLES ? - "glRenderbufferStorage" : "glRenderbufferStorageMultisample"; - struct gl_renderbuffer *rb; GLenum baseFormat; GLenum sample_count_error; - GET_CURRENT_CONTEXT(ctx); - - if (MESA_VERBOSE & VERBOSE_API) { - if (samples == NO_SAMPLES) - _mesa_debug(ctx, "%s(%s, %s, %d, %d)\n", - func, - _mesa_lookup_enum_by_nr(target), - _mesa_lookup_enum_by_nr(internalFormat), - width, height); - else - _mesa_debug(ctx, "%s(%s, %s, %d, %d, %d)\n", - func, - _mesa_lookup_enum_by_nr(target), - _mesa_lookup_enum_by_nr(internalFormat), - width, height, samples); - } - - if (target != GL_RENDERBUFFER_EXT) { - _mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", func); - return; - } baseFormat = _mesa_base_fbo_format(ctx, internalFormat); if (baseFormat == 0) { @@ -1792,12 +1804,14 @@ renderbuffer_storage(GLenum target, GLenum internalFormat, } if (width < 0 || width > (GLsizei) ctx->Const.MaxRenderbufferSize) { - _mesa_error(ctx, GL_INVALID_VALUE, "%s(width)", func); + _mesa_error(ctx, GL_INVALID_VALUE, "%s(invalid width %d)", func, + width); return; } if (height < 0 || height > (GLsizei) ctx->Const.MaxRenderbufferSize) { - _mesa_error(ctx, GL_INVALID_VALUE, "%s(height)", func); + _mesa_error(ctx, GL_INVALID_VALUE, "%s(invalid height %d)", func, + height); return; } @@ -1809,7 +1823,7 @@ renderbuffer_storage(GLenum target, GLenum internalFormat, /* check the sample count; * note: driver may choose to use more samples than what's requested */ - sample_count_error = _mesa_check_sample_count(ctx, target, + sample_count_error = _mesa_check_sample_count(ctx, GL_RENDERBUFFER, internalFormat, samples); if (sample_count_error != GL_NO_ERROR) { _mesa_error(ctx, sample_count_error, "%s(samples)", func); @@ -1817,12 +1831,6 @@ renderbuffer_storage(GLenum target, GLenum internalFormat, } } - rb = ctx->CurrentRenderbuffer; - if (!rb) { - _mesa_error(ctx, GL_INVALID_OPERATION, "%s", func); - return; - } - FLUSH_VERTICES(ctx, _NEW_BUFFERS); if (rb->InternalFormat == internalFormat && @@ -1864,6 +1872,83 @@ renderbuffer_storage(GLenum target, GLenum internalFormat, } } +/** + * Helper function used by _mesa_NamedRenderbufferStorage*(). + * samples will be NO_SAMPLES if called by a non-multisample function. + */ +static void +renderbuffer_storage_named(GLuint renderbuffer, GLenum internalFormat, + GLsizei width, GLsizei height, GLsizei samples, + const char *func) +{ + GET_CURRENT_CONTEXT(ctx); + + if (MESA_VERBOSE & VERBOSE_API) { + if (samples == NO_SAMPLES) + _mesa_debug(ctx, "%s(%u, %s, %d, %d)\n", + func, renderbuffer, + _mesa_lookup_enum_by_nr(internalFormat), + width, height); + else + _mesa_debug(ctx, "%s(%u, %s, %d, %d, %d)\n", + func, renderbuffer, + _mesa_lookup_enum_by_nr(internalFormat), + width, height, samples); + } + + struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, renderbuffer); + if (!rb || rb == &DummyRenderbuffer) { + /* ID was reserved, but no real renderbuffer object made yet */ + _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid renderbuffer %u)", + func, renderbuffer); + return; + } + + renderbuffer_storage(ctx, rb, internalFormat, width, height, samples, func); +} + +/** + * Helper function used by _mesa_RenderbufferStorage() and + * _mesa_RenderbufferStorageMultisample(). + * samples will be NO_SAMPLES if called by _mesa_RenderbufferStorage(). + */ +static void +renderbuffer_storage_target(GLenum target, GLenum internalFormat, + GLsizei width, GLsizei height, GLsizei samples, + const char *func) +{ + GET_CURRENT_CONTEXT(ctx); + + if (MESA_VERBOSE & VERBOSE_API) { + if (samples == NO_SAMPLES) + _mesa_debug(ctx, "%s(%s, %s, %d, %d)\n", + func, + _mesa_lookup_enum_by_nr(target), + _mesa_lookup_enum_by_nr(internalFormat), + width, height); + else + _mesa_debug(ctx, "%s(%s, %s, %d, %d, %d)\n", + func, + _mesa_lookup_enum_by_nr(target), + _mesa_lookup_enum_by_nr(internalFormat), + width, height, samples); + } + + if (target != GL_RENDERBUFFER_EXT) { + _mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", func); + return; + } + + if (!ctx->CurrentRenderbuffer) { + _mesa_error(ctx, GL_INVALID_OPERATION, "%s(no renderbuffer bound)", + func); + return; + } + + renderbuffer_storage(ctx, ctx->CurrentRenderbuffer, internalFormat, width, + height, samples, func); +} + void GLAPIENTRY _mesa_EGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image) @@ -1923,7 +2008,8 @@ _mesa_RenderbufferStorage(GLenum target, GLenum internalFormat, * glRenderbufferStorageMultisample() with samples=0. We pass in * a token value here just for error reporting purposes. */ - renderbuffer_storage(target, internalFormat, width, height, NO_SAMPLES); + renderbuffer_storage_target(target, internalFormat, width, height, + NO_SAMPLES, "glRenderbufferStorage"); } @@ -1932,7 +2018,8 @@ _mesa_RenderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height) { - renderbuffer_storage(target, internalFormat, width, height, samples); + renderbuffer_storage_target(target, internalFormat, width, height, + samples, "glRenderbufferStorageMultisample"); } @@ -1941,7 +2028,7 @@ _mesa_RenderbufferStorageMultisample(GLenum target, GLsizei samples, */ void GLAPIENTRY _es_RenderbufferStorageEXT(GLenum target, GLenum internalFormat, - GLsizei width, GLsizei height) + GLsizei width, GLsizei height) { switch (internalFormat) { case GL_RGB565: @@ -1953,29 +2040,38 @@ _es_RenderbufferStorageEXT(GLenum target, GLenum internalFormat, break; } - renderbuffer_storage(target, internalFormat, width, height, 0); + renderbuffer_storage_target(target, internalFormat, width, height, 0, + "glRenderbufferStorageEXT"); } - void GLAPIENTRY -_mesa_GetRenderbufferParameteriv(GLenum target, GLenum pname, GLint *params) +_mesa_NamedRenderbufferStorage(GLuint renderbuffer, GLenum internalformat, + GLsizei width, GLsizei height) { - struct gl_renderbuffer *rb; - GET_CURRENT_CONTEXT(ctx); + /* GL_ARB_fbo says calling this function is equivalent to calling + * glRenderbufferStorageMultisample() with samples=0. We pass in + * a token value here just for error reporting purposes. + */ + renderbuffer_storage_named(renderbuffer, internalformat, width, height, + NO_SAMPLES, "glNamedRenderbufferStorage"); +} - if (target != GL_RENDERBUFFER_EXT) { - _mesa_error(ctx, GL_INVALID_ENUM, - "glGetRenderbufferParameterivEXT(target)"); - return; - } +void GLAPIENTRY +_mesa_NamedRenderbufferStorageMultisample(GLuint renderbuffer, GLsizei samples, + GLenum internalformat, + GLsizei width, GLsizei height) +{ + renderbuffer_storage_named(renderbuffer, internalformat, width, height, + samples, + "glNamedRenderbufferStorageMultisample"); +} - rb = ctx->CurrentRenderbuffer; - if (!rb) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glGetRenderbufferParameterivEXT"); - return; - } +static void +get_render_buffer_parameteriv(struct gl_context *ctx, + struct gl_renderbuffer *rb, GLenum pname, + GLint *params, const char *func) +{ /* No need to flush here since we're just quering state which is * not effected by rendering. */ @@ -2006,10 +2102,51 @@ _mesa_GetRenderbufferParameteriv(GLenum target, GLenum pname, GLint *params) } /* fallthrough */ default: + _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid pname=%s)", func, + _mesa_lookup_enum_by_nr(pname)); + return; + } +} + + +void GLAPIENTRY +_mesa_GetRenderbufferParameteriv(GLenum target, GLenum pname, GLint *params) +{ + GET_CURRENT_CONTEXT(ctx); + + if (target != GL_RENDERBUFFER_EXT) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetRenderbufferParameterivEXT(target)"); return; } + + if (!ctx->CurrentRenderbuffer) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glGetRenderbufferParameterivEXT" + "(no renderbuffer bound)"); + return; + } + + get_render_buffer_parameteriv(ctx, ctx->CurrentRenderbuffer, pname, + params, "glGetRenderbufferParameteriv"); +} + + +void GLAPIENTRY +_mesa_GetNamedRenderbufferParameteriv(GLuint renderbuffer, GLenum pname, + GLint *params) +{ + GET_CURRENT_CONTEXT(ctx); + + struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, renderbuffer); + if (!rb || rb == &DummyRenderbuffer) { + /* ID was reserved, but no real renderbuffer object made yet */ + _mesa_error(ctx, GL_INVALID_OPERATION, "glGetNamedRenderbufferParameteriv" + "(invalid renderbuffer %i)", renderbuffer); + return; + } + + get_render_buffer_parameteriv(ctx, rb, pname, params, + "glGetNamedRenderbufferParameteriv"); } @@ -2116,12 +2253,12 @@ bind_framebuffer(GLenum target, GLuint framebuffer, bool allow_user_names) } if (!newDrawFb) { - /* create new framebuffer object */ - newDrawFb = ctx->Driver.NewFramebuffer(ctx, framebuffer); - if (!newDrawFb) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindFramebufferEXT"); - return; - } + /* create new framebuffer object */ + newDrawFb = ctx->Driver.NewFramebuffer(ctx, framebuffer); + if (!newDrawFb) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindFramebufferEXT"); + return; + } _mesa_HashInsert(ctx->Shared->FrameBuffers, framebuffer, newDrawFb); } newReadFb = newDrawFb; @@ -2224,9 +2361,9 @@ _mesa_DeleteFramebuffers(GLsizei n, const GLuint *framebuffers) for (i = 0; i < n; i++) { if (framebuffers[i] > 0) { - struct gl_framebuffer *fb; - fb = _mesa_lookup_framebuffer(ctx, framebuffers[i]); - if (fb) { + struct gl_framebuffer *fb; + fb = _mesa_lookup_framebuffer(ctx, framebuffers[i]); + if (fb) { assert(fb == &DummyFramebuffer || fb->Name == framebuffers[i]); /* check if deleting currently bound framebuffer object */ @@ -2241,16 +2378,16 @@ _mesa_DeleteFramebuffers(GLsizei n, const GLuint *framebuffers) _mesa_BindFramebuffer(GL_READ_FRAMEBUFFER, 0); } - /* remove from hash table immediately, to free the ID */ - _mesa_HashRemove(ctx->Shared->FrameBuffers, framebuffers[i]); + /* remove from hash table immediately, to free the ID */ + _mesa_HashRemove(ctx->Shared->FrameBuffers, framebuffers[i]); if (fb != &DummyFramebuffer) { /* But the object will not be freed until it's no longer * bound in any context. */ _mesa_reference_framebuffer(&fb, NULL); - } - } + } + } } } } @@ -2498,34 +2635,34 @@ framebuffer_texture(struct gl_context *ctx, const char *caller, GLenum target, _mesa_tex_target_to_face(textarget) == fb->Attachment[BUFFER_STENCIL].CubeMapFace && zoffset == fb->Attachment[BUFFER_STENCIL].Zoffset) { - /* The texture object is already attached to the stencil attachment - * point. Don't create a new renderbuffer; just reuse the stencil - * attachment's. This is required to prevent a GL error in - * glGetFramebufferAttachmentParameteriv(GL_DEPTH_STENCIL). - */ - reuse_framebuffer_texture_attachment(fb, BUFFER_DEPTH, - BUFFER_STENCIL); + /* The texture object is already attached to the stencil attachment + * point. Don't create a new renderbuffer; just reuse the stencil + * attachment's. This is required to prevent a GL error in + * glGetFramebufferAttachmentParameteriv(GL_DEPTH_STENCIL). + */ + reuse_framebuffer_texture_attachment(fb, BUFFER_DEPTH, + BUFFER_STENCIL); } else if (attachment == GL_STENCIL_ATTACHMENT && - texObj == fb->Attachment[BUFFER_DEPTH].Texture && + texObj == fb->Attachment[BUFFER_DEPTH].Texture && level == fb->Attachment[BUFFER_DEPTH].TextureLevel && _mesa_tex_target_to_face(textarget) == fb->Attachment[BUFFER_DEPTH].CubeMapFace && zoffset == fb->Attachment[BUFFER_DEPTH].Zoffset) { - /* As above, but with depth and stencil transposed. */ - reuse_framebuffer_texture_attachment(fb, BUFFER_STENCIL, - BUFFER_DEPTH); + /* As above, but with depth and stencil transposed. */ + reuse_framebuffer_texture_attachment(fb, BUFFER_STENCIL, + BUFFER_DEPTH); } else { - set_texture_attachment(ctx, fb, att, texObj, textarget, - level, zoffset, layered); - if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) { - /* Above we created a new renderbuffer and attached it to the - * depth attachment point. Now attach it to the stencil attachment - * point too. - */ - assert(att == &fb->Attachment[BUFFER_DEPTH]); - reuse_framebuffer_texture_attachment(fb,BUFFER_STENCIL, - BUFFER_DEPTH); - } + set_texture_attachment(ctx, fb, att, texObj, textarget, + level, zoffset, layered); + if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) { + /* Above we created a new renderbuffer and attached it to the + * depth attachment point. Now attach it to the stencil attachment + * point too. + */ + assert(att == &fb->Attachment[BUFFER_DEPTH]); + reuse_framebuffer_texture_attachment(fb,BUFFER_STENCIL, + BUFFER_DEPTH); + } } /* Set the render-to-texture flag. We'll check this flag in @@ -2541,8 +2678,8 @@ framebuffer_texture(struct gl_context *ctx, const char *caller, GLenum target, else { remove_attachment(ctx, att); if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) { - assert(att == &fb->Attachment[BUFFER_DEPTH]); - remove_attachment(ctx, &fb->Attachment[BUFFER_STENCIL]); + assert(att == &fb->Attachment[BUFFER_DEPTH]); + remove_attachment(ctx, &fb->Attachment[BUFFER_STENCIL]); } } @@ -2721,16 +2858,16 @@ _mesa_FramebufferRenderbuffer(GLenum target, GLenum attachment, if (renderbuffer) { rb = _mesa_lookup_renderbuffer(ctx, renderbuffer); if (!rb) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glFramebufferRenderbuffer(non-existant" + _mesa_error(ctx, GL_INVALID_OPERATION, + "glFramebufferRenderbuffer(non-existant" " renderbuffer %u)", renderbuffer); - return; + return; } else if (rb == &DummyRenderbuffer) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glFramebufferRenderbuffer(renderbuffer %u)", + _mesa_error(ctx, GL_INVALID_OPERATION, + "glFramebufferRenderbuffer(renderbuffer %u)", renderbuffer); - return; + return; } } else { @@ -2795,9 +2932,9 @@ _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, if ((!_mesa_is_desktop_gl(ctx) || !ctx->Extensions.ARB_framebuffer_object) && !_mesa_is_gles3(ctx)) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glGetFramebufferAttachmentParameteriv(bound FBO = 0)"); - return; + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetFramebufferAttachmentParameteriv(bound FBO = 0)"); + return; } if (_mesa_is_gles3(ctx) && attachment != GL_BACK && @@ -2855,10 +2992,10 @@ _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, return; case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT: if (att->Type == GL_RENDERBUFFER_EXT) { - *params = att->Renderbuffer->Name; + *params = att->Renderbuffer->Name; } else if (att->Type == GL_TEXTURE) { - *params = att->Texture->Name; + *params = att->Texture->Name; } else { assert(att->Type == GL_NONE); @@ -2871,7 +3008,7 @@ _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, return; case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT: if (att->Type == GL_TEXTURE) { - *params = att->TextureLevel; + *params = att->TextureLevel; } else if (att->Type == GL_NONE) { _mesa_error(ctx, err, diff --git a/mesalib/src/mesa/main/fbobject.h b/mesalib/src/mesa/main/fbobject.h index 77fdef415..61aa1f503 100644 --- a/mesalib/src/mesa/main/fbobject.h +++ b/mesalib/src/mesa/main/fbobject.h @@ -115,6 +115,9 @@ extern void GLAPIENTRY _mesa_GenRenderbuffers(GLsizei n, GLuint *renderbuffers); extern void GLAPIENTRY +_mesa_CreateRenderbuffers(GLsizei n, GLuint *renderbuffers); + +extern void GLAPIENTRY _mesa_RenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height); @@ -128,12 +131,25 @@ _es_RenderbufferStorageEXT(GLenum target, GLenum internalFormat, GLsizei width, GLsizei height); extern void GLAPIENTRY +_mesa_NamedRenderbufferStorage(GLuint renderbuffer, GLenum internalformat, + GLsizei width, GLsizei height); + +extern void GLAPIENTRY +_mesa_NamedRenderbufferStorageMultisample(GLuint renderbuffer, GLsizei samples, + GLenum internalformat, + GLsizei width, GLsizei height); + +extern void GLAPIENTRY _mesa_EGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image); extern void GLAPIENTRY _mesa_GetRenderbufferParameteriv(GLenum target, GLenum pname, GLint *params); +void GLAPIENTRY +_mesa_GetNamedRenderbufferParameteriv(GLuint renderbuffer, GLenum pname, + GLint *params); + extern GLboolean GLAPIENTRY _mesa_IsFramebuffer(GLuint framebuffer); diff --git a/mesalib/src/mesa/main/ffvertex_prog.c b/mesalib/src/mesa/main/ffvertex_prog.c index 395b00e15..edf7e3390 100644 --- a/mesalib/src/mesa/main/ffvertex_prog.c +++ b/mesalib/src/mesa/main/ffvertex_prog.c @@ -619,13 +619,13 @@ static void emit_op3fn(struct tnl_program *p, #define emit_op3(p, op, dst, mask, src0, src1, src2) \ - emit_op3fn(p, op, dst, mask, src0, src1, src2, __FUNCTION__, __LINE__) + emit_op3fn(p, op, dst, mask, src0, src1, src2, __func__, __LINE__) #define emit_op2(p, op, dst, mask, src0, src1) \ - emit_op3fn(p, op, dst, mask, src0, src1, undef, __FUNCTION__, __LINE__) + emit_op3fn(p, op, dst, mask, src0, src1, undef, __func__, __LINE__) #define emit_op1(p, op, dst, mask, src0) \ - emit_op3fn(p, op, dst, mask, src0, undef, undef, __FUNCTION__, __LINE__) + emit_op3fn(p, op, dst, mask, src0, undef, undef, __func__, __LINE__) static struct ureg make_temp( struct tnl_program *p, struct ureg reg ) diff --git a/mesalib/src/mesa/main/format_pack.py b/mesalib/src/mesa/main/format_pack.py index f141da83c..2f43a30dd 100644 --- a/mesalib/src/mesa/main/format_pack.py +++ b/mesalib/src/mesa/main/format_pack.py @@ -43,7 +43,6 @@ string = """/* #include <stdint.h> -#include "colormac.h" #include "format_pack.h" #include "format_utils.h" #include "macros.h" diff --git a/mesalib/src/mesa/main/format_unpack.h b/mesalib/src/mesa/main/format_unpack.h index eba3c6650..964c6077a 100644 --- a/mesalib/src/mesa/main/format_unpack.h +++ b/mesalib/src/mesa/main/format_unpack.h @@ -25,6 +25,8 @@ #ifndef FORMAT_UNPACK_H #define FORMAT_UNPACK_H +#include "formats.h" + extern void _mesa_unpack_rgba_row(mesa_format format, GLuint n, const void *src, GLfloat dst[][4]); diff --git a/mesalib/src/mesa/main/format_unpack.py b/mesalib/src/mesa/main/format_unpack.py index 53bdf641d..0ae73b897 100644 --- a/mesalib/src/mesa/main/format_unpack.py +++ b/mesalib/src/mesa/main/format_unpack.py @@ -43,7 +43,6 @@ string = """/* #include <stdint.h> -#include "colormac.h" #include "format_unpack.h" #include "format_utils.h" #include "macros.h" @@ -333,7 +332,7 @@ _mesa_unpack_rgba_row(mesa_format format, GLuint n, unpack_float_ycbcr_rev(src, dst, n); break; default: - _mesa_problem(NULL, "%s: bad format %s", __FUNCTION__, + _mesa_problem(NULL, "%s: bad format %s", __func__, _mesa_get_format_name(format)); return; } @@ -402,7 +401,7 @@ _mesa_unpack_uint_rgba_row(mesa_format format, GLuint n, break; %endfor default: - _mesa_problem(NULL, "%s: bad format %s", __FUNCTION__, + _mesa_problem(NULL, "%s: bad format %s", __func__, _mesa_get_format_name(format)); return; } diff --git a/mesalib/src/mesa/main/glformats.c b/mesalib/src/mesa/main/glformats.c index 4e05229cf..8ced57949 100644 --- a/mesalib/src/mesa/main/glformats.c +++ b/mesalib/src/mesa/main/glformats.c @@ -1393,7 +1393,7 @@ _mesa_base_format_has_channel(GLenum base_format, GLenum pname) return GL_FALSE; default: _mesa_warning(NULL, "%s: Unexpected channel token 0x%x\n", - __FUNCTION__, pname); + __func__, pname); return GL_FALSE; } diff --git a/mesalib/src/mesa/main/imports.h b/mesalib/src/mesa/main/imports.h index 29f249980..c4d917ebb 100644 --- a/mesalib/src/mesa/main/imports.h +++ b/mesalib/src/mesa/main/imports.h @@ -433,6 +433,30 @@ _mesa_fls(unsigned int n) #endif } +/** + * Find the last (most significant) bit set in a uint64_t value. + * + * Essentially ffsll() in the reverse direction. + */ +static inline unsigned int +_mesa_flsll(uint64_t n) +{ +#ifdef HAVE___BUILTIN_CLZLL + return n == 0 ? 0 : 64 - __builtin_clzll(n); +#else + unsigned int v = 1; + + if (n == 0) + return 0; + + while (n >>= 1) + v++; + + return v; +#endif +} + + extern GLhalfARB _mesa_float_to_half(float f); diff --git a/mesalib/src/mesa/main/macros.h b/mesalib/src/mesa/main/macros.h index 2d7a6a107..3344ec841 100644 --- a/mesalib/src/mesa/main/macros.h +++ b/mesalib/src/mesa/main/macros.h @@ -789,7 +789,14 @@ NORMALIZE_3FV(GLfloat v[3]) static inline GLboolean DIFFERENT_SIGNS(GLfloat x, GLfloat y) { +#ifdef _MSC_VER +#pragma warning( push ) +#pragma warning( disable : 6334 ) /* sizeof operator applied to an expression with an operator may yield unexpected results */ +#endif return signbit(x) != signbit(y); +#ifdef _MSC_VER +#pragma warning( pop ) +#endif } diff --git a/mesalib/src/mesa/main/mtypes.h b/mesalib/src/mesa/main/mtypes.h index 8e1dba6f0..1c751cfff 100644 --- a/mesalib/src/mesa/main/mtypes.h +++ b/mesalib/src/mesa/main/mtypes.h @@ -42,6 +42,7 @@ #include "main/config.h" #include "glapi/glapi.h" #include "math/m_matrix.h" /* GLmatrix */ +#include "glsl/shader_enums.h" #include "util/simple_list.h" /* struct simple_node */ #include "main/formats.h" /* MESA_FORMAT_COUNT */ @@ -280,13 +281,6 @@ typedef enum /*@}*/ /** - * Bitflags for system values. - */ -#define SYSTEM_BIT_SAMPLE_ID BITFIELD64_BIT(SYSTEM_VALUE_SAMPLE_ID) -#define SYSTEM_BIT_SAMPLE_POS BITFIELD64_BIT(SYSTEM_VALUE_SAMPLE_POS) -#define SYSTEM_BIT_SAMPLE_MASK_IN BITFIELD64_BIT(SYSTEM_VALUE_SAMPLE_MASK_IN) - -/** * Determine if the given gl_varying_slot appears in the fragment shader. */ static inline GLboolean @@ -395,25 +389,6 @@ typedef enum BUFFER_BIT_COLOR6 | \ BUFFER_BIT_COLOR7) - -/** - * Shader stages. Note that these will become 5 with tessellation. - * - * The order must match how shaders are ordered in the pipeline. - * The GLSL linker assumes that if i<j, then the j-th shader is - * executed later than the i-th shader. - */ -typedef enum -{ - MESA_SHADER_VERTEX = 0, - MESA_SHADER_GEOMETRY = 1, - MESA_SHADER_FRAGMENT = 2, - MESA_SHADER_COMPUTE = 3, -} gl_shader_stage; - -#define MESA_SHADER_STAGES (MESA_SHADER_COMPUTE + 1) - - /** * Framebuffer configuration (aka visual / pixelformat) * Note: some of these fields should be boolean, but it appears that @@ -1456,7 +1431,6 @@ struct gl_viewport_attrib GLfloat X, Y; /**< position */ GLfloat Width, Height; /**< size */ GLdouble Near, Far; /**< Depth buffer range */ - GLmatrix _WindowMap; /**< Mapping transformation as a matrix. */ }; @@ -2082,140 +2056,6 @@ typedef enum /** - * If the register file is PROGRAM_SYSTEM_VALUE, the register index will be - * one of these values. - */ -typedef enum -{ - /** - * \name Vertex shader system values - */ - /*@{*/ - /** - * OpenGL-style vertex ID. - * - * Section 2.11.7 (Shader Execution), subsection Shader Inputs, of the - * OpenGL 3.3 core profile spec says: - * - * "gl_VertexID holds the integer index i implicitly passed by - * DrawArrays or one of the other drawing commands defined in section - * 2.8.3." - * - * Section 2.8.3 (Drawing Commands) of the same spec says: - * - * "The commands....are equivalent to the commands with the same base - * name (without the BaseVertex suffix), except that the ith element - * transferred by the corresponding draw call will be taken from - * element indices[i] + basevertex of each enabled array." - * - * Additionally, the overview in the GL_ARB_shader_draw_parameters spec - * says: - * - * "In unextended GL, vertex shaders have inputs named gl_VertexID and - * gl_InstanceID, which contain, respectively the index of the vertex - * and instance. The value of gl_VertexID is the implicitly passed - * index of the vertex being processed, which includes the value of - * baseVertex, for those commands that accept it." - * - * gl_VertexID gets basevertex added in. This differs from DirectX where - * SV_VertexID does \b not get basevertex added in. - * - * \note - * If all system values are available, \c SYSTEM_VALUE_VERTEX_ID will be - * equal to \c SYSTEM_VALUE_VERTEX_ID_ZERO_BASE plus - * \c SYSTEM_VALUE_BASE_VERTEX. - * - * \sa SYSTEM_VALUE_VERTEX_ID_ZERO_BASE, SYSTEM_VALUE_BASE_VERTEX - */ - SYSTEM_VALUE_VERTEX_ID, - - /** - * Instanced ID as supplied to gl_InstanceID - * - * Values assigned to gl_InstanceID always begin with zero, regardless of - * the value of baseinstance. - * - * Section 11.1.3.9 (Shader Inputs) of the OpenGL 4.4 core profile spec - * says: - * - * "gl_InstanceID holds the integer instance number of the current - * primitive in an instanced draw call (see section 10.5)." - * - * Through a big chain of pseudocode, section 10.5 describes that - * baseinstance is not counted by gl_InstanceID. In that section, notice - * - * "If an enabled vertex attribute array is instanced (it has a - * non-zero divisor as specified by VertexAttribDivisor), the element - * index that is transferred to the GL, for all vertices, is given by - * - * floor(instance/divisor) + baseinstance - * - * If an array corresponding to an attribute required by a vertex - * shader is not enabled, then the corresponding element is taken from - * the current attribute state (see section 10.2)." - * - * Note that baseinstance is \b not included in the value of instance. - */ - SYSTEM_VALUE_INSTANCE_ID, - - /** - * DirectX-style vertex ID. - * - * Unlike \c SYSTEM_VALUE_VERTEX_ID, this system value does \b not include - * the value of basevertex. - * - * \sa SYSTEM_VALUE_VERTEX_ID, SYSTEM_VALUE_BASE_VERTEX - */ - SYSTEM_VALUE_VERTEX_ID_ZERO_BASE, - - /** - * Value of \c basevertex passed to \c glDrawElementsBaseVertex and similar - * functions. - * - * \sa SYSTEM_VALUE_VERTEX_ID, SYSTEM_VALUE_VERTEX_ID_ZERO_BASE - */ - SYSTEM_VALUE_BASE_VERTEX, - /*@}*/ - - /** - * \name Geometry shader system values - */ - /*@{*/ - SYSTEM_VALUE_INVOCATION_ID, - /*@}*/ - - /** - * \name Fragment shader system values - */ - /*@{*/ - SYSTEM_VALUE_FRONT_FACE, /**< (not done yet) */ - SYSTEM_VALUE_SAMPLE_ID, - SYSTEM_VALUE_SAMPLE_POS, - SYSTEM_VALUE_SAMPLE_MASK_IN, - /*@}*/ - - SYSTEM_VALUE_MAX /**< Number of values */ -} gl_system_value; - - -/** - * The possible interpolation qualifiers that can be applied to a fragment - * shader input in GLSL. - * - * Note: INTERP_QUALIFIER_NONE must be 0 so that memsetting the - * gl_fragment_program data structure to 0 causes the default behavior. - */ -enum glsl_interp_qualifier -{ - INTERP_QUALIFIER_NONE = 0, - INTERP_QUALIFIER_SMOOTH, - INTERP_QUALIFIER_FLAT, - INTERP_QUALIFIER_NOPERSPECTIVE, - INTERP_QUALIFIER_COUNT /**< Number of interpolation qualifiers */ -}; - - -/** * \brief Layout qualifiers for gl_FragDepth. * * Extension AMD_conservative_depth allows gl_FragDepth to be redeclared with @@ -2247,6 +2087,8 @@ struct gl_program struct prog_instruction *Instructions; + struct nir_shader *nir; + GLbitfield64 InputsRead; /**< Bitmask of which input regs are read */ GLbitfield64 OutputsWritten; /**< Bitmask of which output regs are written */ GLbitfield SystemValuesRead; /**< Bitmask of SYSTEM_VALUE_x inputs used */ @@ -2762,6 +2604,16 @@ struct gl_active_atomic_buffer }; /** + * Active resource in a gl_shader_program + */ +struct gl_program_resource +{ + GLenum Type; /** Program interface type. */ + const void *Data; /** Pointer to resource associated data structure. */ + uint8_t StageReferences; /** Bitmask of shader stage references. */ +}; + +/** * A GLSL program object. * Basically a linked collection of vertex and fragment shaders. */ @@ -2935,6 +2787,10 @@ struct gl_shader_program */ struct gl_shader *_LinkedShaders[MESA_SHADER_STAGES]; + /** List of all active resources after linking. */ + struct gl_program_resource *ProgramResourceList; + unsigned NumProgramResourceList; + /* True if any of the fragment shaders attached to this program use: * #extension ARB_fragment_coord_conventions: enable */ @@ -3527,8 +3383,8 @@ struct gl_constants GLboolean ForceGLSLExtensionsWarn; /** - * If non-zero, forces GLSL shaders without the #version directive to behave - * as if they began with "#version ForceGLSLVersion". + * If non-zero, forces GLSL shaders to behave as if they began + * with "#version ForceGLSLVersion". */ GLuint ForceGLSLVersion; @@ -4523,7 +4379,7 @@ struct gl_context #ifdef DEBUG extern int MESA_VERBOSE; extern int MESA_DEBUG_FLAGS; -# define MESA_FUNCTION __FUNCTION__ +# define MESA_FUNCTION __func__ #else # define MESA_VERBOSE 0 # define MESA_DEBUG_FLAGS 0 diff --git a/mesalib/src/mesa/main/multisample.c b/mesalib/src/mesa/main/multisample.c index 0e9207bc1..816837b95 100644 --- a/mesalib/src/mesa/main/multisample.c +++ b/mesalib/src/mesa/main/multisample.c @@ -150,6 +150,15 @@ GLenum _mesa_check_sample_count(struct gl_context *ctx, GLenum target, GLenum internalFormat, GLsizei samples) { + /* Section 2.5 (GL Errors) of OpenGL 3.0 specification, page 16: + * + * "If a negative number is provided where an argument of type sizei or + * sizeiptr is specified, the error INVALID VALUE is generated." + */ + if (samples < 0) { + return GL_INVALID_VALUE; + } + /* Section 4.4 (Framebuffer objects), page 198 of the OpenGL ES 3.0.0 * specification says: * diff --git a/mesalib/src/mesa/main/pipelineobj.c b/mesalib/src/mesa/main/pipelineobj.c index fb241af1e..0fefa7d56 100644 --- a/mesalib/src/mesa/main/pipelineobj.c +++ b/mesalib/src/mesa/main/pipelineobj.c @@ -498,16 +498,18 @@ _mesa_DeleteProgramPipelines(GLsizei n, const GLuint *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) +static void +create_program_pipelines(struct gl_context *ctx, GLsizei n, GLuint *pipelines, + bool dsa) { - GET_CURRENT_CONTEXT(ctx); - + const char *func; GLuint first; GLint i; + func = dsa ? "glCreateProgramPipelines" : "glGenProgramPipelines"; + if (n < 0) { - _mesa_error(ctx, GL_INVALID_VALUE, "glGenProgramPipelines(n<0)"); + _mesa_error(ctx, GL_INVALID_VALUE, "%s (n < 0)", func); return; } @@ -523,16 +525,37 @@ _mesa_GenProgramPipelines(GLsizei n, GLuint *pipelines) obj = _mesa_new_pipeline_object(ctx, name); if (!obj) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenProgramPipelines"); + _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func); return; } + if (dsa) { + /* make dsa-allocated objects behave like program objects */ + obj->EverBound = GL_TRUE; + } + save_pipeline_object(ctx, obj); pipelines[i] = first + i; } } +void GLAPIENTRY +_mesa_GenProgramPipelines(GLsizei n, GLuint *pipelines) +{ + GET_CURRENT_CONTEXT(ctx); + + create_program_pipelines(ctx, n, pipelines, false); +} + +void GLAPIENTRY +_mesa_CreateProgramPipelines(GLsizei n, GLuint *pipelines) +{ + GET_CURRENT_CONTEXT(ctx); + + create_program_pipelines(ctx, n, pipelines, true); +} + /** * Determine if ID is the name of an pipeline object. * diff --git a/mesalib/src/mesa/main/pipelineobj.h b/mesalib/src/mesa/main/pipelineobj.h index 7285a78f1..b57bcb99e 100644 --- a/mesalib/src/mesa/main/pipelineobj.h +++ b/mesalib/src/mesa/main/pipelineobj.h @@ -82,6 +82,9 @@ _mesa_DeleteProgramPipelines(GLsizei n, const GLuint *pipelines); extern void GLAPIENTRY _mesa_GenProgramPipelines(GLsizei n, GLuint *pipelines); +void GLAPIENTRY +_mesa_CreateProgramPipelines(GLsizei n, GLuint *pipelines); + extern GLboolean GLAPIENTRY _mesa_IsProgramPipeline(GLuint pipeline); diff --git a/mesalib/src/mesa/main/pixel.c b/mesalib/src/mesa/main/pixel.c index 7162c6fef..ecda2694f 100644 --- a/mesalib/src/mesa/main/pixel.c +++ b/mesalib/src/mesa/main/pixel.c @@ -30,7 +30,6 @@ #include "glheader.h" #include "bufferobj.h" -#include "colormac.h" #include "context.h" #include "macros.h" #include "pixel.h" diff --git a/mesalib/src/mesa/main/pixeltransfer.c b/mesalib/src/mesa/main/pixeltransfer.c index 8bbeeb853..94464ea67 100644 --- a/mesalib/src/mesa/main/pixeltransfer.c +++ b/mesalib/src/mesa/main/pixeltransfer.c @@ -31,7 +31,7 @@ #include "glheader.h" -#include "colormac.h" +#include "macros.h" #include "pixeltransfer.h" #include "imports.h" #include "mtypes.h" diff --git a/mesalib/src/mesa/main/program_resource.c b/mesalib/src/mesa/main/program_resource.c new file mode 100644 index 000000000..b15a13210 --- /dev/null +++ b/mesalib/src/mesa/main/program_resource.c @@ -0,0 +1,417 @@ +/* + * Mesa 3-D graphics library + * + * Copyright (C) 2015 Intel Corporation. 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/enums.h" +#include "main/macros.h" +#include "main/mtypes.h" +#include "main/shaderapi.h" +#include "main/shaderobj.h" +#include "program_resource.h" + +static bool +supported_interface_enum(GLenum iface) +{ + switch (iface) { + case GL_UNIFORM: + case GL_UNIFORM_BLOCK: + case GL_PROGRAM_INPUT: + case GL_PROGRAM_OUTPUT: + case GL_TRANSFORM_FEEDBACK_VARYING: + case GL_ATOMIC_COUNTER_BUFFER: + return true; + case GL_VERTEX_SUBROUTINE: + case GL_TESS_CONTROL_SUBROUTINE: + case GL_TESS_EVALUATION_SUBROUTINE: + case GL_GEOMETRY_SUBROUTINE: + case GL_FRAGMENT_SUBROUTINE: + case GL_COMPUTE_SUBROUTINE: + case GL_VERTEX_SUBROUTINE_UNIFORM: + case GL_TESS_CONTROL_SUBROUTINE_UNIFORM: + case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM: + case GL_GEOMETRY_SUBROUTINE_UNIFORM: + case GL_FRAGMENT_SUBROUTINE_UNIFORM: + case GL_COMPUTE_SUBROUTINE_UNIFORM: + case GL_BUFFER_VARIABLE: + case GL_SHADER_STORAGE_BLOCK: + default: + return false; + } +} + +void GLAPIENTRY +_mesa_GetProgramInterfaceiv(GLuint program, GLenum programInterface, + GLenum pname, GLint *params) +{ + GET_CURRENT_CONTEXT(ctx); + unsigned i; + struct gl_shader_program *shProg = + _mesa_lookup_shader_program_err(ctx, program, + "glGetProgramInterfaceiv"); + if (!shProg) + return; + + if (!params) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetProgramInterfaceiv(params NULL)"); + return; + } + + /* Validate interface. */ + if (!supported_interface_enum(programInterface)) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramInterfaceiv(%s)", + _mesa_lookup_enum_by_nr(programInterface)); + return; + } + + /* Validate pname against interface. */ + switch(pname) { + case GL_ACTIVE_RESOURCES: + for (i = 0, *params = 0; i < shProg->NumProgramResourceList; i++) + if (shProg->ProgramResourceList[i].Type == programInterface) + (*params)++; + break; + case GL_MAX_NAME_LENGTH: + if (programInterface == GL_ATOMIC_COUNTER_BUFFER) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetProgramInterfaceiv(%s pname %s)", + _mesa_lookup_enum_by_nr(programInterface), + _mesa_lookup_enum_by_nr(pname)); + return; + } + /* Name length consists of base name, 3 additional chars '[0]' if + * resource is an array and finally 1 char for string terminator. + */ + for (i = 0, *params = 0; i < shProg->NumProgramResourceList; i++) { + if (shProg->ProgramResourceList[i].Type != programInterface) + continue; + const char *name = + _mesa_program_resource_name(&shProg->ProgramResourceList[i]); + unsigned array_size = + _mesa_program_resource_array_size(&shProg->ProgramResourceList[i]); + *params = MAX2(*params, strlen(name) + (array_size ? 3 : 0) + 1); + } + break; + case GL_MAX_NUM_ACTIVE_VARIABLES: + switch (programInterface) { + case GL_UNIFORM_BLOCK: + for (i = 0, *params = 0; i < shProg->NumProgramResourceList; i++) { + if (shProg->ProgramResourceList[i].Type == programInterface) { + struct gl_uniform_block *block = + (struct gl_uniform_block *) + shProg->ProgramResourceList[i].Data; + *params = MAX2(*params, block->NumUniforms); + } + } + break; + case GL_ATOMIC_COUNTER_BUFFER: + for (i = 0, *params = 0; i < shProg->NumProgramResourceList; i++) { + if (shProg->ProgramResourceList[i].Type == programInterface) { + struct gl_active_atomic_buffer *buffer = + (struct gl_active_atomic_buffer *) + shProg->ProgramResourceList[i].Data; + *params = MAX2(*params, buffer->NumUniforms); + } + } + break; + default: + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetProgramInterfaceiv(%s pname %s)", + _mesa_lookup_enum_by_nr(programInterface), + _mesa_lookup_enum_by_nr(pname)); + }; + break; + case GL_MAX_NUM_COMPATIBLE_SUBROUTINES: + default: + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetProgramInterfaceiv(pname %s)", + _mesa_lookup_enum_by_nr(pname)); + } +} + +static bool +is_xfb_marker(const char *str) +{ + static const char *markers[] = { + "gl_NextBuffer", + "gl_SkipComponents1", + "gl_SkipComponents2", + "gl_SkipComponents3", + "gl_SkipComponents4", + NULL + }; + const char **m = markers; + + if (strncmp(str, "gl_", 3) != 0) + return false; + + for (; *m; m++) + if (strcmp(*m, str) == 0) + return true; + + return false; +} + +/** + * Checks if given name index is legal for GetProgramResourceIndex, + * check is written to be compatible with GL_ARB_array_of_arrays. + */ +static bool +valid_program_resource_index_name(const GLchar *name) +{ + const char *array = strstr(name, "["); + const char *close = strrchr(name, ']'); + + /* Not array, no need for the check. */ + if (!array) + return true; + + /* Last array index has to be zero. */ + if (!close || *--close != '0') + return false; + + return true; +} + +GLuint GLAPIENTRY +_mesa_GetProgramResourceIndex(GLuint program, GLenum programInterface, + const GLchar *name) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_program_resource *res; + struct gl_shader_program *shProg = + _mesa_lookup_shader_program_err(ctx, program, + "glGetProgramResourceIndex"); + if (!shProg || !name) + return GL_INVALID_INDEX; + + /* + * For the interface TRANSFORM_FEEDBACK_VARYING, the value INVALID_INDEX + * should be returned when querying the index assigned to the special names + * "gl_NextBuffer", "gl_SkipComponents1", "gl_SkipComponents2", + * "gl_SkipComponents3", and "gl_SkipComponents4". + */ + if (programInterface == GL_TRANSFORM_FEEDBACK_VARYING && + is_xfb_marker(name)) + return GL_INVALID_INDEX; + + switch (programInterface) { + case GL_PROGRAM_INPUT: + case GL_PROGRAM_OUTPUT: + case GL_UNIFORM: + case GL_UNIFORM_BLOCK: + case GL_TRANSFORM_FEEDBACK_VARYING: + /* Validate name syntax for arrays. */ + if (!valid_program_resource_index_name(name)) + return GL_INVALID_INDEX; + + res = _mesa_program_resource_find_name(shProg, programInterface, name); + if (!res) + return GL_INVALID_INDEX; + + return _mesa_program_resource_index(shProg, res); + case GL_ATOMIC_COUNTER_BUFFER: + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramResourceIndex(%s)", + _mesa_lookup_enum_by_nr(programInterface)); + } + + return GL_INVALID_INDEX; +} + +void GLAPIENTRY +_mesa_GetProgramResourceName(GLuint program, GLenum programInterface, + GLuint index, GLsizei bufSize, GLsizei *length, + GLchar *name) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_shader_program *shProg = + _mesa_lookup_shader_program_err(ctx, program, + "glGetProgramResourceName"); + + /* Set user friendly return values in case of errors. */ + if (name) + *name = '\0'; + if (length) + *length = 0; + + if (!shProg || !name) + return; + + if (programInterface == GL_ATOMIC_COUNTER_BUFFER || + !supported_interface_enum(programInterface)) { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramResourceName(%s)", + _mesa_lookup_enum_by_nr(programInterface)); + return; + } + + _mesa_get_program_resource_name(shProg, programInterface, index, bufSize, + length, name, "glGetProgramResourceName"); +} + +void GLAPIENTRY +_mesa_GetProgramResourceiv(GLuint program, GLenum programInterface, + GLuint index, GLsizei propCount, + const GLenum *props, GLsizei bufSize, + GLsizei *length, GLint *params) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_shader_program *shProg = + _mesa_lookup_shader_program_err(ctx, program, "glGetProgramResourceiv"); + + if (!shProg || !params) + return; + + /* The error INVALID_VALUE is generated if <propCount> is zero. + * Note that we check < 0 here because it makes sense to bail early. + */ + if (propCount <= 0) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glGetProgramResourceiv(propCount <= 0)"); + return; + } + + /* No need to write any properties, user requested none. */ + if (bufSize == 0) + return; + + _mesa_get_program_resourceiv(shProg, programInterface, index, + propCount, props, bufSize, length, params); +} + +/** + * Function verifies syntax of given name for GetProgramResourceLocation + * and GetProgramResourceLocationIndex for the following cases: + * + * "array element portion of a string passed to GetProgramResourceLocation + * or GetProgramResourceLocationIndex must not have, a "+" sign, extra + * leading zeroes, or whitespace". + * + * Check is written to be compatible with GL_ARB_array_of_arrays. + */ +static bool +invalid_array_element_syntax(const GLchar *name) +{ + char *first = strchr(name, '['); + char *last = strrchr(name, '['); + + if (!first) + return false; + + /* No '+' or ' ' allowed anywhere. */ + if (strchr(first, '+') || strchr(first, ' ')) + return true; + + /* Check that last array index is 0. */ + if (last[1] == '0' && last[2] != ']') + return true; + + return false; +} + +static struct gl_shader_program * +lookup_linked_program(GLuint program, const char *caller) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_shader_program *prog = + _mesa_lookup_shader_program_err(ctx, program, caller); + + if (!prog) + return NULL; + + if (prog->LinkStatus == GL_FALSE) { + _mesa_error(ctx, GL_INVALID_OPERATION, "%s(program not linked)", + caller); + return NULL; + } + return prog; +} + +GLint GLAPIENTRY +_mesa_GetProgramResourceLocation(GLuint program, GLenum programInterface, + const GLchar *name) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_shader_program *shProg = + lookup_linked_program(program, "glGetProgramResourceLocation"); + + if (!shProg || !name || invalid_array_element_syntax(name)) + return -1; + + /* Validate programInterface. */ + switch (programInterface) { + case GL_UNIFORM: + case GL_PROGRAM_INPUT: + case GL_PROGRAM_OUTPUT: + break; + + /* For reference valid cases requiring additional extension support: + * GL_ARB_shader_subroutine + * GL_ARB_tessellation_shader + * GL_ARB_compute_shader + */ + case GL_VERTEX_SUBROUTINE_UNIFORM: + case GL_TESS_CONTROL_SUBROUTINE_UNIFORM: + case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM: + case GL_GEOMETRY_SUBROUTINE_UNIFORM: + case GL_FRAGMENT_SUBROUTINE_UNIFORM: + case GL_COMPUTE_SUBROUTINE_UNIFORM: + + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramResourceLocation(%s %s)", + _mesa_lookup_enum_by_nr(programInterface), name); + } + + return _mesa_program_resource_location(shProg, programInterface, name); +} + +/** + * Returns output index for dual source blending. + */ +GLint GLAPIENTRY +_mesa_GetProgramResourceLocationIndex(GLuint program, GLenum programInterface, + const GLchar *name) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_shader_program *shProg = + lookup_linked_program(program, "glGetProgramResourceLocationIndex"); + + if (!shProg || !name || invalid_array_element_syntax(name)) + return -1; + + /* From the GL_ARB_program_interface_query spec: + * + * "For GetProgramResourceLocationIndex, <programInterface> must be + * PROGRAM_OUTPUT." + */ + if (programInterface != GL_PROGRAM_OUTPUT) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glGetProgramResourceLocationIndex(%s)", + _mesa_lookup_enum_by_nr(programInterface)); + return -1; + } + + return _mesa_program_resource_location_index(shProg, GL_PROGRAM_OUTPUT, + name); +} diff --git a/mesalib/src/mesa/main/program_resource.h b/mesalib/src/mesa/main/program_resource.h new file mode 100644 index 000000000..326ae1f93 --- /dev/null +++ b/mesalib/src/mesa/main/program_resource.h @@ -0,0 +1,58 @@ +/* + * Mesa 3-D graphics library + * + * Copyright (C) 2015 Intel Corporation. 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. + * + */ + +#ifndef PROGRAM_RESOURCE_H +#define PROGRAM_RESOURCE_H + +#include "glheader.h" + +extern void GLAPIENTRY +_mesa_GetProgramInterfaceiv(GLuint program, GLenum programInterface, + GLenum pname, GLint *params); + +extern GLuint GLAPIENTRY +_mesa_GetProgramResourceIndex(GLuint program, GLenum programInterface, + const GLchar *name); + +extern void GLAPIENTRY +_mesa_GetProgramResourceName(GLuint program, GLenum programInterface, + GLuint index, GLsizei bufSize, GLsizei *length, + GLchar *name); + +extern void GLAPIENTRY +_mesa_GetProgramResourceiv(GLuint program, GLenum programInterface, + GLuint index, GLsizei propCount, + const GLenum *props, GLsizei bufSize, + GLsizei *length, GLint *params); + +extern GLint GLAPIENTRY +_mesa_GetProgramResourceLocation(GLuint program, GLenum programInterface, + const GLchar *name); + +extern GLint GLAPIENTRY +_mesa_GetProgramResourceLocationIndex(GLuint program, GLenum programInterface, + const GLchar *name); + +#endif diff --git a/mesalib/src/mesa/main/queryobj.c b/mesalib/src/mesa/main/queryobj.c index 0842b540d..fbccf3fe6 100644 --- a/mesalib/src/mesa/main/queryobj.c +++ b/mesalib/src/mesa/main/queryobj.c @@ -233,18 +233,22 @@ get_query_binding_point(struct gl_context *ctx, GLenum target, GLuint index) } } - -void GLAPIENTRY -_mesa_GenQueries(GLsizei n, GLuint *ids) +/** + * Create $n query objects and store them in *ids. Make them of type $target + * if dsa is set. Called from _mesa_GenQueries() and _mesa_CreateQueries(). + */ +static void +create_queries(struct gl_context *ctx, GLenum target, GLsizei n, GLuint *ids, + bool dsa) { + const char *func = dsa ? "glGenQueries" : "glCreateQueries"; GLuint first; - GET_CURRENT_CONTEXT(ctx); if (MESA_VERBOSE & VERBOSE_API) - _mesa_debug(ctx, "glGenQueries(%d)\n", n); + _mesa_debug(ctx, "%s(%d)\n", func, n); if (n < 0) { - _mesa_error(ctx, GL_INVALID_VALUE, "glGenQueriesARB(n < 0)"); + _mesa_error(ctx, GL_INVALID_VALUE, "%s(n < 0)", func); return; } @@ -255,8 +259,12 @@ _mesa_GenQueries(GLsizei n, GLuint *ids) struct gl_query_object *q = ctx->Driver.NewQueryObject(ctx, first + i); if (!q) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenQueriesARB"); + _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func); return; + } else if (dsa) { + /* Do the equivalent of binding the buffer with a target */ + q->Target = target; + q->EverBound = GL_TRUE; } ids[i] = first + i; _mesa_HashInsert(ctx->Query.QueryObjects, first + i, q); @@ -264,6 +272,36 @@ _mesa_GenQueries(GLsizei n, GLuint *ids) } } +void GLAPIENTRY +_mesa_GenQueries(GLsizei n, GLuint *ids) +{ + GET_CURRENT_CONTEXT(ctx); + create_queries(ctx, 0, n, ids, false); +} + +void GLAPIENTRY +_mesa_CreateQueries(GLenum target, GLsizei n, GLuint *ids) +{ + GET_CURRENT_CONTEXT(ctx); + + switch (target) { + case GL_SAMPLES_PASSED: + case GL_ANY_SAMPLES_PASSED: + case GL_ANY_SAMPLES_PASSED_CONSERVATIVE: + case GL_TIME_ELAPSED: + case GL_TIMESTAMP: + case GL_PRIMITIVES_GENERATED: + case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN: + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glCreateQueries(invalid target = %s)", + _mesa_lookup_enum_by_nr(target)); + return; + } + + create_queries(ctx, target, n, ids, true); +} + void GLAPIENTRY _mesa_DeleteQueries(GLsizei n, const GLuint *ids) @@ -424,6 +462,18 @@ _mesa_BeginQueryIndexed(GLenum target, GLuint index, GLuint id) } } + /* This possibly changes the target of a buffer allocated by + * CreateQueries. Issue 39) in the ARB_direct_state_access extension states + * the following: + * + * "CreateQueries adds a <target>, so strictly speaking the <target> + * command isn't needed for BeginQuery/EndQuery, but in the end, this also + * isn't a selector, so we decided not to change it." + * + * Updating the target of the query object should be acceptable, so let's + * do that. + */ + q->Target = target; q->Active = GL_TRUE; q->Result = 0; @@ -541,6 +591,18 @@ _mesa_QueryCounter(GLuint id, GLenum target) return; } + /* This possibly changes the target of a buffer allocated by + * CreateQueries. Issue 39) in the ARB_direct_state_access extension states + * the following: + * + * "CreateQueries adds a <target>, so strictly speaking the <target> + * command isn't needed for BeginQuery/EndQuery, but in the end, this also + * isn't a selector, so we decided not to change it." + * + * Updating the target of the query object should be acceptable, so let's + * do that. + */ + q->Target = target; q->Result = 0; q->Ready = GL_FALSE; @@ -710,8 +772,8 @@ _mesa_GetQueryObjectiv(GLuint id, GLenum pname, GLint *params) } break; case GL_QUERY_RESULT_AVAILABLE_ARB: - if (!q->Ready) - ctx->Driver.CheckQuery( ctx, q ); + if (!q->Ready) + ctx->Driver.CheckQuery( ctx, q ); *params = q->Ready; break; default: @@ -761,8 +823,8 @@ _mesa_GetQueryObjectuiv(GLuint id, GLenum pname, GLuint *params) } break; case GL_QUERY_RESULT_AVAILABLE_ARB: - if (!q->Ready) - ctx->Driver.CheckQuery( ctx, q ); + if (!q->Ready) + ctx->Driver.CheckQuery( ctx, q ); *params = q->Ready; break; default: @@ -801,8 +863,8 @@ _mesa_GetQueryObjecti64v(GLuint id, GLenum pname, GLint64EXT *params) *params = q->Result; break; case GL_QUERY_RESULT_AVAILABLE_ARB: - if (!q->Ready) - ctx->Driver.CheckQuery( ctx, q ); + if (!q->Ready) + ctx->Driver.CheckQuery( ctx, q ); *params = q->Ready; break; default: @@ -841,8 +903,8 @@ _mesa_GetQueryObjectui64v(GLuint id, GLenum pname, GLuint64EXT *params) *params = q->Result; break; case GL_QUERY_RESULT_AVAILABLE_ARB: - if (!q->Ready) - ctx->Driver.CheckQuery( ctx, q ); + if (!q->Ready) + ctx->Driver.CheckQuery( ctx, q ); *params = q->Ready; break; default: @@ -852,6 +914,45 @@ _mesa_GetQueryObjectui64v(GLuint id, GLenum pname, GLuint64EXT *params) } /** + * New with GL_ARB_query_buffer_object + */ +void GLAPIENTRY +_mesa_GetQueryBufferObjectiv(GLuint id, GLuint buffer, GLenum pname, + GLintptr offset) +{ + GET_CURRENT_CONTEXT(ctx); + _mesa_error(ctx, GL_INVALID_OPERATION, "glGetQueryBufferObjectiv"); +} + + +void GLAPIENTRY +_mesa_GetQueryBufferObjectuiv(GLuint id, GLuint buffer, GLenum pname, + GLintptr offset) +{ + GET_CURRENT_CONTEXT(ctx); + _mesa_error(ctx, GL_INVALID_OPERATION, "glGetQueryBufferObjectuiv"); +} + + +void GLAPIENTRY +_mesa_GetQueryBufferObjecti64v(GLuint id, GLuint buffer, GLenum pname, + GLintptr offset) +{ + GET_CURRENT_CONTEXT(ctx); + _mesa_error(ctx, GL_INVALID_OPERATION, "glGetQueryBufferObjecti64v"); +} + + +void GLAPIENTRY +_mesa_GetQueryBufferObjectui64v(GLuint id, GLuint buffer, GLenum pname, + GLintptr offset) +{ + GET_CURRENT_CONTEXT(ctx); + _mesa_error(ctx, GL_INVALID_OPERATION, "glGetQueryBufferObjectui64v"); +} + + +/** * Allocate/init the context state related to query objects. */ void diff --git a/mesalib/src/mesa/main/queryobj.h b/mesalib/src/mesa/main/queryobj.h index 6cbcabd46..d1036fcce 100644 --- a/mesalib/src/mesa/main/queryobj.h +++ b/mesalib/src/mesa/main/queryobj.h @@ -51,6 +51,8 @@ _mesa_free_queryobj_data(struct gl_context *ctx); void GLAPIENTRY _mesa_GenQueries(GLsizei n, GLuint *ids); void GLAPIENTRY +_mesa_CreateQueries(GLenum target, GLsizei n, GLuint *ids); +void GLAPIENTRY _mesa_DeleteQueries(GLsizei n, const GLuint *ids); GLboolean GLAPIENTRY _mesa_IsQuery(GLuint id); @@ -77,5 +79,17 @@ void GLAPIENTRY _mesa_GetQueryObjecti64v(GLuint id, GLenum pname, GLint64EXT *params); void GLAPIENTRY _mesa_GetQueryObjectui64v(GLuint id, GLenum pname, GLuint64EXT *params); +void GLAPIENTRY +_mesa_GetQueryBufferObjectiv(GLuint id, GLuint buffer, GLenum pname, + GLintptr offset); +void GLAPIENTRY +_mesa_GetQueryBufferObjectuiv(GLuint id, GLuint buffer, GLenum pname, + GLintptr offset); +void GLAPIENTRY +_mesa_GetQueryBufferObjecti64v(GLuint id, GLuint buffer, GLenum pname, + GLintptr offset); +void GLAPIENTRY +_mesa_GetQueryBufferObjectui64v(GLuint id, GLuint buffer, GLenum pname, + GLintptr offset); #endif /* QUERYOBJ_H */ diff --git a/mesalib/src/mesa/main/samplerobj.c b/mesalib/src/mesa/main/samplerobj.c index d66b0b5e8..a3aacc66a 100644 --- a/mesalib/src/mesa/main/samplerobj.c +++ b/mesalib/src/mesa/main/samplerobj.c @@ -181,19 +181,18 @@ _mesa_delete_sampler_object(struct gl_context *ctx, free(sampObj); } - -void GLAPIENTRY -_mesa_GenSamplers(GLsizei count, GLuint *samplers) +static void +create_samplers(struct gl_context *ctx, GLsizei count, GLuint *samplers, + const char *caller) { - GET_CURRENT_CONTEXT(ctx); GLuint first; GLint i; if (MESA_VERBOSE & VERBOSE_API) - _mesa_debug(ctx, "glGenSamplers(%d)\n", count); + _mesa_debug(ctx, "%s(%d)\n", caller, count); if (count < 0) { - _mesa_error(ctx, GL_INVALID_VALUE, "glGenSamplers"); + _mesa_error(ctx, GL_INVALID_VALUE, "%s(n<0)", caller); return; } @@ -211,6 +210,20 @@ _mesa_GenSamplers(GLsizei count, GLuint *samplers) } } +void GLAPIENTRY +_mesa_GenSamplers(GLsizei count, GLuint *samplers) +{ + GET_CURRENT_CONTEXT(ctx); + create_samplers(ctx, count, samplers, "glGenSamplers"); +} + +void GLAPIENTRY +_mesa_CreateSamplers(GLsizei count, GLuint *samplers) +{ + GET_CURRENT_CONTEXT(ctx); + create_samplers(ctx, count, samplers, "glCreateSamplers"); +} + void GLAPIENTRY _mesa_DeleteSamplers(GLsizei count, const GLuint *samplers) diff --git a/mesalib/src/mesa/main/samplerobj.h b/mesalib/src/mesa/main/samplerobj.h index 1bb3193e4..7bea91114 100644 --- a/mesalib/src/mesa/main/samplerobj.h +++ b/mesalib/src/mesa/main/samplerobj.h @@ -32,6 +32,9 @@ extern "C" { #endif +#include "mtypes.h" + + struct dd_function_table; static inline struct gl_sampler_object * @@ -80,6 +83,8 @@ _mesa_init_sampler_object_functions(struct dd_function_table *driver); void GLAPIENTRY _mesa_GenSamplers(GLsizei count, GLuint *samplers); void GLAPIENTRY +_mesa_CreateSamplers(GLsizei count, GLuint *samplers); +void GLAPIENTRY _mesa_DeleteSamplers(GLsizei count, const GLuint *samplers); GLboolean GLAPIENTRY _mesa_IsSampler(GLuint sampler); diff --git a/mesalib/src/mesa/main/shader_query.cpp b/mesalib/src/mesa/main/shader_query.cpp index df9081b73..b5f1d082c 100644 --- a/mesalib/src/mesa/main/shader_query.cpp +++ b/mesalib/src/mesa/main/shader_query.cpp @@ -34,11 +34,33 @@ #include "shaderobj.h" #include "program/hash_table.h" #include "../glsl/program.h" +#include "uniforms.h" +#include "main/enums.h" extern "C" { #include "shaderapi.h" } +static GLint +program_resource_location(struct gl_shader_program *shProg, + struct gl_program_resource *res, const char *name); + +/** + * Declare convenience functions to return resource data in a given type. + * Warning! this is not type safe so be *very* careful when using these. + */ +#define DECL_RESOURCE_FUNC(name, type) \ +const type * RESOURCE_ ## name (gl_program_resource *res) { \ + assert(res->Data); \ + return (type *) res->Data; \ +} + +DECL_RESOURCE_FUNC(VAR, ir_variable); +DECL_RESOURCE_FUNC(UBO, gl_uniform_block); +DECL_RESOURCE_FUNC(UNI, gl_uniform_storage); +DECL_RESOURCE_FUNC(ATC, gl_active_atomic_buffer); +DECL_RESOURCE_FUNC(XFB, gl_transform_feedback_varying_info); + void GLAPIENTRY _mesa_BindAttribLocation(GLhandleARB program, GLuint index, const GLcharARB *name) @@ -129,45 +151,41 @@ _mesa_GetActiveAttrib(GLhandleARB program, GLuint desired_index, return; } - exec_list *const ir = shProg->_LinkedShaders[MESA_SHADER_VERTEX]->ir; - unsigned current_index = 0; - - foreach_in_list(ir_instruction, node, ir) { - const ir_variable *const var = node->as_variable(); - - if (!is_active_attrib(var)) - continue; + struct gl_program_resource *res = + _mesa_program_resource_find_index(shProg, GL_PROGRAM_INPUT, + desired_index); - if (current_index == desired_index) { - const char *var_name = var->name; + /* User asked for index that does not exist. */ + if (!res) { + _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(index)"); + return; + } - /* Since gl_VertexID may be lowered to gl_VertexIDMESA, we need to - * consider gl_VertexIDMESA as gl_VertexID for purposes of checking - * active attributes. - */ - if (var->data.mode == ir_var_system_value && - var->data.location == SYSTEM_VALUE_VERTEX_ID_ZERO_BASE) { - var_name = "gl_VertexID"; - } + const ir_variable *const var = RESOURCE_VAR(res); - _mesa_copy_string(name, maxLength, length, var_name); + if (!is_active_attrib(var)) + return; - if (size) - *size = (var->type->is_array()) ? var->type->length : 1; + const char *var_name = var->name; - if (type) - *type = var->type->gl_type; + /* Since gl_VertexID may be lowered to gl_VertexIDMESA, we need to + * consider gl_VertexIDMESA as gl_VertexID for purposes of checking + * active attributes. + */ + if (var->data.mode == ir_var_system_value && + var->data.location == SYSTEM_VALUE_VERTEX_ID_ZERO_BASE) { + var_name = "gl_VertexID"; + } - return; - } + _mesa_copy_string(name, maxLength, length, var_name); - current_index++; - } + if (size) + _mesa_program_resource_prop(shProg, res, desired_index, GL_ARRAY_SIZE, + size, "glGetActiveAttrib"); - /* If the loop did not return early, the caller must have asked for - * an index that did not exit. Set an error. - */ - _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(index)"); + if (type) + _mesa_program_resource_prop(shProg, res, desired_index, GL_TYPE, + (GLint *) type, "glGetActiveAttrib"); } /* Locations associated with shader variables (array or non-array) can be @@ -252,31 +270,25 @@ _mesa_GetAttribLocation(GLhandleARB program, const GLcharARB * name) if (shProg->_LinkedShaders[MESA_SHADER_VERTEX] == NULL) return -1; - exec_list *ir = shProg->_LinkedShaders[MESA_SHADER_VERTEX]->ir; - foreach_in_list(ir_instruction, node, ir) { - const ir_variable *const var = node->as_variable(); - - /* The extra check against VERT_ATTRIB_GENERIC0 is because - * glGetAttribLocation cannot be used on "conventional" attributes. - * - * From page 95 of the OpenGL 3.0 spec: - * - * "If name is not an active attribute, if name is a conventional - * attribute, or if an error occurs, -1 will be returned." - */ - if (var == NULL - || var->data.mode != ir_var_shader_in - || var->data.location == -1 - || var->data.location < VERT_ATTRIB_GENERIC0) - continue; - - int index = get_matching_index(var, (const char *) name); + struct gl_program_resource *res = + _mesa_program_resource_find_name(shProg, GL_PROGRAM_INPUT, name); - if (index >= 0) - return var->data.location + index - VERT_ATTRIB_GENERIC0; - } + if (!res) + return -1; - return -1; + GLint loc = program_resource_location(shProg, res, name); + + /* The extra check against against 0 is made because of builtin-attribute + * locations that have offset applied. Function program_resource_location + * can return built-in attribute locations < 0 and glGetAttribLocation + * cannot be used on "conventional" attributes. + * + * From page 95 of the OpenGL 3.0 spec: + * + * "If name is not an active attribute, if name is a conventional + * attribute, or if an error occurs, -1 will be returned." + */ + return (loc >= 0) ? loc : -1; } @@ -416,29 +428,8 @@ _mesa_GetFragDataIndex(GLuint program, const GLchar *name) if (shProg->_LinkedShaders[MESA_SHADER_FRAGMENT] == NULL) return -1; - exec_list *ir = shProg->_LinkedShaders[MESA_SHADER_FRAGMENT]->ir; - foreach_in_list(ir_instruction, node, ir) { - const ir_variable *const var = node->as_variable(); - - /* The extra check against FRAG_RESULT_DATA0 is because - * glGetFragDataLocation cannot be used on "conventional" attributes. - * - * From page 95 of the OpenGL 3.0 spec: - * - * "If name is not an active attribute, if name is a conventional - * attribute, or if an error occurs, -1 will be returned." - */ - if (var == NULL - || var->data.mode != ir_var_shader_out - || var->data.location == -1 - || var->data.location < FRAG_RESULT_DATA0) - continue; - - if (get_matching_index(var, (const char *) name) >= 0) - return var->data.index; - } - - return -1; + return _mesa_program_resource_location_index(shProg, GL_PROGRAM_OUTPUT, + name); } GLint GLAPIENTRY @@ -472,29 +463,612 @@ _mesa_GetFragDataLocation(GLuint program, const GLchar *name) if (shProg->_LinkedShaders[MESA_SHADER_FRAGMENT] == NULL) return -1; - exec_list *ir = shProg->_LinkedShaders[MESA_SHADER_FRAGMENT]->ir; - foreach_in_list(ir_instruction, node, ir) { - const ir_variable *const var = node->as_variable(); + struct gl_program_resource *res = + _mesa_program_resource_find_name(shProg, GL_PROGRAM_OUTPUT, name); - /* The extra check against FRAG_RESULT_DATA0 is because - * glGetFragDataLocation cannot be used on "conventional" attributes. - * - * From page 95 of the OpenGL 3.0 spec: + if (!res) + return -1; + + GLint loc = program_resource_location(shProg, res, name); + + /* The extra check against against 0 is made because of builtin-attribute + * locations that have offset applied. Function program_resource_location + * can return built-in attribute locations < 0 and glGetFragDataLocation + * cannot be used on "conventional" attributes. + * + * From page 95 of the OpenGL 3.0 spec: + * + * "If name is not an active attribute, if name is a conventional + * attribute, or if an error occurs, -1 will be returned." + */ + return (loc >= 0) ? loc : -1; +} + +const char* +_mesa_program_resource_name(struct gl_program_resource *res) +{ + switch (res->Type) { + case GL_UNIFORM_BLOCK: + return RESOURCE_UBO(res)->Name; + case GL_TRANSFORM_FEEDBACK_VARYING: + return RESOURCE_XFB(res)->Name; + case GL_PROGRAM_INPUT: + case GL_PROGRAM_OUTPUT: + return RESOURCE_VAR(res)->name; + case GL_UNIFORM: + return RESOURCE_UNI(res)->name; + default: + assert(!"support for resource type not implemented"); + } + return NULL; +} + + +unsigned +_mesa_program_resource_array_size(struct gl_program_resource *res) +{ + switch (res->Type) { + case GL_TRANSFORM_FEEDBACK_VARYING: + return RESOURCE_XFB(res)->Size > 1 ? + RESOURCE_XFB(res)->Size : 0; + case GL_PROGRAM_INPUT: + case GL_PROGRAM_OUTPUT: + return RESOURCE_VAR(res)->data.max_array_access; + case GL_UNIFORM: + return RESOURCE_UNI(res)->array_elements; + case GL_ATOMIC_COUNTER_BUFFER: + case GL_UNIFORM_BLOCK: + return 0; + default: + assert(!"support for resource type not implemented"); + } + return 0; +} + +static int +array_index_of_resource(struct gl_program_resource *res, + const char *name) +{ + assert(res->Data); + + switch (res->Type) { + case GL_PROGRAM_INPUT: + case GL_PROGRAM_OUTPUT: + return get_matching_index(RESOURCE_VAR(res), name); + default: + assert(!"support for resource type not implemented"); + } +} + +/* Find a program resource with specific name in given interface. + */ +struct gl_program_resource * +_mesa_program_resource_find_name(struct gl_shader_program *shProg, + GLenum programInterface, const char *name) +{ + struct gl_program_resource *res = shProg->ProgramResourceList; + for (unsigned i = 0; i < shProg->NumProgramResourceList; i++, res++) { + if (res->Type != programInterface) + continue; + + /* Resource basename. */ + const char *rname = _mesa_program_resource_name(res); + unsigned baselen = strlen(rname); + + switch (programInterface) { + case GL_TRANSFORM_FEEDBACK_VARYING: + case GL_UNIFORM_BLOCK: + case GL_UNIFORM: + if (strncmp(rname, name, baselen) == 0) { + /* Basename match, check if array or struct. */ + if (name[baselen] == '\0' || + name[baselen] == '[' || + name[baselen] == '.') { + return res; + } + } + break; + case GL_PROGRAM_INPUT: + case GL_PROGRAM_OUTPUT: + if (array_index_of_resource(res, name) >= 0) + return res; + break; + default: + assert(!"not implemented for given interface"); + } + } + return NULL; +} + +static GLuint +calc_resource_index(struct gl_shader_program *shProg, + struct gl_program_resource *res) +{ + unsigned i; + GLuint index = 0; + for (i = 0; i < shProg->NumProgramResourceList; i++) { + if (&shProg->ProgramResourceList[i] == res) + return index; + if (shProg->ProgramResourceList[i].Type == res->Type) + index++; + } + return GL_INVALID_INDEX; +} + +/** + * Calculate index for the given resource. + */ +GLuint +_mesa_program_resource_index(struct gl_shader_program *shProg, + struct gl_program_resource *res) +{ + if (!res) + return GL_INVALID_INDEX; + + switch (res->Type) { + case GL_UNIFORM_BLOCK: + return RESOURCE_UBO(res)- shProg->UniformBlocks; + case GL_ATOMIC_COUNTER_BUFFER: + return RESOURCE_ATC(res) - shProg->AtomicBuffers; + case GL_TRANSFORM_FEEDBACK_VARYING: + default: + return calc_resource_index(shProg, res); + } +} + +/* Find a program resource with specific index in given interface. + */ +struct gl_program_resource * +_mesa_program_resource_find_index(struct gl_shader_program *shProg, + GLenum programInterface, GLuint index) +{ + struct gl_program_resource *res = shProg->ProgramResourceList; + int idx = -1; + + for (unsigned i = 0; i < shProg->NumProgramResourceList; i++, res++) { + if (res->Type != programInterface) + continue; + + switch (res->Type) { + case GL_UNIFORM_BLOCK: + case GL_ATOMIC_COUNTER_BUFFER: + if (_mesa_program_resource_index(shProg, res) == index) + return res; + + case GL_TRANSFORM_FEEDBACK_VARYING: + case GL_PROGRAM_INPUT: + case GL_PROGRAM_OUTPUT: + case GL_UNIFORM: + if (++idx == (int) index) + return res; + break; + default: + assert(!"not implemented for given interface"); + } + } + return NULL; +} + +/* Get full name of a program resource. + */ +bool +_mesa_get_program_resource_name(struct gl_shader_program *shProg, + GLenum programInterface, GLuint index, + GLsizei bufSize, GLsizei *length, + GLchar *name, const char *caller) +{ + GET_CURRENT_CONTEXT(ctx); + + /* Find resource with given interface and index. */ + struct gl_program_resource *res = + _mesa_program_resource_find_index(shProg, programInterface, index); + + /* The error INVALID_VALUE is generated if <index> is greater than + * or equal to the number of entries in the active resource list for + * <programInterface>. + */ + if (!res) { + _mesa_error(ctx, GL_INVALID_VALUE, "%s(index %u)", caller, index); + return false; + } + + if (bufSize < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "%s(bufSize %d)", caller, bufSize); + return false; + } + + GLsizei localLength; + + if (length == NULL) + length = &localLength; + + _mesa_copy_string(name, bufSize, length, _mesa_program_resource_name(res)); + + /* Page 61 (page 73 of the PDF) in section 2.11 of the OpenGL ES 3.0 + * spec says: + * + * "If the active uniform is an array, the uniform name returned in + * name will always be the name of the uniform array appended with + * "[0]"." + * + * The same text also appears in the OpenGL 4.2 spec. It does not, + * however, appear in any previous spec. Previous specifications are + * ambiguous in this regard. However, either name can later be passed + * to glGetUniformLocation (and related APIs), so there shouldn't be any + * harm in always appending "[0]" to uniform array names. + * + * Geometry shader stage has different naming convention where the 'normal' + * condition is an array, therefore for variables referenced in geometry + * stage we do not add '[0]'. + * + * Note, that TCS outputs and TES inputs should not have index appended + * either. + */ + bool add_index = !(((programInterface == GL_PROGRAM_INPUT) && + res->StageReferences & (1 << MESA_SHADER_GEOMETRY))); + + if (add_index && _mesa_program_resource_array_size(res)) { + int i; + + /* The comparison is strange because *length does *NOT* include the + * terminating NUL, but maxLength does. + */ + for (i = 0; i < 3 && (*length + i + 1) < bufSize; i++) + name[*length + i] = "[0]"[i]; + + name[*length + i] = '\0'; + *length += i; + } + return true; +} + +static GLint +program_resource_location(struct gl_shader_program *shProg, + struct gl_program_resource *res, const char *name) +{ + unsigned index, offset; + int array_index = -1; + + if (res->Type == GL_PROGRAM_INPUT || res->Type == GL_PROGRAM_OUTPUT) { + array_index = array_index_of_resource(res, name); + if (array_index < 0) + return -1; + } + + /* VERT_ATTRIB_GENERIC0 and FRAG_RESULT_DATA0 are decremented as these + * offsets are used internally to differentiate between built-in attributes + * and user-defined attributes. + */ + switch (res->Type) { + case GL_PROGRAM_INPUT: + return RESOURCE_VAR(res)->data.location + array_index - VERT_ATTRIB_GENERIC0; + case GL_PROGRAM_OUTPUT: + return RESOURCE_VAR(res)->data.location + array_index - FRAG_RESULT_DATA0; + case GL_UNIFORM: + index = _mesa_get_uniform_location(shProg, name, &offset); + + if (index == GL_INVALID_INDEX) + return -1; + + /* From the GL_ARB_uniform_buffer_object spec: * - * "If name is not an active attribute, if name is a conventional - * attribute, or if an error occurs, -1 will be returned." + * "The value -1 will be returned if <name> does not correspond to an + * active uniform variable name in <program>, if <name> is associated + * with a named uniform block, or if <name> starts with the reserved + * prefix "gl_"." */ - if (var == NULL - || var->data.mode != ir_var_shader_out - || var->data.location == -1 - || var->data.location < FRAG_RESULT_DATA0) - continue; + if (RESOURCE_UNI(res)->block_index != -1 || + RESOURCE_UNI(res)->atomic_buffer_index != -1) + return -1; - int index = get_matching_index(var, (const char *) name); + /* location in remap table + array element offset */ + return RESOURCE_UNI(res)->remap_location + offset; - if (index >= 0) - return var->data.location + index - FRAG_RESULT_DATA0; + default: + return -1; } +} - return -1; +/** + * Function implements following location queries: + * glGetAttribLocation + * glGetFragDataLocation + * glGetUniformLocation + */ +GLint +_mesa_program_resource_location(struct gl_shader_program *shProg, + GLenum programInterface, const char *name) +{ + struct gl_program_resource *res = + _mesa_program_resource_find_name(shProg, programInterface, name); + + /* Resource not found. */ + if (!res) + return -1; + + return program_resource_location(shProg, res, name); +} + +/** + * Function implements following index queries: + * glGetFragDataIndex + */ +GLint +_mesa_program_resource_location_index(struct gl_shader_program *shProg, + GLenum programInterface, const char *name) +{ + struct gl_program_resource *res = + _mesa_program_resource_find_name(shProg, programInterface, name); + + /* Non-existent variable or resource is not referenced by fragment stage. */ + if (!res || !(res->StageReferences & (1 << MESA_SHADER_FRAGMENT))) + return -1; + + return RESOURCE_VAR(res)->data.index; +} + +static uint8_t +stage_from_enum(GLenum ref) +{ + switch (ref) { + case GL_REFERENCED_BY_VERTEX_SHADER: + return MESA_SHADER_VERTEX; + case GL_REFERENCED_BY_GEOMETRY_SHADER: + return MESA_SHADER_GEOMETRY; + case GL_REFERENCED_BY_FRAGMENT_SHADER: + return MESA_SHADER_FRAGMENT; + default: + assert(!"shader stage not supported"); + return MESA_SHADER_STAGES; + } +} + +/** + * Check if resource is referenced by given 'referenced by' stage enum. + * ATC and UBO resources hold stage references of their own. + */ +static bool +is_resource_referenced(struct gl_shader_program *shProg, + struct gl_program_resource *res, + GLuint index, uint8_t stage) +{ + if (res->Type == GL_ATOMIC_COUNTER_BUFFER) + return RESOURCE_ATC(res)->StageReferences[stage]; + + if (res->Type == GL_UNIFORM_BLOCK) + return shProg->UniformBlockStageIndex[stage][index] != -1; + + return res->StageReferences & (1 << stage); +} + +static unsigned +get_buffer_property(struct gl_shader_program *shProg, + struct gl_program_resource *res, const GLenum prop, + GLint *val, const char *caller) +{ + GET_CURRENT_CONTEXT(ctx); + if (res->Type != GL_UNIFORM_BLOCK && + res->Type != GL_ATOMIC_COUNTER_BUFFER) + goto invalid_operation; + + if (res->Type == GL_UNIFORM_BLOCK) { + switch (prop) { + case GL_BUFFER_BINDING: + *val = RESOURCE_UBO(res)->Binding; + return 1; + case GL_BUFFER_DATA_SIZE: + *val = RESOURCE_UBO(res)->UniformBufferSize; + return 1; + case GL_NUM_ACTIVE_VARIABLES: + *val = RESOURCE_UBO(res)->NumUniforms; + return 1; + case GL_ACTIVE_VARIABLES: + for (unsigned i = 0; i < RESOURCE_UBO(res)->NumUniforms; i++) { + const char *iname = RESOURCE_UBO(res)->Uniforms[i].IndexName; + struct gl_program_resource *uni = + _mesa_program_resource_find_name(shProg, GL_UNIFORM, iname); + *val++ = + _mesa_program_resource_index(shProg, uni); + } + return RESOURCE_UBO(res)->NumUniforms; + } + } else if (res->Type == GL_ATOMIC_COUNTER_BUFFER) { + switch (prop) { + case GL_BUFFER_BINDING: + *val = RESOURCE_ATC(res)->Binding; + return 1; + case GL_BUFFER_DATA_SIZE: + *val = RESOURCE_ATC(res)->MinimumSize; + return 1; + case GL_NUM_ACTIVE_VARIABLES: + *val = RESOURCE_ATC(res)->NumUniforms; + return 1; + case GL_ACTIVE_VARIABLES: + for (unsigned i = 0; i < RESOURCE_ATC(res)->NumUniforms; i++) + *val++ = RESOURCE_ATC(res)->Uniforms[i]; + return RESOURCE_ATC(res)->NumUniforms; + } + } + assert(!"support for property type not implemented"); + +invalid_operation: + _mesa_error(ctx, GL_INVALID_OPERATION, "%s(%s prop %s)", caller, + _mesa_lookup_enum_by_nr(res->Type), + _mesa_lookup_enum_by_nr(prop)); + + return 0; +} + +unsigned +_mesa_program_resource_prop(struct gl_shader_program *shProg, + struct gl_program_resource *res, GLuint index, + const GLenum prop, GLint *val, const char *caller) +{ + GET_CURRENT_CONTEXT(ctx); + +#define VALIDATE_TYPE(type)\ + if (res->Type != type)\ + goto invalid_operation; + + switch(prop) { + case GL_NAME_LENGTH: + if (res->Type == GL_ATOMIC_COUNTER_BUFFER) + goto invalid_operation; + /* Base name +3 if array '[0]' + terminator. */ + *val = strlen(_mesa_program_resource_name(res)) + + (_mesa_program_resource_array_size(res) > 0 ? 3 : 0) + 1; + return 1; + case GL_TYPE: + switch (res->Type) { + case GL_UNIFORM: + *val = RESOURCE_UNI(res)->type->gl_type; + return 1; + case GL_PROGRAM_INPUT: + case GL_PROGRAM_OUTPUT: + *val = RESOURCE_VAR(res)->type->gl_type; + return 1; + case GL_TRANSFORM_FEEDBACK_VARYING: + *val = RESOURCE_XFB(res)->Type; + return 1; + default: + goto invalid_operation; + } + case GL_ARRAY_SIZE: + switch (res->Type) { + case GL_UNIFORM: + *val = MAX2(RESOURCE_UNI(res)->array_elements, 1); + return 1; + case GL_PROGRAM_INPUT: + case GL_PROGRAM_OUTPUT: + *val = MAX2(RESOURCE_VAR(res)->type->length, 1); + return 1; + case GL_TRANSFORM_FEEDBACK_VARYING: + *val = MAX2(RESOURCE_XFB(res)->Size, 1); + return 1; + default: + goto invalid_operation; + } + case GL_OFFSET: + VALIDATE_TYPE(GL_UNIFORM); + *val = RESOURCE_UNI(res)->offset; + return 1; + case GL_BLOCK_INDEX: + VALIDATE_TYPE(GL_UNIFORM); + *val = RESOURCE_UNI(res)->block_index; + return 1; + case GL_ARRAY_STRIDE: + VALIDATE_TYPE(GL_UNIFORM); + *val = RESOURCE_UNI(res)->array_stride; + return 1; + case GL_MATRIX_STRIDE: + VALIDATE_TYPE(GL_UNIFORM); + *val = RESOURCE_UNI(res)->matrix_stride; + return 1; + case GL_IS_ROW_MAJOR: + VALIDATE_TYPE(GL_UNIFORM); + *val = RESOURCE_UNI(res)->row_major; + return 1; + case GL_ATOMIC_COUNTER_BUFFER_INDEX: + VALIDATE_TYPE(GL_UNIFORM); + *val = RESOURCE_UNI(res)->atomic_buffer_index; + return 1; + case GL_BUFFER_BINDING: + case GL_BUFFER_DATA_SIZE: + case GL_NUM_ACTIVE_VARIABLES: + case GL_ACTIVE_VARIABLES: + return get_buffer_property(shProg, res, prop, val, caller); + case GL_REFERENCED_BY_VERTEX_SHADER: + case GL_REFERENCED_BY_GEOMETRY_SHADER: + case GL_REFERENCED_BY_FRAGMENT_SHADER: + switch (res->Type) { + case GL_UNIFORM: + case GL_PROGRAM_INPUT: + case GL_PROGRAM_OUTPUT: + case GL_UNIFORM_BLOCK: + case GL_ATOMIC_COUNTER_BUFFER: + *val = is_resource_referenced(shProg, res, index, + stage_from_enum(prop)); + return 1; + default: + goto invalid_operation; + } + case GL_LOCATION: + switch (res->Type) { + case GL_UNIFORM: + case GL_PROGRAM_INPUT: + case GL_PROGRAM_OUTPUT: + *val = program_resource_location(shProg, res, + _mesa_program_resource_name(res)); + return 1; + default: + goto invalid_operation; + } + case GL_LOCATION_INDEX: + if (res->Type != GL_PROGRAM_OUTPUT) + goto invalid_operation; + *val = RESOURCE_VAR(res)->data.index; + return 1; + + /* GL_ARB_tessellation_shader */ + case GL_IS_PER_PATCH: + case GL_REFERENCED_BY_TESS_CONTROL_SHADER: + case GL_REFERENCED_BY_TESS_EVALUATION_SHADER: + /* GL_ARB_compute_shader */ + case GL_REFERENCED_BY_COMPUTE_SHADER: + default: + _mesa_error(ctx, GL_INVALID_ENUM, "%s(%s prop %s)", caller, + _mesa_lookup_enum_by_nr(res->Type), + _mesa_lookup_enum_by_nr(prop)); + return 0; + } + +#undef VALIDATE_TYPE + +invalid_operation: + _mesa_error(ctx, GL_INVALID_OPERATION, "%s(%s prop %s)", caller, + _mesa_lookup_enum_by_nr(res->Type), + _mesa_lookup_enum_by_nr(prop)); + return 0; +} + +extern void +_mesa_get_program_resourceiv(struct gl_shader_program *shProg, + GLenum programInterface, GLuint index, GLsizei propCount, + const GLenum *props, GLsizei bufSize, + GLsizei *length, GLint *params) +{ + GET_CURRENT_CONTEXT(ctx); + GLint *val = (GLint *) params; + const GLenum *prop = props; + GLsizei amount = 0; + + struct gl_program_resource *res = + _mesa_program_resource_find_index(shProg, programInterface, index); + + /* No such resource found or bufSize negative. */ + if (!res || bufSize < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glGetProgramResourceiv(%s index %d bufSize %d)", + _mesa_lookup_enum_by_nr(programInterface), index, bufSize); + return; + } + + /* Write propCount values until error occurs or bufSize reached. */ + for (int i = 0; i < propCount && i < bufSize; i++, val++, prop++) { + int props_written = + _mesa_program_resource_prop(shProg, res, index, *prop, val, + "glGetProgramResourceiv"); + + /* Error happened. */ + if (props_written == 0) + return; + + amount += props_written; + } + + /* If <length> is not NULL, the actual number of integer values + * written to <params> will be written to <length>. + */ + if (length) + *length = amount; } diff --git a/mesalib/src/mesa/main/shaderapi.c b/mesalib/src/mesa/main/shaderapi.c index 30716f5e3..77e2b8745 100644 --- a/mesalib/src/mesa/main/shaderapi.c +++ b/mesalib/src/mesa/main/shaderapi.c @@ -882,10 +882,9 @@ compile_shader(struct gl_context *ctx, GLuint shaderObj) sh->CompileStatus = GL_FALSE; } else { if (ctx->_Shader->Flags & GLSL_DUMP) { - fprintf(stderr, "GLSL source for %s shader %d:\n", + _mesa_log("GLSL source for %s shader %d:\n", _mesa_shader_stage_to_string(sh->Stage), sh->Name); - fprintf(stderr, "%s\n", sh->Source); - fflush(stderr); + _mesa_log("%s\n", sh->Source); } /* this call will set the shader->CompileStatus field to indicate if @@ -899,27 +898,25 @@ compile_shader(struct gl_context *ctx, GLuint shaderObj) if (ctx->_Shader->Flags & GLSL_DUMP) { if (sh->CompileStatus) { - fprintf(stderr, "GLSL IR for shader %d:\n", sh->Name); - _mesa_print_ir(stderr, sh->ir, NULL); - fprintf(stderr, "\n\n"); + _mesa_log("GLSL IR for shader %d:\n", sh->Name); + _mesa_print_ir(_mesa_get_log_file(), sh->ir, NULL); + _mesa_log("\n\n"); } else { - fprintf(stderr, "GLSL shader %d failed to compile.\n", sh->Name); + _mesa_log("GLSL shader %d failed to compile.\n", sh->Name); } if (sh->InfoLog && sh->InfoLog[0] != 0) { - fprintf(stderr, "GLSL shader %d info log:\n", sh->Name); - fprintf(stderr, "%s\n", sh->InfoLog); + _mesa_log("GLSL shader %d info log:\n", sh->Name); + _mesa_log("%s\n", sh->InfoLog); } - fflush(stderr); } } if (!sh->CompileStatus) { if (ctx->_Shader->Flags & GLSL_DUMP_ON_ERROR) { - fprintf(stderr, "GLSL source for %s shader %d:\n", + _mesa_log("GLSL source for %s shader %d:\n", _mesa_shader_stage_to_string(sh->Stage), sh->Name); - fprintf(stderr, "%s\n", sh->Source); - fprintf(stderr, "Info Log:\n%s\n", sh->InfoLog); - fflush(stderr); + _mesa_log("%s\n", sh->Source); + _mesa_log("Info Log:\n%s\n", sh->InfoLog); } if (ctx->_Shader->Flags & GLSL_REPORT_ERRORS) { diff --git a/mesalib/src/mesa/main/shaderapi.h b/mesalib/src/mesa/main/shaderapi.h index 047d2562d..aba6d5d83 100644 --- a/mesalib/src/mesa/main/shaderapi.h +++ b/mesalib/src/mesa/main/shaderapi.h @@ -219,6 +219,51 @@ extern GLuint GLAPIENTRY _mesa_CreateShaderProgramv(GLenum type, GLsizei count, const GLchar* const *strings); +/* GL_ARB_program_resource_query */ +extern const char* +_mesa_program_resource_name(struct gl_program_resource *res); + +extern unsigned +_mesa_program_resource_array_size(struct gl_program_resource *res); + +extern GLuint +_mesa_program_resource_index(struct gl_shader_program *shProg, + struct gl_program_resource *res); + +extern struct gl_program_resource * +_mesa_program_resource_find_name(struct gl_shader_program *shProg, + GLenum programInterface, const char *name); + +extern struct gl_program_resource * +_mesa_program_resource_find_index(struct gl_shader_program *shProg, + GLenum programInterface, GLuint index); + +extern bool +_mesa_get_program_resource_name(struct gl_shader_program *shProg, + GLenum programInterface, GLuint index, + GLsizei bufSize, GLsizei *length, + GLchar *name, const char *caller); + +extern GLint +_mesa_program_resource_location(struct gl_shader_program *shProg, + GLenum programInterface, const char *name); + +extern GLint +_mesa_program_resource_location_index(struct gl_shader_program *shProg, + GLenum programInterface, const char *name); + +extern unsigned +_mesa_program_resource_prop(struct gl_shader_program *shProg, + struct gl_program_resource *res, GLuint index, + const GLenum prop, GLint *val, const char *caller); + +extern void +_mesa_get_program_resourceiv(struct gl_shader_program *shProg, + GLenum programInterface, GLuint index, + GLsizei propCount, const GLenum *props, + GLsizei bufSize, GLsizei *length, + GLint *params); + #ifdef __cplusplus } #endif diff --git a/mesalib/src/mesa/main/shaderobj.c b/mesalib/src/mesa/main/shaderobj.c index d7620c8ef..e42896036 100644 --- a/mesalib/src/mesa/main/shaderobj.c +++ b/mesalib/src/mesa/main/shaderobj.c @@ -315,6 +315,12 @@ _mesa_clear_shader_program_data(struct gl_shader_program *shProg) ralloc_free(shProg->AtomicBuffers); shProg->AtomicBuffers = NULL; shProg->NumAtomicBuffers = 0; + + if (shProg->ProgramResourceList) { + ralloc_free(shProg->ProgramResourceList); + shProg->ProgramResourceList = NULL; + shProg->NumProgramResourceList = 0; + } } diff --git a/mesalib/src/mesa/main/state.c b/mesalib/src/mesa/main/state.c index dadfb3c8c..cc84c6148 100644 --- a/mesalib/src/mesa/main/state.c +++ b/mesalib/src/mesa/main/state.c @@ -269,28 +269,6 @@ update_program_constants(struct gl_context *ctx) -static void -update_viewport_matrix(struct gl_context *ctx) -{ - const GLfloat depthMax = ctx->DrawBuffer->_DepthMaxF; - unsigned i; - - assert(depthMax > 0); - - /* Compute scale and bias values. This is really driver-specific - * and should be maintained elsewhere if at all. - * NOTE: RasterPos uses this. - */ - for (i = 0; i < ctx->Const.MaxViewports; i++) { - double scale[3], translate[3]; - - _mesa_get_viewport_xform(ctx, i, scale, translate); - _math_matrix_viewport(&ctx->ViewportArray[i]._WindowMap, - scale, translate, depthMax); - } -} - - /** * Update the ctx->Polygon._FrontBit flag. */ @@ -407,9 +385,6 @@ _mesa_update_state_locked( struct gl_context *ctx ) if (new_state & _NEW_PIXEL) _mesa_update_pixel( ctx, new_state ); - if (new_state & (_NEW_BUFFERS | _NEW_VIEWPORT)) - update_viewport_matrix(ctx); - if (new_state & (_NEW_MULTISAMPLE | _NEW_BUFFERS)) update_multisample( ctx ); @@ -507,7 +482,7 @@ _mesa_set_varying_vp_inputs( struct gl_context *ctx, ctx->FragmentProgram._TexEnvProgram) { ctx->NewState |= _NEW_VARYING_VP_INPUTS; } - /*printf("%s %x\n", __FUNCTION__, varying_inputs);*/ + /*printf("%s %x\n", __func__, varying_inputs);*/ } } diff --git a/mesalib/src/mesa/main/texcompress.c b/mesalib/src/mesa/main/texcompress.c index 00234d4cc..0fd1a3683 100644 --- a/mesalib/src/mesa/main/texcompress.c +++ b/mesalib/src/mesa/main/texcompress.c @@ -32,7 +32,6 @@ #include "glheader.h" #include "imports.h" -#include "colormac.h" #include "context.h" #include "formats.h" #include "mtypes.h" diff --git a/mesalib/src/mesa/main/texcompress_fxt1.c b/mesalib/src/mesa/main/texcompress_fxt1.c index 562359410..f06f04882 100644 --- a/mesalib/src/mesa/main/texcompress_fxt1.c +++ b/mesalib/src/mesa/main/texcompress_fxt1.c @@ -31,7 +31,6 @@ #include "glheader.h" #include "imports.h" -#include "colormac.h" #include "image.h" #include "macros.h" #include "mipmap.h" diff --git a/mesalib/src/mesa/main/texcompress_rgtc.c b/mesalib/src/mesa/main/texcompress_rgtc.c index f40e4e6c0..66de1f17d 100644 --- a/mesalib/src/mesa/main/texcompress_rgtc.c +++ b/mesalib/src/mesa/main/texcompress_rgtc.c @@ -35,7 +35,6 @@ #include "glheader.h" #include "imports.h" -#include "colormac.h" #include "image.h" #include "macros.h" #include "mipmap.h" diff --git a/mesalib/src/mesa/main/texcompress_s3tc.c b/mesalib/src/mesa/main/texcompress_s3tc.c index 41d00d4e9..7ce3cb88e 100644 --- a/mesalib/src/mesa/main/texcompress_s3tc.c +++ b/mesalib/src/mesa/main/texcompress_s3tc.c @@ -29,13 +29,8 @@ * GL_EXT_texture_compression_s3tc support. */ -#ifndef USE_EXTERNAL_DXTN_LIB -#define USE_EXTERNAL_DXTN_LIB 1 -#endif - #include "glheader.h" #include "imports.h" -#include "colormac.h" #include "dlopen.h" #include "image.h" #include "macros.h" @@ -77,7 +72,6 @@ _mesa_init_texture_s3tc( struct gl_context *ctx ) { /* called during context initialization */ ctx->Mesa_DXTn = GL_FALSE; -#if USE_EXTERNAL_DXTN_LIB if (!dxtlibhandle) { dxtlibhandle = _mesa_dlopen(DXTN_LIBNAME, 0); if (!dxtlibhandle) { @@ -118,9 +112,6 @@ _mesa_init_texture_s3tc( struct gl_context *ctx ) if (dxtlibhandle) { ctx->Mesa_DXTn = GL_TRUE; } -#else - (void) ctx; -#endif } /** diff --git a/mesalib/src/mesa/main/texparam.c b/mesalib/src/mesa/main/texparam.c index 1ef728660..b5d42d304 100644 --- a/mesalib/src/mesa/main/texparam.c +++ b/mesalib/src/mesa/main/texparam.c @@ -32,7 +32,6 @@ #include <stdbool.h> #include "main/glheader.h" #include "main/blend.h" -#include "main/colormac.h" #include "main/context.h" #include "main/enums.h" #include "main/formats.h" diff --git a/mesalib/src/mesa/main/texstate.c b/mesalib/src/mesa/main/texstate.c index 0a7f983fb..1af9d47f0 100644 --- a/mesalib/src/mesa/main/texstate.c +++ b/mesalib/src/mesa/main/texstate.c @@ -31,8 +31,6 @@ #include <stdio.h> #include "glheader.h" #include "bufferobj.h" -#include "colormac.h" -#include "colortab.h" #include "context.h" #include "enums.h" #include "macros.h" diff --git a/mesalib/src/mesa/main/texstore.c b/mesalib/src/mesa/main/texstore.c index 7ad9d2b68..152520598 100644 --- a/mesalib/src/mesa/main/texstore.c +++ b/mesalib/src/mesa/main/texstore.c @@ -53,7 +53,6 @@ #include "glheader.h" #include "bufferobj.h" -#include "colormac.h" #include "format_pack.h" #include "format_utils.h" #include "image.h" diff --git a/mesalib/src/mesa/main/transformfeedback.c b/mesalib/src/mesa/main/transformfeedback.c index ce678c864..103011ce5 100644 --- a/mesalib/src/mesa/main/transformfeedback.c +++ b/mesalib/src/mesa/main/transformfeedback.c @@ -514,22 +514,24 @@ _mesa_EndTransformFeedback(void) * Helper used by BindBufferRange() and BindBufferBase(). */ static void -bind_buffer_range(struct gl_context *ctx, GLuint index, +bind_buffer_range(struct gl_context *ctx, + struct gl_transform_feedback_object *obj, + GLuint index, struct gl_buffer_object *bufObj, - GLintptr offset, GLsizeiptr size) + GLintptr offset, GLsizeiptr size, + bool dsa) { - struct gl_transform_feedback_object *obj = - ctx->TransformFeedback.CurrentObject; - /* Note: no need to FLUSH_VERTICES or flag NewTransformFeedback, because * transform feedback buffers can't be changed while transform feedback is * active. */ - /* The general binding point */ - _mesa_reference_buffer_object(ctx, - &ctx->TransformFeedback.CurrentBuffer, - bufObj); + if (!dsa) { + /* The general binding point */ + _mesa_reference_buffer_object(ctx, + &ctx->TransformFeedback.CurrentBuffer, + bufObj); + } /* The per-attribute binding point */ _mesa_set_transform_feedback_binding(ctx, obj, index, bufObj, offset, size); @@ -539,75 +541,209 @@ bind_buffer_range(struct gl_context *ctx, GLuint index, /** * Specify a buffer object to receive transform feedback results. Plus, * specify the starting offset to place the results, and max size. - * Called from the glBindBufferRange() function. + * Called from the glBindBufferRange() and glTransformFeedbackBufferRange + * functions. */ void _mesa_bind_buffer_range_transform_feedback(struct gl_context *ctx, - GLuint index, - struct gl_buffer_object *bufObj, - GLintptr offset, - GLsizeiptr size) + struct gl_transform_feedback_object *obj, + GLuint index, + struct gl_buffer_object *bufObj, + GLintptr offset, + GLsizeiptr size, + bool dsa) { - struct gl_transform_feedback_object *obj; + const char *gl_methd_name; + if (dsa) + gl_methd_name = "glTransformFeedbackBufferRange"; + else + gl_methd_name = "glBindBufferRange"; - obj = ctx->TransformFeedback.CurrentObject; if (obj->Active) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glBindBufferRange(transform feedback active)"); + _mesa_error(ctx, GL_INVALID_OPERATION, "%s(transform feedback active)", + gl_methd_name); return; } if (index >= ctx->Const.MaxTransformFeedbackBuffers) { - _mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferRange(index=%d)", index); + /* OpenGL 4.5 core profile, 6.1, pdf page 82: "An INVALID_VALUE error is + * generated if index is greater than or equal to the number of binding + * points for transform feedback, as described in section 6.7.1." + */ + _mesa_error(ctx, GL_INVALID_VALUE, "%s(index=%d out of bounds)", + gl_methd_name, index); return; } if (size & 0x3) { - /* must a multiple of four */ - _mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferRange(size=%d)", (int) size); + /* OpenGL 4.5 core profile, 6.7, pdf page 103: multiple of 4 */ + _mesa_error(ctx, GL_INVALID_VALUE, "%s(size=%d must be a multiple of " + "four)", gl_methd_name, (int) size); return; } if (offset & 0x3) { - /* must be multiple of four */ - _mesa_error(ctx, GL_INVALID_VALUE, - "glBindBufferRange(offset=%d)", (int) offset); + /* OpenGL 4.5 core profile, 6.7, pdf page 103: multiple of 4 */ + _mesa_error(ctx, GL_INVALID_VALUE, "%s(offset=%d must be a multiple " + "of four)", gl_methd_name, (int) offset); return; - } + } + + if (offset < 0) { + /* OpenGL 4.5 core profile, 6.1, pdf page 82: "An INVALID_VALUE error is + * generated by BindBufferRange if offset is negative." + * + * OpenGL 4.5 core profile, 13.2, pdf page 445: "An INVALID_VALUE error + * is generated by TransformFeedbackBufferRange if offset is negative." + */ + _mesa_error(ctx, GL_INVALID_VALUE, "%s(offset=%d must be >= 0)", + gl_methd_name, + (int) offset); + return; + } - bind_buffer_range(ctx, index, bufObj, offset, size); + if (size <= 0 && (dsa || bufObj != ctx->Shared->NullBufferObj)) { + /* OpenGL 4.5 core profile, 6.1, pdf page 82: "An INVALID_VALUE error is + * generated by BindBufferRange if buffer is non-zero and size is less + * than or equal to zero." + * + * OpenGL 4.5 core profile, 13.2, pdf page 445: "An INVALID_VALUE error + * is generated by TransformFeedbackBufferRange if size is less than or + * equal to zero." + */ + _mesa_error(ctx, GL_INVALID_VALUE, "%s(size=%d must be > 0)", + gl_methd_name, (int) size); + return; + } + + bind_buffer_range(ctx, obj, index, bufObj, offset, size, dsa); } /** * Specify a buffer object to receive transform feedback results. * As above, but start at offset = 0. - * Called from the glBindBufferBase() function. + * Called from the glBindBufferBase() and glTransformFeedbackBufferBase() + * functions. */ void _mesa_bind_buffer_base_transform_feedback(struct gl_context *ctx, - GLuint index, - struct gl_buffer_object *bufObj) + struct gl_transform_feedback_object *obj, + GLuint index, + struct gl_buffer_object *bufObj, + bool dsa) { - struct gl_transform_feedback_object *obj; - - obj = ctx->TransformFeedback.CurrentObject; - if (obj->Active) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glBindBufferBase(transform feedback active)"); + "%s(transform feedback active)", + dsa ? "glTransformFeedbackBufferBase" : "glBindBufferBase"); return; } if (index >= ctx->Const.MaxTransformFeedbackBuffers) { - _mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferBase(index=%d)", index); + _mesa_error(ctx, GL_INVALID_VALUE, "%s(index=%d out of bounds)", + dsa ? "glTransformFeedbackBufferBase" : "glBindBufferBase", + index); + return; + } + + bind_buffer_range(ctx, obj, index, bufObj, 0, 0, dsa); +} + +/** + * Wrapper around lookup_transform_feedback_object that throws + * GL_INVALID_OPERATION if id is not in the hash table. After calling + * _mesa_error, it returns NULL. + */ +static struct gl_transform_feedback_object * +lookup_transform_feedback_object_err(struct gl_context *ctx, + GLuint xfb, const char* func) +{ + struct gl_transform_feedback_object *obj; + + obj = _mesa_lookup_transform_feedback_object(ctx, xfb); + if (!obj) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s(xfb=%u: non-generated object name)", func, xfb); + } + + return obj; +} + +/** + * Wrapper around _mesa_lookup_bufferobj that throws GL_INVALID_VALUE if id + * is not in the hash table. Specialised version for the + * transform-feedback-related functions. After calling _mesa_error, it + * returns NULL. + */ +static struct gl_buffer_object * +lookup_transform_feedback_bufferobj_err(struct gl_context *ctx, + GLuint buffer, const char* func) +{ + struct gl_buffer_object *bufObj; + + /* OpenGL 4.5 core profile, 13.2, pdf page 444: buffer must be zero or the + * name of an existing buffer object. + */ + if (buffer == 0) { + bufObj = ctx->Shared->NullBufferObj; + } else { + bufObj = _mesa_lookup_bufferobj(ctx, buffer); + if (!bufObj) { + _mesa_error(ctx, GL_INVALID_VALUE, "%s(invalid buffer=%u)", func, + buffer); + } + } + + return bufObj; +} + +void GLAPIENTRY +_mesa_TransformFeedbackBufferBase(GLuint xfb, GLuint index, GLuint buffer) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_transform_feedback_object *obj; + struct gl_buffer_object *bufObj; + + obj = lookup_transform_feedback_object_err(ctx, xfb, + "glTransformFeedbackBufferBase"); + if(!obj) { + return; + } + + bufObj = lookup_transform_feedback_bufferobj_err(ctx, buffer, + "glTransformFeedbackBufferBase"); + if(!bufObj) { return; } - bind_buffer_range(ctx, index, bufObj, 0, 0); + _mesa_bind_buffer_base_transform_feedback(ctx, obj, index, bufObj, true); } +void GLAPIENTRY +_mesa_TransformFeedbackBufferRange(GLuint xfb, GLuint index, GLuint buffer, + GLintptr offset, GLsizeiptr size) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_transform_feedback_object *obj; + struct gl_buffer_object *bufObj; + + obj = lookup_transform_feedback_object_err(ctx, xfb, + "glTransformFeedbackBufferRange"); + if(!obj) { + return; + } + + bufObj = lookup_transform_feedback_bufferobj_err(ctx, buffer, + "glTransformFeedbackBufferRange"); + if(!bufObj) { + return; + } + + _mesa_bind_buffer_range_transform_feedback(ctx, obj, index, bufObj, offset, + size, true); +} /** * Specify a buffer object to receive transform feedback results, plus the @@ -660,7 +796,7 @@ _mesa_BindBufferOffsetEXT(GLenum target, GLuint index, GLuint buffer, return; } - bind_buffer_range(ctx, index, bufObj, offset, 0); + bind_buffer_range(ctx, obj, index, bufObj, offset, 0, false); } @@ -784,7 +920,7 @@ _mesa_GetTransformFeedbackVarying(GLuint program, GLuint index, GLsizei *size, GLenum *type, GLchar *name) { const struct gl_shader_program *shProg; - const struct gl_transform_feedback_info *linked_xfb_info; + struct gl_program_resource *res; GET_CURRENT_CONTEXT(ctx); shProg = _mesa_lookup_shader_program(ctx, program); @@ -794,22 +930,27 @@ _mesa_GetTransformFeedbackVarying(GLuint program, GLuint index, return; } - linked_xfb_info = &shProg->LinkedTransformFeedback; - if (index >= (GLuint) linked_xfb_info->NumVarying) { + res = _mesa_program_resource_find_index((struct gl_shader_program *) shProg, + GL_TRANSFORM_FEEDBACK_VARYING, + index); + if (!res) { _mesa_error(ctx, GL_INVALID_VALUE, "glGetTransformFeedbackVarying(index=%u)", index); return; } /* return the varying's name and length */ - _mesa_copy_string(name, bufSize, length, - linked_xfb_info->Varyings[index].Name); + _mesa_copy_string(name, bufSize, length, _mesa_program_resource_name(res)); /* return the datatype and value's size (in datatype units) */ if (type) - *type = linked_xfb_info->Varyings[index].Type; + _mesa_program_resource_prop((struct gl_shader_program *) shProg, + res, index, GL_TYPE, (GLint*) type, + "glGetTransformFeedbackVarying"); if (size) - *size = linked_xfb_info->Varyings[index].Size; + _mesa_program_resource_prop((struct gl_shader_program *) shProg, + res, index, GL_ARRAY_SIZE, (GLint*) size, + "glGetTransformFeedbackVarying"); } @@ -817,6 +958,10 @@ _mesa_GetTransformFeedbackVarying(GLuint program, GLuint index, struct gl_transform_feedback_object * _mesa_lookup_transform_feedback_object(struct gl_context *ctx, GLuint name) { + /* OpenGL 4.5 core profile, 13.2 pdf page 444: "xfb must be zero, indicating + * the default transform feedback object, or the name of an existing + * transform feedback object." + */ if (name == 0) { return ctx->TransformFeedback.DefaultObject; } @@ -825,25 +970,24 @@ _mesa_lookup_transform_feedback_object(struct gl_context *ctx, GLuint name) _mesa_HashLookup(ctx->TransformFeedback.Objects, name); } - -/** - * Create new transform feedback objects. Transform feedback objects - * encapsulate the state related to transform feedback to allow quickly - * switching state (and drawing the results, below). - * Part of GL_ARB_transform_feedback2. - */ -void GLAPIENTRY -_mesa_GenTransformFeedbacks(GLsizei n, GLuint *names) +static void +create_transform_feedbacks(struct gl_context *ctx, GLsizei n, GLuint *ids, + bool dsa) { GLuint first; - GET_CURRENT_CONTEXT(ctx); + const char* func; + + if (dsa) + func = "glCreateTransformFeedbacks"; + else + func = "glGenTransformFeedbacks"; if (n < 0) { - _mesa_error(ctx, GL_INVALID_VALUE, "glGenTransformFeedbacks(n < 0)"); + _mesa_error(ctx, GL_INVALID_VALUE, "%s(n < 0)", func); return; } - if (!names) + if (!ids) return; /* we don't need contiguous IDs, but this might be faster */ @@ -854,18 +998,56 @@ _mesa_GenTransformFeedbacks(GLsizei n, GLuint *names) struct gl_transform_feedback_object *obj = ctx->Driver.NewTransformFeedback(ctx, first + i); if (!obj) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenTransformFeedbacks"); + _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func); return; } - names[i] = first + i; + ids[i] = first + i; _mesa_HashInsert(ctx->TransformFeedback.Objects, first + i, obj); + if (dsa) { + /* this is normally done at bind time in the non-dsa case */ + obj->EverBound = GL_TRUE; + } } } else { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenTransformFeedbacks"); + _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func); } } +/** + * Create new transform feedback objects. Transform feedback objects + * encapsulate the state related to transform feedback to allow quickly + * switching state (and drawing the results, below). + * Part of GL_ARB_transform_feedback2. + */ +void GLAPIENTRY +_mesa_GenTransformFeedbacks(GLsizei n, GLuint *names) +{ + GET_CURRENT_CONTEXT(ctx); + + /* GenTransformFeedbacks should just reserve the object names that a + * subsequent call to BindTransformFeedback should actively create. For + * the sake of simplicity, we reserve the names and create the objects + * straight away. + */ + + create_transform_feedbacks(ctx, n, names, false); +} + +/** + * Create new transform feedback objects. Transform feedback objects + * encapsulate the state related to transform feedback to allow quickly + * switching state (and drawing the results, below). + * Part of GL_ARB_direct_state_access. + */ +void GLAPIENTRY +_mesa_CreateTransformFeedbacks(GLsizei n, GLuint *names) +{ + GET_CURRENT_CONTEXT(ctx); + + create_transform_feedbacks(ctx, n, names, true); +} + /** * Is the given ID a transform feedback object? @@ -1026,3 +1208,89 @@ _mesa_ResumeTransformFeedback(void) assert(ctx->Driver.ResumeTransformFeedback); ctx->Driver.ResumeTransformFeedback(ctx, obj); } + +extern void GLAPIENTRY +_mesa_GetTransformFeedbackiv(GLuint xfb, GLenum pname, GLint *param) +{ + struct gl_transform_feedback_object *obj; + GET_CURRENT_CONTEXT(ctx); + + obj = lookup_transform_feedback_object_err(ctx, xfb, + "glGetTransformFeedbackiv"); + if(!obj) { + return; + } + + switch(pname) { + case GL_TRANSFORM_FEEDBACK_PAUSED: + *param = obj->Paused; + break; + case GL_TRANSFORM_FEEDBACK_ACTIVE: + *param = obj->Active; + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, + "glGetTransformFeedbackiv(pname=%i)", pname); + } +} + +extern void GLAPIENTRY +_mesa_GetTransformFeedbacki_v(GLuint xfb, GLenum pname, GLuint index, + GLint *param) +{ + struct gl_transform_feedback_object *obj; + GET_CURRENT_CONTEXT(ctx); + + obj = lookup_transform_feedback_object_err(ctx, xfb, + "glGetTransformFeedbacki_v"); + if(!obj) { + return; + } + + if (index >= ctx->Const.MaxTransformFeedbackBuffers) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glGetTransformFeedbacki_v(index=%i)", index); + return; + } + + switch(pname) { + case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING: + *param = obj->BufferNames[index]; + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, + "glGetTransformFeedbacki_v(pname=%i)", pname); + } +} + +extern void GLAPIENTRY +_mesa_GetTransformFeedbacki64_v(GLuint xfb, GLenum pname, GLuint index, + GLint64 *param) +{ + struct gl_transform_feedback_object *obj; + GET_CURRENT_CONTEXT(ctx); + + obj = lookup_transform_feedback_object_err(ctx, xfb, + "glGetTransformFeedbacki64_v"); + if(!obj) { + return; + } + + if (index >= ctx->Const.MaxTransformFeedbackBuffers) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glGetTransformFeedbacki64_v(index=%i)", index); + return; + } + + switch(pname) { + case GL_TRANSFORM_FEEDBACK_BUFFER_START: + *param = obj->Offset[index]; + break; + case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE: + *param = obj->RequestedSize[index]; + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, + "glGetTransformFeedbacki64_v(pname=%i)", pname); + } +} diff --git a/mesalib/src/mesa/main/transformfeedback.h b/mesalib/src/mesa/main/transformfeedback.h index 87f4080e0..bb9729cdb 100644 --- a/mesalib/src/mesa/main/transformfeedback.h +++ b/mesalib/src/mesa/main/transformfeedback.h @@ -65,15 +65,18 @@ _mesa_EndTransformFeedback(void); extern void _mesa_bind_buffer_range_transform_feedback(struct gl_context *ctx, + struct gl_transform_feedback_object *obj, GLuint index, struct gl_buffer_object *bufObj, GLintptr offset, - GLsizeiptr size); + GLsizeiptr size, bool dsa); extern void _mesa_bind_buffer_base_transform_feedback(struct gl_context *ctx, + struct gl_transform_feedback_object *obj, GLuint index, - struct gl_buffer_object *bufObj); + struct gl_buffer_object *bufObj, + bool dsa); extern void GLAPIENTRY _mesa_BindBufferOffsetEXT(GLenum target, GLuint index, GLuint buffer, @@ -102,6 +105,9 @@ _mesa_lookup_transform_feedback_object(struct gl_context *ctx, GLuint name); extern void GLAPIENTRY _mesa_GenTransformFeedbacks(GLsizei n, GLuint *names); +extern void GLAPIENTRY +_mesa_CreateTransformFeedbacks(GLsizei n, GLuint *names); + extern GLboolean GLAPIENTRY _mesa_IsTransformFeedback(GLuint name); @@ -141,4 +147,24 @@ _mesa_set_transform_feedback_binding(struct gl_context *ctx, tfObj->RequestedSize[index] = size; } +/*** GL_ARB_direct_state_access ***/ + +extern void GLAPIENTRY +_mesa_TransformFeedbackBufferBase(GLuint xfb, GLuint index, GLuint buffer); + +extern void GLAPIENTRY +_mesa_TransformFeedbackBufferRange(GLuint xfb, GLuint index, GLuint buffer, + GLintptr offset, GLsizeiptr size); + +extern void GLAPIENTRY +_mesa_GetTransformFeedbackiv(GLuint xfb, GLenum pname, GLint *param); + +extern void GLAPIENTRY +_mesa_GetTransformFeedbacki_v(GLuint xfb, GLenum pname, GLuint index, + GLint *param); + +extern void GLAPIENTRY +_mesa_GetTransformFeedbacki64_v(GLuint xfb, GLenum pname, GLuint index, + GLint64 *param); + #endif /* TRANSFORM_FEEDBACK_H */ diff --git a/mesalib/src/mesa/main/uniform_query.cpp b/mesalib/src/mesa/main/uniform_query.cpp index 2ab5528c3..4e77b3284 100644 --- a/mesalib/src/mesa/main/uniform_query.cpp +++ b/mesalib/src/mesa/main/uniform_query.cpp @@ -46,6 +46,7 @@ _mesa_GetActiveUniform(GLuint program, GLuint index, { GET_CURRENT_CONTEXT(ctx); struct gl_shader_program *shProg; + struct gl_program_resource *res; if (maxLength < 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(maxLength < 0)"); @@ -56,26 +57,51 @@ _mesa_GetActiveUniform(GLuint program, GLuint index, if (!shProg) return; - if (index >= shProg->NumUserUniformStorage) { + res = _mesa_program_resource_find_index((struct gl_shader_program *) shProg, + GL_UNIFORM, index); + + if (!res) { _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)"); return; } - const struct gl_uniform_storage *const uni = &shProg->UniformStorage[index]; - - if (nameOut) { - _mesa_get_uniform_name(uni, maxLength, length, nameOut); - } - - if (size) { - /* array_elements is zero for non-arrays, but the API requires that 1 be - * returned. - */ - *size = MAX2(1, uni->array_elements); - } + if (nameOut) + _mesa_get_program_resource_name(shProg, GL_UNIFORM, index, maxLength, + length, nameOut, "glGetActiveUniform"); + if (type) + _mesa_program_resource_prop((struct gl_shader_program *) shProg, + res, index, GL_TYPE, (GLint*) type, + "glGetActiveUniform"); + if (size) + _mesa_program_resource_prop((struct gl_shader_program *) shProg, + res, index, GL_ARRAY_SIZE, (GLint*) size, + "glGetActiveUniform"); +} - if (type) { - *type = uni->type->gl_type; +static GLenum +resource_prop_from_uniform_prop(GLenum uni_prop) +{ + switch (uni_prop) { + case GL_UNIFORM_TYPE: + return GL_TYPE; + case GL_UNIFORM_SIZE: + return GL_ARRAY_SIZE; + case GL_UNIFORM_NAME_LENGTH: + return GL_NAME_LENGTH; + case GL_UNIFORM_BLOCK_INDEX: + return GL_BLOCK_INDEX; + case GL_UNIFORM_OFFSET: + return GL_OFFSET; + case GL_UNIFORM_ARRAY_STRIDE: + return GL_ARRAY_STRIDE; + case GL_UNIFORM_MATRIX_STRIDE: + return GL_MATRIX_STRIDE; + case GL_UNIFORM_IS_ROW_MAJOR: + return GL_IS_ROW_MAJOR; + case GL_UNIFORM_ATOMIC_COUNTER_BUFFER_INDEX: + return GL_ATOMIC_COUNTER_BUFFER_INDEX; + default: + return 0; } } @@ -88,7 +114,8 @@ _mesa_GetActiveUniformsiv(GLuint program, { GET_CURRENT_CONTEXT(ctx); struct gl_shader_program *shProg; - GLsizei i; + struct gl_program_resource *res; + GLenum res_prop; if (uniformCount < 0) { _mesa_error(ctx, GL_INVALID_VALUE, @@ -100,80 +127,21 @@ _mesa_GetActiveUniformsiv(GLuint program, if (!shProg) return; - for (i = 0; i < uniformCount; i++) { - GLuint index = uniformIndices[i]; + res_prop = resource_prop_from_uniform_prop(pname); - if (index >= shProg->NumUserUniformStorage) { - _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniformsiv(index)"); - return; + for (int i = 0; i < uniformCount; i++) { + res = _mesa_program_resource_find_index(shProg, GL_UNIFORM, + uniformIndices[i]); + if (!res) { + _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniformsiv(index)"); + break; } - } - - for (i = 0; i < uniformCount; i++) { - GLuint index = uniformIndices[i]; - const struct gl_uniform_storage *uni = &shProg->UniformStorage[index]; - - switch (pname) { - case GL_UNIFORM_TYPE: - params[i] = uni->type->gl_type; - break; - - case GL_UNIFORM_SIZE: - /* array_elements is zero for non-arrays, but the API requires that 1 be - * returned. - */ - params[i] = MAX2(1, uni->array_elements); - break; - case GL_UNIFORM_NAME_LENGTH: - params[i] = strlen(uni->name) + 1; - - /* Page 61 (page 73 of the PDF) in section 2.11 of the OpenGL ES 3.0 - * spec says: - * - * "If the active uniform is an array, the uniform name returned - * in name will always be the name of the uniform array appended - * with "[0]"." - */ - if (uni->array_elements != 0) - params[i] += 3; - break; - - case GL_UNIFORM_BLOCK_INDEX: - params[i] = uni->block_index; - break; - - case GL_UNIFORM_OFFSET: - params[i] = uni->offset; - break; - - case GL_UNIFORM_ARRAY_STRIDE: - params[i] = uni->array_stride; - break; - - case GL_UNIFORM_MATRIX_STRIDE: - params[i] = uni->matrix_stride; - break; - - case GL_UNIFORM_IS_ROW_MAJOR: - params[i] = uni->row_major; - break; - - case GL_UNIFORM_ATOMIC_COUNTER_BUFFER_INDEX: - if (!ctx->Extensions.ARB_shader_atomic_counters) - goto invalid_enum; - params[i] = uni->atomic_buffer_index; + if (!_mesa_program_resource_prop(shProg, res, uniformIndices[i], + res_prop, ¶ms[i], + "glGetActiveUniformsiv")) break; - - default: - goto invalid_enum; - } } - - return; - - invalid_enum: - _mesa_error(ctx, GL_INVALID_ENUM, "glGetActiveUniformsiv(pname)"); } static struct gl_uniform_storage * diff --git a/mesalib/src/mesa/main/uniforms.c b/mesalib/src/mesa/main/uniforms.c index fb1482f9c..5548d1d02 100644 --- a/mesalib/src/mesa/main/uniforms.c +++ b/mesalib/src/mesa/main/uniforms.c @@ -911,7 +911,6 @@ GLint GLAPIENTRY _mesa_GetUniformLocation(GLuint programObj, const GLcharARB *name) { struct gl_shader_program *shProg; - GLuint index, offset; GET_CURRENT_CONTEXT(ctx); @@ -931,23 +930,7 @@ _mesa_GetUniformLocation(GLuint programObj, const GLcharARB *name) return -1; } - index = _mesa_get_uniform_location(shProg, name, &offset); - if (index == GL_INVALID_INDEX) - return -1; - - /* From the GL_ARB_uniform_buffer_object spec: - * - * "The value -1 will be returned if <name> does not correspond to an - * active uniform variable name in <program>, if <name> is associated - * with a named uniform block, or if <name> starts with the reserved - * prefix "gl_"." - */ - if (shProg->UniformStorage[index].block_index != -1 || - shProg->UniformStorage[index].atomic_buffer_index != -1) - return -1; - - /* location in remap table + array element offset */ - return shProg->UniformStorage[index].remap_location + offset; + return _mesa_program_resource_location(shProg, GL_UNIFORM, name); } GLuint GLAPIENTRY @@ -955,7 +938,6 @@ _mesa_GetUniformBlockIndex(GLuint program, const GLchar *uniformBlockName) { GET_CURRENT_CONTEXT(ctx); - GLuint i; struct gl_shader_program *shProg; if (!ctx->Extensions.ARB_uniform_buffer_object) { @@ -968,12 +950,13 @@ _mesa_GetUniformBlockIndex(GLuint program, if (!shProg) return GL_INVALID_INDEX; - for (i = 0; i < shProg->NumUniformBlocks; i++) { - if (!strcmp(shProg->UniformBlocks[i].Name, uniformBlockName)) - return i; - } + struct gl_program_resource *res = + _mesa_program_resource_find_name(shProg, GL_UNIFORM_BLOCK, + uniformBlockName); + if (!res) + return GL_INVALID_INDEX; - return GL_INVALID_INDEX; + return _mesa_program_resource_index(shProg, res); } void GLAPIENTRY @@ -1003,9 +986,9 @@ _mesa_GetUniformIndices(GLuint program, } for (i = 0; i < uniformCount; i++) { - unsigned offset; - uniformIndices[i] = _mesa_get_uniform_location(shProg, - uniformNames[i], &offset); + struct gl_program_resource *res = + _mesa_program_resource_find_name(shProg, GL_UNIFORM, uniformNames[i]); + uniformIndices[i] = _mesa_program_resource_index(shProg, res); } } @@ -1061,104 +1044,104 @@ _mesa_UniformBlockBinding(GLuint program, } } -void GLAPIENTRY -_mesa_GetActiveUniformBlockiv(GLuint program, - GLuint uniformBlockIndex, - GLenum pname, - GLint *params) + +/** + * Generic program resource property query. + */ +static void +mesa_bufferiv(struct gl_shader_program *shProg, GLenum type, + GLuint index, GLenum pname, GLint *params, const char *caller) { GET_CURRENT_CONTEXT(ctx); - struct gl_shader_program *shProg; - struct gl_uniform_block *block; - unsigned i; + struct gl_program_resource *res = + _mesa_program_resource_find_index(shProg, type, index); - if (!ctx->Extensions.ARB_uniform_buffer_object) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glGetActiveUniformBlockiv"); + if (!res) { + _mesa_error(ctx, GL_INVALID_VALUE, "%s(bufferindex %d)", caller, index); return; } - shProg = _mesa_lookup_shader_program_err(ctx, program, - "glGetActiveUniformBlockiv"); - if (!shProg) - return; - - if (uniformBlockIndex >= shProg->NumUniformBlocks) { - _mesa_error(ctx, GL_INVALID_VALUE, - "glGetActiveUniformBlockiv(block index %u >= %u)", - uniformBlockIndex, shProg->NumUniformBlocks); - return; - } - - block = &shProg->UniformBlocks[uniformBlockIndex]; - switch (pname) { case GL_UNIFORM_BLOCK_BINDING: - params[0] = block->Binding; + case GL_ATOMIC_COUNTER_BUFFER_BINDING: + _mesa_program_resource_prop(shProg, res, index, GL_BUFFER_BINDING, + params, caller); return; - case GL_UNIFORM_BLOCK_DATA_SIZE: - params[0] = block->UniformBufferSize; + case GL_ATOMIC_COUNTER_BUFFER_DATA_SIZE: + _mesa_program_resource_prop(shProg, res, index, GL_BUFFER_DATA_SIZE, + params, caller); return; - case GL_UNIFORM_BLOCK_NAME_LENGTH: - params[0] = strlen(block->Name) + 1; + _mesa_program_resource_prop(shProg, res, index, GL_NAME_LENGTH, + params, caller); return; - - case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS: { - unsigned count = 0; - - for (i = 0; i < block->NumUniforms; i++) { - unsigned offset; - const int idx = - _mesa_get_uniform_location(shProg, - block->Uniforms[i].IndexName, - &offset); - if (idx != -1) - count++; - } - - params[0] = count; + case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS: + case GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTERS: + _mesa_program_resource_prop(shProg, res, index, GL_NUM_ACTIVE_VARIABLES, + params, caller); return; - } - - case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES: { - unsigned count = 0; - - for (i = 0; i < block->NumUniforms; i++) { - unsigned offset; - const int idx = - _mesa_get_uniform_location(shProg, - block->Uniforms[i].IndexName, - &offset); - - if (idx != -1) - params[count++] = idx; - } + case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES: + case GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTER_INDICES: + _mesa_program_resource_prop(shProg, res, index, GL_ACTIVE_VARIABLES, + params, caller); return; - } - case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER: - params[0] = shProg->UniformBlockStageIndex[MESA_SHADER_VERTEX][uniformBlockIndex] != -1; + case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_VERTEX_SHADER: + _mesa_program_resource_prop(shProg, res, index, + GL_REFERENCED_BY_VERTEX_SHADER, params, + caller); return; - case GL_UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER: - if (!_mesa_has_geometry_shaders(ctx)) - break; - params[0] = shProg->UniformBlockStageIndex[MESA_SHADER_GEOMETRY][uniformBlockIndex] != -1; + case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_GEOMETRY_SHADER: + _mesa_program_resource_prop(shProg, res, index, + GL_REFERENCED_BY_GEOMETRY_SHADER, params, + caller); return; - case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER: - params[0] = shProg->UniformBlockStageIndex[MESA_SHADER_FRAGMENT][uniformBlockIndex] != -1; + case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_FRAGMENT_SHADER: + _mesa_program_resource_prop(shProg, res, index, + GL_REFERENCED_BY_FRAGMENT_SHADER, params, + caller); + return; + case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_CONTROL_SHADER: + params[0] = GL_FALSE; + return; + case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_EVALUATION_SHADER: + params[0] = GL_FALSE; return; - default: _mesa_error(ctx, GL_INVALID_ENUM, - "glGetActiveUniformBlockiv(pname 0x%x (%s))", - pname, _mesa_lookup_enum_by_nr(pname)); + "%s(pname 0x%x (%s))", caller, pname, + _mesa_lookup_enum_by_nr(pname)); return; } } + +void GLAPIENTRY +_mesa_GetActiveUniformBlockiv(GLuint program, + GLuint uniformBlockIndex, + GLenum pname, + GLint *params) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_shader_program *shProg; + + if (!ctx->Extensions.ARB_uniform_buffer_object) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glGetActiveUniformBlockiv"); + return; + } + + shProg = _mesa_lookup_shader_program_err(ctx, program, + "glGetActiveUniformBlockiv"); + if (!shProg) + return; + + mesa_bufferiv(shProg, GL_UNIFORM_BLOCK, uniformBlockIndex, pname, params, + "glGetActiveUniformBlockiv"); +} + void GLAPIENTRY _mesa_GetActiveUniformBlockName(GLuint program, GLuint uniformBlockIndex, @@ -1168,7 +1151,6 @@ _mesa_GetActiveUniformBlockName(GLuint program, { GET_CURRENT_CONTEXT(ctx); struct gl_shader_program *shProg; - struct gl_uniform_block *block; if (!ctx->Extensions.ARB_uniform_buffer_object) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetActiveUniformBlockiv"); @@ -1187,18 +1169,11 @@ _mesa_GetActiveUniformBlockName(GLuint program, if (!shProg) return; - if (uniformBlockIndex >= shProg->NumUniformBlocks) { - _mesa_error(ctx, GL_INVALID_VALUE, - "glGetActiveUniformBlockiv(block index %u >= %u)", - uniformBlockIndex, shProg->NumUniformBlocks); - return; - } - - block = &shProg->UniformBlocks[uniformBlockIndex]; - - if (uniformBlockName) { - _mesa_copy_string(uniformBlockName, bufSize, length, block->Name); - } + if (uniformBlockName) + _mesa_get_program_resource_name(shProg, GL_UNIFORM_BLOCK, + uniformBlockIndex, bufSize, length, + uniformBlockName, + "glGetActiveUniformBlockName"); } void GLAPIENTRY @@ -1226,54 +1201,8 @@ _mesa_GetActiveUniformName(GLuint program, GLuint uniformIndex, if (!shProg) return; - if (uniformIndex >= shProg->NumUserUniformStorage) { - _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)"); - return; - } - - if (uniformName) { - _mesa_get_uniform_name(& shProg->UniformStorage[uniformIndex], - bufSize, length, uniformName); - } -} - -void -_mesa_get_uniform_name(const struct gl_uniform_storage *uni, - GLsizei maxLength, GLsizei *length, - GLchar *nameOut) -{ - GLsizei localLength; - - if (length == NULL) - length = &localLength; - - _mesa_copy_string(nameOut, maxLength, length, uni->name); - - /* Page 61 (page 73 of the PDF) in section 2.11 of the OpenGL ES 3.0 - * spec says: - * - * "If the active uniform is an array, the uniform name returned in - * name will always be the name of the uniform array appended with - * "[0]"." - * - * The same text also appears in the OpenGL 4.2 spec. It does not, - * however, appear in any previous spec. Previous specifications are - * ambiguous in this regard. However, either name can later be passed - * to glGetUniformLocation (and related APIs), so there shouldn't be any - * harm in always appending "[0]" to uniform array names. - */ - if (uni->array_elements != 0) { - int i; - - /* The comparison is strange because *length does *NOT* include the - * terminating NUL, but maxLength does. - */ - for (i = 0; i < 3 && (*length + i + 1) < maxLength; i++) - nameOut[*length + i] = "[0]"[i]; - - nameOut[*length + i] = '\0'; - *length += i; - } + _mesa_get_program_resource_name(shProg, GL_UNIFORM, uniformIndex, bufSize, + length, uniformName, "glGetActiveUniformName"); } void GLAPIENTRY @@ -1282,8 +1211,6 @@ _mesa_GetActiveAtomicCounterBufferiv(GLuint program, GLuint bufferIndex, { GET_CURRENT_CONTEXT(ctx); struct gl_shader_program *shProg; - struct gl_active_atomic_buffer *ab; - GLuint i; if (!ctx->Extensions.ARB_shader_atomic_counters) { _mesa_error(ctx, GL_INVALID_OPERATION, @@ -1296,49 +1223,8 @@ _mesa_GetActiveAtomicCounterBufferiv(GLuint program, GLuint bufferIndex, if (!shProg) return; - if (bufferIndex >= shProg->NumAtomicBuffers) { - _mesa_error(ctx, GL_INVALID_VALUE, - "glGetActiveAtomicCounterBufferiv(bufferIndex)"); - return; - } - - ab = &shProg->AtomicBuffers[bufferIndex]; - - switch (pname) { - case GL_ATOMIC_COUNTER_BUFFER_BINDING: - params[0] = ab->Binding; - return; - case GL_ATOMIC_COUNTER_BUFFER_DATA_SIZE: - params[0] = ab->MinimumSize; - return; - case GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTERS: - params[0] = ab->NumUniforms; - return; - case GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTER_INDICES: - for (i = 0; i < ab->NumUniforms; ++i) - params[i] = ab->Uniforms[i]; - return; - case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_VERTEX_SHADER: - params[0] = ab->StageReferences[MESA_SHADER_VERTEX]; - return; - case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_GEOMETRY_SHADER: - params[0] = ab->StageReferences[MESA_SHADER_GEOMETRY]; - return; - case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_FRAGMENT_SHADER: - params[0] = ab->StageReferences[MESA_SHADER_FRAGMENT]; - return; - case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_CONTROL_SHADER: - params[0] = GL_FALSE; - return; - case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_EVALUATION_SHADER: - params[0] = GL_FALSE; - return; - default: - _mesa_error(ctx, GL_INVALID_ENUM, - "glGetActiveAtomicCounterBufferiv(pname 0x%x (%s))", - pname, _mesa_lookup_enum_by_nr(pname)); - return; - } + mesa_bufferiv(shProg, GL_ATOMIC_COUNTER_BUFFER, bufferIndex, pname, params, + "glGetActiveAtomicCounterBufferiv"); } void GLAPIENTRY diff --git a/mesalib/src/mesa/main/uniforms.h b/mesalib/src/mesa/main/uniforms.h index 0e6113fe9..55fa2357e 100644 --- a/mesalib/src/mesa/main/uniforms.h +++ b/mesalib/src/mesa/main/uniforms.h @@ -398,11 +398,6 @@ _mesa_sampler_uniforms_pipeline_are_valid(struct gl_pipeline_object *); extern const struct gl_program_parameter * get_uniform_parameter(struct gl_shader_program *shProg, GLint index); -extern void -_mesa_get_uniform_name(const struct gl_uniform_storage *uni, - GLsizei maxLength, GLsizei *length, - GLchar *nameOut); - struct gl_builtin_uniform_element { const char *field; int tokens[STATE_LENGTH]; diff --git a/mesalib/src/mesa/main/version.c b/mesalib/src/mesa/main/version.c index 8e0c3ef5b..7c6d99418 100644 --- a/mesalib/src/mesa/main/version.c +++ b/mesalib/src/mesa/main/version.c @@ -382,6 +382,7 @@ compute_version_es2(const struct gl_extensions *extensions) extensions->ARB_shader_texture_lod && extensions->ARB_texture_float && extensions->ARB_texture_rg && + extensions->ARB_depth_buffer_float && extensions->EXT_draw_buffers2 && /* extensions->ARB_framebuffer_object && */ extensions->EXT_framebuffer_sRGB && diff --git a/mesalib/src/mesa/main/viewport.c b/mesalib/src/mesa/main/viewport.c index 0adce9c78..b27063031 100644 --- a/mesalib/src/mesa/main/viewport.c +++ b/mesalib/src/mesa/main/viewport.c @@ -40,8 +40,6 @@ set_viewport_no_notify(struct gl_context *ctx, unsigned idx, GLfloat x, GLfloat y, GLfloat width, GLfloat height) { - double scale[3], translate[3]; - /* clamp width and height to the implementation dependent range */ width = MIN2(width, (GLfloat) ctx->Const.MaxViewportWidth); height = MIN2(height, (GLfloat) ctx->Const.MaxViewportHeight); @@ -72,16 +70,6 @@ set_viewport_no_notify(struct gl_context *ctx, unsigned idx, ctx->ViewportArray[idx].Y = y; ctx->ViewportArray[idx].Height = height; ctx->NewState |= _NEW_VIEWPORT; - -#if 1 - /* XXX remove this someday. Currently the DRI drivers rely on - * the WindowMap matrix being up to date in the driver's Viewport - * and DepthRange functions. - */ - _mesa_get_viewport_xform(ctx, idx, scale, translate); - _math_matrix_viewport(&ctx->ViewportArray[idx]._WindowMap, - scale, translate, ctx->DrawBuffer->_DepthMaxF); -#endif } struct gl_viewport_inputs { @@ -140,8 +128,8 @@ _mesa_Viewport(GLint x, GLint y, GLsizei width, GLsizei height) /** - * Set new viewport parameters and update derived state (the _WindowMap - * matrix). Usually called from _mesa_Viewport(). + * Set new viewport parameters and update derived state. + * Usually called from _mesa_Viewport(). * * \param ctx GL context. * \param idx Index of the viewport to be updated. @@ -246,8 +234,6 @@ static void set_depth_range_no_notify(struct gl_context *ctx, unsigned idx, GLclampd nearval, GLclampd farval) { - double scale[3], translate[3]; - if (ctx->ViewportArray[idx].Near == nearval && ctx->ViewportArray[idx].Far == farval) return; @@ -255,16 +241,6 @@ set_depth_range_no_notify(struct gl_context *ctx, unsigned idx, ctx->ViewportArray[idx].Near = CLAMP(nearval, 0.0, 1.0); ctx->ViewportArray[idx].Far = CLAMP(farval, 0.0, 1.0); ctx->NewState |= _NEW_VIEWPORT; - -#if 1 - /* XXX remove this someday. Currently the DRI drivers rely on - * the WindowMap matrix being up to date in the driver's Viewport - * and DepthRange functions. - */ - _mesa_get_viewport_xform(ctx, idx, scale, translate); - _math_matrix_viewport(&ctx->ViewportArray[idx]._WindowMap, - scale, translate, ctx->DrawBuffer->_DepthMaxF); -#endif } void @@ -388,7 +364,6 @@ _mesa_DepthRangeIndexed(GLuint index, GLclampd nearval, GLclampd farval) */ void _mesa_init_viewport(struct gl_context *ctx) { - GLfloat depthMax = 65535.0F; /* sorf of arbitrary */ unsigned i; ctx->Transform.ClipOrigin = GL_LOWER_LEFT; @@ -398,8 +373,6 @@ void _mesa_init_viewport(struct gl_context *ctx) * so just initialize all of them. */ for (i = 0; i < MAX_VIEWPORTS; i++) { - double scale[3], translate[3]; - /* Viewport group */ ctx->ViewportArray[i].X = 0; ctx->ViewportArray[i].Y = 0; @@ -407,27 +380,10 @@ void _mesa_init_viewport(struct gl_context *ctx) ctx->ViewportArray[i].Height = 0; ctx->ViewportArray[i].Near = 0.0; ctx->ViewportArray[i].Far = 1.0; - _math_matrix_ctr(&ctx->ViewportArray[i]._WindowMap); - - _mesa_get_viewport_xform(ctx, i, scale, translate); - _math_matrix_viewport(&ctx->ViewportArray[i]._WindowMap, - scale, translate, depthMax); } } -/** - * Free the context viewport attribute group data. - * \param ctx the GL context. - */ -void _mesa_free_viewport_data(struct gl_context *ctx) -{ - unsigned i; - - for (i = 0; i < MAX_VIEWPORTS; i++) - _math_matrix_dtr(&ctx->ViewportArray[i]._WindowMap); -} - extern void GLAPIENTRY _mesa_ClipControl(GLenum origin, GLenum depth) { diff --git a/mesalib/src/mesa/main/viewport.h b/mesalib/src/mesa/main/viewport.h index 426e194bd..899dc2d0b 100644 --- a/mesalib/src/mesa/main/viewport.h +++ b/mesalib/src/mesa/main/viewport.h @@ -68,9 +68,6 @@ extern void _mesa_init_viewport(struct gl_context *ctx); -extern void -_mesa_free_viewport_data(struct gl_context *ctx); - extern void GLAPIENTRY _mesa_ClipControl(GLenum origin, GLenum depth); diff --git a/mesalib/src/mesa/program/ir_to_mesa.cpp b/mesalib/src/mesa/program/ir_to_mesa.cpp index 39790ec8e..3dcb53702 100644 --- a/mesalib/src/mesa/program/ir_to_mesa.cpp +++ b/mesalib/src/mesa/program/ir_to_mesa.cpp @@ -303,9 +303,6 @@ public: void emit_scalar(ir_instruction *ir, enum prog_opcode op, dst_reg dst, src_reg src0, src_reg src1); - void emit_scs(ir_instruction *ir, enum prog_opcode op, - dst_reg dst, const src_reg &src); - bool try_emit_mad(ir_expression *ir, int mul_operand); bool try_emit_mad_for_and_not(ir_expression *ir, @@ -479,101 +476,6 @@ ir_to_mesa_visitor::emit_scalar(ir_instruction *ir, enum prog_opcode op, emit_scalar(ir, op, dst, src0, undef); } -/** - * Emit an OPCODE_SCS instruction - * - * The \c SCS opcode functions a bit differently than the other Mesa (or - * ARB_fragment_program) opcodes. Instead of splatting its result across all - * four components of the destination, it writes one value to the \c x - * component and another value to the \c y component. - * - * \param ir IR instruction being processed - * \param op Either \c OPCODE_SIN or \c OPCODE_COS depending on which - * value is desired. - * \param dst Destination register - * \param src Source register - */ -void -ir_to_mesa_visitor::emit_scs(ir_instruction *ir, enum prog_opcode op, - dst_reg dst, - const src_reg &src) -{ - /* Vertex programs cannot use the SCS opcode. - */ - if (this->prog->Target == GL_VERTEX_PROGRAM_ARB) { - emit_scalar(ir, op, dst, src); - return; - } - - const unsigned component = (op == OPCODE_SIN) ? 0 : 1; - const unsigned scs_mask = (1U << component); - int done_mask = ~dst.writemask; - src_reg tmp; - - assert(op == OPCODE_SIN || op == OPCODE_COS); - - /* If there are compnents in the destination that differ from the component - * that will be written by the SCS instrution, we'll need a temporary. - */ - if (scs_mask != unsigned(dst.writemask)) { - tmp = get_temp(glsl_type::vec4_type); - } - - for (unsigned i = 0; i < 4; i++) { - unsigned this_mask = (1U << i); - src_reg src0 = src; - - if ((done_mask & this_mask) != 0) - continue; - - /* The source swizzle specified which component of the source generates - * sine / cosine for the current component in the destination. The SCS - * instruction requires that this value be swizzle to the X component. - * Replace the current swizzle with a swizzle that puts the source in - * the X component. - */ - unsigned src0_swiz = GET_SWZ(src.swizzle, i); - - src0.swizzle = MAKE_SWIZZLE4(src0_swiz, src0_swiz, - src0_swiz, src0_swiz); - for (unsigned j = i + 1; j < 4; j++) { - /* If there is another enabled component in the destination that is - * derived from the same inputs, generate its value on this pass as - * well. - */ - if (!(done_mask & (1 << j)) && - GET_SWZ(src0.swizzle, j) == src0_swiz) { - this_mask |= (1 << j); - } - } - - if (this_mask != scs_mask) { - ir_to_mesa_instruction *inst; - dst_reg tmp_dst = dst_reg(tmp); - - /* Emit the SCS instruction. - */ - inst = emit(ir, OPCODE_SCS, tmp_dst, src0); - inst->dst.writemask = scs_mask; - - /* Move the result of the SCS instruction to the desired location in - * the destination. - */ - tmp.swizzle = MAKE_SWIZZLE4(component, component, - component, component); - inst = emit(ir, OPCODE_SCS, dst, tmp); - inst->dst.writemask = this_mask; - } else { - /* Emit the SCS instruction to write directly to the destination. - */ - ir_to_mesa_instruction *inst = emit(ir, OPCODE_SCS, dst, src0); - inst->dst.writemask = scs_mask; - } - - done_mask |= this_mask; - } -} - src_reg ir_to_mesa_visitor::src_reg_for_float(float val) { @@ -1122,12 +1024,6 @@ ir_to_mesa_visitor::visit(ir_expression *ir) case ir_unop_cos: emit_scalar(ir, OPCODE_COS, result_dst, op[0]); break; - case ir_unop_sin_reduced: - emit_scs(ir, OPCODE_SIN, result_dst, op[0]); - break; - case ir_unop_cos_reduced: - emit_scs(ir, OPCODE_COS, result_dst, op[0]); - break; case ir_unop_dFdx: emit(ir, OPCODE_DDX, result_dst, op[0]); diff --git a/mesalib/src/mesa/program/prog_execute.c b/mesalib/src/mesa/program/prog_execute.c index dc4919ae8..16e8e340d 100644 --- a/mesalib/src/mesa/program/prog_execute.c +++ b/mesalib/src/mesa/program/prog_execute.c @@ -37,7 +37,6 @@ #include "c99_math.h" #include "main/glheader.h" -#include "main/colormac.h" #include "main/macros.h" #include "prog_execute.h" #include "prog_instruction.h" diff --git a/mesalib/src/mesa/program/prog_instruction.h b/mesalib/src/mesa/program/prog_instruction.h index ab3acbc02..96da198f8 100644 --- a/mesalib/src/mesa/program/prog_instruction.h +++ b/mesalib/src/mesa/program/prog_instruction.h @@ -59,6 +59,8 @@ #define SWIZZLE_NOOP MAKE_SWIZZLE4(0,1,2,3) #define GET_SWZ(swz, idx) (((swz) >> ((idx)*3)) & 0x7) #define GET_BIT(msk, idx) (((msk) >> (idx)) & 0x1) +/** Determine if swz contains SWIZZLE_ZERO/ONE/NIL for any components. */ +#define HAS_EXTENDED_SWIZZLE(swz) (swz & 0x924) #define SWIZZLE_XYZW MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W) #define SWIZZLE_XXXX MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X) diff --git a/mesalib/src/mesa/program/prog_parameter.c b/mesalib/src/mesa/program/prog_parameter.c index cdfe25145..53e9813e6 100644 --- a/mesalib/src/mesa/program/prog_parameter.c +++ b/mesalib/src/mesa/program/prog_parameter.c @@ -190,40 +190,6 @@ _mesa_add_parameter(struct gl_program_parameter_list *paramList, /** - * Add a new named constant to the parameter list. - * This will be used when the program contains something like this: - * PARAM myVals = { 0, 1, 2, 3 }; - * - * \param paramList the parameter list - * \param name the name for the constant - * \param values four float values - * \return index/position of the new parameter in the parameter list - */ -GLint -_mesa_add_named_constant(struct gl_program_parameter_list *paramList, - const char *name, const gl_constant_value values[4], - GLuint size) -{ - /* first check if this is a duplicate constant */ - GLint pos; - for (pos = 0; pos < (GLint)paramList->NumParameters; pos++) { - const gl_constant_value *pvals = paramList->ParameterValues[pos]; - if (pvals[0].u == values[0].u && - pvals[1].u == values[1].u && - pvals[2].u == values[2].u && - pvals[3].u == values[3].u && - strcmp(paramList->Parameters[pos].Name, name) == 0) { - /* Same name and value is already in the param list - reuse it */ - return pos; - } - } - /* not found, add new parameter */ - return _mesa_add_parameter(paramList, PROGRAM_CONSTANT, name, - size, GL_NONE, values, NULL); -} - - -/** * Add a new unnamed constant to the parameter list. This will be used * when a fragment/vertex program contains something like this: * MOV r, { 0, 1, 2, 3 }; @@ -303,28 +269,6 @@ _mesa_add_unnamed_constant(struct gl_program_parameter_list *paramList, swizzleOut); } -#if 0 /* not used yet */ -/** - * Returns the number of 4-component registers needed to store a piece - * of GL state. For matrices this may be as many as 4 registers, - * everything else needs - * just 1 register. - */ -static GLuint -sizeof_state_reference(const GLint *stateTokens) -{ - if (stateTokens[0] == STATE_MATRIX) { - GLuint rows = stateTokens[4] - stateTokens[3] + 1; - assert(rows >= 1); - assert(rows <= 4); - return rows; - } - else { - return 1; - } -} -#endif - /** * Add a new state reference to the parameter list. @@ -365,22 +309,6 @@ _mesa_add_state_reference(struct gl_program_parameter_list *paramList, /** - * Lookup a parameter value by name in the given parameter list. - * \return pointer to the float[4] values. - */ -gl_constant_value * -_mesa_lookup_parameter_value(const struct gl_program_parameter_list *paramList, - GLsizei nameLen, const char *name) -{ - GLint i = _mesa_lookup_parameter_index(paramList, nameLen, name); - if (i < 0) - return NULL; - else - return paramList->ParameterValues[i]; -} - - -/** * Given a program parameter name, find its position in the list of parameters. * \param paramList the parameter list to search * \param nameLen length of name (in chars). diff --git a/mesalib/src/mesa/program/prog_parameter.h b/mesalib/src/mesa/program/prog_parameter.h index 6b3b3c262..74a5fd918 100644 --- a/mesalib/src/mesa/program/prog_parameter.h +++ b/mesalib/src/mesa/program/prog_parameter.h @@ -120,11 +120,6 @@ _mesa_add_parameter(struct gl_program_parameter_list *paramList, const gl_state_index state[STATE_LENGTH]); extern GLint -_mesa_add_named_constant(struct gl_program_parameter_list *paramList, - const char *name, const gl_constant_value values[4], - GLuint size); - -extern GLint _mesa_add_typed_unnamed_constant(struct gl_program_parameter_list *paramList, const gl_constant_value values[4], GLuint size, GLenum datatype, GLuint *swizzleOut); @@ -138,10 +133,6 @@ extern GLint _mesa_add_state_reference(struct gl_program_parameter_list *paramList, const gl_state_index stateTokens[STATE_LENGTH]); -extern gl_constant_value * -_mesa_lookup_parameter_value(const struct gl_program_parameter_list *paramList, - GLsizei nameLen, const char *name); - extern GLint _mesa_lookup_parameter_index(const struct gl_program_parameter_list *paramList, GLsizei nameLen, const char *name); diff --git a/mesalib/src/mesa/program/prog_to_nir.c b/mesalib/src/mesa/program/prog_to_nir.c new file mode 100644 index 000000000..c738f5073 --- /dev/null +++ b/mesalib/src/mesa/program/prog_to_nir.c @@ -0,0 +1,1096 @@ +/* + * Copyright © 2015 Intel Corporation + * Copyright © 2014-2015 Broadcom + * Copyright (C) 2014 Rob Clark <robclark@freedesktop.org> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "nir/nir.h" +#include "nir/nir_builder.h" +#include "glsl/list.h" +#include "main/imports.h" +#include "util/ralloc.h" + +#include "prog_to_nir.h" +#include "prog_instruction.h" +#include "prog_parameter.h" +#include "prog_print.h" + +/** + * \file prog_to_nir.c + * + * A translator from Mesa IR (prog_instruction.h) to NIR. This is primarily + * intended to support ARB_vertex_program, ARB_fragment_program, and fixed-function + * vertex processing. Full GLSL support should use glsl_to_nir instead. + */ + +struct ptn_compile { + const struct gl_program *prog; + nir_builder build; + bool error; + + nir_variable *input_vars[VARYING_SLOT_MAX]; + nir_variable *output_vars[VARYING_SLOT_MAX]; + nir_register **output_regs; + nir_register **temp_regs; + + nir_register *addr_reg; +}; + +#define SWIZ(X, Y, Z, W) \ + (unsigned[4]){ SWIZZLE_##X, SWIZZLE_##Y, SWIZZLE_##Z, SWIZZLE_##W } +#define ptn_swizzle(b, src, x, y, z, w) nir_swizzle(b, src, SWIZ(x, y, z, w), 4, true) +#define ptn_channel(b, src, ch) nir_swizzle(b, src, SWIZ(ch, ch, ch, ch), 1, true) + +static nir_ssa_def * +ptn_src_for_dest(struct ptn_compile *c, nir_alu_dest *dest) +{ + nir_builder *b = &c->build; + + nir_alu_src src; + memset(&src, 0, sizeof(src)); + + if (dest->dest.is_ssa) + src.src = nir_src_for_ssa(&dest->dest.ssa); + else { + assert(!dest->dest.reg.indirect); + src.src = nir_src_for_reg(dest->dest.reg.reg); + src.src.reg.base_offset = dest->dest.reg.base_offset; + } + + for (int i = 0; i < 4; i++) + src.swizzle[i] = i; + + return nir_fmov_alu(b, src, 4); +} + +static nir_alu_dest +ptn_get_dest(struct ptn_compile *c, const struct prog_dst_register *prog_dst) +{ + nir_alu_dest dest; + + memset(&dest, 0, sizeof(dest)); + + switch (prog_dst->File) { + case PROGRAM_TEMPORARY: + dest.dest.reg.reg = c->temp_regs[prog_dst->Index]; + break; + case PROGRAM_OUTPUT: + dest.dest.reg.reg = c->output_regs[prog_dst->Index]; + break; + case PROGRAM_ADDRESS: + assert(prog_dst->Index == 0); + dest.dest.reg.reg = c->addr_reg; + break; + case PROGRAM_UNDEFINED: + break; + } + + dest.write_mask = prog_dst->WriteMask; + dest.saturate = false; + + assert(!prog_dst->RelAddr); + + return dest; +} + +/** + * Multiply the contents of the ADDR register by 4 to convert from the number + * of vec4s to the number of floating point components. + */ +static nir_ssa_def * +ptn_addr_reg_value(struct ptn_compile *c) +{ + nir_builder *b = &c->build; + nir_alu_src src; + memset(&src, 0, sizeof(src)); + src.src = nir_src_for_reg(c->addr_reg); + + return nir_imul(b, nir_fmov_alu(b, src, 1), nir_imm_int(b, 4)); +} + +static nir_ssa_def * +ptn_get_src(struct ptn_compile *c, const struct prog_src_register *prog_src) +{ + nir_builder *b = &c->build; + nir_alu_src src; + + memset(&src, 0, sizeof(src)); + + switch (prog_src->File) { + case PROGRAM_UNDEFINED: + return nir_imm_float(b, 0.0); + case PROGRAM_TEMPORARY: + assert(!prog_src->RelAddr && prog_src->Index >= 0); + src.src.reg.reg = c->temp_regs[prog_src->Index]; + break; + case PROGRAM_INPUT: { + /* ARB_vertex_program doesn't allow relative addressing on vertex + * attributes; ARB_fragment_program has no relative addressing at all. + */ + assert(!prog_src->RelAddr); + + assert(prog_src->Index >= 0 && prog_src->Index < VARYING_SLOT_MAX); + + nir_intrinsic_instr *load = + nir_intrinsic_instr_create(b->shader, nir_intrinsic_load_var); + load->num_components = 4; + load->variables[0] = nir_deref_var_create(load, c->input_vars[prog_src->Index]); + + nir_ssa_dest_init(&load->instr, &load->dest, 4, NULL); + nir_instr_insert_after_cf_list(b->cf_node_list, &load->instr); + + src.src = nir_src_for_ssa(&load->dest.ssa); + break; + } + case PROGRAM_STATE_VAR: + case PROGRAM_CONSTANT: { + /* We actually want to look at the type in the Parameters list for this, + * because it lets us upload constant builtin uniforms as actual + * constants. + */ + struct gl_program_parameter_list *plist = c->prog->Parameters; + gl_register_file file = prog_src->RelAddr ? prog_src->File : + plist->Parameters[prog_src->Index].Type; + + switch (file) { + case PROGRAM_CONSTANT: + if ((c->prog->IndirectRegisterFiles & (1 << PROGRAM_CONSTANT)) == 0) { + float *v = (float *) plist->ParameterValues[prog_src->Index]; + src.src = nir_src_for_ssa(nir_imm_vec4(b, v[0], v[1], v[2], v[3])); + break; + } + /* FALLTHROUGH */ + case PROGRAM_STATE_VAR: { + nir_intrinsic_op load_op = + prog_src->RelAddr ? nir_intrinsic_load_uniform_indirect : + nir_intrinsic_load_uniform; + nir_intrinsic_instr *load = nir_intrinsic_instr_create(b->shader, load_op); + nir_ssa_dest_init(&load->instr, &load->dest, 4, NULL); + load->num_components = 4; + + /* Multiply src->Index by 4 to scale from # of vec4s to components. */ + load->const_index[0] = 4 * prog_src->Index; + load->const_index[1] = 1; + + if (prog_src->RelAddr) { + nir_ssa_def *reladdr = ptn_addr_reg_value(c); + if (prog_src->Index < 0) { + /* This is a negative offset which should be added to the address + * register's value. + */ + reladdr = nir_iadd(b, reladdr, nir_imm_int(b, load->const_index[0])); + load->const_index[0] = 0; + } + load->src[0] = nir_src_for_ssa(reladdr); + } + + nir_instr_insert_after_cf_list(b->cf_node_list, &load->instr); + + src.src = nir_src_for_ssa(&load->dest.ssa); + break; + } + default: + fprintf(stderr, "bad uniform src register file: %s (%d)\n", + _mesa_register_file_name(file), file); + abort(); + } + break; + } + default: + fprintf(stderr, "unknown src register file: %s (%d)\n", + _mesa_register_file_name(prog_src->File), prog_src->File); + abort(); + } + + nir_ssa_def *def; + if (!HAS_EXTENDED_SWIZZLE(prog_src->Swizzle)) { + for (int i = 0; i < 4; i++) + src.swizzle[i] = GET_SWZ(prog_src->Swizzle, i); + + def = nir_fmov_alu(b, src, 4); + } else { + nir_ssa_def *chans[4]; + for (int i = 0; i < 4; i++) { + int swizzle = GET_SWZ(prog_src->Swizzle, i); + if (swizzle == SWIZZLE_ZERO) { + chans[i] = nir_imm_float(b, 0.0); + } else if (swizzle == SWIZZLE_ONE) { + chans[i] = nir_imm_float(b, 1.0); + } else { + assert(swizzle != SWIZZLE_NIL); + nir_alu_instr *mov = nir_alu_instr_create(b->shader, nir_op_fmov); + nir_ssa_dest_init(&mov->instr, &mov->dest.dest, 1, NULL); + mov->dest.write_mask = 0x1; + mov->src[0] = src; + mov->src[0].swizzle[0] = swizzle; + nir_instr_insert_after_cf_list(b->cf_node_list, &mov->instr); + + chans[i] = &mov->dest.dest.ssa; + } + } + def = nir_vec4(b, chans[0], chans[1], chans[2], chans[3]); + } + + if (prog_src->Abs) + def = nir_fabs(b, def); + + if (prog_src->Negate) + def = nir_fneg(b, def); + + return def; +} + +static void +ptn_alu(nir_builder *b, nir_op op, nir_alu_dest dest, nir_ssa_def **src) +{ + unsigned num_srcs = nir_op_infos[op].num_inputs; + nir_alu_instr *instr = nir_alu_instr_create(b->shader, op); + unsigned i; + + for (i = 0; i < num_srcs; i++) + instr->src[i].src = nir_src_for_ssa(src[i]); + + instr->dest = dest; + nir_instr_insert_after_cf_list(b->cf_node_list, &instr->instr); +} + +static void +ptn_move_dest_masked(nir_builder *b, nir_alu_dest dest, + nir_ssa_def *def, unsigned write_mask) +{ + if (!(dest.write_mask & write_mask)) + return; + + nir_alu_instr *mov = nir_alu_instr_create(b->shader, nir_op_fmov); + if (!mov) + return; + + mov->dest = dest; + mov->dest.write_mask &= write_mask; + mov->src[0].src = nir_src_for_ssa(def); + for (unsigned i = def->num_components; i < 4; i++) + mov->src[0].swizzle[i] = def->num_components - 1; + nir_instr_insert_after_cf_list(b->cf_node_list, &mov->instr); +} + +static void +ptn_move_dest(nir_builder *b, nir_alu_dest dest, nir_ssa_def *def) +{ + ptn_move_dest_masked(b, dest, def, WRITEMASK_XYZW); +} + +static void +ptn_arl(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src) +{ + ptn_move_dest(b, dest, nir_f2i(b, nir_ffloor(b, src[0]))); +} + +/* EXP - Approximate Exponential Base 2 + * dst.x = 2^{\lfloor src.x\rfloor} + * dst.y = src.x - \lfloor src.x\rfloor + * dst.z = 2^{src.x} + * dst.w = 1.0 + */ +static void +ptn_exp(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src) +{ + nir_ssa_def *srcx = ptn_channel(b, src[0], X); + + ptn_move_dest_masked(b, dest, nir_fexp2(b, nir_ffloor(b, srcx)), WRITEMASK_X); + ptn_move_dest_masked(b, dest, nir_fsub(b, srcx, nir_ffloor(b, srcx)), WRITEMASK_Y); + ptn_move_dest_masked(b, dest, nir_fexp2(b, srcx), WRITEMASK_Z); + ptn_move_dest_masked(b, dest, nir_imm_float(b, 1.0), WRITEMASK_W); +} + +/* LOG - Approximate Logarithm Base 2 + * dst.x = \lfloor\log_2{|src.x|}\rfloor + * dst.y = |src.x| * 2^{-\lfloor\log_2{|src.x|}\rfloor}} + * dst.z = \log_2{|src.x|} + * dst.w = 1.0 + */ +static void +ptn_log(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src) +{ + nir_ssa_def *abs_srcx = nir_fabs(b, ptn_channel(b, src[0], X)); + nir_ssa_def *log2 = nir_flog2(b, abs_srcx); + nir_ssa_def *floor_log2 = nir_ffloor(b, log2); + + ptn_move_dest_masked(b, dest, floor_log2, WRITEMASK_X); + ptn_move_dest_masked(b, dest, + nir_fmul(b, abs_srcx, + nir_fexp2(b, nir_fneg(b, floor_log2))), + WRITEMASK_Y); + ptn_move_dest_masked(b, dest, log2, WRITEMASK_Z); + ptn_move_dest_masked(b, dest, nir_imm_float(b, 1.0), WRITEMASK_W); +} + +/* DST - Distance Vector + * dst.x = 1.0 + * dst.y = src0.y \times src1.y + * dst.z = src0.z + * dst.w = src1.w + */ +static void +ptn_dst(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src) +{ + ptn_move_dest_masked(b, dest, nir_imm_float(b, 1.0), WRITEMASK_X); + ptn_move_dest_masked(b, dest, nir_fmul(b, src[0], src[1]), WRITEMASK_Y); + ptn_move_dest_masked(b, dest, nir_fmov(b, src[0]), WRITEMASK_Z); + ptn_move_dest_masked(b, dest, nir_fmov(b, src[1]), WRITEMASK_W); +} + +/* LIT - Light Coefficients + * dst.x = 1.0 + * dst.y = max(src.x, 0.0) + * dst.z = (src.x > 0.0) ? max(src.y, 0.0)^{clamp(src.w, -128.0, 128.0))} : 0 + * dst.w = 1.0 + */ +static void +ptn_lit(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src) +{ + ptn_move_dest_masked(b, dest, nir_imm_float(b, 1.0), WRITEMASK_XW); + + ptn_move_dest_masked(b, dest, nir_fmax(b, ptn_channel(b, src[0], X), + nir_imm_float(b, 0.0)), WRITEMASK_Y); + + if (dest.write_mask & WRITEMASK_Z) { + nir_ssa_def *src0_y = ptn_channel(b, src[0], Y); + nir_ssa_def *wclamp = nir_fmax(b, nir_fmin(b, ptn_channel(b, src[0], W), + nir_imm_float(b, 128.0)), + nir_imm_float(b, -128.0)); + nir_ssa_def *pow = nir_fpow(b, nir_fmax(b, src0_y, nir_imm_float(b, 0.0)), + wclamp); + + nir_ssa_def *z; + if (b->shader->options->native_integers) { + z = nir_bcsel(b, + nir_fge(b, nir_imm_float(b, 0.0), ptn_channel(b, src[0], X)), + nir_imm_float(b, 0.0), + pow); + } else { + z = nir_fcsel(b, + nir_sge(b, nir_imm_float(b, 0.0), ptn_channel(b, src[0], X)), + nir_imm_float(b, 0.0), + pow); + } + + ptn_move_dest_masked(b, dest, z, WRITEMASK_Z); + } +} + +/* SCS - Sine Cosine + * dst.x = \cos{src.x} + * dst.y = \sin{src.x} + * dst.z = 0.0 + * dst.w = 1.0 + */ +static void +ptn_scs(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src) +{ + ptn_move_dest_masked(b, dest, nir_fcos(b, ptn_channel(b, src[0], X)), + WRITEMASK_X); + ptn_move_dest_masked(b, dest, nir_fsin(b, ptn_channel(b, src[0], X)), + WRITEMASK_Y); + ptn_move_dest_masked(b, dest, nir_imm_float(b, 0.0), WRITEMASK_Z); + ptn_move_dest_masked(b, dest, nir_imm_float(b, 1.0), WRITEMASK_W); +} + +/** + * Emit SLT. For platforms with integers, prefer b2f(flt(...)). + */ +static void +ptn_slt(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src) +{ + if (b->shader->options->native_integers) { + ptn_move_dest(b, dest, nir_b2f(b, nir_flt(b, src[0], src[1]))); + } else { + ptn_move_dest(b, dest, nir_slt(b, src[0], src[1])); + } +} + +/** + * Emit SGE. For platforms with integers, prefer b2f(fge(...)). + */ +static void +ptn_sge(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src) +{ + if (b->shader->options->native_integers) { + ptn_move_dest(b, dest, nir_b2f(b, nir_fge(b, src[0], src[1]))); + } else { + ptn_move_dest(b, dest, nir_sge(b, src[0], src[1])); + } +} + +static void +ptn_sle(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src) +{ + nir_ssa_def *commuted[] = { src[1], src[0] }; + ptn_sge(b, dest, commuted); +} + +static void +ptn_sgt(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src) +{ + nir_ssa_def *commuted[] = { src[1], src[0] }; + ptn_slt(b, dest, commuted); +} + +/** + * Emit SEQ. For platforms with integers, prefer b2f(feq(...)). + */ +static void +ptn_seq(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src) +{ + if (b->shader->options->native_integers) { + ptn_move_dest(b, dest, nir_b2f(b, nir_feq(b, src[0], src[1]))); + } else { + ptn_move_dest(b, dest, nir_seq(b, src[0], src[1])); + } +} + +/** + * Emit SNE. For platforms with integers, prefer b2f(fne(...)). + */ +static void +ptn_sne(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src) +{ + if (b->shader->options->native_integers) { + ptn_move_dest(b, dest, nir_b2f(b, nir_fne(b, src[0], src[1]))); + } else { + ptn_move_dest(b, dest, nir_sne(b, src[0], src[1])); + } +} + +static void +ptn_xpd(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src) +{ + ptn_move_dest_masked(b, dest, + nir_fsub(b, + nir_fmul(b, + ptn_swizzle(b, src[0], Y, Z, X, X), + ptn_swizzle(b, src[1], Z, X, Y, X)), + nir_fmul(b, + ptn_swizzle(b, src[1], Y, Z, X, X), + ptn_swizzle(b, src[0], Z, X, Y, X))), + WRITEMASK_XYZ); + ptn_move_dest_masked(b, dest, nir_imm_float(b, 1.0), WRITEMASK_W); +} + +static void +ptn_dp2(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src) +{ + ptn_move_dest(b, dest, nir_fdot2(b, src[0], src[1])); +} + +static void +ptn_dp3(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src) +{ + ptn_move_dest(b, dest, nir_fdot3(b, src[0], src[1])); +} + +static void +ptn_dp4(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src) +{ + ptn_move_dest(b, dest, nir_fdot4(b, src[0], src[1])); +} + +static void +ptn_dph(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src) +{ + nir_ssa_def *dp3 = nir_fdot3(b, src[0], src[1]); + ptn_move_dest(b, dest, nir_fadd(b, dp3, ptn_channel(b, src[1], W))); +} + +static void +ptn_cmp(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src) +{ + if (b->shader->options->native_integers) { + ptn_move_dest(b, dest, nir_bcsel(b, + nir_flt(b, src[0], nir_imm_float(b, 0.0)), + src[1], src[2])); + } else { + ptn_move_dest(b, dest, nir_fcsel(b, + nir_slt(b, src[0], nir_imm_float(b, 0.0)), + src[1], src[2])); + } +} + +static void +ptn_lrp(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src) +{ + ptn_move_dest(b, dest, nir_flrp(b, src[2], src[1], src[0])); +} + +static void +ptn_kil(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src) +{ + nir_ssa_def *cmp = b->shader->options->native_integers ? + nir_bany4(b, nir_flt(b, src[0], nir_imm_float(b, 0.0))) : + nir_fany4(b, nir_slt(b, src[0], nir_imm_float(b, 0.0))); + + nir_intrinsic_instr *discard = + nir_intrinsic_instr_create(b->shader, nir_intrinsic_discard_if); + discard->src[0] = nir_src_for_ssa(cmp); + nir_instr_insert_after_cf_list(b->cf_node_list, &discard->instr); +} + +static void +ptn_tex(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src, + struct prog_instruction *prog_inst) +{ + nir_tex_instr *instr; + nir_texop op; + unsigned num_srcs; + + switch (prog_inst->Opcode) { + case OPCODE_TEX: + op = nir_texop_tex; + num_srcs = 1; + break; + case OPCODE_TXB: + op = nir_texop_txb; + num_srcs = 2; + break; + case OPCODE_TXD: + op = nir_texop_txd; + num_srcs = 3; + break; + case OPCODE_TXL: + op = nir_texop_txl; + num_srcs = 2; + break; + case OPCODE_TXP: + op = nir_texop_tex; + num_srcs = 2; + break; + case OPCODE_TXP_NV: + assert(!"not handled"); + op = nir_texop_tex; + num_srcs = 2; + break; + default: + fprintf(stderr, "unknown tex op %d\n", prog_inst->Opcode); + abort(); + } + + if (prog_inst->TexShadow) + num_srcs++; + + instr = nir_tex_instr_create(b->shader, num_srcs); + instr->op = op; + instr->dest_type = nir_type_float; + instr->is_shadow = prog_inst->TexShadow; + instr->sampler_index = prog_inst->TexSrcUnit; + + switch (prog_inst->TexSrcTarget) { + case TEXTURE_1D_INDEX: + instr->sampler_dim = GLSL_SAMPLER_DIM_1D; + break; + case TEXTURE_2D_INDEX: + instr->sampler_dim = GLSL_SAMPLER_DIM_2D; + break; + case TEXTURE_3D_INDEX: + instr->sampler_dim = GLSL_SAMPLER_DIM_3D; + break; + case TEXTURE_CUBE_INDEX: + instr->sampler_dim = GLSL_SAMPLER_DIM_CUBE; + break; + case TEXTURE_RECT_INDEX: + instr->sampler_dim = GLSL_SAMPLER_DIM_RECT; + break; + default: + fprintf(stderr, "Unknown texture target %d\n", prog_inst->TexSrcTarget); + abort(); + } + + switch (instr->sampler_dim) { + case GLSL_SAMPLER_DIM_1D: + case GLSL_SAMPLER_DIM_BUF: + instr->coord_components = 1; + break; + case GLSL_SAMPLER_DIM_2D: + case GLSL_SAMPLER_DIM_RECT: + case GLSL_SAMPLER_DIM_EXTERNAL: + case GLSL_SAMPLER_DIM_MS: + instr->coord_components = 2; + break; + case GLSL_SAMPLER_DIM_3D: + case GLSL_SAMPLER_DIM_CUBE: + instr->coord_components = 3; + break; + } + + unsigned src_number = 0; + + instr->src[src_number].src = + nir_src_for_ssa(ptn_swizzle(b, src[0], X, Y, Z, W)); + instr->src[src_number].src_type = nir_tex_src_coord; + src_number++; + + if (prog_inst->Opcode == OPCODE_TXP) { + instr->src[src_number].src = nir_src_for_ssa(ptn_channel(b, src[0], W)); + instr->src[src_number].src_type = nir_tex_src_projector; + src_number++; + } + + if (prog_inst->Opcode == OPCODE_TXB) { + instr->src[src_number].src = nir_src_for_ssa(ptn_channel(b, src[0], W)); + instr->src[src_number].src_type = nir_tex_src_bias; + src_number++; + } + + if (prog_inst->Opcode == OPCODE_TXL) { + instr->src[src_number].src = nir_src_for_ssa(ptn_channel(b, src[0], W)); + instr->src[src_number].src_type = nir_tex_src_lod; + src_number++; + } + + if (instr->is_shadow) { + if (instr->coord_components < 3) + instr->src[src_number].src = nir_src_for_ssa(ptn_channel(b, src[0], Z)); + else + instr->src[src_number].src = nir_src_for_ssa(ptn_channel(b, src[0], W)); + + instr->src[src_number].src_type = nir_tex_src_comparitor; + src_number++; + } + + assert(src_number == num_srcs); + + nir_ssa_dest_init(&instr->instr, &instr->dest, 4, NULL); + nir_instr_insert_after_cf_list(b->cf_node_list, &instr->instr); + + /* Resolve the writemask on the texture op. */ + ptn_move_dest(b, dest, &instr->dest.ssa); +} + +static const nir_op op_trans[MAX_OPCODE] = { + [OPCODE_NOP] = 0, + [OPCODE_ABS] = nir_op_fabs, + [OPCODE_ADD] = nir_op_fadd, + [OPCODE_ARL] = 0, + [OPCODE_CMP] = 0, + [OPCODE_COS] = nir_op_fcos, + [OPCODE_DDX] = nir_op_fddx, + [OPCODE_DDY] = nir_op_fddy, + [OPCODE_DP2] = 0, + [OPCODE_DP3] = 0, + [OPCODE_DP4] = 0, + [OPCODE_DPH] = 0, + [OPCODE_DST] = 0, + [OPCODE_END] = 0, + [OPCODE_EX2] = nir_op_fexp2, + [OPCODE_EXP] = nir_op_fexp, + [OPCODE_FLR] = nir_op_ffloor, + [OPCODE_FRC] = nir_op_ffract, + [OPCODE_LG2] = nir_op_flog2, + [OPCODE_LIT] = 0, + [OPCODE_LOG] = 0, + [OPCODE_LRP] = 0, + [OPCODE_MAD] = nir_op_ffma, + [OPCODE_MAX] = nir_op_fmax, + [OPCODE_MIN] = nir_op_fmin, + [OPCODE_MOV] = nir_op_fmov, + [OPCODE_MUL] = nir_op_fmul, + [OPCODE_POW] = nir_op_fpow, + [OPCODE_RCP] = nir_op_frcp, + + [OPCODE_RSQ] = nir_op_frsq, + [OPCODE_SCS] = 0, + [OPCODE_SEQ] = 0, + [OPCODE_SGE] = 0, + [OPCODE_SGT] = 0, + [OPCODE_SIN] = nir_op_fsin, + [OPCODE_SLE] = 0, + [OPCODE_SLT] = 0, + [OPCODE_SNE] = 0, + [OPCODE_SSG] = nir_op_fsign, + [OPCODE_SUB] = nir_op_fsub, + [OPCODE_SWZ] = 0, + [OPCODE_TEX] = 0, + [OPCODE_TRUNC] = nir_op_ftrunc, + [OPCODE_TXB] = 0, + [OPCODE_TXD] = 0, + [OPCODE_TXL] = 0, + [OPCODE_TXP] = 0, + [OPCODE_TXP_NV] = 0, + [OPCODE_XPD] = 0, +}; + +static void +ptn_emit_instruction(struct ptn_compile *c, struct prog_instruction *prog_inst) +{ + nir_builder *b = &c->build; + unsigned i; + const unsigned op = prog_inst->Opcode; + + if (op == OPCODE_END) + return; + + nir_ssa_def *src[3]; + for (i = 0; i < 3; i++) { + src[i] = ptn_get_src(c, &prog_inst->SrcReg[i]); + } + nir_alu_dest dest = ptn_get_dest(c, &prog_inst->DstReg); + if (c->error) + return; + + switch (op) { + case OPCODE_RSQ: + ptn_move_dest(b, dest, nir_frsq(b, ptn_channel(b, src[0], X))); + break; + + case OPCODE_RCP: + ptn_move_dest(b, dest, nir_frcp(b, ptn_channel(b, src[0], X))); + break; + + case OPCODE_EX2: + ptn_move_dest(b, dest, nir_fexp2(b, ptn_channel(b, src[0], X))); + break; + + case OPCODE_LG2: + ptn_move_dest(b, dest, nir_flog2(b, ptn_channel(b, src[0], X))); + break; + + case OPCODE_POW: + ptn_move_dest(b, dest, nir_fpow(b, + ptn_channel(b, src[0], X), + ptn_channel(b, src[1], X))); + break; + + case OPCODE_COS: + ptn_move_dest(b, dest, nir_fcos(b, ptn_channel(b, src[0], X))); + break; + + case OPCODE_SIN: + ptn_move_dest(b, dest, nir_fsin(b, ptn_channel(b, src[0], X))); + break; + + case OPCODE_ARL: + ptn_arl(b, dest, src); + break; + + case OPCODE_EXP: + ptn_exp(b, dest, src); + break; + + case OPCODE_LOG: + ptn_log(b, dest, src); + break; + + case OPCODE_LRP: + ptn_lrp(b, dest, src); + break; + + case OPCODE_DST: + ptn_dst(b, dest, src); + break; + + case OPCODE_LIT: + ptn_lit(b, dest, src); + break; + + case OPCODE_XPD: + ptn_xpd(b, dest, src); + break; + + case OPCODE_DP2: + ptn_dp2(b, dest, src); + break; + + case OPCODE_DP3: + ptn_dp3(b, dest, src); + break; + + case OPCODE_DP4: + ptn_dp4(b, dest, src); + break; + + case OPCODE_DPH: + ptn_dph(b, dest, src); + break; + + case OPCODE_KIL: + ptn_kil(b, dest, src); + break; + + case OPCODE_CMP: + ptn_cmp(b, dest, src); + break; + + case OPCODE_SCS: + ptn_scs(b, dest, src); + break; + + case OPCODE_SLT: + ptn_slt(b, dest, src); + break; + + case OPCODE_SGT: + ptn_sgt(b, dest, src); + break; + + case OPCODE_SLE: + ptn_sle(b, dest, src); + break; + + case OPCODE_SGE: + ptn_sge(b, dest, src); + break; + + case OPCODE_SEQ: + ptn_seq(b, dest, src); + break; + + case OPCODE_SNE: + ptn_sne(b, dest, src); + break; + + case OPCODE_TEX: + case OPCODE_TXB: + case OPCODE_TXD: + case OPCODE_TXL: + case OPCODE_TXP: + case OPCODE_TXP_NV: + ptn_tex(b, dest, src, prog_inst); + break; + + case OPCODE_SWZ: + /* Extended swizzles were already handled in ptn_get_src(). */ + ptn_alu(b, nir_op_fmov, dest, src); + break; + + case OPCODE_NOP: + break; + + default: + if (op_trans[op] != 0 || op == OPCODE_MOV) { + ptn_alu(b, op_trans[op], dest, src); + } else { + fprintf(stderr, "unknown opcode: %s\n", _mesa_opcode_string(op)); + abort(); + } + break; + } + + if (prog_inst->SaturateMode) { + assert(prog_inst->SaturateMode == SATURATE_ZERO_ONE); + assert(!dest.dest.is_ssa); + ptn_move_dest(b, dest, nir_fsat(b, ptn_src_for_dest(c, &dest))); + } +} + +/** + * Puts a NIR intrinsic to store of each PROGRAM_OUTPUT value to the output + * variables at the end of the shader. + * + * We don't generate these incrementally as the PROGRAM_OUTPUT values are + * written, because there's no output load intrinsic, which means we couldn't + * handle writemasks. + */ +static void +ptn_add_output_stores(struct ptn_compile *c) +{ + nir_builder *b = &c->build; + + foreach_list_typed(nir_variable, var, node, &b->shader->outputs) { + nir_intrinsic_instr *store = + nir_intrinsic_instr_create(b->shader, nir_intrinsic_store_var); + store->num_components = 4; + store->variables[0] = + nir_deref_var_create(store, c->output_vars[var->data.location]); + store->src[0].reg.reg = c->output_regs[var->data.location]; + nir_instr_insert_after_cf_list(c->build.cf_node_list, &store->instr); + } +} + +static void +setup_registers_and_variables(struct ptn_compile *c) +{ + nir_builder *b = &c->build; + struct nir_shader *shader = b->shader; + + /* Create input variables. */ + const int num_inputs = _mesa_flsll(c->prog->InputsRead); + for (int i = 0; i < num_inputs; i++) { + if (!(c->prog->InputsRead & BITFIELD64_BIT(i))) + continue; + nir_variable *var = rzalloc(shader, nir_variable); + var->type = glsl_vec4_type(); + var->data.read_only = true; + var->data.mode = nir_var_shader_in; + var->name = ralloc_asprintf(var, "in_%d", i); + var->data.location = i; + var->data.index = 0; + + if (c->prog->Target == GL_FRAGMENT_PROGRAM_ARB) { + struct gl_fragment_program *fp = + (struct gl_fragment_program *) c->prog; + + var->data.interpolation = fp->InterpQualifier[i]; + + if (i == VARYING_SLOT_POS) { + var->data.origin_upper_left = fp->OriginUpperLeft; + var->data.pixel_center_integer = fp->PixelCenterInteger; + } else if (i == VARYING_SLOT_FOGC) { + /* fogcoord is defined as <f, 0.0, 0.0, 1.0>. Make the actual + * input variable a float, and create a local containing the + * full vec4 value. + */ + var->type = glsl_float_type(); + + nir_intrinsic_instr *load_x = + nir_intrinsic_instr_create(shader, nir_intrinsic_load_var); + load_x->num_components = 1; + load_x->variables[0] = nir_deref_var_create(load_x, var); + nir_ssa_dest_init(&load_x->instr, &load_x->dest, 1, NULL); + nir_instr_insert_after_cf_list(b->cf_node_list, &load_x->instr); + + nir_ssa_def *f001 = nir_vec4(b, &load_x->dest.ssa, nir_imm_float(b, 0.0), + nir_imm_float(b, 0.0), nir_imm_float(b, 1.0)); + + nir_variable *fullvar = rzalloc(shader, nir_variable); + fullvar->type = glsl_vec4_type(); + fullvar->data.mode = nir_var_local; + fullvar->name = "fogcoord_tmp"; + exec_list_push_tail(&b->impl->locals, &fullvar->node); + + nir_intrinsic_instr *store = + nir_intrinsic_instr_create(shader, nir_intrinsic_store_var); + store->num_components = 4; + store->variables[0] = nir_deref_var_create(store, fullvar); + store->src[0] = nir_src_for_ssa(f001); + nir_instr_insert_after_cf_list(b->cf_node_list, &store->instr); + + /* Insert the real input into the list so the driver has real + * inputs, but set c->input_vars[i] to the temporary so we use + * the splatted value. + */ + exec_list_push_tail(&shader->inputs, &var->node); + c->input_vars[i] = fullvar; + continue; + } + } + + exec_list_push_tail(&shader->inputs, &var->node); + c->input_vars[i] = var; + } + + /* Create output registers and variables. */ + int max_outputs = _mesa_fls(c->prog->OutputsWritten); + c->output_regs = rzalloc_array(c, nir_register *, max_outputs); + + for (int i = 0; i < max_outputs; i++) { + if (!(c->prog->OutputsWritten & BITFIELD64_BIT(i))) + continue; + + /* Since we can't load from outputs in the IR, we make temporaries + * for the outputs and emit stores to the real outputs at the end of + * the shader. + */ + nir_register *reg = nir_local_reg_create(b->impl); + reg->num_components = 4; + + nir_variable *var = rzalloc(shader, nir_variable); + var->type = glsl_vec4_type(); + var->data.mode = nir_var_shader_out; + var->name = ralloc_asprintf(var, "out_%d", i); + + var->data.location = i; + var->data.index = 0; + + c->output_regs[i] = reg; + + exec_list_push_tail(&shader->outputs, &var->node); + c->output_vars[i] = var; + } + + /* Create temporary registers. */ + c->temp_regs = rzalloc_array(c, nir_register *, c->prog->NumTemporaries); + + nir_register *reg; + for (int i = 0; i < c->prog->NumTemporaries; i++) { + reg = nir_local_reg_create(b->impl); + if (!reg) { + c->error = true; + return; + } + reg->num_components = 4; + c->temp_regs[i] = reg; + } + + /* Create the address register (for ARB_vertex_program). */ + reg = nir_local_reg_create(b->impl); + if (!reg) { + c->error = true; + return; + } + reg->num_components = 1; + c->addr_reg = reg; + + /* Set the number of uniforms */ + shader->num_uniforms = 4 * c->prog->Parameters->NumParameters; +} + +struct nir_shader * +prog_to_nir(const struct gl_program *prog, const nir_shader_compiler_options *options) +{ + struct ptn_compile *c; + struct nir_shader *s; + + c = rzalloc(NULL, struct ptn_compile); + if (!c) + return NULL; + s = nir_shader_create(NULL, options); + if (!s) + goto fail; + c->prog = prog; + + nir_function *func = nir_function_create(s, "main"); + nir_function_overload *overload = nir_function_overload_create(func); + nir_function_impl *impl = nir_function_impl_create(overload); + + c->build.shader = s; + c->build.impl = impl; + c->build.cf_node_list = &impl->body; + + setup_registers_and_variables(c); + if (unlikely(c->error)) + goto fail; + + for (unsigned int i = 0; i < prog->NumInstructions; i++) { + ptn_emit_instruction(c, &prog->Instructions[i]); + + if (unlikely(c->error)) + break; + } + + ptn_add_output_stores(c); + +fail: + if (c->error) { + ralloc_free(s); + s = NULL; + } + ralloc_free(c); + return s; +} diff --git a/mesalib/src/mesa/program/prog_to_nir.h b/mesalib/src/mesa/program/prog_to_nir.h new file mode 100644 index 000000000..34e4cd104 --- /dev/null +++ b/mesalib/src/mesa/program/prog_to_nir.h @@ -0,0 +1,37 @@ +/* + * Copyright © 2015 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. + */ + +#pragma once +#ifndef PROG_TO_NIR_H +#define PROG_TO_NIR_H +#ifdef __cplusplus +extern "C" { +#endif + +struct nir_shader *prog_to_nir(const struct gl_program *prog, + const nir_shader_compiler_options *options); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/mesalib/src/mesa/program/program.c b/mesalib/src/mesa/program/program.c index 3c214d5e3..4f28e2a3b 100644 --- a/mesalib/src/mesa/program/program.c +++ b/mesalib/src/mesa/program/program.c @@ -37,6 +37,7 @@ #include "prog_cache.h" #include "prog_parameter.h" #include "prog_instruction.h" +#include "util/ralloc.h" /** @@ -380,6 +381,10 @@ _mesa_delete_program(struct gl_context *ctx, struct gl_program *prog) _mesa_free_parameter_list(prog->Parameters); } + if (prog->nir) { + ralloc_free(prog->nir); + } + free(prog); } diff --git a/mesalib/src/mesa/state_tracker/st_atom.c b/mesalib/src/mesa/state_tracker/st_atom.c index f0fe11ffa..428f2d9d7 100644 --- a/mesalib/src/mesa/state_tracker/st_atom.c +++ b/mesalib/src/mesa/state_tracker/st_atom.c @@ -183,7 +183,7 @@ void st_validate_state( struct st_context *st ) if (state->st == 0) return; - /*printf("%s %x/%x\n", __FUNCTION__, state->mesa, state->st);*/ + /*printf("%s %x/%x\n", __func__, state->mesa, state->st);*/ #ifdef DEBUG if (1) { diff --git a/mesalib/src/mesa/state_tracker/st_atom_array.c b/mesalib/src/mesa/state_tracker/st_atom_array.c index 9b52f9779..d4fb8b862 100644 --- a/mesalib/src/mesa/state_tracker/st_atom_array.c +++ b/mesalib/src/mesa/state_tracker/st_atom_array.c @@ -598,7 +598,7 @@ static void update_array(struct st_context *st) const struct st_tracked_state st_update_array = { "st_update_array", /* name */ { /* dirty */ - 0, /* mesa */ + _NEW_CURRENT_ATTRIB, /* mesa */ ST_NEW_VERTEX_ARRAYS | ST_NEW_VERTEX_PROGRAM, /* st */ }, update_array /* update */ diff --git a/mesalib/src/mesa/state_tracker/st_atom_constbuf.c b/mesalib/src/mesa/state_tracker/st_atom_constbuf.c index 7984bf742..a54e0d9db 100644 --- a/mesalib/src/mesa/state_tracker/st_atom_constbuf.c +++ b/mesalib/src/mesa/state_tracker/st_atom_constbuf.c @@ -92,7 +92,7 @@ void st_upload_constants( struct st_context *st, if (ST_DEBUG & DEBUG_CONSTANTS) { debug_printf("%s(shader=%d, numParams=%d, stateFlags=0x%x)\n", - __FUNCTION__, shader_type, params->NumParameters, + __func__, shader_type, params->NumParameters, params->StateFlags); _mesa_print_parameter_list(params); } diff --git a/mesalib/src/mesa/state_tracker/st_atom_shader.c b/mesalib/src/mesa/state_tracker/st_atom_shader.c index 73768ed12..629f54f25 100644 --- a/mesalib/src/mesa/state_tracker/st_atom_shader.c +++ b/mesalib/src/mesa/state_tracker/st_atom_shader.c @@ -40,9 +40,8 @@ #include "program/program.h" #include "pipe/p_context.h" - +#include "pipe/p_shader_tokens.h" #include "util/u_simple_shaders.h" - #include "cso_cache/cso_context.h" #include "st_context.h" diff --git a/mesalib/src/mesa/state_tracker/st_cb_clear.c b/mesalib/src/mesa/state_tracker/st_cb_clear.c index dd81a6273..f10e9063a 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_clear.c +++ b/mesalib/src/mesa/state_tracker/st_cb_clear.c @@ -247,7 +247,7 @@ clear_with_quad(struct gl_context *ctx, unsigned clear_buffers) util_framebuffer_get_num_layers(&st->state.framebuffer); /* - printf("%s %s%s%s %f,%f %f,%f\n", __FUNCTION__, + printf("%s %s%s%s %f,%f %f,%f\n", __func__, color ? "color, " : "", depth ? "depth, " : "", stencil ? "stencil" : "", diff --git a/mesalib/src/mesa/state_tracker/st_cb_program.c b/mesalib/src/mesa/state_tracker/st_cb_program.c index aa301d830..c382d7d2c 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_program.c +++ b/mesalib/src/mesa/state_tracker/st_cb_program.c @@ -41,6 +41,7 @@ #include "draw/draw_context.h" #include "st_context.h" +#include "st_debug.h" #include "st_program.h" #include "st_mesa_to_tgsi.h" #include "st_cb_program.h" @@ -214,6 +215,9 @@ st_program_string_notify( struct gl_context *ctx, st->dirty.st |= ST_NEW_VERTEX_PROGRAM; } + if (ST_DEBUG & DEBUG_PRECOMPILE) + st_precompile_shader_variant(st, prog); + /* XXX check if program is legal, within limits */ return GL_TRUE; } diff --git a/mesalib/src/mesa/state_tracker/st_cb_texture.c b/mesalib/src/mesa/state_tracker/st_cb_texture.c index 5c520b44f..bdf236e82 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_texture.c +++ b/mesalib/src/mesa/state_tracker/st_cb_texture.c @@ -123,7 +123,7 @@ gl_target_to_pipe(GLenum target) static struct gl_texture_image * st_NewTextureImage(struct gl_context * ctx) { - DBG("%s\n", __FUNCTION__); + DBG("%s\n", __func__); (void) ctx; return (struct gl_texture_image *) ST_CALLOC_STRUCT(st_texture_image); } @@ -144,7 +144,7 @@ st_NewTextureObject(struct gl_context * ctx, GLuint name, GLenum target) { struct st_texture_object *obj = ST_CALLOC_STRUCT(st_texture_object); - DBG("%s\n", __FUNCTION__); + DBG("%s\n", __func__); _mesa_initialize_texture_object(ctx, &obj->base, name, target); return &obj->base; @@ -172,7 +172,7 @@ st_FreeTextureImageBuffer(struct gl_context *ctx, { struct st_texture_image *stImage = st_texture_image(texImage); - DBG("%s\n", __FUNCTION__); + DBG("%s\n", __func__); if (stImage->pt) { pipe_resource_reference(&stImage->pt, NULL); @@ -405,7 +405,7 @@ guess_and_alloc_texture(struct st_context *st, GLuint ptWidth, ptHeight, ptDepth, ptLayers; enum pipe_format fmt; - DBG("%s\n", __FUNCTION__); + DBG("%s\n", __func__); assert(!stObj->pt); @@ -473,7 +473,7 @@ guess_and_alloc_texture(struct st_context *st, stObj->lastLevel = lastLevel; - DBG("%s returning %d\n", __FUNCTION__, (stObj->pt != NULL)); + DBG("%s returning %d\n", __func__, (stObj->pt != NULL)); return stObj->pt != NULL; } @@ -496,7 +496,7 @@ st_AllocTextureImageBuffer(struct gl_context *ctx, GLuint height = texImage->Height; GLuint depth = texImage->Depth; - DBG("%s\n", __FUNCTION__); + DBG("%s\n", __func__); assert(!stImage->pt); /* xxx this might be wrong */ @@ -738,6 +738,11 @@ st_TexSubImage(struct gl_context *ctx, GLuint dims, if (gl_target == GL_TEXTURE_CUBE_MAP) { gl_target = GL_TEXTURE_2D; } + /* TexSubImage can specify subsets of cube map array faces + * so we need to upload via 2D array instead */ + if (gl_target == GL_TEXTURE_CUBE_MAP_ARRAY) { + gl_target = GL_TEXTURE_2D_ARRAY; + } /* Initialize the source texture description. */ memset(&src_templ, 0, sizeof(src_templ)); @@ -1148,7 +1153,7 @@ st_GetTexImage(struct gl_context * ctx, } if (ST_DEBUG & DEBUG_FALLBACK) - debug_printf("%s: fallback format translation\n", __FUNCTION__); + debug_printf("%s: fallback format translation\n", __func__); dstMesaFormat = _mesa_format_from_format_and_type(format, type); dstStride = _mesa_image_row_stride(&ctx->Pack, width, format, type); @@ -1234,7 +1239,7 @@ fallback_copy_texsubimage(struct gl_context *ctx, struct pipe_transfer *transfer; if (ST_DEBUG & DEBUG_FALLBACK) - debug_printf("%s: fallback processing\n", __FUNCTION__); + debug_printf("%s: fallback processing\n", __func__); if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) { srcY = strb->Base.Height - srcY - height; @@ -1389,7 +1394,7 @@ st_CopyTexSubImage(struct gl_context *ctx, GLuint dims, texImage->TexFormat != MESA_FORMAT_ETC1_RGB8); if (!strb || !strb->surface || !stImage->pt) { - debug_printf("%s: null strb or stImage\n", __FUNCTION__); + debug_printf("%s: null strb or stImage\n", __func__); return; } diff --git a/mesalib/src/mesa/state_tracker/st_debug.c b/mesalib/src/mesa/state_tracker/st_debug.c index de3e3a9cd..50891c112 100644 --- a/mesalib/src/mesa/state_tracker/st_debug.c +++ b/mesalib/src/mesa/state_tracker/st_debug.c @@ -56,6 +56,7 @@ static const struct debug_named_value st_debug_flags[] = { { "draw", DEBUG_DRAW, NULL }, { "buffer", DEBUG_BUFFER, NULL }, { "wf", DEBUG_WIREFRAME, NULL }, + { "precompile", DEBUG_PRECOMPILE, NULL }, DEBUG_NAMED_VALUE_END }; diff --git a/mesalib/src/mesa/state_tracker/st_debug.h b/mesalib/src/mesa/state_tracker/st_debug.h index cc8197836..288eccf9f 100644 --- a/mesalib/src/mesa/state_tracker/st_debug.h +++ b/mesalib/src/mesa/state_tracker/st_debug.h @@ -47,6 +47,7 @@ st_print_current(void); #define DEBUG_DRAW 0x100 #define DEBUG_BUFFER 0x200 #define DEBUG_WIREFRAME 0x400 +#define DEBUG_PRECOMPILE 0x800 #ifdef DEBUG extern int ST_DEBUG; 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 efee4b258..93671ba9c 100644 --- a/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp +++ b/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp @@ -30,40 +30,25 @@ * Translate GLSL IR to TGSI. */ -#include <stdio.h> -#include "main/compiler.h" -#include "ir.h" -#include "ir_visitor.h" -#include "ir_expression_flattening.h" -#include "glsl_types.h" +#include "st_glsl_to_tgsi.h" + #include "glsl_parser_extras.h" -#include "../glsl/program.h" #include "ir_optimization.h" -#include "ast.h" -#include "main/mtypes.h" +#include "main/errors.h" #include "main/shaderobj.h" #include "main/uniforms.h" #include "main/shaderapi.h" -#include "program/hash_table.h" #include "program/prog_instruction.h" -#include "program/prog_optimize.h" -#include "program/prog_print.h" -#include "program/program.h" -#include "program/prog_parameter.h" #include "program/sampler.h" -#include "pipe/p_compiler.h" #include "pipe/p_context.h" #include "pipe/p_screen.h" -#include "pipe/p_shader_tokens.h" -#include "pipe/p_state.h" -#include "util/u_math.h" #include "tgsi/tgsi_ureg.h" #include "tgsi/tgsi_info.h" -#include "st_context.h" +#include "util/u_math.h" +#include "util/u_memory.h" #include "st_program.h" -#include "st_glsl_to_tgsi.h" #include "st_mesa_to_tgsi.h" @@ -328,6 +313,7 @@ public: int num_address_regs; int samplers_used; bool indirect_addr_consts; + int wpos_transform_const; int glsl_version; bool native_integers; @@ -441,9 +427,6 @@ public: void emit_arl(ir_instruction *ir, st_dst_reg dst, st_src_reg src0); - void emit_scs(ir_instruction *ir, unsigned op, - st_dst_reg dst, const st_src_reg &src); - bool try_emit_mad(ir_expression *ir, int mul_operand); bool try_emit_mad_for_and_not(ir_expression *ir, @@ -966,101 +949,6 @@ glsl_to_tgsi_visitor::emit_arl(ir_instruction *ir, emit(NULL, op, dst, src0); } -/** - * Emit an TGSI_OPCODE_SCS instruction - * - * The \c SCS opcode functions a bit differently than the other TGSI opcodes. - * Instead of splatting its result across all four components of the - * destination, it writes one value to the \c x component and another value to - * the \c y component. - * - * \param ir IR instruction being processed - * \param op Either \c TGSI_OPCODE_SIN or \c TGSI_OPCODE_COS depending - * on which value is desired. - * \param dst Destination register - * \param src Source register - */ -void -glsl_to_tgsi_visitor::emit_scs(ir_instruction *ir, unsigned op, - st_dst_reg dst, - const st_src_reg &src) -{ - /* Vertex programs cannot use the SCS opcode. - */ - if (this->prog->Target == GL_VERTEX_PROGRAM_ARB) { - emit_scalar(ir, op, dst, src); - return; - } - - const unsigned component = (op == TGSI_OPCODE_SIN) ? 0 : 1; - const unsigned scs_mask = (1U << component); - int done_mask = ~dst.writemask; - st_src_reg tmp; - - assert(op == TGSI_OPCODE_SIN || op == TGSI_OPCODE_COS); - - /* If there are compnents in the destination that differ from the component - * that will be written by the SCS instrution, we'll need a temporary. - */ - if (scs_mask != unsigned(dst.writemask)) { - tmp = get_temp(glsl_type::vec4_type); - } - - for (unsigned i = 0; i < 4; i++) { - unsigned this_mask = (1U << i); - st_src_reg src0 = src; - - if ((done_mask & this_mask) != 0) - continue; - - /* The source swizzle specified which component of the source generates - * sine / cosine for the current component in the destination. The SCS - * instruction requires that this value be swizzle to the X component. - * Replace the current swizzle with a swizzle that puts the source in - * the X component. - */ - unsigned src0_swiz = GET_SWZ(src.swizzle, i); - - src0.swizzle = MAKE_SWIZZLE4(src0_swiz, src0_swiz, - src0_swiz, src0_swiz); - for (unsigned j = i + 1; j < 4; j++) { - /* If there is another enabled component in the destination that is - * derived from the same inputs, generate its value on this pass as - * well. - */ - if (!(done_mask & (1 << j)) && - GET_SWZ(src0.swizzle, j) == src0_swiz) { - this_mask |= (1 << j); - } - } - - if (this_mask != scs_mask) { - glsl_to_tgsi_instruction *inst; - st_dst_reg tmp_dst = st_dst_reg(tmp); - - /* Emit the SCS instruction. - */ - inst = emit(ir, TGSI_OPCODE_SCS, tmp_dst, src0); - inst->dst[0].writemask = scs_mask; - - /* Move the result of the SCS instruction to the desired location in - * the destination. - */ - tmp.swizzle = MAKE_SWIZZLE4(component, component, - component, component); - inst = emit(ir, TGSI_OPCODE_SCS, dst, tmp); - inst->dst[0].writemask = this_mask; - } else { - /* Emit the SCS instruction to write directly to the destination. - */ - glsl_to_tgsi_instruction *inst = emit(ir, TGSI_OPCODE_SCS, dst, src0); - inst->dst[0].writemask = scs_mask; - } - - done_mask |= this_mask; - } -} - int glsl_to_tgsi_visitor::add_constant(gl_register_file file, gl_constant_value values[8], int size, int datatype, @@ -1611,12 +1499,6 @@ glsl_to_tgsi_visitor::visit(ir_expression *ir) case ir_unop_cos: emit_scalar(ir, TGSI_OPCODE_COS, result_dst, op[0]); break; - case ir_unop_sin_reduced: - emit_scs(ir, TGSI_OPCODE_SIN, result_dst, op[0]); - break; - case ir_unop_cos_reduced: - emit_scs(ir, TGSI_OPCODE_COS, result_dst, op[0]); - break; case ir_unop_saturate: { glsl_to_tgsi_instruction *inst; inst = emit(ir, TGSI_OPCODE_MOV, result_dst, op[0]); @@ -3134,7 +3016,7 @@ glsl_to_tgsi_visitor::visit(ir_texture *ir) break; case ir_query_levels: opcode = TGSI_OPCODE_TXQ; - lod_info = st_src_reg(PROGRAM_IMMEDIATE, 0, GLSL_TYPE_INT); + lod_info = undef_src; levels_src = get_temp(ir->type); break; case ir_txf: @@ -3456,6 +3338,7 @@ glsl_to_tgsi_visitor::glsl_to_tgsi_visitor() num_address_regs = 0; samplers_used = 0; indirect_addr_consts = false; + wpos_transform_const = -1; glsl_version = 0; native_integers = false; mem_ctx = ralloc_context(NULL); @@ -3465,6 +3348,7 @@ glsl_to_tgsi_visitor::glsl_to_tgsi_visitor() shader = NULL; options = NULL; have_sqrt = false; + have_fma = false; } glsl_to_tgsi_visitor::~glsl_to_tgsi_visitor() @@ -3937,6 +3821,7 @@ glsl_to_tgsi_visitor::copy_propagate(void) inst->dst[0].index == inst->src[0].index) && !inst->dst[0].reladdr && !inst->saturate && + inst->src[0].file != PROGRAM_ARRAY && !inst->src[0].reladdr && !inst->src[0].reladdr2 && !inst->src[0].negate) { @@ -4464,7 +4349,9 @@ struct st_translate { struct ureg_dst arrays[MAX_ARRAYS]; struct ureg_src *constants; + int num_constants; struct ureg_src *immediates; + int num_immediates; struct ureg_dst outputs[PIPE_MAX_SHADER_OUTPUTS]; struct ureg_src inputs[PIPE_MAX_SHADER_INPUTS]; struct ureg_dst address[3]; @@ -4666,7 +4553,7 @@ src_register(struct st_translate *t, const st_src_reg *reg) { switch(reg->file) { case PROGRAM_UNDEFINED: - return ureg_src_undef(); + return ureg_imm4f(t->ureg, 0, 0, 0, 0); case PROGRAM_TEMPORARY: case PROGRAM_ARRAY: @@ -4674,17 +4561,18 @@ src_register(struct st_translate *t, const st_src_reg *reg) case PROGRAM_UNIFORM: assert(reg->index >= 0); - return t->constants[reg->index]; + return reg->index < t->num_constants ? + t->constants[reg->index] : ureg_imm4f(t->ureg, 0, 0, 0, 0); case PROGRAM_STATE_VAR: case PROGRAM_CONSTANT: /* ie, immediate */ if (reg->has_index2) return ureg_src_register(TGSI_FILE_CONSTANT, reg->index); - else if (reg->index < 0) - return ureg_DECL_constant(t->ureg, 0); else - return t->constants[reg->index]; + return reg->index >= 0 && reg->index < t->num_constants ? + t->constants[reg->index] : ureg_imm4f(t->ureg, 0, 0, 0, 0); case PROGRAM_IMMEDIATE: + assert(reg->index >= 0 && reg->index < t->num_immediates); return t->immediates[reg->index]; case PROGRAM_INPUT: @@ -4805,6 +4693,7 @@ translate_tex_offset(struct st_translate *t, switch (in_offset->file) { case PROGRAM_IMMEDIATE: + assert(in_offset->index >= 0 && in_offset->index < t->num_immediates); imm_src = t->immediates[in_offset->index]; offset.File = imm_src.File; @@ -4867,10 +4756,8 @@ compile_tgsi_instruction(struct st_translate *t, inst->saturate, clamp_dst_color_output); - for (i = 0; i < num_src; i++) { - assert(inst->src[i].file != PROGRAM_UNDEFINED); + for (i = 0; i < num_src; i++) src[i] = translate_src(t, &inst->src[i]); - } switch(inst->op) { case TGSI_OPCODE_BGNLOOP: @@ -4939,28 +4826,19 @@ compile_tgsi_instruction(struct st_translate *t, */ static void emit_wpos_adjustment( struct st_translate *t, - const struct gl_program *program, + int wpos_transform_const, boolean invert, GLfloat adjX, GLfloat adjY[2]) { struct ureg_program *ureg = t->ureg; + assert(wpos_transform_const >= 0); + /* Fragment program uses fragment position input. * Need to replace instances of INPUT[WPOS] with temp T - * where T = INPUT[WPOS] by y is inverted. + * where T = INPUT[WPOS] is inverted by Y. */ - static const gl_state_index wposTransformState[STATE_LENGTH] - = { STATE_INTERNAL, STATE_FB_WPOS_Y_TRANSFORM, - (gl_state_index)0, (gl_state_index)0, (gl_state_index)0 }; - - /* XXX: note we are modifying the incoming shader here! Need to - * do this before emitting the constant decls below, or this - * will be missed: - */ - unsigned wposTransConst = _mesa_add_state_reference(program->Parameters, - wposTransformState); - - struct ureg_src wpostrans = ureg_DECL_constant( ureg, wposTransConst ); + struct ureg_src wpostrans = ureg_DECL_constant(ureg, wpos_transform_const); struct ureg_dst wpos_temp = ureg_DECL_temporary( ureg ); struct ureg_src wpos_input = t->inputs[t->inputMapping[VARYING_SLOT_POS]]; @@ -5024,7 +4902,8 @@ static void emit_wpos(struct st_context *st, struct st_translate *t, const struct gl_program *program, - struct ureg_program *ureg) + struct ureg_program *ureg, + int wpos_transform_const) { const struct gl_fragment_program *fp = (const struct gl_fragment_program *) program; @@ -5121,7 +5000,7 @@ emit_wpos(struct st_context *st, /* we invert after adjustment so that we avoid the MOV to temporary, * and reuse the adjustment ADD instead */ - emit_wpos_adjustment(t, program, invert, adjX, adjY); + emit_wpos_adjustment(t, wpos_transform_const, invert, adjX, adjY); } /** @@ -5238,15 +5117,6 @@ st_translate_program( t->outputMapping = outputMapping; t->ureg = ureg; - if (program->shader_program) { - for (i = 0; i < program->shader_program->NumUserUniformStorage; i++) { - struct gl_uniform_storage *const storage = - &program->shader_program->UniformStorage[i]; - - _mesa_uniform_detach_all_driver_storage(storage); - } - } - /* * Declare input attributes. */ @@ -5260,10 +5130,9 @@ st_translate_program( } if (proginfo->InputsRead & VARYING_BIT_POS) { - /* Must do this after setting up t->inputs, and before - * emitting constant references, below: - */ - emit_wpos(st_context(ctx), t, proginfo, ureg); + /* Must do this after setting up t->inputs. */ + emit_wpos(st_context(ctx), t, proginfo, ureg, + program->wpos_transform_const); } if (proginfo->InputsRead & VARYING_BIT_FACE) @@ -5400,6 +5269,7 @@ st_translate_program( ret = PIPE_ERROR_OUT_OF_MEMORY; goto out; } + t->num_constants = proginfo->Parameters->NumParameters; for (i = 0; i < proginfo->Parameters->NumParameters; i++) { switch (proginfo->Parameters->Parameters[i].Type) { @@ -5451,6 +5321,8 @@ st_translate_program( ret = PIPE_ERROR_OUT_OF_MEMORY; goto out; } + t->num_immediates = program->num_immediates; + i = 0; foreach_in_list(immediate_storage, imm, &program->immediates) { assert(i < program->num_immediates); @@ -5479,33 +5351,21 @@ st_translate_program( t->insn[t->labels[i].branch_target]); } - if (program->shader_program) { - /* This has to be done last. Any operation the can cause - * prog->ParameterValues to get reallocated (e.g., anything that adds a - * program constant) has to happen before creating this linkage. - */ - for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) { - if (program->shader_program->_LinkedShaders[i] == NULL) - continue; - - _mesa_associate_uniform_storage(ctx, program->shader_program, - program->shader_program->_LinkedShaders[i]->Program->Parameters); - } - } - out: if (t) { free(t->temps); free(t->insn); free(t->labels); free(t->constants); + t->num_constants = 0; free(t->immediates); + t->num_immediates = 0; if (t->error) { - debug_printf("%s: translate error flag set\n", __FUNCTION__); + debug_printf("%s: translate error flag set\n", __func__); } - free(t); + FREE(t); } return ret; @@ -5634,14 +5494,12 @@ get_mesa_program(struct gl_context *ctx, v->emit(NULL, TGSI_OPCODE_END); if (ctx->_Shader->Flags & GLSL_DUMP) { - printf("\n"); - printf("GLSL IR for linked %s program %d:\n", + _mesa_log("\n"); + _mesa_log("GLSL IR for linked %s program %d:\n", _mesa_shader_stage_to_string(shader->Stage), shader_program->Name); - _mesa_print_ir(stdout, shader->ir, NULL); - printf("\n"); - printf("\n"); - fflush(stdout); + _mesa_print_ir(_mesa_get_log_file(), shader->ir, NULL); + _mesa_log("\n\n"); } prog->Instructions = NULL; @@ -5650,6 +5508,17 @@ get_mesa_program(struct gl_context *ctx, do_set_program_inouts(shader->ir, prog, shader->Stage); count_resources(v, prog); + /* This must be done before the uniform storage is associated. */ + if (shader->Type == GL_FRAGMENT_SHADER && + prog->InputsRead & VARYING_BIT_POS){ + static const gl_state_index wposTransformState[STATE_LENGTH] = { + STATE_INTERNAL, STATE_FB_WPOS_Y_TRANSFORM + }; + + v->wpos_transform_const = _mesa_add_state_reference(prog->Parameters, + wposTransformState); + } + _mesa_reference_program(ctx, &shader->Program, prog); /* This has to be done last. Any operation the can cause diff --git a/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.h b/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.h index 5ed640747..2cb80bcf9 100644 --- a/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.h +++ b/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.h @@ -22,17 +22,18 @@ * DEALINGS IN THE SOFTWARE. */ +#include "pipe/p_defines.h" +#include "main/mtypes.h" + #ifdef __cplusplus extern "C" { #endif -#include "main/glheader.h" -#include "tgsi/tgsi_ureg.h" - struct gl_context; struct gl_shader; struct gl_shader_program; struct glsl_to_tgsi_visitor; +struct ureg_program; enum pipe_error st_translate_program( struct gl_context *ctx, diff --git a/mesalib/src/mesa/state_tracker/st_mesa_to_tgsi.c b/mesalib/src/mesa/state_tracker/st_mesa_to_tgsi.c index 2f1016110..98d525c86 100644 --- a/mesalib/src/mesa/state_tracker/st_mesa_to_tgsi.c +++ b/mesalib/src/mesa/state_tracker/st_mesa_to_tgsi.c @@ -1249,7 +1249,7 @@ out: free(t->constants); if (t->error) { - debug_printf("%s: translate error flag set\n", __FUNCTION__); + debug_printf("%s: translate error flag set\n", __func__); } return ret; diff --git a/mesalib/src/mesa/state_tracker/st_program.c b/mesalib/src/mesa/state_tracker/st_program.c index 4cfd817ce..d93b3c7bc 100644 --- a/mesalib/src/mesa/state_tracker/st_program.c +++ b/mesalib/src/mesa/state_tracker/st_program.c @@ -185,9 +185,6 @@ st_prepare_vertex_program(struct gl_context *ctx, if (stvp->Base.IsPositionInvariant) _mesa_insert_mvp_code(ctx, &stvp->Base); - if (!stvp->glsl_to_tgsi) - assert(stvp->Base.Base.NumInstructions > 1); - /* * Determine number of inputs, the mappings between VERT_ATTRIB_x * and TGSI generic input indexes, plus input attrib semantic info. @@ -403,7 +400,7 @@ st_translate_vertex_program(struct st_context *st, return vpv; fail: - debug_printf("%s: failed to translate Mesa program:\n", __FUNCTION__); + debug_printf("%s: failed to translate Mesa program:\n", __func__); _mesa_print_program(&stvp->Base.Base); debug_assert(0); @@ -1318,3 +1315,47 @@ st_print_current_vertex_program(void) } } } + + +/** + * Compile one shader variant. + */ +void +st_precompile_shader_variant(struct st_context *st, + struct gl_program *prog) +{ + switch (prog->Target) { + case GL_VERTEX_PROGRAM_ARB: { + struct st_vertex_program *p = (struct st_vertex_program *)prog; + struct st_vp_variant_key key; + + memset(&key, 0, sizeof(key)); + key.st = st; + st_get_vp_variant(st, p, &key); + break; + } + + case GL_GEOMETRY_PROGRAM_NV: { + struct st_geometry_program *p = (struct st_geometry_program *)prog; + struct st_gp_variant_key key; + + memset(&key, 0, sizeof(key)); + key.st = st; + st_get_gp_variant(st, p, &key); + break; + } + + case GL_FRAGMENT_PROGRAM_ARB: { + struct st_fragment_program *p = (struct st_fragment_program *)prog; + struct st_fp_variant_key key; + + memset(&key, 0, sizeof(key)); + key.st = st; + st_get_fp_variant(st, p, &key); + break; + } + + default: + assert(0); + } +} diff --git a/mesalib/src/mesa/state_tracker/st_program.h b/mesalib/src/mesa/state_tracker/st_program.h index 451d7bb6a..b2c86faec 100644 --- a/mesalib/src/mesa/state_tracker/st_program.h +++ b/mesalib/src/mesa/state_tracker/st_program.h @@ -329,6 +329,9 @@ st_destroy_program_variants(struct st_context *st); extern void st_print_current_vertex_program(void); +extern void +st_precompile_shader_variant(struct st_context *st, + struct gl_program *prog); #ifdef __cplusplus } diff --git a/mesalib/src/mesa/state_tracker/st_texture.c b/mesalib/src/mesa/state_tracker/st_texture.c index ca7c83c21..6beb21e33 100644 --- a/mesalib/src/mesa/state_tracker/st_texture.c +++ b/mesalib/src/mesa/state_tracker/st_texture.c @@ -74,7 +74,7 @@ st_texture_create(struct st_context *st, if (target == PIPE_TEXTURE_CUBE) assert(layers == 6); - DBG("%s target %d format %s last_level %d\n", __FUNCTION__, + DBG("%s target %d format %s last_level %d\n", __func__, (int) target, util_format_name(format), last_level); assert(format); @@ -177,7 +177,7 @@ st_gl_texture_dims_to_pipe_dims(GLenum texture, *widthOut = widthIn; *heightOut = heightIn; *depthOut = 1; - *layersOut = depthIn; + *layersOut = util_align_npot(depthIn, 6); break; default: assert(0 && "Unexpected texture in st_gl_texture_dims_to_pipe_dims()"); @@ -250,7 +250,7 @@ st_texture_image_map(struct st_context *st, struct st_texture_image *stImage, GLuint level; void *map; - DBG("%s \n", __FUNCTION__); + DBG("%s \n", __func__); if (!stImage->pt) return NULL; @@ -304,7 +304,7 @@ st_texture_image_unmap(struct st_context *st, slice += stObj->base.MinLayer; transfer = &stImage->transfer[slice + stImage->base.Face].transfer; - DBG("%s\n", __FUNCTION__); + DBG("%s\n", __func__); pipe_transfer_unmap(pipe, *transfer); *transfer = NULL; diff --git a/mesalib/src/mesa/swrast/s_aatriangle.c b/mesalib/src/mesa/swrast/s_aatriangle.c index 1d076cc7d..b51098704 100644 --- a/mesalib/src/mesa/swrast/s_aatriangle.c +++ b/mesalib/src/mesa/swrast/s_aatriangle.c @@ -30,7 +30,6 @@ #include "main/glheader.h" #include "main/context.h" -#include "main/colormac.h" #include "main/macros.h" #include "main/imports.h" #include "main/state.h" diff --git a/mesalib/src/mesa/swrast/s_alpha.c b/mesalib/src/mesa/swrast/s_alpha.c index b1a7ff132..841642fa9 100644 --- a/mesalib/src/mesa/swrast/s_alpha.c +++ b/mesalib/src/mesa/swrast/s_alpha.c @@ -29,7 +29,6 @@ #include "main/glheader.h" #include "main/context.h" -#include "main/colormac.h" #include "main/macros.h" #include "s_alpha.h" diff --git a/mesalib/src/mesa/swrast/s_atifragshader.c b/mesalib/src/mesa/swrast/s_atifragshader.c index 0bf03771f..9e029db25 100644 --- a/mesalib/src/mesa/swrast/s_atifragshader.c +++ b/mesalib/src/mesa/swrast/s_atifragshader.c @@ -20,7 +20,6 @@ */ #include "main/glheader.h" -#include "main/colormac.h" #include "main/macros.h" #include "main/atifragshader.h" #include "main/samplerobj.h" diff --git a/mesalib/src/mesa/swrast/s_context.c b/mesalib/src/mesa/swrast/s_context.c index ecde292e3..af24207e5 100644 --- a/mesalib/src/mesa/swrast/s_context.c +++ b/mesalib/src/mesa/swrast/s_context.c @@ -27,7 +27,6 @@ #include "main/imports.h" #include "main/bufferobj.h" -#include "main/colormac.h" #include "main/mtypes.h" #include "main/samplerobj.h" #include "main/teximage.h" diff --git a/mesalib/src/mesa/swrast/s_copypix.c b/mesalib/src/mesa/swrast/s_copypix.c index 17140ad2d..68c83e44e 100644 --- a/mesalib/src/mesa/swrast/s_copypix.c +++ b/mesalib/src/mesa/swrast/s_copypix.c @@ -25,7 +25,6 @@ #include "main/glheader.h" #include "main/context.h" -#include "main/colormac.h" #include "main/condrender.h" #include "main/macros.h" #include "main/pixeltransfer.h" diff --git a/mesalib/src/mesa/swrast/s_feedback.c b/mesalib/src/mesa/swrast/s_feedback.c index f25b89735..71f48ce92 100644 --- a/mesalib/src/mesa/swrast/s_feedback.c +++ b/mesalib/src/mesa/swrast/s_feedback.c @@ -23,7 +23,6 @@ */ #include "main/glheader.h" -#include "main/colormac.h" #include "main/feedback.h" #include "main/macros.h" diff --git a/mesalib/src/mesa/swrast/s_fog.c b/mesalib/src/mesa/swrast/s_fog.c index e270b7e24..8b0bdf8fa 100644 --- a/mesalib/src/mesa/swrast/s_fog.c +++ b/mesalib/src/mesa/swrast/s_fog.c @@ -25,7 +25,6 @@ #include "c99_math.h" #include "main/glheader.h" -#include "main/colormac.h" #include "main/macros.h" #include "s_context.h" diff --git a/mesalib/src/mesa/swrast/s_fragprog.c b/mesalib/src/mesa/swrast/s_fragprog.c index 12bcda311..175915a5a 100644 --- a/mesalib/src/mesa/swrast/s_fragprog.c +++ b/mesalib/src/mesa/swrast/s_fragprog.c @@ -23,7 +23,7 @@ */ #include "main/glheader.h" -#include "main/colormac.h" +#include "main/macros.h" #include "main/samplerobj.h" #include "main/teximage.h" #include "program/prog_instruction.h" diff --git a/mesalib/src/mesa/swrast/s_lines.c b/mesalib/src/mesa/swrast/s_lines.c index 3e626b9e0..58bd2fc72 100644 --- a/mesalib/src/mesa/swrast/s_lines.c +++ b/mesalib/src/mesa/swrast/s_lines.c @@ -25,7 +25,6 @@ #include "main/glheader.h" #include "main/context.h" -#include "main/colormac.h" #include "main/macros.h" #include "s_aaline.h" #include "s_context.h" diff --git a/mesalib/src/mesa/swrast/s_linetemp.h b/mesalib/src/mesa/swrast/s_linetemp.h index 352c88428..035a1e640 100644 --- a/mesalib/src/mesa/swrast/s_linetemp.h +++ b/mesalib/src/mesa/swrast/s_linetemp.h @@ -106,7 +106,7 @@ NAME( struct gl_context *ctx, const SWvertex *vert0, const SWvertex *vert1 ) } /* - printf("%s():\n", __FUNCTION__); + printf("%s():\n", __func__); printf(" (%f, %f, %f) -> (%f, %f, %f)\n", vert0->attrib[VARYING_SLOT_POS][0], vert0->attrib[VARYING_SLOT_POS][1], @@ -154,7 +154,7 @@ NAME( struct gl_context *ctx, const SWvertex *vert0, const SWvertex *vert1 ) return; /* - printf("%s %d,%d %g %g %g %g %g %g %g %g\n", __FUNCTION__, dx, dy, + printf("%s %d,%d %g %g %g %g %g %g %g %g\n", __func__, dx, dy, vert0->attrib[VARYING_SLOT_COL1][0], vert0->attrib[VARYING_SLOT_COL1][1], vert0->attrib[VARYING_SLOT_COL1][2], diff --git a/mesalib/src/mesa/swrast/s_points.c b/mesalib/src/mesa/swrast/s_points.c index 8180483ba..2212c95fa 100644 --- a/mesalib/src/mesa/swrast/s_points.c +++ b/mesalib/src/mesa/swrast/s_points.c @@ -24,7 +24,6 @@ #include "main/glheader.h" -#include "main/colormac.h" #include "main/macros.h" #include "s_context.h" #include "s_feedback.h" diff --git a/mesalib/src/mesa/swrast/s_span.c b/mesalib/src/mesa/swrast/s_span.c index e304b6b5a..3db10e163 100644 --- a/mesalib/src/mesa/swrast/s_span.c +++ b/mesalib/src/mesa/swrast/s_span.c @@ -33,7 +33,6 @@ #include "c99_math.h" #include "main/glheader.h" -#include "main/colormac.h" #include "main/format_pack.h" #include "main/format_unpack.h" #include "main/macros.h" @@ -1144,7 +1143,7 @@ _swrast_write_rgba_span( struct gl_context *ctx, SWspan *span) struct gl_framebuffer *fb = ctx->DrawBuffer; /* - printf("%s() interp 0x%x array 0x%x\n", __FUNCTION__, + printf("%s() interp 0x%x array 0x%x\n", __func__, span->interpMask, span->arrayMask); */ diff --git a/mesalib/src/mesa/swrast/s_texcombine.c b/mesalib/src/mesa/swrast/s_texcombine.c index 58ff16465..0adb8e5ba 100644 --- a/mesalib/src/mesa/swrast/s_texcombine.c +++ b/mesalib/src/mesa/swrast/s_texcombine.c @@ -26,8 +26,8 @@ #include "main/glheader.h" #include "main/context.h" -#include "main/colormac.h" #include "main/imports.h" +#include "main/macros.h" #include "main/pixeltransfer.h" #include "main/samplerobj.h" #include "program/prog_instruction.h" diff --git a/mesalib/src/mesa/swrast/s_texfetch.c b/mesalib/src/mesa/swrast/s_texfetch.c index 3c4ee15ba..1fe21c0b4 100644 --- a/mesalib/src/mesa/swrast/s_texfetch.c +++ b/mesalib/src/mesa/swrast/s_texfetch.c @@ -33,7 +33,6 @@ */ -#include "main/colormac.h" #include "main/macros.h" #include "main/texcompress.h" #include "main/texcompress_fxt1.h" diff --git a/mesalib/src/mesa/swrast/s_texfilter.c b/mesalib/src/mesa/swrast/s_texfilter.c index 3ade99519..abc1727cf 100644 --- a/mesalib/src/mesa/swrast/s_texfilter.c +++ b/mesalib/src/mesa/swrast/s_texfilter.c @@ -26,8 +26,8 @@ #include "c99_math.h" #include "main/glheader.h" #include "main/context.h" -#include "main/colormac.h" #include "main/imports.h" +#include "main/macros.h" #include "main/samplerobj.h" #include "main/teximage.h" #include "main/texobj.h" diff --git a/mesalib/src/mesa/swrast/s_texrender.c b/mesalib/src/mesa/swrast/s_texrender.c index 29bb270d6..fa853c919 100644 --- a/mesalib/src/mesa/swrast/s_texrender.c +++ b/mesalib/src/mesa/swrast/s_texrender.c @@ -1,6 +1,5 @@ #include "main/context.h" -#include "main/colormac.h" #include "main/fbobject.h" #include "main/macros.h" #include "main/teximage.h" diff --git a/mesalib/src/mesa/swrast/s_triangle.c b/mesalib/src/mesa/swrast/s_triangle.c index af039c359..876a74b08 100644 --- a/mesalib/src/mesa/swrast/s_triangle.c +++ b/mesalib/src/mesa/swrast/s_triangle.c @@ -31,7 +31,6 @@ #include "main/glheader.h" #include "main/context.h" -#include "main/colormac.h" #include "main/imports.h" #include "main/macros.h" #include "main/mtypes.h" diff --git a/mesalib/src/mesa/swrast/s_tritemp.h b/mesalib/src/mesa/swrast/s_tritemp.h index fb73b2d59..fddbbfd99 100644 --- a/mesalib/src/mesa/swrast/s_tritemp.h +++ b/mesalib/src/mesa/swrast/s_tritemp.h @@ -92,7 +92,7 @@ #ifndef MAX_GLUINT -#define MAX_GLUINT 0xffffffff +#define MAX_GLUINT 0xffffffffu #endif @@ -156,7 +156,7 @@ static void NAME(struct gl_context *ctx, const SWvertex *v0, #endif /* - printf("%s()\n", __FUNCTION__); + printf("%s()\n", __func__); printf(" %g, %g, %g\n", v0->attrib[VARYING_SLOT_POS][0], v0->attrib[VARYING_SLOT_POS][1], diff --git a/mesalib/src/mesa/swrast/s_zoom.c b/mesalib/src/mesa/swrast/s_zoom.c index ab22652c7..9879e2a5f 100644 --- a/mesalib/src/mesa/swrast/s_zoom.c +++ b/mesalib/src/mesa/swrast/s_zoom.c @@ -26,7 +26,6 @@ #include "main/macros.h" #include "main/imports.h" #include "main/format_pack.h" -#include "main/colormac.h" #include "s_context.h" #include "s_span.h" diff --git a/mesalib/src/mesa/swrast_setup/ss_context.c b/mesalib/src/mesa/swrast_setup/ss_context.c index 0b3b9e4df..74b1da342 100644 --- a/mesalib/src/mesa/swrast_setup/ss_context.c +++ b/mesalib/src/mesa/swrast_setup/ss_context.c @@ -27,7 +27,7 @@ #include "main/glheader.h" #include "main/imports.h" -#include "main/colormac.h" +#include "main/macros.h" #include "tnl/tnl.h" #include "tnl/t_context.h" #include "tnl/t_pipeline.h" @@ -167,7 +167,7 @@ setup_vertex_format(struct gl_context *ctx) EMIT_ATTR( _TNL_ATTRIB_POINTSIZE, EMIT_1F, pointSize ); _tnl_install_attrs( ctx, map, e, - ctx->ViewportArray[0]._WindowMap.m, + tnl->_WindowMap.m, sizeof(SWvertex) ); swsetup->last_index_bitset = index_bitset; @@ -265,7 +265,8 @@ _swsetup_Wakeup( struct gl_context *ctx ) void _swsetup_Translate( struct gl_context *ctx, const void *vertex, SWvertex *dest ) { - const GLfloat *m = ctx->ViewportArray[0]._WindowMap.m; + TNLcontext *tnl = TNL_CONTEXT(ctx); + const GLfloat *m = tnl->_WindowMap.m; GLfloat tmp[4]; GLuint i; diff --git a/mesalib/src/mesa/swrast_setup/ss_triangle.c b/mesalib/src/mesa/swrast_setup/ss_triangle.c index 483c41592..b92c20be2 100644 --- a/mesalib/src/mesa/swrast_setup/ss_triangle.c +++ b/mesalib/src/mesa/swrast_setup/ss_triangle.c @@ -27,7 +27,6 @@ #include "c99_math.h" #include "main/glheader.h" -#include "main/colormac.h" #include "main/macros.h" #include "main/mtypes.h" diff --git a/mesalib/src/mesa/tnl/t_context.c b/mesalib/src/mesa/tnl/t_context.c index bc705d7a3..5b9dd54d7 100644 --- a/mesalib/src/mesa/tnl/t_context.c +++ b/mesalib/src/mesa/tnl/t_context.c @@ -35,6 +35,7 @@ #include "math/m_translate.h" #include "math/m_xform.h" #include "main/state.h" +#include "main/viewport.h" #include "tnl.h" #include "t_context.h" @@ -69,6 +70,8 @@ _tnl_CreateContext( struct gl_context *ctx ) _tnl_install_pipeline( ctx, _tnl_default_pipeline ); } + _math_matrix_ctr(&tnl->_WindowMap); + tnl->NeedNdcCoords = GL_TRUE; tnl->AllowVertexFog = GL_TRUE; tnl->AllowPixelFog = GL_TRUE; @@ -108,6 +111,8 @@ _tnl_DestroyContext( struct gl_context *ctx ) struct tnl_shine_tab *s, *tmps; TNLcontext *tnl = TNL_CONTEXT(ctx); + _math_matrix_dtr(&tnl->_WindowMap); + /* Free lighting shininess exponentiation table */ foreach_s( s, tmps, tnl->_ShineTabList ) { free( s ); @@ -182,6 +187,13 @@ _tnl_InvalidateState( struct gl_context *ctx, GLuint new_state ) } } } + + if (new_state & (_NEW_VIEWPORT | _NEW_BUFFERS)) { + double scale[3], translate[3]; + _mesa_get_viewport_xform(ctx, 0, scale, translate); + _math_matrix_viewport(&tnl->_WindowMap, scale, translate, + ctx->DrawBuffer->_DepthMaxF); + } } diff --git a/mesalib/src/mesa/tnl/t_context.h b/mesalib/src/mesa/tnl/t_context.h index e89a7f836..e7adb5f53 100644 --- a/mesalib/src/mesa/tnl/t_context.h +++ b/mesalib/src/mesa/tnl/t_context.h @@ -514,6 +514,7 @@ typedef struct /* Clipspace/ndc/window vertex managment: */ struct tnl_clipspace clipspace; + GLmatrix _WindowMap; /* Probably need a better configuration mechanism: */ diff --git a/mesalib/src/mesa/tnl/t_draw.c b/mesalib/src/mesa/tnl/t_draw.c index 60265d60b..6adf1dce6 100644 --- a/mesalib/src/mesa/tnl/t_draw.c +++ b/mesalib/src/mesa/tnl/t_draw.c @@ -448,7 +448,7 @@ void _tnl_draw_prims(struct gl_context *ctx, if (0) { - printf("%s %d..%d\n", __FUNCTION__, min_index, max_index); + printf("%s %d..%d\n", __func__, min_index, max_index); for (i = 0; i < nr_prims; i++) printf("prim %d: %s start %d count %d\n", i, _mesa_lookup_enum_by_nr(prim[i].mode), diff --git a/mesalib/src/mesa/tnl/t_rasterpos.c b/mesalib/src/mesa/tnl/t_rasterpos.c index 9ecf947df..d4b45bac9 100644 --- a/mesalib/src/mesa/tnl/t_rasterpos.c +++ b/mesalib/src/mesa/tnl/t_rasterpos.c @@ -25,12 +25,12 @@ #include "c99_math.h" #include "main/glheader.h" -#include "main/colormac.h" #include "main/feedback.h" #include "main/light.h" #include "main/macros.h" #include "util/simple_list.h" #include "main/mtypes.h" +#include "main/viewport.h" #include "math/m_matrix.h" #include "tnl/tnl.h" @@ -378,6 +378,7 @@ _tnl_RasterPos(struct gl_context *ctx, const GLfloat vObj[4]) GLfloat eye[4], clip[4], ndc[3], d; GLfloat *norm, eyenorm[3]; GLfloat *objnorm = ctx->Current.Attrib[VERT_ATTRIB_NORMAL]; + double scale[3], translate[3]; /* apply modelview matrix: eye = MV * obj */ TRANSFORM_POINT( eye, ctx->ModelviewMatrixStack.Top->m, vObj ); @@ -410,13 +411,10 @@ _tnl_RasterPos(struct gl_context *ctx, const GLfloat vObj[4]) ndc[1] = clip[1] * d; ndc[2] = clip[2] * d; /* wincoord = viewport_mapping(ndc) */ - ctx->Current.RasterPos[0] = (ndc[0] * ctx->ViewportArray[0]._WindowMap.m[MAT_SX] - + ctx->ViewportArray[0]._WindowMap.m[MAT_TX]); - ctx->Current.RasterPos[1] = (ndc[1] * ctx->ViewportArray[0]._WindowMap.m[MAT_SY] - + ctx->ViewportArray[0]._WindowMap.m[MAT_TY]); - ctx->Current.RasterPos[2] = (ndc[2] * ctx->ViewportArray[0]._WindowMap.m[MAT_SZ] - + ctx->ViewportArray[0]._WindowMap.m[MAT_TZ]) - / ctx->DrawBuffer->_DepthMaxF; + _mesa_get_viewport_xform(ctx, 0, scale, translate); + ctx->Current.RasterPos[0] = ndc[0] * scale[0] + translate[0]; + ctx->Current.RasterPos[1] = ndc[1] * scale[1] + translate[1]; + ctx->Current.RasterPos[2] = ndc[2] * scale[2] + translate[2]; ctx->Current.RasterPos[3] = clip[3]; if (ctx->Transform.DepthClamp) { diff --git a/mesalib/src/mesa/tnl/t_vb_fog.c b/mesalib/src/mesa/tnl/t_vb_fog.c index 3626f1da3..1ca72f866 100644 --- a/mesalib/src/mesa/tnl/t_vb_fog.c +++ b/mesalib/src/mesa/tnl/t_vb_fog.c @@ -28,7 +28,6 @@ #include "c99_math.h" #include "main/glheader.h" -#include "main/colormac.h" #include "main/macros.h" #include "main/imports.h" #include "main/mtypes.h" diff --git a/mesalib/src/mesa/tnl/t_vb_light.c b/mesalib/src/mesa/tnl/t_vb_light.c index 7781b6a6c..dbd57fa6b 100644 --- a/mesalib/src/mesa/tnl/t_vb_light.c +++ b/mesalib/src/mesa/tnl/t_vb_light.c @@ -25,7 +25,6 @@ #include "c99_math.h" #include "main/glheader.h" -#include "main/colormac.h" #include "main/light.h" #include "main/macros.h" #include "main/imports.h" diff --git a/mesalib/src/mesa/tnl/t_vb_lighttmp.h b/mesalib/src/mesa/tnl/t_vb_lighttmp.h index 57f569bd7..f8786accb 100644 --- a/mesalib/src/mesa/tnl/t_vb_lighttmp.h +++ b/mesalib/src/mesa/tnl/t_vb_lighttmp.h @@ -68,7 +68,7 @@ static void TAG(light_rgba_spec)( struct gl_context *ctx, const GLuint nr = VB->Count; #ifdef TRACE - fprintf(stderr, "%s\n", __FUNCTION__ ); + fprintf(stderr, "%s\n", __func__ ); #endif VB->AttribPtr[_TNL_ATTRIB_COLOR0] = &store->LitColor[0]; @@ -249,7 +249,7 @@ static void TAG(light_rgba)( struct gl_context *ctx, const GLuint nr = VB->Count; #ifdef TRACE - fprintf(stderr, "%s\n", __FUNCTION__ ); + fprintf(stderr, "%s\n", __func__ ); #endif VB->AttribPtr[_TNL_ATTRIB_COLOR0] = &store->LitColor[0]; @@ -429,7 +429,7 @@ static void TAG(light_fast_rgba_single)( struct gl_context *ctx, #endif #ifdef TRACE - fprintf(stderr, "%s\n", __FUNCTION__ ); + fprintf(stderr, "%s\n", __func__ ); #endif (void) input; /* doesn't refer to Eye or Obj */ @@ -533,7 +533,7 @@ static void TAG(light_fast_rgba)( struct gl_context *ctx, const struct gl_light *light; #ifdef TRACE - fprintf(stderr, "%s %d\n", __FUNCTION__, nr ); + fprintf(stderr, "%s %d\n", __func__, nr ); #endif (void) input; diff --git a/mesalib/src/mesa/tnl/t_vb_normals.c b/mesalib/src/mesa/tnl/t_vb_normals.c index b67789e42..9aee1a2fb 100644 --- a/mesalib/src/mesa/tnl/t_vb_normals.c +++ b/mesalib/src/mesa/tnl/t_vb_normals.c @@ -27,7 +27,6 @@ #include "main/glheader.h" -#include "main/colormac.h" #include "main/macros.h" #include "main/imports.h" #include "main/mtypes.h" diff --git a/mesalib/src/mesa/tnl/t_vb_program.c b/mesalib/src/mesa/tnl/t_vb_program.c index 464a4cddd..149434971 100644 --- a/mesalib/src/mesa/tnl/t_vb_program.c +++ b/mesalib/src/mesa/tnl/t_vb_program.c @@ -32,7 +32,6 @@ #include "main/glheader.h" -#include "main/colormac.h" #include "main/macros.h" #include "main/imports.h" #include "main/samplerobj.h" diff --git a/mesalib/src/mesa/tnl/t_vb_texgen.c b/mesalib/src/mesa/tnl/t_vb_texgen.c index 9a61ef2fe..94066f4f6 100644 --- a/mesalib/src/mesa/tnl/t_vb_texgen.c +++ b/mesalib/src/mesa/tnl/t_vb_texgen.c @@ -35,7 +35,6 @@ */ #include "main/glheader.h" -#include "main/colormac.h" #include "main/macros.h" #include "main/imports.h" #include "main/mtypes.h" diff --git a/mesalib/src/mesa/tnl/t_vb_texmat.c b/mesalib/src/mesa/tnl/t_vb_texmat.c index 1cc2c8116..ef034d643 100644 --- a/mesalib/src/mesa/tnl/t_vb_texmat.c +++ b/mesalib/src/mesa/tnl/t_vb_texmat.c @@ -27,7 +27,6 @@ #include "main/glheader.h" -#include "main/colormac.h" #include "main/macros.h" #include "main/imports.h" #include "main/mtypes.h" diff --git a/mesalib/src/mesa/tnl/t_vb_vertex.c b/mesalib/src/mesa/tnl/t_vb_vertex.c index ea3a56cd1..b56d6803c 100644 --- a/mesalib/src/mesa/tnl/t_vb_vertex.c +++ b/mesalib/src/mesa/tnl/t_vb_vertex.c @@ -27,7 +27,6 @@ #include "main/glheader.h" -#include "main/colormac.h" #include "main/macros.h" #include "main/imports.h" #include "main/mtypes.h" diff --git a/mesalib/src/mesa/tnl/t_vertex.c b/mesalib/src/mesa/tnl/t_vertex.c index 369d6d945..c3294b007 100644 --- a/mesalib/src/mesa/tnl/t_vertex.c +++ b/mesalib/src/mesa/tnl/t_vertex.c @@ -28,7 +28,6 @@ #include <stdio.h> #include "main/glheader.h" #include "main/context.h" -#include "main/colormac.h" #include "swrast/s_chan.h" #include "t_context.h" #include "t_vertex.h" diff --git a/mesalib/src/mesa/tnl/t_vertex_generic.c b/mesalib/src/mesa/tnl/t_vertex_generic.c index 079d473fc..2a25a9692 100644 --- a/mesalib/src/mesa/tnl/t_vertex_generic.c +++ b/mesalib/src/mesa/tnl/t_vertex_generic.c @@ -28,7 +28,7 @@ #include "main/glheader.h" #include "main/context.h" -#include "main/colormac.h" +#include "main/macros.h" #include "util/simple_list.h" #include "swrast/s_chan.h" #include "t_context.h" @@ -36,7 +36,7 @@ #if 0 -#define DEBUG_INSERT printf("%s\n", __FUNCTION__) +#define DEBUG_INSERT printf("%s\n", __func__) #else #define DEBUG_INSERT #endif diff --git a/mesalib/src/mesa/tnl/t_vertex_sse.c b/mesalib/src/mesa/tnl/t_vertex_sse.c index 963432c48..30dc1a720 100644 --- a/mesalib/src/mesa/tnl/t_vertex_sse.c +++ b/mesalib/src/mesa/tnl/t_vertex_sse.c @@ -29,7 +29,6 @@ #include "main/glheader.h" #include "main/context.h" -#include "main/colormac.h" #include "util/simple_list.h" #include "main/enums.h" #include "swrast/s_chan.h" diff --git a/mesalib/src/mesa/vbo/vbo_exec_api.c b/mesalib/src/mesa/vbo/vbo_exec_api.c index 02741c2bc..859078f12 100644 --- a/mesalib/src/mesa/vbo/vbo_exec_api.c +++ b/mesalib/src/mesa/vbo/vbo_exec_api.c @@ -439,7 +439,7 @@ do { \ } while (0) -#define ERROR(err) _mesa_error( ctx, err, __FUNCTION__ ) +#define ERROR(err) _mesa_error( ctx, err, __func__ ) #define TAG(x) vbo_##x #include "vbo_attrib_tmp.h" diff --git a/mesalib/src/mesa/vbo/vbo_exec_draw.c b/mesalib/src/mesa/vbo/vbo_exec_draw.c index 91f2ca43a..37b53a830 100644 --- a/mesalib/src/mesa/vbo/vbo_exec_draw.c +++ b/mesalib/src/mesa/vbo/vbo_exec_draw.c @@ -45,7 +45,7 @@ vbo_exec_debug_verts( struct vbo_exec_context *exec ) GLuint i; printf("%s: %u vertices %d primitives, %d vertsize\n", - __FUNCTION__, + __func__, count, exec->vtx.prim_count, exec->vtx.vertex_size); @@ -402,7 +402,7 @@ vbo_exec_vtx_flush(struct vbo_exec_context *exec, GLboolean keepUnmapped) } if (0) - printf("%s %d %d\n", __FUNCTION__, exec->vtx.prim_count, + printf("%s %d %d\n", __func__, exec->vtx.prim_count, exec->vtx.vert_count); vbo_context(ctx)->draw_prims( ctx, diff --git a/mesalib/src/mesa/vbo/vbo_primitive_restart.c b/mesalib/src/mesa/vbo/vbo_primitive_restart.c index 562dedcd5..dafc4fd2a 100644 --- a/mesalib/src/mesa/vbo/vbo_primitive_restart.c +++ b/mesalib/src/mesa/vbo/vbo_primitive_restart.c @@ -167,6 +167,8 @@ vbo_sw_primitive_restart(struct gl_context *ctx, struct gl_buffer_object *indirect) { GLuint prim_num; + struct _mesa_prim new_prim; + struct _mesa_index_buffer new_ib; struct sub_primitive *sub_prims; struct sub_primitive *sub_prim; GLuint num_sub_prims; @@ -182,8 +184,6 @@ vbo_sw_primitive_restart(struct gl_context *ctx, /* If there is an indirect buffer, map it and extract the draw params */ if (indirect && prims[0].is_indirect) { - struct _mesa_prim new_prim = *prims; - 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, MAP_INTERNAL)) { @@ -195,6 +195,7 @@ vbo_sw_primitive_restart(struct gl_context *ctx, } assert(nr_prims == 1); + new_prim = prims[0]; indirect_params = (const uint32_t *) ADD_POINTERS(indirect->Mappings[MAP_INTERNAL].Pointer, new_prim.indirect_offset); @@ -206,6 +207,7 @@ vbo_sw_primitive_restart(struct gl_context *ctx, new_prim.basevertex = indirect_params[3]; new_prim.base_instance = indirect_params[4]; + new_ib = *ib; new_ib.count = new_prim.count; prims = &new_prim; diff --git a/mesalib/src/mesa/vbo/vbo_rebase.c b/mesalib/src/mesa/vbo/vbo_rebase.c index b06df4ab2..c3c4b64e6 100644 --- a/mesalib/src/mesa/vbo/vbo_rebase.c +++ b/mesalib/src/mesa/vbo/vbo_rebase.c @@ -142,7 +142,7 @@ void vbo_rebase_prims( struct gl_context *ctx, assert(min_index != 0); if (0) - printf("%s %d..%d\n", __FUNCTION__, min_index, max_index); + printf("%s %d..%d\n", __func__, min_index, max_index); /* XXX this path is disabled for now. diff --git a/mesalib/src/mesa/vbo/vbo_save_api.c b/mesalib/src/mesa/vbo/vbo_save_api.c index fd9a5de3d..5927beeb3 100644 --- a/mesalib/src/mesa/vbo/vbo_save_api.c +++ b/mesalib/src/mesa/vbo/vbo_save_api.c @@ -763,7 +763,7 @@ _save_reset_vertex(struct gl_context *ctx) -#define ERROR(err) _mesa_compile_error(ctx, err, __FUNCTION__); +#define ERROR(err) _mesa_compile_error(ctx, err, __func__); /* Only one size for each attribute may be active at once. Eg. if diff --git a/mesalib/src/mesa/x86/common_x86.c b/mesalib/src/mesa/x86/common_x86.c index 86fbca91e..1c8640514 100644 --- a/mesalib/src/mesa/x86/common_x86.c +++ b/mesalib/src/mesa/x86/common_x86.c @@ -42,7 +42,7 @@ #include <sys/types.h> #include <sys/sysctl.h> #endif -#if defined(USE_SSE_ASM) && defined(__OpenBSD__) +#if defined(USE_SSE_ASM) && (defined(__OpenBSD__) || defined(__NetBSD__)) #include <sys/param.h> #include <sys/sysctl.h> #include <machine/cpu.h> |