X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fmain%2Ftransformfeedback.c;h=a46c9f94bca63273a57e1bc2ffef630124581e3e;hb=38ab39f6501f78ea7048e8a16a97fdb075b9d8c7;hp=62a40050cefc231895fab06e63d5367fac4a715a;hpb=4f532ab30ed8b5fb1132224323d0d471ae453db6;p=mesa.git diff --git a/src/mesa/main/transformfeedback.c b/src/mesa/main/transformfeedback.c index 62a40050cef..a46c9f94bca 100644 --- a/src/mesa/main/transformfeedback.c +++ b/src/mesa/main/transformfeedback.c @@ -39,7 +39,6 @@ #include "transformfeedback.h" #include "shaderapi.h" #include "shaderobj.h" -#include "main/dispatch.h" #include "program/prog_parameter.h" @@ -201,7 +200,7 @@ _mesa_init_transform_feedback_object(struct gl_transform_feedback_object *obj, /** Default fallback for ctx->Driver.NewTransformFeedback() */ static struct gl_transform_feedback_object * -new_transform_feedback(struct gl_context *ctx, GLuint name) +new_transform_feedback_fallback(struct gl_context *ctx, GLuint name) { struct gl_transform_feedback_object *obj; @@ -215,8 +214,8 @@ new_transform_feedback(struct gl_context *ctx, GLuint name) /** Default fallback for ctx->Driver.DeleteTransformFeedback() */ static void -delete_transform_feedback(struct gl_context *ctx, - struct gl_transform_feedback_object *obj) +delete_transform_feedback_fallback(struct gl_context *ctx, + struct gl_transform_feedback_object *obj) { GLuint i; @@ -231,32 +230,32 @@ delete_transform_feedback(struct gl_context *ctx, /** Default fallback for ctx->Driver.BeginTransformFeedback() */ static void -begin_transform_feedback(struct gl_context *ctx, GLenum mode, - struct gl_transform_feedback_object *obj) +begin_transform_feedback_fallback(struct gl_context *ctx, GLenum mode, + struct gl_transform_feedback_object *obj) { /* nop */ } /** Default fallback for ctx->Driver.EndTransformFeedback() */ static void -end_transform_feedback(struct gl_context *ctx, - struct gl_transform_feedback_object *obj) +end_transform_feedback_fallback(struct gl_context *ctx, + struct gl_transform_feedback_object *obj) { /* nop */ } /** Default fallback for ctx->Driver.PauseTransformFeedback() */ static void -pause_transform_feedback(struct gl_context *ctx, - struct gl_transform_feedback_object *obj) +pause_transform_feedback_fallback(struct gl_context *ctx, + struct gl_transform_feedback_object *obj) { /* nop */ } /** Default fallback for ctx->Driver.ResumeTransformFeedback() */ static void -resume_transform_feedback(struct gl_context *ctx, - struct gl_transform_feedback_object *obj) +resume_transform_feedback_fallback(struct gl_context *ctx, + struct gl_transform_feedback_object *obj) { /* nop */ } @@ -269,12 +268,12 @@ resume_transform_feedback(struct gl_context *ctx, void _mesa_init_transform_feedback_functions(struct dd_function_table *driver) { - driver->NewTransformFeedback = new_transform_feedback; - driver->DeleteTransformFeedback = delete_transform_feedback; - driver->BeginTransformFeedback = begin_transform_feedback; - driver->EndTransformFeedback = end_transform_feedback; - driver->PauseTransformFeedback = pause_transform_feedback; - driver->ResumeTransformFeedback = resume_transform_feedback; + driver->NewTransformFeedback = new_transform_feedback_fallback; + driver->DeleteTransformFeedback = delete_transform_feedback_fallback; + driver->BeginTransformFeedback = begin_transform_feedback_fallback; + driver->EndTransformFeedback = end_transform_feedback_fallback; + driver->PauseTransformFeedback = pause_transform_feedback_fallback; + driver->ResumeTransformFeedback = resume_transform_feedback_fallback; } @@ -346,7 +345,7 @@ _mesa_compute_max_transform_feedback_vertices(struct gl_context *ctx, /* Skip any inactive buffers, which have a stride of 0. */ if (stride == 0) - continue; + continue; max_for_this_buffer = obj->Size[i] / (4 * stride); max_index = MIN2(max_index, max_for_this_buffer); @@ -381,22 +380,22 @@ get_xfb_source(struct gl_context *ctx) } -void GLAPIENTRY -_mesa_BeginTransformFeedback(GLenum mode) +static ALWAYS_INLINE void +begin_transform_feedback(struct gl_context *ctx, GLenum mode, bool no_error) { struct gl_transform_feedback_object *obj; struct gl_transform_feedback_info *info = NULL; + struct gl_program *source; GLuint i; unsigned vertices_per_prim; - GET_CURRENT_CONTEXT(ctx); obj = ctx->TransformFeedback.CurrentObject; /* Figure out what pipeline stage is the source of data for transform * feedback. */ - struct gl_program *source = get_xfb_source(ctx); - if (source == NULL) { + source = get_xfb_source(ctx); + if (!no_error && source == NULL) { _mesa_error(ctx, GL_INVALID_OPERATION, "glBeginTransformFeedback(no program active)"); return; @@ -404,7 +403,7 @@ _mesa_BeginTransformFeedback(GLenum mode) info = source->sh.LinkedTransformFeedback; - if (info->NumOutputs == 0) { + if (!no_error && info->NumOutputs == 0) { _mesa_error(ctx, GL_INVALID_OPERATION, "glBeginTransformFeedback(no varyings to record)"); return; @@ -421,23 +420,30 @@ _mesa_BeginTransformFeedback(GLenum mode) vertices_per_prim = 3; break; default: - _mesa_error(ctx, GL_INVALID_ENUM, "glBeginTransformFeedback(mode)"); - return; + if (!no_error) { + _mesa_error(ctx, GL_INVALID_ENUM, "glBeginTransformFeedback(mode)"); + return; + } else { + /* Stop compiler warnings */ + unreachable("Error in API use when using KHR_no_error"); + } } - if (obj->Active) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glBeginTransformFeedback(already active)"); - return; - } + if (!no_error) { + if (obj->Active) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glBeginTransformFeedback(already active)"); + return; + } - for (i = 0; i < ctx->Const.MaxTransformFeedbackBuffers; i++) { - if ((info->ActiveBuffers >> i) & 1) { - if (obj->BufferNames[i] == 0) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glBeginTransformFeedback(binding point %d does not " - "have a buffer object bound)", i); - return; + for (i = 0; i < ctx->Const.MaxTransformFeedbackBuffers; i++) { + if ((info->ActiveBuffers >> i) & 1) { + if (obj->BufferNames[i] == 0) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glBeginTransformFeedback(binding point %d does not " + "have a buffer object bound)", i); + return; + } } } } @@ -473,19 +479,25 @@ _mesa_BeginTransformFeedback(GLenum mode) void GLAPIENTRY -_mesa_EndTransformFeedback(void) +_mesa_BeginTransformFeedback_no_error(GLenum mode) { - struct gl_transform_feedback_object *obj; GET_CURRENT_CONTEXT(ctx); + begin_transform_feedback(ctx, mode, true); +} - obj = ctx->TransformFeedback.CurrentObject; - if (!obj->Active) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glEndTransformFeedback(not active)"); - return; - } +void GLAPIENTRY +_mesa_BeginTransformFeedback(GLenum mode) +{ + GET_CURRENT_CONTEXT(ctx); + begin_transform_feedback(ctx, mode, false); +} + +static void +end_transform_feedback(struct gl_context *ctx, + struct gl_transform_feedback_object *obj) +{ FLUSH_VERTICES(ctx, 0); ctx->NewDriverState |= ctx->DriverFlags.NewTransformFeedback; @@ -498,6 +510,32 @@ _mesa_EndTransformFeedback(void) } +void GLAPIENTRY +_mesa_EndTransformFeedback_no_error(void) +{ + GET_CURRENT_CONTEXT(ctx); + end_transform_feedback(ctx, ctx->TransformFeedback.CurrentObject); +} + + +void GLAPIENTRY +_mesa_EndTransformFeedback(void) +{ + struct gl_transform_feedback_object *obj; + GET_CURRENT_CONTEXT(ctx); + + obj = ctx->TransformFeedback.CurrentObject; + + if (!obj->Active) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glEndTransformFeedback(not active)"); + return; + } + + end_transform_feedback(ctx, obj); +} + + /** * Helper used by BindBufferRange() and BindBufferBase(). */ @@ -566,7 +604,7 @@ _mesa_validate_buffer_range_xfb(struct gl_context *ctx, _mesa_error(ctx, GL_INVALID_VALUE, "%s(size=%d must be a multiple of " "four)", gl_methd_name, (int) size); return false; - } + } if (offset & 0x3) { /* OpenGL 4.5 core profile, 6.7, pdf page 103: multiple of 4 */ @@ -693,13 +731,13 @@ _mesa_TransformFeedbackBufferBase(GLuint xfb, GLuint index, GLuint buffer) obj = lookup_transform_feedback_object_err(ctx, xfb, "glTransformFeedbackBufferBase"); - if(!obj) { + if (!obj) { return; } bufObj = lookup_transform_feedback_bufferobj_err(ctx, buffer, "glTransformFeedbackBufferBase"); - if(!bufObj) { + if (!bufObj) { return; } @@ -716,13 +754,13 @@ _mesa_TransformFeedbackBufferRange(GLuint xfb, GLuint index, GLuint buffer, obj = lookup_transform_feedback_object_err(ctx, xfb, "glTransformFeedbackBufferRange"); - if(!obj) { + if (!obj) { return; } bufObj = lookup_transform_feedback_bufferobj_err(ctx, buffer, "glTransformFeedbackBufferRange"); - if(!bufObj) { + if (!bufObj) { return; } @@ -740,12 +778,43 @@ _mesa_TransformFeedbackBufferRange(GLuint xfb, GLuint index, GLuint buffer, * offset in the buffer to start placing results. * This function is part of GL_EXT_transform_feedback, but not GL3. */ +static ALWAYS_INLINE void +bind_buffer_offset(struct gl_context *ctx, + struct gl_transform_feedback_object *obj, GLuint index, + GLuint buffer, GLintptr offset, bool no_error) +{ + struct gl_buffer_object *bufObj; + + if (buffer == 0) { + bufObj = ctx->Shared->NullBufferObj; + } else { + bufObj = _mesa_lookup_bufferobj(ctx, buffer); + if (!no_error && !bufObj) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glBindBufferOffsetEXT(invalid buffer=%u)", buffer); + return; + } + } + + _mesa_bind_buffer_range_xfb(ctx, obj, index, bufObj, offset, 0); +} + + +void GLAPIENTRY +_mesa_BindBufferOffsetEXT_no_error(GLenum target, GLuint index, GLuint buffer, + GLintptr offset) +{ + GET_CURRENT_CONTEXT(ctx); + bind_buffer_offset(ctx, ctx->TransformFeedback.CurrentObject, index, buffer, + offset, true); +} + + void GLAPIENTRY _mesa_BindBufferOffsetEXT(GLenum target, GLuint index, GLuint buffer, GLintptr offset) { struct gl_transform_feedback_object *obj; - struct gl_buffer_object *bufObj; GET_CURRENT_CONTEXT(ctx); if (target != GL_TRANSFORM_FEEDBACK_BUFFER) { @@ -774,26 +843,61 @@ _mesa_BindBufferOffsetEXT(GLenum target, GLuint index, GLuint buffer, return; } - if (buffer == 0) { - bufObj = ctx->Shared->NullBufferObj; - } else { - bufObj = _mesa_lookup_bufferobj(ctx, buffer); + bind_buffer_offset(ctx, obj, index, buffer, offset, false); +} + + +/** + * This function specifies the transform feedback outputs to be written + * to the feedback buffer(s), and in what order. + */ +static ALWAYS_INLINE void +transform_feedback_varyings(struct gl_context *ctx, + struct gl_shader_program *shProg, GLsizei count, + const GLchar *const *varyings, GLenum bufferMode) +{ + GLint i; + + /* free existing varyings, if any */ + for (i = 0; i < (GLint) shProg->TransformFeedback.NumVarying; i++) { + free(shProg->TransformFeedback.VaryingNames[i]); } + free(shProg->TransformFeedback.VaryingNames); - if (!bufObj) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glBindBufferOffsetEXT(invalid buffer=%u)", buffer); + /* allocate new memory for varying names */ + shProg->TransformFeedback.VaryingNames = + malloc(count * sizeof(GLchar *)); + + if (!shProg->TransformFeedback.VaryingNames) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTransformFeedbackVaryings()"); return; } - _mesa_bind_buffer_range_xfb(ctx, obj, index, bufObj, offset, 0); + /* Save the new names and the count */ + for (i = 0; i < count; i++) { + shProg->TransformFeedback.VaryingNames[i] = strdup(varyings[i]); + } + shProg->TransformFeedback.NumVarying = count; + + shProg->TransformFeedback.BufferMode = bufferMode; + + /* No need to invoke FLUSH_VERTICES or flag NewTransformFeedback since + * the varyings won't be used until shader link time. + */ } -/** - * This function specifies the transform feedback outputs to be written - * to the feedback buffer(s), and in what order. - */ +void GLAPIENTRY +_mesa_TransformFeedbackVaryings_no_error(GLuint program, GLsizei count, + const GLchar *const *varyings, + GLenum bufferMode) +{ + GET_CURRENT_CONTEXT(ctx); + + struct gl_shader_program *shProg = _mesa_lookup_shader_program(ctx, program); + transform_feedback_varyings(ctx, shProg, count, varyings, bufferMode); +} + void GLAPIENTRY _mesa_TransformFeedbackVaryings(GLuint program, GLsizei count, const GLchar * const *varyings, @@ -869,32 +973,7 @@ _mesa_TransformFeedbackVaryings(GLuint program, GLsizei count, } } - /* free existing varyings, if any */ - for (i = 0; i < (GLint) shProg->TransformFeedback.NumVarying; i++) { - free(shProg->TransformFeedback.VaryingNames[i]); - } - free(shProg->TransformFeedback.VaryingNames); - - /* allocate new memory for varying names */ - shProg->TransformFeedback.VaryingNames = - malloc(count * sizeof(GLchar *)); - - if (!shProg->TransformFeedback.VaryingNames) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTransformFeedbackVaryings()"); - return; - } - - /* Save the new names and the count */ - for (i = 0; i < count; i++) { - shProg->TransformFeedback.VaryingNames[i] = strdup(varyings[i]); - } - shProg->TransformFeedback.NumVarying = count; - - shProg->TransformFeedback.BufferMode = bufferMode; - - /* No need to invoke FLUSH_VERTICES or flag NewTransformFeedback since - * the varyings won't be used until shader link time. - */ + transform_feedback_varyings(ctx, shProg, count, varyings, bufferMode); } @@ -1063,10 +1142,34 @@ _mesa_IsTransformFeedback(GLuint name) * Bind the given transform feedback object. * Part of GL_ARB_transform_feedback2. */ +static ALWAYS_INLINE void +bind_transform_feedback(struct gl_context *ctx, GLuint name, bool no_error) +{ + struct gl_transform_feedback_object *obj; + + obj = _mesa_lookup_transform_feedback_object(ctx, name); + if (!no_error && !obj) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glBindTransformFeedback(name=%u)", name); + return; + } + + reference_transform_feedback_object(&ctx->TransformFeedback.CurrentObject, + obj); +} + + +void GLAPIENTRY +_mesa_BindTransformFeedback_no_error(GLenum target, GLuint name) +{ + GET_CURRENT_CONTEXT(ctx); + bind_transform_feedback(ctx, name, true); +} + + void GLAPIENTRY _mesa_BindTransformFeedback(GLenum target, GLuint name) { - struct gl_transform_feedback_object *obj; GET_CURRENT_CONTEXT(ctx); if (target != GL_TRANSFORM_FEEDBACK) { @@ -1080,15 +1183,7 @@ _mesa_BindTransformFeedback(GLenum target, GLuint name) return; } - obj = _mesa_lookup_transform_feedback_object(ctx, name); - if (!obj) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glBindTransformFeedback(name=%u)", name); - return; - } - - reference_transform_feedback_object(&ctx->TransformFeedback.CurrentObject, - obj); + bind_transform_feedback(ctx, name, false); } @@ -1139,6 +1234,28 @@ _mesa_DeleteTransformFeedbacks(GLsizei n, const GLuint *names) * Pause transform feedback. * Part of GL_ARB_transform_feedback2. */ +static void +pause_transform_feedback(struct gl_context *ctx, + struct gl_transform_feedback_object *obj) +{ + FLUSH_VERTICES(ctx, 0); + ctx->NewDriverState |= ctx->DriverFlags.NewTransformFeedback; + + assert(ctx->Driver.PauseTransformFeedback); + ctx->Driver.PauseTransformFeedback(ctx, obj); + + obj->Paused = GL_TRUE; +} + + +void GLAPIENTRY +_mesa_PauseTransformFeedback_no_error(void) +{ + GET_CURRENT_CONTEXT(ctx); + pause_transform_feedback(ctx, ctx->TransformFeedback.CurrentObject); +} + + void GLAPIENTRY _mesa_PauseTransformFeedback(void) { @@ -1153,13 +1270,7 @@ _mesa_PauseTransformFeedback(void) return; } - FLUSH_VERTICES(ctx, 0); - ctx->NewDriverState |= ctx->DriverFlags.NewTransformFeedback; - - assert(ctx->Driver.PauseTransformFeedback); - ctx->Driver.PauseTransformFeedback(ctx, obj); - - obj->Paused = GL_TRUE; + pause_transform_feedback(ctx, obj); } @@ -1167,6 +1278,28 @@ _mesa_PauseTransformFeedback(void) * Resume transform feedback. * Part of GL_ARB_transform_feedback2. */ +static void +resume_transform_feedback(struct gl_context *ctx, + struct gl_transform_feedback_object *obj) +{ + FLUSH_VERTICES(ctx, 0); + ctx->NewDriverState |= ctx->DriverFlags.NewTransformFeedback; + + obj->Paused = GL_FALSE; + + assert(ctx->Driver.ResumeTransformFeedback); + ctx->Driver.ResumeTransformFeedback(ctx, obj); +} + + +void GLAPIENTRY +_mesa_ResumeTransformFeedback_no_error(void) +{ + GET_CURRENT_CONTEXT(ctx); + resume_transform_feedback(ctx, ctx->TransformFeedback.CurrentObject); +} + + void GLAPIENTRY _mesa_ResumeTransformFeedback(void) { @@ -1192,13 +1325,7 @@ _mesa_ResumeTransformFeedback(void) return; } - FLUSH_VERTICES(ctx, 0); - ctx->NewDriverState |= ctx->DriverFlags.NewTransformFeedback; - - obj->Paused = GL_FALSE; - - assert(ctx->Driver.ResumeTransformFeedback); - ctx->Driver.ResumeTransformFeedback(ctx, obj); + resume_transform_feedback(ctx, obj); } extern void GLAPIENTRY @@ -1209,7 +1336,7 @@ _mesa_GetTransformFeedbackiv(GLuint xfb, GLenum pname, GLint *param) obj = lookup_transform_feedback_object_err(ctx, xfb, "glGetTransformFeedbackiv"); - if(!obj) { + if (!obj) { return; } @@ -1235,7 +1362,7 @@ _mesa_GetTransformFeedbacki_v(GLuint xfb, GLenum pname, GLuint index, obj = lookup_transform_feedback_object_err(ctx, xfb, "glGetTransformFeedbacki_v"); - if(!obj) { + if (!obj) { return; } @@ -1264,7 +1391,7 @@ _mesa_GetTransformFeedbacki64_v(GLuint xfb, GLenum pname, GLuint index, obj = lookup_transform_feedback_object_err(ctx, xfb, "glGetTransformFeedbacki64_v"); - if(!obj) { + if (!obj) { return; } @@ -1274,12 +1401,34 @@ _mesa_GetTransformFeedbacki64_v(GLuint xfb, GLenum pname, GLuint index, return; } + /** + * This follows the same general rules used for BindBufferBase: + * + * "To query the starting offset or size of the range of a buffer + * object binding in an indexed array, call GetInteger64i_v with + * target set to respectively the starting offset or binding size + * name from table 6.5 for that array. Index must be in the range + * zero to the number of bind points supported minus one. If the + * starting offset or size was not specified when the buffer object + * was bound (e.g. if it was bound with BindBufferBase), or if no + * buffer object is bound to the target array at index, zero is + * returned." + */ + if (obj->RequestedSize[index] == 0 && + (pname == GL_TRANSFORM_FEEDBACK_BUFFER_START || + pname == GL_TRANSFORM_FEEDBACK_BUFFER_SIZE)) { + *param = 0; + return; + } + compute_transform_feedback_buffer_sizes(obj); switch(pname) { case GL_TRANSFORM_FEEDBACK_BUFFER_START: + assert(obj->RequestedSize[index] > 0); *param = obj->Offset[index]; break; case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE: + assert(obj->RequestedSize[index] > 0); *param = obj->Size[index]; break; default: