#include "trace_parser.hpp"
#include "trace_writer.hpp"
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define STRNCMP_LITERAL(var, literal) strncmp((var), (literal), sizeof (literal) -1)
static const char *synopsis = "Create a new trace by trimming an existing trace.";
bool transformFeedbackActive;
bool framebufferObjectActive;
bool insideBeginEnd;
+ GLuint insideNewEndList;
GLuint activeProgram;
GLenum activeTextureUnit;
}
return;
}
+
+ if (strcmp(name, "glNewList") == 0) {
+ GLuint list = call->arg(0).toUInt();
+
+ insideNewEndList = list;
+ }
}
void stateTrackPostCall(trace::Call *call) {
resources.erase("framebuffer");
return;
}
+
+ if (strcmp(name, "glEndList") == 0) {
+ insideNewEndList = 0;
+ }
}
void recordSideEffects(trace::Call *call) {
const char *name = call->name();
+ /* Handle display lists before any other processing. */
+
+ /* FIXME: If we encode the list of commands that are executed
+ * immediately (as opposed to those that are compiled into a
+ * display list) then we could generate a "display-list-X"
+ * resource just as we do for "texture-X" resources and only
+ * emit it in the trace if a glCallList(X) is emitted. For
+ * now, simply punt and include anything within glNewList and
+ * glEndList in the trim output. This guarantees that display
+ * lists will work, but does not trim out unused display
+ * lists. */
+ if (insideNewEndList != 0) {
+ provide("state", call->no);
+ return;
+ }
+
/* If call is flagged as no side effects, then we are done here. */
if (call->flags & trace::CALL_FLAG_NO_SIDE_EFFECTS) {
return;
strcmp(call->sig->arg_names[0], "location") == 0) {
providef("program-", activeProgram, call->no);
+
+ /* We can't easily tell if this uniform is being used to
+ * associate a sampler in the shader with a texture
+ * unit. The conservative option is to assume that it is
+ * and create a link from the active program to any bound
+ * textures for the given unit number.
+ *
+ * FIXME: We should be doing the same thing for calls to
+ * glUniform1iv. */
+ if (strcmp(name, "glUniform1i") == 0 ||
+ strcmp(name, "glUniform1iARB") == 0) {
+
+ GLint max_unit = MAX(GL_MAX_TEXTURE_COORDS, GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS);
+
+ GLint unit = call->arg(1).toSInt();
+ std::stringstream ss_program;
+ std::stringstream ss_texture;
+
+ if (unit < max_unit) {
+
+ ss_program << "program-" << activeProgram;
+
+ ss_texture << "texture-unit-" << GL_TEXTURE0 + unit << "-target-";
+
+ /* We don't know what target(s) might get bound to
+ * this texture unit, so conservatively link to
+ * all. Only bound textures will actually get inserted
+ * into the output call stream. */
+ linkf(ss_program.str(), ss_texture.str(), GL_TEXTURE_1D);
+ linkf(ss_program.str(), ss_texture.str(), GL_TEXTURE_2D);
+ linkf(ss_program.str(), ss_texture.str(), GL_TEXTURE_3D);
+ linkf(ss_program.str(), ss_texture.str(), GL_TEXTURE_CUBE_MAP);
+ }
+ }
+
return;
}
TraceAnalyzer(): transformFeedbackActive(false),
framebufferObjectActive(false),
insideBeginEnd(false),
+ insideNewEndList(0),
activeTextureUnit(GL_TEXTURE0)
{}