aboutsummaryrefslogtreecommitdiff
path: root/mesalib/src/glsl/glsl_parser_extras.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'mesalib/src/glsl/glsl_parser_extras.cpp')
-rw-r--r--mesalib/src/glsl/glsl_parser_extras.cpp172
1 files changed, 172 insertions, 0 deletions
diff --git a/mesalib/src/glsl/glsl_parser_extras.cpp b/mesalib/src/glsl/glsl_parser_extras.cpp
index f1fdd3a47..d36089226 100644
--- a/mesalib/src/glsl/glsl_parser_extras.cpp
+++ b/mesalib/src/glsl/glsl_parser_extras.cpp
@@ -37,6 +37,16 @@ extern "C" {
#include "ir_optimization.h"
#include "loop_analysis.h"
+/**
+ * Format a short human-readable description of the given GLSL version.
+ */
+const char *
+glsl_compute_version_string(void *mem_ctx, bool is_es, unsigned version)
+{
+ return ralloc_asprintf(mem_ctx, "GLSL%s %d.%02d", is_es ? " ES" : "",
+ version / 100, version % 100);
+}
+
_mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx,
GLenum target, void *mem_ctx)
: ctx(_ctx)
@@ -82,6 +92,8 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx,
this->Const.MaxCombinedTextureImageUnits = ctx->Const.MaxCombinedTextureImageUnits;
this->Const.MaxTextureImageUnits = ctx->Const.MaxTextureImageUnits;
this->Const.MaxFragmentUniformComponents = ctx->Const.FragmentProgram.MaxUniformComponents;
+ this->Const.MinProgramTexelOffset = ctx->Const.MinProgramTexelOffset;
+ this->Const.MaxProgramTexelOffset = ctx->Const.MaxProgramTexelOffset;
this->Const.MaxDrawBuffers = ctx->Const.MaxDrawBuffers;
@@ -113,6 +125,166 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx,
this->default_uniform_qualifier->flags.q.column_major = 1;
}
+/**
+ * Determine whether the current GLSL version is sufficiently high to support
+ * a certain feature, and generate an error message if it isn't.
+ *
+ * \param required_glsl_version and \c required_glsl_es_version are
+ * interpreted as they are in _mesa_glsl_parse_state::is_version().
+ *
+ * \param locp is the parser location where the error should be reported.
+ *
+ * \param fmt (and additional arguments) constitute a printf-style error
+ * message to report if the version check fails. Information about the
+ * current and required GLSL versions will be appended. So, for example, if
+ * the GLSL version being compiled is 1.20, and check_version(130, 300, locp,
+ * "foo unsupported") is called, the error message will be "foo unsupported in
+ * GLSL 1.20 (GLSL 1.30 or GLSL 3.00 ES required)".
+ */
+bool
+_mesa_glsl_parse_state::check_version(unsigned required_glsl_version,
+ unsigned required_glsl_es_version,
+ YYLTYPE *locp, const char *fmt, ...)
+{
+ if (this->is_version(required_glsl_version, required_glsl_es_version))
+ return true;
+
+ va_list args;
+ va_start(args, fmt);
+ char *problem = ralloc_vasprintf(ctx, fmt, args);
+ va_end(args);
+ const char *glsl_version_string
+ = glsl_compute_version_string(ctx, false, required_glsl_version);
+ const char *glsl_es_version_string
+ = glsl_compute_version_string(ctx, true, required_glsl_es_version);
+ const char *requirement_string = "";
+ if (required_glsl_version && required_glsl_es_version) {
+ requirement_string = ralloc_asprintf(ctx, " (%s or %s required)",
+ glsl_version_string,
+ glsl_es_version_string);
+ } else if (required_glsl_version) {
+ requirement_string = ralloc_asprintf(ctx, " (%s required)",
+ glsl_version_string);
+ } else if (required_glsl_es_version) {
+ requirement_string = ralloc_asprintf(ctx, " (%s required)",
+ glsl_es_version_string);
+ }
+ _mesa_glsl_error(locp, this, "%s in %s%s.",
+ problem, this->get_version_string(),
+ requirement_string);
+
+ return false;
+}
+
+/**
+ * Process a GLSL #version directive.
+ *
+ * \param version is the integer that follows the #version token.
+ *
+ * \param ident is a string identifier that follows the integer, if any is
+ * present. Otherwise NULL.
+ */
+void
+_mesa_glsl_parse_state::process_version_directive(YYLTYPE *locp, int version,
+ const char *ident)
+{
+ bool es_token_present = false;
+ if (ident) {
+ if (strcmp(ident, "es") == 0) {
+ es_token_present = true;
+ } else {
+ _mesa_glsl_error(locp, this,
+ "Illegal text following version number\n");
+ }
+ }
+
+ bool supported = false;
+
+ if (es_token_present) {
+ this->es_shader = true;
+ switch (version) {
+ case 100:
+ _mesa_glsl_error(locp, this,
+ "GLSL 1.00 ES should be selected using "
+ "`#version 100'\n");
+ supported = this->ctx->API == API_OPENGLES2 ||
+ this->ctx->Extensions.ARB_ES2_compatibility;
+ break;
+ case 300:
+ supported = _mesa_is_gles3(this->ctx) ||
+ this->ctx->Extensions.ARB_ES3_compatibility;
+ break;
+ default:
+ supported = false;
+ break;
+ }
+ } else {
+ switch (version) {
+ case 100:
+ this->es_shader = true;
+ supported = this->ctx->API == API_OPENGLES2 ||
+ this->ctx->Extensions.ARB_ES2_compatibility;
+ break;
+ case 110:
+ case 120:
+ /* FINISHME: Once the OpenGL 3.0 'forward compatible' context or
+ * the OpenGL 3.2 Core context is supported, this logic will need
+ * change. Older versions of GLSL are no longer supported
+ * outside the compatibility contexts of 3.x.
+ */
+ case 130:
+ case 140:
+ case 150:
+ case 330:
+ case 400:
+ case 410:
+ case 420:
+ supported = _mesa_is_desktop_gl(this->ctx) &&
+ ((unsigned) version) <= this->ctx->Const.GLSLVersion;
+ break;
+ default:
+ supported = false;
+ break;
+ }
+ }
+
+ this->language_version = version;
+
+ if (!supported) {
+ _mesa_glsl_error(locp, this, "%s is not supported. "
+ "Supported versions are: %s\n",
+ this->get_version_string(),
+ this->supported_version_string);
+
+ /* On exit, the language_version must be set to a valid value.
+ * Later calls to _mesa_glsl_initialize_types will misbehave if
+ * the version is invalid.
+ */
+ switch (this->ctx->API) {
+ case API_OPENGL_COMPAT:
+ case API_OPENGL_CORE:
+ this->language_version = this->ctx->Const.GLSLVersion;
+ break;
+
+ case API_OPENGLES:
+ assert(!"Should not get here.");
+ /* FALLTHROUGH */
+
+ case API_OPENGLES2:
+ this->language_version = 100;
+ break;
+ }
+ }
+
+ if (this->language_version >= 140) {
+ this->ARB_uniform_buffer_object_enable = true;
+ }
+
+ if (this->language_version == 300 && this->es_shader) {
+ this->ARB_explicit_attrib_location_enable = true;
+ }
+}
+
const char *
_mesa_glsl_shader_target_name(enum _mesa_glsl_parser_targets target)
{