2 * Copyright © 2010 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
23 * Author: Kristian Høgsberg <krh@bitplanet.net>
28 * Common framework for EGL tests.
30 * \author Kristian Høgsberg <krh@bitplanet.net>
33 #include <X11/XKBlib.h>
34 #include "piglit-util-gl.h"
35 #include "piglit-util-egl.h"
41 egl_probe_front_pixel_rgb(struct egl_state
*state
,
42 int x
, int y
, const float *expected
)
44 XImage
*ximage
= XGetImage(state
->dpy
, state
->win
,
45 x
, state
->height
- y
- 1, 1, 1, AllPlanes
, ZPixmap
);
46 unsigned long pixel
= XGetPixel(ximage
, 0, 0);
47 uint8_t *probe
= (uint8_t *)&pixel
;
51 XDestroyImage(ximage
);
53 /* NB: XGetPixel returns a normalized BGRA, byte per
54 * component, pixel format */
55 for(i
= 0; i
< 3; ++i
) {
56 if (fabs(probe
[2 - i
]/255.0 - expected
[i
]) > piglit_tolerance
[i
]) {
64 printf("Front Buffer Probe at (%i,%i)\n", x
, y
);
65 printf(" Expected: %f %f %f %f\n", expected
[0], expected
[1], expected
[2], expected
[3]);
66 printf(" Observed: %f %f %f %f\n", probe
[0]/255.0, probe
[1]/255.0, probe
[2]/255.0, probe
[3]/255.0);
72 egl_init_test(struct egl_test
*test
)
74 static const char *no_extensions
[] = { NULL
};
76 test
->context_attribs
= NULL
;
77 test
->config_attribs
= egl_default_attribs
;
78 test
->surface_attribs
= NULL
;
80 test
->extensions
= no_extensions
;
81 test
->window_width
= egl_default_window_width
;
82 test
->window_height
= egl_default_window_height
;
83 test
->stop_on_failure
= true;
87 egl_util_create_native_pixmap(struct egl_state
*state
, int width
, int height
)
89 return XCreatePixmap(state
->dpy
, state
->win
,
90 width
, height
, state
->depth
);
94 egl_util_create_pixmap(struct egl_state
*state
,
95 int width
, int height
, const EGLint
*attribs
)
97 EGLNativePixmapType pixmap
;
100 pixmap
= egl_util_create_native_pixmap(state
, width
, height
);
102 surf
= eglCreatePixmapSurface(state
->egl_dpy
, state
->cfg
,
108 static enum piglit_result
109 create_window(struct egl_state
*state
)
111 XSetWindowAttributes window_attr
;
112 XVisualInfo
template, *vinfo
;
115 int screen
= DefaultScreen(state
->dpy
);
116 Window root_win
= RootWindow(state
->dpy
, screen
);
119 if (!eglGetConfigAttrib(state
->egl_dpy
,
120 state
->cfg
, EGL_NATIVE_VISUAL_ID
, &id
)) {
121 fprintf(stderr
, "eglGetConfigAttrib() failed\n");
125 template.visualid
= id
;
126 vinfo
= XGetVisualInfo(state
->dpy
, VisualIDMask
, &template, &count
);
128 fprintf(stderr
, "XGetVisualInfo() failed\n");
134 state
->depth
= vinfo
->depth
;
135 window_attr
.background_pixel
= 0;
136 window_attr
.border_pixel
= 0;
137 window_attr
.colormap
= XCreateColormap(state
->dpy
, root_win
,
138 vinfo
->visual
, AllocNone
);
139 window_attr
.event_mask
=
140 StructureNotifyMask
| ExposureMask
| KeyPressMask
;
141 mask
= CWBackPixel
| CWBorderPixel
| CWColormap
| CWEventMask
;
142 state
->win
= XCreateWindow(state
->dpy
, root_win
, 0, 0,
143 state
->width
, state
->height
,
144 0, vinfo
->depth
, InputOutput
,
145 vinfo
->visual
, mask
, &window_attr
);
147 /* Some tests expect the window size to be what they set. It is really
148 * up to the window manager to decide the size, but we can at least
149 * try to ask it to do what we want.
151 XSetWMNormalHints(state
->dpy
, state
->win
, &(XSizeHints
){
152 .flags
= PSize
| PMinSize
| PMaxSize
| PBaseSize
,
153 .width
= state
->width
,
154 .height
= state
->height
,
155 .min_width
= state
->width
,
156 .min_height
= state
->height
,
157 .max_width
= state
->width
,
158 .max_height
= state
->height
,
159 .base_width
= state
->width
,
160 .base_height
= state
->height
,
163 XMapWindow(state
->dpy
, state
->win
);
169 static enum piglit_result
170 event_loop(struct egl_state
*state
, const struct egl_test
*test
)
173 enum piglit_result result
= PIGLIT_FAIL
;
176 XNextEvent (state
->dpy
, &event
);
178 if (event
.type
== Expose
) {
179 result
= test
->draw(state
);
180 if (piglit_automatic
)
184 if (event
.type
== KeyPress
) {
185 KeySym sym
= XkbKeycodeToKeysym (state
->dpy
,
189 if (sym
== XK_Escape
|| sym
== XK_q
|| sym
== XK_Q
)
198 check_extensions(struct egl_state
*state
, const struct egl_test
*test
)
202 for (i
= 0; test
->extensions
[i
]; i
++)
203 piglit_require_egl_extension(state
->egl_dpy
,
204 test
->extensions
[i
]);
208 egl_util_run(const struct egl_test
*test
, int argc
, char *argv
[])
210 struct egl_state state
= { 0 };
212 enum piglit_result result
= PIGLIT_PASS
;
213 int i
, dispatch_api
, api_bit
= EGL_OPENGL_BIT
;
215 EGLint nCtxAttribs
= 0;
216 EGLint ctxAttribs
[40];
218 for (i
= 1; i
< argc
; ++i
) {
219 if (!strcmp(argv
[i
], "-auto"))
220 piglit_automatic
= 1;
222 fprintf(stderr
, "Unknown option: %s\n", argv
[i
]);
225 state
.dpy
= XOpenDisplay(NULL
);
226 if (state
.dpy
== NULL
) {
227 fprintf(stderr
, "couldn't open display\n");
228 piglit_report_result(PIGLIT_SKIP
);
231 /* read api_bit if EGL_RENDERABLE_TYPE set in the attribs */
232 for (count
= 0; test
->config_attribs
[count
] != EGL_NONE
; count
+= 2) {
233 if (test
->config_attribs
[count
] == EGL_RENDERABLE_TYPE
) {
234 api_bit
= test
->config_attribs
[count
+1];
238 /* choose dispatch_api and set ctx version to ctxAttribs if using ES */
240 case EGL_OPENGL_ES_BIT
:
241 dispatch_api
= PIGLIT_DISPATCH_ES1
;
242 ctxAttribs
[nCtxAttribs
++] = EGL_CONTEXT_CLIENT_VERSION
;
243 ctxAttribs
[nCtxAttribs
++] = 1;
245 case EGL_OPENGL_ES2_BIT
:
246 dispatch_api
= PIGLIT_DISPATCH_ES2
;
247 ctxAttribs
[nCtxAttribs
++] = EGL_CONTEXT_CLIENT_VERSION
;
248 ctxAttribs
[nCtxAttribs
++] = 2;
251 fprintf(stderr
, "Note: No EGL_RENDERABLE_TYPE defined in test attributes, defaulted to gl\n");
252 dispatch_api
= PIGLIT_DISPATCH_GL
;
256 state
.egl_dpy
= piglit_egl_get_display(EGL_PLATFORM_X11_EXT
, state
.dpy
);
257 if (state
.egl_dpy
== EGL_NO_DISPLAY
) {
258 fprintf(stderr
, "piglit_egl_get_display() failed\n");
259 result
= PIGLIT_FAIL
;
263 if (!eglInitialize(state
.egl_dpy
, &state
.major
, &state
.minor
)) {
264 fprintf(stderr
, "eglInitialize() failed\n");
265 result
= PIGLIT_FAIL
;
269 /* bind chosen API and set ctxattribs if using ES */
270 if (api_bit
== EGL_OPENGL_BIT
)
271 eglBindAPI(EGL_OPENGL_API
);
273 eglBindAPI(EGL_OPENGL_ES_API
);
275 check_extensions(&state
, test
);
277 if (!eglChooseConfig(state
.egl_dpy
, test
->config_attribs
, &state
.cfg
, 1, &count
) ||
279 fprintf(stderr
, "eglChooseConfig() failed\n");
280 result
= PIGLIT_FAIL
;
284 for (int i
= 0; test
->context_attribs
&& test
->context_attribs
[i
] != EGL_NONE
; i
++)
285 ctxAttribs
[nCtxAttribs
++] = test
->context_attribs
[i
];
287 ctxAttribs
[nCtxAttribs
++] = EGL_NONE
;
288 assert(nCtxAttribs
< ARRAY_SIZE(ctxAttribs
));
290 state
.ctx
= eglCreateContext(state
.egl_dpy
, state
.cfg
,
291 EGL_NO_CONTEXT
, ctxAttribs
);
292 if (state
.ctx
== EGL_NO_CONTEXT
) {
293 fprintf(stderr
, "eglCreateContext() failed\n");
294 result
= PIGLIT_FAIL
;
298 state
.width
= test
->window_width
;
299 state
.height
= test
->window_height
;
300 result
= create_window(&state
);
301 if (result
!= PIGLIT_PASS
)
304 state
.surf
= eglCreateWindowSurface(state
.egl_dpy
,
305 state
.cfg
, state
.win
,
306 test
->surface_attribs
);
307 if (state
.surf
== EGL_NO_SURFACE
) {
308 fprintf(stderr
, "eglCreateWindowSurface() failed\n");
309 result
= PIGLIT_FAIL
;
313 if (!eglMakeCurrent(state
.egl_dpy
,
314 state
.surf
, state
.surf
, state
.ctx
)) {
315 fprintf(stderr
, "eglMakeCurrent() failed\n");
316 result
= PIGLIT_FAIL
;
320 piglit_dispatch_default_init(dispatch_api
);
322 result
= event_loop(&state
, test
);
326 eglMakeCurrent(state
.egl_dpy
, EGL_NO_SURFACE
, EGL_NO_SURFACE
, EGL_NO_CONTEXT
);
327 eglDestroyContext(state
.egl_dpy
, state
.ctx
);
330 XDestroyWindow(state
.dpy
, state
.win
);
332 eglTerminate(state
.egl_dpy
);
333 if (test
->stop_on_failure
)
334 piglit_report_result(result
);