aboutsummaryrefslogtreecommitdiff
path: root/mesalib/src/mesa/main
diff options
context:
space:
mode:
Diffstat (limited to 'mesalib/src/mesa/main')
-rw-r--r--mesalib/src/mesa/main/api_validate.c70
-rw-r--r--mesalib/src/mesa/main/context.h11
-rw-r--r--mesalib/src/mesa/main/fbobject.c187
-rw-r--r--mesalib/src/mesa/main/fbobject.h6
-rw-r--r--mesalib/src/mesa/main/get.c2
-rw-r--r--mesalib/src/mesa/main/lines.c3
-rw-r--r--mesalib/src/mesa/main/mtypes.h80
-rw-r--r--mesalib/src/mesa/main/shaderapi.c48
-rw-r--r--mesalib/src/mesa/main/shaderapi.h5
-rw-r--r--mesalib/src/mesa/main/shared.c3
-rw-r--r--mesalib/src/mesa/main/texobj.c53
-rw-r--r--mesalib/src/mesa/main/texparam.c22
-rw-r--r--mesalib/src/mesa/main/texstate.c18
-rw-r--r--mesalib/src/mesa/main/varray.c20
-rw-r--r--mesalib/src/mesa/main/version.c1
15 files changed, 425 insertions, 104 deletions
diff --git a/mesalib/src/mesa/main/api_validate.c b/mesalib/src/mesa/main/api_validate.c
index 7ab8e305d..243bb89d1 100644
--- a/mesalib/src/mesa/main/api_validate.c
+++ b/mesalib/src/mesa/main/api_validate.c
@@ -222,7 +222,7 @@ _mesa_is_valid_prim_mode(struct gl_context *ctx, GLenum mode)
case GL_LINE_STRIP_ADJACENCY:
case GL_TRIANGLES_ADJACENCY:
case GL_TRIANGLE_STRIP_ADJACENCY:
- return _mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_geometry_shader4;
+ return _mesa_has_geometry_shaders(ctx);
default:
return false;
}
@@ -245,6 +245,74 @@ _mesa_valid_prim_mode(struct gl_context *ctx, GLenum mode, const char *name)
return GL_FALSE;
}
+ /* From the ARB_geometry_shader4 spec:
+ *
+ * The error INVALID_OPERATION is generated if Begin, or any command that
+ * implicitly calls Begin, is called when a geometry shader is active and:
+ *
+ * * the input primitive type of the current geometry shader is
+ * POINTS and <mode> is not POINTS,
+ *
+ * * the input primitive type of the current geometry shader is
+ * LINES and <mode> is not LINES, LINE_STRIP, or LINE_LOOP,
+ *
+ * * the input primitive type of the current geometry shader is
+ * TRIANGLES and <mode> is not TRIANGLES, TRIANGLE_STRIP or
+ * TRIANGLE_FAN,
+ *
+ * * the input primitive type of the current geometry shader is
+ * LINES_ADJACENCY_ARB and <mode> is not LINES_ADJACENCY_ARB or
+ * LINE_STRIP_ADJACENCY_ARB, or
+ *
+ * * the input primitive type of the current geometry shader is
+ * TRIANGLES_ADJACENCY_ARB and <mode> is not
+ * TRIANGLES_ADJACENCY_ARB or TRIANGLE_STRIP_ADJACENCY_ARB.
+ *
+ */
+ if (ctx->Shader.CurrentGeometryProgram) {
+ const GLenum geom_mode =
+ ctx->Shader.CurrentGeometryProgram->Geom.InputType;
+ switch (mode) {
+ case GL_POINTS:
+ valid_enum = (geom_mode == GL_POINTS);
+ break;
+ case GL_LINES:
+ case GL_LINE_LOOP:
+ case GL_LINE_STRIP:
+ valid_enum = (geom_mode == GL_LINES);
+ break;
+ case GL_TRIANGLES:
+ case GL_TRIANGLE_STRIP:
+ case GL_TRIANGLE_FAN:
+ valid_enum = (geom_mode == GL_TRIANGLES);
+ break;
+ case GL_QUADS:
+ case GL_QUAD_STRIP:
+ case GL_POLYGON:
+ valid_enum = false;
+ break;
+ case GL_LINES_ADJACENCY:
+ case GL_LINE_STRIP_ADJACENCY:
+ valid_enum = (geom_mode == GL_LINES_ADJACENCY);
+ break;
+ case GL_TRIANGLES_ADJACENCY:
+ case GL_TRIANGLE_STRIP_ADJACENCY:
+ valid_enum = (geom_mode == GL_TRIANGLES_ADJACENCY);
+ break;
+ default:
+ valid_enum = false;
+ break;
+ }
+ if (!valid_enum) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(mode=%s vs geometry shader input %s)",
+ name,
+ _mesa_lookup_prim_by_nr(mode),
+ _mesa_lookup_prim_by_nr(geom_mode));
+ return GL_FALSE;
+ }
+ }
+
/* From the GL_EXT_transform_feedback spec:
*
* "The error INVALID_OPERATION is generated if Begin, or any command
diff --git a/mesalib/src/mesa/main/context.h b/mesalib/src/mesa/main/context.h
index 8872be1f4..792ab4cd5 100644
--- a/mesalib/src/mesa/main/context.h
+++ b/mesalib/src/mesa/main/context.h
@@ -312,6 +312,17 @@ _mesa_is_gles3(const struct gl_context *ctx)
}
+/**
+ * Checks if the context supports geometry shaders.
+ */
+static inline GLboolean
+_mesa_has_geometry_shaders(const struct gl_context *ctx)
+{
+ return _mesa_is_desktop_gl(ctx) &&
+ (ctx->Version >= 32 || ctx->Extensions.ARB_geometry_shader4);
+}
+
+
#ifdef __cplusplus
}
#endif
diff --git a/mesalib/src/mesa/main/fbobject.c b/mesalib/src/mesa/main/fbobject.c
index bf7e85c88..1034c7a71 100644
--- a/mesalib/src/mesa/main/fbobject.c
+++ b/mesalib/src/mesa/main/fbobject.c
@@ -343,6 +343,28 @@ _mesa_remove_attachment(struct gl_context *ctx,
}
/**
+ * Verify a couple error conditions that will lead to an incomplete FBO and
+ * may cause problems for the driver's RenderTexture path.
+ */
+static bool
+driver_RenderTexture_is_safe(const struct gl_renderbuffer_attachment *att)
+{
+ const struct gl_texture_image *const texImage =
+ att->Texture->Image[att->CubeMapFace][att->TextureLevel];
+
+ if (texImage->Width == 0 || texImage->Height == 0 || texImage->Depth == 0)
+ return false;
+
+ if ((texImage->TexObject->Target == GL_TEXTURE_1D_ARRAY
+ && att->Zoffset >= texImage->Height)
+ || (texImage->TexObject->Target != GL_TEXTURE_1D_ARRAY
+ && att->Zoffset >= texImage->Depth))
+ return false;
+
+ return true;
+}
+
+/**
* Create a renderbuffer which will be set up by the driver to wrap the
* texture image slice.
*
@@ -363,8 +385,6 @@ _mesa_update_texture_renderbuffer(struct gl_context *ctx,
struct gl_renderbuffer *rb;
texImage = att->Texture->Image[att->CubeMapFace][att->TextureLevel];
- if (!texImage)
- return;
rb = att->Renderbuffer;
if (!rb) {
@@ -383,6 +403,9 @@ _mesa_update_texture_renderbuffer(struct gl_context *ctx,
rb->NeedsFinishRenderTexture = ctx->Driver.FinishRenderTexture != NULL;
}
+ if (!texImage)
+ return;
+
rb->_BaseFormat = texImage->_BaseFormat;
rb->Format = texImage->TexFormat;
rb->InternalFormat = texImage->InternalFormat;
@@ -391,7 +414,8 @@ _mesa_update_texture_renderbuffer(struct gl_context *ctx,
rb->NumSamples = texImage->NumSamples;
rb->TexImage = texImage;
- ctx->Driver.RenderTexture(ctx, fb, att);
+ if (driver_RenderTexture_is_safe(att))
+ ctx->Driver.RenderTexture(ctx, fb, att);
}
/**
@@ -703,15 +727,39 @@ test_attachment_completeness(const struct gl_context *ctx, GLenum format,
}
if (texImage->Width < 1 || texImage->Height < 1) {
att_incomplete("teximage width/height=0");
- printf("texobj = %u\n", texObj->Name);
- printf("level = %d\n", att->TextureLevel);
att->Complete = GL_FALSE;
return;
}
- if (texObj->Target == GL_TEXTURE_3D && att->Zoffset >= texImage->Depth) {
- att_incomplete("bad z offset");
- att->Complete = GL_FALSE;
- return;
+
+ switch (texObj->Target) {
+ case GL_TEXTURE_3D:
+ if (att->Zoffset >= texImage->Depth) {
+ att_incomplete("bad z offset");
+ att->Complete = GL_FALSE;
+ return;
+ }
+ break;
+ case GL_TEXTURE_1D_ARRAY:
+ if (att->Zoffset >= texImage->Height) {
+ att_incomplete("bad 1D-array layer");
+ att->Complete = GL_FALSE;
+ return;
+ }
+ break;
+ case GL_TEXTURE_2D_ARRAY:
+ if (att->Zoffset >= texImage->Depth) {
+ att_incomplete("bad 2D-array layer");
+ att->Complete = GL_FALSE;
+ return;
+ }
+ break;
+ case GL_TEXTURE_CUBE_MAP_ARRAY:
+ if (att->Zoffset >= texImage->Depth) {
+ att_incomplete("bad cube-array layer");
+ att->Complete = GL_FALSE;
+ return;
+ }
+ break;
}
baseFormat = _mesa_get_format_base_format(texImage->TexFormat);
@@ -1104,8 +1152,8 @@ _mesa_IsRenderbuffer(GLuint renderbuffer)
}
-void GLAPIENTRY
-_mesa_BindRenderbuffer(GLenum target, GLuint renderbuffer)
+static void
+bind_renderbuffer(GLenum target, GLuint renderbuffer, bool allow_user_names)
{
struct gl_renderbuffer *newRb;
GET_CURRENT_CONTEXT(ctx);
@@ -1125,9 +1173,7 @@ _mesa_BindRenderbuffer(GLenum target, GLuint renderbuffer)
/* ID was reserved, but no real renderbuffer object made yet */
newRb = NULL;
}
- else if (!newRb
- && _mesa_is_desktop_gl(ctx)
- && ctx->Extensions.ARB_framebuffer_object) {
+ else if (!newRb && !allow_user_names) {
/* All RB IDs must be Gen'd */
_mesa_error(ctx, GL_INVALID_OPERATION, "glBindRenderbuffer(buffer)");
return;
@@ -1154,32 +1200,68 @@ _mesa_BindRenderbuffer(GLenum target, GLuint renderbuffer)
_mesa_reference_renderbuffer(&ctx->CurrentRenderbuffer, newRb);
}
+void GLAPIENTRY
+_mesa_BindRenderbuffer(GLenum target, GLuint renderbuffer)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ /* OpenGL ES glBindRenderbuffer and glBindRenderbufferOES use this same
+ * entry point, but they allow the use of user-generated names.
+ */
+ bind_renderbuffer(target, renderbuffer, _mesa_is_gles(ctx));
+}
void GLAPIENTRY
_mesa_BindRenderbufferEXT(GLenum target, GLuint renderbuffer)
{
- _mesa_BindRenderbuffer(target, renderbuffer);
+ /* This function should not be in the dispatch table for core profile /
+ * OpenGL 3.1, so execution should never get here in those cases -- no
+ * need for an explicit test.
+ */
+ bind_renderbuffer(target, renderbuffer, true);
}
/**
- * If the given renderbuffer is anywhere attached to the framebuffer, detach
- * the renderbuffer.
- * This is used when a renderbuffer object is deleted.
- * The spec calls for unbinding.
+ * Remove the specified renderbuffer or texture from any attachment point in
+ * the framebuffer.
+ *
+ * \returns
+ * \c true if the renderbuffer was detached from an attachment point. \c
+ * false otherwise.
*/
-static void
-detach_renderbuffer(struct gl_context *ctx,
- struct gl_framebuffer *fb,
- struct gl_renderbuffer *rb)
+bool
+_mesa_detach_renderbuffer(struct gl_context *ctx,
+ struct gl_framebuffer *fb,
+ const void *att)
{
- GLuint i;
+ unsigned i;
+ bool progress = false;
+
for (i = 0; i < BUFFER_COUNT; i++) {
- if (fb->Attachment[i].Renderbuffer == rb) {
+ if (fb->Attachment[i].Texture == att
+ || fb->Attachment[i].Renderbuffer == att) {
_mesa_remove_attachment(ctx, &fb->Attachment[i]);
+ progress = true;
}
}
- invalidate_framebuffer(fb);
+
+ /* Section 4.4.4 (Framebuffer Completeness), subsection "Whole Framebuffer
+ * Completeness," of the OpenGL 3.1 spec says:
+ *
+ * "Performing any of the following actions may change whether the
+ * framebuffer is considered complete or incomplete:
+ *
+ * ...
+ *
+ * - Deleting, with DeleteTextures or DeleteRenderbuffers, an object
+ * containing an image that is attached to a framebuffer object
+ * that is bound to the framebuffer."
+ */
+ if (progress)
+ invalidate_framebuffer(fb);
+
+ return progress;
}
@@ -1203,12 +1285,29 @@ _mesa_DeleteRenderbuffers(GLsizei n, const GLuint *renderbuffers)
_mesa_BindRenderbuffer(GL_RENDERBUFFER_EXT, 0);
}
+ /* Section 4.4.2 (Attaching Images to Framebuffer Objects),
+ * subsection "Attaching Renderbuffer Images to a Framebuffer," of
+ * the OpenGL 3.1 spec says:
+ *
+ * "If a renderbuffer object is deleted while its image is
+ * attached to one or more attachment points in the currently
+ * bound framebuffer, then it is as if FramebufferRenderbuffer
+ * had been called, with a renderbuffer of 0, for each
+ * attachment point to which this image was attached in the
+ * currently bound framebuffer. In other words, this
+ * renderbuffer image is first detached from all attachment
+ * points in the currently bound framebuffer. Note that the
+ * renderbuffer image is specifically not detached from any
+ * non-bound framebuffers. Detaching the image from any
+ * non-bound framebuffers is the responsibility of the
+ * application.
+ */
if (_mesa_is_user_fbo(ctx->DrawBuffer)) {
- detach_renderbuffer(ctx, ctx->DrawBuffer, rb);
+ _mesa_detach_renderbuffer(ctx, ctx->DrawBuffer, rb);
}
if (_mesa_is_user_fbo(ctx->ReadBuffer)
&& ctx->ReadBuffer != ctx->DrawBuffer) {
- detach_renderbuffer(ctx, ctx->ReadBuffer, rb);
+ _mesa_detach_renderbuffer(ctx, ctx->ReadBuffer, rb);
}
/* Remove from hash table immediately, to free the ID.
@@ -1875,7 +1974,8 @@ check_begin_texture_render(struct gl_context *ctx, struct gl_framebuffer *fb)
for (i = 0; i < BUFFER_COUNT; i++) {
struct gl_renderbuffer_attachment *att = fb->Attachment + i;
- if (att->Texture && att->Renderbuffer->TexImage) {
+ if (att->Texture && att->Renderbuffer->TexImage
+ && driver_RenderTexture_is_safe(att)) {
ctx->Driver.RenderTexture(ctx, fb, att);
}
}
@@ -1906,8 +2006,8 @@ check_end_texture_render(struct gl_context *ctx, struct gl_framebuffer *fb)
}
-void GLAPIENTRY
-_mesa_BindFramebuffer(GLenum target, GLuint framebuffer)
+static void
+bind_framebuffer(GLenum target, GLuint framebuffer, bool allow_user_names)
{
struct gl_framebuffer *newDrawFb, *newReadFb;
struct gl_framebuffer *oldDrawFb, *oldReadFb;
@@ -1953,9 +2053,7 @@ _mesa_BindFramebuffer(GLenum target, GLuint framebuffer)
/* ID was reserved, but no real framebuffer object made yet */
newDrawFb = NULL;
}
- else if (!newDrawFb
- && _mesa_is_desktop_gl(ctx)
- && ctx->Extensions.ARB_framebuffer_object) {
+ else if (!newDrawFb && !allow_user_names) {
/* All FBO IDs must be Gen'd */
_mesa_error(ctx, GL_INVALID_OPERATION, "glBindFramebuffer(buffer)");
return;
@@ -2033,12 +2131,25 @@ _mesa_BindFramebuffer(GLenum target, GLuint framebuffer)
}
void GLAPIENTRY
-_mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer)
+_mesa_BindFramebuffer(GLenum target, GLuint framebuffer)
{
- _mesa_BindFramebuffer(target, framebuffer);
-}
+ GET_CURRENT_CONTEXT(ctx);
+ /* OpenGL ES glBindFramebuffer and glBindFramebufferOES use this same entry
+ * point, but they allow the use of user-generated names.
+ */
+ bind_framebuffer(target, framebuffer, _mesa_is_gles(ctx));
+}
+void GLAPIENTRY
+_mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer)
+{
+ /* This function should not be in the dispatch table for core profile /
+ * OpenGL 3.1, so execution should never get here in those cases -- no
+ * need for an explicit test.
+ */
+ bind_framebuffer(target, framebuffer, true);
+}
void GLAPIENTRY
_mesa_DeleteFramebuffers(GLsizei n, const GLuint *framebuffers)
@@ -2476,7 +2587,7 @@ _mesa_FramebufferTexture(GLenum target, GLenum attachment,
{
GET_CURRENT_CONTEXT(ctx);
- if (ctx->Version >= 32 || ctx->Extensions.ARB_geometry_shader4) {
+ if (_mesa_has_geometry_shaders(ctx)) {
framebuffer_texture(ctx, "Layer", target, attachment, 0, texture,
level, 0, GL_TRUE);
} else {
diff --git a/mesalib/src/mesa/main/fbobject.h b/mesalib/src/mesa/main/fbobject.h
index 0a2a5cc59..ab138cfff 100644
--- a/mesalib/src/mesa/main/fbobject.h
+++ b/mesalib/src/mesa/main/fbobject.h
@@ -28,6 +28,7 @@
#include "compiler.h"
#include "glheader.h"
+#include <stdbool.h>
struct gl_context;
struct gl_texture_object;
@@ -113,6 +114,11 @@ _mesa_is_legal_color_format(const struct gl_context *ctx, GLenum baseFormat);
extern GLenum
_mesa_base_fbo_format(struct gl_context *ctx, GLenum internalFormat);
+extern bool
+_mesa_detach_renderbuffer(struct gl_context *ctx,
+ struct gl_framebuffer *fb,
+ const void *att);
+
extern GLboolean GLAPIENTRY
_mesa_IsRenderbuffer(GLuint renderbuffer);
diff --git a/mesalib/src/mesa/main/get.c b/mesalib/src/mesa/main/get.c
index 0b33fa49b..09b008a07 100644
--- a/mesalib/src/mesa/main/get.c
+++ b/mesalib/src/mesa/main/get.c
@@ -989,7 +989,7 @@ check_extra(struct gl_context *ctx, const char *func, const struct value_desc *d
case EXTRA_EXT_UBO_GS4:
api_check = GL_TRUE;
api_found = (ctx->Extensions.ARB_uniform_buffer_object &&
- ctx->Extensions.ARB_geometry_shader4);
+ _mesa_has_geometry_shaders(ctx));
break;
case EXTRA_END:
break;
diff --git a/mesalib/src/mesa/main/lines.c b/mesalib/src/mesa/main/lines.c
index 0df9d66b0..3c08ed2e7 100644
--- a/mesalib/src/mesa/main/lines.c
+++ b/mesalib/src/mesa/main/lines.c
@@ -62,7 +62,8 @@ _mesa_LineWidth( GLfloat width )
*/
if (ctx->API == API_OPENGL_CORE
&& ((ctx->Const.ContextFlags & GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT)
- != 0)) {
+ != 0)
+ && width > 1.0) {
_mesa_error( ctx, GL_INVALID_VALUE, "glLineWidth" );
return;
}
diff --git a/mesalib/src/mesa/main/mtypes.h b/mesalib/src/mesa/main/mtypes.h
index 5bb680745..5f9b7f983 100644
--- a/mesalib/src/mesa/main/mtypes.h
+++ b/mesalib/src/mesa/main/mtypes.h
@@ -1152,31 +1152,32 @@ struct gl_sampler_object
*/
struct gl_texture_object
{
- _glthread_Mutex Mutex; /**< for thread safety */
- GLint RefCount; /**< reference count */
- GLuint Name; /**< the user-visible texture object ID */
- GLenum Target; /**< GL_TEXTURE_1D, GL_TEXTURE_2D, etc. */
+ _glthread_Mutex Mutex; /**< for thread safety */
+ GLint RefCount; /**< reference count */
+ GLuint Name; /**< the user-visible texture object ID */
+ GLenum Target; /**< GL_TEXTURE_1D, GL_TEXTURE_2D, etc. */
struct gl_sampler_object Sampler;
- GLenum DepthMode; /**< GL_ARB_depth_texture */
-
- GLfloat Priority; /**< in [0,1] */
- GLint BaseLevel; /**< min mipmap level, OpenGL 1.2 */
- GLint MaxLevel; /**< max mipmap level, OpenGL 1.2 */
- GLint ImmutableLevels; /**< ES 3.0 / ARB_texture_view */
- GLint _MaxLevel; /**< actual max mipmap level (q in the spec) */
- GLfloat _MaxLambda; /**< = _MaxLevel - BaseLevel (q - b in spec) */
- GLint CropRect[4]; /**< GL_OES_draw_texture */
- GLenum Swizzle[4]; /**< GL_EXT_texture_swizzle */
- GLuint _Swizzle; /**< same as Swizzle, but SWIZZLE_* format */
- GLboolean GenerateMipmap; /**< GL_SGIS_generate_mipmap */
- GLboolean _BaseComplete; /**< Is the base texture level valid? */
- GLboolean _MipmapComplete; /**< Is the whole mipmap valid? */
- GLboolean _IsIntegerFormat; /**< Does the texture store integer values? */
- GLboolean _RenderToTexture; /**< Any rendering to this texture? */
- GLboolean Purgeable; /**< Is the buffer purgeable under memory pressure? */
- GLboolean Immutable; /**< GL_ARB_texture_storage */
+ GLenum DepthMode; /**< GL_ARB_depth_texture */
+
+ GLfloat Priority; /**< in [0,1] */
+ GLint BaseLevel; /**< min mipmap level, OpenGL 1.2 */
+ GLint MaxLevel; /**< max mipmap level, OpenGL 1.2 */
+ GLint ImmutableLevels; /**< ES 3.0 / ARB_texture_view */
+ GLint _MaxLevel; /**< actual max mipmap level (q in the spec) */
+ GLfloat _MaxLambda; /**< = _MaxLevel - BaseLevel (q - p in spec) */
+ GLint CropRect[4]; /**< GL_OES_draw_texture */
+ GLenum Swizzle[4]; /**< GL_EXT_texture_swizzle */
+ GLuint _Swizzle; /**< same as Swizzle, but SWIZZLE_* format */
+ GLboolean GenerateMipmap; /**< GL_SGIS_generate_mipmap */
+ GLboolean _BaseComplete; /**< Is the base texture level valid? */
+ GLboolean _MipmapComplete; /**< Is the whole mipmap valid? */
+ GLboolean _IsIntegerFormat; /**< Does the texture store integer values? */
+ GLboolean _RenderToTexture; /**< Any rendering to this texture? */
+ GLboolean Purgeable; /**< Is the buffer purgeable under memory
+ pressure? */
+ GLboolean Immutable; /**< GL_ARB_texture_storage */
/** Actual texture images, indexed by [cube face] and [mipmap level] */
struct gl_texture_image *Image[MAX_FACES][MAX_TEXTURE_LEVELS];
@@ -1851,7 +1852,7 @@ struct gl_program
GLuint Id;
GLubyte *String; /**< Null-terminated program text */
GLint RefCount;
- GLenum Target; /**< GL_VERTEX/FRAGMENT_PROGRAM_ARB */
+ GLenum Target; /**< GL_VERTEX/FRAGMENT_PROGRAM_ARB, GL_GEOMETRY_PROGRAM_NV */
GLenum Format; /**< String encoding format */
struct prog_instruction *Instructions;
@@ -1918,6 +1919,7 @@ struct gl_geometry_program
{
struct gl_program Base; /**< base class */
+ GLint VerticesIn;
GLint VerticesOut;
GLenum InputType; /**< GL_POINTS, GL_LINES, GL_LINES_ADJACENCY_ARB,
GL_TRIANGLES, or GL_TRIANGLES_ADJACENCY_ARB */
@@ -2169,6 +2171,24 @@ struct gl_shader
/** Shaders containing built-in functions that are used for linking. */
struct gl_shader *builtins_to_link[16];
unsigned num_builtins_to_link;
+
+ /**
+ * Geometry shader state from GLSL 1.50 layout qualifiers.
+ */
+ struct {
+ GLint VerticesOut;
+ /**
+ * GL_POINTS, GL_LINES, GL_LINES_ADJACENCY, GL_TRIANGLES, or
+ * GL_TRIANGLES_ADJACENCY, or PRIM_UNKNOWN if it's not set in this
+ * shader.
+ */
+ GLenum InputType;
+ /**
+ * GL_POINTS, GL_LINE_STRIP or GL_TRIANGLE_STRIP, or PRIM_UNKNOWN if
+ * it's not set in this shader.
+ */
+ GLenum OutputType;
+ } Geom;
};
@@ -2318,17 +2338,25 @@ struct gl_shader_program
/** Post-link gl_FragDepth layout for ARB_conservative_depth. */
enum gl_frag_depth_layout FragDepthLayout;
- /** Geometry shader state - copied into gl_geometry_program at link time */
+ /**
+ * Geometry shader state - copied into gl_geometry_program by
+ * _mesa_copy_linked_program_data().
+ */
struct {
+ GLint VerticesIn;
GLint VerticesOut;
GLenum InputType; /**< GL_POINTS, GL_LINES, GL_LINES_ADJACENCY_ARB,
GL_TRIANGLES, or GL_TRIANGLES_ADJACENCY_ARB */
GLenum OutputType; /**< GL_POINTS, GL_LINE_STRIP or GL_TRIANGLE_STRIP */
} Geom;
- /** Vertex shader state - copied into gl_vertex_program at link time */
+ /** Vertex shader state */
struct {
- GLboolean UsesClipDistance; /**< True if gl_ClipDistance is written to. */
+ /**
+ * True if gl_ClipDistance is written to. Copied into gl_vertex_program
+ * by _mesa_copy_linked_program_data().
+ */
+ GLboolean UsesClipDistance;
GLuint ClipDistanceArraySize; /**< Size of the gl_ClipDistance array, or
0 if not present. */
} Vert;
diff --git a/mesalib/src/mesa/main/shaderapi.c b/mesalib/src/mesa/main/shaderapi.c
index c349b0cb5..d184b114c 100644
--- a/mesalib/src/mesa/main/shaderapi.c
+++ b/mesalib/src/mesa/main/shaderapi.c
@@ -179,7 +179,7 @@ validate_shader_target(const struct gl_context *ctx, GLenum type)
case GL_VERTEX_SHADER:
return ctx->Extensions.ARB_vertex_shader;
case GL_GEOMETRY_SHADER_ARB:
- return _mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_geometry_shader4;
+ return _mesa_has_geometry_shaders(ctx);
default:
return false;
}
@@ -478,8 +478,7 @@ get_programiv(struct gl_context *ctx, GLuint program, GLenum pname, GLint *param
/* Are geometry shaders available in this context?
*/
- const bool has_gs =
- _mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_geometry_shader4;
+ const bool has_gs = _mesa_has_geometry_shaders(ctx);
/* Are uniform buffer objects available in this context?
*/
@@ -743,6 +742,12 @@ compile_shader(struct gl_context *ctx, GLuint shaderObj)
if (!sh)
return;
+ /* Geometry shaders are not yet fully supported, so issue a warning message
+ * if we're compiling one.
+ */
+ if (sh->Type == GL_GEOMETRY_SHADER)
+ printf("WARNING: Geometry shader support is currently experimental.\n");
+
options = &ctx->ShaderCompilerOptions[_mesa_shader_type_to_index(sh->Type)];
/* set default pragma state for shader */
@@ -1635,10 +1640,10 @@ _mesa_ProgramParameteri(GLuint program, GLenum pname, GLint value)
if (!_mesa_is_desktop_gl(ctx) || !ctx->Extensions.ARB_geometry_shader4)
break;
- if (value < 1 ||
+ if (value < 0 ||
(unsigned) value > ctx->Const.MaxGeometryOutputVertices) {
_mesa_error(ctx, GL_INVALID_VALUE,
- "glProgramParameteri(GL_GEOMETRY_VERTICES_OUT_ARB=%d",
+ "glProgramParameteri(GL_GEOMETRY_VERTICES_OUT_ARB=%d)",
value);
return;
}
@@ -1658,7 +1663,7 @@ _mesa_ProgramParameteri(GLuint program, GLenum pname, GLint value)
break;
default:
_mesa_error(ctx, GL_INVALID_VALUE,
- "glProgramParameteri(geometry input type = %s",
+ "glProgramParameteri(geometry input type = %s)",
_mesa_lookup_enum_by_nr(value));
return;
}
@@ -1675,7 +1680,7 @@ _mesa_ProgramParameteri(GLuint program, GLenum pname, GLint value)
break;
default:
_mesa_error(ctx, GL_INVALID_VALUE,
- "glProgramParameteri(geometry output type = %s",
+ "glProgramParameteri(geometry output type = %s)",
_mesa_lookup_enum_by_nr(value));
return;
}
@@ -1843,3 +1848,32 @@ _mesa_CreateShaderProgramEXT(GLenum type, const GLchar *string)
return program;
}
+
+
+/**
+ * Copy program-specific data generated by linking from the gl_shader_program
+ * object to a specific gl_program object.
+ */
+void
+_mesa_copy_linked_program_data(gl_shader_type type,
+ const struct gl_shader_program *src,
+ struct gl_program *dst)
+{
+ switch (type) {
+ case MESA_SHADER_VERTEX: {
+ struct gl_vertex_program *dst_vp = (struct gl_vertex_program *) dst;
+ dst_vp->UsesClipDistance = src->Vert.UsesClipDistance;
+ }
+ break;
+ case MESA_SHADER_GEOMETRY: {
+ struct gl_geometry_program *dst_gp = (struct gl_geometry_program *) dst;
+ dst_gp->VerticesIn = src->Geom.VerticesIn;
+ dst_gp->VerticesOut = src->Geom.VerticesOut;
+ dst_gp->InputType = src->Geom.InputType;
+ dst_gp->OutputType = src->Geom.OutputType;
+ }
+ break;
+ default:
+ break;
+ }
+}
diff --git a/mesalib/src/mesa/main/shaderapi.h b/mesalib/src/mesa/main/shaderapi.h
index 1cd4ffcea..fe58e7de9 100644
--- a/mesalib/src/mesa/main/shaderapi.h
+++ b/mesalib/src/mesa/main/shaderapi.h
@@ -210,6 +210,11 @@ _mesa_ActiveProgramEXT(GLuint program);
extern GLuint GLAPIENTRY
_mesa_CreateShaderProgramEXT(GLenum type, const GLchar *string);
+extern void
+_mesa_copy_linked_program_data(gl_shader_type type,
+ const struct gl_shader_program *src,
+ struct gl_program *dst);
+
#ifdef __cplusplus
}
diff --git a/mesalib/src/mesa/main/shared.c b/mesalib/src/mesa/main/shared.c
index 5ef88098f..2f73cf3ca 100644
--- a/mesalib/src/mesa/main/shared.c
+++ b/mesalib/src/mesa/main/shared.c
@@ -218,7 +218,8 @@ delete_shader_cb(GLuint id, void *data, void *userData)
{
struct gl_context *ctx = (struct gl_context *) userData;
struct gl_shader *sh = (struct gl_shader *) data;
- if (sh->Type == GL_FRAGMENT_SHADER || sh->Type == GL_VERTEX_SHADER) {
+ if (sh->Type == GL_FRAGMENT_SHADER || sh->Type == GL_VERTEX_SHADER ||
+ sh->Type == GL_GEOMETRY_SHADER) {
ctx->Driver.DeleteShader(ctx, sh);
}
else {
diff --git a/mesalib/src/mesa/main/texobj.c b/mesalib/src/mesa/main/texobj.c
index 334dee77b..7c8f04db9 100644
--- a/mesalib/src/mesa/main/texobj.c
+++ b/mesalib/src/mesa/main/texobj.c
@@ -548,12 +548,13 @@ _mesa_test_texobj_completeness( const struct gl_context *ctx,
ASSERT(maxLevels > 0);
- t->_MaxLevel =
- baseLevel + baseImage->MaxNumLevels - 1; /* 'p' in the GL spec */
- t->_MaxLevel = MIN2(t->_MaxLevel, t->MaxLevel);
- t->_MaxLevel = MIN2(t->_MaxLevel, maxLevels - 1); /* 'q' in the GL spec */
+ t->_MaxLevel = MIN3(t->MaxLevel,
+ /* 'p' in the GL spec */
+ baseLevel + baseImage->MaxNumLevels - 1,
+ /* 'q' in the GL spec */
+ maxLevels - 1);
- /* Compute _MaxLambda = q - b (see the 1.2 spec) used during mipmapping */
+ /* Compute _MaxLambda = q - p in the spec used during mipmapping */
t->_MaxLambda = (GLfloat) (t->_MaxLevel - baseLevel);
if (t->Immutable) {
@@ -1040,23 +1041,35 @@ static void
unbind_texobj_from_fbo(struct gl_context *ctx,
struct gl_texture_object *texObj)
{
- const GLuint n = (ctx->DrawBuffer == ctx->ReadBuffer) ? 1 : 2;
- GLuint i;
+ bool progress = false;
- for (i = 0; i < n; i++) {
- struct gl_framebuffer *fb = (i == 0) ? ctx->DrawBuffer : ctx->ReadBuffer;
- if (_mesa_is_user_fbo(fb)) {
- GLuint j;
- for (j = 0; j < BUFFER_COUNT; j++) {
- if (fb->Attachment[j].Type == GL_TEXTURE &&
- fb->Attachment[j].Texture == texObj) {
- /* Vertices are already flushed by _mesa_DeleteTextures */
- ctx->NewState |= _NEW_BUFFERS;
- _mesa_remove_attachment(ctx, fb->Attachment + j);
- }
- }
- }
+ /* Section 4.4.2 (Attaching Images to Framebuffer Objects), subsection
+ * "Attaching Texture Images to a Framebuffer," of the OpenGL 3.1 spec
+ * says:
+ *
+ * "If a texture object is deleted while its image is attached to one
+ * or more attachment points in the currently bound framebuffer, then
+ * it is as if FramebufferTexture* had been called, with a texture of
+ * zero, for each attachment point to which this image was attached in
+ * the currently bound framebuffer. In other words, this texture image
+ * is first detached from all attachment points in the currently bound
+ * framebuffer. Note that the texture image is specifically not
+ * detached from any other framebuffer objects. Detaching the texture
+ * image from any other framebuffer objects is the responsibility of
+ * the application."
+ */
+ if (_mesa_is_user_fbo(ctx->DrawBuffer)) {
+ progress = _mesa_detach_renderbuffer(ctx, ctx->DrawBuffer, texObj);
}
+ if (_mesa_is_user_fbo(ctx->ReadBuffer)
+ && ctx->ReadBuffer != ctx->DrawBuffer) {
+ progress = _mesa_detach_renderbuffer(ctx, ctx->ReadBuffer, texObj)
+ || progress;
+ }
+
+ if (progress)
+ /* Vertices are already flushed by _mesa_DeleteTextures */
+ ctx->NewState |= _NEW_BUFFERS;
}
diff --git a/mesalib/src/mesa/main/texparam.c b/mesalib/src/mesa/main/texparam.c
index 32109951c..757ae80ec 100644
--- a/mesalib/src/mesa/main/texparam.c
+++ b/mesalib/src/mesa/main/texparam.c
@@ -386,7 +386,13 @@ set_tex_parameteri(struct gl_context *ctx,
return GL_FALSE;
}
incomplete(ctx, texObj);
- texObj->BaseLevel = params[0];
+
+ /** See note about ARB_texture_storage below */
+ if (texObj->Immutable)
+ texObj->BaseLevel = MIN2(texObj->ImmutableLevels - 1, params[0]);
+ else
+ texObj->BaseLevel = params[0];
+
return GL_TRUE;
case GL_TEXTURE_MAX_LEVEL:
@@ -399,7 +405,19 @@ set_tex_parameteri(struct gl_context *ctx,
return GL_FALSE;
}
incomplete(ctx, texObj);
- texObj->MaxLevel = params[0];
+
+ /** From ARB_texture_storage:
+ * However, if TEXTURE_IMMUTABLE_FORMAT is TRUE, then level_base is
+ * clamped to the range [0, <levels> - 1] and level_max is then clamped to
+ * the range [level_base, <levels> - 1], where <levels> is the parameter
+ * passed the call to TexStorage* for the texture object.
+ */
+ if (texObj->Immutable)
+ texObj->MaxLevel = CLAMP(params[0], texObj->BaseLevel,
+ texObj->ImmutableLevels - 1);
+ else
+ texObj->MaxLevel = params[0];
+
return GL_TRUE;
case GL_GENERATE_MIPMAP_SGIS:
diff --git a/mesalib/src/mesa/main/texstate.c b/mesalib/src/mesa/main/texstate.c
index afff01359..dad69a8f6 100644
--- a/mesalib/src/mesa/main/texstate.c
+++ b/mesalib/src/mesa/main/texstate.c
@@ -528,6 +528,7 @@ update_texture_state( struct gl_context *ctx )
GLuint unit;
struct gl_program *fprog = NULL;
struct gl_program *vprog = NULL;
+ struct gl_program *gprog = NULL;
GLbitfield enabledFragUnits = 0x0;
if (ctx->Shader.CurrentVertexProgram &&
@@ -535,6 +536,11 @@ update_texture_state( struct gl_context *ctx )
vprog = ctx->Shader.CurrentVertexProgram->_LinkedShaders[MESA_SHADER_VERTEX]->Program;
}
+ if (ctx->Shader.CurrentGeometryProgram &&
+ ctx->Shader.CurrentGeometryProgram->LinkStatus) {
+ gprog = ctx->Shader.CurrentGeometryProgram->_LinkedShaders[MESA_SHADER_GEOMETRY]->Program;
+ }
+
if (ctx->Shader.CurrentFragmentProgram &&
ctx->Shader.CurrentFragmentProgram->LinkStatus) {
fprog = ctx->Shader.CurrentFragmentProgram->_LinkedShaders[MESA_SHADER_FRAGMENT]->Program;
@@ -543,10 +549,6 @@ update_texture_state( struct gl_context *ctx )
fprog = &ctx->FragmentProgram.Current->Base;
}
- /* FINISHME: Geometry shader texture accesses should also be considered
- * FINISHME: here.
- */
-
/* TODO: only set this if there are actual changes */
ctx->NewState |= _NEW_TEXTURE;
@@ -562,6 +564,7 @@ update_texture_state( struct gl_context *ctx )
struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
GLbitfield enabledVertTargets = 0x0;
GLbitfield enabledFragTargets = 0x0;
+ GLbitfield enabledGeomTargets = 0x0;
GLbitfield enabledTargets = 0x0;
GLuint texIndex;
@@ -575,6 +578,10 @@ update_texture_state( struct gl_context *ctx )
enabledVertTargets |= vprog->TexturesUsed[unit];
}
+ if (gprog) {
+ enabledGeomTargets |= gprog->TexturesUsed[unit];
+ }
+
if (fprog) {
enabledFragTargets |= fprog->TexturesUsed[unit];
}
@@ -583,7 +590,8 @@ update_texture_state( struct gl_context *ctx )
enabledFragTargets |= texUnit->Enabled;
}
- enabledTargets = enabledVertTargets | enabledFragTargets;
+ enabledTargets = enabledVertTargets | enabledFragTargets |
+ enabledGeomTargets;
texUnit->_ReallyEnabled = 0x0;
diff --git a/mesalib/src/mesa/main/varray.c b/mesalib/src/mesa/main/varray.c
index 529d93324..dee476abb 100644
--- a/mesalib/src/mesa/main/varray.c
+++ b/mesalib/src/mesa/main/varray.c
@@ -196,6 +196,16 @@ update_array(struct gl_context *ctx,
if (ctx->Extensions.EXT_vertex_array_bgra &&
sizeMax == BGRA_OR_4 &&
size == GL_BGRA) {
+ /* Page 298 of the PDF of the OpenGL 4.3 (Core Profile) spec says:
+ *
+ * "An INVALID_OPERATION error is generated under any of the following
+ * conditions:
+ * ...
+ * • size is BGRA and type is not UNSIGNED_BYTE, INT_2_10_10_10_REV
+ * or UNSIGNED_INT_2_10_10_10_REV;
+ * ...
+ * • size is BGRA and normalized is FALSE;"
+ */
GLboolean bgra_error = GL_FALSE;
if (ctx->Extensions.ARB_vertex_type_2_10_10_10_rev) {
@@ -207,9 +217,17 @@ update_array(struct gl_context *ctx,
bgra_error = GL_TRUE;
if (bgra_error) {
- _mesa_error(ctx, GL_INVALID_VALUE, "%s(GL_BGRA/GLubyte)", func);
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(size=GL_BGRA and type=%s)",
+ func, _mesa_lookup_enum_by_nr(type));
return;
}
+
+ if (!normalized) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(size=GL_BGRA and normalized=GL_FALSE)", func);
+ return;
+ }
+
format = GL_BGRA;
size = 4;
}
diff --git a/mesalib/src/mesa/main/version.c b/mesalib/src/mesa/main/version.c
index ab9b14c02..55411faf8 100644
--- a/mesalib/src/mesa/main/version.c
+++ b/mesalib/src/mesa/main/version.c
@@ -262,7 +262,6 @@ compute_version(struct gl_context *ctx)
ctx->Extensions.ARB_depth_clamp &&
ctx->Extensions.ARB_draw_elements_base_vertex &&
ctx->Extensions.ARB_fragment_coord_conventions &&
- ctx->Extensions.ARB_geometry_shader4 &&
ctx->Extensions.EXT_provoking_vertex &&
ctx->Extensions.ARB_seamless_cube_map &&
ctx->Extensions.ARB_sync &&