[Piglit] [PATCH 1/7] framework: Add an option to run a test into an FBO.

Eric Anholt eric at anholt.net
Mon Aug 15 12:49:20 PDT 2011


This is not safe for all tests, but it means we can make some tests
run into FBOs and reduce disruption on developer systems.
---
 tests/util/piglit-framework.c |  186 +++++++++++++++++++++++++++++++++++++----
 tests/util/piglit-framework.h |    1 +
 tests/util/piglit-glx-util.c  |   38 ++++++++-
 tests/util/piglit-glx-util.h  |    2 +
 4 files changed, 207 insertions(+), 20 deletions(-)

diff --git a/tests/util/piglit-framework.c b/tests/util/piglit-framework.c
index a034440..f275b40 100644
--- a/tests/util/piglit-framework.c
+++ b/tests/util/piglit-framework.c
@@ -39,8 +39,16 @@
 #endif
 
 int piglit_automatic = 0;
+bool piglit_use_fbo = false;
+GLuint piglit_fbo;
 static int piglit_window;
 static enum piglit_result result;
+#ifdef USE_GLX
+Display *piglit_glx_dpy;
+Window piglit_glx_window;
+XVisualInfo *piglit_glx_visinfo;
+GLXContext piglit_glx_context;
+#endif
 
 static void
 display(void)
@@ -72,27 +80,19 @@ reshape(int w, int h)
 	glViewport(0, 0, w, h);
 }
 
-int main(int argc, char *argv[])
+/* Swapbuffers the results to the window in non-auto mode. */
+void
+piglit_present_results()
 {
-	int j;
+	if (!piglit_automatic && !piglit_use_fbo)
+		glutSwapBuffers();
+}
 
