• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 The SwiftShader Authors. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //    http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 // libEGL.cpp: Implements the exported EGL functions.
16 
17 #include "main.h"
18 #include "Display.h"
19 #include "Surface.h"
20 #include "Texture.hpp"
21 #include "Context.hpp"
22 #include "common/Image.hpp"
23 #include "common/debug.h"
24 #include "Common/Version.h"
25 
26 #if defined(__ANDROID__)
27 #include <system/window.h>
28 #elif defined(__linux__)
29 #include "Main/libX11.hpp"
30 #endif
31 
32 #include <string.h>
33 
34 using namespace egl;
35 
validateDisplay(egl::Display * display)36 static bool validateDisplay(egl::Display *display)
37 {
38 	if(display == EGL_NO_DISPLAY)
39 	{
40 		return error(EGL_BAD_DISPLAY, false);
41 	}
42 
43 	if(!display->isInitialized())
44 	{
45 		return error(EGL_NOT_INITIALIZED, false);
46 	}
47 
48 	return true;
49 }
50 
validateConfig(egl::Display * display,EGLConfig config)51 static bool validateConfig(egl::Display *display, EGLConfig config)
52 {
53 	if(!validateDisplay(display))
54 	{
55 		return false;
56 	}
57 
58 	if(!display->isValidConfig(config))
59 	{
60 		return error(EGL_BAD_CONFIG, false);
61 	}
62 
63 	return true;
64 }
65 
validateContext(egl::Display * display,egl::Context * context)66 static bool validateContext(egl::Display *display, egl::Context *context)
67 {
68 	if(!validateDisplay(display))
69 	{
70 		return false;
71 	}
72 
73 	if(!display->isValidContext(context))
74 	{
75 		return error(EGL_BAD_CONTEXT, false);
76 	}
77 
78 	return true;
79 }
80 
validateSurface(egl::Display * display,egl::Surface * surface)81 static bool validateSurface(egl::Display *display, egl::Surface *surface)
82 {
83 	if(!validateDisplay(display))
84 	{
85 		return false;
86 	}
87 
88 	if(!display->isValidSurface(surface))
89 	{
90 		return error(EGL_BAD_SURFACE, false);
91 	}
92 
93 	return true;
94 }
95 
96 namespace egl
97 {
GetError(void)98 EGLint GetError(void)
99 {
100 	TRACE("()");
101 
102 	EGLint error = egl::getCurrentError();
103 
104 	if(error != EGL_SUCCESS)
105 	{
106 		egl::setCurrentError(EGL_SUCCESS);
107 	}
108 
109 	return error;
110 }
111 
GetDisplay(EGLNativeDisplayType display_id)112 EGLDisplay GetDisplay(EGLNativeDisplayType display_id)
113 {
114 	TRACE("(EGLNativeDisplayType display_id = %p)", display_id);
115 
116 	if(display_id != EGL_DEFAULT_DISPLAY)
117 	{
118 		// FIXME: Check if display_id is the default display
119 	}
120 
121 	#if defined(__linux__) && !defined(__ANDROID__)
122 		if(!libX11)
123 		{
124 			return success(HEADLESS_DISPLAY);
125 		}
126 	#endif
127 
128 	return success(PRIMARY_DISPLAY);   // We only support the default display
129 }
130 
Initialize(EGLDisplay dpy,EGLint * major,EGLint * minor)131 EGLBoolean Initialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
132 {
133 	TRACE("(EGLDisplay dpy = %p, EGLint *major = %p, EGLint *minor = %p)",
134 		  dpy, major, minor);
135 
136 	if(dpy == EGL_NO_DISPLAY)
137 	{
138 		return error(EGL_BAD_DISPLAY, EGL_FALSE);
139 	}
140 
141 	egl::Display *display = egl::Display::get(dpy);
142 
143 	if(!display->initialize())
144 	{
145 		return error(EGL_NOT_INITIALIZED, EGL_FALSE);
146 	}
147 
148 	if(major) *major = 1;
149 	if(minor) *minor = 4;
150 
151 	return success(EGL_TRUE);
152 }
153 
Terminate(EGLDisplay dpy)154 EGLBoolean Terminate(EGLDisplay dpy)
155 {
156 	TRACE("(EGLDisplay dpy = %p)", dpy);
157 
158 	if(dpy == EGL_NO_DISPLAY)
159 	{
160 		return error(EGL_BAD_DISPLAY, EGL_FALSE);
161 	}
162 
163 	egl::Display *display = egl::Display::get(dpy);
164 
165 	display->terminate();
166 
167 	return success(EGL_TRUE);
168 }
169 
QueryString(EGLDisplay dpy,EGLint name)170 const char *QueryString(EGLDisplay dpy, EGLint name)
171 {
172 	TRACE("(EGLDisplay dpy = %p, EGLint name = %d)", dpy, name);
173 
174 	#if defined(__linux__) && !defined(__ANDROID__)
175 		if(dpy == EGL_NO_DISPLAY && name == EGL_EXTENSIONS)
176 		{
177 			return success("EGL_KHR_platform_gbm "
178 			               "EGL_KHR_platform_x11 "
179 			               "EGL_EXT_client_extensions "
180 			               "EGL_EXT_platform_base");
181 		}
182 	#endif
183 
184 	egl::Display *display = egl::Display::get(dpy);
185 
186 	if(!validateDisplay(display))
187 	{
188 		return nullptr;
189 	}
190 
191 	switch(name)
192 	{
193 	case EGL_CLIENT_APIS:
194 		return success("OpenGL_ES");
195 	case EGL_EXTENSIONS:
196 		return success("EGL_KHR_create_context "
197 		               "EGL_KHR_gl_texture_2D_image "
198 		               "EGL_KHR_gl_texture_cubemap_image "
199 		               "EGL_KHR_gl_renderbuffer_image "
200 		               "EGL_KHR_fence_sync "
201 		               "EGL_KHR_image_base "
202 		               "EGL_ANDROID_framebuffer_target "
203 		               "EGL_ANDROID_recordable");
204 	case EGL_VENDOR:
205 		return success("Google Inc.");
206 	case EGL_VERSION:
207 		return success("1.4 SwiftShader " VERSION_STRING);
208 	}
209 
210 	return error(EGL_BAD_PARAMETER, (const char*)nullptr);
211 }
212 
GetConfigs(EGLDisplay dpy,EGLConfig * configs,EGLint config_size,EGLint * num_config)213 EGLBoolean GetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config)
214 {
215 	TRACE("(EGLDisplay dpy = %p, EGLConfig *configs = %p, "
216 	      "EGLint config_size = %d, EGLint *num_config = %p)",
217 	      dpy, configs, config_size, num_config);
218 
219 	egl::Display *display = egl::Display::get(dpy);
220 
221 	if(!validateDisplay(display))
222 	{
223 		return EGL_FALSE;
224 	}
225 
226 	if(!num_config)
227 	{
228 		return error(EGL_BAD_PARAMETER, EGL_FALSE);
229 	}
230 
231 	const EGLint attribList[] = {EGL_NONE};
232 
233 	if(!display->getConfigs(configs, attribList, config_size, num_config))
234 	{
235 		return error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
236 	}
237 
238 	return success(EGL_TRUE);
239 }
240 
ChooseConfig(EGLDisplay dpy,const EGLint * attrib_list,EGLConfig * configs,EGLint config_size,EGLint * num_config)241 EGLBoolean ChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config)
242 {
243 	TRACE("(EGLDisplay dpy = %p, const EGLint *attrib_list = %p, "
244 	      "EGLConfig *configs = %p, EGLint config_size = %d, EGLint *num_config = %p)",
245 	      dpy, attrib_list, configs, config_size, num_config);
246 
247 	egl::Display *display = egl::Display::get(dpy);
248 
249 	if(!validateDisplay(display))
250 	{
251 		return EGL_FALSE;
252 	}
253 
254 	if(!num_config)
255 	{
256 		return error(EGL_BAD_PARAMETER, EGL_FALSE);
257 	}
258 
259 	const EGLint attribList[] = {EGL_NONE};
260 
261 	if(!attrib_list)
262 	{
263 		attrib_list = attribList;
264 	}
265 
266 	if(!display->getConfigs(configs, attrib_list, config_size, num_config))
267 	{
268 		return error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
269 	}
270 
271 	return success(EGL_TRUE);
272 }
273 
GetConfigAttrib(EGLDisplay dpy,EGLConfig config,EGLint attribute,EGLint * value)274 EGLBoolean GetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value)
275 {
276 	TRACE("(EGLDisplay dpy = %p, EGLConfig config = %p, EGLint attribute = %d, EGLint *value = %p)",
277 	      dpy, config, attribute, value);
278 
279 	egl::Display *display = egl::Display::get(dpy);
280 
281 	if(!validateConfig(display, config))
282 	{
283 		return EGL_FALSE;
284 	}
285 
286 	if(!display->getConfigAttrib(config, attribute, value))
287 	{
288 		return error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
289 	}
290 
291 	return success(EGL_TRUE);
292 }
293 
CreateWindowSurface(EGLDisplay dpy,EGLConfig config,EGLNativeWindowType window,const EGLint * attrib_list)294 EGLSurface CreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType window, const EGLint *attrib_list)
295 {
296 	TRACE("(EGLDisplay dpy = %p, EGLConfig config = %p, EGLNativeWindowType win = %p, "
297 	      "const EGLint *attrib_list = %p)", dpy, config, window, attrib_list);
298 
299 	egl::Display *display = egl::Display::get(dpy);
300 
301 	if(!validateConfig(display, config))
302 	{
303 		return EGL_NO_SURFACE;
304 	}
305 
306 	if(!display->isValidWindow(window))
307 	{
308 		return error(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
309 	}
310 
311 	return display->createWindowSurface(window, config, attrib_list);
312 }
313 
CreatePbufferSurface(EGLDisplay dpy,EGLConfig config,const EGLint * attrib_list)314 EGLSurface CreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list)
315 {
316 	TRACE("(EGLDisplay dpy = %p, EGLConfig config = %p, const EGLint *attrib_list = %p)",
317 	      dpy, config, attrib_list);
318 
319 	egl::Display *display = egl::Display::get(dpy);
320 
321 	if(!validateConfig(display, config))
322 	{
323 		return EGL_NO_SURFACE;
324 	}
325 
326 	return display->createPBufferSurface(config, attrib_list);
327 }
328 
CreatePixmapSurface(EGLDisplay dpy,EGLConfig config,EGLNativePixmapType pixmap,const EGLint * attrib_list)329 EGLSurface CreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list)
330 {
331 	TRACE("(EGLDisplay dpy = %p, EGLConfig config = %p, EGLNativePixmapType pixmap = %p, "
332 	      "const EGLint *attrib_list = %p)", dpy, config, pixmap, attrib_list);
333 
334 	egl::Display *display = egl::Display::get(dpy);
335 
336 	if(!validateConfig(display, config))
337 	{
338 		return EGL_NO_SURFACE;
339 	}
340 
341 	UNIMPLEMENTED();   // FIXME
342 
343 	return success(EGL_NO_SURFACE);
344 }
345 
DestroySurface(EGLDisplay dpy,EGLSurface surface)346 EGLBoolean DestroySurface(EGLDisplay dpy, EGLSurface surface)
347 {
348 	TRACE("(EGLDisplay dpy = %p, EGLSurface surface = %p)", dpy, surface);
349 
350 	egl::Display *display = egl::Display::get(dpy);
351 	egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
352 
353 	if(!validateSurface(display, eglSurface))
354 	{
355 		return EGL_FALSE;
356 	}
357 
358 	if(surface == EGL_NO_SURFACE)
359 	{
360 		return error(EGL_BAD_SURFACE, EGL_FALSE);
361 	}
362 
363 	display->destroySurface((egl::Surface*)surface);
364 
365 	return success(EGL_TRUE);
366 }
367 
QuerySurface(EGLDisplay dpy,EGLSurface surface,EGLint attribute,EGLint * value)368 EGLBoolean QuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value)
369 {
370 	TRACE("(EGLDisplay dpy = %p, EGLSurface surface = %p, EGLint attribute = %d, EGLint *value = %p)",
371 	      dpy, surface, attribute, value);
372 
373 	egl::Display *display = egl::Display::get(dpy);
374 	egl::Surface *eglSurface = (egl::Surface*)surface;
375 
376 	if(!validateSurface(display, eglSurface))
377 	{
378 		return EGL_FALSE;
379 	}
380 
381 	if(surface == EGL_NO_SURFACE)
382 	{
383 		return error(EGL_BAD_SURFACE, EGL_FALSE);
384 	}
385 
386 	switch(attribute)
387 	{
388 	case EGL_VG_ALPHA_FORMAT:
389 		UNIMPLEMENTED();   // FIXME
390 		break;
391 	case EGL_VG_COLORSPACE:
392 		UNIMPLEMENTED();   // FIXME
393 		break;
394 	case EGL_CONFIG_ID:
395 		*value = eglSurface->getConfigID();
396 		break;
397 	case EGL_HEIGHT:
398 		*value = eglSurface->getHeight();
399 		break;
400 	case EGL_HORIZONTAL_RESOLUTION:
401 		UNIMPLEMENTED();   // FIXME
402 		break;
403 	case EGL_LARGEST_PBUFFER:
404 		if(eglSurface->isPBufferSurface())   // For a window or pixmap surface, the contents of *value are not modified.
405 		{
406 			*value = eglSurface->getLargestPBuffer();
407 		}
408 		break;
409 	case EGL_MIPMAP_TEXTURE:
410 		UNIMPLEMENTED();   // FIXME
411 		break;
412 	case EGL_MIPMAP_LEVEL:
413 		UNIMPLEMENTED();   // FIXME
414 		break;
415 	case EGL_MULTISAMPLE_RESOLVE:
416 		UNIMPLEMENTED();   // FIXME
417 		break;
418 	case EGL_PIXEL_ASPECT_RATIO:
419 		*value = eglSurface->getPixelAspectRatio();
420 		break;
421 	case EGL_RENDER_BUFFER:
422 		*value = eglSurface->getRenderBuffer();
423 		break;
424 	case EGL_SWAP_BEHAVIOR:
425 		*value = eglSurface->getSwapBehavior();
426 		break;
427 	case EGL_TEXTURE_FORMAT:
428 		*value = eglSurface->getTextureFormat();
429 		break;
430 	case EGL_TEXTURE_TARGET:
431 		*value = eglSurface->getTextureTarget();
432 		break;
433 	case EGL_VERTICAL_RESOLUTION:
434 		UNIMPLEMENTED();   // FIXME
435 		break;
436 	case EGL_WIDTH:
437 		*value = eglSurface->getWidth();
438 		break;
439 	default:
440 		return error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
441 	}
442 
443 	return success(EGL_TRUE);
444 }
445 
BindAPI(EGLenum api)446 EGLBoolean BindAPI(EGLenum api)
447 {
448 	TRACE("(EGLenum api = 0x%X)", api);
449 
450 	switch(api)
451 	{
452 	case EGL_OPENGL_API:
453 	case EGL_OPENVG_API:
454 		return error(EGL_BAD_PARAMETER, EGL_FALSE);   // Not supported by this implementation
455 	case EGL_OPENGL_ES_API:
456 		break;
457 	default:
458 		return error(EGL_BAD_PARAMETER, EGL_FALSE);
459 	}
460 
461 	egl::setCurrentAPI(api);
462 
463 	return success(EGL_TRUE);
464 }
465 
QueryAPI(void)466 EGLenum QueryAPI(void)
467 {
468 	TRACE("()");
469 
470 	EGLenum API = egl::getCurrentAPI();
471 
472 	return success(API);
473 }
474 
WaitClient(void)475 EGLBoolean WaitClient(void)
476 {
477 	TRACE("()");
478 
479 	UNIMPLEMENTED();   // FIXME
480 
481 	return success(EGL_FALSE);
482 }
483 
ReleaseThread(void)484 EGLBoolean ReleaseThread(void)
485 {
486 	TRACE("()");
487 
488 	eglMakeCurrent(EGL_NO_DISPLAY, EGL_NO_CONTEXT, EGL_NO_SURFACE, EGL_NO_SURFACE);
489 
490 	return success(EGL_TRUE);
491 }
492 
CreatePbufferFromClientBuffer(EGLDisplay dpy,EGLenum buftype,EGLClientBuffer buffer,EGLConfig config,const EGLint * attrib_list)493 EGLSurface CreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list)
494 {
495 	TRACE("(EGLDisplay dpy = %p, EGLenum buftype = 0x%X, EGLClientBuffer buffer = %p, "
496 	      "EGLConfig config = %p, const EGLint *attrib_list = %p)",
497 	      dpy, buftype, buffer, config, attrib_list);
498 
499 	UNIMPLEMENTED();
500 
501 	return error(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
502 }
503 
SurfaceAttrib(EGLDisplay dpy,EGLSurface surface,EGLint attribute,EGLint value)504 EGLBoolean SurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
505 {
506 	TRACE("(EGLDisplay dpy = %p, EGLSurface surface = %p, EGLint attribute = %d, EGLint value = %d)",
507 	      dpy, surface, attribute, value);
508 
509 	egl::Display *display = egl::Display::get(dpy);
510 	egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
511 
512 	if(!validateSurface(display, eglSurface))
513 	{
514 		return EGL_FALSE;
515 	}
516 
517 	switch(attribute)
518 	{
519 	case EGL_SWAP_BEHAVIOR:
520 		if(value == EGL_BUFFER_PRESERVED)
521 		{
522 			if(!(eglSurface->getSurfaceType() & EGL_SWAP_BEHAVIOR_PRESERVED_BIT))
523 			{
524 				return error(EGL_BAD_MATCH, EGL_FALSE);
525 			}
526 		}
527 		else if(value != EGL_BUFFER_DESTROYED)
528 		{
529 			return error(EGL_BAD_PARAMETER, EGL_FALSE);
530 		}
531 		eglSurface->setSwapBehavior(value);
532 		break;
533 	default:
534 		UNIMPLEMENTED();   // FIXME
535 	}
536 
537 	return success(EGL_TRUE);
538 }
539 
BindTexImage(EGLDisplay dpy,EGLSurface surface,EGLint buffer)540 EGLBoolean BindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
541 {
542 	TRACE("(EGLDisplay dpy = %p, EGLSurface surface = %p, EGLint buffer = %d)", dpy, surface, buffer);
543 
544 	egl::Display *display = egl::Display::get(dpy);
545 	egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
546 
547 	if(!validateSurface(display, eglSurface))
548 	{
549 		return EGL_FALSE;
550 	}
551 
552 	if(buffer != EGL_BACK_BUFFER)
553 	{
554 		return error(EGL_BAD_PARAMETER, EGL_FALSE);
555 	}
556 
557 	if(surface == EGL_NO_SURFACE || eglSurface->isWindowSurface())
558 	{
559 		return error(EGL_BAD_SURFACE, EGL_FALSE);
560 	}
561 
562 	if(eglSurface->getBoundTexture())
563 	{
564 		return error(EGL_BAD_ACCESS, EGL_FALSE);
565 	}
566 
567 	if(eglSurface->getTextureFormat() == EGL_NO_TEXTURE)
568 	{
569 		return error(EGL_BAD_MATCH, EGL_FALSE);
570 	}
571 
572 	egl::Context *context = egl::getCurrentContext();
573 
574 	if(context)
575 	{
576 		context->bindTexImage(eglSurface);
577 	}
578 
579 	return success(EGL_TRUE);
580 }
581 
ReleaseTexImage(EGLDisplay dpy,EGLSurface surface,EGLint buffer)582 EGLBoolean ReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
583 {
584 	TRACE("(EGLDisplay dpy = %p, EGLSurface surface = %p, EGLint buffer = %d)", dpy, surface, buffer);
585 
586 	egl::Display *display = egl::Display::get(dpy);
587 	egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
588 
589 	if(!validateSurface(display, eglSurface))
590 	{
591 		return EGL_FALSE;
592 	}
593 
594 	if(buffer != EGL_BACK_BUFFER)
595 	{
596 		return error(EGL_BAD_PARAMETER, EGL_FALSE);
597 	}
598 
599 	if(surface == EGL_NO_SURFACE || eglSurface->isWindowSurface())
600 	{
601 		return error(EGL_BAD_SURFACE, EGL_FALSE);
602 	}
603 
604 	if(eglSurface->getTextureFormat() == EGL_NO_TEXTURE)
605 	{
606 		return error(EGL_BAD_MATCH, EGL_FALSE);
607 	}
608 
609 	egl::Texture *texture = eglSurface->getBoundTexture();
610 
611 	if(texture)
612 	{
613 		texture->releaseTexImage();
614 	}
615 
616 	return success(EGL_TRUE);
617 }
618 
SwapInterval(EGLDisplay dpy,EGLint interval)619 EGLBoolean SwapInterval(EGLDisplay dpy, EGLint interval)
620 {
621 	TRACE("(EGLDisplay dpy = %p, EGLint interval = %d)", dpy, interval);
622 
623 	egl::Display *display = egl::Display::get(dpy);
624 	egl::Context *context = egl::getCurrentContext();
625 
626 	if(!validateContext(display, context))
627 	{
628 		return EGL_FALSE;
629 	}
630 
631 	egl::Surface *draw_surface = static_cast<egl::Surface*>(egl::getCurrentDrawSurface());
632 
633 	if(!draw_surface)
634 	{
635 		return error(EGL_BAD_SURFACE, EGL_FALSE);
636 	}
637 
638 	draw_surface->setSwapInterval(interval);
639 
640 	return success(EGL_TRUE);
641 }
642 
CreateContext(EGLDisplay dpy,EGLConfig config,EGLContext share_context,const EGLint * attrib_list)643 EGLContext CreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list)
644 {
645 	TRACE("(EGLDisplay dpy = %p, EGLConfig config = %p, EGLContext share_context = %p, "
646 	      "const EGLint *attrib_list = %p)", dpy, config, share_context, attrib_list);
647 
648 	EGLint majorVersion = 1;
649 	EGLint minorVersion = 0;
650 
651 	if(attrib_list)
652 	{
653 		for(const EGLint* attribute = attrib_list; attribute[0] != EGL_NONE; attribute += 2)
654 		{
655 			switch(attribute[0])
656 			{
657 			case EGL_CONTEXT_MAJOR_VERSION_KHR:   // This token is an alias for EGL_CONTEXT_CLIENT_VERSION
658 				majorVersion = attribute[1];
659 				break;
660 			case EGL_CONTEXT_MINOR_VERSION_KHR:
661 				minorVersion = attribute[1];
662 				break;
663 			case EGL_CONTEXT_FLAGS_KHR:
664 				switch(attribute[1])
665 				{
666 				case EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR:
667 					// According to the EGL_KHR_create_context spec:
668 					// "Khronos is still defining the expected and required features of debug contexts, so
669 					//  implementations are currently free to implement "debug contexts" with little or no debug
670 					//  functionality. However, OpenGL and OpenGL ES implementations supporting the GL_KHR_debug
671 					//  extension should enable it when this bit is set."
672 					break;
673 				case EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR:
674 				case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR:
675 					// These bits are for OpenGL contexts only, not OpenGL ES contexts
676 					return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
677 				default:
678 					return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
679 				}
680 				break;
681 			case EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR:
682 				switch(attribute[1])
683 				{
684 				case EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR:
685 				case EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR:
686 					// These bits are for OpenGL contexts only, not OpenGL ES contexts
687 					return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
688 				default:
689 					return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
690 				}
691 				break;
692 			case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR:
693 				switch(attribute[1])
694 				{
695 				case EGL_NO_RESET_NOTIFICATION_KHR:
696 				case EGL_LOSE_CONTEXT_ON_RESET_KHR:
697 					// These bits are for OpenGL contexts only, not OpenGL ES contexts
698 					return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
699 				default:
700 					return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
701 				}
702 				break;
703 			default:
704 				return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
705 			}
706 		}
707 	}
708 
709 	switch(majorVersion)
710 	{
711 	case 1:
712 		if(minorVersion != 0 && minorVersion != 1)
713 		{
714 			// 1.X: Only OpenGL ES 1.0 and 1.1 contexts are supported
715 			return error(EGL_BAD_MATCH, EGL_NO_CONTEXT);
716 		}
717 		break;
718 	case 2:
719 	case 3:
720 		if(minorVersion != 0)
721 		{
722 			// 2.X and 3.X: Only OpenGL ES 2.0 and 3.0 contexts are currently supported
723 			return error(EGL_BAD_MATCH, EGL_NO_CONTEXT);
724 		}
725 		break;
726 	default:
727 		return error(EGL_BAD_MATCH, EGL_NO_CONTEXT);
728 	}
729 
730 	egl::Display *display = egl::Display::get(dpy);
731 	egl::Context *shareContext = static_cast<egl::Context*>(share_context);
732 
733 	if(!validateConfig(display, config))
734 	{
735 		return EGL_NO_CONTEXT;
736 	}
737 
738 	if(shareContext && shareContext->getClientVersion() != majorVersion)
739 	{
740 		return error(EGL_BAD_CONTEXT, EGL_NO_CONTEXT);
741 	}
742 
743 	return display->createContext(config, shareContext, majorVersion);
744 }
745 
DestroyContext(EGLDisplay dpy,EGLContext ctx)746 EGLBoolean DestroyContext(EGLDisplay dpy, EGLContext ctx)
747 {
748 	TRACE("(EGLDisplay dpy = %p, EGLContext ctx = %p)", dpy, ctx);
749 
750 	egl::Display *display = egl::Display::get(dpy);
751 	egl::Context *context = static_cast<egl::Context*>(ctx);
752 
753 	if(!validateContext(display, context))
754 	{
755 		return EGL_FALSE;
756 	}
757 
758 	if(ctx == EGL_NO_CONTEXT)
759 	{
760 		return error(EGL_BAD_CONTEXT, EGL_FALSE);
761 	}
762 
763 	display->destroyContext(context);
764 
765 	return success(EGL_TRUE);
766 }
767 
MakeCurrent(EGLDisplay dpy,EGLSurface draw,EGLSurface read,EGLContext ctx)768 EGLBoolean MakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx)
769 {
770 	TRACE("(EGLDisplay dpy = %p, EGLSurface draw = %p, EGLSurface read = %p, EGLContext ctx = %p)",
771 	      dpy, draw, read, ctx);
772 
773 	egl::Display *display = egl::Display::get(dpy);
774 	egl::Context *context = static_cast<egl::Context*>(ctx);
775 	egl::Surface *drawSurface = static_cast<egl::Surface*>(draw);
776 	egl::Surface *readSurface = static_cast<egl::Surface*>(read);
777 
778 	if(ctx != EGL_NO_CONTEXT || draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE)
779 	{
780 		if(!validateDisplay(display))
781 		{
782 			return EGL_FALSE;
783 		}
784 	}
785 
786 	if(ctx == EGL_NO_CONTEXT && (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE))
787 	{
788 		return error(EGL_BAD_MATCH, EGL_FALSE);
789 	}
790 
791 	if(ctx != EGL_NO_CONTEXT && !validateContext(display, context))
792 	{
793 		return EGL_FALSE;
794 	}
795 
796 	if((draw != EGL_NO_SURFACE && !validateSurface(display, drawSurface)) ||
797 	   (read != EGL_NO_SURFACE && !validateSurface(display, readSurface)))
798 	{
799 		return EGL_FALSE;
800 	}
801 
802 	if((draw != EGL_NO_SURFACE) ^ (read != EGL_NO_SURFACE))
803 	{
804 		return error(EGL_BAD_MATCH, EGL_FALSE);
805 	}
806 
807 	if(draw != read)
808 	{
809 		UNIMPLEMENTED();   // FIXME
810 	}
811 
812 	egl::setCurrentDisplay(dpy);
813 	egl::setCurrentDrawSurface(drawSurface);
814 	egl::setCurrentReadSurface(readSurface);
815 	egl::setCurrentContext(context);
816 
817 	if(context)
818 	{
819 		context->makeCurrent(drawSurface);
820 	}
821 
822 	return success(EGL_TRUE);
823 }
824 
GetCurrentContext(void)825 EGLContext GetCurrentContext(void)
826 {
827 	TRACE("()");
828 
829 	EGLContext context = egl::getCurrentContext();
830 
831 	return success(context);
832 }
833 
GetCurrentSurface(EGLint readdraw)834 EGLSurface GetCurrentSurface(EGLint readdraw)
835 {
836 	TRACE("(EGLint readdraw = %d)", readdraw);
837 
838 	if(readdraw == EGL_READ)
839 	{
840 		EGLSurface read = egl::getCurrentReadSurface();
841 		return success(read);
842 	}
843 	else if(readdraw == EGL_DRAW)
844 	{
845 		EGLSurface draw = egl::getCurrentDrawSurface();
846 		return success(draw);
847 	}
848 	else
849 	{
850 		return error(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
851 	}
852 }
853 
GetCurrentDisplay(void)854 EGLDisplay GetCurrentDisplay(void)
855 {
856 	TRACE("()");
857 
858 	return success(egl::getCurrentDisplay());
859 }
860 
QueryContext(EGLDisplay dpy,EGLContext ctx,EGLint attribute,EGLint * value)861 EGLBoolean QueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value)
862 {
863 	TRACE("(EGLDisplay dpy = %p, EGLContext ctx = %p, EGLint attribute = %d, EGLint *value = %p)",
864 	      dpy, ctx, attribute, value);
865 
866 	egl::Display *display = egl::Display::get(dpy);
867 	egl::Context *context = static_cast<egl::Context*>(ctx);
868 
869 	if(!validateContext(display, context))
870 	{
871 		return EGL_FALSE;
872 	}
873 
874 	UNIMPLEMENTED();   // FIXME
875 
876 	return success(0);
877 }
878 
WaitGL(void)879 EGLBoolean WaitGL(void)
880 {
881 	TRACE("()");
882 
883 	UNIMPLEMENTED();   // FIXME
884 
885 	return success(EGL_FALSE);
886 }
887 
WaitNative(EGLint engine)888 EGLBoolean WaitNative(EGLint engine)
889 {
890 	TRACE("(EGLint engine = %d)", engine);
891 
892 	UNIMPLEMENTED();   // FIXME
893 
894 	return success(EGL_FALSE);
895 }
896 
SwapBuffers(EGLDisplay dpy,EGLSurface surface)897 EGLBoolean SwapBuffers(EGLDisplay dpy, EGLSurface surface)
898 {
899 	TRACE("(EGLDisplay dpy = %p, EGLSurface surface = %p)", dpy, surface);
900 
901 	egl::Display *display = egl::Display::get(dpy);
902 	egl::Surface *eglSurface = (egl::Surface*)surface;
903 
904 	if(!validateSurface(display, eglSurface))
905 	{
906 		return EGL_FALSE;
907 	}
908 
909 	if(surface == EGL_NO_SURFACE)
910 	{
911 		return error(EGL_BAD_SURFACE, EGL_FALSE);
912 	}
913 
914 	eglSurface->swap();
915 
916 	return success(EGL_TRUE);
917 }
918 
CopyBuffers(EGLDisplay dpy,EGLSurface surface,EGLNativePixmapType target)919 EGLBoolean CopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target)
920 {
921 	TRACE("(EGLDisplay dpy = %p, EGLSurface surface = %p, EGLNativePixmapType target = %p)", dpy, surface, target);
922 
923 	egl::Display *display = egl::Display::get(dpy);
924 	egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
925 
926 	if(!validateSurface(display, eglSurface))
927 	{
928 		return EGL_FALSE;
929 	}
930 
931 	UNIMPLEMENTED();   // FIXME
932 
933 	return success(EGL_FALSE);
934 }
935 
CreateImageKHR(EGLDisplay dpy,EGLContext ctx,EGLenum target,EGLClientBuffer buffer,const EGLint * attrib_list)936 EGLImageKHR CreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list)
937 {
938 	TRACE("(EGLDisplay dpy = %p, EGLContext ctx = %p, EGLenum target = 0x%X, buffer = %p, const EGLint attrib_list = %p)", dpy, ctx, target, buffer, attrib_list);
939 
940 	egl::Display *display = egl::Display::get(dpy);
941 	egl::Context *context = static_cast<egl::Context*>(ctx);
942 
943 	if(!validateDisplay(display))
944 	{
945 		return error(EGL_BAD_DISPLAY, EGL_NO_IMAGE_KHR);
946 	}
947 
948 	if(context != EGL_NO_CONTEXT && !display->isValidContext(context))
949 	{
950 		return error(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
951 	}
952 
953 	EGLenum imagePreserved = EGL_FALSE;
954 	GLuint textureLevel = 0;
955 	if(attrib_list)
956 	{
957 		for(const EGLint *attribute = attrib_list; attribute[0] != EGL_NONE; attribute += 2)
958 		{
959 			if(attribute[0] == EGL_IMAGE_PRESERVED_KHR)
960 			{
961 				imagePreserved = attribute[1];
962 			}
963 			else if(attribute[0] == EGL_GL_TEXTURE_LEVEL_KHR)
964 			{
965 				textureLevel = attribute[1];
966 			}
967 			else
968 			{
969 				return error(EGL_BAD_ATTRIBUTE, EGL_NO_IMAGE_KHR);
970 			}
971 		}
972 	}
973 
974 	#if defined(__ANDROID__)
975 		if(target == EGL_NATIVE_BUFFER_ANDROID)
976 		{
977 			ANativeWindowBuffer *nativeBuffer = reinterpret_cast<ANativeWindowBuffer*>(buffer);
978 
979 			if(!nativeBuffer || GLPixelFormatFromAndroid(nativeBuffer->format) == GL_NONE)
980 			{
981 				ALOGW("%s badness unsupported HAL format=%x", __FUNCTION__, nativeBuffer ? nativeBuffer->format : 0);
982 				return error(EGL_BAD_ATTRIBUTE, EGL_NO_IMAGE_KHR);
983 			}
984 
985 			return success(new AndroidNativeImage(nativeBuffer));
986 		}
987 	#endif
988 
989 	GLuint name = reinterpret_cast<intptr_t>(buffer);
990 
991 	if(name == 0)
992 	{
993 		return error(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
994 	}
995 
996 	EGLenum validationResult = context->validateSharedImage(target, name, textureLevel);
997 
998 	if(validationResult != EGL_SUCCESS)
999 	{
1000 		return error(validationResult, EGL_NO_IMAGE_KHR);
1001 	}
1002 
1003 	egl::Image *image = context->createSharedImage(target, name, textureLevel);
1004 
1005 	if(!image)
1006 	{
1007 		return error(EGL_BAD_MATCH, EGL_NO_IMAGE_KHR);
1008 	}
1009 
1010 	if(image->getDepth() > 1)
1011 	{
1012 		return error(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
1013 	}
1014 
1015 	return success((EGLImageKHR)image);
1016 }
1017 
DestroyImageKHR(EGLDisplay dpy,EGLImageKHR image)1018 EGLBoolean DestroyImageKHR(EGLDisplay dpy, EGLImageKHR image)
1019 {
1020 	TRACE("(EGLDisplay dpy = %p, EGLImageKHR image = %p)", dpy, image);
1021 
1022 	egl::Display *display = egl::Display::get(dpy);
1023 
1024 	if(!validateDisplay(display))
1025 	{
1026 		return error(EGL_BAD_DISPLAY, EGL_FALSE);
1027 	}
1028 
1029 	if(!image)
1030 	{
1031 		return error(EGL_BAD_PARAMETER, EGL_FALSE);
1032 	}
1033 
1034 	egl::Image *glImage = static_cast<egl::Image*>(image);
1035 	glImage->destroyShared();
1036 
1037 	return success(EGL_TRUE);
1038 }
1039 
GetPlatformDisplayEXT(EGLenum platform,void * native_display,const EGLint * attrib_list)1040 EGLDisplay GetPlatformDisplayEXT(EGLenum platform, void *native_display, const EGLint *attrib_list)
1041 {
1042 	TRACE("(EGLenum platform = 0x%X, void *native_display = %p, const EGLint *attrib_list = %p)", platform, native_display, attrib_list);
1043 
1044 	switch(platform)
1045 	{
1046 	#if defined(__linux__) && !defined(__ANDROID__)
1047 	case EGL_PLATFORM_X11_EXT: break;
1048 	case EGL_PLATFORM_GBM_KHR: break;
1049 	#endif
1050 	default:
1051 		return error(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
1052 	}
1053 
1054 	#if defined(__linux__) && !defined(__ANDROID__)
1055 		if(platform == EGL_PLATFORM_X11_EXT)
1056 		{
1057 			if(!libX11)
1058 			{
1059 				return error(EGL_BAD_ATTRIBUTE, EGL_NO_DISPLAY);
1060 			}
1061 
1062 			if(native_display != (void*)EGL_DEFAULT_DISPLAY || attrib_list != NULL)
1063 			{
1064 				return error(EGL_BAD_ATTRIBUTE, EGL_NO_DISPLAY);   // Unimplemented
1065 			}
1066 		}
1067 		else if(platform == EGL_PLATFORM_GBM_KHR)
1068 		{
1069 			if(native_display != (void*)EGL_DEFAULT_DISPLAY || attrib_list != NULL)
1070 			{
1071 				return error(EGL_BAD_ATTRIBUTE, EGL_NO_DISPLAY);   // Unimplemented
1072 			}
1073 
1074 			return success(HEADLESS_DISPLAY);
1075 		}
1076 	#endif
1077 
1078 	return success(PRIMARY_DISPLAY);   // We only support the default display
1079 }
1080 
CreatePlatformWindowSurfaceEXT(EGLDisplay dpy,EGLConfig config,void * native_window,const EGLint * attrib_list)1081 EGLSurface CreatePlatformWindowSurfaceEXT(EGLDisplay dpy, EGLConfig config, void *native_window, const EGLint *attrib_list)
1082 {
1083 	return CreateWindowSurface(dpy, config, (EGLNativeWindowType)native_window, attrib_list);
1084 }
1085 
CreatePlatformPixmapSurfaceEXT(EGLDisplay dpy,EGLConfig config,void * native_pixmap,const EGLint * attrib_list)1086 EGLSurface CreatePlatformPixmapSurfaceEXT(EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLint *attrib_list)
1087 {
1088 	return CreatePixmapSurface(dpy, config, (EGLNativePixmapType)native_pixmap, attrib_list);
1089 }
1090 
CreateSyncKHR(EGLDisplay dpy,EGLenum type,const EGLint * attrib_list)1091 EGLSyncKHR CreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
1092 {
1093 	TRACE("(EGLDisplay dpy = %p, EGLunum type = %x, EGLint *attrib_list=%p)", dpy, type, attrib_list);
1094 
1095 	egl::Display *display = egl::Display::get(dpy);
1096 
1097 	if(!validateDisplay(display))
1098 	{
1099 		return error(EGL_BAD_DISPLAY, EGL_NO_SYNC_KHR);
1100 	}
1101 
1102 	if(type != EGL_SYNC_FENCE_KHR)
1103 	{
1104 		return error(EGL_BAD_ATTRIBUTE, EGL_NO_SYNC_KHR);
1105 	}
1106 
1107 	if(attrib_list && attrib_list[0] != EGL_NONE)
1108 	{
1109 		return error(EGL_BAD_ATTRIBUTE, EGL_NO_SYNC_KHR);
1110 	}
1111 
1112 	egl::Context *context = egl::getCurrentContext();
1113 
1114 	if(!validateContext(display, context))
1115 	{
1116 		return error(EGL_BAD_MATCH, EGL_NO_SYNC_KHR);
1117 	}
1118 
1119 	EGLSyncKHR sync = display->createSync(context);
1120 
1121 	return success(sync);
1122 }
1123 
DestroySyncKHR(EGLDisplay dpy,EGLSyncKHR sync)1124 EGLBoolean DestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
1125 {
1126 	TRACE("(EGLDisplay dpy = %p, EGLSyncKHR sync = %p)", dpy, sync);
1127 
1128 	egl::Display *display = egl::Display::get(dpy);
1129 	FenceSync *eglSync = static_cast<FenceSync*>(sync);
1130 
1131 	if(!validateDisplay(display))
1132 	{
1133 		return error(EGL_BAD_DISPLAY, EGL_FALSE);
1134 	}
1135 
1136 	if(!display->isValidSync(eglSync))
1137 	{
1138 		return error(EGL_BAD_PARAMETER, EGL_FALSE);
1139 	}
1140 
1141 	display->destroySync(eglSync);
1142 
1143 	return success(EGL_TRUE);
1144 }
1145 
ClientWaitSyncKHR(EGLDisplay dpy,EGLSyncKHR sync,EGLint flags,EGLTimeKHR timeout)1146 EGLint ClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout)
1147 {
1148 	TRACE("(EGLDisplay dpy = %p, EGLSyncKHR sync = %p, EGLint flags = %x, EGLTimeKHR value = %llx)", dpy, sync, flags, timeout);
1149 
1150 	egl::Display *display = egl::Display::get(dpy);
1151 	FenceSync *eglSync = static_cast<FenceSync*>(sync);
1152 
1153 	if(!validateDisplay(display))
1154 	{
1155 		return error(EGL_BAD_DISPLAY, EGL_FALSE);
1156 	}
1157 
1158 	if(!display->isValidSync(eglSync))
1159 	{
1160 		return error(EGL_BAD_PARAMETER, EGL_FALSE);
1161 	}
1162 
1163 	(void)flags;
1164 	(void)timeout;
1165 
1166 	if(!eglSync->isSignaled())
1167 	{
1168 		eglSync->wait();
1169 	}
1170 
1171 	return success(EGL_CONDITION_SATISFIED_KHR);
1172 }
1173 
GetSyncAttribKHR(EGLDisplay dpy,EGLSyncKHR sync,EGLint attribute,EGLint * value)1174 EGLBoolean GetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value)
1175 {
1176 	TRACE("(EGLDisplay dpy = %p, EGLSyncKHR sync = %p, EGLint attribute = %x, EGLint *value = %p)", dpy, sync, attribute, value);
1177 
1178 	egl::Display *display = egl::Display::get(dpy);
1179 	FenceSync *eglSync = static_cast<FenceSync*>(sync);
1180 
1181 	if(!validateDisplay(display))
1182 	{
1183 		return error(EGL_BAD_DISPLAY, EGL_FALSE);
1184 	}
1185 
1186 	if(!display->isValidSync(eglSync))
1187 	{
1188 		return error(EGL_BAD_PARAMETER, EGL_FALSE);
1189 	}
1190 
1191 	switch(attribute)
1192 	{
1193 	case EGL_SYNC_TYPE_KHR:
1194 		*value = EGL_SYNC_FENCE_KHR;
1195 		return success(EGL_TRUE);
1196 	case EGL_SYNC_STATUS_KHR:
1197 		eglSync->wait();   // TODO: Don't block. Just poll based on sw::Query.
1198 		*value = eglSync->isSignaled() ? EGL_SIGNALED_KHR : EGL_UNSIGNALED_KHR;
1199 		return success(EGL_TRUE);
1200 	case EGL_SYNC_CONDITION_KHR:
1201 		*value = EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR;
1202 		return success(EGL_TRUE);
1203 	default:
1204 		return error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
1205 	}
1206 }
1207 
GetProcAddress(const char * procname)1208 __eglMustCastToProperFunctionPointerType GetProcAddress(const char *procname)
1209 {
1210 	TRACE("(const char *procname = \"%s\")", procname);
1211 
1212 	struct Extension
1213 	{
1214 		const char *name;
1215 		__eglMustCastToProperFunctionPointerType address;
1216 	};
1217 
1218 	static const Extension eglExtensions[] =
1219 	{
1220 		#define EXTENSION(name) {#name, (__eglMustCastToProperFunctionPointerType)name}
1221 
1222 		EXTENSION(eglCreateImageKHR),
1223 		EXTENSION(eglDestroyImageKHR),
1224 		EXTENSION(eglGetPlatformDisplayEXT),
1225 		EXTENSION(eglCreatePlatformWindowSurfaceEXT),
1226 		EXTENSION(eglCreatePlatformPixmapSurfaceEXT),
1227 		EXTENSION(eglCreateSyncKHR),
1228 		EXTENSION(eglDestroySyncKHR),
1229 		EXTENSION(eglClientWaitSyncKHR),
1230 		EXTENSION(eglGetSyncAttribKHR),
1231 
1232 		#undef EXTENSION
1233 	};
1234 
1235 	for(unsigned int ext = 0; ext < sizeof(eglExtensions) / sizeof(Extension); ext++)
1236 	{
1237 		if(strcmp(procname, eglExtensions[ext].name) == 0)
1238 		{
1239 			return success((__eglMustCastToProperFunctionPointerType)eglExtensions[ext].address);
1240 		}
1241 	}
1242 
1243 	if(libGLESv2)
1244 	{
1245 		__eglMustCastToProperFunctionPointerType proc = libGLESv2->es2GetProcAddress(procname);
1246 		if(proc) return success(proc);
1247 	}
1248 
1249 	if(libGLES_CM)
1250 	{
1251 		__eglMustCastToProperFunctionPointerType proc =  libGLES_CM->es1GetProcAddress(procname);
1252 		if(proc) return success(proc);
1253 	}
1254 
1255 	return success((__eglMustCastToProperFunctionPointerType)NULL);
1256 }
1257 }
1258