framework/replay: disable AA accounting when comparing with no tolerance
[piglit.git] / tests / glx / glx-multithread-texture.c
blob441bf735bf3e3479248a41ca5c83fbf32bee9814
1 /*
2 * Copyright 2013 Google Inc.
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 /** @file glx-multithread-texture.c
26 * Test loading texture data from one thread and context while drawing with
27 * those textures from another thread and shared context. The threads are
28 * synchronized so they do not attempt to use the same texture at the same time.
31 #include <unistd.h>
33 #include "piglit-util-gl.h"
34 #include "piglit-glx-util.h"
35 #include "pthread.h"
37 int piglit_width = 50, piglit_height = 50;
38 static int tex_width = 512, tex_height = 512;
39 static unsigned num_test = 300;
40 static bool quit = false;
42 static Display *dpy;
43 static Window draw_win;
44 static GLXPixmap load_win;
45 static pthread_mutex_t mutex;
46 static XVisualInfo *visinfo;
47 static GLXContext draw_ctx, load_ctx;
50 * list of textures
52 * user == DRAW means draw thread may draw with this texture
53 * user == LOAD means load thread may load data into this texture
54 * user == NONE means texture not in use and may be claimed by either thread
56 * Minimum of three items needed in this array for the code to work.
58 static struct texture {
59 GLuint id;
60 int color;
61 enum user { DRAW, LOAD, NONE } user;
62 } texture[5];
65 * If texture at *pos is not in use claim it for 'user' and increment *pos.
66 * Return texture at *pos.
68 static struct texture *
69 advance(int *pos, enum user user)
71 int cur = *pos % ARRAY_SIZE(texture);
72 int next = (cur + 1) % ARRAY_SIZE(texture);
74 pthread_mutex_lock(&mutex);
75 assert(texture[cur].user == user);
76 if (texture[next].user == NONE) {
77 texture[cur].user = NONE;
78 cur = next;
79 *pos += 1;
80 texture[cur].user = user;
82 pthread_mutex_unlock(&mutex);
84 /* helps avoid starvation */
85 usleep(1);
87 return texture + cur;
91 * Texture writing thread: loads data into successive textures, taking note
92 * of what color was used so it can be checked later.
93 * Return NULL on failure, else non-NULL.
95 static void *
96 load_func(void *arg)
98 int count = 1;
99 struct texture *tex = texture + count;
100 unsigned int tex_bytes = tex_width * tex_height * 4;
101 unsigned char *tex_data = malloc(tex_bytes);
102 int ret;
104 ret = glXMakeCurrent(dpy, load_win, load_ctx);
105 assert(ret);
107 glEnable(GL_TEXTURE_2D);
109 while (!quit && count <= num_test) {
110 int color = (3 * count) & 0xff;
112 assert(tex->user == LOAD);
113 if (tex->color != color) {
114 memset(tex_data, color, tex_bytes);
115 tex->color = color;
116 glBindTexture(GL_TEXTURE_2D, tex->id);
117 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex_width,
118 tex_height, 0, GL_RGBA, GL_UNSIGNED_BYTE,
119 tex_data);
120 glFlush();
123 tex = advance(&count, LOAD);
126 glFinish();
127 free(tex_data);
129 if (count <= num_test) {
130 quit = true;
131 return NULL;
134 return "";
138 * Texture using thread: draws with successive textures and checks that the
139 * correct color is drawn. Return NULL on failure, else non-NULL.
141 static void *
142 draw_func(void *arg)
144 int count = 0;
145 int ret;
147 ret = glXMakeCurrent(dpy, draw_win, draw_ctx);
148 assert(ret);
150 piglit_ortho_projection(piglit_width, piglit_height, GL_FALSE);
152 glEnable(GL_TEXTURE_2D);
153 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
155 while (!quit && count < num_test) {
156 struct texture *tex = advance(&count, DRAW);
157 float expect[] = {
158 tex->color / 255.,
159 tex->color / 255.,
160 tex->color / 255.,
163 assert(tex->user == DRAW);
165 glBindTexture(GL_TEXTURE_2D, tex->id);
166 piglit_draw_rect_tex(0, 0, piglit_width, piglit_height,
167 0, 0, 1, 1);
169 /* first texture not filled so don't check it */
170 if (count > 0 &&
171 !piglit_probe_rect_rgb(0, 0, piglit_width,
172 piglit_height, expect)) {
173 break;
177 glXSwapBuffers(dpy, draw_win);
179 if (count < num_test) {
180 quit = true;
181 return NULL;
184 return "";
187 enum piglit_result
188 draw(Display *dpy)
190 pthread_t draw_thread, load_thread;
191 void *draw_ret, *load_ret;
192 int ret, i;
193 GLXContext my_ctx;
195 my_ctx = piglit_get_glx_context_share(dpy, visinfo, NULL);
196 draw_ctx = piglit_get_glx_context_share(dpy, visinfo, my_ctx);
197 load_ctx = piglit_get_glx_context_share(dpy, visinfo, my_ctx);
199 ret = glXMakeCurrent(dpy, draw_win, my_ctx);
200 assert(ret);
201 piglit_dispatch_default_init(PIGLIT_DISPATCH_GL);
203 glEnable(GL_TEXTURE_2D);
205 for (i = 0; i < ARRAY_SIZE(texture); ++i) {
206 glGenTextures(1, &texture[i].id);
207 texture[i].color = -1;
208 texture[i].user = NONE;
209 glBindTexture(GL_TEXTURE_2D, texture[i].id);
210 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
211 GL_NEAREST);
212 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
213 GL_NEAREST);
214 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex_width, tex_height,
215 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
217 texture[0].user = DRAW;
218 texture[1].user = LOAD;
220 pthread_mutex_init(&mutex, NULL);
222 pthread_create(&draw_thread, NULL, draw_func, NULL);
223 pthread_create(&load_thread, NULL, load_func, NULL);
225 ret = pthread_join(draw_thread, &draw_ret);
226 assert(ret == 0);
227 ret = pthread_join(load_thread, &load_ret);
228 assert(ret == 0);
230 pthread_mutex_destroy(&mutex);
232 glXDestroyContext(dpy, load_ctx);
233 glXDestroyContext(dpy, draw_ctx);
234 glXDestroyContext(dpy, my_ctx);
236 return draw_ret && load_ret ? PIGLIT_PASS : PIGLIT_FAIL;
240 main(int argc, char **argv)
242 int i;
243 Pixmap pixmap;
245 for(i = 1; i < argc; ++i) {
246 if (!strcmp(argv[i], "-auto"))
247 piglit_automatic = 1;
248 else
249 fprintf(stderr, "Unknown option: %s\n", argv[i]);
252 XInitThreads();
253 dpy = XOpenDisplay(NULL);
254 if (dpy == NULL) {
255 fprintf(stderr, "couldn't open display\n");
256 piglit_report_result(PIGLIT_FAIL);
258 visinfo = piglit_get_glx_visual(dpy);
259 draw_win = piglit_get_glx_window(dpy, visinfo);
260 pixmap = XCreatePixmap(dpy, DefaultRootWindow(dpy),
261 piglit_width, piglit_height, visinfo->depth);
262 load_win = glXCreateGLXPixmap(dpy, visinfo, pixmap);
264 piglit_glx_event_loop(dpy, draw);
266 return 0;