1 #include "evas_gl_core_private.h"
2 
3 #ifndef _WIN32
4 # include <dlfcn.h>
5 #endif
6 
7 // EVGL GL Format Pair
8 typedef struct _GL_Format
9 {
10    int    bit;
11    GLenum fmt;
12 } GL_Format;
13 
14 // Extended struct size based on the 314 functions found in gl31.h
15 #define EVAS_GL_API_STRUCT_SIZE (sizeof(Evas_GL_API) + 300 * sizeof(void*))
16 static Evas_GL_API *gles1_funcs = NULL;
17 static Evas_GL_API *gles2_funcs = NULL;
18 static Evas_GL_API *gles3_funcs = NULL;
19 
20 EVGL_Engine *evgl_engine = NULL;
21 int _evas_gl_log_dom   = -1;
22 int _evas_gl_log_level = -1;
23 
24 typedef void           *(*glsym_func_void_ptr) ();
25 glsym_func_void_ptr glsym_evas_gl_native_context_get = NULL;
26 glsym_func_void_ptr glsym_evas_gl_engine_data_get = NULL;
27 
28 static void _surface_cap_print(int error);
29 static void _surface_context_list_print();
30 static void _internal_resources_destroy(void *eng_data, EVGL_Resource *rsc);
31 static void *_egl_image_create(EVGL_Context *context, int target, void *buffer);
32 static void _egl_image_destroy(void *image);
33 static int _evgl_direct_renderable(EVGL_Resource *rsc, EVGL_Surface *sfc);
34 
35 // NOTE: These constants are "hidden", kinda non public API. They should not
36 // be used unless you know exactly what you are doing.
37 // These vars replace environment variables.
38 #define EVAS_GL_OPTIONS_DIRECT_MEMORY_OPTIMIZE 0x1000
39 #define EVAS_GL_OPTIONS_DIRECT_OVERRIDE        0x2000
40 
41 extern void (*EXT_FUNC_GLES1(glGenFramebuffersOES)) (GLsizei n, GLuint* framebuffers);
42 extern void (*EXT_FUNC_GLES1(glBindFramebufferOES)) (GLenum target, GLuint framebuffer);
43 extern void (*EXT_FUNC_GLES1(glFramebufferTexture2DOES)) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
44 extern void (*EXT_FUNC_GLES1(glFramebufferRenderbufferOES)) (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
45 extern GLenum (*EXT_FUNC_GLES1(glCheckFramebufferStatusOES)) (GLenum target);
46 
47 //---------------------------------------------------------------//
48 // Internal Resources:
49 //  - Surface and Context used for internal buffer creation
50 //---------------------------------------------------------------//
51 static void *
_internal_resources_create(void * eng_data)52 _internal_resources_create(void *eng_data)
53 {
54    EVGL_Resource *rsc = NULL;
55 
56    // Check if engine is valid
57    if (!evgl_engine)
58      {
59         ERR("EVGL Engine not initialized!");
60         return NULL;
61      }
62 
63    // Allocate resource
64    rsc = calloc(1, sizeof(EVGL_Resource));
65    if (!rsc)
66      {
67         ERR("Error allocating EVGL_Resource");
68         return NULL;
69      }
70    rsc->id = eina_thread_self();
71    rsc->error_state = EVAS_GL_SUCCESS;
72 
73    // Get display
74    rsc->display = evgl_engine->funcs->display_get(eng_data);
75    if (!rsc->display)
76      {
77         ERR("Error getting display");
78         goto error;
79      }
80 
81    return rsc;
82 
83 error:
84    _internal_resources_destroy(eng_data, rsc);
85    return NULL;
86 }
87 
88 static void
_internal_resources_destroy(void * eng_data,EVGL_Resource * rsc)89 _internal_resources_destroy(void *eng_data, EVGL_Resource *rsc)
90 {
91    if (!rsc) return;
92 
93    if (!eng_data)
94      {
95         free(rsc);
96         return;
97      }
98 
99    if (rsc->context)
100      evgl_engine->funcs->context_destroy(eng_data, rsc->context);
101    if (rsc->surface)
102      evgl_engine->funcs->surface_destroy(eng_data, rsc->surface);
103    if (rsc->window)
104      evgl_engine->funcs->native_window_destroy(eng_data, rsc->window);
105 
106    free(rsc);
107 }
108 
109 static int
_internal_resource_make_current(void * eng_data,EVGL_Surface * sfc,EVGL_Context * ctx)110 _internal_resource_make_current(void *eng_data, EVGL_Surface *sfc, EVGL_Context *ctx)
111 {
112    EVGL_Resource *rsc = NULL;
113    void *surface = NULL;
114    void *context = NULL;
115    int ret = 0;
116 
117    // Retrieve the resource object
118    if (!(rsc = _evgl_tls_resource_get()))
119      {
120         if (!(rsc = _evgl_tls_resource_create(eng_data)))
121           {
122              ERR("Error creating resources in tls.");
123              return 0;
124           }
125      }
126 
127    // Set context from input or from resource
128    if (ctx)
129      context = ctx->context;
130    else
131      {
132         if (!rsc->context)
133           {
134              // Create a resource context
135              rsc->context = evgl_engine->funcs->context_create(eng_data, NULL, EVAS_GL_GLES_2_X);
136              if (!rsc->context)
137                {
138                   ERR("Internal resource context creation failed.");
139                   return 0;
140                }
141           }
142 
143         context = (void*)rsc->context;
144      }
145 
146    if (sfc)
147      {
148         if (_evgl_direct_renderable(rsc, sfc)) // Direct rendering
149           {
150              // Do Nothing
151           }
152         else if ((ctx) && (ctx->pixmap_image_supported)) // Pixmap surface
153           {
154              if (!sfc->indirect_sfc)
155                {
156                   evgl_engine->funcs->indirect_surface_create(evgl_engine, eng_data, sfc, sfc->cfg, sfc->w, sfc->h);
157                   if (sfc->egl_image) _egl_image_destroy(sfc->egl_image);
158                   sfc->egl_image = _egl_image_create(NULL, EVAS_GL_NATIVE_PIXMAP, sfc->indirect_sfc_native);
159                }
160              surface = (void*)sfc->indirect_sfc;
161 
162              if (!ctx->indirect_context)
163                ctx->indirect_context = evgl_engine->funcs->gles_context_create(eng_data, ctx, sfc);
164              context = (void*)ctx->indirect_context;
165           }
166         else if (sfc->pbuffer.native_surface) // Pbuffer surface
167           {
168              surface = (void*)sfc->pbuffer.native_surface;
169           }
170         else // FBO
171           {
172              // Do Nothing
173           }
174      }
175 
176    if (!surface)
177      {
178         // Set the surface to evas surface if it's there
179         if (rsc->id == evgl_engine->main_tid)
180            rsc->direct.surface = evgl_engine->funcs->evas_surface_get(eng_data);
181 
182         if (rsc->direct.surface)
183            surface = (void*)rsc->direct.surface;
184         else
185           {
186              if (!rsc->window)
187                {
188                   // Create resource surface
189                   rsc->window = evgl_engine->funcs->native_window_create(eng_data);
190                   if (!rsc->window)
191                     {
192                        ERR("Error creating native window");
193                        return 0;
194                     }
195                }
196 
197              if (!rsc->surface)
198                {
199                   rsc->surface = evgl_engine->funcs->surface_create(eng_data, rsc->window);
200                   if (!rsc->surface)
201                     {
202                        ERR("Error creating native surface");
203                        return 0;
204                     }
205                }
206 
207              surface = (void*)rsc->surface;
208           }
209      }
210 
211    // Do the make current
212    if (evgl_engine->api_debug_mode)
213      DBG("Calling make_current(%p, %p)", surface, context);
214    ret = evgl_engine->funcs->make_current(eng_data, surface, context, 1);
215    if (!ret)
216      {
217         ERR("Engine make_current with internal resources failed.");
218         return 0;
219      }
220 
221    return 1;
222 }
223 
224 //---------------------------------------------------------------//
225 // Surface Related Functions
226 //  - Texture/ Renderbuffer Creation/ Attachment to FBO
227 //  - Surface capability check
228 //  - Internal config choose function
229 //---------------------------------------------------------------//
230 // Gen Texture
231 static void
_texture_create(GLuint * tex)232 _texture_create(GLuint *tex)
233 {
234    glGenTextures(1, tex);
235 }
236 
237 // Create and allocate 2D texture
238 static void
_texture_allocate_2d(GLuint tex,GLint ifmt,GLenum fmt,GLenum type,int w,int h)239 _texture_allocate_2d(GLuint tex, GLint ifmt, GLenum fmt, GLenum type, int w, int h)
240 {
241    //if (!(*tex))
242    //   glGenTextures(1, tex);
243    GLint curr_tex = 0;
244    glGetIntegerv(GL_TEXTURE_BINDING_2D, &curr_tex);
245 
246    glBindTexture(GL_TEXTURE_2D, tex);
247    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
248    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
249    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
250    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
251    glTexImage2D(GL_TEXTURE_2D, 0, ifmt, w, h, 0, fmt, type, NULL);
252    glBindTexture(GL_TEXTURE_2D, (GLuint)curr_tex);
253 }
254 
255 // Destroy Texture
256 static void
_texture_destroy(GLuint * tex)257 _texture_destroy(GLuint *tex)
258 {
259    GLint curr_tex = 0;
260    glGetIntegerv(GL_TEXTURE_BINDING_2D, &curr_tex);
261 
262    if ((GLuint)curr_tex == *tex) glBindTexture(GL_TEXTURE_2D, 0);
263    if (*tex)
264      {
265         glDeleteTextures(1, tex);
266         *tex = 0;
267      }
268 }
269 
270 // Attach 2D texture with the given format to already bound FBO
271 // *NOTE: attach2 here is used for depth_stencil attachment in GLES env.
272 static void
_texture_attach_2d(GLuint tex,GLenum attach,GLenum attach2,int samples,Evas_GL_Context_Version version)273 _texture_attach_2d(GLuint tex, GLenum attach, GLenum attach2, int samples, Evas_GL_Context_Version version)
274 {
275    if (samples && (version == EVAS_GL_GLES_2_X))
276      {
277 #ifdef GL_GLES
278         if (EXT_FUNC(glFramebufferTexture2DMultisample))
279           {
280              EXT_FUNC(glFramebufferTexture2DMultisample)(GL_FRAMEBUFFER,
281                                                          attach,
282                                                          GL_TEXTURE_2D, tex,
283                                                          0, samples);
284 
285              if (attach2)
286                EXT_FUNC(glFramebufferTexture2DMultisample)(GL_FRAMEBUFFER,
287                                                            attach2,
288                                                            GL_TEXTURE_2D, tex,
289                                                            0, samples);
290           }
291         else
292 #endif
293         ERR("MSAA not supported.  Should not have come in here...!");
294      }
295    else if (version == EVAS_GL_GLES_1_X)
296      {
297         if (EXT_FUNC_GLES1(glFramebufferTexture2DOES))
298           EXT_FUNC_GLES1(glFramebufferTexture2DOES)(GL_FRAMEBUFFER, attach, GL_TEXTURE_2D, tex, 0);
299 
300         if (attach2)
301           if (EXT_FUNC_GLES1(glFramebufferTexture2DOES))
302             EXT_FUNC_GLES1(glFramebufferTexture2DOES)(GL_FRAMEBUFFER, attach2, GL_TEXTURE_2D, tex, 0);
303      }
304    else
305      {
306         glFramebufferTexture2D(GL_FRAMEBUFFER, attach, GL_TEXTURE_2D, tex, 0);
307 
308         if (attach2)
309            glFramebufferTexture2D(GL_FRAMEBUFFER, attach2, GL_TEXTURE_2D, tex, 0);
310 
311      }
312 }
313 
314 static void *
_egl_image_create(EVGL_Context * context,int target,void * buffer)315 _egl_image_create(EVGL_Context *context, int target, void *buffer)
316 {
317 #ifdef GL_GLES
318    EGLDisplay dpy = EGL_NO_DISPLAY;
319    EGLContext ctx = EGL_NO_CONTEXT;
320    EVGL_Resource *rsc = NULL;
321    int attribs[10];
322    int n = 0;
323 
324    // Retrieve the resource object
325    if (!(rsc = _evgl_tls_resource_get()))
326      {
327         ERR("Error creating resources in tls.");
328         return NULL;
329      }
330 
331    dpy = (EGLDisplay)rsc->display;
332    if (target == EGL_GL_TEXTURE_2D_KHR)
333      {
334         ctx = (EGLContext)context->context;
335         attribs[n++] = EGL_GL_TEXTURE_LEVEL_KHR;
336         attribs[n++] = 0;
337      }
338    attribs[n++] = EGL_IMAGE_PRESERVED_KHR;
339    attribs[n++] = 0;
340    attribs[n++] = EGL_NONE;
341 
342    return EXT_FUNC_EGL(eglCreateImage)(dpy, ctx, target, (EGLClientBuffer)(uintptr_t)buffer, attribs);
343 #else
344    (void) context; (void) target; (void) buffer;
345    return NULL;
346 #endif
347 }
348 
349 static void
_egl_image_destroy(void * image)350 _egl_image_destroy(void *image)
351 {
352 #ifdef GL_GLES
353    EGLDisplay dpy = EGL_NO_DISPLAY;
354    EVGL_Resource *rsc = NULL;
355 
356    // Retrieve the resource object
357    if (!(rsc = _evgl_tls_resource_get()))
358      {
359         ERR("Error creating resources in tls.");
360         return;
361      }
362 
363    dpy = (EGLDisplay)rsc->display;
364    if (!dpy) return;
365 
366    EXT_FUNC_EGL(eglDestroyImage)(dpy, image);
367 #else
368    (void) image;
369 #endif
370 }
371 
372 static void
_framebuffer_create(GLuint * buf,Evas_GL_Context_Version version)373 _framebuffer_create(GLuint *buf, Evas_GL_Context_Version version)
374 {
375    if (version == EVAS_GL_GLES_1_X)
376      {
377         if (EXT_FUNC_GLES1(glGenFramebuffersOES))
378             EXT_FUNC_GLES1(glGenFramebuffersOES)(1, buf);
379      }
380    else
381      {
382         glGenFramebuffers(1, buf);
383      }
384 }
385 
386 static void
_framebuffer_bind(GLuint buf,Evas_GL_Context_Version version)387 _framebuffer_bind(GLuint buf, Evas_GL_Context_Version version)
388 {
389    if (version == EVAS_GL_GLES_1_X)
390      {
391         if (EXT_FUNC_GLES1(glBindFramebufferOES))
392           EXT_FUNC_GLES1(glBindFramebufferOES)(GL_FRAMEBUFFER, buf);
393      }
394    else
395      {
396         glBindFramebuffer(GL_FRAMEBUFFER, buf);
397      }
398 }
399 
400 static void
_framebuffer_draw_bind(GLuint buf,Evas_GL_Context_Version version)401 _framebuffer_draw_bind(GLuint buf, Evas_GL_Context_Version version)
402 {
403    if (version == EVAS_GL_GLES_3_X)
404      glBindFramebuffer(GL_DRAW_FRAMEBUFFER, buf);
405 }
406 
407 //This function is not needed in EvasGL backend engine with GLES 2.0.
408 //But It is useful when EvasGL backend works with GLES 3.X and use read buffers.
409 static void
_framebuffer_read_bind(GLuint buf,Evas_GL_Context_Version version)410 _framebuffer_read_bind(GLuint buf, Evas_GL_Context_Version version)
411 {
412    if (version == EVAS_GL_GLES_3_X)
413      glBindFramebuffer(GL_READ_FRAMEBUFFER, buf);
414 }
415 
416 static GLenum
_framebuffer_check(Evas_GL_Context_Version version)417 _framebuffer_check(Evas_GL_Context_Version version)
418 {
419    GLenum ret = 0;
420    if (version == EVAS_GL_GLES_1_X)
421      {
422         if (EXT_FUNC_GLES1(glCheckFramebufferStatusOES))
423           ret = EXT_FUNC_GLES1(glCheckFramebufferStatusOES)(GL_FRAMEBUFFER);
424      }
425    else
426      {
427         ret = glCheckFramebufferStatus(GL_FRAMEBUFFER);
428      }
429    return ret;
430 }
431 
432 // Gen Renderbuffer
433 static void
_renderbuffer_create(GLuint * buf)434 _renderbuffer_create(GLuint *buf)
435 {
436    glGenRenderbuffers(1, buf);
437 }
438 
439 
440 // Attach a renderbuffer with the given format to already bound FBO
441 static void
_renderbuffer_allocate(GLuint buf,GLenum fmt,int w,int h,int samples)442 _renderbuffer_allocate(GLuint buf, GLenum fmt, int w, int h, int samples)
443 {
444    glBindRenderbuffer(GL_RENDERBUFFER, buf);
445    if (samples)
446      {
447         if (glsym_glRenderbufferStorageMultisample)
448           glsym_glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, fmt, w, h);
449         else
450           {
451 #ifdef GL_GLES
452              if (EXT_FUNC(glRenderbufferStorageMultisample))
453                EXT_FUNC(glRenderbufferStorageMultisample)(GL_RENDERBUFFER, samples, fmt, w, h);
454              else
455 #endif
456                ERR("MSAA not supported.  Should not have come in here...!");
457           }
458      }
459    else
460      glRenderbufferStorage(GL_RENDERBUFFER, fmt, w, h);
461    glBindRenderbuffer(GL_RENDERBUFFER, 0);
462 }
463 
464 static void
_renderbuffer_destroy(GLuint * buf)465 _renderbuffer_destroy(GLuint *buf)
466 {
467    if (*buf)
468      {
469         glDeleteRenderbuffers(1, buf);
470         *buf = 0;
471      }
472 }
473 
474 // Attach a renderbuffer with the given format to already bound FBO
475 static void
_renderbuffer_attach(GLuint buf,GLenum attach,Evas_GL_Context_Version version)476 _renderbuffer_attach(GLuint buf, GLenum attach, Evas_GL_Context_Version version)
477 {
478    if (version == EVAS_GL_GLES_1_X)
479      {
480         if (EXT_FUNC_GLES1(glFramebufferRenderbufferOES))
481           EXT_FUNC_GLES1(glFramebufferRenderbufferOES)(GL_FRAMEBUFFER, attach, GL_RENDERBUFFER, buf);
482      }
483    else
484      {
485         glFramebufferRenderbuffer(GL_FRAMEBUFFER, attach, GL_RENDERBUFFER, buf);
486      }
487 }
488 
489 // Check whether the given FBO surface config is supported by the driver
490 // TODO - we also should test with GLES3's formats.
491 static int
_fbo_surface_cap_test(GLint color_ifmt,GLenum color_fmt,GLenum depth_fmt,GLenum stencil_fmt,int mult_samples)492 _fbo_surface_cap_test(GLint color_ifmt, GLenum color_fmt,
493                       GLenum depth_fmt, GLenum stencil_fmt, int mult_samples)
494 {
495    GLuint fbo = 0;
496    GLuint color_buf = 0;
497    GLuint depth_buf = 0;
498    GLuint stencil_buf = 0;
499    GLuint depth_stencil_buf = 0;
500    int depth_stencil = 0;
501    int fb_status = 0;
502    int w = 2, h = 2;   // Test it with a simple (2,2) surface.  Should I test it with NPOT?
503    Evas_GL_Context_Version ver = evas_gl_common_version_check(NULL);
504 
505    // Gen FBO
506    glGenFramebuffers(1, &fbo);
507    glBindFramebuffer(GL_FRAMEBUFFER, fbo);
508 
509    // FIXME: GLES 3 support for MSAA is NOT IMPLEMENTED!
510    // Needs to use RenderbufferStorageMultisample + FramebufferRenderbuffer
511 
512    // Color Buffer Texture
513    if ((color_ifmt) && (color_fmt))
514      {
515         _texture_create(&color_buf);
516         _texture_allocate_2d(color_buf, color_ifmt, color_fmt, GL_UNSIGNED_BYTE, w, h);
517         _texture_attach_2d(color_buf, GL_COLOR_ATTACHMENT0, 0, mult_samples, ver);
518      }
519 
520       // Check Depth_Stencil Format First
521 #ifdef GL_GLES
522    if ((depth_fmt == GL_DEPTH_STENCIL_OES) && (!mult_samples))
523      {
524         _texture_create(&depth_stencil_buf);
525         _texture_allocate_2d(depth_stencil_buf, depth_fmt,
526                            depth_fmt, GL_UNSIGNED_INT_24_8_OES, w, h);
527         _texture_attach_2d(depth_stencil_buf, GL_DEPTH_ATTACHMENT,
528                            GL_STENCIL_ATTACHMENT, mult_samples, EINA_FALSE);
529         depth_stencil = 1;
530      }
531    else if ((depth_fmt == GL_DEPTH24_STENCIL8_OES) && (mult_samples))
532 #else
533    if (depth_fmt == GL_DEPTH24_STENCIL8)
534 #endif
535      {
536         _renderbuffer_create(&depth_stencil_buf);
537         _renderbuffer_allocate(depth_stencil_buf, depth_fmt, w, h, mult_samples);
538 #ifdef GL_GLES
539         _renderbuffer_attach(depth_stencil_buf, GL_DEPTH_ATTACHMENT, EINA_FALSE);
540         _renderbuffer_attach(depth_stencil_buf, GL_STENCIL_ATTACHMENT, EINA_FALSE);
541 #else
542         _renderbuffer_attach(depth_stencil_buf, GL_DEPTH_STENCIL_ATTACHMENT, EINA_FALSE);
543 #endif
544         depth_stencil = 1;
545      }
546 
547    // Depth Attachment
548    if ((!depth_stencil) && (depth_fmt))
549      {
550         _renderbuffer_create(&depth_buf);
551         _renderbuffer_allocate(depth_buf, depth_fmt, w, h, mult_samples);
552         _renderbuffer_attach(depth_buf, GL_DEPTH_ATTACHMENT, EVAS_GL_GLES_2_X);
553      }
554 
555    // Stencil Attachment
556    if ((!depth_stencil) && (stencil_fmt))
557      {
558         _renderbuffer_create(&stencil_buf);
559         _renderbuffer_allocate(stencil_buf, stencil_fmt, w, h, mult_samples);
560         _renderbuffer_attach(stencil_buf, GL_STENCIL_ATTACHMENT, EVAS_GL_GLES_2_X);
561      }
562 
563    // Check FBO for completeness
564    fb_status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
565 
566    // Delete Created Resources
567    _texture_destroy(&color_buf);
568    _renderbuffer_destroy(&depth_buf);
569    _renderbuffer_destroy(&stencil_buf);
570 #ifdef GL_GLES
571    _texture_destroy(&depth_stencil_buf);
572 #else
573    _renderbuffer_destroy(&depth_stencil_buf);
574 #endif
575 
576    // Delete FBO
577    glBindFramebuffer(GL_FRAMEBUFFER, 0);
578    if (fbo) glDeleteFramebuffers(1, &fbo);
579 
580    // Return the result
581    if (fb_status != GL_FRAMEBUFFER_COMPLETE)
582      {
583         int err = glGetError();
584 
585         if (err != GL_NO_ERROR)
586            DBG("glGetError() returns %x ", err);
587 
588         return 0;
589      }
590    else
591       return 1;
592 }
593 
594 static int
_surface_cap_test(EVGL_Surface_Format * fmt,GL_Format * color,GL_Format * depth,GL_Format * stencil,int samples)595 _surface_cap_test(EVGL_Surface_Format *fmt, GL_Format *color,
596                   GL_Format *depth, GL_Format *stencil, int samples)
597 {
598    int ret = 0;
599 
600    if ( (depth->bit == DEPTH_STENCIL) && (stencil->bit != STENCIL_BIT_8))
601       return 0;
602 
603    ret = _fbo_surface_cap_test((GLint)color->fmt,
604                                color->fmt,
605                                depth->fmt,
606                                stencil->fmt, samples);
607    if (ret)
608      {
609         fmt->color_bit  = color->bit;
610         fmt->color_ifmt = (GLint)color->fmt;
611         fmt->color_fmt  = color->fmt;
612         fmt->samples = samples;
613 
614         if (depth->bit == DEPTH_STENCIL)
615           {
616              // Depth Stencil Case
617              fmt->depth_stencil_fmt = depth->fmt;
618              fmt->depth_bit   = DEPTH_BIT_24;
619              fmt->depth_fmt   = 0;
620              fmt->stencil_bit = STENCIL_BIT_8;
621              fmt->stencil_fmt = 0;
622           }
623         else
624           {
625              fmt->depth_stencil_fmt = 0;
626              fmt->depth_bit = depth->bit;
627              fmt->depth_fmt = depth->fmt;
628              fmt->stencil_bit = stencil->bit;
629              fmt->stencil_fmt = stencil->fmt;
630           }
631      }
632 
633    return ret;
634 }
635 
636 
637 static int
_surface_cap_check()638 _surface_cap_check()
639 {
640    int num_fmts = 0;
641    int i, j, k, m;
642 
643    GL_Format color[]   = {
644                            { COLOR_RGB_888,   GL_RGB },
645                            { COLOR_RGBA_8888, GL_RGBA },
646                            { -1, -1 },
647                          };
648 
649 #ifdef GL_GLES
650    GL_Format depth[]   = {
651                            { DEPTH_NONE,   0 },
652                            { DEPTH_STENCIL, GL_DEPTH_STENCIL_OES },
653                            { DEPTH_STENCIL, GL_DEPTH24_STENCIL8_OES },
654                            { DEPTH_BIT_8,   GL_DEPTH_COMPONENT },
655                            { DEPTH_BIT_16,  GL_DEPTH_COMPONENT16 },
656                            { DEPTH_BIT_24,  GL_DEPTH_COMPONENT24_OES },
657                            { DEPTH_BIT_32,  GL_DEPTH_COMPONENT32_OES },
658                            { -1, -1 },
659                          };
660    GL_Format stencil[] = {
661                            { STENCIL_NONE, 0 },
662                            { STENCIL_BIT_1, GL_STENCIL_INDEX1_OES },
663                            { STENCIL_BIT_4, GL_STENCIL_INDEX4_OES },
664                            { STENCIL_BIT_8, GL_STENCIL_INDEX8 },
665                            { -1, -1 },
666                          };
667 #else
668    GL_Format depth[]   = {
669                            { DEPTH_NONE,   0 },
670                            { DEPTH_STENCIL, GL_DEPTH24_STENCIL8 },
671                            { DEPTH_BIT_8,   GL_DEPTH_COMPONENT },
672                            { DEPTH_BIT_16,  GL_DEPTH_COMPONENT16 },
673                            { DEPTH_BIT_24,  GL_DEPTH_COMPONENT24 },
674                            { DEPTH_BIT_32,  GL_DEPTH_COMPONENT32 },
675                            { -1, -1 },
676                          };
677    GL_Format stencil[] = {
678                            { STENCIL_NONE, 0 },
679                            { STENCIL_BIT_1, GL_STENCIL_INDEX1 },
680                            { STENCIL_BIT_4, GL_STENCIL_INDEX4 },
681                            { STENCIL_BIT_8, GL_STENCIL_INDEX8 },
682                            { -1, -1 },
683                          };
684 #endif
685 
686    int msaa_samples[4] = {0, -1, -1, -1};  // { NO_MSAA, LOW, MED, HIGH }
687 
688    EVGL_Surface_Format *fmt = NULL;
689 
690    // Check if engine is valid
691    if (!evgl_engine)
692      {
693         ERR("EVGL Engine not initialized!");
694         return 0;
695      }
696 
697    // Check Surface Cap for MSAA
698    if (evgl_engine->caps.msaa_supported)
699      {
700         if ((evgl_engine->caps.msaa_samples[2] != evgl_engine->caps.msaa_samples[1]) &&
701             (evgl_engine->caps.msaa_samples[2] != evgl_engine->caps.msaa_samples[0]))
702              msaa_samples[3] = evgl_engine->caps.msaa_samples[2];    // HIGH
703         if ((evgl_engine->caps.msaa_samples[1] != evgl_engine->caps.msaa_samples[0]))
704              msaa_samples[2] = evgl_engine->caps.msaa_samples[1];    // MED
705         if (evgl_engine->caps.msaa_samples[0])
706              msaa_samples[1] = evgl_engine->caps.msaa_samples[0];    // LOW
707      }
708 
709 
710    // MSAA
711    for ( m = 0; m < 4; m++)
712      {
713         if (msaa_samples[m] < 0) continue;
714 
715         // Color Formats
716         i = 0;
717         while ( color[i].bit >= 0 )
718           {
719              j = 0;
720              // Depth Formats
721              while ( depth[j].bit >= 0 )
722                {
723                   k = 0;
724                   // Stencil Formats
725                   while ( stencil[k].bit >= 0)
726                     {
727                        fmt = &evgl_engine->caps.fbo_fmts[num_fmts];
728                        if (_surface_cap_test(fmt, &color[i], &depth[j], &stencil[k], msaa_samples[m]))
729                           num_fmts++;
730                        k++;
731                     }
732                   j++;
733                }
734              i++;
735           }
736      }
737 
738    return num_fmts;
739 }
740 
741 static int
_surface_cap_load(Eet_File * ef)742 _surface_cap_load(Eet_File *ef)
743 {
744    int res = 0, i = 0, length = 0;
745    char tag[80];
746    char *data = NULL;
747 
748    data = eet_read(ef, "num_fbo_fmts", &length);
749    if ((!data) || (length <= 0)) goto finish;
750    if (data[length - 1] != 0) goto finish;
751    evgl_engine->caps.num_fbo_fmts = atoi(data);
752    free(data);
753    data = NULL;
754 
755    // !!!FIXME
756    // Should use eet functionality instead of just reading using sscanfs...
757    for (i = 0; i < evgl_engine->caps.num_fbo_fmts; ++i)
758      {
759         EVGL_Surface_Format *fmt = &evgl_engine->caps.fbo_fmts[i];
760 
761         snprintf(tag, sizeof(tag), "fbo_%d", i);
762         data = eet_read(ef, tag, &length);
763         if ((!data) || (length <= 0)) goto finish;
764         if (data[length - 1] != 0) goto finish;
765         sscanf(data, "%d%d%d%d%d%d%d%d%d%d",
766                &(fmt->index),
767                (int*)(&(fmt->color_bit)), &(fmt->color_ifmt), &(fmt->color_fmt),
768                (int*)(&(fmt->depth_bit)), &(fmt->depth_fmt),
769                (int*)(&(fmt->stencil_bit)), &(fmt->stencil_fmt),
770                &(fmt->depth_stencil_fmt),
771                &(fmt->samples));
772         free(data);
773         data = NULL;
774      }
775    res = 1;
776 
777 finish:
778    if (data) free(data);
779    return res;
780 }
781 
782 static int
_surface_cap_save(Eet_File * ef)783 _surface_cap_save(Eet_File *ef)
784 {
785    int i = 0;
786    char tag[80], data[80];
787 
788    snprintf(data, sizeof(data), "%d", evgl_engine->caps.num_fbo_fmts);
789    if (eet_write(ef, "num_fbo_fmts", data, strlen(data) + 1, 1) < 0)
790       return 0;
791 
792    // !!!FIXME
793    // Should use eet functionality instead of just writing out using snprintfs...
794    for (i = 0; i < evgl_engine->caps.num_fbo_fmts; ++i)
795      {
796         EVGL_Surface_Format *fmt = &evgl_engine->caps.fbo_fmts[i];
797 
798         snprintf(tag, sizeof(tag), "fbo_%d", i);
799         snprintf(data, sizeof(data), "%d %d %d %d %d %d %d %d %d %d",
800                  fmt->index,
801                  fmt->color_bit, fmt->color_ifmt, fmt->color_fmt,
802                  fmt->depth_bit, fmt->depth_fmt,
803                  fmt->stencil_bit, fmt->stencil_fmt,
804                  fmt->depth_stencil_fmt,
805                  fmt->samples);
806         if (eet_write(ef, tag, data, strlen(data) + 1, 1) < 0) return 0;
807      }
808 
809    return 1;
810 }
811 
812 static int
_surface_cap_cache_load()813 _surface_cap_cache_load()
814 {
815    /* check eet */
816    Eet_File *et = NULL;
817    char cap_dir_path[PATH_MAX];
818    char cap_file_path[PATH_MAX];
819 
820    if (!evas_gl_common_file_cache_dir_check(cap_dir_path, sizeof(cap_dir_path)))
821       return 0;
822 
823    if (!evas_gl_common_file_cache_file_check(cap_dir_path, "surface_cap",
824                                              cap_file_path, sizeof(cap_dir_path)))
825       return 0;
826 
827    /* use eet */
828    if (!eet_init()) return 0;
829    et = eet_open(cap_file_path, EET_FILE_MODE_READ);
830    if (!et) goto error;
831 
832    if (!_surface_cap_load(et))
833       goto error;
834 
835    if (et) eet_close(et);
836    eet_shutdown();
837    return 1;
838 
839 error:
840    if (et) eet_close(et);
841    eet_shutdown();
842    return 0;
843 }
844 
845 static int
_surface_cap_cache_save()846 _surface_cap_cache_save()
847 {
848    /* check eet */
849    Eet_File *et = NULL; //check eet file
850    int tmpfd = -1;
851    char cap_dir_path[PATH_MAX];
852    char cap_file_path[PATH_MAX];
853    char tmp_file_name[PATH_MAX + PATH_MAX + 128];
854    Eina_Tmpstr *tmp_file_path = NULL;
855 
856    /* use eet */
857    if (!eet_init()) return 0;
858 
859    if (!evas_gl_common_file_cache_dir_check(cap_dir_path, sizeof(cap_dir_path)))
860      {
861         if (!evas_gl_common_file_cache_mkpath(cap_dir_path))
862           return 0; /* we can't make directory */
863      }
864 
865    evas_gl_common_file_cache_file_check(cap_dir_path, "surface_cap", cap_file_path,
866                                         sizeof(cap_dir_path));
867 
868    /* use mkstemp for writing */
869    snprintf(tmp_file_name, sizeof(tmp_file_name), "%s.XXXXXX.cache", cap_file_path);
870    tmpfd = eina_file_mkstemp(tmp_file_name, &tmp_file_path);
871    if (tmpfd < 0) goto error;
872 
873    et = eet_open(tmp_file_path, EET_FILE_MODE_WRITE);
874    if (!et) goto error;
875 
876    if (!_surface_cap_save(et)) goto error;
877 
878    if (eet_close(et) != EET_ERROR_NONE) goto destroyed;
879    if (rename(tmp_file_path, cap_file_path) < 0) goto destroyed;
880    eina_tmpstr_del(tmp_file_path);
881    close(tmpfd);
882    eet_shutdown();
883 
884    return 1;
885 
886 destroyed:
887    et = NULL;
888 
889 error:
890    if (tmpfd >= 0) close(tmpfd);
891    if (et) eet_close(et);
892    if (evas_gl_common_file_cache_file_exists(tmp_file_path))
893      unlink(tmp_file_path);
894    eina_tmpstr_del(tmp_file_path);
895    eet_shutdown();
896    return 0;
897 }
898 
899 static int
_surface_cap_init(void * eng_data)900 _surface_cap_init(void *eng_data)
901 {
902    int gles_version;
903    int ret = 0;
904    int max_size = 0;
905    int max_samples = 0;
906 
907    // Do internal make current
908    if (!_internal_resource_make_current(eng_data, NULL, NULL))
909      {
910         ERR("Error doing an internal resource make current");
911         return ret;
912      }
913 
914    // Query the max width and height of the surface
915    glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &max_size);
916 
917    evgl_engine->caps.max_w = max_size;
918    evgl_engine->caps.max_h = max_size;
919    DBG("Max Surface Width: %d   Height: %d", evgl_engine->caps.max_w, evgl_engine->caps.max_h);
920 
921    gles_version = evas_gl_common_version_check(NULL);
922 
923    // Check for MSAA support
924    if (gles_version == 3)
925      {
926         glGetIntegerv(GL_MAX_SAMPLES, &max_samples);
927         INF("MSAA support for GLES 3 is not implemented yet!");
928         max_samples = 0;
929      }
930 #ifdef GL_GLES
931    else if (EXTENSION_SUPPORT(IMG_multisampled_render_to_texture))
932      {
933         glGetIntegerv(GL_MAX_SAMPLES_IMG, &max_samples);
934      }
935    else if (EXTENSION_SUPPORT(EXT_multisampled_render_to_texture))
936      {
937         glGetIntegerv(GL_MAX_SAMPLES_EXT, &max_samples);
938      }
939    else
940      {
941         const char *exts = (const char *) glGetString(GL_EXTENSIONS);
942 
943         if (exts && strstr(exts, "EXT_multisampled_render_to_texture"))
944           glGetIntegerv(GL_MAX_SAMPLES_EXT, &max_samples);
945         else if (exts && strstr(exts, "IMG_multisampled_render_to_texture"))
946           glGetIntegerv(GL_MAX_SAMPLES_IMG, &max_samples);
947      }
948 #endif
949 
950    if (max_samples >= 2)
951      {
952         evgl_engine->caps.msaa_samples[0] = 2;
953         evgl_engine->caps.msaa_samples[1] = (max_samples >> 1) < 2 ? 2 : (max_samples >> 1);
954         evgl_engine->caps.msaa_samples[2] = max_samples;
955         evgl_engine->caps.msaa_supported  = 1;
956      }
957 
958    // Load Surface Cap
959    if (!_surface_cap_cache_load())
960      {
961         // Check Surface Cap
962         evgl_engine->caps.num_fbo_fmts = _surface_cap_check();
963         _surface_cap_cache_save();
964         DBG("Ran Evas GL Surface Cap and Cached the existing values.");
965      }
966    else
967      {
968         DBG("Loaded cached Evas GL Surface Cap values.");
969      }
970 
971    if (evgl_engine->caps.num_fbo_fmts)
972      {
973         _surface_cap_print(0);
974         DBG("Number of supported surface formats: %d", evgl_engine->caps.num_fbo_fmts);
975         ret = 1;
976      }
977    else
978      {
979         ERR("There are no available surface formats. Error!");
980      }
981 
982    // Destroy internal resources
983    _evgl_tls_resource_destroy(eng_data);
984 
985    return ret;
986 }
987 
988 static int
_context_ext_check(EVGL_Context * ctx)989 _context_ext_check(EVGL_Context *ctx)
990 {
991    if (!ctx)
992       return 0;
993 
994    if (ctx->extension_checked)
995       return 1;
996 
997 #ifdef GL_GLES
998    int fbo_supported = 0;
999    int egl_image_supported = 0;
1000    int texture_image_supported = 0;
1001 
1002    switch (ctx->version)
1003      {
1004       case EVAS_GL_GLES_1_X:
1005          if (EXTENSION_SUPPORT_GLES1(framebuffer_object))
1006            fbo_supported = 1;
1007          break;
1008       case EVAS_GL_GLES_2_X:
1009       case EVAS_GL_GLES_3_X:
1010       default:
1011          fbo_supported = 1;
1012      }
1013 
1014    if (EXTENSION_SUPPORT_EGL(EGL_KHR_image_base))
1015      egl_image_supported = 1;
1016    if (EXTENSION_SUPPORT_EGL(EGL_KHR_gl_texture_2D_image))
1017      texture_image_supported = 1;
1018 
1019    if (egl_image_supported)
1020      {
1021         if (fbo_supported && texture_image_supported)
1022           ctx->fbo_image_supported = 1;
1023         else
1024           ctx->pixmap_image_supported = 1;
1025      }
1026 #endif
1027 
1028    if (ctx->version == EVAS_GL_GLES_3_X)
1029      {
1030         /* HACK, as of 2017/03/08:
1031          * Some NVIDIA drivers pretend to support GLES 3.1 with EGL but in
1032          * fact none of the new functions are available, neither through
1033          * dlsym() nor eglGetProcAddress(). GLX/OpenGL should work though.
1034          * This is a fixup for glGetString(GL_VERSION).
1035          */
1036         if (!gles3_funcs->glVertexBindingDivisor)
1037           ctx->version_minor = 0;
1038         else
1039           ctx->version_minor = 1;
1040      }
1041 
1042    ctx->extension_checked = 1;
1043 
1044    return 1;
1045 }
1046 
1047 
1048 static const char *
_glenum_string_get(GLenum e)1049 _glenum_string_get(GLenum e)
1050 {
1051    switch (e)
1052      {
1053       case 0:
1054          return "0";
1055       case GL_RGB:
1056          return "GL_RGB";
1057       case GL_RGBA:
1058          return "GL_RGBA";
1059 
1060 #ifdef GL_GLES
1061          // Depth
1062       case GL_DEPTH_COMPONENT:
1063          return "GL_DEPTH_COMPONENT";
1064       case GL_DEPTH_COMPONENT16:
1065          return "GL_DEPTH_COMPONENT16";
1066       case GL_DEPTH_COMPONENT24_OES:
1067          return "GL_DEPTH_COMPONENT24_OES";
1068       case GL_DEPTH_COMPONENT32_OES:
1069        return "GL_DEPTH_COMPONENT32_OES";
1070 
1071          // Stencil
1072       case GL_STENCIL_INDEX1_OES:
1073          return "GL_STENCIL_INDEX1_OES";
1074       case GL_STENCIL_INDEX4_OES:
1075          return "GL_STENCIL_INDEX4_OES";
1076       case GL_STENCIL_INDEX8:
1077          return "GL_STENCIL_INDEX8";
1078 
1079          // Depth_Stencil
1080       case GL_DEPTH_STENCIL_OES:
1081          return "GL_DEPTH_STENCIL_OES";
1082       case GL_DEPTH24_STENCIL8_OES:
1083          return "GL_DEPTH24_STENCIL8_OES";
1084 #else
1085          // Depth
1086       case GL_DEPTH_COMPONENT:
1087          return "GL_DEPTH_COMPONENT";
1088       case GL_DEPTH_COMPONENT16:
1089          return "GL_DEPTH_COMPONENT16";
1090       case GL_DEPTH_COMPONENT24:
1091          return "GL_DEPTH_COMPONENT24";
1092       case GL_DEPTH_COMPONENT32:
1093          return "GL_DEPTH_COMPONENT32";
1094 
1095          // Stencil
1096       case GL_STENCIL_INDEX:
1097          return "GL_STENCIL_INDEX";
1098       case GL_STENCIL_INDEX1:
1099          return "GL_STENCIL_INDEX1";
1100       case GL_STENCIL_INDEX4:
1101          return "GL_STENCIL_INDEX4";
1102       case GL_STENCIL_INDEX8:
1103          return "GL_STENCIL_INDEX8";
1104 
1105          // Depth_Stencil
1106       case GL_DEPTH_STENCIL:
1107         return "GL_DEPTH_STENCIL";
1108       case GL_DEPTH24_STENCIL8:
1109          return "GL_DEPTH24_STENCIL8";
1110 #endif
1111       default:
1112          return "ERR";
1113      }
1114 }
1115 
1116 static void
_surface_cap_print(int error)1117 _surface_cap_print(int error)
1118 {
1119    int i = 0;
1120 #define PRINT_LOG(...) \
1121    if (error) \
1122       ERR(__VA_ARGS__); \
1123    else \
1124       DBG(__VA_ARGS__);
1125 
1126    PRINT_LOG("----------------------------------------------------------------------------------------------------------------");
1127    PRINT_LOG("                 Evas GL Supported Surface Format                                                               ");
1128    PRINT_LOG("----------------------------------------------------------------------------------------------------------------");
1129    PRINT_LOG(" Max Surface Width: %d Height: %d", evgl_engine->caps.max_w, evgl_engine->caps.max_h);
1130    PRINT_LOG(" Multisample Support: %d", evgl_engine->caps.msaa_supported);
1131    //if (evgl_engine->caps.msaa_supported)
1132      {
1133         PRINT_LOG("             Low  Samples: %d", evgl_engine->caps.msaa_samples[0]);
1134         PRINT_LOG("             Med  Samples: %d", evgl_engine->caps.msaa_samples[1]);
1135         PRINT_LOG("             High Samples: %d", evgl_engine->caps.msaa_samples[2]);
1136      }
1137    PRINT_LOG("[Index] [Color Format]  [------Depth Bits------]      [----Stencil Bits---]     [---Depth_Stencil---]  [Samples]");
1138 
1139 #define PRINT_SURFACE_CAP(IDX, COLOR, DEPTH, STENCIL, DS, SAMPLE) \
1140      { \
1141         PRINT_LOG("  %3d  %10s    %25s  %25s  %25s  %5d", IDX, _glenum_string_get(COLOR), _glenum_string_get(DEPTH), _glenum_string_get(STENCIL), _glenum_string_get(DS), SAMPLE ); \
1142      }
1143 
1144    for (i = 0; i < evgl_engine->caps.num_fbo_fmts; ++i)
1145      {
1146         EVGL_Surface_Format *fmt = &evgl_engine->caps.fbo_fmts[i];
1147         PRINT_SURFACE_CAP(i, fmt->color_fmt, fmt->depth_fmt, fmt->stencil_fmt, fmt->depth_stencil_fmt, fmt->samples);
1148      }
1149 
1150 #undef PRINT_SURFACE_CAP
1151 #undef PRINT_LOG
1152 }
1153 
1154 static void
_surface_context_list_print()1155 _surface_context_list_print()
1156 {
1157    Eina_List *l;
1158    EVGL_Surface *s;
1159    EVGL_Context *c;
1160    int count = 0;
1161 
1162    // Only print them when the log level is 6
1163    if (_evas_gl_log_level < 6) return;
1164 
1165 #define RESET "\e[m"
1166 #define GREEN "\e[1;32m"
1167 #define YELLOW "\e[1;33m"
1168 #define RED "\e[1;31m"
1169 
1170    LKL(evgl_engine->resource_lock);
1171 
1172    DBG( YELLOW "-----------------------------------------------" RESET);
1173    DBG("Total Number of active Evas GL Surfaces: %d", eina_list_count(evgl_engine->surfaces));
1174 
1175    EINA_LIST_FOREACH(evgl_engine->surfaces, l, s)
1176      {
1177         DBG( YELLOW "\t-----------------------------------------------" RESET);
1178         DBG( RED "\t[Surface %d]" YELLOW " Ptr: %p" RED " Appx Mem: %d Byte", count++, s, (s->buffer_mem[0]+s->buffer_mem[1]+s->buffer_mem[2]+s->buffer_mem[3]));
1179         DBG( GREEN "\t\t Size:" RESET " (%d, %d)",  s->w, s->h);
1180 
1181         if (s->buffer_mem[0])
1182           {
1183              DBG( GREEN "\t\t Color Format:" RESET " %s", _glenum_string_get(s->color_fmt));
1184              DBG( GREEN "\t\t Color Buffer Appx. Mem Usage:" RESET " %d Byte", s->buffer_mem[0]);
1185           }
1186         if (s->buffer_mem[1])
1187           {
1188              DBG( GREEN "\t\t Depth Format:" RESET " %s", _glenum_string_get(s->depth_fmt));
1189              DBG( GREEN "\t\t Depth Buffer Appx. Mem Usage: " RESET "%d Byte", s->buffer_mem[1]);
1190           }
1191         if (s->buffer_mem[2])
1192           {
1193              DBG( GREEN "\t\t Stencil Format:" RESET " %s", _glenum_string_get(s->stencil_fmt));
1194              DBG( GREEN "\t\t Stencil Buffer Appx. Mem Usage:" RESET " %d Byte", s->buffer_mem[2]);
1195           }
1196         if (s->buffer_mem[3])
1197           {
1198              DBG( GREEN "\t\t D-Stencil Format:" RESET " %s", _glenum_string_get(s->depth_stencil_fmt));
1199              DBG( GREEN "\t\t D-Stencil Buffer Appx. Mem Usage:" RESET " %d Byte", s->buffer_mem[3]);
1200           }
1201         if (s->msaa_samples)
1202            DBG( GREEN "\t\t MSAA Samples:" RESET " %d", s->msaa_samples);
1203         if (s->direct_fb_opt)
1204            DBG( GREEN "\t\t Direct Option Enabled" RESET );
1205         DBG( YELLOW "\t-----------------------------------------------" RESET);
1206      }
1207 
1208    count = 0;
1209 
1210    DBG( YELLOW "-----------------------------------------------" RESET);
1211    DBG("Total Number of active Evas GL Contexts: %d", eina_list_count(evgl_engine->contexts));
1212    EINA_LIST_FOREACH(evgl_engine->contexts, l, c)
1213      {
1214         DBG( YELLOW "\t-----------------------------------------------" RESET);
1215         DBG( RED "\t[Context %d]" YELLOW " Ptr: %p", count++, c);
1216      }
1217    DBG( YELLOW "-----------------------------------------------" RESET);
1218 
1219    LKU(evgl_engine->resource_lock);
1220 
1221 #undef RESET
1222 #undef GREEN
1223 #undef YELLOW
1224 #undef RED
1225 }
1226 
1227 //--------------------------------------------------------//
1228 // Start from here.....
1229 //--------------------------------------------------------//
1230 static int
_surface_buffers_fbo_set(EVGL_Surface * sfc,GLuint fbo,Evas_GL_Context_Version version)1231 _surface_buffers_fbo_set(EVGL_Surface *sfc, GLuint fbo, Evas_GL_Context_Version version)
1232 {
1233    int status;
1234 
1235    _framebuffer_bind(fbo, version);
1236 
1237    // Detach any previously attached buffers
1238    _texture_attach_2d(0, GL_COLOR_ATTACHMENT0, 0, 0, version);
1239    _renderbuffer_attach(0, GL_DEPTH_ATTACHMENT, version);
1240    _renderbuffer_attach(0, GL_STENCIL_ATTACHMENT, version);
1241 #ifdef GL_GLES
1242    _texture_attach_2d(0, GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT, 0, version);
1243 #else
1244     _renderbuffer_attach(0, GL_DEPTH_STENCIL_ATTACHMENT, version);
1245 #endif
1246 
1247    // Render Target Texture
1248    if (sfc->color_buf)
1249      _texture_attach_2d(sfc->color_buf, GL_COLOR_ATTACHMENT0, 0, sfc->msaa_samples, version);
1250 
1251    // Depth Stencil RenderBuffer - Attach it to FBO
1252    if (sfc->depth_stencil_buf)
1253      {
1254 #ifdef GL_GLES
1255         if (sfc->depth_stencil_fmt == GL_DEPTH_STENCIL_OES)
1256           _texture_attach_2d(sfc->depth_stencil_buf, GL_DEPTH_ATTACHMENT,
1257                              GL_STENCIL_ATTACHMENT, sfc->msaa_samples, version);
1258         else
1259           {
1260              _renderbuffer_attach(sfc->depth_stencil_buf, GL_DEPTH_ATTACHMENT, version);
1261              _renderbuffer_attach(sfc->depth_stencil_buf, GL_STENCIL_ATTACHMENT, version);
1262           }
1263 #else
1264        _renderbuffer_attach(sfc->depth_stencil_buf, GL_DEPTH_STENCIL_ATTACHMENT, version);
1265 #endif
1266      }
1267 
1268    // Depth RenderBuffer - Attach it to FBO
1269    if (sfc->depth_buf)
1270      _renderbuffer_attach(sfc->depth_buf, GL_DEPTH_ATTACHMENT, version);
1271 
1272    // Stencil RenderBuffer - Attach it to FBO
1273    if (sfc->stencil_buf)
1274      _renderbuffer_attach(sfc->stencil_buf, GL_STENCIL_ATTACHMENT, version);
1275 
1276    // Check FBO for completeness
1277    status = _framebuffer_check(version);
1278    if (status != GL_FRAMEBUFFER_COMPLETE)
1279      {
1280         ERR("FBO not complete. Error Code: %x!", status);
1281         return 0;
1282      }
1283 
1284    return 1;
1285 }
1286 
1287 static int
_surface_buffers_create(EVGL_Surface * sfc)1288 _surface_buffers_create(EVGL_Surface *sfc)
1289 {
1290    // Create buffers
1291    if (sfc->color_fmt)
1292      {
1293         _texture_create(&sfc->color_buf);
1294      }
1295 
1296 
1297    // Depth_stencil buffers or separate buffers
1298    if (sfc->depth_stencil_fmt)
1299      {
1300 #ifdef GL_GLES
1301         if (sfc->depth_stencil_fmt == GL_DEPTH_STENCIL_OES)
1302           _texture_create(&sfc->depth_stencil_buf);
1303         else
1304 #endif
1305           _renderbuffer_create(&sfc->depth_stencil_buf);
1306      }
1307    else
1308      {
1309         if (sfc->depth_fmt)
1310           {
1311              _renderbuffer_create(&sfc->depth_buf);
1312           }
1313         if (sfc->stencil_fmt)
1314           {
1315              _renderbuffer_create(&sfc->stencil_buf);
1316           }
1317      }
1318 
1319    return 1; //ret;
1320 }
1321 
1322 
1323 static int
_surface_buffers_allocate(void * eng_data EINA_UNUSED,EVGL_Surface * sfc,int w,int h,Evas_GL_Context_Version version EINA_UNUSED)1324 _surface_buffers_allocate(void *eng_data EINA_UNUSED, EVGL_Surface *sfc, int w, int h, Evas_GL_Context_Version version EINA_UNUSED/* unused ecept gles */)
1325 {
1326    // Create buffers
1327    if (sfc->color_fmt)
1328      {
1329         _texture_allocate_2d(sfc->color_buf, sfc->color_ifmt, sfc->color_fmt,
1330                              GL_UNSIGNED_BYTE, w, h);
1331         if (sfc->egl_image)
1332           {
1333              _egl_image_destroy(sfc->egl_image);
1334              sfc->egl_image = NULL;
1335           }
1336         if ((sfc->current_ctx) && (sfc->current_ctx->fbo_image_supported) && (w) && (h))
1337           sfc->egl_image = _egl_image_create(sfc->current_ctx, EGL_GL_TEXTURE_2D_KHR, (void *)(uintptr_t)sfc->color_buf);
1338 
1339         sfc->buffer_mem[0] = w * h * 4;
1340      }
1341 
1342    // Depth_stencil buffers or separate buffers
1343    if (sfc->depth_stencil_fmt)
1344      {
1345 #ifdef GL_GLES
1346         if (sfc->depth_stencil_fmt == GL_DEPTH_STENCIL_OES)
1347           {
1348              if (version == EVAS_GL_GLES_3_X)
1349                {
1350                   _texture_allocate_2d(sfc->depth_stencil_buf, GL_DEPTH24_STENCIL8_OES,
1351                      sfc->depth_stencil_fmt, GL_UNSIGNED_INT_24_8_OES,
1352                      w, h);
1353                }
1354              else
1355                {
1356                   _texture_allocate_2d(sfc->depth_stencil_buf, sfc->depth_stencil_fmt,
1357                      sfc->depth_stencil_fmt, GL_UNSIGNED_INT_24_8_OES,
1358                      w, h);
1359                }
1360           }
1361         else
1362 #endif
1363           {
1364              _renderbuffer_allocate(sfc->depth_stencil_buf,
1365                                     sfc->depth_stencil_fmt, w, h,
1366                                     sfc->msaa_samples);
1367           }
1368         sfc->buffer_mem[3] = w * h * 4;
1369      }
1370    else
1371      {
1372         if (sfc->depth_fmt)
1373           {
1374              _renderbuffer_allocate(sfc->depth_buf, sfc->depth_fmt, w, h,
1375                                     sfc->msaa_samples);
1376              sfc->buffer_mem[1] = w * h * 3; // Assume it's 24 bits
1377           }
1378         if (sfc->stencil_fmt)
1379           {
1380              _renderbuffer_allocate(sfc->stencil_buf, sfc->stencil_fmt, w,
1381                                     h, sfc->msaa_samples);
1382              sfc->buffer_mem[2] = w * h; // Assume it's 8 bits
1383           }
1384      }
1385 
1386    return 1; //ret;
1387 }
1388 
1389 static int
_surface_buffers_destroy(EVGL_Surface * sfc)1390 _surface_buffers_destroy(EVGL_Surface *sfc)
1391 {
1392    if (sfc->egl_image)
1393      {
1394         _egl_image_destroy(sfc->egl_image);
1395         sfc->egl_image = NULL;
1396      }
1397    if (sfc->color_buf)
1398       _texture_destroy(&sfc->color_buf);
1399    if (sfc->depth_buf)
1400       _renderbuffer_destroy(&sfc->depth_buf);
1401    if (sfc->stencil_buf)
1402       _renderbuffer_destroy(&sfc->stencil_buf);
1403    if (sfc->depth_stencil_buf)
1404      {
1405 #ifdef GL_GLES
1406         if (sfc->depth_stencil_fmt == GL_DEPTH_STENCIL_OES)
1407           _texture_destroy(&sfc->depth_stencil_buf);
1408         else
1409 #endif
1410           _renderbuffer_destroy(&sfc->depth_stencil_buf);
1411      }
1412 
1413    return 1;
1414 }
1415 
1416 static int
_internal_config_set(void * eng_data,EVGL_Surface * sfc,Evas_GL_Config * cfg)1417 _internal_config_set(void *eng_data, EVGL_Surface *sfc, Evas_GL_Config *cfg)
1418 {
1419    int i = 0, cfg_index = -1;
1420    int color_bit = 0, depth_bit = 0, stencil_bit = 0, msaa_samples = 0;
1421    int depth_size = 0;
1422    int native_win_depth = 0, native_win_stencil = 0, native_win_msaa = 0;
1423 
1424    // Check if engine is valid
1425    if (!evgl_engine)
1426      {
1427         ERR("Invalid EVGL Engine!");
1428         return 0;
1429      }
1430 
1431    // Convert Config Format to bitmask friendly format
1432    color_bit = (1 << cfg->color_format);
1433    if (cfg->depth_bits)
1434      {
1435         depth_bit = (1 << (cfg->depth_bits-1));
1436         depth_size = 8 * cfg->depth_bits;
1437      }
1438    if (cfg->stencil_bits) stencil_bit = (1 << (cfg->stencil_bits-1));
1439    if (cfg->multisample_bits)
1440       msaa_samples = evgl_engine->caps.msaa_samples[cfg->multisample_bits-1];
1441 
1442 try_again:
1443    // Run through all the available formats and choose the first match
1444    for (i = 0; i < evgl_engine->caps.num_fbo_fmts; ++i)
1445      {
1446         // Check if the MSAA is supported.  Fallback if not.
1447         if ((msaa_samples) && (evgl_engine->caps.msaa_supported))
1448           {
1449              if (msaa_samples > evgl_engine->caps.fbo_fmts[i].samples)
1450                   continue;
1451           }
1452 
1453         if (color_bit & evgl_engine->caps.fbo_fmts[i].color_bit)
1454           {
1455              if (depth_bit)
1456                {
1457                   if (!(depth_bit & evgl_engine->caps.fbo_fmts[i].depth_bit))
1458                      continue;
1459                }
1460 
1461              if (stencil_bit)
1462                {
1463                   if (!(stencil_bit & evgl_engine->caps.fbo_fmts[i].stencil_bit))
1464                      continue;
1465                }
1466 
1467              // Set the surface format
1468              sfc->color_ifmt        = evgl_engine->caps.fbo_fmts[i].color_ifmt;
1469              sfc->color_fmt         = evgl_engine->caps.fbo_fmts[i].color_fmt;
1470              sfc->depth_fmt         = evgl_engine->caps.fbo_fmts[i].depth_fmt;
1471              sfc->stencil_fmt       = evgl_engine->caps.fbo_fmts[i].stencil_fmt;
1472              sfc->depth_stencil_fmt = evgl_engine->caps.fbo_fmts[i].depth_stencil_fmt;
1473              sfc->msaa_samples      = evgl_engine->caps.fbo_fmts[i].samples;
1474 
1475              // Direct Rendering Option
1476              if (cfg->options_bits & EVAS_GL_OPTIONS_DIRECT)
1477                {
1478                   Eina_Bool support_win_cfg = EINA_FALSE;
1479 
1480                   if (evgl_engine->funcs->native_win_surface_config_get)
1481                     evgl_engine->funcs->native_win_surface_config_get(eng_data, &native_win_depth, &native_win_stencil, &native_win_msaa);
1482                   if ((native_win_depth >= depth_size)
1483                       && (native_win_stencil >= stencil_bit)
1484                       && (native_win_msaa >= msaa_samples))
1485                     {
1486                        DBG("Win cfg can support the Req Evas GL's config successfully");
1487                        support_win_cfg = EINA_TRUE;
1488                     }
1489                   else
1490                     {
1491                        ERR("Win config can't support Evas GL direct rendering, "
1492                            "win: [depth %d, stencil %d, msaa %d] "
1493                            "want: [depth %d, stencil %d, msaa %d]. %s",
1494                            native_win_depth, native_win_stencil, native_win_msaa,
1495                            depth_size, stencil_bit, msaa_samples,
1496                            sfc->direct_override ?
1497                               "Forcing direct rendering anyway." :
1498                               "Falling back to indirect rendering (FBO).");
1499                        support_win_cfg = EINA_FALSE;
1500                     }
1501 
1502                   if (sfc->direct_override || support_win_cfg)
1503                     {
1504                        sfc->direct_fb_opt = EINA_TRUE;
1505 
1506                        // Extra flags for direct rendering
1507                        sfc->client_side_rotation = !!(cfg->options_bits & EVAS_GL_OPTIONS_CLIENT_SIDE_ROTATION);
1508                        sfc->alpha = (cfg->color_format == EVAS_GL_RGBA_8888);
1509                     }
1510                   else
1511                     {
1512                        const char *s1[] = { "", ":depth8", ":depth16", ":depth24", ":depth32" };
1513                        const char *s2[] = { "", ":stencil1", ":stencil2", ":stencil4", ":stencil8", ":stencil16" };
1514                        const char *s3[] = { "", ":msaa_low", ":msaa_mid", ":msaa_high" };
1515                        INF("Can not enable direct rendering with depth %d, stencil %d "
1516                            "and MSAA %d. When using Elementary GLView, try to call "
1517                            "elm_config_accel_preference_set(\"opengl%s%s%s\") before "
1518                            "creating any window.",
1519                            depth_size, stencil_bit, msaa_samples,
1520                            s1[cfg->depth_bits], s2[cfg->stencil_bits], s3[cfg->multisample_bits]);
1521                     }
1522 
1523                   // When direct rendering is enabled, FBO configuration should match
1524                   // window surface configuration as FBO will be used in fallback cases.
1525                   // So we search again for the formats that match window surface's.
1526                   if (sfc->direct_fb_opt &&
1527                       ((native_win_depth != depth_size) ||
1528                        (native_win_stencil != stencil_bit) ||
1529                        (native_win_msaa != msaa_samples)))
1530                     {
1531                        if (native_win_depth < 8) depth_bit = 0;
1532                        else depth_bit = (1 << ((native_win_depth / 8) - 1));
1533                        depth_size = native_win_depth;
1534                        stencil_bit = native_win_stencil;
1535                        msaa_samples = native_win_msaa;
1536                        goto try_again;
1537                     }
1538                }
1539 
1540              cfg_index = i;
1541              break;
1542           }
1543      }
1544 
1545    if (cfg_index < 0)
1546      {
1547         ERR("Unable to find a matching config format (depth:%d, stencil:%d, msaa:%d)",
1548             depth_size, stencil_bit, msaa_samples);
1549         if ((stencil_bit > 8) || (depth_size > 24))
1550           {
1551              INF("Please note that Evas GL might not support 32-bit depth or "
1552                  "16-bit stencil buffers, so depth24, stencil8 are the maximum "
1553                  "recommended values.");
1554              if (depth_size > 24)
1555                {
1556                   depth_bit = 4; // see DEPTH_BIT_24
1557                   depth_size = 24;
1558                }
1559              if (stencil_bit > 8) stencil_bit = 8; // see STENCIL_BIT_8
1560              DBG("Fallback to depth:%d, stencil:%d", depth_size, stencil_bit);
1561              goto try_again;
1562           }
1563         else if (msaa_samples > 0)
1564           {
1565              msaa_samples /= 2;
1566              if (msaa_samples == 1) msaa_samples = 0;
1567              DBG("Fallback to msaa:%d", msaa_samples);
1568              goto try_again;
1569           }
1570         return 0;
1571      }
1572    else
1573      {
1574         DBG("-------------Evas GL Surface Config---------------");
1575         DBG("Selected Config Index: %d", cfg_index);
1576         DBG("  Color Format     : %s", _glenum_string_get(sfc->color_fmt));
1577         DBG("  Depth Format     : %s", _glenum_string_get(sfc->depth_fmt));
1578         DBG("  Stencil Format   : %s", _glenum_string_get(sfc->stencil_fmt));
1579         DBG("  D-Stencil Format : %s", _glenum_string_get(sfc->depth_stencil_fmt));
1580         DBG("  MSAA Samples     : %d", sfc->msaa_samples);
1581         DBG("  Direct Option    : %d%s", sfc->direct_fb_opt, sfc->direct_override ? " (override)" : "");
1582         DBG("  Client-side Rot. : %d", sfc->client_side_rotation);
1583         DBG("--------------------------------------------------");
1584         sfc->cfg_index = cfg_index;
1585         return 1;
1586      }
1587 }
1588 
1589 static int
_evgl_direct_renderable(EVGL_Resource * rsc,EVGL_Surface * sfc)1590 _evgl_direct_renderable(EVGL_Resource *rsc, EVGL_Surface *sfc)
1591 {
1592    if (evgl_engine->direct_force_off) return 0;
1593    if (rsc->id != evgl_engine->main_tid) return 0;
1594    if (!sfc->direct_fb_opt) return 0;
1595    if (!rsc->direct.enabled) return 0;
1596 
1597    return 1;
1598 }
1599 
1600 //---------------------------------------------------------------//
1601 // Functions used by Evas GL module
1602 //---------------------------------------------------------------//
1603 EVGL_Resource *
_evgl_tls_resource_get(void)1604 _evgl_tls_resource_get(void)
1605 {
1606    EVGL_Resource *rsc = NULL;
1607 
1608    // Check if engine is valid
1609    if (!evgl_engine)
1610      {
1611         ERR("Invalid EVGL Engine!");
1612         return NULL;
1613      }
1614 
1615    if (evgl_engine->resource_key)
1616      rsc = eina_tls_get(evgl_engine->resource_key);
1617 
1618    return rsc;
1619 }
1620 
1621 static void
_evgl_tls_resource_destroy_cb(void * data)1622 _evgl_tls_resource_destroy_cb(void *data)
1623 {
1624    EVGL_Resource *rsc = data;
1625 
1626    LKL(evgl_engine->resource_lock);
1627    evgl_engine->resource_list = eina_list_remove(evgl_engine->resource_list, rsc);
1628    LKU(evgl_engine->resource_lock);
1629 
1630    _internal_resources_destroy(rsc->current_eng, rsc);
1631 }
1632 
1633 EVGL_Resource *
_evgl_tls_resource_create(void * eng_data)1634 _evgl_tls_resource_create(void *eng_data)
1635 {
1636    EVGL_Resource *rsc;
1637 
1638    // Check if engine is valid
1639    if (!evgl_engine)
1640      {
1641         ERR("Invalid EVGL Engine!");
1642         return NULL;
1643      }
1644 
1645    // Initialize Resource TLS
1646    if (!evgl_engine->resource_key && eina_tls_cb_new(&evgl_engine->resource_key, _evgl_tls_resource_destroy_cb) == EINA_FALSE)
1647      {
1648         ERR("Error creating tls key");
1649         return NULL;
1650      }
1651    DBG("TLS KEY created: %d", evgl_engine->resource_key);
1652 
1653    // Create internal resources if it hasn't been created already
1654    if (!(rsc = _internal_resources_create(eng_data)))
1655      {
1656         ERR("Error creating internal resources.");
1657         return NULL;
1658      }
1659 
1660    // Set the resource in TLS
1661    if (eina_tls_set(evgl_engine->resource_key, (void*)rsc) == EINA_TRUE)
1662      {
1663         // Add to the resource resource list for cleanup
1664         LKL(evgl_engine->resource_lock);
1665         evgl_engine->resource_list = eina_list_prepend(evgl_engine->resource_list, rsc);
1666         LKU(evgl_engine->resource_lock);
1667         return rsc;
1668      }
1669    else
1670      {
1671         ERR("Failed setting TLS Resource");
1672         _internal_resources_destroy(eng_data, rsc);
1673         return NULL;
1674      }
1675 }
1676 
1677 void
_evgl_tls_resource_destroy(void * eng_data)1678 _evgl_tls_resource_destroy(void *eng_data)
1679 {
1680    Eina_List *l;
1681    EVGL_Resource *rsc;
1682    EVGL_Surface *sfc;
1683    EVGL_Context *ctx;
1684 
1685    // Check if engine is valid
1686    if (!evgl_engine)
1687      {
1688         ERR("Invalid EVGL Engine!");
1689         return;
1690      }
1691 
1692    EINA_LIST_FOREACH(evgl_engine->surfaces, l, sfc)
1693      {
1694         evgl_surface_destroy(eng_data, sfc);
1695      }
1696    EINA_LIST_FOREACH(evgl_engine->contexts, l, ctx)
1697      {
1698         evgl_context_destroy(eng_data, ctx);
1699      }
1700 
1701    LKL(evgl_engine->resource_lock);
1702 
1703    eina_list_free(evgl_engine->surfaces);
1704    evgl_engine->surfaces = NULL;
1705 
1706    eina_list_free(evgl_engine->contexts);
1707    evgl_engine->contexts = NULL;
1708 
1709    EINA_LIST_FOREACH(evgl_engine->resource_list, l, rsc)
1710      {
1711         _internal_resources_destroy(eng_data, rsc);
1712      }
1713    eina_list_free(evgl_engine->resource_list);
1714    evgl_engine->resource_list = NULL;
1715 
1716    LKU(evgl_engine->resource_lock);
1717 
1718    // Destroy TLS
1719    if (evgl_engine->resource_key)
1720       eina_tls_free(evgl_engine->resource_key);
1721    evgl_engine->resource_key = 0;
1722 }
1723 
1724 EAPI void * /* EVGL_Context */
evas_gl_common_current_context_get(void)1725 evas_gl_common_current_context_get(void)
1726 {
1727    EVGL_Resource *rsc;
1728 
1729    if (!(rsc = _evgl_tls_resource_get()))
1730      {
1731         ERR("No current context set.");
1732         return NULL;
1733      }
1734    else
1735      return rsc->current_ctx;
1736 }
1737 
1738 EAPI void *
evgl_current_native_context_get(EVGL_Context * ctx)1739 evgl_current_native_context_get(EVGL_Context *ctx)
1740 {
1741    EVGLNative_Context context;
1742 
1743    if (!ctx)
1744      return NULL;
1745 
1746    context = ctx->context;
1747 
1748    if ((ctx->pixmap_image_supported) && evgl_direct_rendered())
1749      context = ctx->indirect_context;
1750 
1751    return context;
1752 }
1753 
1754 int
_evgl_not_in_pixel_get(void)1755 _evgl_not_in_pixel_get(void)
1756 {
1757    EVGL_Resource *rsc;
1758    EVGL_Context *ctx;
1759 
1760    if (!(rsc=_evgl_tls_resource_get()))
1761      return 1;
1762 
1763    if (rsc->id != evgl_engine->main_tid)
1764      return 0;
1765 
1766    ctx = rsc->current_ctx;
1767    if (!ctx || !ctx->current_sfc)
1768      return 0;
1769 
1770    // if indirect rendering, we don't care. eg. elm_glview's init cb
1771    if (!ctx->current_sfc->direct_fb_opt)
1772      return 0;
1773 
1774    return !rsc->direct.in_get_pixels;
1775 }
1776 
1777 int
_evgl_direct_enabled(void)1778 _evgl_direct_enabled(void)
1779 {
1780    EVGL_Resource *rsc;
1781    EVGL_Surface  *sfc;
1782 
1783    if (!(rsc=_evgl_tls_resource_get())) return 0;
1784    if (!(rsc->current_ctx)) return 0;
1785    if (!(sfc=rsc->current_ctx->current_sfc)) return 0;
1786 
1787    return _evgl_direct_renderable(rsc, sfc);
1788 }
1789 
1790 EAPI void
evas_gl_common_error_set(int error_enum)1791 evas_gl_common_error_set(int error_enum)
1792 {
1793    EVGL_Resource *rsc;
1794 
1795    if (!(rsc=_evgl_tls_resource_get()))
1796      {
1797         WRN("evgl: Unable to set error!");
1798         return;
1799      }
1800 
1801    rsc->error_state = error_enum;
1802 }
1803 
1804 EAPI int
evas_gl_common_error_get(void)1805 evas_gl_common_error_get(void)
1806 {
1807    EVGL_Resource *rsc;
1808 
1809    if (!(rsc=_evgl_tls_resource_get()))
1810      {
1811         WRN("evgl: Unable to get error!");
1812         return EVAS_GL_NOT_INITIALIZED;
1813      }
1814 
1815    return rsc->error_state;
1816 }
1817 
1818 EVGLNative_Context
_evgl_native_context_get(Evas_GL_Context * ctx)1819 _evgl_native_context_get(Evas_GL_Context *ctx)
1820 {
1821    EVGL_Context *evglctx;
1822 
1823    if (!glsym_evas_gl_native_context_get)
1824      {
1825         ERR("Engine can't get a pointer to the native context");
1826         return NULL;
1827      }
1828 
1829    evglctx = glsym_evas_gl_native_context_get(ctx);
1830    if (!evglctx) return NULL;
1831    return evgl_current_native_context_get(evglctx);
1832 }
1833 
1834 void *
_evgl_engine_data_get(Evas_GL * evasgl)1835 _evgl_engine_data_get(Evas_GL *evasgl)
1836 {
1837    if (!glsym_evas_gl_engine_data_get)
1838      {
1839         ERR("Engine can't get a pointer to the native display");
1840         return NULL;
1841      }
1842 
1843    return glsym_evas_gl_engine_data_get(evasgl);
1844 }
1845 
1846 //---------------------------------------------------------------//
1847 // Exported functions for evas_engine to use
1848 
1849 // Initialize engine
1850 //    - Allocate the engine struct
1851 //    - Assign engine funcs form evas_engine
1852 //    - Create internal resources: internal context, surface for resource creation
1853 //    - Initialize extensions
1854 //    - Check surface capability
1855 //
1856 // This code should be called during eng_setup() in evas_engine
1857 EVGL_Engine *
evgl_engine_init(void * eng_data,const EVGL_Interface * efunc)1858 evgl_engine_init(void *eng_data, const EVGL_Interface *efunc)
1859 {
1860    int direct_off = 0, direct_soff = 0, debug_mode = 0;
1861    char *s = NULL;
1862 
1863    if (evgl_engine) return evgl_engine;
1864 
1865    // Initialize Log Domain
1866    if (_evas_gl_log_dom < 0)
1867       _evas_gl_log_dom = eina_log_domain_register("EvasGL", EVAS_DEFAULT_LOG_COLOR);
1868    if (_evas_gl_log_dom < 0)
1869      {
1870         EINA_LOG_ERR("Can not create a module log domain.");
1871         return NULL;
1872      }
1873 
1874    // Store the Log Level
1875    _evas_gl_log_level = eina_log_domain_level_get("EvasGL");
1876 
1877    // Check the validity of the efunc
1878    if ((!efunc) ||
1879        (!efunc->surface_create) ||
1880        (!efunc->context_create) ||
1881        (!efunc->make_current))
1882      {
1883         ERR("Invalid Engine Functions for Evas GL Engine.");
1884         return NULL;
1885      }
1886 
1887    // Allocate engine
1888    evgl_engine = calloc(1, sizeof(EVGL_Engine));
1889    if (!evgl_engine)
1890      {
1891         ERR("Error allocating EVGL Engine. GL initialization failed.");
1892         goto error;
1893      }
1894 
1895    LKI(evgl_engine->resource_lock);
1896 
1897    // Assign functions
1898    evgl_engine->funcs = efunc;
1899    evgl_engine->safe_extensions = eina_hash_string_small_new(NULL);
1900 
1901    // Main Thread ID
1902    evgl_engine->main_tid = eina_thread_self();
1903 
1904    // Surface Caps
1905    if (!_surface_cap_init(eng_data))
1906      {
1907         ERR("Error initializing surface cap");
1908         goto error;
1909      }
1910 
1911    // NOTE: Should we finally remove these variables?
1912    // Check for Direct rendering override env var.
1913    if ((s = getenv("EVAS_GL_DIRECT_OVERRIDE")))
1914      {
1915         WRN("EVAS_GL_DIRECT_OVERRIDE is set to '%s' for the whole application. "
1916             "This should never be done except for debugging purposes.", s);
1917         if (atoi(s) == 1)
1918           evgl_engine->direct_override = 1;
1919      }
1920 
1921    // Check if Direct Rendering Memory Optimzation flag is on
1922    // Creates resources on demand when it fallsback to fbo rendering
1923    if ((s = getenv("EVAS_GL_DIRECT_MEM_OPT")))
1924      {
1925         WRN("EVAS_GL_DIRECT_MEM_OPT is set to '%s' for the whole application. "
1926             "This should never be done except for debugging purposes.", s);
1927         if (atoi(s) == 1)
1928           evgl_engine->direct_mem_opt = 1;
1929      }
1930 
1931    // Check if Direct Rendering Override Force Off flag is on
1932    s = getenv("EVAS_GL_DIRECT_OVERRIDE_FORCE_OFF");
1933    if (s) direct_off = atoi(s);
1934    if (direct_off == 1)
1935       evgl_engine->direct_force_off = 1;
1936 
1937    // Check if Direct Rendering Override Force Off flag is on
1938    s = getenv("EVAS_GL_DIRECT_SCISSOR_OFF");
1939    if (s) direct_soff = atoi(s);
1940    if (direct_soff == 1)
1941       evgl_engine->direct_scissor_off = 1;
1942 
1943    // Check if API Debug mode is on
1944    s = getenv("EVAS_GL_API_DEBUG");
1945    if (s) debug_mode = atoi(s);
1946    if (debug_mode == 1)
1947       evgl_engine->api_debug_mode = 1;
1948 
1949    return evgl_engine;
1950 
1951 error:
1952    ERR("Failed to initialize EvasGL!");
1953    if (evgl_engine)
1954      {
1955         eina_hash_free(evgl_engine->safe_extensions);
1956         if (evgl_engine->resource_key)
1957           eina_tls_free(evgl_engine->resource_key);
1958         LKD(evgl_engine->resource_lock);
1959         free(evgl_engine);
1960      }
1961    evgl_engine = NULL;
1962    return NULL;
1963 }
1964 
1965 // Terminate engine and all the resources
1966 //    - destroy all internal resources
1967 //    - free allocated engine struct
1968 void
evgl_engine_shutdown(void * eng_data)1969 evgl_engine_shutdown(void *eng_data)
1970 {
1971    // Check if engine is valid
1972    if (!evgl_engine)
1973      {
1974         EINA_LOG_INFO("EvasGL Engine is not initialized.");
1975         return;
1976      }
1977 
1978    if (evgl_engine->safe_extensions)
1979      eina_hash_free(evgl_engine->safe_extensions);
1980    evgl_engine->safe_extensions = NULL;
1981 
1982    if (gles1_funcs) free(gles1_funcs);
1983    if (gles2_funcs) free(gles2_funcs);
1984    if (gles3_funcs) free(gles3_funcs);
1985    gles1_funcs = NULL;
1986    gles2_funcs = NULL;
1987    gles3_funcs = NULL;
1988 
1989    // Destroy internal resources
1990    _evgl_tls_resource_destroy(eng_data);
1991 
1992    LKD(evgl_engine->resource_lock);
1993 
1994    // Log
1995    eina_log_domain_unregister(_evas_gl_log_dom);
1996    _evas_gl_log_dom = -1;
1997 
1998    // Free engine
1999    free(evgl_engine);
2000    evgl_engine = NULL;
2001 }
2002 
2003 void *
evgl_surface_create(void * eng_data,Evas_GL_Config * cfg,int w,int h)2004 evgl_surface_create(void *eng_data, Evas_GL_Config *cfg, int w, int h)
2005 {
2006    EVGL_Surface *sfc = NULL;
2007    Eina_Bool dbg;
2008 
2009    // Check if engine is valid
2010    if (!evgl_engine)
2011      {
2012         ERR("Invalid EVGL Engine!");
2013         evas_gl_common_error_set(EVAS_GL_BAD_ACCESS);
2014         return NULL;
2015      }
2016    dbg = evgl_engine->api_debug_mode;
2017 
2018    if (!cfg)
2019      {
2020         ERR("Invalid Config!");
2021         evas_gl_common_error_set(EVAS_GL_BAD_CONFIG);
2022         return NULL;
2023      }
2024 
2025    // Check the size of the surface
2026    if ((w > evgl_engine->caps.max_w) || (h > evgl_engine->caps.max_h))
2027      {
2028         ERR("Requested surface size [%d, %d] is greater than max supported size [%d, %d]",
2029              w, h, evgl_engine->caps.max_w, evgl_engine->caps.max_h);
2030         evas_gl_common_error_set(EVAS_GL_BAD_PARAMETER);
2031         return NULL;
2032      }
2033 
2034    // Allocate surface structure
2035    sfc = calloc(1, sizeof(EVGL_Surface));
2036    if (!sfc)
2037      {
2038         ERR("Surface allocation failed.");
2039         evas_gl_common_error_set(EVAS_GL_BAD_ALLOC);
2040         goto error;
2041      }
2042 
2043    // Set surface info
2044    sfc->w = w;
2045    sfc->h = h;
2046 
2047    // Extra options for DR
2048    if (cfg->options_bits & EVAS_GL_OPTIONS_DIRECT_MEMORY_OPTIMIZE)
2049      {
2050         DBG("Setting DIRECT_MEMORY_OPTIMIZE bit");
2051         sfc->direct_mem_opt = EINA_TRUE;
2052      }
2053    else if (evgl_engine->direct_mem_opt == 1)
2054      sfc->direct_mem_opt = EINA_TRUE;
2055 
2056    if (cfg->options_bits & EVAS_GL_OPTIONS_DIRECT_OVERRIDE)
2057      {
2058         DBG("Setting DIRECT_OVERRIDE bit");
2059         sfc->direct_override = EINA_TRUE;
2060      }
2061    else if (evgl_engine->direct_override == 1)
2062      sfc->direct_override = EINA_TRUE;
2063 
2064    // Set the internal config value
2065    if (!_internal_config_set(eng_data, sfc, cfg))
2066      {
2067         ERR("Unsupported Format!");
2068         evas_gl_common_error_set(EVAS_GL_BAD_CONFIG);
2069         goto error;
2070      }
2071    sfc->cfg = cfg;
2072 
2073    // Keep track of all the created surfaces
2074    LKL(evgl_engine->resource_lock);
2075    evgl_engine->surfaces = eina_list_prepend(evgl_engine->surfaces, sfc);
2076    LKU(evgl_engine->resource_lock);
2077 
2078    if (dbg) DBG("Created surface sfc %p (eng %p)", sfc, eng_data);
2079 
2080    _surface_context_list_print();
2081 
2082    return sfc;
2083 
2084 error:
2085    if (sfc) free(sfc);
2086    return NULL;
2087 }
2088 
2089 void *
evgl_pbuffer_surface_create(void * eng_data,Evas_GL_Config * cfg,int w,int h,const int * attrib_list)2090 evgl_pbuffer_surface_create(void *eng_data, Evas_GL_Config *cfg,
2091                             int w, int h, const int *attrib_list)
2092 {
2093    EVGL_Surface *sfc = NULL;
2094    void *pbuffer;
2095    Eina_Bool dbg;
2096 
2097    // Check if engine is valid
2098    if (!evgl_engine)
2099      {
2100         ERR("Invalid EVGL Engine!");
2101         evas_gl_common_error_set(EVAS_GL_BAD_ACCESS);
2102         return NULL;
2103      }
2104    dbg = evgl_engine->api_debug_mode;
2105 
2106    if (!cfg)
2107      {
2108         ERR("Invalid Config!");
2109         evas_gl_common_error_set(EVAS_GL_BAD_CONFIG);
2110         return NULL;
2111      }
2112 
2113    if (!evgl_engine->funcs->pbuffer_surface_create)
2114      {
2115         ERR("Engine can not create PBuffers");
2116         evas_gl_common_error_set(EVAS_GL_NOT_INITIALIZED);
2117         return NULL;
2118      }
2119 
2120    // Allocate surface structure
2121    sfc = calloc(1, sizeof(EVGL_Surface));
2122    if (!sfc)
2123      {
2124         ERR("Surface allocation failed.");
2125         evas_gl_common_error_set(EVAS_GL_BAD_ALLOC);
2126         goto error;
2127      }
2128 
2129    sfc->w = w;
2130    sfc->h = h;
2131    sfc->pbuffer.color_fmt = cfg->color_format;
2132    sfc->pbuffer.is_pbuffer = EINA_TRUE;
2133 
2134    // If the surface is defined as RGB or RGBA, then create an FBO
2135    if (sfc->pbuffer.color_fmt == EVAS_GL_NO_FBO)
2136       sfc->buffers_skip_allocate = 1;
2137 
2138    if (!sfc->buffers_skip_allocate)
2139      {
2140         // Set the internal config value
2141         if (!_internal_config_set(eng_data, sfc, cfg))
2142           {
2143              ERR("Unsupported Format!");
2144              evas_gl_common_error_set(EVAS_GL_BAD_CONFIG);
2145              goto error;
2146           }
2147      }
2148    sfc->cfg = cfg;
2149 
2150    pbuffer = evgl_engine->funcs->pbuffer_surface_create
2151      (eng_data, sfc, attrib_list);
2152 
2153    if (!pbuffer)
2154      {
2155         ERR("Engine failed to create a PBuffer");
2156         goto error;
2157      }
2158 
2159    sfc->pbuffer.native_surface = pbuffer;
2160 
2161    // Keep track of all the created surfaces
2162    LKL(evgl_engine->resource_lock);
2163    evgl_engine->surfaces = eina_list_prepend(evgl_engine->surfaces, sfc);
2164    LKU(evgl_engine->resource_lock);
2165 
2166    if (dbg) DBG("Created PBuffer surface sfc %p:%p (eng %p)", sfc, pbuffer, eng_data);
2167 
2168    return sfc;
2169 
2170 error:
2171    free(sfc);
2172    return NULL;
2173 }
2174 
2175 int
evgl_surface_destroy(void * eng_data,EVGL_Surface * sfc)2176 evgl_surface_destroy(void *eng_data, EVGL_Surface *sfc)
2177 {
2178    EVGL_Resource *rsc;
2179    Eina_List *l;
2180    EVGL_Context *ctx;
2181    Eina_Bool dbg;
2182 
2183    // Check input parameter
2184    if ((!evgl_engine) || (!sfc))
2185      {
2186         ERR("Invalid input data.  Engine: %p  Surface:%p", evgl_engine, sfc);
2187         return 0;
2188      }
2189 
2190    if ((dbg = evgl_engine->api_debug_mode))
2191      DBG("Destroying surface sfc %p (eng %p)", sfc, eng_data);
2192 
2193    // Retrieve the resource object
2194    rsc = _evgl_tls_resource_get();
2195    if (rsc && rsc->current_ctx)
2196      {
2197         // Make current to current context to destroy surface buffers
2198         if (!_internal_resource_make_current(eng_data, sfc, rsc->current_ctx))
2199           {
2200              ERR("Error doing an internal resource make current");
2201              return 0;
2202           }
2203 
2204         // Destroy created buffers
2205         if (!_surface_buffers_destroy(sfc))
2206           {
2207              ERR("Error deleting surface resources.");
2208              return 0;
2209           }
2210 
2211         if (rsc->current_ctx->current_sfc == sfc)
2212           {
2213              if (evgl_engine->api_debug_mode)
2214                {
2215                   ERR("The surface is still current before it's being destroyed.");
2216                   ERR("Doing make_current(NULL, NULL)");
2217                }
2218              else
2219                {
2220                   WRN("The surface is still current before it's being destroyed.");
2221                   WRN("Doing make_current(NULL, NULL)");
2222                }
2223              evgl_make_current(eng_data, NULL, NULL);
2224           }
2225      }
2226 
2227    // Destroy indirect surface
2228    if (sfc->indirect)
2229      {
2230         int ret;
2231         if (dbg) DBG("sfc %p is used for indirect rendering", sfc);
2232 
2233         if (!evgl_engine->funcs->indirect_surface_destroy)
2234           {
2235              ERR("Error destroying indirect surface");
2236              return 0;
2237           }
2238 
2239         DBG("Destroying special surface used for indirect rendering");
2240         ret = evgl_engine->funcs->indirect_surface_destroy(eng_data, sfc);
2241 
2242         if (!ret)
2243           {
2244              ERR("Engine failed to destroy indirect surface.");
2245              return ret;
2246           }
2247      }
2248 
2249    // Destroy PBuffer surface
2250    if (sfc->pbuffer.native_surface)
2251      {
2252         int ret;
2253         if (dbg) DBG("Surface sfc %p is a pbuffer: %p", sfc, sfc->pbuffer.native_surface);
2254 
2255         if (!evgl_engine->funcs->pbuffer_surface_destroy)
2256           {
2257              ERR("Error destroying PBuffer surface");
2258              return 0;
2259           }
2260 
2261         DBG("Destroying PBuffer surface");
2262         ret = evgl_engine->funcs->pbuffer_surface_destroy(eng_data, sfc->pbuffer.native_surface);
2263 
2264         if (!ret)
2265           {
2266              ERR("Engine failed to destroy the PBuffer.");
2267              return ret;
2268           }
2269      }
2270 
2271    if (dbg) DBG("Calling make_current(NULL, NULL)");
2272    if (!evgl_engine->funcs->make_current(eng_data, NULL, NULL, 0))
2273      {
2274         ERR("Error doing make_current(NULL, NULL).");
2275         return 0;
2276      }
2277 
2278    // Remove it from the list
2279    LKL(evgl_engine->resource_lock);
2280    evgl_engine->surfaces = eina_list_remove(evgl_engine->surfaces, sfc);
2281    LKU(evgl_engine->resource_lock);
2282 
2283    EINA_LIST_FOREACH(evgl_engine->contexts, l, ctx)
2284      {
2285         if (ctx->current_sfc == sfc)
2286           ctx->current_sfc = NULL;
2287      }
2288 
2289    free(sfc);
2290 
2291    _surface_context_list_print();
2292 
2293    return 1;
2294 
2295 }
2296 
2297 void *
evgl_context_create(void * eng_data,EVGL_Context * share_ctx,Evas_GL_Context_Version version,void * (* native_context_get)(void *),void * (* engine_data_get)(void *))2298 evgl_context_create(void *eng_data, EVGL_Context *share_ctx,
2299                     Evas_GL_Context_Version version,
2300                     void *(*native_context_get)(void *),
2301                     void *(*engine_data_get)(void *))
2302 {
2303    EVGL_Context *ctx   = NULL;
2304 
2305    // A little bit ugly. But it works even when dlsym(DEFAULT) doesn't work.
2306    glsym_evas_gl_native_context_get = native_context_get;
2307    glsym_evas_gl_engine_data_get = engine_data_get;
2308 
2309    // Check the input
2310    if (!evgl_engine)
2311      {
2312         ERR("Invalid EVGL Engine!");
2313         evas_gl_common_error_set(EVAS_GL_BAD_ACCESS);
2314         return NULL;
2315      }
2316 
2317    if ((version < EVAS_GL_GLES_1_X) || (version > EVAS_GL_GLES_3_X))
2318      {
2319         ERR("Invalid context version number %d", version);
2320         evas_gl_common_error_set(EVAS_GL_BAD_PARAMETER);
2321         return NULL;
2322      }
2323 
2324    if (evgl_engine->api_debug_mode)
2325      DBG("Creating context GLESv%d (eng = %p, shctx = %p)", version, eng_data, share_ctx);
2326 
2327    // Allocate context object
2328    ctx = calloc(1, sizeof(EVGL_Context));
2329    if (!ctx)
2330      {
2331         ERR("Error allocating context object.");
2332         evas_gl_common_error_set(EVAS_GL_BAD_ALLOC);
2333         return NULL;
2334      }
2335 
2336    // Set default values
2337    ctx->version = version;
2338    ctx->version_minor = 0;
2339    ctx->scissor_coord[0] = 0;
2340    ctx->scissor_coord[1] = 0;
2341    ctx->scissor_coord[2] = evgl_engine->caps.max_w;
2342    ctx->scissor_coord[3] = evgl_engine->caps.max_h;
2343    ctx->gl_error = GL_NO_ERROR;
2344 
2345    // Call engine create context
2346    if (share_ctx)
2347       ctx->context = evgl_engine->funcs->context_create(eng_data, share_ctx->context, version);
2348    else
2349       ctx->context = evgl_engine->funcs->context_create(eng_data, NULL, version);
2350 
2351    // Call engine create context
2352    if (!ctx->context)
2353      {
2354         ERR("Error creating context from the Engine.");
2355         free(ctx);
2356         return NULL;
2357      }
2358 
2359    // Keep track of all the created context
2360    LKL(evgl_engine->resource_lock);
2361    evgl_engine->contexts = eina_list_prepend(evgl_engine->contexts, ctx);
2362    LKU(evgl_engine->resource_lock);
2363 
2364    if (evgl_engine->api_debug_mode)
2365      DBG("Created ctx %p", ctx);
2366 
2367    return ctx;
2368 }
2369 
2370 int
evgl_context_destroy(void * eng_data,EVGL_Context * ctx)2371 evgl_context_destroy(void *eng_data, EVGL_Context *ctx)
2372 {
2373    EVGL_Resource *rsc;
2374    Eina_Bool dbg;
2375 
2376    // Check the input
2377    if ((!evgl_engine) || (!ctx))
2378      {
2379         ERR("Invalid input data.  Engine: %p  Context:%p", evgl_engine, ctx);
2380         return 0;
2381      }
2382 
2383    // Retrieve the resource object
2384    if (!(rsc = _evgl_tls_resource_get()))
2385      {
2386         ERR("Error retrieving resource from TLS");
2387         return 0;
2388      }
2389 
2390    if ((dbg = evgl_engine->api_debug_mode))
2391      DBG("Destroying context (eng = %p, ctx = %p)", eng_data, ctx);
2392 
2393    if ((rsc->current_ctx) && (rsc->current_ctx == ctx))
2394      {
2395         if (evgl_engine->api_debug_mode)
2396           {
2397              ERR("The context is still current before it's being destroyed. "
2398                  "Calling make_current(NULL, NULL)");
2399           }
2400         else
2401           {
2402              WRN("The context is still current before it's being destroyed. "
2403                  "Calling make_current(NULL, NULL)");
2404           }
2405         evgl_make_current(eng_data, NULL, NULL);
2406      }
2407 
2408    if (ctx->current_sfc && (ctx->current_sfc->current_ctx == ctx))
2409      ctx->current_sfc->current_ctx = NULL;
2410 
2411    // Delete the FBO
2412    if (ctx->surface_fbo)
2413      {
2414         // Set the context current with resource context/surface
2415         if (!_internal_resource_make_current(eng_data, ctx->current_sfc, ctx))
2416           {
2417              ERR("Error doing an internal resource make current");
2418              return 0;
2419           }
2420         glDeleteFramebuffers(1, &ctx->surface_fbo);
2421      }
2422 
2423    // Retrieve the resource object
2424    rsc = _evgl_tls_resource_get();
2425    if (rsc && rsc->current_ctx == ctx)
2426      {
2427         // Unset the currrent context
2428         if (dbg) DBG("Calling make_current(NULL, NULL)");
2429         if (!evgl_engine->funcs->make_current(eng_data, NULL, NULL, 0))
2430           {
2431              ERR("Error doing make_current(NULL, NULL).");
2432              return 0;
2433           }
2434         rsc->current_ctx = NULL;
2435      }
2436 
2437    // Destroy indirect rendering context
2438    if (ctx->indirect_context &&
2439        !evgl_engine->funcs->context_destroy(eng_data, ctx->indirect_context))
2440      {
2441         ERR("Error destroying the indirect context.");
2442         return 0;
2443      }
2444 
2445    // Destroy engine context
2446    if (!evgl_engine->funcs->context_destroy(eng_data, ctx->context))
2447      {
2448         ERR("Error destroying the engine context.");
2449         return 0;
2450      }
2451 
2452    // Remove it from the list
2453    LKL(evgl_engine->resource_lock);
2454    evgl_engine->contexts = eina_list_remove(evgl_engine->contexts, ctx);
2455    LKU(evgl_engine->resource_lock);
2456 
2457    // Free context
2458    free(ctx);
2459 
2460    return 1;
2461 }
2462 
2463 int
evgl_make_current(void * eng_data,EVGL_Surface * sfc,EVGL_Context * ctx)2464 evgl_make_current(void *eng_data, EVGL_Surface *sfc, EVGL_Context *ctx)
2465 {
2466    Eina_Bool dbg = EINA_FALSE;
2467    EVGL_Resource *rsc;
2468    int curr_fbo = 0, curr_draw_fbo = 0, curr_read_fbo = 0;
2469    Eina_Bool ctx_changed = EINA_FALSE;
2470 
2471    // Check the input validity. If either sfc is valid but ctx is NULL, it's also error.
2472    // sfc can be NULL as evas gl supports surfaceless make current
2473    if ( (!evgl_engine) || ((sfc) && (!ctx)) )
2474      {
2475         ERR("Invalid Input: Engine: %p, Surface: %p, Context: %p", evgl_engine, sfc, ctx);
2476         if (!evgl_engine) evas_gl_common_error_set(EVAS_GL_NOT_INITIALIZED);
2477         if (!ctx) evas_gl_common_error_set(EVAS_GL_BAD_CONTEXT);
2478         return 0;
2479      }
2480 
2481    // Get TLS Resources
2482    rsc = _evgl_tls_resource_get();
2483    if (!rsc)
2484      {
2485         DBG("Creating new TLS for this thread: %lu", (unsigned long)eina_thread_self());
2486         rsc = _evgl_tls_resource_create(eng_data);
2487         if (!rsc) return 0;
2488      }
2489 
2490    // Abuse debug mode - extra tracing for make_current and friends
2491    dbg = evgl_engine->api_debug_mode;
2492    if (dbg) DBG("(eng = %p, sfc = %p, ctx = %p), rsc = %p", eng_data, sfc, ctx, rsc);
2493 
2494    // Unset
2495    if ((!sfc) && (!ctx))
2496      {
2497         if (rsc->current_ctx)
2498           {
2499              if (rsc->direct.partial.enabled)
2500                evgl_direct_partial_render_end();
2501 
2502              if (rsc->current_ctx->version == EVAS_GL_GLES_3_X)
2503                {
2504                   glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &curr_draw_fbo);
2505                   if ((rsc->current_ctx->surface_fbo == (GLuint) curr_draw_fbo) ||
2506                       (rsc->current_ctx->current_sfc &&
2507                        rsc->current_ctx->current_sfc->color_buf == (GLuint) curr_draw_fbo))
2508                     {
2509                        glBindFramebuffer(GL_FRAMEBUFFER, 0);
2510                        rsc->current_ctx->current_draw_fbo = 0;
2511                        rsc->current_ctx->current_read_fbo = 0;
2512                     }
2513                }
2514              else
2515                {
2516                   glGetIntegerv(GL_FRAMEBUFFER_BINDING, &curr_fbo);
2517                   if ((rsc->current_ctx->surface_fbo == (GLuint) curr_fbo) ||
2518                       (rsc->current_ctx->current_sfc &&
2519                        rsc->current_ctx->current_sfc->color_buf == (GLuint) curr_fbo))
2520                     {
2521                        glBindFramebuffer(GL_FRAMEBUFFER, 0);
2522                        rsc->current_ctx->current_fbo = 0;
2523                     }
2524                }
2525 
2526           }
2527 
2528         if (dbg) DBG("Calling make_current(NULL, NULL)");
2529         if (!evgl_engine->funcs->make_current(eng_data, NULL, NULL, 0))
2530           {
2531              ERR("Error calling make_current(NULL, NULL).");
2532              return 0;
2533           }
2534 
2535         // FIXME -- What is this "FIXME" about?
2536         if (rsc->current_ctx)
2537           {
2538              rsc->current_ctx->current_sfc = NULL;
2539              rsc->current_ctx = NULL;
2540              rsc->current_eng = NULL;
2541           }
2542         if (dbg) DBG("Call to make_current(NULL, NULL) was successful.");
2543         return 1;
2544      }
2545 
2546    // Disable partial rendering for previous context
2547    if ((rsc->current_ctx) && (rsc->current_ctx != ctx))
2548      {
2549         evas_gl_common_tiling_done(NULL);
2550         rsc->current_ctx->partial_render = 0;
2551      }
2552 
2553    // Do a make current
2554    if (!_internal_resource_make_current(eng_data, sfc, ctx))
2555      {
2556         ERR("Error doing a make current with internal surface. Context: %p", ctx);
2557         evas_gl_common_error_set(EVAS_GL_BAD_CONTEXT);
2558         return 0;
2559      }
2560 
2561    if (rsc->current_ctx != ctx)
2562      ctx_changed = EINA_TRUE;
2563 
2564    rsc->current_ctx = ctx;
2565    rsc->current_eng = eng_data;
2566 
2567    // Check whether extensions are supported for the current context version
2568    // to use fbo & egl image passing to evas
2569    if (!ctx->extension_checked)
2570      {
2571         if (!evgl_api_get(eng_data, ctx->version, EINA_FALSE))
2572           {
2573              ERR("Unable to get the list of GL APIs for version %d", ctx->version);
2574              evas_gl_common_error_set(EVAS_GL_NOT_INITIALIZED);
2575              return 0;
2576           }
2577 
2578         if (!_context_ext_check(ctx))
2579           {
2580              ERR("Unable to check required extension for the current context");
2581              evas_gl_common_error_set(EVAS_GL_NOT_INITIALIZED);
2582              return 0;
2583           }
2584      }
2585 
2586    if (sfc) sfc->current_ctx = ctx;
2587    else
2588      {
2589         DBG("Performing surfaceless make current");
2590         glViewport(0, 0, 0, 0);
2591         glScissor(0, 0, 0, 0);
2592         rsc->direct.rendered = 0;
2593         goto finish;
2594      }
2595 
2596    if (!sfc->buffers_skip_allocate)
2597      {
2598         if (!sfc->color_buf && !_surface_buffers_create(sfc))
2599           {
2600              ERR("Unable to create specified surfaces.");
2601              evas_gl_common_error_set(EVAS_GL_BAD_ALLOC);
2602              return 0;
2603           }
2604 
2605         // Allocate or free resources depending on what mode (direct of fbo) it's
2606         // running only if the env var EVAS_GL_DIRECT_MEM_OPT is set.
2607         if (sfc->direct_mem_opt)
2608           {
2609              if (_evgl_direct_renderable(rsc, sfc))
2610                {
2611                   if (dbg) DBG("sfc %p is direct renderable (has buffers: %d).", sfc, (int) sfc->buffers_allocated);
2612 
2613                   // Destroy created resources
2614                   if (sfc->buffers_allocated)
2615                     {
2616                        if (!_surface_buffers_allocate(eng_data, sfc, 0, 0, ctx->version))
2617                          {
2618                             ERR("Unable to destroy surface buffers!");
2619                             evas_gl_common_error_set(EVAS_GL_BAD_ALLOC);
2620                             return 0;
2621                          }
2622                        sfc->buffers_allocated = 0;
2623                     }
2624                }
2625              else
2626                {
2627                   if (sfc->direct_override)
2628                     {
2629                        DBG("Not creating fallback surfaces even though it should. Use at OWN discretion!");
2630                     }
2631                   else
2632                     {
2633                        // Create internal buffers if not yet created
2634                        if (!sfc->buffers_allocated)
2635                          {
2636                             if (dbg) DBG("Allocating buffers for sfc %p", sfc);
2637                             if (!_surface_buffers_allocate(eng_data, sfc, sfc->w, sfc->h, ctx->version))
2638                               {
2639                                  ERR("Unable Create Specificed Surfaces.  Unsupported format!");
2640                                  evas_gl_common_error_set(EVAS_GL_BAD_ALLOC);
2641                                  return 0;
2642                               }
2643                             sfc->buffers_allocated = 1;
2644                          }
2645                     }
2646                }
2647           }
2648         else
2649           {
2650              if (!sfc->buffers_allocated)
2651                {
2652                   if (!_surface_buffers_allocate(eng_data, sfc, sfc->w, sfc->h, ctx->version))
2653                     {
2654                        ERR("Unable Create Allocate Memory for Surface.");
2655                        evas_gl_common_error_set(EVAS_GL_BAD_ALLOC);
2656                        return 0;
2657                     }
2658                   sfc->buffers_allocated = 1;
2659                }
2660           }
2661      }
2662 
2663    if (ctx->pixmap_image_supported)
2664      {
2665         if (dbg) DBG("ctx %p is GLES %d", ctx, ctx->version);
2666         if (_evgl_direct_renderable(rsc, sfc))
2667           {
2668              // Transition from indirect rendering to direct rendering
2669              if (!rsc->direct.rendered)
2670                {
2671                   // Restore viewport and scissor test to direct rendering mode
2672                   glViewport(ctx->viewport_direct[0], ctx->viewport_direct[1], ctx->viewport_direct[2], ctx->viewport_direct[3]);
2673                   if ((ctx->direct_scissor) && (!ctx->scissor_enabled))
2674                     glEnable(GL_SCISSOR_TEST);
2675                }
2676              if (dbg) DBG("sfc %p is direct renderable.", sfc);
2677              rsc->direct.rendered = 1;
2678           }
2679         else
2680           {
2681              // Transition from direct rendering to indirect rendering
2682              if (rsc->direct.rendered)
2683                {
2684                   glViewport(ctx->viewport_coord[0], ctx->viewport_coord[1], ctx->viewport_coord[2], ctx->viewport_coord[3]);
2685                   if ((ctx->direct_scissor) && (!ctx->scissor_enabled))
2686                     glDisable(GL_SCISSOR_TEST);
2687              }
2688 
2689              if (ctx->version == EVAS_GL_GLES_3_X)
2690                {
2691                   ctx->current_draw_fbo = 0;
2692                   ctx->current_read_fbo = 0;
2693                }
2694              else
2695                {
2696                   ctx->current_fbo = 0;
2697                }
2698 
2699              rsc->direct.rendered = 0;
2700           }
2701      }
2702    else
2703      {
2704         // Direct Rendering
2705         if (_evgl_direct_renderable(rsc, sfc))
2706           {
2707              if (dbg) DBG("sfc %p is direct renderable.", sfc);
2708 
2709              // Create FBO if it hasn't been created
2710              if (!ctx->surface_fbo)
2711                _framebuffer_create(&ctx->surface_fbo, ctx->version);
2712 
2713              if (ctx->version == EVAS_GL_GLES_3_X)
2714                {
2715                   // This is to transition from FBO rendering to direct rendering
2716                   glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &curr_draw_fbo);
2717                   if (ctx->surface_fbo == (GLuint)curr_draw_fbo)
2718                     {
2719                        _framebuffer_draw_bind(0, ctx->version);
2720                        ctx->current_draw_fbo = 0;
2721                     }
2722                   else if (ctx->current_sfc && (ctx->current_sfc->pbuffer.is_pbuffer))
2723                     {
2724                        // Using the same context, we were rendering on a pbuffer
2725                        _framebuffer_draw_bind(0, ctx->version);
2726                        ctx->current_draw_fbo = 0;
2727                     }
2728 
2729                   glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &curr_read_fbo);
2730                   if (ctx->surface_fbo == (GLuint)curr_read_fbo)
2731                     {
2732                        _framebuffer_read_bind(0, ctx->version);
2733                        ctx->current_read_fbo = 0;
2734                     }
2735                   else if (ctx->current_sfc && (ctx->current_sfc->pbuffer.is_pbuffer))
2736                     {
2737                        _framebuffer_read_bind(0, ctx->version);
2738                        ctx->current_read_fbo = 0;
2739                     }
2740 
2741                   if (ctx->current_read_fbo == 0)
2742                     {
2743                        // If master clip is set and clip is greater than 0, do partial render
2744                        if (rsc->direct.partial.enabled)
2745                          {
2746                             if (!ctx->partial_render)
2747                               {
2748                                  evgl_direct_partial_render_start();
2749                                  ctx->partial_render = 1;
2750                               }
2751                          }
2752                     }
2753                }
2754              else
2755                {
2756                   // This is to transition from FBO rendering to direct rendering
2757                   glGetIntegerv(GL_FRAMEBUFFER_BINDING, &curr_fbo);
2758                   if (ctx->surface_fbo == (GLuint)curr_fbo)
2759                     {
2760                        _framebuffer_bind(0, ctx->version);
2761                        ctx->current_fbo = 0;
2762                     }
2763                   else if (ctx->current_sfc && (ctx->current_sfc->pbuffer.is_pbuffer))
2764                     {
2765                        // Using the same context, we were rendering on a pbuffer
2766                        _framebuffer_bind(0, ctx->version);
2767                        ctx->current_fbo = 0;
2768                     }
2769 
2770                   if (ctx->current_fbo == 0)
2771                     {
2772                        // If master clip is set and clip is greater than 0, do partial render
2773                        if (rsc->direct.partial.enabled)
2774                          {
2775                             if (!ctx->partial_render)
2776                               {
2777                                  evgl_direct_partial_render_start();
2778                                  ctx->partial_render = 1;
2779                               }
2780                          }
2781                     }
2782                }
2783 
2784              rsc->direct.rendered = 1;
2785           }
2786         else if (sfc->pbuffer.native_surface)
2787           {
2788              if (dbg) DBG("Surface sfc %p is a pbuffer: %p", sfc, sfc->pbuffer.native_surface);
2789 
2790              // Call end tiling
2791              if (rsc->direct.partial.enabled)
2792                evgl_direct_partial_render_end();
2793 
2794              // Bind to the previously bound buffer (may be 0)
2795              if (ctx->version == EVAS_GL_GLES_3_X)
2796                {
2797                   if (ctx->current_draw_fbo)
2798                     {
2799                        _framebuffer_draw_bind(ctx->current_draw_fbo, ctx->version);
2800                     }
2801                }
2802              else
2803                {
2804                   if (ctx->current_fbo)
2805                     {
2806                        _framebuffer_bind(ctx->current_fbo, ctx->version);
2807                     }
2808                }
2809 
2810              rsc->direct.rendered = 0;
2811           }
2812         else
2813           {
2814              if (dbg) DBG("Surface sfc %p is a normal surface.", sfc);
2815 
2816              // Create FBO if it hasn't been created
2817              if (!ctx->surface_fbo)
2818                _framebuffer_create(&ctx->surface_fbo, ctx->version);
2819 
2820              // Attach fbo and the buffers
2821              if ((ctx_changed) || (ctx->current_sfc != sfc) || (rsc->direct.rendered))
2822                {
2823                   sfc->current_ctx = ctx;
2824                   if ((sfc->direct_mem_opt) && (sfc->direct_override))
2825                     {
2826                        DBG("Not creating fallback surfaces even though it should. Use at OWN discretion!");
2827                     }
2828                   else
2829                     {
2830                        // If it's transitioning from direct render to fbo render
2831                        // Call end tiling
2832                        if (rsc->direct.partial.enabled)
2833                           evgl_direct_partial_render_end();
2834 
2835                        if (!_surface_buffers_fbo_set(sfc, ctx->surface_fbo, ctx->version))
2836                          {
2837                             ERR("Attaching buffers to context fbo failed. Engine: %p  Surface: %p Context FBO: %u", evgl_engine, sfc, ctx->surface_fbo);
2838                             evas_gl_common_error_set(EVAS_GL_BAD_CONTEXT);
2839                             return 0;
2840                          }
2841                     }
2842 
2843                   // Bind to the previously bound buffer
2844 
2845                   if (ctx->version == EVAS_GL_GLES_3_X)
2846                     {
2847                        if (ctx->current_draw_fbo)
2848                          _framebuffer_draw_bind(ctx->current_draw_fbo, ctx->version);
2849 
2850                        if (ctx->current_read_fbo)
2851                          _framebuffer_read_bind(ctx->current_read_fbo, ctx->version);
2852                     }
2853                   else
2854                     {
2855                        if (ctx->current_fbo)
2856                          _framebuffer_bind(ctx->current_fbo, ctx->version);
2857                     }
2858                }
2859              rsc->direct.rendered = 0;
2860           }
2861      }
2862 
2863 finish:
2864    ctx->current_sfc = sfc;
2865 
2866    _surface_context_list_print();
2867 
2868    return 1;
2869 }
2870 
2871 const char *
evgl_string_query(int name)2872 evgl_string_query(int name)
2873 {
2874    EVGL_Resource *rsc;
2875    int ctx_version = EVAS_GL_GLES_2_X;
2876 
2877    switch(name)
2878      {
2879       case EVAS_GL_EXTENSIONS:
2880         {
2881            Eina_Strbuf *extstr = eina_strbuf_new();
2882            const char *glstr = NULL, *eglstr = NULL, *str = NULL;
2883            rsc = _evgl_tls_resource_get();
2884            if ((rsc) && (rsc->current_ctx))
2885              ctx_version = rsc->current_ctx->version;
2886            glstr = evgl_api_ext_string_get(EINA_FALSE, ctx_version);
2887            if (glstr)
2888              eina_strbuf_append(extstr, glstr);
2889            eglstr = evgl_api_ext_egl_string_get();
2890            if (eglstr)
2891              eina_strbuf_append(extstr, eglstr);
2892            str = eina_strbuf_string_steal(extstr);
2893            eina_strbuf_free(extstr);
2894            return str;
2895         }
2896 
2897       default:
2898          return "";
2899      };
2900 }
2901 
2902 void
evgl_safe_extension_add(const char * name,void * funcptr)2903 evgl_safe_extension_add(const char *name, void *funcptr)
2904 {
2905    if (!name) return;
2906 
2907    if (evgl_engine->api_debug_mode)
2908      DBG("Whitelisting function [%p] %s", funcptr, name);
2909 
2910    if (funcptr)
2911      eina_hash_set(evgl_engine->safe_extensions, name, funcptr);
2912    else
2913      eina_hash_set(evgl_engine->safe_extensions, name, (void*) 0x1);
2914 }
2915 
2916 Eina_Bool
evgl_safe_extension_get(const char * name,void ** pfuncptr)2917 evgl_safe_extension_get(const char *name, void **pfuncptr)
2918 {
2919    static Eina_Bool _unsafe_checked = EINA_FALSE, _unsafe = EINA_FALSE;
2920    void *func;
2921 
2922    if (!name || !*name)
2923      return EINA_FALSE;
2924 
2925    // use this for debugging or if you want to break everything
2926    if (!_unsafe_checked)
2927      {
2928         if (getenv("EVAS_GL_UNSAFE_EXTENSIONS"))
2929           _unsafe = EINA_TRUE;
2930      }
2931 
2932    if (_unsafe)
2933      return EINA_TRUE;
2934 
2935    func = eina_hash_find(evgl_engine->safe_extensions, name);
2936    if (!func) return EINA_FALSE;
2937 
2938    // this is for safe extensions of which we didn't resolve the address
2939    if (func == (void *) 0x1)
2940      {
2941         if (pfuncptr) *pfuncptr = NULL;
2942         return EINA_TRUE;
2943      }
2944 
2945    if (pfuncptr) *pfuncptr = func;
2946    return EINA_TRUE;
2947 }
2948 
2949 void *
evgl_native_surface_buffer_get(EVGL_Surface * sfc,Eina_Bool * is_egl_image)2950 evgl_native_surface_buffer_get(EVGL_Surface *sfc, Eina_Bool *is_egl_image)
2951 {
2952    void *buf = NULL;
2953    *is_egl_image = EINA_FALSE;
2954 
2955    if (!evgl_engine)
2956      {
2957         ERR("Invalid input data.  Engine: %p", evgl_engine);
2958         return NULL;
2959      }
2960 
2961    if (sfc->egl_image)
2962      {
2963         buf = sfc->egl_image;
2964         *is_egl_image = EINA_TRUE;
2965      }
2966    else
2967      {
2968         buf = (void *)(uintptr_t)sfc->color_buf;
2969      }
2970 
2971    return buf;
2972 }
2973 
2974 int
evgl_native_surface_yinvert_get(EVGL_Surface * sfc)2975 evgl_native_surface_yinvert_get(EVGL_Surface *sfc)
2976 {
2977    int ret = 0;
2978    if (!evgl_engine)
2979      {
2980         ERR("Invalid input data.  Engine: %p", evgl_engine);
2981         return 0;
2982      }
2983 
2984    if (sfc->indirect)
2985       ret = sfc->yinvert;
2986 
2987    return ret;
2988 }
2989 
2990 int
evgl_native_surface_get(EVGL_Surface * sfc,Evas_Native_Surface * ns)2991 evgl_native_surface_get(EVGL_Surface *sfc, Evas_Native_Surface *ns)
2992 {
2993    // Check the input
2994    if ((!evgl_engine) || (!ns))
2995      {
2996         ERR("Invalid input data.  Engine: %p  NS:%p", evgl_engine, ns);
2997         return 0;
2998      }
2999 
3000    ns->type = EVAS_NATIVE_SURFACE_EVASGL;
3001    ns->version = EVAS_NATIVE_SURFACE_VERSION;
3002    ns->data.evasgl.surface = sfc;
3003 
3004    return 1;
3005 }
3006 
3007 int
evgl_direct_rendered(void)3008 evgl_direct_rendered(void)
3009 {
3010    EVGL_Resource *rsc;
3011 
3012    if (!(rsc=_evgl_tls_resource_get())) return 0;
3013 
3014    return rsc->direct.rendered;
3015 }
3016 
3017 /*
3018  * This function can tell the engine whether a surface can be directly
3019  * rendered to the Evas, despite any window rotation. For that purpose,
3020  * we let the engine know the surface flags for this texture
3021  */
3022 Eina_Bool
evgl_native_surface_direct_opts_get(Evas_Native_Surface * ns,Eina_Bool * direct_render,Eina_Bool * client_side_rotation,Eina_Bool * direct_override)3023 evgl_native_surface_direct_opts_get(Evas_Native_Surface *ns,
3024                                     Eina_Bool *direct_render,
3025                                     Eina_Bool *client_side_rotation,
3026                                     Eina_Bool *direct_override)
3027 {
3028    EVGL_Surface *sfc;
3029 
3030    if (direct_render) *direct_render = EINA_FALSE;
3031    if (direct_override) *direct_override = EINA_FALSE;
3032    if (client_side_rotation) *client_side_rotation = EINA_FALSE;
3033 
3034    if (!evgl_engine) return EINA_FALSE;
3035    if (!ns) return EINA_FALSE;
3036 
3037    if (ns->type == EVAS_NATIVE_SURFACE_EVASGL &&
3038             ns->data.evasgl.surface)
3039      {
3040         sfc = ns->data.evasgl.surface;
3041      }
3042    else return EINA_FALSE;
3043 
3044    if (evgl_engine->api_debug_mode)
3045      {
3046         DBG("Found native surface:  DR:%d CSR:%d",
3047             (int) sfc->direct_fb_opt, (int) sfc->client_side_rotation);
3048      }
3049 
3050    if (direct_render) *direct_render = sfc->direct_fb_opt;
3051    if (direct_override) *direct_override |= sfc->direct_override;
3052    if (client_side_rotation) *client_side_rotation = sfc->client_side_rotation;
3053    return EINA_TRUE;
3054 }
3055 
3056 void
evgl_direct_info_set(int win_w,int win_h,int rot,int img_x,int img_y,int img_w,int img_h,int clip_x,int clip_y,int clip_w,int clip_h,int render_op,void * surface)3057 evgl_direct_info_set(int win_w, int win_h, int rot,
3058                      int img_x, int img_y, int img_w, int img_h,
3059                      int clip_x, int clip_y, int clip_w, int clip_h,
3060                      int render_op, void *surface)
3061 {
3062    EVGL_Resource *rsc;
3063    EVGL_Surface *sfc = surface;
3064 
3065    if (!(rsc = _evgl_tls_resource_get()))
3066      return;
3067 
3068    /* Check for direct rendering
3069     *
3070     * DR is allowed iif:
3071     * - Rotation == 0
3072     * OR: - Client-Side Rotation is set on the surface
3073     *     - Direct Override is set
3074     *
3075     * If the surface is not found, we assume indirect rendering.
3076     */
3077 
3078    if (sfc &&
3079        ((rot == 0) || sfc->client_side_rotation || sfc->direct_override))
3080      {
3081         if (evgl_engine->api_debug_mode)
3082           DBG("Direct rendering is enabled.");
3083 
3084         rsc->direct.enabled = EINA_TRUE;
3085 
3086         rsc->direct.win_w   = win_w;
3087         rsc->direct.win_h   = win_h;
3088         rsc->direct.rot     = rot;
3089 
3090         rsc->direct.img.x   = img_x;
3091         rsc->direct.img.y   = img_y;
3092         rsc->direct.img.w   = img_w;
3093         rsc->direct.img.h   = img_h;
3094 
3095         rsc->direct.clip.x  = clip_x;
3096         rsc->direct.clip.y  = clip_y;
3097         rsc->direct.clip.w  = clip_w;
3098         rsc->direct.clip.h  = clip_h;
3099 
3100         rsc->direct.render_op_copy = (render_op == EVAS_RENDER_COPY);
3101      }
3102    else
3103      {
3104         if (evgl_engine->api_debug_mode)
3105           DBG("Direct rendering is disabled.");
3106 
3107         rsc->direct.enabled = EINA_FALSE;
3108      }
3109 }
3110 
3111 void
evgl_direct_info_clear(void)3112 evgl_direct_info_clear(void)
3113 {
3114    EVGL_Resource *rsc;
3115 
3116    if (!(rsc=_evgl_tls_resource_get())) return;
3117 
3118    rsc->direct.enabled = EINA_FALSE;
3119 }
3120 
3121 void
evgl_get_pixels_pre(void)3122 evgl_get_pixels_pre(void)
3123 {
3124    EVGL_Resource *rsc;
3125 
3126    if (!(rsc=_evgl_tls_resource_get())) return;
3127 
3128    rsc->direct.in_get_pixels = EINA_TRUE;
3129 }
3130 
3131 void
evgl_get_pixels_post(void)3132 evgl_get_pixels_post(void)
3133 {
3134    EVGL_Resource *rsc;
3135 
3136    if (!(rsc=_evgl_tls_resource_get())) return;
3137 
3138    rsc->direct.in_get_pixels = EINA_FALSE;
3139 }
3140 
3141 Evas_GL_API *
evgl_api_get(void * eng_data,Evas_GL_Context_Version version,Eina_Bool alloc_only)3142 evgl_api_get(void *eng_data, Evas_GL_Context_Version version, Eina_Bool alloc_only)
3143 {
3144    Evas_GL_API *api = NULL;
3145    int minor_version = 0;
3146 
3147    if (version == EVAS_GL_GLES_2_X)
3148      {
3149         if (!gles2_funcs) gles2_funcs = calloc(1, EVAS_GL_API_STRUCT_SIZE);
3150         api = gles2_funcs;
3151      }
3152    else if (version == EVAS_GL_GLES_1_X)
3153      {
3154         if (!gles1_funcs) gles1_funcs = calloc(1, EVAS_GL_API_STRUCT_SIZE);
3155         api = gles1_funcs;
3156      }
3157    else if (version == EVAS_GL_GLES_3_X)
3158      {
3159         if (evas_gl_common_version_check(&minor_version) < 3)
3160           {
3161              ERR("OpenGL ES 3.x is not supported.");
3162              return NULL;
3163           }
3164         if (!gles3_funcs) gles3_funcs = calloc(1, EVAS_GL_API_STRUCT_SIZE);
3165         api = gles3_funcs;
3166      }
3167    if (!api) return NULL;
3168    if (alloc_only && (api->version == EVAS_GL_API_VERSION))
3169      return api;
3170 
3171 #ifdef GL_GLES
3172     if (!evgl_api_egl_ext_init(evgl_engine->funcs->proc_address_get, evgl_engine->funcs->ext_string_get(eng_data)))
3173       {
3174          ERR("EGL extensions initialization failed");
3175       }
3176 #endif
3177    if (version == EVAS_GL_GLES_2_X)
3178      {
3179         _evgl_api_gles2_get(api, evgl_engine->api_debug_mode);
3180         evgl_api_gles2_ext_get(api, evgl_engine->funcs->proc_address_get, evgl_engine->funcs->ext_string_get(eng_data));
3181      }
3182    else if (version == EVAS_GL_GLES_1_X)
3183      {
3184         _evgl_api_gles1_get(api, evgl_engine->api_debug_mode);
3185         evgl_api_gles1_ext_get(api, evgl_engine->funcs->proc_address_get, evgl_engine->funcs->ext_string_get(eng_data));
3186      }
3187    else if (version == EVAS_GL_GLES_3_X)
3188      {
3189         void *(*get_proc_address)(const char *) = NULL;
3190         const char *egl_exts;
3191 
3192         egl_exts = evgl_engine->funcs->ext_string_get(eng_data);
3193         if (egl_exts && strstr(egl_exts, "EGL_KHR_get_all_proc_addresses"))
3194           get_proc_address = evgl_engine->funcs->proc_address_get;
3195 
3196         _evgl_api_gles3_get(api, get_proc_address, evgl_engine->api_debug_mode, minor_version);
3197         evgl_api_gles3_ext_get(api, evgl_engine->funcs->proc_address_get, evgl_engine->funcs->ext_string_get(eng_data));
3198      }
3199 
3200    return api;
3201 }
3202 
3203 
3204 void
evgl_direct_partial_info_set(int pres)3205 evgl_direct_partial_info_set(int pres)
3206 {
3207    EVGL_Resource *rsc;
3208 
3209    if (!(rsc=_evgl_tls_resource_get())) return;
3210 
3211    rsc->direct.partial.enabled  = EINA_TRUE;
3212    rsc->direct.partial.preserve = pres;
3213 }
3214 
3215 void
evgl_direct_partial_info_clear()3216 evgl_direct_partial_info_clear()
3217 {
3218    EVGL_Resource *rsc;
3219 
3220    if (!(rsc=_evgl_tls_resource_get())) return;
3221 
3222    rsc->direct.partial.enabled = EINA_FALSE;
3223 }
3224 
3225 void
evgl_direct_override_get(Eina_Bool * override,Eina_Bool * force_off)3226 evgl_direct_override_get(Eina_Bool *override, Eina_Bool *force_off)
3227 {
3228    if (!evgl_engine) return;
3229    if (override)  *override  = evgl_engine->direct_override;
3230    if (force_off) *force_off = evgl_engine->direct_force_off;
3231 }
3232 
3233 void
evgl_direct_partial_render_start()3234 evgl_direct_partial_render_start()
3235 {
3236    EVGL_Resource *rsc;
3237 
3238    if (!(rsc=_evgl_tls_resource_get())) return;
3239 
3240    evas_gl_common_tiling_start(NULL,
3241                                rsc->direct.rot,
3242                                rsc->direct.win_w,
3243                                rsc->direct.win_h,
3244                                rsc->direct.clip.x,
3245                                rsc->direct.win_h - rsc->direct.clip.y - rsc->direct.clip.h,
3246                                rsc->direct.clip.w,
3247                                rsc->direct.clip.h,
3248                                rsc->direct.partial.preserve);
3249 
3250    if (!rsc->direct.partial.preserve)
3251       rsc->direct.partial.preserve = GL_COLOR_BUFFER_BIT0_QCOM;
3252 }
3253 
3254 void
evgl_direct_partial_render_end()3255 evgl_direct_partial_render_end()
3256 {
3257    EVGL_Context *ctx;
3258    ctx = evas_gl_common_current_context_get();
3259 
3260    if (!ctx) return;
3261 
3262    if (ctx->partial_render)
3263      {
3264         evas_gl_common_tiling_done(NULL);
3265         ctx->partial_render = 0;
3266      }
3267 }
3268 
3269 EAPI void
evas_gl_common_context_restore_set(Eina_Bool enable)3270 evas_gl_common_context_restore_set(Eina_Bool enable)
3271 {
3272    _need_context_restore = enable;
3273 }
3274 
3275 //-----------------------------------------------------//
3276 
3277 
3278