[Piglit] [PATCH 4/5] Test interaction between fast color clears and glXSwapBuffers.
Paul Berry
stereotype441 at gmail.com
Wed May 22 10:20:26 PDT 2013
---
tests/all.tests | 1 +
tests/glx/CMakeLists.gl.txt | 3 +
tests/glx/glx-fast-color-clear.c | 285 +++++++++++++++++++++++++++++++++++++++
3 files changed, 289 insertions(+)
create mode 100644 tests/glx/glx-fast-color-clear.c
diff --git a/tests/all.tests b/tests/all.tests
index d9a1d10..07f1040 100644
--- a/tests/all.tests
+++ b/tests/all.tests
@@ -389,6 +389,7 @@ glx['glx-query-drawable-GLX_HEIGHT'] = PlainExecTest(['glx-query-drawable', '-au
glx['glx-query-drawable-GLXBadDrawable'] = PlainExecTest(['glx-query-drawable', '-auto', '--bad-drawable'])
glx['extension string sanity'] = PlainExecTest(['glx-string-sanity'])
glx['extension string sanity'].runConcurrent = True
+add_plain_test(glx, 'glx-fast-color-clear')
import_context = Group();
glx['GLX_EXT_import_context'] = import_context
diff --git a/tests/glx/CMakeLists.gl.txt b/tests/glx/CMakeLists.gl.txt
index ca85317..881724d 100644
--- a/tests/glx/CMakeLists.gl.txt
+++ b/tests/glx/CMakeLists.gl.txt
@@ -70,6 +70,9 @@ IF(PIGLIT_BUILD_GLX_TESTS)
piglit_add_executable (glx-query-drawable glx-query-drawable.c)
piglit_add_executable (glx-string-sanity glx-string-sanity.c)
+ piglit_add_executable (glx-fast-color-clear glx-fast-color-clear.c)
+ target_link_libraries(glx-fast-color-clear X11-xcb)
+ target_link_libraries(glx-fast-color-clear xcb-image)
ENDIF(PIGLIT_BUILD_GLX_TESTS)
# vim: ft=cmake:
diff --git a/tests/glx/glx-fast-color-clear.c b/tests/glx/glx-fast-color-clear.c
new file mode 100644
index 0000000..aed2442
--- /dev/null
+++ b/tests/glx/glx-fast-color-clear.c
@@ -0,0 +1,285 @@
+/*
+ * Copyright © 2013 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file glx-fast-color-clear.c
+ *
+ * On implementations that support fast color clear (e.g. i965/gen7+),
+ * verify that memory writes that were deferred as the result of a
+ * fast clear are properly resolved at the time of glXSwapBuffers.
+ *
+ * We can't use glReadPixels() to do this, since glReadPixels() also
+ * does a resolve, so instead we read the contents of the front buffer
+ * directly from X after the swap.
+ *
+ * Since glXSwapBuffers doesn't actually perform the swap (it simply
+ * queues it to happen later), the test needs to wait for the swap to
+ * occur before reading the front buffer. If the implementation
+ * supports it, we do so using the GLX_INTEL_swap_event extension.
+ * Otherwise we sleep for 1 second to give time for the swap to occur.
+ */
+
+#include "piglit-util-gl-common.h"
+#include "GL/glx.h"
+#include <sys/time.h>
+#include "piglit-glx-util.h"
+#include <X11/Xlib-xcb.h>
+#include <xcb/xcb_image.h>
+#include <unistd.h>
+
+
+static Window win;
+static GLXWindow glxWin;
+
+enum piglit_result
+draw(Display *dpy);
+
+
+#define WIDTH 30
+#define HEIGHT 30
+
+
+static const char *vs_text =
+ "void main()\n"
+ "{\n"
+ " gl_Position = gl_Vertex;\n"
+ "}\n";
+
+static const char *fs_text =
+ "void main()\n"
+ "{\n"
+ " gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
+ "}\n";
+
+
+static GLuint prog;
+static bool is_intel_swap_event_supported = false;
+static int error_base, event_base;
+
+
+/**
+ * Determine whether or not a GLX extension is supported.
+ */
+static int
+is_glx_extension_supported(Display *dpy, const char *query)
+{
+ const int scrnum = DefaultScreen(dpy);
+ const char *glx_extensions = NULL;
+ const size_t len = strlen(query);
+ const char *ptr;
+
+ if (glx_extensions == NULL) {
+ glx_extensions = glXQueryExtensionsString(dpy, scrnum);
+ }
+
+ ptr = strstr(glx_extensions, query);
+ return ((ptr != NULL) && ((ptr[len] == ' ') || (ptr[len] == '\0')));
+}
+
+
+/*
+ * Create an RGB, double-buffered window.
+ * Return the window and context handles.
+ */
+static void
+make_window( Display *dpy, const char *name,
+ int x, int y, int width, int height,
+ Window *winRet, GLXContext *ctxRet, GLXWindow *glxWinRet)
+{
+ /* Request a double-buffered color buffer */
+ int attribs[] = {
+ GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
+ GLX_RENDER_TYPE, GLX_RGBA_BIT,
+ GLX_DOUBLEBUFFER, True,
+ GLX_RED_SIZE, 1,
+ GLX_GREEN_SIZE, 1,
+ GLX_BLUE_SIZE, 1,
+ None };
+
+ int scrnum, nelements;
+ XSetWindowAttributes attr;
+ unsigned long mask;
+ Window root;
+ Window win;
+ GLXContext ctx;
+ XVisualInfo *visinfo;
+ GLXFBConfig *fbc;
+ GLXWindow gwin;
+ Bool ret;
+
+ scrnum = DefaultScreen( dpy );
+ root = RootWindow( dpy, scrnum );
+
+ fbc = glXChooseFBConfig(dpy, scrnum, attribs, &nelements);
+ if (!fbc) {
+ printf("Error: couldn't get framebuffer config\n");
+ piglit_report_result(PIGLIT_FAIL);
+ }
+ visinfo = glXGetVisualFromFBConfig(dpy, fbc[0]);
+ if (!visinfo) {
+ printf("Error: couldn't get an RGB, Double-buffered visual\n");
+ piglit_report_result(PIGLIT_SKIP);
+ }
+ ctx = glXCreateNewContext(dpy, fbc[0], GLX_RGBA_TYPE, 0, GL_TRUE);
+
+ /* window attributes */
+ attr.background_pixel = 0;
+ attr.border_pixel = 0;
+ attr.colormap = XCreateColormap(dpy, root, visinfo->visual, AllocNone);
+ attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
+ mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
+
+ win = XCreateWindow( dpy, root, x, y, width, height,
+ 0, visinfo->depth, InputOutput,
+ visinfo->visual, mask, &attr );
+ XMapWindow(dpy, win);
+ gwin = glXCreateWindow(dpy, fbc[0], win, attribs);
+ ret = glXMakeContextCurrent(dpy, gwin, gwin, ctx);
+ if (!ret)
+ printf("make current failed: %d\n", glGetError());
+ glXSelectEvent(dpy, gwin, GLX_BUFFER_SWAP_COMPLETE_INTEL_MASK);
+
+ XFree(visinfo);
+
+ *winRet = win;
+ *ctxRet = ctx;
+ *glxWinRet = gwin;
+}
+
+
+static void
+wait_for_event(Display *dpy, int desired_type)
+{
+ while (true) {
+ XEvent event;
+ XNextEvent(dpy, &event);
+ if (event.type == desired_type)
+ break;
+ }
+}
+
+
+int
+main(int argc, char **argv)
+{
+ GLuint vs, fs;
+ GLXContext ctx;
+ Display *dpy;
+ enum piglit_result result;
+
+ dpy = XOpenDisplay(NULL);
+ if (dpy == NULL) {
+ fprintf(stderr, "couldn't open display\n");
+ piglit_report_result(PIGLIT_FAIL);
+ }
+
+ make_window(dpy, "GLX fast color clear test", 0, 0, WIDTH, HEIGHT,
+ &win, &ctx, &glxWin);
+
+ is_intel_swap_event_supported =
+ is_glx_extension_supported(dpy, "GLX_INTEL_swap_event");
+
+ glXQueryExtension(dpy, &error_base, &event_base);
+
+ piglit_dispatch_default_init();
+
+ piglit_require_gl_version(11);
+ piglit_require_GLSL_version(110);
+
+ /* Compile shader */
+ vs = piglit_compile_shader_text(GL_VERTEX_SHADER, vs_text);
+ fs = piglit_compile_shader_text(GL_FRAGMENT_SHADER, fs_text);
+ prog = piglit_link_simple_program(vs, fs);
+ if (!prog)
+ piglit_report_result(PIGLIT_FAIL);
+ if (!piglit_check_gl_error(GL_NO_ERROR))
+ piglit_report_result(PIGLIT_FAIL);
+
+ wait_for_event(dpy, Expose);
+ result = draw(dpy);
+
+ glXDestroyContext(dpy, ctx);
+ XDestroyWindow(dpy, win);
+ XCloseDisplay(dpy);
+
+ piglit_report_result(result);
+ return 0;
+}
+
+
+static bool
+verify_front_buffer_contents(Display *dpy)
+{
+ xcb_connection_t *conn = XGetXCBConnection(dpy);
+ unsigned plane_mask = ~0;
+ xcb_image_t *image =
+ xcb_image_get(conn, win, 0, 0, WIDTH, HEIGHT, plane_mask,
+ XCB_IMAGE_FORMAT_Z_PIXMAP);
+ unsigned x;
+ unsigned y;
+ for (y = 0; y < HEIGHT; y++) {
+ for (x = 0; x < WIDTH; x++) {
+ uint32_t pixel = xcb_image_get_pixel(image, x, y);
+ if (pixel != 0xff00ff00) {
+ printf("Bad pixel at %d, %d: %x\n",
+ x, y, pixel);
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+
+enum piglit_result
+draw(Display *dpy)
+{
+ bool pass = true;
+
+ /* Paint the window red using a shader (not a fast clear). */
+ glUseProgram(prog);
+ piglit_draw_rect(-1, -1, 2, 2);
+
+ /* Clear the window to green; this will be optimized using a
+ * fast color clear if the hardware is capable of it.
+ */
+ glClearColor(0, 1, 0, 1);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ if (!piglit_check_gl_error(GL_NO_ERROR))
+ pass = false;
+
+ /* Swap the resulting image to the screen. */
+ glXSwapBuffers(dpy, glxWin);
+
+ /* Wait for the swap to occur. */
+ if (is_intel_swap_event_supported)
+ wait_for_event(dpy, event_base + GLX_BufferSwapComplete);
+ else
+ sleep(1);
+
+ /* Verify that the front buffer contains the correct data. */
+ pass = verify_front_buffer_contents(dpy) && pass;
+
+ return pass ? PIGLIT_PASS : PIGLIT_FAIL;
+}
--
1.8.2.3
More information about the Piglit
mailing list