struct using_program_tuple
{
- struct gl_shader_program *shProg;
+ struct gl_program *prog;
bool found;
};
{
struct using_program_tuple *callback_data = user_data;
struct gl_transform_feedback_object *obj = data;
- if (obj->Active && obj->shader_program == callback_data->shProg)
+ if (obj->Active && obj->program == callback_data->prog)
callback_data->found = true;
}
_mesa_transform_feedback_is_using_program(struct gl_context *ctx,
struct gl_shader_program *shProg)
{
+ if (!shProg->last_vert_prog)
+ return false;
+
struct using_program_tuple callback_data;
- callback_data.shProg = shProg;
callback_data.found = false;
+ callback_data.prog = shProg->last_vert_prog;
- _mesa_HashWalk(ctx->TransformFeedback.Objects,
- active_xfb_object_references_program, &callback_data);
+ _mesa_HashWalkLocked(ctx->TransformFeedback.Objects,
+ active_xfb_object_references_program, &callback_data);
/* Also check DefaultObject, as it's not in the Objects hash table. */
active_xfb_object_references_program(0, ctx->TransformFeedback.DefaultObject,
assert(!*ptr);
if (obj) {
+ assert(obj->RefCount > 0);
+
/* reference new object */
- if (obj->RefCount == 0) {
- _mesa_problem(NULL, "referencing deleted transform feedback object");
- *ptr = NULL;
- }
- else {
- obj->RefCount++;
- obj->EverBound = GL_TRUE;
- *ptr = obj;
- }
+ obj->RefCount++;
+ obj->EverBound = GL_TRUE;
+ *ptr = obj;
}
}
* enabled transform feedback buffers without overflowing any of them.
*/
unsigned
-_mesa_compute_max_transform_feedback_vertices(
+_mesa_compute_max_transform_feedback_vertices(struct gl_context *ctx,
const struct gl_transform_feedback_object *obj,
const struct gl_transform_feedback_info *info)
{
unsigned max_index = 0xffffffff;
unsigned i;
- for (i = 0; i < info->NumBuffers; ++i) {
- unsigned stride = info->BufferStride[i];
- unsigned max_for_this_buffer;
+ for (i = 0; i < ctx->Const.MaxTransformFeedbackBuffers; i++) {
+ if ((info->ActiveBuffers >> i) & 1) {
+ unsigned stride = info->Buffers[i].Stride;
+ unsigned max_for_this_buffer;
- /* Skip any inactive buffers, which have a stride of 0. */
- if (stride == 0)
- continue;
+ /* Skip any inactive buffers, which have a stride of 0. */
+ if (stride == 0)
+ continue;
- max_for_this_buffer = obj->Size[i] / (4 * stride);
- max_index = MIN2(max_index, max_for_this_buffer);
+ max_for_this_buffer = obj->Size[i] / (4 * stride);
+ max_index = MIN2(max_index, max_for_this_buffer);
+ }
}
return max_index;
/**
* Figure out which stage of the pipeline is the source of transform feedback
- * data given the current context state, and return its gl_shader_program.
+ * data given the current context state, and return its gl_program.
*
* If no active program can generate transform feedback data (i.e. no vertex
* shader is active), returns NULL.
*/
-static struct gl_shader_program *
+static struct gl_program *
get_xfb_source(struct gl_context *ctx)
{
int i;
{
struct gl_transform_feedback_object *obj;
struct gl_transform_feedback_info *info = NULL;
- struct gl_shader_program *source;
GLuint i;
unsigned vertices_per_prim;
GET_CURRENT_CONTEXT(ctx);
/* Figure out what pipeline stage is the source of data for transform
* feedback.
*/
- source = get_xfb_source(ctx);
+ struct gl_program *source = get_xfb_source(ctx);
if (source == NULL) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glBeginTransformFeedback(no program active)");
return;
}
- info = &source->LinkedTransformFeedback;
+ info = source->sh.LinkedTransformFeedback;
if (info->NumOutputs == 0) {
_mesa_error(ctx, GL_INVALID_OPERATION,
return;
}
- for (i = 0; i < info->NumBuffers; ++i) {
- 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;
+ }
}
}
* feedback.
*/
unsigned max_vertices
- = _mesa_compute_max_transform_feedback_vertices(obj, info);
+ = _mesa_compute_max_transform_feedback_vertices(ctx, obj, info);
obj->GlesRemainingPrims = max_vertices / vertices_per_prim;
}
- if (obj->shader_program != source) {
+ if (obj->program != source) {
ctx->NewDriverState |= ctx->DriverFlags.NewTransformFeedbackProg;
- obj->shader_program = source;
+ obj->program = source;
}
assert(ctx->Driver.BeginTransformFeedback);
FLUSH_VERTICES(ctx, 0);
ctx->NewDriverState |= ctx->DriverFlags.NewTransformFeedback;
+ assert(ctx->Driver.EndTransformFeedback);
+ ctx->Driver.EndTransformFeedback(ctx, obj);
+
ctx->TransformFeedback.CurrentObject->Active = GL_FALSE;
ctx->TransformFeedback.CurrentObject->Paused = GL_FALSE;
ctx->TransformFeedback.CurrentObject->EndedAnytime = GL_TRUE;
-
- assert(ctx->Driver.EndTransformFeedback);
- ctx->Driver.EndTransformFeedback(ctx, obj);
}
/**
- * Specify a buffer object to receive transform feedback results. Plus,
- * specify the starting offset to place the results, and max size.
+ * Validate the buffer object to receive transform feedback results. Plus,
+ * validate the starting offset to place the results, and max size.
* Called from the glBindBufferRange() and glTransformFeedbackBufferRange
* functions.
*/
-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,
- bool dsa)
+bool
+_mesa_validate_buffer_range_xfb(struct gl_context *ctx,
+ struct gl_transform_feedback_object *obj,
+ GLuint index, struct gl_buffer_object *bufObj,
+ GLintptr offset, GLsizeiptr size, bool dsa)
{
const char *gl_methd_name;
if (dsa)
if (obj->Active) {
_mesa_error(ctx, GL_INVALID_OPERATION, "%s(transform feedback active)",
gl_methd_name);
- return;
+ return false;
}
if (index >= ctx->Const.MaxTransformFeedbackBuffers) {
*/
_mesa_error(ctx, GL_INVALID_VALUE, "%s(index=%d out of bounds)",
gl_methd_name, index);
- return;
+ return false;
}
if (size & 0x3) {
/* 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;
+ return false;
}
if (offset & 0x3) {
/* 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;
+ return false;
}
if (offset < 0) {
_mesa_error(ctx, GL_INVALID_VALUE, "%s(offset=%d must be >= 0)",
gl_methd_name,
(int) offset);
- return;
+ return false;
}
if (size <= 0 && (dsa || bufObj != ctx->Shared->NullBufferObj)) {
*/
_mesa_error(ctx, GL_INVALID_VALUE, "%s(size=%d must be > 0)",
gl_methd_name, (int) size);
- return;
+ return false;
}
- bind_buffer_range(ctx, obj, index, bufObj, offset, size, dsa);
+ return true;
}
return;
}
- _mesa_bind_buffer_range_transform_feedback(ctx, obj, index, bufObj, offset,
- size, true);
+ if (!_mesa_validate_buffer_range_xfb(ctx, obj, index, bufObj, offset,
+ size, true))
+ return;
+
+ /* The per-attribute binding point */
+ _mesa_set_transform_feedback_binding(ctx, obj, index, bufObj, offset,
+ size);
}
/**
return;
}
- bind_buffer_range(ctx, obj, index, bufObj, offset, 0, false);
+ _mesa_bind_buffer_range_xfb(ctx, obj, index, bufObj, offset, 0);
}
return;
}
- shProg = _mesa_lookup_shader_program(ctx, program);
- if (!shProg) {
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glTransformFeedbackVaryings(program=%u)", program);
+ shProg = _mesa_lookup_shader_program_err(ctx, program,
+ "glTransformFeedbackVaryings");
+ if (!shProg)
return;
- }
if (ctx->Extensions.ARB_transform_feedback3) {
if (bufferMode == GL_INTERLEAVED_ATTRIBS) {
struct gl_program_resource *res;
GET_CURRENT_CONTEXT(ctx);
- shProg = _mesa_lookup_shader_program(ctx, program);
- if (!shProg) {
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glGetTransformFeedbackVarying(program=%u)", program);
+ shProg = _mesa_lookup_shader_program_err(ctx, program,
+ "glGetTransformFeedbackVarying");
+ if (!shProg)
return;
- }
res = _mesa_program_resource_find_index((struct gl_shader_program *) shProg,
GL_TRANSFORM_FEEDBACK_VARYING,
}
else
return (struct gl_transform_feedback_object *)
- _mesa_HashLookup(ctx->TransformFeedback.Objects, name);
+ _mesa_HashLookupLocked(ctx->TransformFeedback.Objects, name);
}
static void
return;
}
ids[i] = first + i;
- _mesa_HashInsert(ctx->TransformFeedback.Objects, first + i, obj);
+ _mesa_HashInsertLocked(ctx->TransformFeedback.Objects, first + i,
+ obj);
if (dsa) {
/* this is normally done at bind time in the non-dsa case */
obj->EverBound = GL_TRUE;
names[i]);
return;
}
- _mesa_HashRemove(ctx->TransformFeedback.Objects, names[i]);
+ _mesa_HashRemoveLocked(ctx->TransformFeedback.Objects, names[i]);
/* unref, but object may not be deleted until later */
+ if (obj == ctx->TransformFeedback.CurrentObject) {
+ reference_transform_feedback_object(
+ &ctx->TransformFeedback.CurrentObject,
+ ctx->TransformFeedback.DefaultObject);
+ }
reference_transform_feedback_object(&obj, NULL);
}
}
FLUSH_VERTICES(ctx, 0);
ctx->NewDriverState |= ctx->DriverFlags.NewTransformFeedback;
- obj->Paused = GL_TRUE;
-
assert(ctx->Driver.PauseTransformFeedback);
ctx->Driver.PauseTransformFeedback(ctx, obj);
+
+ obj->Paused = GL_TRUE;
}
* the program object being used by the current transform feedback object
* is not active."
*/
- if (obj->shader_program != get_xfb_source(ctx)) {
+ if (obj->program != get_xfb_source(ctx)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glResumeTransformFeedback(wrong program bound)");
return;
return;
}
+ compute_transform_feedback_buffer_sizes(obj);
switch(pname) {
case GL_TRANSFORM_FEEDBACK_BUFFER_START:
*param = obj->Offset[index];
break;
case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
- *param = obj->RequestedSize[index];
+ *param = obj->Size[index];
break;
default:
_mesa_error(ctx, GL_INVALID_ENUM,