sync with latest
[sdk/emulator/qemu.git] / hw / gles2_egl_calls.c
1 /* Copyright (c) 2009-2010 Nokia Corporation
2  *
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.
7  *
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/>.
10  */
11
12 #include "console.h"
13 #include "gles2_calls.h"
14 #include "GLES2/gl2.h"
15
16 #undef GLES2_CB
17 #define GLES2_CB(func) \
18     CB(func,egl)
19
20 extern int gles2_getMaxVertexAttrib(void);
21 int surf_id = 1;
22 /**
23  * used to know the index in %gles2_Client context array
24  * where contexts of type context_client_type are stored
25  * @param context_client_type is the client API.
26  */
27 static int gles2_getContextArrayIndex(EGLenum context_client_type)
28 {
29     switch (context_client_type) {
30         case EGL_OPENGL_ES_API:
31         case EGL_OPENGL_API:
32             return 0;
33         break;
34         case EGL_OPENVG_API:
35             return 1;
36         break;
37         default:
38             return -1;
39         break;
40     }
41
42 }
43
44 // See if guest offscreen drawable was changed and if so, update host copy.
45 static int gles2_surface_update(gles2_State *s, gles2_Surface *surf)
46 {
47     int ret = 0;
48
49     uint32_t width   = gles2_get_dword(s, surf->ddrawp + 0*sizeof(uint32_t));
50     uint32_t height  = gles2_get_dword(s, surf->ddrawp + 1*sizeof(uint32_t));
51     uint32_t depth   = gles2_get_dword(s, surf->ddrawp + 2*sizeof(uint32_t));
52     uint32_t bpp     = gles2_get_dword(s, surf->ddrawp + 3*sizeof(uint32_t));
53     uint32_t pixelsp = gles2_get_dword(s, surf->ddrawp + 4*sizeof(uint32_t));
54
55     if (width != surf->ddraw.width
56          || height != surf->ddraw.height
57          || depth != surf->ddraw.depth) {
58         surf->ddraw.width = width;
59         surf->ddraw.height = height;
60         surf->ddraw.depth = depth;
61         surf->ddraw.bpp = bpp;
62         ret = 1;
63     }
64
65     surf->pixelsp = pixelsp;
66
67     return ret;
68 }
69
70 // TODO: Support swapping of offscreen surfaces.
71 static void gles2_eglSwapCallback(void* userdata)
72 {
73     (void)userdata;
74     GLES2_PRINT("Swap called!\n");
75 }
76
77
78 GLES2_CB(eglGetError)
79 {
80     GLES2_BARRIER_ARG;
81     EGLint ret = eglGetError();
82     GLES2_BARRIER_RET;
83     gles2_ret_TGLint(s, ret);
84 }
85
86 GLES2_CB(eglBindAPI)
87 {
88     GLES2_ARG(TEGLenum, api);
89     GLES2_BARRIER_ARG;
90
91     EGLBoolean ret = eglBindAPI(api);
92     if(ret)
93         c->rendering_api = api;
94     GLES2_BARRIER_RET;
95     gles2_ret_TEGLBoolean(s, ret);
96 }
97
98 GLES2_CB(eglGetDisplay)
99 {
100 //  GLES2_ARG(TEGLDisplay, dpy);
101 //  (void)dpy;
102     GLES2_BARRIER_ARG;
103
104     GLES2_PRINT("Getting display...\n");
105
106     EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
107
108     GLES2_PRINT("\tGot host display %p...\n", dpy);
109
110     GLES2_BARRIER_RET;
111
112     pthread_mutex_lock(&s->m);
113
114     uint32_t handle = gles2_handle_find(s, dpy);
115
116     if (!handle)
117     {
118         handle = gles2_handle_create(s, dpy);
119         gles2_ret_TEGLDisplay(s, handle);
120         dpy_updatecaption(get_displaystate());
121     }
122     else
123     {
124         gles2_ret_TEGLDisplay(s, handle);
125     }
126
127     pthread_mutex_unlock(&s->m);
128 }
129
130 GLES2_CB(eglInitialize)
131 {
132     GLES2_ARG(TEGLDisplay, dpy_);
133     GLES2_ARG(Tptr, majorp);
134     GLES2_ARG(Tptr, minorp);
135
136     GLES2_BARRIER_ARG;
137
138     pthread_mutex_lock(&s->m);
139
140     EGLDisplay dpy = (EGLDisplay)gles2_handle_get(s, dpy_);
141
142     pthread_mutex_unlock(&s->m);
143
144     GLES2_PRINT("Request to initialize display %p...\n", dpy);
145
146     EGLint major, minor;
147     if (eglInitialize(dpy, &major, &minor)) {
148         GLES2_PRINT("Display initialized (EGL %d.%d)!\n", major, minor);
149         GLES2_BARRIER_RET;
150         gles2_put_TEGLint(s, majorp, major);
151         gles2_put_TEGLint(s, minorp, minor);
152         gles2_ret_TEGLBoolean(s, EGL_TRUE);
153         return;
154     }
155
156     GLES2_PRINT("Failed to initialize...\n");
157     GLES2_BARRIER_RET;
158     gles2_ret_TEGLBoolean(s, EGL_FALSE);
159 }
160
161 GLES2_CB(eglGetConfigs)
162 {
163     GLES2_ARG(TEGLDisplay, dpy_);
164     GLES2_ARG(Tptr, configsp);
165     GLES2_ARG(TEGLint, config_size);
166     GLES2_ARG(Tptr, num_configp);
167
168     GLES2_BARRIER_ARG;
169
170     pthread_mutex_lock(&s->m);
171
172     EGLDisplay dpy = (EGLDisplay)gles2_handle_get(s, dpy_);
173
174     pthread_mutex_unlock(&s->m);
175
176     EGLConfig* configs = configsp ? malloc(sizeof(EGLConfig)*config_size) : NULL;
177
178     EGLint num_config;
179     EGLBoolean ret = eglGetConfigs(dpy, configs, config_size, &num_config);
180
181     GLES2_BARRIER_RET;
182     if (configs) {
183         EGLint i;
184
185         pthread_mutex_lock(&s->m);
186         for (i = 0; i < num_config; ++i) {
187             uint32_t handle;
188             if (!(handle = gles2_handle_find(s, configs[i]))) {
189                 handle = gles2_handle_create(s, configs[i]);
190             }
191             gles2_put_TEGLConfig(s, configsp + i*sizeof(TEGLConfig), handle);
192         }
193         pthread_mutex_unlock(&s->m);
194
195         free(configs);
196     }
197     gles2_put_TEGLint(s, num_configp, num_config);
198
199     gles2_ret_TEGLBoolean(s, ret);
200 }
201
202 GLES2_CB(eglChooseConfig)
203 {
204     GLES2_ARG(TEGLDisplay, dpy_);
205     GLES2_ARG(Tptr, attrib_listp);
206     GLES2_ARG(Tptr, configsp);
207     GLES2_ARG(TEGLint, config_size);
208     GLES2_ARG(Tptr, num_configp);
209     (void)config_size;
210     (void)attrib_listp;
211
212     EGLint attrib_list_n = 0;
213     while (gles2_get_TEGLint(s, attrib_listp
214         + attrib_list_n*sizeof(EGLint)) != EGL_NONE) {
215         attrib_list_n += 2;
216     }
217     EGLint* attrib_list = malloc((attrib_list_n + 1)*sizeof(EGLint));
218     EGLint i;
219
220     for (i = 0; i < attrib_list_n; ++i) {
221         attrib_list[i] = gles2_get_TEGLint(s, attrib_listp
222             + i*sizeof(EGLint));
223     }
224     attrib_list[attrib_list_n] = EGL_NONE;
225
226     pthread_mutex_lock(&s->m);
227
228     EGLDisplay dpy = (EGLDisplay)gles2_handle_get(s, dpy_);
229
230     pthread_mutex_unlock(&s->m);
231
232     GLES2_BARRIER_ARG;
233     EGLConfig* configs = configsp ? malloc(sizeof(EGLConfig)*config_size) : NULL;
234
235     EGLint num_config;
236     EGLBoolean ret = eglChooseConfig(dpy, attrib_list, configs, config_size, &num_config);
237     free(attrib_list);
238     GLES2_BARRIER_RET;
239     if (configs) {
240         EGLint i;
241
242         pthread_mutex_lock(&s->m);
243
244         for (i = 0; i < num_config; ++i) {
245             uint32_t handle;
246             if (!(handle = gles2_handle_find(s, configs[i]))) {
247                 handle = gles2_handle_create(s, configs[i]);
248             }
249             gles2_put_TEGLConfig(s, configsp + i*sizeof(TEGLConfig), handle);
250         }
251
252         pthread_mutex_unlock(&s->m);
253
254         free(configs);
255     }
256     gles2_put_TEGLint(s, num_configp, num_config);
257
258     gles2_ret_TEGLBoolean(s, ret);
259 }
260
261 GLES2_CB(eglGetConfigAttrib)
262 {
263     GLES2_ARG(TEGLDisplay, dpy_);
264     GLES2_ARG(TEGLConfig, config);
265     GLES2_ARG(TEGLint, attribute);
266     GLES2_ARG(Tptr, valuep);
267     GLES2_BARRIER_ARG;
268
269     pthread_mutex_lock(&s->m);
270
271     EGLDisplay dpy = (EGLDisplay)gles2_handle_get(s, dpy_);
272
273     EGLint value;
274     EGLBoolean ret = eglGetConfigAttrib(dpy, gles2_handle_get(s, config), attribute, &value);
275
276     pthread_mutex_unlock(&s->m);
277
278     GLES2_BARRIER_RET;
279
280     gles2_put_TEGLint(s, valuep, value);
281     gles2_ret_TEGLBoolean(s, ret);
282 }
283
284 GLES2_CB(eglCreateWindowSurface)
285 {
286     GLES2_ARG(TEGLDisplay, dpy_);
287     GLES2_ARG(TEGLConfig, config_);
288     GLES2_ARG(Tptr, winp);
289     GLES2_ARG(Tptr, attrib_listp);
290
291     pthread_mutex_lock(&s->m);
292
293     EGLDisplay dpy = (EGLDisplay)gles2_handle_get(s, dpy_);
294     EGLConfig config = (EGLConfig)gles2_handle_get(s, config_);
295
296     pthread_mutex_unlock(&s->m);
297
298     (void)attrib_listp;
299
300     gles2_Surface* fsurf;
301
302     if (!(fsurf = malloc(sizeof(*fsurf)))) {
303         GLES2_PRINT("\tFake window creation failed!\n");
304         GLES2_BARRIER_ARG;
305         GLES2_BARRIER_RET;
306         gles2_ret_TEGLSurface(s, 0);
307         return;
308     }
309
310     memset(fsurf, 0, sizeof(*fsurf));
311
312     fsurf->id = surf_id++;
313
314     fsurf->ddrawp = winp;
315     fsurf->pixmap = 0;
316     gles2_surface_update(s, fsurf);
317     GLES2_BARRIER_ARG;
318     DEGLDrawable* ddraw=&(fsurf->ddraw);
319
320     GLES2_PRINT("Host window creation requested, %dx%d@%d(Bpp=%d) at 0x%x, ID = %d...\n",
321         ddraw->width, ddraw->height,
322         ddraw->depth, ddraw->bpp, fsurf->pixelsp, fsurf->id);
323
324     unsigned nbytes = ddraw->width*ddraw->height*ddraw->bpp;
325     ddraw->pixels = malloc(nbytes);
326     ddraw->userdata = fsurf;
327     ddraw->swap = gles2_eglSwapCallback;
328
329     if((fsurf->surf = eglCreateOffscreenSurfaceDGLES(dpy, config, ddraw))
330         == EGL_NO_SURFACE)
331     {
332         GLES2_PRINT("\tHost window creation failed!\n");
333         free(ddraw->pixels);
334         free(fsurf);
335         GLES2_BARRIER_RET;
336         gles2_ret_TEGLSurface(s, 0);
337         return;
338     }
339
340     GLES2_PRINT("Created at %p!\n", fsurf);
341     GLES2_BARRIER_RET;
342     gles2_transfer_compile(&fsurf->tfr, s, fsurf->pixelsp, nbytes);
343     pthread_mutex_lock(&s->m);
344
345     gles2_ret_TEGLSurface(s, gles2_handle_create(s, fsurf));
346
347     pthread_mutex_unlock(&s->m);
348 }
349
350 GLES2_CB(eglCreatePixmapSurface)
351 {
352     GLES2_ARG(TEGLDisplay, dpy_);
353     GLES2_ARG(TEGLConfig, config_);
354     GLES2_ARG(Tptr, pixmapp);
355     GLES2_ARG(Tptr, attrib_listp);
356
357     pthread_mutex_lock(&s->m);
358
359     EGLDisplay dpy = (EGLDisplay)gles2_handle_get(s, dpy_);
360     EGLConfig config = (EGLConfig)gles2_handle_get(s, config_);
361
362     pthread_mutex_unlock(&s->m);
363
364     (void)attrib_listp;
365
366     gles2_Surface* fsurf;
367
368     if (!(fsurf = malloc(sizeof(*fsurf)))) {
369         GLES2_PRINT("\tFake pixmap creation failed!\n");
370         GLES2_BARRIER_ARG;
371         GLES2_BARRIER_RET;
372         gles2_ret_TEGLSurface(s, 0);
373         return;
374     }
375
376     memset(fsurf, 0, sizeof(*fsurf));
377
378     fsurf->id = surf_id++;
379     fsurf->ddrawp = pixmapp;
380     fsurf->pixmap = 1;
381     gles2_surface_update(s, fsurf);
382     GLES2_BARRIER_ARG;
383     DEGLDrawable* ddraw=&(fsurf->ddraw);
384
385     GLES2_PRINT("Host pixmap creation requested, %dx%d@%d(Bpp=%d) at 0x%x, ID = %d...\n",
386         ddraw->width, ddraw->height,
387         ddraw->depth, ddraw->bpp, fsurf->pixelsp, fsurf->id);
388
389     unsigned nbytes = ddraw->width*ddraw->height*ddraw->bpp;
390     ddraw->pixels = malloc(nbytes);
391     ddraw->userdata = fsurf;
392     ddraw->swap = gles2_eglSwapCallback;
393
394
395     if((fsurf->surf = eglCreateOffscreenSurfaceDGLES(dpy, config, ddraw))
396         == EGL_NO_SURFACE)
397     {
398         GLES2_PRINT("\tHost pixmap creation failed!\n");
399         free(ddraw->pixels);
400         free(fsurf);
401         GLES2_BARRIER_RET;
402         gles2_ret_TEGLSurface(s, 0);
403         return;
404     }
405
406     GLES2_PRINT("Created at %p!\n", fsurf);
407     GLES2_BARRIER_RET;
408     gles2_transfer_compile(&fsurf->tfr, s, fsurf->pixelsp, nbytes);
409     pthread_mutex_lock(&s->m);
410     gles2_ret_TEGLSurface(s, gles2_handle_create(s, fsurf));
411     pthread_mutex_unlock(&s->m);
412 }
413
414 GLES2_CB(eglCreatePbufferSurface)
415 {
416     GLES2_ARG(TEGLDisplay, dpy_);
417     GLES2_ARG(TEGLConfig, config_);
418     GLES2_ARG(Tptr, attrib_listp);
419
420     pthread_mutex_lock(&s->m);
421     EGLDisplay dpy = (EGLDisplay)gles2_handle_get(s, dpy_);
422     EGLConfig config = (EGLConfig)gles2_handle_get(s, config_);
423     pthread_mutex_unlock(&s->m);
424      EGLint attrib_list_n = 0;
425     while (gles2_get_TEGLint(s, attrib_listp
426         + attrib_list_n*sizeof(EGLint)) != EGL_NONE) {
427         attrib_list_n += 2;
428     }
429     EGLint* attrib_list = malloc((attrib_list_n + 1)*sizeof(EGLint));
430     EGLint i;
431
432     for (i = 0; i < attrib_list_n; ++i) {
433         attrib_list[i] = gles2_get_TEGLint(s, attrib_listp
434             + i*sizeof(EGLint));
435     }
436     attrib_list[attrib_list_n] = EGL_NONE;
437
438     gles2_Surface* fsurf;
439
440     if (!(fsurf = malloc(sizeof(*fsurf)))) {
441         GLES2_PRINT("\tPbuffer creation failed!\n");
442         GLES2_BARRIER_ARG;
443         GLES2_BARRIER_RET;
444         gles2_ret_TEGLSurface(s, 0);
445         return;
446     }
447
448     memset(fsurf, 0, sizeof(*fsurf));
449
450     fsurf->id = surf_id++;
451
452     fsurf->ddrawp = 0;
453     fsurf->pixmap = 0;
454     GLES2_BARRIER_ARG;
455
456     if((fsurf->surf = eglCreatePbufferSurface(dpy, config, attrib_list))
457         == EGL_NO_SURFACE)
458     {
459         GLES2_PRINT("\tPbuffer creation failed!\n");
460         free(fsurf);
461         GLES2_BARRIER_RET;
462         gles2_ret_TEGLSurface(s, 0);
463         return;
464     }
465
466     GLES2_PRINT("Created at %p!\n", fsurf);
467     GLES2_BARRIER_RET;
468     pthread_mutex_lock(&s->m);
469     gles2_ret_TEGLSurface(s, gles2_handle_create(s, fsurf));
470     pthread_mutex_unlock(&s->m);
471 }
472
473 GLES2_CB(eglDestroySurface)
474 {
475     GLES2_ARG(TEGLDisplay, dpy_);
476     GLES2_ARG(TEGLSurface, surface_);
477     GLES2_BARRIER_ARG_NORET;
478
479     pthread_mutex_lock(&s->m);
480     EGLDisplay dpy = (EGLDisplay)gles2_handle_get(s, dpy_);
481     gles2_Surface* fsurf = (EGLSurface)gles2_handle_get(s, surface_);
482     gles2_handle_free(s, surface_);
483     pthread_mutex_unlock(&s->m);
484
485     GLES2_PRINT("Destroyed surface ID = %d...\n", fsurf->id);
486     fsurf->id = -1;
487
488     eglDestroySurface(dpy, fsurf->surf);
489     if(fsurf->ddraw.pixels)
490         free(fsurf->ddraw.pixels);
491
492 //    if(fsurf->pixmap == 0) {
493         gles2_transfer_free(&fsurf->tfr);
494 //    }
495     free(fsurf);
496 }
497
498 GLES2_CB(eglBindTexImage)
499 {
500     GLES2_ARG(TEGLDisplay, dpy_);
501     GLES2_ARG(TEGLSurface, surface_);
502     GLES2_ARG(TEGLint, buffer);
503     gles2_CompiledTransfer tfr;
504
505     pthread_mutex_lock(&s->m);
506     EGLDisplay dpy = (EGLDisplay)gles2_handle_get(s, dpy_);
507     gles2_Surface* fsurf = (gles2_Surface*)gles2_handle_get(s, surface_);
508     pthread_mutex_unlock(&s->m);
509
510     // FIXME: Not a very clean way..
511     uint32_t pixelsp = gles2_get_dword(s, fsurf->ddrawp + 4*sizeof(uint32_t));
512     if (pixelsp) {
513         unsigned nbytes = fsurf->ddraw.width
514             * fsurf->ddraw.height*fsurf->ddraw.bpp;
515         gles2_transfer_compile(&tfr, s, pixelsp, nbytes);
516     }
517     GLES2_BARRIER_ARG;
518
519     if (pixelsp) {
520 //        gles2_transfer(s, pixelsp, nbytes, fsurf->ddraw.pixels, 0);
521         gles2_transfer_exec(&tfr, s, fsurf->ddraw.pixels, 0);
522     }
523
524     GLES2_PRINT("Binding surface ID = %d!\n", fsurf->id);
525
526     EGLBoolean ret = eglBindTexImage(dpy, fsurf->surf, buffer);
527     if (pixelsp) {
528         gles2_transfer_free(&tfr);
529     }
530
531     GLES2_BARRIER_RET;
532     gles2_ret_TEGLBoolean(s, ret);
533 }
534
535 GLES2_CB(eglReleaseTexImage)
536 {
537     GLES2_ARG(TEGLDisplay, dpy_);
538     GLES2_ARG(TEGLSurface, surface_);
539     GLES2_ARG(TEGLint, buffer);
540     GLES2_BARRIER_ARG;
541
542     pthread_mutex_lock(&s->m);
543     EGLDisplay dpy = (EGLDisplay)gles2_handle_get(s, dpy_);
544     gles2_Surface* fsurf = (gles2_Surface*)gles2_handle_get(s, surface_);
545     pthread_mutex_unlock(&s->m);
546
547     GLES2_PRINT("Unbinding surface ID = %d!\n", fsurf->id);
548
549     EGLBoolean ret = eglReleaseTexImage(dpy, fsurf->surf, buffer);
550     GLES2_BARRIER_RET;
551     gles2_ret_TEGLBoolean(s, ret);
552 }
553
554 GLES2_CB(eglCreateContext)
555 {
556     GLES2_ARG(TEGLDisplay, dpy_);
557     GLES2_ARG(TEGLConfig, config_);
558     GLES2_ARG(TEGLContext, share_context_);
559     GLES2_ARG(Tptr, attrib_listp);
560
561     pthread_mutex_lock(&s->m);
562     EGLDisplay dpy = (EGLDisplay)gles2_handle_get(s, dpy_);
563     EGLConfig config = (EGLConfig)gles2_handle_get(s, config_);
564     gles2_Context* share_context = gles2_handle_get(s, share_context_);
565     pthread_mutex_unlock(&s->m);
566
567
568     EGLint *attribs= NULL;
569
570     if (attrib_listp) {
571         EGLint list_n = 1;
572         EGLint name = gles2_get_TEGLint(s, attrib_listp);
573         while ( name != EGL_NONE) {
574             list_n += 2;
575             name = gles2_get_TEGLint(s, attrib_listp
576             + (list_n-1)*sizeof(EGLint));
577         }
578         attribs = malloc(list_n*sizeof(EGLint));
579         int i;
580         for (i=0; i< list_n; i++) {
581
582                     attribs[i] = gles2_get_TEGLint(s, attrib_listp
583                     + i*sizeof(EGLint));
584         }
585     }
586     GLES2_BARRIER_ARG;
587     GLES2_PRINT("Host context creation requested...\n");
588     EGLContext hctx = eglCreateContext(dpy, config, share_context?share_context->hctx:NULL, attribs);
589     GLES2_BARRIER_RET;
590
591     if (hctx == EGL_NO_CONTEXT) {
592         GLES2_PRINT("Context creation failed!\n");
593         (void)attrib_listp;
594         gles2_ret_TEGLContext(s, 0);
595     } else {
596         gles2_Context * ctx = malloc(sizeof(gles2_Context));
597         memset(ctx, 0, sizeof(*ctx));
598         ctx->hctx = hctx;
599         int version = 1;
600         //if OpenGL ES check for client version from attrib_list
601         if(c->rendering_api == EGL_OPENGL_ES_API && attrib_listp) {
602             EGLint attrib_list_n = 0;
603             EGLint attribname = gles2_get_TEGLint(s, attrib_listp
604                 + attrib_list_n*sizeof(EGLint));
605             while ( attribname != EGL_NONE &&
606                     attribname != EGL_CONTEXT_CLIENT_VERSION) {
607                 attrib_list_n += 2;
608                 attribname = gles2_get_TEGLint(s, attrib_listp
609                 + attrib_list_n*sizeof(EGLint));
610             }
611             if (attribname == EGL_CONTEXT_CLIENT_VERSION) {
612                 attrib_list_n++;
613                 version = gles2_get_TEGLint(s, attrib_listp
614                     + attrib_list_n*sizeof(EGLint));
615             }
616         }
617
618         ctx->client_type = c->rendering_api;
619         ctx->client_version = version;
620         ctx->arrays = NULL;
621         ctx->narrays = 0;
622         ctx->ebo_list = malloc(sizeof(gles2_ebo));
623         ctx->ebo_list->name = -1;
624         ctx->ebo_list->next = NULL;
625         if (attribs)
626             free(attribs);
627         memset(ctx->ebo_list, 0, sizeof(*ctx->ebo_list));
628         GLES2_PRINT("Created at %p!\n", ctx);
629         pthread_mutex_lock(&s->m);
630         gles2_ret_TEGLContext(s, gles2_handle_create(s, ctx));
631         pthread_mutex_unlock(&s->m);
632     }
633 }
634
635 GLES2_CB(eglDestroyContext)
636 {
637     GLES2_ARG(TEGLDisplay, dpy_);
638     GLES2_ARG(TEGLContext, ctx_);
639     GLES2_BARRIER_ARG;
640
641     pthread_mutex_lock(&s->m);
642     EGLDisplay dpy = (EGLDisplay)gles2_handle_get(s, dpy_);
643     gles2_Context* ctx = (gles2_Context*) gles2_handle_get(s, ctx_);
644     EGLBoolean ret = eglDestroyContext(dpy, ctx->hctx);
645     if (ret) {
646         if (ctx->arrays)
647             free(ctx->arrays);
648         gles2_ebo_free(ctx->ebo_list);
649         free(ctx);
650         gles2_handle_free(s, ctx_);
651         GLES2_PRINT("Destroyed %p!\n", ctx);
652     }
653     pthread_mutex_unlock(&s->m);
654
655     GLES2_BARRIER_RET;
656     gles2_ret_TEGLBoolean(s,ret);
657 }
658
659 GLES2_CB(eglMakeCurrent)
660 {
661     GLES2_ARG(TEGLDisplay, dpy_);
662     GLES2_ARG(TEGLSurface, draw_);
663     GLES2_ARG(TEGLSurface, read_);
664     GLES2_ARG(TEGLContext, ctx_);
665     GLES2_BARRIER_ARG;
666
667     pthread_mutex_lock(&s->m);
668     EGLDisplay dpy = (EGLDisplay)gles2_handle_get(s, dpy_);
669     gles2_Surface* draw = (EGLSurface)gles2_handle_get(s, draw_);
670     gles2_Surface* read = (EGLSurface)gles2_handle_get(s, read_);
671     gles2_Context* ctx = (gles2_Context*)gles2_handle_get(s, ctx_);
672     pthread_mutex_unlock(&s->m);
673
674     if (!dpy)
675     {
676         /*
677          * Evas sets 'dpy' to NULL and calls this function after it
678          * destroys a context
679          */
680         dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
681     }
682
683     GLES2_PRINT("Making host context current...\n");
684
685     if (!eglMakeCurrent(dpy,
686         draw ? draw->surf : NULL,
687         read ? read->surf : NULL,
688         ctx?ctx->hctx:NULL)) {
689         GLES2_PRINT("\tMakeCurrent failed!\n");
690         GLES2_BARRIER_RET;
691         gles2_ret_TEGLBoolean(s, EGL_FALSE);
692         return;
693     }
694
695     // Initialize context arrays.
696     //TODO: if arrays already exist then keep them as is?
697     if (ctx && !ctx->arrays) {
698         if (ctx->client_type == EGL_OPENGL_ES_API) {
699             if(ctx->client_version == 1) {
700                 ctx->narrays = 6;
701                 ctx->arrays = malloc(ctx->narrays * sizeof(*ctx->arrays));
702             }
703             else if(ctx->client_version == 2) {
704                 ctx->narrays = gles2_getMaxVertexAttrib();
705                 ctx->arrays = malloc(ctx->narrays * sizeof(*ctx->arrays));
706                 GLES2_PRINT("Maximum number of host vertex arrays: %d.\n", ctx->narrays);
707             }
708             int i;
709             for (i = 0; i < ctx->narrays; ++i) {
710                     memset(&ctx->arrays[i], 0, sizeof(ctx->arrays[i]));
711             }
712         }
713     }
714
715     int context_index = gles2_getContextArrayIndex(ctx?ctx->client_type:c->rendering_api);
716     //TODO: Find out if we need to do anything with old context here
717     c->context[context_index] = ctx;
718     GLES2_PRINT("Made %p current (DRAW = %d, READ = %d)!\n", ctx, draw ? draw->id : 0, read ? read->id : 0);
719     GLES2_BARRIER_RET;
720     gles2_ret_TEGLBoolean(s, EGL_TRUE);
721 }
722
723 GLES2_CB(eglSwapBuffers)
724 {
725     GLES2_ARG(TEGLDisplay, dpy_);
726     GLES2_ARG(TEGLSurface, surface_);
727
728     pthread_mutex_lock(&s->m);
729     EGLDisplay dpy = (EGLDisplay)gles2_handle_get(s, dpy_);
730     gles2_Surface* fsurf = (EGLSurface)gles2_handle_get(s, surface_);
731     pthread_mutex_unlock(&s->m);
732     if (!fsurf) {
733         fprintf(stderr, "ERROR: Trying to swap NULL surface!\n");
734         GLES2_BARRIER_ARG;
735         GLES2_BARRIER_RET;
736         gles2_ret_TEGLBoolean(s, EGL_TRUE);
737         return;
738     }
739
740     if (gles2_surface_update(s, fsurf)) {
741         GLES2_BARRIER_ARG;
742         GLES2_PRINT("DIMENSIONS CHANGED!\n");
743        // glFinish();
744         free(fsurf->ddraw.pixels);
745         unsigned nbytes = fsurf->ddraw.width
746             * fsurf->ddraw.height*fsurf->ddraw.bpp;
747         fsurf->ddraw.pixels = malloc(nbytes);
748
749         gles2_transfer_free(&fsurf->tfr);
750         GLES2_BARRIER_RET;
751         gles2_transfer_compile(&fsurf->tfr, s, fsurf->pixelsp, nbytes);
752         eglSwapBuffers(dpy, fsurf->surf);
753         gles2_ret_TEGLBoolean(s, EGL_TRUE);
754         return;
755     }
756     GLES2_BARRIER_ARG;
757
758     GLES2_PRINT("Swapping DGLES surface ID = %d!\n", fsurf->id);
759     eglSwapBuffers(dpy, fsurf->surf);
760
761     GLES2_PRINT("Transferring frame!\n");
762     gles2_transfer_exec(&fsurf->tfr, s, fsurf->ddraw.pixels, 1);
763     GLES2_PRINT("\tDone!\n");
764     GLES2_BARRIER_RET;
765     gles2_ret_TEGLBoolean(s, EGL_TRUE);
766 }