ext_image_dma_buf_import-export-tex: fix multi plane export
[piglit.git] / tests / spec / ext_image_dma_buf_import / export-tex.c
blobef25f20e77228f9dcfd3f82d249b2585418541ec
1 /*
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
13 * Software.
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
21 * IN THE SOFTWARE.
24 #include "sample_common.h"
25 #include "image_common.h"
27 /**
28 * @file export-tex.c
30 * Verifies that we can correctly sample from an image that was:
31 * - Rendered to
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
44 enum piglit_result
45 piglit_display(void)
47 return PIGLIT_PASS;
50 static void
51 tex_clear(GLuint tex, uint32_t w, uint32_t h)
53 GLuint fbo;
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);
65 static EGLImageKHR
66 create_cleared_eglImage(EGLDisplay egl_dpy, int w, int h)
68 GLuint tex;
69 glGenTextures(1, &tex);
70 glBindTexture(GL_TEXTURE_2D, tex);
71 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, w, h);
73 EGLImageKHR img =
74 eglCreateImageKHR(egl_dpy, eglGetCurrentContext(),
75 EGL_GL_TEXTURE_2D_KHR,
76 (EGLClientBuffer)(uintptr_t)tex,
77 NULL);
78 tex_clear(tex, w, h);
79 glDeleteTextures(1, &tex);
80 return img;
83 static bool
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;
91 dmabuf_query =
92 (PFNEGLEXPORTDMABUFIMAGEQUERYMESAPROC) eglGetProcAddress(
93 "eglExportDMABUFImageQueryMESA");
94 dmabuf_export =
95 (PFNEGLEXPORTDMABUFIMAGEMESAPROC) eglGetProcAddress(
96 "eglExportDMABUFImageMESA");
98 if (!dmabuf_query || !dmabuf_export) {
99 fprintf(stderr, "could not find extension entrypoints\n");
100 return false;
104 /* Query the image properties, verify fourcc and num planes. */
105 if (!dmabuf_query(egl_dpy, img, fourcc, num_planes, modifiers))
106 return false;
108 if (!piglit_check_egl_error(EGL_SUCCESS))
109 return false;
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))
118 return false;
120 if (!piglit_check_egl_error(EGL_SUCCESS))
121 return false;
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);
128 return false;
131 return true;
134 static bool
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,
141 EGL_WIDTH, w,
142 EGL_HEIGHT, h,
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,
149 EGL_NONE, EGL_NONE
152 EGLImageKHR img = eglCreateImageKHR(eglGetCurrentDisplay(),
153 EGL_NO_CONTEXT,
154 EGL_LINUX_DMA_BUF_EXT,
155 (EGLClientBuffer)0, attrs);
157 if (!piglit_check_egl_error(EGL_SUCCESS)) {
158 *out_img = NULL;
159 return false;
162 *out_img = img;
163 return true;
166 bool
167 test(EGLDisplay egl_dpy, bool glfinish_after_dmabuf_export)
169 /* Create EGLImage */
170 const int w = 128;
171 const int h = 32;
172 EGLImageKHR img = create_cleared_eglImage(egl_dpy, w, h);
174 /* Conditionally finish the clear */
175 if (!glfinish_after_dmabuf_export)
176 glFinish();
178 /* Export DMABUF from EGLImage */
179 int fourcc = -1;
180 int num_planes = -1;
181 EGLuint64KHR modifiers[64] = { -1, };
182 int fd = -1;
183 EGLint stride = -1;
184 EGLint offset = -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)
193 glFinish();
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,
201 fourcc, num_planes,
202 modifiers[0], fd, stride, offset)) {
203 fprintf(stderr, "dmabuf import failed!\n");
204 piglit_report_result(PIGLIT_FAIL);
207 /* Draw EGLImage contents */
208 GLuint imported_tex;
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);
217 void
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);