2 * Copyright © 2015 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
27 * Test transcoding NV12 to RGB by importing the Y plane as DRM_FORMAT_R8 and the UV
28 * plane as DRM_FORMAT_GR88.
30 * The shader implements a simple but fake NV12->RGB conversion equation,
31 * because the test's goal is not to test NV12->RGB conversion. Its goal is to
32 * test that EGL correctly imports and OpenGL correctly textures from the R8
33 * and GR88 DRM formats.
36 #include "piglit-framework-gl/piglit_drm_dma_buf.h"
38 #include "image_common.h"
40 #define WINDOW_WIDTH 4
41 #define WINDOW_HEIGHT 4
43 PIGLIT_GL_TEST_CONFIG_BEGIN
45 config
.supports_gl_es_version
= 30;
46 config
.window_width
= WINDOW_WIDTH
;
47 config
.window_height
= WINDOW_HEIGHT
;
49 PIGLIT_GL_TEST_CONFIG_END
51 /* Fake data for a 4x4 pixel image in NV12 format. */
52 static const uint8_t y_data
[] = {
53 0x00, 0x11, 0x22, 0x33,
54 0x44, 0x55, 0x66, 0x77,
55 0x88, 0x99, 0xaa, 0xbb,
56 0xcc, 0xdd, 0xee, 0xff,
59 static const uint8_t u_data
[] = {
64 static const uint8_t v_data
[] = {
70 create_dma_buf_texture(uint32_t width
, uint32_t height
, uint32_t fourcc
,
73 EGLDisplay dpy
= eglGetCurrentDisplay();
75 enum piglit_result result
= PIGLIT_PASS
;
77 struct piglit_dma_buf
*dma_buf
;
79 EGLint image_attrs
[13];
83 result
= piglit_create_dma_buf(width
, height
, fourcc
, pixels
, &dma_buf
);
85 if (result
!= PIGLIT_PASS
) {
86 piglit_loge("failed to create dma_buf");
87 piglit_report_result(result
);
91 image_attrs
[i
++] = EGL_LINUX_DRM_FOURCC_EXT
;
92 image_attrs
[i
++] = fourcc
;
93 image_attrs
[i
++] = EGL_WIDTH
;
94 image_attrs
[i
++] = width
;
95 image_attrs
[i
++] = EGL_HEIGHT
;
96 image_attrs
[i
++] = height
;
97 image_attrs
[i
++] = EGL_DMA_BUF_PLANE0_FD_EXT
;
98 image_attrs
[i
++] = dma_buf
->fd
;
99 image_attrs
[i
++] = EGL_DMA_BUF_PLANE0_PITCH_EXT
;
100 image_attrs
[i
++] = dma_buf
->stride
[0];
101 image_attrs
[i
++] = EGL_DMA_BUF_PLANE0_OFFSET_EXT
;
102 image_attrs
[i
++] = dma_buf
->offset
[0];
103 image_attrs
[i
++] = EGL_NONE
;
106 image
= eglCreateImageKHR(dpy
, EGL_NO_CONTEXT
, EGL_LINUX_DMA_BUF_EXT
,
107 (EGLClientBuffer
) NULL
, image_attrs
);
108 if (image
== EGL_NO_IMAGE_KHR
) {
109 piglit_loge("failed to create EGLImage from dma_buf");
110 piglit_report_result(PIGLIT_FAIL
);
113 glGenTextures(1, &tex
);
114 glBindTexture(GL_TEXTURE_2D
, tex
);
115 glEGLImageTargetTexture2DOES(GL_TEXTURE_2D
, (GLeglImageOES
) image
);
116 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
117 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
119 if (!piglit_check_gl_error(GL_NO_ERROR
))
120 piglit_report_result(PIGLIT_FAIL
);
126 piglit_init(int argc
, char **argv
)
128 EGLDisplay dpy
= eglGetCurrentDisplay();
130 piglit_require_egl_extension(dpy
, "EGL_EXT_image_dma_buf_import");
131 piglit_require_egl_extension(dpy
, "EGL_KHR_image_base");
132 piglit_require_extension("GL_OES_EGL_image");
136 create_textures(GLuint
*r8_tex
, GLuint
*gr88_tex
, float **ref_rgba_image
)
138 const int width
= WINDOW_WIDTH
;
139 const int height
= WINDOW_HEIGHT
;
142 uint8_t *gr88_pixels
;
146 r8_pixels
= malloc(width
* height
);
147 gr88_pixels
= malloc(2 * (width
/ 2) * (height
/ 2));
148 *ref_rgba_image
= malloc(4 * sizeof(float) * width
* height
);
150 if (!r8_pixels
|| !gr88_pixels
|| !*ref_rgba_image
)
153 for (i
= 0; i
< width
* height
; ++i
) {
154 r8_pixels
[i
] = y_data
[i
];
157 for (i
= 0; i
< (width
/ 2) * (height
/ 2); ++i
) {
158 gr88_pixels
[2*i
+ 0] = u_data
[i
];
159 gr88_pixels
[2*i
+ 1] = v_data
[i
];
162 for (y
= 0; y
< height
; ++y
) {
163 for (x
= 0; x
< width
; ++x
) {
164 float *rgba
= &(*ref_rgba_image
)[4 * (y
* width
+ x
)];
166 /* This must match the fake NV12->RGB conversion in the
169 rgba
[0] = y_data
[y
* width
+ x
] / 255.0f
;
170 rgba
[1] = u_data
[(y
/ 2) * (width
/ 2) + (x
/ 2)] / 255.0f
;
171 rgba
[2] = v_data
[(y
/ 2) * (width
/ 2) + (x
/ 2)] / 255.0f
;
176 glActiveTexture(GL_TEXTURE0
);
177 *r8_tex
= create_dma_buf_texture(width
, height
,
178 DRM_FORMAT_R8
, r8_pixels
);
180 glActiveTexture(GL_TEXTURE1
);
181 *gr88_tex
= create_dma_buf_texture(width
/ 2, height
/ 2,
182 DRM_FORMAT_GR88
, gr88_pixels
);
188 GLuint r8_tex
, gr88_tex
;
189 float *ref_rgba_image
;
191 GLuint va
; /* vertex array */
192 GLuint vb
; /* vertex buffer */
195 static const float vb_data
[] = {
202 if (piglit_width
!= WINDOW_WIDTH
||
203 piglit_height
!= WINDOW_HEIGHT
) {
204 piglit_loge("window is not %dx%d",
205 WINDOW_WIDTH
, WINDOW_HEIGHT
);
209 create_textures(&r8_tex
, &gr88_tex
, &ref_rgba_image
);
211 prog
= piglit_build_simple_program(
214 "in vec2 a_position;\n"
215 "out vec2 v_texcoord;\n"
219 " gl_Position = vec4(a_position, 0, 1);\n"
221 " v_texcoord = a_position;\n"
222 " v_texcoord += vec2(1, 1);\n"
223 " v_texcoord /= vec2(2, 2);\n"
228 "precision highp float;\n"
229 "uniform sampler2D u_r8_tex;\n"
230 "uniform sampler2D u_gr88_tex;\n"
231 "in vec2 v_texcoord;\n"
232 "out vec4 f_color;\n"
236 " float y = texture(u_r8_tex, v_texcoord).r;\n"
237 " vec2 uv = texture(u_gr88_tex, v_texcoord).rg;\n"
239 " /* A very fake NV12->RGB conversion */\n"
240 " f_color = vec4(y, uv.r, uv.g, 1);\n"
245 glUniform1i(glGetUniformLocation(prog
, "u_r8_tex"), 0);
246 glUniform1i(glGetUniformLocation(prog
, "u_gr88_tex"), 1);
248 if (!piglit_check_gl_error(GL_NO_ERROR
)) {
249 free(ref_rgba_image
);
250 piglit_report_result(PIGLIT_FAIL
);
253 glGenBuffers(1, &vb
);
254 glBindBuffer(GL_ARRAY_BUFFER
, vb
);
255 glBufferData(GL_ARRAY_BUFFER
, sizeof(vb_data
), vb_data
,
258 glGenVertexArrays(1, &va
);
259 glBindVertexArray(va
);
261 glVertexAttribPointer(0, 2, GL_FLOAT
, GL_FALSE
, 0, (void *) 0);
262 glEnableVertexAttribArray(0);
264 glViewport(0, 0, piglit_width
, piglit_height
);
265 glClearColor(0.2, 0.2, 0.2, 0.2);
266 glClear(GL_COLOR_BUFFER_BIT
);
267 glDrawArrays(GL_TRIANGLE_FAN
, /*first*/ 0, /*count*/ 4);
269 if (!piglit_check_gl_error(GL_NO_ERROR
)) {
270 free(ref_rgba_image
);
271 piglit_report_result(PIGLIT_FAIL
);
274 /* Increase the tolerance because the conversion path
275 * ubyte --(texturing)--> float --(glReadPixels)--> ubyte
278 piglit_tolerance
[0] = 0.05;
279 piglit_tolerance
[1] = 0.05;
280 piglit_tolerance
[2] = 0.05;
281 if (!piglit_probe_image_rgba(0, 0, piglit_width
, piglit_height
,
283 free(ref_rgba_image
);
287 free(ref_rgba_image
);