1 /* Copyright (c) 2009-2010 Nokia Corporation
3 * This program is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU General Public License as
5 * published by the Free Software Foundation; either version 2 or
6 * (at your option) any later version of the License.
8 * You should have received a copy of the GNU General Public License along
9 * with this program; if not, see <http://www.gnu.org/licenses/>.
12 #include "gles2_calls.h"
14 void* gles2_client_worker(void *opaque);
17 #define GLES2_CB(func) \
20 // Called by kernel module when a new client connects.
26 uint32_t abi = gles2_arg_dword(s, d);
28 for (i = 0; i < GLES2_NCLIENTS; ++i) {
34 if (i == GLES2_NCLIENTS) {
35 GLES2_PRINT("ERROR: No free slots!\n");
36 gles2_ret_dword(s, 0);
40 GLES2_PRINT("Client Initialization!\n");
42 if (!abi || abi >= gles2_abi_last) {
43 GLES2_PRINT("ERROR: unknown ABI %d!\n", abi);
44 /* support legacy clients that do not provide ABI id */
45 abi = gles2_abi_arm_softfp;
48 GLES2_PRINT("Selected ABI %d\n", s->abi);
50 client = malloc(sizeof(*client));
51 memset(client, 0, sizeof(*client));
54 client->rendering_api = EGL_OPENGL_ES_API;
55 pthread_mutex_init(&client->mutex_wait, NULL);
56 pthread_mutex_init(&client->mutex_run, NULL);
57 pthread_mutex_init(&client->mutex_xcode, NULL);
58 pthread_cond_init(&client->cond_start, NULL);
59 pthread_cond_init(&client->cond_state, NULL);
60 pthread_cond_init(&client->cond_xcode, NULL);
61 pthread_cond_init(&client->cond_return, NULL);
62 client->state = gles2_ClientState_init;
63 pthread_attr_init(&attr);
64 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
66 pthread_mutex_lock(&client->mutex_wait);
68 GLES2_PRINT("Creating worker...\n");
69 pthread_create(&client->thread, &attr, gles2_client_worker, client);
72 pthread_cond_wait(&client->cond_state, &client->mutex_wait);
73 } while(client->state != gles2_ClientState_ready);
74 pthread_mutex_unlock(&client->mutex_wait);
76 GLES2_PRINT("Worker initialized\n");
78 s->clients[i] = client;
79 gles2_ret_dword(s, client->nr);
82 // Called by kernel module when an existing client disconnects.
85 uint32_t nr = gles2_arg_dword(s, d);
88 GLES2_PRINT("Exit called for client %d!\n", nr);
90 if ((nr > GLES2_NCLIENTS + 1) ||
92 GLES2_PRINT("Client number (%d) out of range!\n",nr);
95 client = s->clients[nr - 1];
99 GLES2_PRINT("Can't exit NULL client!\n");
103 GLES2_PRINT("\tRequesting worker to exit.\n");
105 // Make sure nothing is running.
106 GLES2_PRINT("Syncing with worker...\n");
107 pthread_mutex_lock(&client->mutex_wait);
108 while (client->state != gles2_ClientState_ready) {
109 pthread_cond_wait(&client->cond_state, &client->mutex_wait);
111 pthread_mutex_lock(&client->mutex_run);
113 client->state = gles2_ClientState_pending;
114 GLES2_PRINT("Requesting exit...\n");
115 pthread_cond_signal(&client->cond_start);
116 pthread_mutex_unlock(&client->mutex_wait);
118 GLES2_PRINT("Waiting worker to exit...\n");
120 pthread_cond_wait(&client->cond_state, &client->mutex_run);
121 } while (client->state != gles2_ClientState_exit);
122 pthread_mutex_unlock(&client->mutex_run);
124 GLES2_PRINT("\tJoining...\n");
125 pthread_join(client->thread, NULL);
126 pthread_mutex_destroy(&client->mutex_wait);
127 pthread_mutex_destroy(&client->mutex_run);
128 pthread_cond_destroy(&client->cond_start);
129 pthread_cond_destroy(&client->cond_state);
132 s->clients[nr - 1] = NULL;
134 GLES2_PRINT("\tDone!\n");
138 * Worker thread function for clients .
139 * Each worker thread is linked to a %gles2_Client struct and to
140 * one guest thread in the guest system.
142 void* gles2_client_worker(void *opaque)
144 gles2_Client *client = opaque;
147 GLES2_PRINT("WORKER(%d): Starting!\n", client->nr);
149 pthread_mutex_lock(&client->mutex_xcode);
152 gles2_decode_t d = 0;
153 GLES2_PRINT("WORKER(%d): Waiting for call...\n", client->nr);
154 pthread_mutex_lock(&client->mutex_wait);
156 client->state = gles2_ClientState_ready;
157 pthread_cond_signal(&client->cond_state);
158 client->phase_xcode = 4;
159 pthread_cond_signal(&client->cond_xcode);
160 pthread_mutex_unlock(&client->mutex_xcode);
161 while (client->state != gles2_ClientState_pending) {
162 pthread_cond_wait(&client->cond_start, &client->mutex_wait);
165 GLES2_PRINT("WORKER(%d): Got call, waiting permission to run...\n", client->nr);
167 pthread_mutex_lock(&client->mutex_run);
168 GLES2_PRINT("WORKER(%d): Running!\n", client->nr);
169 client->state = gles2_ClientState_running;
170 pthread_mutex_unlock(&client->mutex_wait);
173 GLES2_TRACE("WORKER(%d): Calling function %s (%p)...\n",
174 client->nr, client->call->name, client->call);
175 client->call->callback(client->s, &d, client);
176 #ifdef CONFIG_DEBUG_GLES
177 /*if (client->call->name[0] == 'g') {
178 unsigned int error = gles20_glGetError();
180 fprintf(stderr, "GL error 0x%04x from function %s\n",
181 error, client->call->name);
184 #endif // CONFIG_DEBUG_GLES == 1
185 GLES2_PRINT("\tWORKER(%d): Done.\n", client->nr);
186 client->prev_call = client->call;
187 client->state = gles2_ClientState_done;
189 GLES2_PRINT("WORKER(%d): Exit requested!\n", client->nr);
191 client->state = gles2_ClientState_exit;
192 pthread_cond_signal(&client->cond_state);
194 pthread_mutex_unlock(&client->mutex_run);
197 GLES2_PRINT("WORKER(%d): Exiting!\n", client->nr);