/** * Is 'mode' a valid value for glBegin(), glDrawArrays(), glDrawElements(), * etc? Also, do additional checking related to transformation feedback. * Note: this function cannot be called during glNewList(GL_COMPILE) because * this code depends on current transform feedback state. */ GLboolean _mesa_valid_prim_mode(struct gl_context *ctx, GLenum mode, const char *name) { bool valid_enum = _mesa_is_valid_prim_mode(ctx, mode); if (!valid_enum) { _mesa_error(ctx, GL_INVALID_ENUM, "%s(mode=%x)", name, mode); return GL_FALSE; } /* From the GL_EXT_transform_feedback spec: * * "The error INVALID_OPERATION is generated if Begin, or any command * that performs an explicit Begin, is called when: * * * a geometry shader is not active and <mode> does not match the * allowed begin modes for the current transform feedback state as * given by table X.1. * * * a geometry shader is active and the output primitive type of the * geometry shader does not match the allowed begin modes for the * current transform feedback state as given by table X.1. * */ if (_mesa_is_xfb_active_and_unpaused(ctx)) { GLboolean pass = GL_TRUE; switch (mode) { case GL_POINTS: pass = ctx->TransformFeedback.Mode == GL_POINTS; break; case GL_LINES: case GL_LINE_STRIP: case GL_LINE_LOOP: pass = ctx->TransformFeedback.Mode == GL_LINES; break; default: pass = ctx->TransformFeedback.Mode == GL_TRIANGLES; break; } if (!pass) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(mode=%s vs transform feedback %s)", name, _mesa_lookup_prim_by_nr(mode), _mesa_lookup_prim_by_nr(ctx->TransformFeedback.Mode)); return GL_FALSE; } } return GL_TRUE; }
static void vbo_print_vertex_list(struct gl_context *ctx, void *data, FILE *f) { struct vbo_save_vertex_list *node = (struct vbo_save_vertex_list *) data; GLuint i; struct gl_buffer_object *buffer = node->vertex_store ? node->vertex_store->bufferobj : NULL; (void) ctx; fprintf(f, "VBO-VERTEX-LIST, %u vertices %d primitives, %d vertsize " "buffer %p\n", node->count, node->prim_count, node->vertex_size, buffer); for (i = 0; i < node->prim_count; i++) { struct _mesa_prim *prim = &node->prim[i]; fprintf(f, " prim %d: %s%s %d..%d %s %s\n", i, _mesa_lookup_prim_by_nr(prim->mode), prim->weak ? " (weak)" : "", prim->start, prim->start + prim->count, (prim->begin) ? "BEGIN" : "(wrap)", (prim->end) ? "END" : "(wrap)"); } }
static void vbo_print_vertex_list(struct gl_context *ctx, void *data) { struct vbo_save_vertex_list *node = (struct vbo_save_vertex_list *) data; GLuint i; (void) ctx; printf("VBO-VERTEX-LIST, %u vertices %d primitives, %d vertsize\n", node->count, node->prim_count, node->vertex_size); for (i = 0; i < node->prim_count; i++) { struct _mesa_prim *prim = &node->prim[i]; _mesa_debug(NULL, " prim %d: %s%s %d..%d %s %s\n", i, _mesa_lookup_prim_by_nr(prim->mode), prim->weak ? " (weak)" : "", prim->start, prim->start + prim->count, (prim->begin) ? "BEGIN" : "(wrap)", (prim->end) ? "END" : "(wrap)"); } }
static void vbo_exec_debug_verts(struct vbo_exec_context *exec) { GLuint count = exec->vtx.vert_count; GLuint i; printf("%s: %u vertices %d primitives, %d vertsize\n", __func__, count, exec->vtx.prim_count, exec->vtx.vertex_size); for (i = 0 ; i < exec->vtx.prim_count ; i++) { struct _mesa_prim *prim = &exec->vtx.prim[i]; printf(" prim %d: %s %d..%d %s %s\n", i, _mesa_lookup_prim_by_nr(prim->mode), prim->start, prim->start + prim->count, prim->begin ? "BEGIN" : "(wrap)", prim->end ? "END" : "(wrap)"); } }
/** * Is 'mode' a valid value for glBegin(), glDrawArrays(), glDrawElements(), * etc? Also, do additional checking related to transformation feedback. * Note: this function cannot be called during glNewList(GL_COMPILE) because * this code depends on current transform feedback state. * Also, do additional checking related to tessellation shaders. */ GLboolean _mesa_valid_prim_mode(struct gl_context *ctx, GLenum mode, const char *name) { bool valid_enum = _mesa_is_valid_prim_mode(ctx, mode); if (!valid_enum) { _mesa_error(ctx, GL_INVALID_ENUM, "%s(mode=%x)", name, mode); return GL_FALSE; } /* From the OpenGL 4.5 specification, section 11.3.1: * * 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. * * The GL spec doesn't mention any interaction with tessellation, which * is clearly a spec bug. The same rule should apply, but instead of * the draw primitive mode, the tessellation evaluation shader primitive * mode should be used for the checking. */ if (ctx->_Shader->CurrentProgram[MESA_SHADER_GEOMETRY]) { const GLenum geom_mode = ctx->_Shader->CurrentProgram[MESA_SHADER_GEOMETRY]-> _LinkedShaders[MESA_SHADER_GEOMETRY]->Geom.InputType; struct gl_shader_program *tes = ctx->_Shader->CurrentProgram[MESA_SHADER_TESS_EVAL]; GLenum mode_before_gs = mode; if (tes) { struct gl_shader *tes_sh = tes->_LinkedShaders[MESA_SHADER_TESS_EVAL]; if (tes_sh->TessEval.PointMode) mode_before_gs = GL_POINTS; else if (tes_sh->TessEval.PrimitiveMode == GL_ISOLINES) mode_before_gs = GL_LINES; else /* the GL_QUADS mode generates triangles too */ mode_before_gs = GL_TRIANGLES; } switch (mode_before_gs) { 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_before_gs), _mesa_lookup_prim_by_nr(geom_mode)); return GL_FALSE; } } /* From the OpenGL 4.0 (Core Profile) spec (section 2.12): * * "Tessellation operates only on patch primitives. If tessellation is * active, any command that transfers vertices to the GL will * generate an INVALID_OPERATION error if the primitive mode is not * PATCHES. * Patch primitives are not supported by pipeline stages below the * tessellation evaluation shader. If there is no active program * object or the active program object does not contain a tessellation * evaluation shader, the error INVALID_OPERATION is generated by any * command that transfers vertices to the GL if the primitive mode is * PATCHES." * */ if (ctx->_Shader->CurrentProgram[MESA_SHADER_TESS_EVAL] || ctx->_Shader->CurrentProgram[MESA_SHADER_TESS_CTRL]) { if (mode != GL_PATCHES) { _mesa_error(ctx, GL_INVALID_OPERATION, "only GL_PATCHES valid with tessellation"); return GL_FALSE; } } else { if (mode == GL_PATCHES) { _mesa_error(ctx, GL_INVALID_OPERATION, "GL_PATCHES only valid with tessellation"); return GL_FALSE; } } /* From the GL_EXT_transform_feedback spec: * * "The error INVALID_OPERATION is generated if Begin, or any command * that performs an explicit Begin, is called when: * * * a geometry shader is not active and <mode> does not match the * allowed begin modes for the current transform feedback state as * given by table X.1. * * * a geometry shader is active and the output primitive type of the * geometry shader does not match the allowed begin modes for the * current transform feedback state as given by table X.1. * */ if (_mesa_is_xfb_active_and_unpaused(ctx)) { GLboolean pass = GL_TRUE; if(ctx->_Shader->CurrentProgram[MESA_SHADER_GEOMETRY]) { switch (ctx->_Shader->CurrentProgram[MESA_SHADER_GEOMETRY]-> _LinkedShaders[MESA_SHADER_GEOMETRY]->Geom.OutputType) { case GL_POINTS: pass = ctx->TransformFeedback.Mode == GL_POINTS; break; case GL_LINE_STRIP: pass = ctx->TransformFeedback.Mode == GL_LINES; break; case GL_TRIANGLE_STRIP: pass = ctx->TransformFeedback.Mode == GL_TRIANGLES; break; default: pass = GL_FALSE; } } else if (ctx->_Shader->CurrentProgram[MESA_SHADER_TESS_EVAL]) { struct gl_shader_program *tes = ctx->_Shader->CurrentProgram[MESA_SHADER_TESS_EVAL]; struct gl_shader *tes_sh = tes->_LinkedShaders[MESA_SHADER_TESS_EVAL]; if (tes_sh->TessEval.PointMode) pass = ctx->TransformFeedback.Mode == GL_POINTS; else if (tes_sh->TessEval.PrimitiveMode == GL_ISOLINES) pass = ctx->TransformFeedback.Mode == GL_LINES; else pass = ctx->TransformFeedback.Mode == GL_TRIANGLES; } else { switch (mode) { case GL_POINTS: pass = ctx->TransformFeedback.Mode == GL_POINTS; break; case GL_LINES: case GL_LINE_STRIP: case GL_LINE_LOOP: pass = ctx->TransformFeedback.Mode == GL_LINES; break; default: pass = ctx->TransformFeedback.Mode == GL_TRIANGLES; break; } } if (!pass) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(mode=%s vs transform feedback %s)", name, _mesa_lookup_prim_by_nr(mode), _mesa_lookup_prim_by_nr(ctx->TransformFeedback.Mode)); return GL_FALSE; } } return GL_TRUE; }
/** * Is 'mode' a valid value for glBegin(), glDrawArrays(), glDrawElements(), * etc? Also, do additional checking related to transformation feedback. * Note: this function cannot be called during glNewList(GL_COMPILE) because * this code depends on current transform feedback state. */ GLboolean _mesa_valid_prim_mode(struct gl_context *ctx, GLenum mode, const char *name) { bool valid_enum = _mesa_is_valid_prim_mode(ctx, mode); if (!valid_enum) { _mesa_error(ctx, GL_INVALID_ENUM, "%s(mode=%x)", name, mode); 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 * that performs an explicit Begin, is called when: * * * a geometry shader is not active and <mode> does not match the * allowed begin modes for the current transform feedback state as * given by table X.1. * * * a geometry shader is active and the output primitive type of the * geometry shader does not match the allowed begin modes for the * current transform feedback state as given by table X.1. * */ if (_mesa_is_xfb_active_and_unpaused(ctx)) { GLboolean pass = GL_TRUE; switch (mode) { case GL_POINTS: pass = ctx->TransformFeedback.Mode == GL_POINTS; break; case GL_LINES: case GL_LINE_STRIP: case GL_LINE_LOOP: pass = ctx->TransformFeedback.Mode == GL_LINES; break; default: pass = ctx->TransformFeedback.Mode == GL_TRIANGLES; break; } if (!pass) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(mode=%s vs transform feedback %s)", name, _mesa_lookup_prim_by_nr(mode), _mesa_lookup_prim_by_nr(ctx->TransformFeedback.Mode)); return GL_FALSE; } } return GL_TRUE; }