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