2 * Copyright © 2021 Intel Corporation
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24 #include "sample_common.h"
25 #include "image_common.h"
30 * Verifies that we can correctly sample from an image that was:
32 * - Exported as DMA BUF
33 * - Imported as EGLImage/Texture
36 PIGLIT_GL_TEST_CONFIG_BEGIN
38 config
.supports_gl_es_version
= 30;
40 PIGLIT_GL_TEST_CONFIG_END
42 #define CLEAR_VALUE 1.0, 1.0, 1.0, 1.0
51 tex_clear(GLuint tex
, uint32_t w
, uint32_t h
)
54 glGenFramebuffers(1, &fbo
);
55 glBindFramebuffer(GL_FRAMEBUFFER
, fbo
);
56 glFramebufferTexture(GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
, tex
, 0);
58 const float ones
[] = { CLEAR_VALUE
};
59 glClearBufferfv(GL_COLOR
, 0, ones
);
61 glDeleteFramebuffers(1, &fbo
);
62 glBindFramebuffer(GL_FRAMEBUFFER
, 0);
66 create_cleared_eglImage(EGLDisplay egl_dpy
, int w
, int h
)
69 glGenTextures(1, &tex
);
70 glBindTexture(GL_TEXTURE_2D
, tex
);
71 glTexStorage2D(GL_TEXTURE_2D
, 1, GL_RGBA8
, w
, h
);
74 eglCreateImageKHR(egl_dpy
, eglGetCurrentContext(),
75 EGL_GL_TEXTURE_2D_KHR
,
76 (EGLClientBuffer
)(uintptr_t)tex
,
79 glDeleteTextures(1, &tex
);
84 eglImage_to_dma_buf(EGLDisplay egl_dpy
, EGLImageKHR img
,
85 int *fourcc
, int *num_planes
, EGLuint64KHR
*modifiers
,
86 int *fd
, EGLint
*stride
, EGLint
*offset
)
88 PFNEGLEXPORTDMABUFIMAGEQUERYMESAPROC dmabuf_query
;
89 PFNEGLEXPORTDMABUFIMAGEMESAPROC dmabuf_export
;
92 (PFNEGLEXPORTDMABUFIMAGEQUERYMESAPROC
) eglGetProcAddress(
93 "eglExportDMABUFImageQueryMESA");
95 (PFNEGLEXPORTDMABUFIMAGEMESAPROC
) eglGetProcAddress(
96 "eglExportDMABUFImageMESA");
98 if (!dmabuf_query
|| !dmabuf_export
) {
99 fprintf(stderr
, "could not find extension entrypoints\n");
104 /* Query the image properties, verify fourcc and num planes. */
105 if (!dmabuf_query(egl_dpy
, img
, fourcc
, num_planes
, modifiers
))
108 if (!piglit_check_egl_error(EGL_SUCCESS
))
111 if (*num_planes
!= 1) {
112 fprintf(stderr
, "Test only supports single plane\n");
113 piglit_report_result(PIGLIT_SKIP
);
116 /* Export the image, verify success. */
117 if (!dmabuf_export(egl_dpy
, img
, fd
, stride
, offset
))
120 if (!piglit_check_egl_error(EGL_SUCCESS
))
123 /* Verify that we got a valid stride and offset for the fd. */
124 if (*fd
!= -1 && (*stride
< 1 || *offset
< 0)) {
125 fprintf(stderr
, "invalid data from driver: "
126 "fd %d stride %d offset %d\n",
127 *fd
, *stride
, *offset
);
135 dma_buf_to_eglImage(EGLDisplay egl_dpy
, EGLImageKHR
*out_img
, int w
, int h
,
136 int fourcc
, int num_planes
, EGLuint64KHR modifier
,
137 int fd
, EGLint stride
, EGLint offset
)
139 const EGLint attrs
[] = {
140 EGL_IMAGE_PRESERVED
, EGL_TRUE
,
143 EGL_LINUX_DRM_FOURCC_EXT
, fourcc
,
144 EGL_DMA_BUF_PLANE0_FD_EXT
, fd
,
145 EGL_DMA_BUF_PLANE0_OFFSET_EXT
, offset
,
146 EGL_DMA_BUF_PLANE0_PITCH_EXT
, stride
,
147 EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT
, modifier
,
148 EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT
, modifier
>> 32,
152 EGLImageKHR img
= eglCreateImageKHR(eglGetCurrentDisplay(),
154 EGL_LINUX_DMA_BUF_EXT
,
155 (EGLClientBuffer
)0, attrs
);
157 if (!piglit_check_egl_error(EGL_SUCCESS
)) {
167 test(EGLDisplay egl_dpy
, bool glfinish_after_dmabuf_export
)
169 /* Create EGLImage */
172 EGLImageKHR img
= create_cleared_eglImage(egl_dpy
, w
, h
);
174 /* Conditionally finish the clear */
175 if (!glfinish_after_dmabuf_export
)
178 /* Export DMABUF from EGLImage */
181 EGLuint64KHR modifiers
[64] = { -1, };
185 if (!eglImage_to_dma_buf(egl_dpy
, img
, &fourcc
, &num_planes
,
186 modifiers
, &fd
, &stride
, &offset
)) {
187 fprintf(stderr
, "image export failed!\n");
188 piglit_report_result(PIGLIT_FAIL
);
191 /* Conditionally finish the clear */
192 if (glfinish_after_dmabuf_export
)
195 /* Delete the EGLImage. */
196 eglDestroyImageKHR(egl_dpy
, img
);
198 /* Import EGLImage from DMABUF */
199 EGLImageKHR imported_img
;
200 if (!dma_buf_to_eglImage(egl_dpy
, &imported_img
, w
, h
,
202 modifiers
[0], fd
, stride
, offset
)) {
203 fprintf(stderr
, "dmabuf import failed!\n");
204 piglit_report_result(PIGLIT_FAIL
);
207 /* Draw EGLImage contents */
209 texture_for_egl_image(imported_img
, &imported_tex
, true);
210 sample_tex(imported_tex
, 0, 0, 1, piglit_height
, true);
212 /* Verify the contents */
213 const float ones
[] = { CLEAR_VALUE
};
214 return piglit_probe_pixel_rgba(0, 0, ones
);
218 piglit_init(int argc
, char **argv
)
220 EGLDisplay egl_dpy
= eglGetCurrentDisplay();
222 piglit_require_egl_extension(egl_dpy
, "EGL_MESA_image_dma_buf_export");
223 piglit_require_egl_extension(egl_dpy
, "EGL_EXT_image_dma_buf_import");
224 piglit_require_egl_extension(egl_dpy
, "EGL_KHR_gl_texture_2D_image");
225 piglit_require_extension("GL_OES_EGL_image_external");
226 piglit_require_extension("GL_EXT_EGL_image_storage");
228 printf("Testing glFinish before dmabuf export\n");
229 if (!test(egl_dpy
, false))
230 piglit_report_result(PIGLIT_FAIL
);
232 printf("Testing glFinish after dmabuf export\n");
233 if (!test(egl_dpy
, true))
234 piglit_report_result(PIGLIT_FAIL
);
236 piglit_report_result(PIGLIT_PASS
);