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/>.
13 #include "gles2_calls.h"
14 #include "GLES2/gl2.h"
17 #define GLES2_CB(func) \
20 extern int gles2_getMaxVertexAttrib(void);
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.
27 static int gles2_getContextArrayIndex(EGLenum context_client_type)
29 switch (context_client_type) {
30 case EGL_OPENGL_ES_API:
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)
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));
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;
65 surf->pixelsp = pixelsp;
70 // TODO: Support swapping of offscreen surfaces.
71 static void gles2_eglSwapCallback(void* userdata)
74 GLES2_PRINT("Swap called!\n");
81 EGLint ret = eglGetError();
83 gles2_ret_TGLint(s, ret);
88 GLES2_ARG(TEGLenum, api);
91 EGLBoolean ret = eglBindAPI(api);
93 c->rendering_api = api;
95 gles2_ret_TEGLBoolean(s, ret);
98 GLES2_CB(eglGetDisplay)
100 // GLES2_ARG(TEGLDisplay, dpy);
104 GLES2_PRINT("Getting display...\n");
106 EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
108 GLES2_PRINT("\tGot host display %p...\n", dpy);
112 pthread_mutex_lock(&s->m);
114 uint32_t handle = gles2_handle_find(s, dpy);
118 handle = gles2_handle_create(s, dpy);
119 gles2_ret_TEGLDisplay(s, handle);
120 dpy_updatecaption(get_displaystate());
124 gles2_ret_TEGLDisplay(s, handle);
127 pthread_mutex_unlock(&s->m);
130 GLES2_CB(eglInitialize)
132 GLES2_ARG(TEGLDisplay, dpy_);
133 GLES2_ARG(Tptr, majorp);
134 GLES2_ARG(Tptr, minorp);
138 pthread_mutex_lock(&s->m);
140 EGLDisplay dpy = (EGLDisplay)gles2_handle_get(s, dpy_);
142 pthread_mutex_unlock(&s->m);
144 GLES2_PRINT("Request to initialize display %p...\n", dpy);
147 if (eglInitialize(dpy, &major, &minor)) {
148 GLES2_PRINT("Display initialized (EGL %d.%d)!\n", major, minor);
150 gles2_put_TEGLint(s, majorp, major);
151 gles2_put_TEGLint(s, minorp, minor);
152 gles2_ret_TEGLBoolean(s, EGL_TRUE);
156 GLES2_PRINT("Failed to initialize...\n");
158 gles2_ret_TEGLBoolean(s, EGL_FALSE);
161 GLES2_CB(eglGetConfigs)
163 GLES2_ARG(TEGLDisplay, dpy_);
164 GLES2_ARG(Tptr, configsp);
165 GLES2_ARG(TEGLint, config_size);
166 GLES2_ARG(Tptr, num_configp);
170 pthread_mutex_lock(&s->m);
172 EGLDisplay dpy = (EGLDisplay)gles2_handle_get(s, dpy_);
174 pthread_mutex_unlock(&s->m);
176 EGLConfig* configs = configsp ? malloc(sizeof(EGLConfig)*config_size) : NULL;
179 EGLBoolean ret = eglGetConfigs(dpy, configs, config_size, &num_config);
185 pthread_mutex_lock(&s->m);
186 for (i = 0; i < num_config; ++i) {
188 if (!(handle = gles2_handle_find(s, configs[i]))) {
189 handle = gles2_handle_create(s, configs[i]);
191 gles2_put_TEGLConfig(s, configsp + i*sizeof(TEGLConfig), handle);
193 pthread_mutex_unlock(&s->m);
197 gles2_put_TEGLint(s, num_configp, num_config);
199 gles2_ret_TEGLBoolean(s, ret);
202 GLES2_CB(eglChooseConfig)
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);
212 EGLint attrib_list_n = 0;
213 while (gles2_get_TEGLint(s, attrib_listp
214 + attrib_list_n*sizeof(EGLint)) != EGL_NONE) {
217 EGLint* attrib_list = malloc((attrib_list_n + 1)*sizeof(EGLint));
220 for (i = 0; i < attrib_list_n; ++i) {
221 attrib_list[i] = gles2_get_TEGLint(s, attrib_listp
224 attrib_list[attrib_list_n] = EGL_NONE;
226 pthread_mutex_lock(&s->m);
228 EGLDisplay dpy = (EGLDisplay)gles2_handle_get(s, dpy_);
230 pthread_mutex_unlock(&s->m);
233 EGLConfig* configs = configsp ? malloc(sizeof(EGLConfig)*config_size) : NULL;
236 EGLBoolean ret = eglChooseConfig(dpy, attrib_list, configs, config_size, &num_config);
242 pthread_mutex_lock(&s->m);
244 for (i = 0; i < num_config; ++i) {
246 if (!(handle = gles2_handle_find(s, configs[i]))) {
247 handle = gles2_handle_create(s, configs[i]);
249 gles2_put_TEGLConfig(s, configsp + i*sizeof(TEGLConfig), handle);
252 pthread_mutex_unlock(&s->m);
256 gles2_put_TEGLint(s, num_configp, num_config);
258 gles2_ret_TEGLBoolean(s, ret);
261 GLES2_CB(eglGetConfigAttrib)
263 GLES2_ARG(TEGLDisplay, dpy_);
264 GLES2_ARG(TEGLConfig, config);
265 GLES2_ARG(TEGLint, attribute);
266 GLES2_ARG(Tptr, valuep);
269 pthread_mutex_lock(&s->m);
271 EGLDisplay dpy = (EGLDisplay)gles2_handle_get(s, dpy_);
274 EGLBoolean ret = eglGetConfigAttrib(dpy, gles2_handle_get(s, config), attribute, &value);
276 pthread_mutex_unlock(&s->m);
280 gles2_put_TEGLint(s, valuep, value);
281 gles2_ret_TEGLBoolean(s, ret);
284 GLES2_CB(eglCreateWindowSurface)
286 GLES2_ARG(TEGLDisplay, dpy_);
287 GLES2_ARG(TEGLConfig, config_);
288 GLES2_ARG(Tptr, winp);
289 GLES2_ARG(Tptr, attrib_listp);
291 pthread_mutex_lock(&s->m);
293 EGLDisplay dpy = (EGLDisplay)gles2_handle_get(s, dpy_);
294 EGLConfig config = (EGLConfig)gles2_handle_get(s, config_);
296 pthread_mutex_unlock(&s->m);
300 gles2_Surface* fsurf;
302 if (!(fsurf = malloc(sizeof(*fsurf)))) {
303 GLES2_PRINT("\tFake window creation failed!\n");
306 gles2_ret_TEGLSurface(s, 0);
310 memset(fsurf, 0, sizeof(*fsurf));
312 fsurf->id = surf_id++;
314 fsurf->ddrawp = winp;
316 gles2_surface_update(s, fsurf);
318 DEGLDrawable* ddraw=&(fsurf->ddraw);
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);
324 unsigned nbytes = ddraw->width*ddraw->height*ddraw->bpp;
325 ddraw->pixels = malloc(nbytes);
326 ddraw->userdata = fsurf;
327 ddraw->swap = gles2_eglSwapCallback;
329 if((fsurf->surf = eglCreateOffscreenSurfaceDGLES(dpy, config, ddraw))
332 GLES2_PRINT("\tHost window creation failed!\n");
336 gles2_ret_TEGLSurface(s, 0);
340 GLES2_PRINT("Created at %p!\n", fsurf);
342 gles2_transfer_compile(&fsurf->tfr, s, fsurf->pixelsp, nbytes);
343 pthread_mutex_lock(&s->m);
345 gles2_ret_TEGLSurface(s, gles2_handle_create(s, fsurf));
347 pthread_mutex_unlock(&s->m);
350 GLES2_CB(eglCreatePixmapSurface)
352 GLES2_ARG(TEGLDisplay, dpy_);
353 GLES2_ARG(TEGLConfig, config_);
354 GLES2_ARG(Tptr, pixmapp);
355 GLES2_ARG(Tptr, attrib_listp);
357 pthread_mutex_lock(&s->m);
359 EGLDisplay dpy = (EGLDisplay)gles2_handle_get(s, dpy_);
360 EGLConfig config = (EGLConfig)gles2_handle_get(s, config_);
362 pthread_mutex_unlock(&s->m);
366 gles2_Surface* fsurf;
368 if (!(fsurf = malloc(sizeof(*fsurf)))) {
369 GLES2_PRINT("\tFake pixmap creation failed!\n");
372 gles2_ret_TEGLSurface(s, 0);
376 memset(fsurf, 0, sizeof(*fsurf));
378 fsurf->id = surf_id++;
379 fsurf->ddrawp = pixmapp;
381 gles2_surface_update(s, fsurf);
383 DEGLDrawable* ddraw=&(fsurf->ddraw);
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);
389 unsigned nbytes = ddraw->width*ddraw->height*ddraw->bpp;
390 ddraw->pixels = malloc(nbytes);
391 ddraw->userdata = fsurf;
392 ddraw->swap = gles2_eglSwapCallback;
395 if((fsurf->surf = eglCreateOffscreenSurfaceDGLES(dpy, config, ddraw))
398 GLES2_PRINT("\tHost pixmap creation failed!\n");
402 gles2_ret_TEGLSurface(s, 0);
406 GLES2_PRINT("Created at %p!\n", fsurf);
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);
414 GLES2_CB(eglCreatePbufferSurface)
416 GLES2_ARG(TEGLDisplay, dpy_);
417 GLES2_ARG(TEGLConfig, config_);
418 GLES2_ARG(Tptr, attrib_listp);
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) {
429 EGLint* attrib_list = malloc((attrib_list_n + 1)*sizeof(EGLint));
432 for (i = 0; i < attrib_list_n; ++i) {
433 attrib_list[i] = gles2_get_TEGLint(s, attrib_listp
436 attrib_list[attrib_list_n] = EGL_NONE;
438 gles2_Surface* fsurf;
440 if (!(fsurf = malloc(sizeof(*fsurf)))) {
441 GLES2_PRINT("\tPbuffer creation failed!\n");
444 gles2_ret_TEGLSurface(s, 0);
448 memset(fsurf, 0, sizeof(*fsurf));
450 fsurf->id = surf_id++;
456 if((fsurf->surf = eglCreatePbufferSurface(dpy, config, attrib_list))
459 GLES2_PRINT("\tPbuffer creation failed!\n");
462 gles2_ret_TEGLSurface(s, 0);
466 GLES2_PRINT("Created at %p!\n", fsurf);
468 pthread_mutex_lock(&s->m);
469 gles2_ret_TEGLSurface(s, gles2_handle_create(s, fsurf));
470 pthread_mutex_unlock(&s->m);
473 GLES2_CB(eglDestroySurface)
475 GLES2_ARG(TEGLDisplay, dpy_);
476 GLES2_ARG(TEGLSurface, surface_);
477 GLES2_BARRIER_ARG_NORET;
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);
485 GLES2_PRINT("Destroyed surface ID = %d...\n", fsurf->id);
488 eglDestroySurface(dpy, fsurf->surf);
489 if(fsurf->ddraw.pixels)
490 free(fsurf->ddraw.pixels);
492 // if(fsurf->pixmap == 0) {
493 gles2_transfer_free(&fsurf->tfr);
498 GLES2_CB(eglBindTexImage)
500 GLES2_ARG(TEGLDisplay, dpy_);
501 GLES2_ARG(TEGLSurface, surface_);
502 GLES2_ARG(TEGLint, buffer);
503 gles2_CompiledTransfer tfr;
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);
510 // FIXME: Not a very clean way..
511 uint32_t pixelsp = gles2_get_dword(s, fsurf->ddrawp + 4*sizeof(uint32_t));
513 unsigned nbytes = fsurf->ddraw.width
514 * fsurf->ddraw.height*fsurf->ddraw.bpp;
515 gles2_transfer_compile(&tfr, s, pixelsp, nbytes);
520 // gles2_transfer(s, pixelsp, nbytes, fsurf->ddraw.pixels, 0);
521 gles2_transfer_exec(&tfr, s, fsurf->ddraw.pixels, 0);
524 GLES2_PRINT("Binding surface ID = %d!\n", fsurf->id);
526 EGLBoolean ret = eglBindTexImage(dpy, fsurf->surf, buffer);
528 gles2_transfer_free(&tfr);
532 gles2_ret_TEGLBoolean(s, ret);
535 GLES2_CB(eglReleaseTexImage)
537 GLES2_ARG(TEGLDisplay, dpy_);
538 GLES2_ARG(TEGLSurface, surface_);
539 GLES2_ARG(TEGLint, buffer);
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);
547 GLES2_PRINT("Unbinding surface ID = %d!\n", fsurf->id);
549 EGLBoolean ret = eglReleaseTexImage(dpy, fsurf->surf, buffer);
551 gles2_ret_TEGLBoolean(s, ret);
554 GLES2_CB(eglCreateContext)
556 GLES2_ARG(TEGLDisplay, dpy_);
557 GLES2_ARG(TEGLConfig, config_);
558 GLES2_ARG(TEGLContext, share_context_);
559 GLES2_ARG(Tptr, attrib_listp);
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);
568 EGLint *attribs= NULL;
572 EGLint name = gles2_get_TEGLint(s, attrib_listp);
573 while ( name != EGL_NONE) {
575 name = gles2_get_TEGLint(s, attrib_listp
576 + (list_n-1)*sizeof(EGLint));
578 attribs = malloc(list_n*sizeof(EGLint));
580 for (i=0; i< list_n; i++) {
582 attribs[i] = gles2_get_TEGLint(s, attrib_listp
587 GLES2_PRINT("Host context creation requested...\n");
588 EGLContext hctx = eglCreateContext(dpy, config, share_context?share_context->hctx:NULL, attribs);
591 if (hctx == EGL_NO_CONTEXT) {
592 GLES2_PRINT("Context creation failed!\n");
594 gles2_ret_TEGLContext(s, 0);
596 gles2_Context * ctx = malloc(sizeof(gles2_Context));
597 memset(ctx, 0, sizeof(*ctx));
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) {
608 attribname = gles2_get_TEGLint(s, attrib_listp
609 + attrib_list_n*sizeof(EGLint));
611 if (attribname == EGL_CONTEXT_CLIENT_VERSION) {
613 version = gles2_get_TEGLint(s, attrib_listp
614 + attrib_list_n*sizeof(EGLint));
618 ctx->client_type = c->rendering_api;
619 ctx->client_version = version;
622 ctx->ebo_list = malloc(sizeof(gles2_ebo));
623 ctx->ebo_list->name = -1;
624 ctx->ebo_list->next = NULL;
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);
635 GLES2_CB(eglDestroyContext)
637 GLES2_ARG(TEGLDisplay, dpy_);
638 GLES2_ARG(TEGLContext, ctx_);
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);
648 gles2_ebo_free(ctx->ebo_list);
650 gles2_handle_free(s, ctx_);
651 GLES2_PRINT("Destroyed %p!\n", ctx);
653 pthread_mutex_unlock(&s->m);
656 gles2_ret_TEGLBoolean(s,ret);
659 GLES2_CB(eglMakeCurrent)
661 GLES2_ARG(TEGLDisplay, dpy_);
662 GLES2_ARG(TEGLSurface, draw_);
663 GLES2_ARG(TEGLSurface, read_);
664 GLES2_ARG(TEGLContext, ctx_);
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);
677 * Evas sets 'dpy' to NULL and calls this function after it
680 dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
683 GLES2_PRINT("Making host context current...\n");
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");
691 gles2_ret_TEGLBoolean(s, EGL_FALSE);
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) {
701 ctx->arrays = malloc(ctx->narrays * sizeof(*ctx->arrays));
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);
709 for (i = 0; i < ctx->narrays; ++i) {
710 memset(&ctx->arrays[i], 0, sizeof(ctx->arrays[i]));
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);
720 gles2_ret_TEGLBoolean(s, EGL_TRUE);
723 GLES2_CB(eglSwapBuffers)
725 GLES2_ARG(TEGLDisplay, dpy_);
726 GLES2_ARG(TEGLSurface, surface_);
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);
733 fprintf(stderr, "ERROR: Trying to swap NULL surface!\n");
736 gles2_ret_TEGLBoolean(s, EGL_TRUE);
740 if (gles2_surface_update(s, fsurf)) {
742 GLES2_PRINT("DIMENSIONS CHANGED!\n");
744 free(fsurf->ddraw.pixels);
745 unsigned nbytes = fsurf->ddraw.width
746 * fsurf->ddraw.height*fsurf->ddraw.bpp;
747 fsurf->ddraw.pixels = malloc(nbytes);
749 gles2_transfer_free(&fsurf->tfr);
751 gles2_transfer_compile(&fsurf->tfr, s, fsurf->pixelsp, nbytes);
752 eglSwapBuffers(dpy, fsurf->surf);
753 gles2_ret_TEGLBoolean(s, EGL_TRUE);
758 GLES2_PRINT("Swapping DGLES surface ID = %d!\n", fsurf->id);
759 eglSwapBuffers(dpy, fsurf->surf);
761 GLES2_PRINT("Transferring frame!\n");
762 gles2_transfer_exec(&fsurf->tfr, s, fsurf->ddraw.pixels, 1);
763 GLES2_PRINT("\tDone!\n");
765 gles2_ret_TEGLBoolean(s, EGL_TRUE);