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 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; }
/** * 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; }
PIGLIT_GL_TEST_CONFIG_END static enum piglit_result test_create_and_destroy(unsigned w, unsigned h, void *buf, int fd, unsigned stride, unsigned offset) { EGLint error; EGLImageKHR img; EGLint attr[] = { EGL_WIDTH, w, EGL_HEIGHT, h, EGL_LINUX_DRM_FOURCC_EXT, DRM_FORMAT_ARGB8888, EGL_DMA_BUF_PLANE0_FD_EXT, fd, EGL_DMA_BUF_PLANE0_OFFSET_EXT, offset, EGL_DMA_BUF_PLANE0_PITCH_EXT, stride, EGL_NONE }; img = eglCreateImageKHR(eglGetCurrentDisplay(), EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, (EGLClientBuffer)0, attr); /* Release the creator side of the buffer. */ piglit_destroy_dma_buf(buf); error = eglGetError(); /* EGL may not support the format, this is not an error. */ if (!img && error == EGL_BAD_MATCH) return PIGLIT_SKIP; if (error != EGL_SUCCESS) { fprintf(stderr, "eglCreateImageKHR() failed: %s 0x%x\n", piglit_get_egl_error_name(error), error); return PIGLIT_FAIL; } if (!img) { fprintf(stderr, "image creation succeed but returned NULL\n"); return PIGLIT_FAIL; } eglDestroyImageKHR(eglGetCurrentDisplay(), img); if (!piglit_check_egl_error(EGL_SUCCESS)) return PIGLIT_FAIL; /** * EGL stack is allowed to keep the importing file descriptor open until * all resources are released. Therefore close the display first. */ if (!eglTerminate(eglGetCurrentDisplay())) { fprintf(stderr, "eglTerminate() failed\n"); return PIGLIT_FAIL; } /* * Our own file descriptor must still be valid, and therefore * closing it must succeed. */ return close(fd) == 0 ? PIGLIT_PASS : PIGLIT_FAIL; }
static enum piglit_result sample_buffer(void *buf, int fd, int fourcc, unsigned w, unsigned h, unsigned stride, unsigned offset) { EGLint error; EGLImageKHR img; EGLint attr_packed[] = { EGL_WIDTH, w, EGL_HEIGHT, h, EGL_LINUX_DRM_FOURCC_EXT, fourcc, EGL_DMA_BUF_PLANE0_FD_EXT, fd, EGL_DMA_BUF_PLANE0_OFFSET_EXT, offset, EGL_DMA_BUF_PLANE0_PITCH_EXT, stride, EGL_NONE }; EGLint attr_nv12[] = { EGL_WIDTH, w, EGL_HEIGHT, h, EGL_LINUX_DRM_FOURCC_EXT, fourcc, EGL_DMA_BUF_PLANE0_FD_EXT, fd, EGL_DMA_BUF_PLANE0_OFFSET_EXT, offset, EGL_DMA_BUF_PLANE0_PITCH_EXT, stride, EGL_DMA_BUF_PLANE1_FD_EXT, fd, EGL_DMA_BUF_PLANE1_OFFSET_EXT, offset + h * stride, EGL_DMA_BUF_PLANE1_PITCH_EXT, stride, EGL_NONE }; EGLint attr_yuv420[] = { EGL_WIDTH, w, EGL_HEIGHT, h, EGL_LINUX_DRM_FOURCC_EXT, fourcc, EGL_DMA_BUF_PLANE0_FD_EXT, fd, EGL_DMA_BUF_PLANE0_OFFSET_EXT, offset, EGL_DMA_BUF_PLANE0_PITCH_EXT, stride, EGL_DMA_BUF_PLANE1_FD_EXT, fd, EGL_DMA_BUF_PLANE1_OFFSET_EXT, offset + h * stride, EGL_DMA_BUF_PLANE1_PITCH_EXT, stride, EGL_DMA_BUF_PLANE2_FD_EXT, fd, EGL_DMA_BUF_PLANE2_OFFSET_EXT, offset + h * stride + w / 2, EGL_DMA_BUF_PLANE2_PITCH_EXT, stride, EGL_NONE }; EGLint *attr; switch (fourcc) { case DRM_FORMAT_NV12: attr = attr_nv12; break; case DRM_FORMAT_YUV420: case DRM_FORMAT_YVU420: attr = attr_yuv420; break; default: attr = attr_packed; break; } img = eglCreateImageKHR(eglGetCurrentDisplay(), EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, (EGLClientBuffer)0, attr); /* Release the creator side of the buffer. */ piglit_destroy_dma_buf(buf); error = eglGetError(); /* EGL may not support the format, this is not an error. */ if (!img && error == EGL_BAD_MATCH) return PIGLIT_SKIP; if (error != EGL_SUCCESS) { printf("eglCreateImageKHR() failed: %s 0x%x\n", piglit_get_egl_error_name(error), error); /* Close the descriptor also, EGL does not have ownership */ close(fd); return PIGLIT_FAIL; } if (!img) { fprintf(stderr, "image creation succeeded but returned NULL\n"); return PIGLIT_FAIL; } return sample_and_destroy_img(w, h, img); }