+static void
+piglit_framework_glut_init(int argc, char *argv[])
+{
 	piglit_glutInit(argc, argv);
 
-	/* Find/remove "-auto" from the argument vector.
-	 */
-	for (j = 1; j < argc; j++) {
-		if (!strcmp(argv[j], "-auto")) {
-			int i;
-
-			piglit_automatic = 1;
-		
-			for (i = j + 1; i < argc; i++) {
-				argv[i - 1] = argv[i];
-			}
-			argc--;
-			j--;
-		}
-	}
 	glutInitWindowPosition(0, 0);
 	glutInitWindowSize(piglit_width, piglit_height);
 	glutInitDisplayMode(piglit_window_mode);
@@ -110,10 +110,160 @@ int main(int argc, char *argv[])
 #ifdef USE_OPENGL
 	glewInit();
 #endif
+}
+
+#ifdef USE_GLX
+static void
+piglit_framework_fbo_glx_init()
+{
+	piglit_glx_dpy = piglit_get_glx_display();
+
+	/* Unfortunately in GLX we need a drawable to bind our context
+	 * to.  Make an unmapped window.
+	 */
+	piglit_glx_visinfo = piglit_get_glx_visual(piglit_glx_dpy);
+
+	piglit_glx_context = piglit_get_glx_context(piglit_glx_dpy,
+						    piglit_glx_visinfo);
+
+	piglit_glx_window = piglit_get_glx_window_unmapped(piglit_glx_dpy,
+							   piglit_glx_visinfo);
+
+	glXMakeCurrent(piglit_glx_dpy, piglit_glx_window, piglit_glx_context);
+}
+#endif
+
+static void
+piglit_framework_fbo_glx_destroy()
+{
+#ifdef USE_GLX
+	glXMakeCurrent(piglit_glx_dpy, None, None);
+	glXDestroyContext(piglit_glx_dpy, piglit_glx_context);
+	XFree(piglit_glx_visinfo);
+	XCloseDisplay(piglit_glx_dpy);
+#endif
+}
+
+static bool
+piglit_framework_fbo_init()
+{
+	GLuint tex, depth = 0;
+	GLenum status;
+
+#ifdef USE_GLX
+	piglit_framework_fbo_glx_init();
+#else
+	return false;
+#endif
+
+#ifdef USE_OPENGL
+	glewInit();
+
+	if (!GLEW_VERSION_2_0)
+		return false;
+#endif
+
+	glGenFramebuffers(1, &piglit_fbo);
+	glBindFramebuffer(GL_FRAMEBUFFER, piglit_fbo);
+
+	glGenTextures(1, &tex);
+	glBindTexture(GL_TEXTURE_2D, tex);
+	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
+		     piglit_width, piglit_height, 0,
+		     GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+	glFramebufferTexture2D(GL_FRAMEBUFFER,
+			       GL_COLOR_ATTACHMENT0,
+			       GL_TEXTURE_2D,
+			       tex,
+			       0);
+
+	if (piglit_window_mode & (GLUT_DEPTH | GLUT_STENCIL)) {
+		GLenum depth_stencil;
+
+#ifdef USE_OPENGL
+		depth_stencil = GL_DEPTH_STENCIL;
+#else
+		depth_stencil = GL_DEPTH_STENCIL_OES;
+#endif
+
+		glGenTextures(1, &depth);
+		glBindTexture(GL_TEXTURE_2D, depth);
+		glTexImage2D(GL_TEXTURE_2D, 0, depth_stencil,
+			     piglit_width, piglit_height, 0,
+			     GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+		glFramebufferTexture2D(GL_FRAMEBUFFER,
+				       GL_DEPTH_ATTACHMENT,
+				       GL_TEXTURE_2D,
+				       depth,
+				       0);
+		glFramebufferTexture2D(GL_FRAMEBUFFER,
+				       GL_STENCIL_ATTACHMENT,
+				       GL_TEXTURE_2D,
+				       depth,
+				       0);
+	}
+
+	status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+	if (status != GL_FRAMEBUFFER_COMPLETE) {
+		fprintf(stderr,
+			"-fbo resulted in incomplete FBO, falling back\n");
+		glBindFramebuffer(GL_FRAMEBUFFER, 0);
+		return false;
+	}
+
+	return true;
+}
+
+static void
+piglit_framework_fbo_destroy()
+{
+	piglit_framework_fbo_glx_destroy();
+}
+
+static void
+delete_arg(char *argv[], int argc, int arg)
+{
+	int i;
+
+	for (i = arg + 1; i < argc; i++) {
+		argv[i - 1] = argv[i];
+	}
+}
+
+int main(int argc, char *argv[])
+{
+	int j;
+
+	/* Find/remove "-auto" and "-fbo" from the argument vector.
+	 */
+	for (j = 1; j < argc; j++) {
+		if (!strcmp(argv[j], "-auto")) {
+			piglit_automatic = 1;
+			delete_arg(argv, argc--, j--);
+		}
+
+		if (!strcmp(argv[j], "-fbo")) {
+			piglit_use_fbo = true;
+			delete_arg(argv, argc--, j--);
+		}
+	}
+
+	if (piglit_use_fbo) {
+		if (!piglit_framework_fbo_init())
+			piglit_use_fbo = false;
+	}
+
+	if (!piglit_use_fbo)
+		piglit_framework_glut_init(argc, argv);
 
 	piglit_init(argc, argv);
 
-	glutMainLoop();
+	if (piglit_use_fbo) {
+		result = piglit_display();
+		piglit_framework_fbo_destroy();
+	} else {
+		glutMainLoop();
+	}
 
 	piglit_report_result(result);
 	/* UNREACHED */
diff --git a/tests/util/piglit-framework.h b/tests/util/piglit-framework.h
index d9fccf6..41565be 100644
--- a/tests/util/piglit-framework.h
+++ b/tests/util/piglit-framework.h
@@ -31,3 +31,4 @@ extern int piglit_height;
 
 extern enum piglit_result piglit_display(void);
 extern void piglit_init(int argc, char **argv);
+extern void piglit_present_results();
diff --git a/tests/util/piglit-glx-util.c b/tests/util/piglit-glx-util.c
index f99be4a..0406615 100644
--- a/tests/util/piglit-glx-util.c
+++ b/tests/util/piglit-glx-util.c
@@ -30,6 +30,20 @@
 
 int piglit_automatic;
 
+Display *
+piglit_get_glx_display()
+{
+	Display *dpy;
+
+	dpy = XOpenDisplay(NULL);
+	if (!dpy) {
+		fprintf(stderr, "couldn't open display\n");
+		piglit_report_result(PIGLIT_FAIL);
+	}
+
+	return dpy;
+}
+
 XVisualInfo *
 piglit_get_glx_visual(Display *dpy)
 {
@@ -76,7 +90,7 @@ piglit_get_glx_context_share(Display *dpy, XVisualInfo *visinfo, GLXContext shar
 }
 
 Window
-piglit_get_glx_window(Display *dpy, XVisualInfo *visinfo)
+_piglit_get_glx_window(Display *dpy, XVisualInfo *visinfo, bool map)
 {
 	XSetWindowAttributes window_attr;
 	unsigned long mask;
@@ -99,11 +113,24 @@ piglit_get_glx_window(Display *dpy, XVisualInfo *visinfo)
 	if (piglit_automatic)
 		piglit_glx_window_set_no_input(dpy, win);
 
-	XMapWindow(dpy, win);
+	if (map)
+		XMapWindow(dpy, win);
 
 	return win;
 }
 
+Window
+piglit_get_glx_window_unmapped(Display *dpy, XVisualInfo *visinfo)
+{
+	return _piglit_get_glx_window(dpy, visinfo, false);
+}
+
+Window
+piglit_get_glx_window(Display *dpy, XVisualInfo *visinfo)
+{
+	return _piglit_get_glx_window(dpy, visinfo, true);
+}
+
 void
 piglit_require_glx_extension(Display *dpy, const char *name)
 {
@@ -319,3 +346,10 @@ piglit_glx_get_error(Display *dpy, XErrorEvent *err)
 
 	return err->error_code - errbase;
 }
+
+/* Creates a GLX context for rendering into an FBO */
+void
+piglit_framework_fbo_init_glx()
+{
+
+}
diff --git a/tests/util/piglit-glx-util.h b/tests/util/piglit-glx-util.h
index 445c263..dcd91cb 100644
--- a/tests/util/piglit-glx-util.h
+++ b/tests/util/piglit-glx-util.h
@@ -31,10 +31,12 @@
 #include "GL/glx.h"
 #include "GL/glxproto.h"
 
+Display *piglit_get_glx_display();
 XVisualInfo * piglit_get_glx_visual(Display *dpy);
 GLXContext piglit_get_glx_context(Display *dpy, XVisualInfo *visinfo);
 GLXContext piglit_get_glx_context_share(Display *dpy, XVisualInfo *visinfo, GLXContext share);
 Window piglit_get_glx_window(Display *dpy, XVisualInfo *visinfo);
+Window piglit_get_glx_window_unmapped(Display *dpy, XVisualInfo *visinfo);
 void piglit_require_glx_extension(Display *dpy, const char *name);
 void piglit_require_glx_version(Display *dpy, int major, int minor);
 void piglit_glx_event_loop(Display *dpy,
-- 
1.7.5.4



More information about the Piglit mailing list