/** * Verify that eglCreateSyncKHR emits correct error when no context is current. * * From the EGL_KHR_fence_sync spec: * * If <type> is EGL_SYNC_FENCE_KHR and no context is current for * the bound API (i.e., eglGetCurrentContext returns * EGL_NO_CONTEXT), EGL_NO_SYNC_KHR is returned and an * EGL_BAD_MATCH error is generated. */ static enum piglit_result test_eglCreateSyncKHR_no_current_context(void *test_data) { enum piglit_result result = PIGLIT_PASS; EGLSyncKHR sync = 0; result = test_setup(); if (result != PIGLIT_PASS) { return result; } eglMakeCurrent(g_dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); sync = peglCreateSyncKHR(g_dpy, EGL_SYNC_TYPE_KHR, NULL); if (sync) { piglit_loge("eglCreateSyncKHR() succeeded when no context was " "current"); peglDestroySyncKHR(g_dpy, sync); result = PIGLIT_FAIL; } if (!piglit_check_egl_error(EGL_BAD_MATCH)) { piglit_loge("eglCreateSyncKHR emitted wrong error"); result = PIGLIT_FAIL; } test_cleanup(sync, &result); return result; }
/** * Verify that eglCreateSyncKHR emits correct error when given an invalid * sync type. * * From the EGL_KHR_fence_sync spec: * * If <type> is not a supported type of sync object, * EGL_NO_SYNC_KHR is returned and an EGL_BAD_ATTRIBUTE error is * generated. * * TODO(chadv,joshtriplett): eglCreateSyncKHR should generate EGL_BAD_PARAMETER * TODO: on bad sync types, not EGL_BAD_ATTRIBUTE. Bug filed in Khronos private * TODO: Bugzilla; update the test when resolved. */ static enum piglit_result test_eglCreateSyncKHR_invalid_sync_type(void *test_data) { enum piglit_result result = PIGLIT_PASS; EGLSyncKHR sync = 0; EGLenum bad_sync_type = EGL_SYNC_TYPE_KHR; result = test_setup(); if (result != PIGLIT_PASS) { return result; } sync = peglCreateSyncKHR(g_dpy, bad_sync_type, NULL); if (sync) { piglit_loge("eglCreateSyncKHR() succeeded with invalid " "sync type"); result = PIGLIT_FAIL; } if (!piglit_check_egl_error(EGL_BAD_ATTRIBUTE)) { piglit_loge("eglCreateSyncKHR emitted wrong error"); result = PIGLIT_FAIL; } test_cleanup(sync, &result); return result; }
/** * Verify that eglDestroySyncKHR() emits the correct error when given an * invalid sync object. * * From the EGL_KHR_fence_sync spec: * * * If <sync> is not a valid sync object for <dpy>, EGL_FALSE is * returned and an EGL_BAD_PARAMETER error is generated. */ static enum piglit_result test_eglDestroySyncKHR_invalid_sync(void *test_data) { enum piglit_result result = PIGLIT_PASS; bool ok = false; EGLSyncKHR invalid_sync = (EGLSyncKHR) &canary; result = test_setup(); if (result != PIGLIT_PASS) { return result; } ok = peglDestroySyncKHR(g_dpy, invalid_sync); if (ok) { piglit_loge("eglDestroySyncKHR() succeeded when given invalid " "sync object"); result = PIGLIT_FAIL; } if (!piglit_check_egl_error(EGL_BAD_PARAMETER)) { piglit_loge("eglGetSyncAttribKHR(EGL_SYNC_TYPE_KHR) emitted " "an incorrect error"); result = PIGLIT_FAIL; } test_cleanup(EGL_NO_SYNC_KHR, &result); return result; }
/** * Verify that eglClientWaitSyncKHR() accepts the * EGL_SYNC_FLUSH_COMMANDS_BIT_KHR flag. * * From the EGL_KHR_fence_sync: * * Accepted in the <flags> parameter of eglClientWaitSyncKHR: * EGL_SYNC_FLUSH_COMMANDS_BIT_KHR 0x0001 */ static enum piglit_result test_eglClientWaitSyncKHR_flag_sync_flush(void *test_data) { enum piglit_result result = PIGLIT_PASS; EGLSyncKHR sync = 0; EGLint wait_status = 0; result = test_setup(); if (result != PIGLIT_PASS) { return result; } glClear(GL_COLOR_BUFFER_BIT); sync = peglCreateSyncKHR(g_dpy, EGL_SYNC_FENCE_KHR, NULL); if (!sync) { piglit_loge("eglCreateSyncKHR(EGL_SYNC_FENCE_KHR) failed"); result = PIGLIT_FAIL; goto cleanup; } wait_status = peglClientWaitSyncKHR(g_dpy, sync, EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, 0); if (wait_status != EGL_TIMEOUT_EXPIRED_KHR && wait_status != EGL_CONDITION_SATISFIED_KHR) { piglit_loge("eglClientWaitSyncKHR() before glFinish:\n" " Expected status: EGL_TIMEOUT_EXPIRED_KHR or " " EGL_CONDITION_SATISFIED_KHR\n" " Actual status: 0x%x\n", wait_status); result = PIGLIT_FAIL; } cleanup: test_cleanup(sync, &result); return result; }
/** * Verify that eglGetSyncAttribKHR emits the correct error when given an object * that is not a sync object. * * From the EGL_KHR_fence_sync: * * * If <sync> is not a valid sync object for <dpy>, EGL_FALSE is * returned and an EGL_BAD_PARAMETER error is generated. * * [...] * * If any error occurs, <*value> is not modified. */ static enum piglit_result test_eglGetSyncAttribKHR_invalid_sync(void *test_data) { enum piglit_result result = PIGLIT_PASS; bool ok = false; EGLint sync_type = canary; EGLSyncKHR invalid_sync = (EGLSyncKHR) &canary; result = test_setup(); if (result != PIGLIT_PASS) { return result; } ok = peglGetSyncAttribKHR(g_dpy, invalid_sync, EGL_SYNC_TYPE_KHR, &sync_type); if (ok) { piglit_loge("eglGetSyncAttribKHR incorrectly succeeded when " "given an invalid sync object"); result = PIGLIT_FAIL; } if (!piglit_check_egl_error(EGL_BAD_PARAMETER)) { piglit_loge("eglGetSyncAttribKHR emitted wrong error"); result = PIGLIT_FAIL; } if (sync_type != canary) { piglit_loge("eglGetSynAttribKHR modified out parameter <value>"); result = PIGLIT_FAIL; } test_cleanup(EGL_NO_SYNC_KHR, &result); return result; }
static EGLDisplay create_display(void) { EGLDisplay dpy; bool ok; EGLint egl_major, egl_minor; dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY); if (!dpy) { fprintf(stderr, "failed to get EGLDisplay\n"); piglit_report_result(PIGLIT_SKIP); } ok = eglInitialize(dpy, &egl_major, &egl_minor); if (!ok) { EGLint egl_error = eglGetError(); piglit_loge("failed to get EGLConfig: %s(0x%x)", piglit_get_egl_error_name(egl_error), egl_error); piglit_report_result(PIGLIT_FAIL); } if (!piglit_is_egl_extension_supported(dpy, "EGL_KHR_gl_renderbuffer_image")) { piglit_loge("display does not support EGL_KHR_gl_renderbuffer_image\n"); piglit_report_result(PIGLIT_SKIP); } eglCreateImageKHR = (void*) eglGetProcAddress("eglCreateImageKHR"); if (!eglCreateImageKHR) { fprintf(stderr, "eglGetProcAddress(\"eglCreateImageKHR\") failed\n"); piglit_report_result(PIGLIT_FAIL); } return dpy; }
/** * Verify that eglClientWaitSyncKHR() emits correct error when given an invalid * sync object. * * From the EGL_KHR_fence_sync: * * * If <sync> is not a valid sync object for <dpy>, EGL_FALSE is * returned and an EGL_BAD_PARAMETER error is generated. */ static enum piglit_result test_eglClientWaitSyncKHR_invalid_sync(void *test_data) { enum piglit_result result = PIGLIT_PASS; EGLint wait_status = 0; EGLSyncKHR invalid_sync = (EGLSyncKHR) &canary; result = test_setup(); if (result != PIGLIT_PASS) { return result; } wait_status = peglClientWaitSyncKHR(g_dpy, invalid_sync, 0, 0); if (wait_status != EGL_FALSE) { piglit_loge("Given an invalid sync object, eglClientWaitSyncKHR() " "should return EGL_FALSE, but returned 0x%x", wait_status); result = PIGLIT_FAIL; } if (!piglit_check_egl_error(EGL_BAD_PARAMETER)) { piglit_loge("Given an invalid sync object, eglClientWaitSyncKHR() " "did not emit EGL_BAD_PARAMETER"); result = PIGLIT_FAIL; } test_cleanup(EGL_NO_SYNC_KHR, &result); return result; }
/** * Verify that eglCreateSyncKHR emits correct error when given an invalid * attribute list. * * From the EGL_KHR_fence_sync spec: * * If <attrib_list> is neither NULL nor empty (containing only * EGL_NONE), EGL_NO_SYNC_KHR is returned and an EGL_BAD_ATTRIBUTE * error is generated. */ static enum piglit_result test_eglCreateSyncKHR_invalid_attrib_list(void *test_data) { enum piglit_result result = PIGLIT_PASS; EGLSyncKHR sync = 0; const EGLint attrib_list[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE, }; result = test_setup(); if (result != PIGLIT_PASS) { return result; } sync = peglCreateSyncKHR(g_dpy, EGL_SYNC_FENCE_KHR, attrib_list); if (sync) { piglit_loge("eglCreateSyncKHR() succeeded with invalid " "attrib list"); result = PIGLIT_FAIL; } if (!piglit_check_egl_error(EGL_BAD_ATTRIBUTE)) { piglit_loge("eglCreateSyncKHR emitted wrong error"); result = PIGLIT_FAIL; } test_cleanup(sync, &result); return result; }
static void* thread2_create_sync_with_display_bound_in_other_thread(void *arg) { enum piglit_result *result; EGLDisplay t2_dpy = 0; EGLContext t2_ctx = 0; EGLSyncKHR t2_sync = 0; result = malloc(sizeof(*result)); *result = PIGLIT_FAIL; piglit_logi("create second EGLDisplay"); *result = init_other_display(&t2_dpy, g_dpy); if (*result != PIGLIT_PASS) { piglit_loge("failed to initialize a second EGLDisplay"); goto cleanup; } if (!piglit_is_egl_extension_supported(t2_dpy, "EGL_KHR_fence_sync")) { piglit_loge("EGL_KHR_fence_sync unsupported on second display"); *result = PIGLIT_SKIP; goto cleanup; } piglit_logi("create and make context current on second display"); *result = init_context(t2_dpy, &t2_ctx); if (*result != PIGLIT_PASS) { goto cleanup; } *result = check_sync_in_current_context(); if (*result != PIGLIT_PASS) { goto cleanup; } piglit_logi("try to create sync on first display, which is " "bound on thread1"); t2_sync = peglCreateSyncKHR(t2_dpy, EGL_SYNC_FENCE_KHR, NULL); if (t2_sync) { piglit_loge("eglCreateSyncKHR incorrectly succeeded"); *result = PIGLIT_FAIL; goto cleanup; } if (!piglit_check_egl_error(EGL_BAD_MATCH)) { piglit_loge("eglCreateSyncKHR emitted wrong error"); *result = PIGLIT_FAIL; goto cleanup; } piglit_logi("eglCreateSyncKHR correctly failed with " "EGL_BAD_MATCH"); cleanup: if (t2_dpy) { eglMakeCurrent(t2_dpy, 0, 0, 0); eglTerminate(t2_dpy); } return result; }
static GLuint create_dma_buf_texture(uint32_t width, uint32_t height, uint32_t fourcc, const void *pixels) { EGLDisplay dpy = eglGetCurrentDisplay(); enum piglit_result result = PIGLIT_PASS; struct piglit_dma_buf *dma_buf; EGLImageKHR image; EGLint image_attrs[13]; GLuint tex; int i; result = piglit_create_dma_buf(width, height, fourcc, pixels, &dma_buf); if (result != PIGLIT_PASS) { piglit_loge("failed to create dma_buf"); piglit_report_result(result); } i = 0; image_attrs[i++] = EGL_LINUX_DRM_FOURCC_EXT; image_attrs[i++] = fourcc; image_attrs[i++] = EGL_WIDTH; image_attrs[i++] = width; image_attrs[i++] = EGL_HEIGHT; image_attrs[i++] = height; image_attrs[i++] = EGL_DMA_BUF_PLANE0_FD_EXT; image_attrs[i++] = dma_buf->fd; image_attrs[i++] = EGL_DMA_BUF_PLANE0_PITCH_EXT; image_attrs[i++] = dma_buf->stride[0]; image_attrs[i++] = EGL_DMA_BUF_PLANE0_OFFSET_EXT; image_attrs[i++] = dma_buf->offset[0]; image_attrs[i++] = EGL_NONE; image = eglCreateImageKHR(dpy, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, (EGLClientBuffer) NULL, image_attrs); if (image == EGL_NO_IMAGE_KHR) { piglit_loge("failed to create EGLImage from dma_buf"); piglit_report_result(PIGLIT_FAIL); } glGenTextures(1, &tex); glBindTexture(GL_TEXTURE_2D, tex); glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES) image); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); if (!piglit_check_gl_error(GL_NO_ERROR)) piglit_report_result(PIGLIT_FAIL); return tex; }
int main(int argc, char **argv) { GLenum internal_format = 0; EGLDisplay dpy; EGLContext ctx; bool ok; /* Strip common piglit args. */ piglit_strip_arg(&argc, argv, "-fbo"); piglit_strip_arg(&argc, argv, "-auto"); if (argc == 2) { if (streq(argv[1], "GL_RGBA")) { internal_format = GL_RGBA; } else if (streq(argv[1], "GL_DEPTH_COMPONENT24")) { internal_format = GL_DEPTH_COMPONENT24; } } if (internal_format == 0) usage_error(); dpy = create_display(); ctx = create_context(dpy); ok = eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, ctx); if (!ok) { piglit_loge("failed to make context current without surface"); piglit_report_result(PIGLIT_FAIL); } piglit_dispatch_default_init(PIGLIT_DISPATCH_ES2); if (!piglit_is_extension_supported("GL_OES_EGL_image")) { piglit_loge("context does not support GL_OES_EGL_image"); piglit_report_result(PIGLIT_SKIP); } switch (internal_format) { case GL_RGBA: test_rgba(dpy, ctx); break; case GL_DEPTH_COMPONENT24: test_depth24(dpy, ctx); break; default: break; } /* unreachable */ abort(); }
/** * Verify that eglCreateSyncKHR() emits correct error when given a display that * does not match the display of the bound context. * * From the EGL_KHR_fence_sync spec: * * * If <type> is EGL_SYNC_FENCE_KHR and <dpy> does not match the * EGLDisplay of the currently bound context for the currently * bound client API (the EGLDisplay returned by * eglGetCurrentDisplay()) then EGL_NO_SYNC_KHR is returned and an * EGL_BAD_MATCH error is generated. * * This test strives to avoid false passes. It initializes a second display in * a second thread and binds a context there, then verifies that EGL can * successfully create and wait on fence syncs in each thread. Then, one thread * calls eglCreateSyncKHR, supplying the display bound in the other thread. * The verification step reduces the possibility that eglCreateSyncKHR fails * for some reason not under test. */ static enum piglit_result test_eglCreateSyncKHR_with_display_bound_in_other_thread(void *test_data) { enum piglit_result result = PIGLIT_PASS; enum piglit_result *t2_result = NULL; bool orig_print_tid; pthread_t thread2; int err; orig_print_tid = piglit_log_get_opt(PIGLIT_LOG_PRINT_TID); piglit_log_set_opt(PIGLIT_LOG_PRINT_TID, true); result = test_setup(); if (result != PIGLIT_PASS) { goto cleanup; } result = check_sync_in_current_context(); if (result != PIGLIT_PASS) { goto cleanup; } err = pthread_create( &thread2, NULL, thread2_create_sync_with_display_bound_in_other_thread, NULL); if (err) { piglit_loge("failed to create second thread"); result = PIGLIT_FAIL; goto cleanup; } err = pthread_join(thread2, (void**) &t2_result); if (err) { piglit_loge("failed to join thread %"PRIuMAX, (uintmax_t) thread2); result = PIGLIT_FAIL; goto cleanup; } if (t2_result) { piglit_merge_result(&result, *t2_result); } else { piglit_loge("thread %"PRIuMAX" returned no piglit_result"); result = PIGLIT_FAIL; } cleanup: free(t2_result); piglit_log_set_opt(PIGLIT_LOG_PRINT_TID, orig_print_tid); test_cleanup(EGL_NO_SYNC_KHR, &result); return result; }
static EGLContext create_context(EGLDisplay dpy) { bool ok = false; EGLConfig config = 0; EGLint num_configs = 0; EGLContext ctx = 0; static const EGLint config_attribs[] = { EGL_RED_SIZE, EGL_DONT_CARE, EGL_GREEN_SIZE, EGL_DONT_CARE, EGL_BLUE_SIZE, EGL_DONT_CARE, EGL_ALPHA_SIZE, EGL_DONT_CARE, EGL_DEPTH_SIZE, EGL_DONT_CARE, EGL_STENCIL_SIZE, EGL_DONT_CARE, EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT, EGL_SURFACE_TYPE, 0, EGL_NONE, }; static const EGLint context_attribs[] = { EGL_CONTEXT_MAJOR_VERSION, 3, EGL_CONTEXT_MINOR_VERSION, 2, EGL_NONE, }; ok = eglChooseConfig(dpy, config_attribs, &config, 1, &num_configs); if (!ok || !config || num_configs == 0) { EGLint egl_error = eglGetError(); piglit_loge("failed to get EGLConfig: %s(0x%x)", piglit_get_egl_error_name(egl_error), egl_error); piglit_report_result(PIGLIT_SKIP); } ok = piglit_egl_bind_api(EGL_OPENGL_API); if (!ok) { piglit_loge("failed to bind EGL_OPENGL_API"); piglit_report_result(PIGLIT_FAIL); } ctx = eglCreateContext(dpy, config, EGL_NO_CONTEXT, context_attribs); if (!ctx) { EGLint egl_error = eglGetError(); piglit_loge("failed to create EGLContext: %s(0x%x)", piglit_get_egl_error_name(egl_error), egl_error); piglit_report_result(PIGLIT_FAIL); } return ctx; }
static void parse_args(int *argc, char **argv, const char ***selected_subtests, size_t *num_selected_subtests) { *selected_subtests = NULL; *num_selected_subtests = 0; prog_name = basename(argv[0]); if (*argc == 1) { return; } if (streq(argv[1], "-h") || streq(argv[1], "--help")) { print_usage(); exit(0); } /* Strip common piglit args. */ piglit_strip_arg(argc, argv, "-fbo"); piglit_strip_arg(argc, argv, "-auto"); piglit_parse_subtest_args(argc, argv, subtests, selected_subtests, num_selected_subtests); if (*argc > 1) { piglit_loge("unrecognized option: %s", argv[1]); usage_error(); } }
static void validate_delta(GLint64 gl_ts1, GLint64 gl_ts2, GLint64 cpu_delay_ns) { GLint64 gl_ts_delta = gl_ts2 - gl_ts1; int64_t drift = llabs(cpu_delay_ns - gl_ts_delta); int64_t drift_per_sec = drift * 1000000000LL / cpu_delay_ns; /* XXX: technically we shouldn't be as strict about drift when the gpu * clock is running fast and the duration is longer than expected, * because we can't easily exclude other factors like OS scheduling * affecting the measurements. For now though we don't take this into * account. */ if (drift_per_sec > DRIFT_NS_PER_SEC_THRESHOLD) { printf("GL_TIMESTAMP 1 = %" PRId64 " us\n", gl_ts1 / 1000); printf("GL_TIMESTAMP 2 = %" PRId64 " us\n", gl_ts2 / 1000); printf("delta = %" PRId64 " us (expect >= %"PRId64" us)\n", gl_ts_delta / 1000, cpu_delay_ns / 1000); piglit_loge("GL_TIMESTAMP drift of %" PRId64 " ns/sec, greater than %" PRId64 " ns/sec", drift_per_sec, (int64_t)DRIFT_NS_PER_SEC_THRESHOLD); piglit_report_result(PIGLIT_FAIL); } else printf("GL_TIMESTAMP drift of approx. %" PRId64 " ns/sec\n", drift_per_sec); }
/** * Verify that eglClientWaitSyncKHR() accepts nonzero timeout values, including * EGL_FOREVER_KHR. */ static enum piglit_result test_eglClientWaitSyncKHR_nonzero_timeout(void *test_data) { enum piglit_result result = PIGLIT_PASS; EGLSyncKHR sync = 0; EGLint wait_status = 0; result = test_setup(); if (result != PIGLIT_PASS) { return result; } sync = peglCreateSyncKHR(g_dpy, EGL_SYNC_FENCE_KHR, NULL); if (!sync) { piglit_loge("eglCreateSyncKHR(EGL_SYNC_FENCE_KHR) failed"); result = PIGLIT_FAIL; goto cleanup; } /* There exist no pending GL commands, so the sync status should be * EGL_CONDITION_SATISFIED_KHR. */ wait_status = peglClientWaitSyncKHR(g_dpy, sync, 0, 0.5e9); if (wait_status != EGL_CONDITION_SATISFIED_KHR) { piglit_loge("eglClientWaitSyncKHR(timeout=0.5sec)\n" " Expected status EGL_CONDITION_SATISFIED_KHR(0x%x)\n" " Actual status 0x%x\n", EGL_CONDITION_SATISFIED_KHR, wait_status); result = PIGLIT_FAIL; } wait_status = peglClientWaitSyncKHR(g_dpy, sync, 0, EGL_FOREVER_KHR); if (wait_status != EGL_CONDITION_SATISFIED_KHR) { piglit_loge("eglClientWaitSyncKHR(timeout=forever)\n" " Expected status EGL_CONDITION_SATISFIED_KHR(0x%x)\n" " Actual status 0x%x\n", EGL_CONDITION_SATISFIED_KHR, wait_status); result = PIGLIT_FAIL; } cleanup: test_cleanup(sync, &result); return result; }
static void create_framebuffers(EGLDisplay dpy, EGLContext ctx, GLuint *fb1, GLuint *fb2, GLenum internal_format) { GLuint rb1, rb2; EGLImageKHR img; GLenum attachment_point = 0; switch (internal_format) { case GL_RGBA: attachment_point = GL_COLOR_ATTACHMENT0; break; case GL_DEPTH_COMPONENT24: attachment_point = GL_DEPTH_ATTACHMENT; break; default: abort(); } glGenRenderbuffers(1, &rb1); glBindRenderbuffer(GL_RENDERBUFFER, rb1); glRenderbufferStorage(GL_RENDERBUFFER, internal_format, width, height); if (!piglit_check_gl_error(GL_NO_ERROR)) piglit_report_result(PIGLIT_FAIL); glGenFramebuffers(1, fb1); glBindFramebuffer(GL_FRAMEBUFFER, *fb1); glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachment_point, GL_RENDERBUFFER, rb1); if (!piglit_check_gl_error(GL_NO_ERROR)) piglit_report_result(PIGLIT_FAIL); /* We intentionally create the EGLImage before using the renderbuffer. * This confuses some versions of the Intel driver. */ img = eglCreateImageKHR(dpy, ctx, EGL_GL_RENDERBUFFER_KHR, (EGLClientBuffer) (uintptr_t) rb1, NULL); if (img == EGL_NO_IMAGE_KHR) { /* Skip, not fail, because the spec allows the implementation * to reject image creation. */ piglit_loge("failed to create EGLImage"); piglit_report_result(PIGLIT_SKIP); } glGenRenderbuffers(1, &rb2); glBindRenderbuffer(GL_RENDERBUFFER, rb2); glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, img); if (!piglit_check_gl_error(GL_NO_ERROR)) piglit_report_result(PIGLIT_FAIL); glGenFramebuffers(1, fb2); glBindFramebuffer(GL_FRAMEBUFFER, *fb2); glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachment_point, GL_RENDERBUFFER, rb2); if (!piglit_check_gl_error(GL_NO_ERROR)) piglit_report_result(PIGLIT_FAIL); }
/** * Verify that eglGetSyncAttribKHR emits the correct error when querying an * unrecognized attribute of a fence sync. * * From the EGL_KHR_fence_sync: * * [eglGetSyncAttribKHR] is used to query attributes of the sync object * <sync>. Legal values for <attribute> depend on the type of sync object, * as shown in table * 3.cc. [...] * * Attribute Description Supported Sync Objects * ----------------- ----------------------- ---------------------- * EGL_SYNC_TYPE_KHR Type of the sync object All * EGL_SYNC_STATUS_KHR Status of the sync object All * EGL_SYNC_CONDITION_KHR Signaling condition EGL_SYNC_FENCE_KHR only * * Table 3.cc Attributes Accepted by eglGetSyncAttribKHR Command * * [...] * * * If <attribute> is not one of the attributes in table 3.cc, * EGL_FALSE is returned and an EGL_BAD_ATTRIBUTE error is * generated. * * [...] * * If any error occurs, <*value> is not modified. */ static enum piglit_result test_eglGetSyncAttribKHR_invalid_attrib(void *test_data) { enum piglit_result result = PIGLIT_PASS; bool ok = false; EGLSyncKHR sync = 0; EGLint attrib_value = canary; result = test_setup(); if (result != PIGLIT_PASS) { return result; } sync = peglCreateSyncKHR(g_dpy, EGL_SYNC_FENCE_KHR, NULL); if (!sync) { piglit_loge("eglCreateSyncKHR(EGL_SYNC_FENCE_KHR) failed"); result = PIGLIT_FAIL; goto cleanup; } ok = peglGetSyncAttribKHR(g_dpy, sync, EGL_BUFFER_PRESERVED, &attrib_value); if (ok) { piglit_loge("eglGetSyncAttribKHR(attrib=EGL_BUFFER_PRESERVED) " "incorrectly succeeded"); result = PIGLIT_FAIL; } if (!piglit_check_egl_error(EGL_BAD_ATTRIBUTE)) { piglit_loge("eglGetSyncAttribKHR emitted wrong error"); result = PIGLIT_FAIL; } if (attrib_value != canary) { piglit_loge("eglGetSynAttribKHR modified out parameter <value>"); result = PIGLIT_FAIL; } cleanup: test_cleanup(sync, &result); return result; }
/** * Verify that eglCreateSyncKHR() emits correct error when given a display that * does not match the display of the bound context. * * From the EGL_KHR_fence_sync spec: * * * If <type> is EGL_SYNC_FENCE_KHR and <dpy> does not match the * EGLDisplay of the currently bound context for the currently * bound client API (the EGLDisplay returned by * eglGetCurrentDisplay()) then EGL_NO_SYNC_KHR is returned and an * EGL_BAD_MATCH error is generated. * * This test verifies a simple case for the above error. It binds a context and * display to the main thread, creates a second display on the same threads but * does not bind it, then gives the second display to eglCreateSyncKHR(). */ static enum piglit_result test_eglCreateSyncKHR_wrong_display_same_thread(void *test_data) { enum piglit_result result = PIGLIT_PASS; EGLDisplay wrong_dpy = 0; EGLSyncKHR sync = 0; result = test_setup(); if (result != PIGLIT_PASS) { return result; } piglit_logi("create second EGLDisplay"); result = init_other_display(&wrong_dpy, g_dpy); if (result != PIGLIT_PASS) { goto cleanup; } piglit_require_egl_extension(wrong_dpy, "EGL_KHR_fence_sync"); piglit_logi("try to create sync with second display"); sync = peglCreateSyncKHR(wrong_dpy, EGL_SYNC_FENCE_KHR, NULL); if (sync) { piglit_loge("eglCreateSyncKHR() incorrectly succeeded"); result = PIGLIT_FAIL; goto cleanup; } if (!piglit_check_egl_error(EGL_BAD_MATCH)) { piglit_loge("eglCreateSyncKHR emitted wrong error"); result = PIGLIT_FAIL; goto cleanup; } cleanup: if (wrong_dpy) { eglTerminate(wrong_dpy); } test_cleanup(EGL_NO_SYNC_KHR, &result); return result; }
/** * Teardown state after each subtest completes. */ static void test_cleanup(EGLSyncKHR sync, enum piglit_result *inout_result) { bool ok = false; if (sync) { /* From the EGL_KHR_fence_sync spec: * * If no errors are generated, EGL_TRUE is returned, and * <sync> will no longer be the handle of a valid sync * object. */ ok = peglDestroySyncKHR(g_dpy, sync); if (!ok) { piglit_loge("eglDestroySyncKHR failed"); *inout_result = PIGLIT_FAIL; } if (!piglit_check_egl_error(EGL_SUCCESS)) { piglit_loge("eglDestroySyncKHR emitted an error"); *inout_result = PIGLIT_FAIL; } } /* Ensure that no leftover GL commands impact the next test. */ if (eglGetCurrentContext()) { glFinish(); } if (g_dpy) { eglMakeCurrent(g_dpy, 0, 0, 0); ok = eglTerminate(g_dpy); if (!ok) { piglit_loge("failed to terminate EGLDisplay"); *inout_result = PIGLIT_FAIL; } } g_dpy = EGL_NO_DISPLAY; g_ctx = EGL_NO_CONTEXT; }
/** * Verify that glClientWaitSyncKHR emits correct error when given invalid flag. * * From the EGL_KHR_fence_sync spec: * * Accepted in the <flags> parameter of eglClientWaitSyncKHR: * * EGL_SYNC_FLUSH_COMMANDS_BIT_KHR 0x0001 */ static enum piglit_result test_eglClientWaitSyncKHR_invalid_flag(void *test_data) { enum piglit_result result = PIGLIT_PASS; EGLSyncKHR sync = 0; EGLint wait_status = 0; EGLint invalid_flag = 0x8000; result = test_setup(); if (result != PIGLIT_PASS) { return result; } sync = peglCreateSyncKHR(g_dpy, EGL_SYNC_FENCE_KHR, NULL); if (!sync) { piglit_loge("eglCreateSyncKHR(EGL_SYNC_FENCE_KHR) failed"); result = PIGLIT_FAIL; goto cleanup; } /* Use timeout=0 so that eglClientWaitSyncKHR immediately returns. */ wait_status = peglClientWaitSyncKHR(g_dpy, sync, invalid_flag, 0); if (wait_status != EGL_FALSE) { piglit_loge("eglClientWaitSyncKHR succeeded when given invalid " "flag 0x%x", invalid_flag); result = PIGLIT_FAIL; } if (!piglit_check_egl_error(EGL_BAD_PARAMETER)) { piglit_loge("eglClientWaitSyncKHR emitted wrong error"); result = PIGLIT_FAIL; } cleanup: test_cleanup(sync, &result); return result; }
/** * Check that EGL can create and wait on sync fences in the current context. */ static enum piglit_result check_sync_in_current_context(void) { enum piglit_result result = PIGLIT_PASS; EGLDisplay dpy = eglGetCurrentDisplay(); EGLSyncKHR sync = 0; EGLint wait_status = 0; if (!eglGetCurrentContext()) { piglit_loge("no context is bound"); result = PIGLIT_FAIL; goto cleanup; } piglit_logi("verify that syncs can be created and waited on in " "this thread"); sync = peglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, NULL); if (!sync) { piglit_loge("eglCreateSyncKHR failed"); result = PIGLIT_FAIL; goto cleanup; } wait_status = peglClientWaitSyncKHR(dpy, sync, 0, 0); if (wait_status == EGL_FALSE) { piglit_loge("eglClientWaitSyncKHR failed"); result = PIGLIT_FAIL; goto cleanup; } cleanup: if (sync) { peglDestroySyncKHR(dpy, sync); } return result; }
/** * Verify that eglCreateSyncKHR emits correct error when given an invalid * display. * * From the EGL_KHR_fence_sync spec: * * If <dpy> is not the name of a valid, initialized EGLDisplay, * EGL_NO_SYNC_KHR is returned and an EGL_BAD_DISPLAY error is * generated. */ static enum piglit_result test_eglCreateSyncKHR_invalid_display(void *test_data) { enum piglit_result result = PIGLIT_PASS; EGLSyncKHR sync = 0; result = test_setup(); if (result != PIGLIT_PASS) { return result; } sync = peglCreateSyncKHR(EGL_NO_DISPLAY, EGL_SYNC_FENCE_KHR, NULL); if (sync) { piglit_loge("eglCreateSyncKHR(EGL_NO_DISPLAY) succeeded"); result = PIGLIT_FAIL; } if (!piglit_check_egl_error(EGL_BAD_DISPLAY)) { piglit_loge("eglCreateSyncKHR emitted wrong error"); result = PIGLIT_FAIL; } test_cleanup(sync, &result); return result; }
static enum piglit_result init_display(EGLenum platform, EGLDisplay *out_dpy) { enum piglit_result result = PIGLIT_PASS; EGLDisplay dpy; EGLint egl_major, egl_minor; bool ok; dpy = piglit_egl_get_default_display(platform); if (!dpy) { result = PIGLIT_SKIP; goto error; } ok = eglInitialize(dpy, &egl_major, &egl_minor); if (!ok) { result = PIGLIT_SKIP; goto error; } if (!piglit_is_egl_extension_supported(dpy, "EGL_KHR_fence_sync")) { piglit_loge("display does not support EGL_KHR_fence_sync"); result = PIGLIT_SKIP; goto error; } *out_dpy = dpy; return result; error: if (dpy) { eglTerminate(dpy); } return result; }
/** * Create OpenGL ES 2.0 context, make it current, and verify that it supports * GL_OES_EGL_sync. */ static enum piglit_result init_context(EGLDisplay dpy, EGLContext *out_ctx) { enum piglit_result result = PIGLIT_PASS; bool ok = false; EGLConfig config = 0; EGLint num_configs = 0; EGLContext ctx = 0; /* Create OpenGL ES 2.0 or backwards-compatible context. */ static const EGLint config_attribs[] = { EGL_RED_SIZE, EGL_DONT_CARE, EGL_GREEN_SIZE, EGL_DONT_CARE, EGL_BLUE_SIZE, EGL_DONT_CARE, EGL_ALPHA_SIZE, EGL_DONT_CARE, EGL_DEPTH_SIZE, EGL_DONT_CARE, EGL_STENCIL_SIZE, EGL_DONT_CARE, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT | EGL_OPENGL_ES3_BIT_KHR, EGL_NONE, }; static const EGLint context_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE, }; ok = eglChooseConfig(dpy, config_attribs, &config, 1, &num_configs); if (!ok || !config || num_configs == 0) { EGLint egl_error = eglGetError(); piglit_loge("failed to get EGLConfig: %s(0x%x)", piglit_get_egl_error_name(egl_error), egl_error); result = PIGLIT_SKIP; goto error; } ok = piglit_egl_bind_api(EGL_OPENGL_ES_API); if (!ok) { piglit_loge("failed to bind EGL_OPENGL_ES_API"); result = PIGLIT_FAIL; goto error; } ctx = eglCreateContext(dpy, config, EGL_NO_CONTEXT, context_attribs); if (!ctx) { EGLint egl_error = eglGetError(); piglit_loge("failed to create EGLContext: %s(0x%x)", piglit_get_egl_error_name(egl_error), egl_error); result = PIGLIT_FAIL; goto error; } ok = eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, ctx); if (!ok) { /* Skip, don't fail. Assume the context doesn't support * GL_OES_surfaceless_context or equivalent. */ piglit_loge("failed to make context current without surface"); result = PIGLIT_SKIP; goto error; } piglit_dispatch_default_init(PIGLIT_DISPATCH_ES2); /* From the EGL_KHR_fence_sync spec: * * Each client API which supports fence commands indicates this * support in the form of a client API extension. If the * GL_OES_EGL_sync extension is supported by OpenGL ES (either * version 1.x or 2.0), a fence sync object may be created when the * currently bound API is OpenGL ES. */ if (!piglit_is_extension_supported("GL_OES_EGL_sync")) { piglit_loge("context does not support GL_OES_EGL_sync; " "skipping test"); result = PIGLIT_SKIP; goto error; } *out_ctx = ctx; return result; error: if (ctx) { eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); eglDestroyContext(dpy, ctx); } return result; }
enum piglit_result piglit_display(void) { GLuint r8_tex, gr88_tex; float *ref_rgba_image; GLuint va; /* vertex array */ GLuint vb; /* vertex buffer */ GLuint prog; static const float vb_data[] = { -1, -1, 1, -1, 1, 1, -1, 1, }; if (piglit_width != WINDOW_WIDTH || piglit_height != WINDOW_HEIGHT) { piglit_loge("window is not %dx%d", WINDOW_WIDTH, WINDOW_HEIGHT); return PIGLIT_FAIL; } create_textures(&r8_tex, &gr88_tex, &ref_rgba_image); prog = piglit_build_simple_program( "#version 300 es\n" "\n" "in vec2 a_position;\n" "out vec2 v_texcoord;\n" "\n" "void main()\n" "{\n" " gl_Position = vec4(a_position, 0, 1);\n" "\n" " v_texcoord = a_position;\n" " v_texcoord += vec2(1, 1);\n" " v_texcoord /= vec2(2, 2);\n" "}\n", "#version 300 es\n" "\n" "precision highp float;\n" "uniform sampler2D u_r8_tex;\n" "uniform sampler2D u_gr88_tex;\n" "in vec2 v_texcoord;\n" "out vec4 f_color;\n" "\n" "void main()\n" "{\n" " float y = texture(u_r8_tex, v_texcoord).r;\n" " vec2 uv = texture(u_gr88_tex, v_texcoord).rg;\n" "\n" " /* A very fake NV12->RGB conversion */\n" " f_color = vec4(y, uv.r, uv.g, 1);\n" "}\n"); glUseProgram(prog); glUniform1i(glGetUniformLocation(prog, "u_r8_tex"), 0); glUniform1i(glGetUniformLocation(prog, "u_gr88_tex"), 1); if (!piglit_check_gl_error(GL_NO_ERROR)) piglit_report_result(PIGLIT_FAIL); glGenBuffers(1, &vb); glBindBuffer(GL_ARRAY_BUFFER, vb); glBufferData(GL_ARRAY_BUFFER, sizeof(vb_data), vb_data, GL_STATIC_DRAW); glGenVertexArrays(1, &va); glBindVertexArray(va); glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (void *) 0); glEnableVertexAttribArray(0); glViewport(0, 0, piglit_width, piglit_height); glClearColor(0.2, 0.2, 0.2, 0.2); glClear(GL_COLOR_BUFFER_BIT); glDrawArrays(GL_TRIANGLE_FAN, /*first*/ 0, /*count*/ 4); if (!piglit_check_gl_error(GL_NO_ERROR)) piglit_report_result(PIGLIT_FAIL); /* Increase the tolerance because the conversion path * ubyte --(texturing)--> float --(glReadPixels)--> ubyte * is lossy. */ piglit_tolerance[0] = 0.05; piglit_tolerance[1] = 0.05; piglit_tolerance[2] = 0.05; if (!piglit_probe_image_rgba(0, 0, piglit_width, piglit_height, ref_rgba_image)) { return PIGLIT_FAIL; } return PIGLIT_PASS; }
/** * Verify that eglGetSyncAttribKHR() reports correct sync status before and * after glFinish(). */ static enum piglit_result test_eglGetSyncAttribKHR_sync_status(void *test_data) { enum piglit_result result = PIGLIT_PASS; EGLSyncKHR sync = 0; EGLint sync_status = 0; bool ok = false; result = test_setup(); if (result != PIGLIT_PASS) { return result; } glClear(GL_COLOR_BUFFER_BIT); sync = peglCreateSyncKHR(g_dpy, EGL_SYNC_FENCE_KHR, NULL); if (!sync) { piglit_loge("eglCreateSyncKHR(EGL_SYNC_FENCE_KHR) failed"); result = PIGLIT_FAIL; goto cleanup; } ok = peglGetSyncAttribKHR(g_dpy, sync, EGL_SYNC_STATUS_KHR, &sync_status); if (!ok) { piglit_loge("before glFinish, eglGetSyncAttribKHR(EGL_SYNC_STATUS_KHR) " "failed"); result = PIGLIT_FAIL; } if (!piglit_check_egl_error(EGL_SUCCESS)) { piglit_loge("before glFinish, eglGetSyncAttribKHR(EGL_SYNC_STATUS_KHR) " "emitted an error"); result = PIGLIT_FAIL; } if (sync_status != EGL_SIGNALED_KHR && sync_status != EGL_UNSIGNALED_KHR) { piglit_loge("before glFinish, eglGetSyncAttribKHR(EGL_SYNC_STATUS_KHR):\n" " Expected status: EGL_SIGNALED_KHR or EGL_UNSIGNALED_KHR\n", " Actual status: 0x%x", sync_status); result = PIGLIT_FAIL; } glFinish(); ok = peglGetSyncAttribKHR(g_dpy, sync, EGL_SYNC_STATUS_KHR, &sync_status); if (!ok) { piglit_loge("after glFinish, eglGetSyncAttribKHR(EGL_SYNC_STATUS_KHR) " "failed"); result = PIGLIT_FAIL; } if (!piglit_check_egl_error(EGL_SUCCESS)) { piglit_loge("after glFinish, eglGetSyncAttribKHR(EGL_SYNC_STATUS_KHR) " "emitted an error"); result = PIGLIT_FAIL; } if (sync_status != EGL_SIGNALED_KHR) { piglit_loge("after glFinish, eglGetSyncAttribKHR(EGL_SYNC_STATUS_KHR):\n" " Expected status: EGL_SIGNALED_KHR\n", " Actual status: 0x%x", sync_status); result = PIGLIT_FAIL; } cleanup: test_cleanup(sync, &result); return result; }
/** * Verify that eglCreateSyncKHR(), when given an empty attribute list, * intializes the sync object's attributes to the correct values. * * From the EGL_KHR_fence_sync spec: * * Attributes not specified in the list will be assigned their default * values. * * Attributes of the fence sync object are * set as follows: * * Attribute Name Initial Attribute Value(s) * --------------- -------------------------- * EGL_SYNC_TYPE_KHR EGL_SYNC_FENCE_KHR * EGL_SYNC_STATUS_KHR EGL_UNSIGNALED_KHR * EGL_SYNC_CONDITION_KHR EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR */ static enum piglit_result test_eglCreateSyncKHR_default_attributes(void *test_data) { enum piglit_result result = PIGLIT_PASS; EGLSyncKHR sync = 0; EGLint sync_type = canary, sync_status = canary, sync_condition = canary; bool ok = false; result = test_setup(); if (result != PIGLIT_PASS) { return result; } sync = peglCreateSyncKHR(g_dpy, EGL_SYNC_FENCE_KHR, NULL); if (!sync) { piglit_loge("eglCreateSyncKHR(EGL_SYNC_FENCE_KHR) failed"); result = PIGLIT_FAIL; goto cleanup; } ok = peglGetSyncAttribKHR(g_dpy, sync, EGL_SYNC_TYPE_KHR, &sync_type); if (ok) { piglit_loge("eglGetSyncAttribKHR(EGL_SYNC_TYPE_KHR) failed"); result = PIGLIT_FAIL; } if (!piglit_check_egl_error(EGL_SUCCESS)) { piglit_loge("eglGetSyncAttribKHR(EGL_SYNC_TYPE_KHR) emitted " "an error"); result = PIGLIT_FAIL; } if (sync_type != EGL_SYNC_FENCE_KHR) { piglit_loge("eglGetSyncAttribKHR(EGL_SYNC_TYPE_KHR) returned " "0x%x but expected EGL_SYNC_FENCE_KHR(0x%x)", sync_type, EGL_SYNC_FENCE_KHR); result = PIGLIT_FAIL; } ok = peglGetSyncAttribKHR(g_dpy, sync, EGL_SYNC_STATUS_KHR, &sync_status); if (!ok) { piglit_loge("eglGetSyncAttribKHR(EGL_SYNC_STATUS_KHR) failed"); result = PIGLIT_FAIL; } if (!piglit_check_egl_error(EGL_SUCCESS)) { piglit_loge("eglGetSyncAttribKHR(EGL_SYNC_STATUS_KHR) emitted " "an error"); result = PIGLIT_FAIL; } if (sync_status != EGL_UNSIGNALED_KHR) { piglit_loge("eglGetSyncAttribKHR(EGL_SYNC_STATUS_KHR) returned " "0x%x but expected EGL_UNSIGNALED_KHR(0x%x)", sync_status, EGL_UNSIGNALED_KHR); result = PIGLIT_FAIL; } ok = peglGetSyncAttribKHR(g_dpy, sync, EGL_SYNC_CONDITION_KHR, &sync_condition); if (!ok) { piglit_loge("eglGetSyncAttribKHR(EGL_SYNC_CONDITION_KHR) failed"); result = PIGLIT_FAIL; } if (!piglit_check_egl_error(EGL_SUCCESS)) { piglit_loge("eglGetSyncAttribKHR(EGL_SYNC_CONDITION_KHR) " "emitted an error"); result = PIGLIT_FAIL; } if (sync_condition != EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR) { piglit_loge("eglGetSyncAttribKHR(EGL_SYNC_CONDITION_KHR) " "returned 0x%x but expected " "EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR(0x%x)", sync_condition, EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR); result = PIGLIT_FAIL; } cleanup: test_cleanup(sync, &result); return result; }