diff options
Diffstat (limited to 'mesalib/src/mesa/main')
-rw-r--r-- | mesalib/src/mesa/main/api_validate.c | 70 | ||||
-rw-r--r-- | mesalib/src/mesa/main/context.h | 11 | ||||
-rw-r--r-- | mesalib/src/mesa/main/fbobject.c | 187 | ||||
-rw-r--r-- | mesalib/src/mesa/main/fbobject.h | 6 | ||||
-rw-r--r-- | mesalib/src/mesa/main/get.c | 2 | ||||
-rw-r--r-- | mesalib/src/mesa/main/lines.c | 3 | ||||
-rw-r--r-- | mesalib/src/mesa/main/mtypes.h | 80 | ||||
-rw-r--r-- | mesalib/src/mesa/main/shaderapi.c | 48 | ||||
-rw-r--r-- | mesalib/src/mesa/main/shaderapi.h | 5 | ||||
-rw-r--r-- | mesalib/src/mesa/main/shared.c | 3 | ||||
-rw-r--r-- | mesalib/src/mesa/main/texobj.c | 53 | ||||
-rw-r--r-- | mesalib/src/mesa/main/texparam.c | 22 | ||||
-rw-r--r-- | mesalib/src/mesa/main/texstate.c | 18 | ||||
-rw-r--r-- | mesalib/src/mesa/main/varray.c | 20 | ||||
-rw-r--r-- | mesalib/src/mesa/main/version.c | 1 |
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 && |