/* BEGIN_COPYRIGHT -*- glean -*- * * Copyright (C) 2007, 2014 Intel Corporation * Copyright (C) 1999 Allen Akin All Rights Reserved. * * 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 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. * * END_COPYRIGHT */ /** @file pbo.c * * Test OpenGL Extension GL_ARB_pixel_buffer_object * * Authors: * Shuang He * Adapted to Piglit by Laura Ekstrand , November 2014. */ #include "piglit-util-gl.h" #define WINSIZE 100 #define BUFFER_OFFSET(i) ((char *)NULL + (i)) PIGLIT_GL_TEST_CONFIG_BEGIN config.supports_gl_compat_version = 10; config.window_visual = PIGLIT_GL_VISUAL_RGBA | PIGLIT_GL_VISUAL_DOUBLE; config.khr_no_error_support = PIGLIT_NO_ERRORS; PIGLIT_GL_TEST_CONFIG_END void piglit_init(int argc, char **argv) { piglit_require_extension("GL_ARB_pixel_buffer_object"); piglit_ortho_projection(piglit_width, piglit_height, GL_FALSE); } static void report_failure(const char *msg, const int line) { printf("FAILURE: %s (at pbo.c: %d)\n", msg, line); } #define REPORT_FAILURE(MSG) report_failure(MSG, __LINE__) #define TEXSIZE 64 enum piglit_result test_sanity(void *null) { GLuint pbs[1]; GLuint pb_binding; glGetIntegerv(GL_PIXEL_UNPACK_BUFFER_BINDING_ARB, (GLint *) & pb_binding); if (pb_binding != 0) { REPORT_FAILURE("Failed to bind unpack pixel buffer object"); return PIGLIT_FAIL; } glGetIntegerv(GL_PIXEL_PACK_BUFFER_BINDING_ARB, (GLint *) & pb_binding); if (pb_binding != 0) { REPORT_FAILURE("Failed to bind pack pixel buffer object"); return PIGLIT_FAIL; } glGenBuffersARB(1, pbs); if (glIsBufferARB(pbs[0]) != GL_FALSE) { REPORT_FAILURE("glIsBufferARB failed"); return PIGLIT_FAIL; } glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pbs[0]); glGetIntegerv(GL_PIXEL_UNPACK_BUFFER_BINDING_ARB, (GLint *) & pb_binding); glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0); if (pb_binding != pbs[0]) { REPORT_FAILURE("Failed to bind unpack pixel buffer object"); return PIGLIT_FAIL; } glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pbs[0]); glGetIntegerv(GL_PIXEL_PACK_BUFFER_BINDING_ARB, (GLint *) & pb_binding); glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0); if (pb_binding != pbs[0]) { REPORT_FAILURE("Failed to bind unpack pixel buffer object"); return PIGLIT_FAIL; } glDeleteBuffersARB(1, pbs); if (glIsBufferARB(pbs[0]) == GL_TRUE) { REPORT_FAILURE("glIsBufferARB failed"); return PIGLIT_FAIL; } return PIGLIT_PASS; } enum piglit_result test_draw_pixels(void *null) { int use_unpack; int use_pack; GLuint pb_pack[1]; GLuint pb_unpack[1]; GLubyte buf[WINSIZE * WINSIZE * 4]; GLubyte t[TEXSIZE * TEXSIZE * 4]; int i, j; GLubyte * pbo_pack_mem = NULL; GLubyte black[4] = { 0, 0, 0, 255 }; bool pass = true; GLubyte expected[WINSIZE * WINSIZE * 4]; glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, 0); glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0); for (use_unpack = 0; use_unpack < 2; use_unpack++) { for (use_pack = 0; use_pack < 2; use_pack++) { GLubyte *pbo_mem = NULL; glClearColor(0.0, 0.0, 0.0, 1.0); glClear(GL_COLOR_BUFFER_BIT); if (use_unpack) { glGenBuffersARB(1, pb_unpack); glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pb_unpack[0]); glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, TEXSIZE * TEXSIZE * 4 * sizeof(GLubyte), NULL, GL_STREAM_DRAW); } if (use_unpack) { pbo_mem = (GLubyte *) glMapBufferARB( GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY); } else { pbo_mem = t; } /* Fill the buffer */ for (i = 0; i < TEXSIZE; i++) for (j = 0; j < TEXSIZE; j++) { int idx = 4 * (i * TEXSIZE + j); pbo_mem[idx + 0] = i % 256; pbo_mem[idx + 1] = i % 256; pbo_mem[idx + 2] = i % 256; pbo_mem[idx + 3] = 0; } if (use_unpack) { glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB); glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0); } /* Draw the buffer */ if (use_unpack) { glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pb_unpack[0]); glDrawPixels(TEXSIZE, TEXSIZE, GL_BGRA, GL_UNSIGNED_BYTE, NULL); glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0); } else { glDrawPixels(TEXSIZE, TEXSIZE, GL_BGRA, GL_UNSIGNED_BYTE, pbo_mem); } if (!piglit_automatic) piglit_present_results(); /* Check the result */ if (use_pack) { glGenBuffersARB(1, pb_pack); glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pb_pack[0]); glBufferDataARB(GL_PIXEL_PACK_BUFFER_ARB, WINSIZE * WINSIZE * 4 * sizeof(GL_UNSIGNED_BYTE), NULL, GL_STREAM_DRAW); glReadPixels(0, 0, WINSIZE, WINSIZE, GL_BGRA, GL_UNSIGNED_BYTE, NULL); pbo_pack_mem = (GLubyte *) glMapBufferARB( GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY); } else { pbo_pack_mem = buf; glReadPixels(0, 0, WINSIZE, WINSIZE, GL_BGRA, GL_UNSIGNED_BYTE, pbo_pack_mem); } /* Make expected. */ for (j = 0; j < WINSIZE; j++) { for (i = 0; i < WINSIZE; i++) { int idx = (j * WINSIZE + i) * 4; if (i < TEXSIZE && j < TEXSIZE) { expected[idx + 0] = j % 256; expected[idx + 1] = j % 256; expected[idx + 2] = j % 256; expected[idx + 3] = 0; } else { expected[idx + 0] = black[0]; expected[idx + 1] = black[1]; expected[idx + 2] = black[2]; expected[idx + 3] = black[3]; } } } pass &= piglit_compare_images_ubyte(0, 0, WINSIZE, WINSIZE, expected, pbo_pack_mem); if (use_pack) { glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0); glDeleteBuffersARB(1, pb_pack); } if (use_unpack) { glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, 0); glDeleteBuffersARB(1, pb_unpack); } } } return pass ? PIGLIT_PASS : PIGLIT_FAIL; } enum piglit_result test_pixel_map(void *null) { int use_unpack; int use_pack; GLuint pb_pack[1]; GLuint pb_unpack[1]; int i; int size; int max; GLushort *pbo_mem; glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0); glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0); glGetIntegerv(GL_MAX_PIXEL_MAP_TABLE, &max); for (use_pack = 0; use_pack < 2; use_pack++) { for (use_unpack = 0; use_unpack < 2; use_unpack++) { glClearColor(0.0, 0.0, 0.0, 1.0); glClear(GL_COLOR_BUFFER_BIT); if (use_unpack) { glGenBuffersARB(1, pb_unpack); glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pb_unpack[0]); glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, max * sizeof(GLushort), NULL, GL_STREAM_DRAW); } pbo_mem = NULL; if (use_unpack) { pbo_mem = (GLushort *) glMapBufferARB( GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY); } else { pbo_mem = (GLushort *) malloc(sizeof(GLushort) * max); } for (i = 0; i < max; i++) pbo_mem[i] = max - i - 1; if (use_unpack) { glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB); glPixelMapusv(GL_PIXEL_MAP_R_TO_R, max, NULL); glPixelMapusv(GL_PIXEL_MAP_G_TO_G, max, NULL); glPixelMapusv(GL_PIXEL_MAP_B_TO_B, max, NULL); glPixelMapusv(GL_PIXEL_MAP_A_TO_A, max, NULL); glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0); } else { glPixelMapusv(GL_PIXEL_MAP_R_TO_R, max, pbo_mem); glPixelMapusv(GL_PIXEL_MAP_G_TO_G, max, pbo_mem); glPixelMapusv(GL_PIXEL_MAP_B_TO_B, max, pbo_mem); glPixelMapusv(GL_PIXEL_MAP_A_TO_A, max, pbo_mem); free(pbo_mem); } glGetIntegerv(GL_PIXEL_MAP_R_TO_R_SIZE, &size); if (size != max) { REPORT_FAILURE("glPixelMap failed"); return PIGLIT_FAIL; } glPixelTransferi(GL_MAP_COLOR, GL_FALSE); /* Read back pixel map */ if (use_pack) { glGenBuffersARB(1, pb_pack); glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pb_pack[0]); glBufferDataARB(GL_PIXEL_PACK_BUFFER_ARB, max * sizeof(GLushort), NULL, GL_STREAM_DRAW); glGetPixelMapusv(GL_PIXEL_MAP_R_TO_R, NULL); pbo_mem = (GLushort *) glMapBufferARB( GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY); } else { pbo_mem = (GLushort *) malloc(sizeof(GLushort) * max); glGetPixelMapusv(GL_PIXEL_MAP_R_TO_R, pbo_mem); } for (i = 0; i < max; i++) { if (pbo_mem[i] != max - i - 1) { REPORT_FAILURE("get PixelMap failed"); return PIGLIT_FAIL; } } if (use_pack) { glUnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB); glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0); glDeleteBuffersARB(1, pb_pack); } else { free(pbo_mem); } if (use_unpack) { glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0); glDeleteBuffersARB(1, pb_unpack); } if (!piglit_automatic) piglit_present_results(); } } return PIGLIT_PASS; } enum piglit_result test_bitmap(void *null) { GLuint pb_unpack[1]; GLuint pb_pack[1]; int use_unpack = 1; int use_pack = 0; GLubyte bitmap[TEXSIZE * TEXSIZE / 8]; GLfloat buf[WINSIZE * WINSIZE * 3]; GLfloat white[3] = { 1.0, 1.0, 1.0 }; GLfloat black[3] = { 0.0, 0.0, 0.0 }; int i, j; GLubyte *pbo_unpack_mem = NULL; GLfloat *pbo_pack_mem = NULL; GLfloat expected[WINSIZE * WINSIZE * 3]; float tolerance[4]; bool pass = true; glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0); glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0); for (use_pack = 0; use_pack < 2; use_pack++) { for (use_unpack = 0; use_unpack < 2; use_unpack++) { glClearColor(0.0, 0.0, 0.0, 1.0); glClear(GL_COLOR_BUFFER_BIT); if (use_unpack) { glGenBuffersARB(1, pb_unpack); glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pb_unpack[0]); glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, TEXSIZE * TEXSIZE, NULL, GL_STREAM_DRAW); pbo_unpack_mem = (GLubyte *) glMapBufferARB( GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY); } else { pbo_unpack_mem = bitmap; } for (i = 0; i < TEXSIZE * TEXSIZE / 8; i++) { pbo_unpack_mem[i] = 0xAA; /* Binary 10101010 */ } glColor4f(1.0, 1.0, 1.0, 0.0); glRasterPos2f(0.0, 0.0); if (use_unpack) { glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB); /* Draw white into every other pixel, * for a white/black checkerboard. */ glBitmap(TEXSIZE, TEXSIZE, 0, 0, 0, 0, NULL); glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0); } else { glBitmap(TEXSIZE, TEXSIZE, 0, 0, 0, 0, pbo_unpack_mem); } if (!piglit_automatic) piglit_present_results(); /* Check the result */ if (use_pack) { glGenBuffersARB(1, pb_pack); glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pb_pack[0]); glBufferDataARB(GL_PIXEL_PACK_BUFFER_ARB, WINSIZE * WINSIZE * 4 * sizeof(GLfloat), NULL, GL_STREAM_DRAW); glReadPixels(0, 0, WINSIZE, WINSIZE, GL_RGB, GL_FLOAT, NULL); pbo_pack_mem = (GLfloat *) glMapBufferARB( GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY); } else { pbo_pack_mem = buf; glReadPixels(0, 0, WINSIZE, WINSIZE, GL_RGB, GL_FLOAT, pbo_pack_mem); } /* Compute expected and compare it to the result. */ for (j = 0; j < WINSIZE; j++) { for (i = 0; i < WINSIZE; i++) { int idx = (j * WINSIZE + i) * 3; if ((i & 1) || (i >= TEXSIZE) || (j >= TEXSIZE)) { expected[idx + 0] = black[0]; expected[idx + 1] = black[1]; expected[idx + 2] = black[2]; } else { expected[idx + 0] = white[0]; expected[idx + 1] = white[1]; expected[idx + 2] = white[2]; } } } piglit_compute_probe_tolerance(GL_RGB, &tolerance[0]); pass &= piglit_compare_images_color(0, 0, WINSIZE, WINSIZE, 3, tolerance, expected, pbo_pack_mem); if (use_pack) { glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB); glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0); glDeleteBuffersARB(1, pb_pack); } if (use_unpack) { glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, 0); glDeleteBuffersARB(1, pb_unpack); } } } return pass ? PIGLIT_PASS : PIGLIT_FAIL; } #define TEXTURE_SIZE TEXSIZE * TEXSIZE * 3 #define WINDOW_SIZE WINSIZE * WINSIZE * 3 enum piglit_result test_tex_image(void *null) { bool pass = true; int break_pbo_cow, break_tex_cow; /* cow = copy on write */ int use_unpack, use_pack; GLuint unpack_pb[1]; GLuint pack_pb[1]; GLenum pack = GL_PIXEL_PACK_BUFFER_ARB; GLenum unpack = GL_PIXEL_UNPACK_BUFFER_ARB; GLfloat t1[TEXTURE_SIZE]; GLfloat t2[TEXTURE_SIZE]; GLfloat *pbo_mem = NULL; int i, j; GLfloat green[3] = { 1.0, 1.0, 0.0 }; GLfloat black[3] = { 0.0, 0.0, 0.0 }; GLfloat buf[WINDOW_SIZE]; GLfloat exp_tex[TEXTURE_SIZE]; GLfloat exp_win[WINDOW_SIZE]; GLfloat tolerance[4]; piglit_compute_probe_tolerance(GL_RGB, tolerance); glBindBufferARB(unpack, 0); glBindBufferARB(pack, 0); glClearColor(0.0, 0.0, 0.0, 1.0); glClear(GL_COLOR_BUFFER_BIT); for (use_pack = 0; use_pack < 2; use_pack++) { for (use_unpack = 0; use_unpack < 2; use_unpack++) { for (break_pbo_cow = 0; break_pbo_cow < use_unpack + 1; break_pbo_cow++) { for (break_tex_cow = 0; break_tex_cow < use_unpack + 1; break_tex_cow++) { if (use_unpack) { glGenBuffersARB(1, unpack_pb); glBindBufferARB(unpack, unpack_pb[0]); glBufferDataARB(unpack, TEXTURE_SIZE * sizeof(GLfloat), NULL, GL_STREAM_DRAW); } glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); if (use_unpack) { pbo_mem = (GLfloat *) glMapBufferARB(unpack, GL_WRITE_ONLY); } else { pbo_mem = t1; } for (i = 0; i < TEXTURE_SIZE/3; i++) { pbo_mem[3 * i] = 1.0; pbo_mem[3 * i + 1] = 1.0; pbo_mem[3 * i + 2] = 0.0; } if (use_unpack) { glUnmapBufferARB(unpack); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, TEXSIZE, TEXSIZE, 0, GL_RGB, GL_FLOAT, NULL); glBindBufferARB(unpack, 0); } else glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, TEXSIZE, TEXSIZE, 0, GL_RGB, GL_FLOAT, pbo_mem); if (use_unpack && break_pbo_cow) { glBindBufferARB(unpack, unpack_pb[0]); pbo_mem = (GLfloat *) glMapBufferARB( unpack, GL_WRITE_ONLY); for (i = 0; i < TEXTURE_SIZE; i++) pbo_mem[i] = 0.2; glUnmapBufferARB(unpack); glBindBufferARB(unpack, 0); } if (use_unpack && break_tex_cow) { GLfloat temp[3]; for (i = 0; i < 3; i++) temp[i] = 0.8; glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGB, GL_FLOAT, temp); } /* Check PBO's content */ if (use_unpack) { glBindBufferARB(unpack, unpack_pb[0]); pbo_mem = (GLfloat *) glMapBuffer(unpack, GL_READ_ONLY); if (break_pbo_cow) { for (i = 0; i < TEXTURE_SIZE; i++) if (fabsf(pbo_mem[i] - 0.2f) > tolerance[0]) { REPORT_FAILURE ("PBO modified by someone else, " "there must be something wrong"); return PIGLIT_FAIL; } } glUnmapBufferARB(unpack); glBindBufferARB(unpack, 0); } /* Read texture back */ if (use_pack) { glGenBuffersARB(1, pack_pb); glBindBufferARB(pack, pack_pb[0]); glBufferDataARB(pack, TEXTURE_SIZE * sizeof(GLfloat), NULL, GL_STREAM_DRAW); glGetTexImage(GL_TEXTURE_2D, 0, GL_RGB, GL_FLOAT, NULL); pbo_mem = (GLfloat *) glMapBufferARB(pack, GL_READ_ONLY); } else { glGetTexImage(GL_TEXTURE_2D, 0, GL_RGB, GL_FLOAT, t2); pbo_mem = t2; } /* Check texture image */ for (i = 0; i < TEXTURE_SIZE/3; i++) { int idx = i * 3; if (i == 0 && break_tex_cow && use_unpack) { exp_tex[idx + 0] = 0.8; exp_tex[idx + 1] = 0.8; exp_tex[idx + 2] = 0.8; } else { exp_tex[idx + 0] = 1.0; exp_tex[idx + 1] = 1.0; exp_tex[idx + 2] = 0.0; } } pass &= piglit_compare_images_color(0, 0, TEXSIZE, TEXSIZE, 3, tolerance, exp_tex, pbo_mem); if (use_pack) { glUnmapBufferARB(pack); glBindBufferARB(pack, 0); glDeleteBuffersARB(1, pack_pb); } if (use_unpack) { glDeleteBuffersARB(1, unpack_pb); } glEnable(GL_TEXTURE_2D); glBegin(GL_POLYGON); glTexCoord2f(0, 0); glVertex2f(0, 0); glTexCoord2f(1, 0); glVertex2f(TEXSIZE, 0); glTexCoord2f(1, 1); glVertex2f(TEXSIZE, TEXSIZE); glTexCoord2f(0, 1); glVertex2f(0, TEXSIZE); glEnd(); glDisable(GL_TEXTURE_2D); glReadPixels(0, 0, WINSIZE, WINSIZE, GL_RGB, GL_FLOAT, buf); for (j = 0; j < WINSIZE; j++) { for (i = 0; i < WINSIZE; i++) { int idx = (j * WINSIZE + i) * 3; if (i == 0 && j == 0 && break_tex_cow && use_unpack) { exp_win[idx + 0] = 0.8; exp_win[idx + 1] = 0.8; exp_win[idx + 2] = 0.8; } else if (i < TEXSIZE && j < TEXSIZE) { exp_win[idx + 0] = green[0]; exp_win[idx + 1] = green[1]; exp_win[idx + 2] = green[2]; } else { exp_win[idx + 0] = black[0]; exp_win[idx + 1] = black[1]; exp_win[idx + 2] = black[2]; } } } pass &= piglit_compare_images_color(0, 0, WINSIZE, WINSIZE, 3, tolerance, exp_win, buf); } } } } return pass ? PIGLIT_PASS : PIGLIT_FAIL; } enum piglit_result test_tex_sub_image(void *null) { GLuint pbs[1]; GLfloat t[TEXSIZE * TEXSIZE * 3]; int i, j; int use_unpack = 0; GLfloat green[3] = { 0.0, 1.0, 0.0 }; GLfloat black[3] = { 0.0, 0.0, 0.0 }; GLfloat *pbo_mem = NULL; GLfloat buf[WINSIZE * WINSIZE * 3]; bool pass = true; GLfloat expected[WINSIZE * WINSIZE * 3]; GLfloat tolerance[4]; piglit_compute_probe_tolerance(GL_RGB, &tolerance[0]); glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0); glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0); for (use_unpack = 0; use_unpack < 2; use_unpack++) { pbo_mem = NULL; glClearColor(0.0, 0.0, 0.0, 1.0); glClear(GL_COLOR_BUFFER_BIT); if (use_unpack) { glGenBuffersARB(1, pbs); glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pbs[0]); glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, TEXSIZE * TEXSIZE * 3 * sizeof(GLfloat), NULL, GL_STREAM_DRAW); glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0); } glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, TEXSIZE, TEXSIZE, 0, GL_RGB, GL_FLOAT, NULL); if (use_unpack) { glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pbs[0]); pbo_mem = (GLfloat *) glMapBufferARB( GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY); } else { pbo_mem = t; } for (i = 0; i < TEXSIZE * TEXSIZE; i++) { pbo_mem[3 * i] = 0.0; pbo_mem[3 * i + 1] = 1.0; pbo_mem[3 * i + 2] = 0.0; } if (use_unpack) { glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, TEXSIZE, TEXSIZE, GL_RGB, GL_FLOAT, NULL); glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0); } else glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, TEXSIZE, TEXSIZE, GL_RGB, GL_FLOAT, pbo_mem); glEnable(GL_TEXTURE_2D); glBegin(GL_POLYGON); glTexCoord2f(0, 0); glVertex2f(0, 0); glTexCoord2f(1, 0); glVertex2f(10, 0); glTexCoord2f(1, 1); glVertex2f(10, 10); glTexCoord2f(0, 1); glVertex2f(0, 10); glEnd(); glDisable(GL_TEXTURE_2D); glReadPixels(0, 0, WINSIZE, WINSIZE, GL_RGB, GL_FLOAT, buf); for (j = 0; j < WINSIZE; j++) { for (i = 0; i < WINSIZE; i++) { int idx = (j * WINSIZE + i) * 3; if (i < 10 && j < 10) { expected[idx + 0] = green[0]; expected[idx + 1] = green[1]; expected[idx + 2] = green[2]; } else { expected[idx + 0] = black[0]; expected[idx + 1] = black[1]; expected[idx + 2] = black[2]; } } } pass &= piglit_compare_images_color(0, 0, WINSIZE, WINSIZE, 3, tolerance, expected, buf); } return pass ? PIGLIT_PASS : PIGLIT_FAIL; } enum piglit_result test_polygon_stip(void *null) { int use_unpack = 0; int use_pack = 0; GLuint unpack_pb[1]; GLuint pack_pb[1]; GLubyte t1[32 * 32 / 8]; GLubyte t2[32 * 32 / 8]; GLubyte *pbo_mem = NULL; int i, j; GLfloat white[3] = { 1.0, 1.0, 1.0 }; GLfloat black[3] = { 0.0, 0.0, 0.0 }; GLfloat buf[WINSIZE * WINSIZE * 3]; bool pass = true; GLfloat expected[WINSIZE * WINSIZE * 3]; GLfloat tolerance[4]; piglit_compute_probe_tolerance(GL_RGB, &tolerance[0]); glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0); glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0); for (use_unpack = 0; use_unpack < 2; use_unpack++) { for (use_pack = 0; use_pack < 2; use_pack++) { glClearColor(0.0, 0.0, 0.0, 1.0); glClear(GL_COLOR_BUFFER_BIT); if (use_unpack) { glGenBuffersARB(1, unpack_pb); glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, unpack_pb[0]); glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, 32 * 32 / 8, NULL, GL_STREAM_DRAW); pbo_mem = (GLubyte *) glMapBufferARB( GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY); } else { pbo_mem = t1; } /* Fill in the stipple pattern */ for (i = 0; i < 32 * 32 / 8; i++) { pbo_mem[i] = 0xAA; /* Checkerboard */ } if (use_unpack) { glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB); glPolygonStipple(NULL); } else { glPolygonStipple(pbo_mem); } /* Read back the stipple pattern */ if (use_pack) { glGenBuffersARB(1, pack_pb); glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pack_pb[0]); glBufferDataARB(GL_PIXEL_PACK_BUFFER_ARB, 32 * 32 / 8, NULL, GL_STREAM_DRAW); glGetPolygonStipple(NULL); pbo_mem = (GLubyte *) glMapBufferARB( GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY); } else { glGetPolygonStipple(t2); pbo_mem = t2; } for (i = 0; i < 32 * 32 / 8; i++) { if (pbo_mem[i] != 0xAA) { REPORT_FAILURE("glGetPolygonStipple failed"); return PIGLIT_FAIL; } } if (use_unpack) { glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0); glDeleteBuffersARB(1, unpack_pb); } if (use_pack) { glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0); glDeleteBuffersARB(1, pack_pb); } glEnable(GL_POLYGON_STIPPLE); glColor4f(1.0, 1.0, 1.0, 0.0); glBegin(GL_POLYGON); glVertex2f(0, 0); glVertex2f(10, 0); glVertex2f(10, 10); glVertex2f(0, 10); glEnd(); glDisable(GL_POLYGON_STIPPLE); /* Check the result */ glReadPixels(0, 0, WINSIZE, WINSIZE, GL_RGB, GL_FLOAT, buf); for (j = 0; j < WINSIZE; j++) { for (i = 0; i < WINSIZE; i++) { int idx = (j * WINSIZE + i) * 3; if (!(i & 1) && i < 10 && j < 10) { expected[idx + 0] = white[0]; expected[idx + 1] = white[1]; expected[idx + 2] = white[2]; } else { expected[idx + 0] = black[0]; expected[idx + 1] = black[1]; expected[idx + 2] = black[2]; } } } pass &= piglit_compare_images_color(0, 0, WINSIZE, WINSIZE, 3, tolerance, expected, buf); } } return pass ? PIGLIT_PASS : PIGLIT_FAIL; } enum piglit_result test_error_handling(void *null) { bool pass = true; GLuint fbs[1]; GLuint tex; if (piglit_khr_no_error) return PIGLIT_SKIP; glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0); glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0); /* glDrawPixels raises an error when the buffer is too small */ glGenBuffersARB(1, fbs); glBindBufferARB(GL_PIXEL_UNPACK_BUFFER, fbs[0]); glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, 32 * 32 * 4, NULL, GL_STREAM_DRAW); glDrawPixels(32, 32 + 1, GL_BGRA, GL_UNSIGNED_BYTE, NULL); pass = piglit_check_gl_error(GL_INVALID_OPERATION) && pass; glDeleteBuffersARB(1, fbs); glBindBufferARB(GL_PIXEL_UNPACK_BUFFER, 0); /* test that glReadPixels into too small of buffer raises error */ glGenBuffersARB(1, fbs); glBindBufferARB(GL_PIXEL_PACK_BUFFER, fbs[0]); glBufferDataARB(GL_PIXEL_PACK_BUFFER_ARB, 32 * 32 * 4, NULL, GL_STREAM_DRAW); glReadPixels(0, 0, 32, 32 + 1, GL_BGRA, GL_UNSIGNED_BYTE, NULL); pass = piglit_check_gl_error(GL_INVALID_OPERATION) && pass; glDeleteBuffersARB(1, fbs); glBindBufferARB(GL_PIXEL_PACK_BUFFER, 0); /* test that glTexImage2D raises an error when the buffer is too small */ glGenBuffers(1, fbs); glBindBuffer(GL_PIXEL_UNPACK_BUFFER, fbs[0]); glBufferData(GL_PIXEL_UNPACK_BUFFER, 4 * (32 * 32 - 1), NULL, GL_STREAM_DRAW); glGenTextures(1, &tex); glBindTexture(GL_TEXTURE_2D, tex); pass = piglit_check_gl_error(GL_NO_ERROR) && pass; glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); pass = piglit_check_gl_error(GL_INVALID_OPERATION) && pass; glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 32, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, (void*)(32 * 16 * 4)); pass = piglit_check_gl_error(GL_INVALID_OPERATION) && pass; glDeleteTextures(1, &tex); glDeleteBuffers(1, fbs); /* test that glGetTexImage raises an error when the buffer is too small */ glGenBuffers(1, fbs); glBindBuffer(GL_PIXEL_PACK_BUFFER, fbs[0]); glBufferData(GL_PIXEL_PACK_BUFFER, 4 * (32 * 32 - 1), NULL, GL_STREAM_DRAW); glGenTextures(1, &tex); glBindTexture(GL_TEXTURE_2D, tex); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); pass = piglit_check_gl_error(GL_NO_ERROR) && pass; glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); pass = piglit_check_gl_error(GL_INVALID_OPERATION) && pass; glDeleteTextures(1, &tex); glDeleteBuffers(1, fbs); return pass ? PIGLIT_PASS : PIGLIT_FAIL; } enum piglit_result piglit_display(void) { enum piglit_result result = PIGLIT_PASS; static struct piglit_subtest funcs[] = { { "test_sanity", "", test_sanity, NULL }, { "test_draw_pixels", "", test_draw_pixels, NULL }, { "test_pixel_map", "", test_pixel_map, NULL }, { "test_bitmap", "", test_bitmap, NULL }, { "test_tex_image", "", test_tex_image, NULL }, { "test_tex_sub_image", "", test_tex_sub_image, NULL }, { "test_polygon_stip", "", test_polygon_stip, NULL }, { "test_error_handling", "", test_error_handling, NULL }, { NULL, NULL, NULL, NULL } /* End of list sentinal */ }; result = piglit_run_selected_subtests(funcs, NULL, 0, result); return result; }