blob: c2ef7afe4a7855cee82be467eb8a79d562005e33 [file] [log] [blame]
Mathias Agopian518ec112011-05-13 16:21:08 -07001/*
2 ** Copyright 2007, The Android Open Source Project
3 **
4 ** Licensed under the Apache License, Version 2.0 (the "License");
5 ** you may not use this file except in compliance with the License.
6 ** You may obtain a copy of the License at
7 **
8 ** http://www.apache.org/licenses/LICENSE-2.0
9 **
10 ** Unless required by applicable law or agreed to in writing, software
11 ** distributed under the License is distributed on an "AS IS" BASIS,
12 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 ** See the License for the specific language governing permissions and
14 ** limitations under the License.
15 */
16
17#include <ctype.h>
18#include <stdlib.h>
19#include <string.h>
20
21#include <hardware/gralloc.h>
22#include <system/window.h>
23
24#include <EGL/egl.h>
25#include <EGL/eglext.h>
26#include <GLES/gl.h>
27#include <GLES/glext.h>
28
29#include <cutils/log.h>
30#include <cutils/atomic.h>
31#include <cutils/properties.h>
32#include <cutils/memory.h>
33
34#include <utils/KeyedVector.h>
35#include <utils/SortedVector.h>
36#include <utils/String8.h>
37
38#include "egl_impl.h"
39#include "egl_tls.h"
Siva Velusamy0469dd62011-11-30 15:05:37 -080040#include "glestrace.h"
Mathias Agopian518ec112011-05-13 16:21:08 -070041#include "hooks.h"
42
43#include "egl_display.h"
44#include "egl_impl.h"
45#include "egl_object.h"
46#include "egl_tls.h"
Mathias Agopianada798b2012-02-13 17:09:30 -080047#include "egldefs.h"
Mathias Agopian518ec112011-05-13 16:21:08 -070048
49using namespace android;
50
51// ----------------------------------------------------------------------------
52
Mathias Agopianbc2d79e2011-11-29 17:55:46 -080053#define EGL_VERSION_HW_ANDROID 0x3143
54
Mathias Agopian518ec112011-05-13 16:21:08 -070055struct extention_map_t {
56 const char* name;
57 __eglMustCastToProperFunctionPointerType address;
58};
59
60static const extention_map_t sExtentionMap[] = {
61 { "eglLockSurfaceKHR",
62 (__eglMustCastToProperFunctionPointerType)&eglLockSurfaceKHR },
63 { "eglUnlockSurfaceKHR",
64 (__eglMustCastToProperFunctionPointerType)&eglUnlockSurfaceKHR },
65 { "eglCreateImageKHR",
66 (__eglMustCastToProperFunctionPointerType)&eglCreateImageKHR },
67 { "eglDestroyImageKHR",
68 (__eglMustCastToProperFunctionPointerType)&eglDestroyImageKHR },
Jonas Yang1c3d72a2011-08-26 20:04:39 +080069 { "eglGetSystemTimeFrequencyNV",
70 (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeFrequencyNV },
71 { "eglGetSystemTimeNV",
72 (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeNV },
Mathias Agopian518ec112011-05-13 16:21:08 -070073};
74
75// accesses protected by sExtensionMapMutex
76static DefaultKeyedVector<String8, __eglMustCastToProperFunctionPointerType> sGLExtentionMap;
77static int sGLExtentionSlot = 0;
78static pthread_mutex_t sExtensionMapMutex = PTHREAD_MUTEX_INITIALIZER;
79
80static void(*findProcAddress(const char* name,
81 const extention_map_t* map, size_t n))() {
82 for (uint32_t i=0 ; i<n ; i++) {
83 if (!strcmp(name, map[i].name)) {
84 return map[i].address;
85 }
86 }
87 return NULL;
88}
89
90// ----------------------------------------------------------------------------
91
92template<typename T>
93static __attribute__((noinline))
94int binarySearch(T const sortedArray[], int first, int last, T key) {
95 while (first <= last) {
96 int mid = (first + last) / 2;
97 if (sortedArray[mid] < key) {
98 first = mid + 1;
99 } else if (key < sortedArray[mid]) {
100 last = mid - 1;
101 } else {
102 return mid;
103 }
104 }
105 return -1;
106}
107
108// ----------------------------------------------------------------------------
109
110namespace android {
111extern void setGLHooksThreadSpecific(gl_hooks_t const *value);
112extern EGLBoolean egl_init_drivers();
113extern const __eglMustCastToProperFunctionPointerType gExtensionForwarders[MAX_NUMBER_OF_GL_EXTENSIONS];
114extern int gEGLDebugLevel;
115extern gl_hooks_t gHooksTrace;
Mathias Agopian518ec112011-05-13 16:21:08 -0700116} // namespace android;
117
118// ----------------------------------------------------------------------------
119
120static inline void clearError() { egl_tls_t::clearError(); }
121static inline EGLContext getContext() { return egl_tls_t::getContext(); }
122
123// ----------------------------------------------------------------------------
124
125EGLDisplay eglGetDisplay(EGLNativeDisplayType display)
126{
127 clearError();
128
129 uint32_t index = uint32_t(display);
130 if (index >= NUM_DISPLAYS) {
131 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
132 }
133
134 if (egl_init_drivers() == EGL_FALSE) {
135 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
136 }
137
138 EGLDisplay dpy = egl_display_t::getFromNativeDisplay(display);
139 return dpy;
140}
141
142// ----------------------------------------------------------------------------
143// Initialization
144// ----------------------------------------------------------------------------
145
146EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
147{
148 clearError();
149
150 egl_display_t * const dp = get_display(dpy);
151 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
152
153 EGLBoolean res = dp->initialize(major, minor);
154
155 return res;
156}
157
158EGLBoolean eglTerminate(EGLDisplay dpy)
159{
160 // NOTE: don't unload the drivers b/c some APIs can be called
161 // after eglTerminate() has been called. eglTerminate() only
162 // terminates an EGLDisplay, not a EGL itself.
163
164 clearError();
165
166 egl_display_t* const dp = get_display(dpy);
167 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
168
169 EGLBoolean res = dp->terminate();
170
171 return res;
172}
173
174// ----------------------------------------------------------------------------
175// configuration
176// ----------------------------------------------------------------------------
177
178EGLBoolean eglGetConfigs( EGLDisplay dpy,
179 EGLConfig *configs,
180 EGLint config_size, EGLint *num_config)
181{
182 clearError();
183
184 egl_display_t const * const dp = validate_display(dpy);
185 if (!dp) return EGL_FALSE;
186
187 GLint numConfigs = dp->numTotalConfigs;
188 if (!configs) {
189 *num_config = numConfigs;
190 return EGL_TRUE;
191 }
192
193 GLint n = 0;
194 for (intptr_t i=0 ; i<dp->numTotalConfigs && config_size ; i++) {
195 *configs++ = EGLConfig(i);
196 config_size--;
197 n++;
198 }
199
200 *num_config = n;
201 return EGL_TRUE;
202}
203
204EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list,
205 EGLConfig *configs, EGLint config_size,
206 EGLint *num_config)
207{
208 clearError();
209
210 egl_display_t const * const dp = validate_display(dpy);
211 if (!dp) return EGL_FALSE;
212
213 if (num_config==0) {
214 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
215 }
216
217 EGLint n;
218 EGLBoolean res = EGL_FALSE;
219 *num_config = 0;
220
221
222 // It is unfortunate, but we need to remap the EGL_CONFIG_IDs,
223 // to do this, we have to go through the attrib_list array once
224 // to figure out both its size and if it contains an EGL_CONFIG_ID
225 // key. If so, the full array is copied and patched.
226 // NOTE: we assume that there can be only one occurrence
227 // of EGL_CONFIG_ID.
228
229 EGLint patch_index = -1;
230 GLint attr;
231 size_t size = 0;
232 if (attrib_list) {
233 while ((attr=attrib_list[size]) != EGL_NONE) {
234 if (attr == EGL_CONFIG_ID)
235 patch_index = size;
236 size += 2;
237 }
238 }
239 if (patch_index >= 0) {
240 size += 2; // we need copy the sentinel as well
241 EGLint* new_list = (EGLint*)malloc(size*sizeof(EGLint));
242 if (new_list == 0)
243 return setError(EGL_BAD_ALLOC, EGL_FALSE);
244 memcpy(new_list, attrib_list, size*sizeof(EGLint));
245
246 // patch the requested EGL_CONFIG_ID
247 bool found = false;
248 EGLConfig ourConfig(0);
249 EGLint& configId(new_list[patch_index+1]);
250 for (intptr_t i=0 ; i<dp->numTotalConfigs ; i++) {
251 if (dp->configs[i].configId == configId) {
252 ourConfig = EGLConfig(i);
253 configId = dp->configs[i].implConfigId;
254 found = true;
255 break;
256 }
257 }
258
Mathias Agopianada798b2012-02-13 17:09:30 -0800259 egl_connection_t* const cnx = &gEGLImpl;
Mathias Agopian518ec112011-05-13 16:21:08 -0700260 if (found && cnx->dso) {
261 // and switch to the new list
262 attrib_list = const_cast<const EGLint *>(new_list);
263
264 // At this point, the only configuration that can match is
265 // dp->configs[i][index], however, we don't know if it would be
266 // rejected because of the other attributes, so we do have to call
267 // cnx->egl.eglChooseConfig() -- but we don't have to loop
268 // through all the EGLimpl[].
269 // We also know we can only get a single config back, and we know
270 // which one.
271
272 res = cnx->egl.eglChooseConfig(
Mathias Agopianada798b2012-02-13 17:09:30 -0800273 dp->disp.dpy,
Mathias Agopian518ec112011-05-13 16:21:08 -0700274 attrib_list, configs, config_size, &n);
275 if (res && n>0) {
276 // n has to be 0 or 1, by construction, and we already know
277 // which config it will return (since there can be only one).
278 if (configs) {
279 configs[0] = ourConfig;
280 }
281 *num_config = 1;
282 }
283 }
284
285 free(const_cast<EGLint *>(attrib_list));
286 return res;
287 }
288
289
Mathias Agopianada798b2012-02-13 17:09:30 -0800290 egl_connection_t* const cnx = &gEGLImpl;
291 if (cnx->dso) {
292 if (cnx->egl.eglChooseConfig(
293 dp->disp.dpy, attrib_list, configs, config_size, &n)) {
294 if (configs) {
295 // now we need to convert these client EGLConfig to our
296 // internal EGLConfig format.
297 // This is done in O(n Log(n)) time.
298 for (int j=0 ; j<n ; j++) {
299 egl_config_t key(configs[j]);
300 intptr_t index = binarySearch<egl_config_t>(
301 dp->configs, 0, dp->numTotalConfigs, key);
302 if (index >= 0) {
303 configs[j] = EGLConfig(index);
304 } else {
305 return setError(EGL_BAD_CONFIG, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700306 }
Mathias Agopian518ec112011-05-13 16:21:08 -0700307 }
Mathias Agopianada798b2012-02-13 17:09:30 -0800308 configs += n;
309 config_size -= n;
Mathias Agopian518ec112011-05-13 16:21:08 -0700310 }
Mathias Agopianada798b2012-02-13 17:09:30 -0800311 *num_config += n;
312 res = EGL_TRUE;
Mathias Agopian518ec112011-05-13 16:21:08 -0700313 }
314 }
Mathias Agopianada798b2012-02-13 17:09:30 -0800315
Mathias Agopian518ec112011-05-13 16:21:08 -0700316 return res;
317}
318
319EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
320 EGLint attribute, EGLint *value)
321{
322 clearError();
323
324 egl_display_t const* dp = 0;
325 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
326 if (!cnx) return EGL_FALSE;
327
328 if (attribute == EGL_CONFIG_ID) {
329 *value = dp->configs[intptr_t(config)].configId;
330 return EGL_TRUE;
331 }
332 return cnx->egl.eglGetConfigAttrib(
Mathias Agopianada798b2012-02-13 17:09:30 -0800333 dp->disp.dpy,
Mathias Agopian518ec112011-05-13 16:21:08 -0700334 dp->configs[intptr_t(config)].config, attribute, value);
335}
336
337// ----------------------------------------------------------------------------
338// surfaces
339// ----------------------------------------------------------------------------
340
341EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config,
342 NativeWindowType window,
343 const EGLint *attrib_list)
344{
345 clearError();
346
347 egl_display_t const* dp = 0;
348 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
349 if (cnx) {
Mathias Agopianada798b2012-02-13 17:09:30 -0800350 EGLDisplay iDpy = dp->disp.dpy;
Mathias Agopian518ec112011-05-13 16:21:08 -0700351 EGLConfig iConfig = dp->configs[intptr_t(config)].config;
352 EGLint format;
353
Mathias Agopian81a63352011-07-29 17:55:48 -0700354 if (native_window_api_connect(window, NATIVE_WINDOW_API_EGL) != OK) {
Steve Blocke6f43dd2012-01-06 19:20:56 +0000355 ALOGE("EGLNativeWindowType %p already connected to another API",
Mathias Agopian81a63352011-07-29 17:55:48 -0700356 window);
357 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
358 }
359
Mathias Agopian518ec112011-05-13 16:21:08 -0700360 // set the native window's buffers format to match this config
361 if (cnx->egl.eglGetConfigAttrib(iDpy,
362 iConfig, EGL_NATIVE_VISUAL_ID, &format)) {
363 if (format != 0) {
Jamie Gennisbee205f2011-07-01 13:12:07 -0700364 int err = native_window_set_buffers_format(window, format);
365 if (err != 0) {
Steve Blocke6f43dd2012-01-06 19:20:56 +0000366 ALOGE("error setting native window pixel format: %s (%d)",
Jamie Gennisbee205f2011-07-01 13:12:07 -0700367 strerror(-err), err);
Mathias Agopian81a63352011-07-29 17:55:48 -0700368 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
Jamie Gennisbee205f2011-07-01 13:12:07 -0700369 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
370 }
Mathias Agopian518ec112011-05-13 16:21:08 -0700371 }
372 }
373
Jamie Gennis59769462011-11-19 18:04:43 -0800374 // the EGL spec requires that a new EGLSurface default to swap interval
375 // 1, so explicitly set that on the window here.
376 ANativeWindow* anw = reinterpret_cast<ANativeWindow*>(window);
377 anw->setSwapInterval(anw, 1);
378
Mathias Agopian518ec112011-05-13 16:21:08 -0700379 EGLSurface surface = cnx->egl.eglCreateWindowSurface(
380 iDpy, iConfig, window, attrib_list);
381 if (surface != EGL_NO_SURFACE) {
Mathias Agopianada798b2012-02-13 17:09:30 -0800382 egl_surface_t* s = new egl_surface_t(dpy, config, window, surface, cnx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700383 return s;
384 }
Mathias Agopian81a63352011-07-29 17:55:48 -0700385
386 // EGLSurface creation failed
387 native_window_set_buffers_format(window, 0);
388 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
Mathias Agopian518ec112011-05-13 16:21:08 -0700389 }
390 return EGL_NO_SURFACE;
391}
392
393EGLSurface eglCreatePixmapSurface( EGLDisplay dpy, EGLConfig config,
394 NativePixmapType pixmap,
395 const EGLint *attrib_list)
396{
397 clearError();
398
399 egl_display_t const* dp = 0;
400 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
401 if (cnx) {
402 EGLSurface surface = cnx->egl.eglCreatePixmapSurface(
Mathias Agopianada798b2012-02-13 17:09:30 -0800403 dp->disp.dpy,
Mathias Agopian518ec112011-05-13 16:21:08 -0700404 dp->configs[intptr_t(config)].config, pixmap, attrib_list);
405 if (surface != EGL_NO_SURFACE) {
Mathias Agopianada798b2012-02-13 17:09:30 -0800406 egl_surface_t* s = new egl_surface_t(dpy, config, NULL, surface, cnx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700407 return s;
408 }
409 }
410 return EGL_NO_SURFACE;
411}
412
413EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config,
414 const EGLint *attrib_list)
415{
416 clearError();
417
418 egl_display_t const* dp = 0;
419 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
420 if (cnx) {
421 EGLSurface surface = cnx->egl.eglCreatePbufferSurface(
Mathias Agopianada798b2012-02-13 17:09:30 -0800422 dp->disp.dpy,
Mathias Agopian518ec112011-05-13 16:21:08 -0700423 dp->configs[intptr_t(config)].config, attrib_list);
424 if (surface != EGL_NO_SURFACE) {
Mathias Agopianada798b2012-02-13 17:09:30 -0800425 egl_surface_t* s = new egl_surface_t(dpy, config, NULL, surface, cnx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700426 return s;
427 }
428 }
429 return EGL_NO_SURFACE;
430}
431
432EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
433{
434 clearError();
435
436 egl_display_t const * const dp = validate_display(dpy);
437 if (!dp) return EGL_FALSE;
438
Mathias Agopianf0480de2011-11-13 20:50:07 -0800439 SurfaceRef _s(dp, surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700440 if (!_s.get())
441 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700442
443 egl_surface_t * const s = get_surface(surface);
Mathias Agopianada798b2012-02-13 17:09:30 -0800444 EGLBoolean result = s->cnx->egl.eglDestroySurface(dp->disp.dpy, s->surface);
Mathias Agopian518ec112011-05-13 16:21:08 -0700445 if (result == EGL_TRUE) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700446 _s.terminate();
447 }
448 return result;
449}
450
451EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface surface,
452 EGLint attribute, EGLint *value)
453{
454 clearError();
455
456 egl_display_t const * const dp = validate_display(dpy);
457 if (!dp) return EGL_FALSE;
458
Mathias Agopianf0480de2011-11-13 20:50:07 -0800459 SurfaceRef _s(dp, surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700460 if (!_s.get())
461 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700462
Mathias Agopian518ec112011-05-13 16:21:08 -0700463 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian518ec112011-05-13 16:21:08 -0700464 EGLBoolean result(EGL_TRUE);
465 if (attribute == EGL_CONFIG_ID) {
466 // We need to remap EGL_CONFIG_IDs
467 *value = dp->configs[intptr_t(s->config)].configId;
468 } else {
469 result = s->cnx->egl.eglQuerySurface(
Mathias Agopianada798b2012-02-13 17:09:30 -0800470 dp->disp.dpy, s->surface, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -0700471 }
472
473 return result;
474}
475
Jamie Gennise8696a42012-01-15 18:54:57 -0800476void EGLAPI eglBeginFrame(EGLDisplay dpy, EGLSurface surface) {
477 clearError();
478
479 egl_display_t const * const dp = validate_display(dpy);
480 if (!dp) {
481 return;
482 }
483
484 SurfaceRef _s(dp, surface);
485 if (!_s.get()) {
486 setError(EGL_BAD_SURFACE, EGL_FALSE);
487 return;
488 }
489
490 int64_t timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
491
492 egl_surface_t const * const s = get_surface(surface);
493 native_window_set_buffers_timestamp(s->win.get(), timestamp);
494}
495
Mathias Agopian518ec112011-05-13 16:21:08 -0700496// ----------------------------------------------------------------------------
497// Contexts
498// ----------------------------------------------------------------------------
499
500EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config,
501 EGLContext share_list, const EGLint *attrib_list)
502{
503 clearError();
504
505 egl_display_t const* dp = 0;
506 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
507 if (cnx) {
508 if (share_list != EGL_NO_CONTEXT) {
509 egl_context_t* const c = get_context(share_list);
510 share_list = c->context;
511 }
512 EGLContext context = cnx->egl.eglCreateContext(
Mathias Agopianada798b2012-02-13 17:09:30 -0800513 dp->disp.dpy,
Mathias Agopian518ec112011-05-13 16:21:08 -0700514 dp->configs[intptr_t(config)].config,
515 share_list, attrib_list);
516 if (context != EGL_NO_CONTEXT) {
517 // figure out if it's a GLESv1 or GLESv2
518 int version = 0;
519 if (attrib_list) {
520 while (*attrib_list != EGL_NONE) {
521 GLint attr = *attrib_list++;
522 GLint value = *attrib_list++;
523 if (attr == EGL_CONTEXT_CLIENT_VERSION) {
524 if (value == 1) {
525 version = GLESv1_INDEX;
526 } else if (value == 2) {
527 version = GLESv2_INDEX;
528 }
529 }
530 };
531 }
Mathias Agopianada798b2012-02-13 17:09:30 -0800532 egl_context_t* c = new egl_context_t(dpy, context, config, cnx, version);
Siva Velusamy0469dd62011-11-30 15:05:37 -0800533#if EGL_TRACE
534 if (gEGLDebugLevel > 0)
535 GLTrace_eglCreateContext(version, c);
536#endif
Mathias Agopian518ec112011-05-13 16:21:08 -0700537 return c;
538 }
539 }
540 return EGL_NO_CONTEXT;
541}
542
543EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
544{
545 clearError();
546
547 egl_display_t const * const dp = validate_display(dpy);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700548 if (!dp)
549 return EGL_FALSE;
Mathias Agopian518ec112011-05-13 16:21:08 -0700550
Mathias Agopianf0480de2011-11-13 20:50:07 -0800551 ContextRef _c(dp, ctx);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700552 if (!_c.get())
553 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700554
Mathias Agopian518ec112011-05-13 16:21:08 -0700555 egl_context_t * const c = get_context(ctx);
Mathias Agopianada798b2012-02-13 17:09:30 -0800556 EGLBoolean result = c->cnx->egl.eglDestroyContext(dp->disp.dpy, c->context);
Mathias Agopian518ec112011-05-13 16:21:08 -0700557 if (result == EGL_TRUE) {
558 _c.terminate();
559 }
560 return result;
561}
562
Mathias Agopian518ec112011-05-13 16:21:08 -0700563EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw,
564 EGLSurface read, EGLContext ctx)
565{
566 clearError();
567
568 egl_display_t const * const dp = get_display(dpy);
569 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
570
Mathias Agopian5b287a62011-05-16 18:58:55 -0700571 // If ctx is not EGL_NO_CONTEXT, read is not EGL_NO_SURFACE, or draw is not
572 // EGL_NO_SURFACE, then an EGL_NOT_INITIALIZED error is generated if dpy is
573 // a valid but uninitialized display.
Mathias Agopian518ec112011-05-13 16:21:08 -0700574 if ( (ctx != EGL_NO_CONTEXT) || (read != EGL_NO_SURFACE) ||
575 (draw != EGL_NO_SURFACE) ) {
576 if (!dp->isReady()) return setError(EGL_NOT_INITIALIZED, EGL_FALSE);
577 }
578
579 // get a reference to the object passed in
Mathias Agopianf0480de2011-11-13 20:50:07 -0800580 ContextRef _c(dp, ctx);
581 SurfaceRef _d(dp, draw);
582 SurfaceRef _r(dp, read);
Mathias Agopian518ec112011-05-13 16:21:08 -0700583
584 // validate the context (if not EGL_NO_CONTEXT)
Mathias Agopian5b287a62011-05-16 18:58:55 -0700585 if ((ctx != EGL_NO_CONTEXT) && !_c.get()) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700586 // EGL_NO_CONTEXT is valid
587 return EGL_FALSE;
588 }
589
590 // these are the underlying implementation's object
591 EGLContext impl_ctx = EGL_NO_CONTEXT;
592 EGLSurface impl_draw = EGL_NO_SURFACE;
593 EGLSurface impl_read = EGL_NO_SURFACE;
594
595 // these are our objects structs passed in
596 egl_context_t * c = NULL;
597 egl_surface_t const * d = NULL;
598 egl_surface_t const * r = NULL;
599
600 // these are the current objects structs
601 egl_context_t * cur_c = get_context(getContext());
602
603 if (ctx != EGL_NO_CONTEXT) {
604 c = get_context(ctx);
605 impl_ctx = c->context;
606 } else {
607 // no context given, use the implementation of the current context
608 if (cur_c == NULL) {
609 // no current context
610 if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE) {
611 // calling eglMakeCurrent( ..., !=0, !=0, EGL_NO_CONTEXT);
612 return setError(EGL_BAD_MATCH, EGL_FALSE);
613 }
614 // not an error, there is just no current context.
615 return EGL_TRUE;
616 }
617 }
618
619 // retrieve the underlying implementation's draw EGLSurface
620 if (draw != EGL_NO_SURFACE) {
621 d = get_surface(draw);
Mathias Agopian518ec112011-05-13 16:21:08 -0700622 impl_draw = d->surface;
623 }
624
625 // retrieve the underlying implementation's read EGLSurface
626 if (read != EGL_NO_SURFACE) {
627 r = get_surface(read);
Mathias Agopian518ec112011-05-13 16:21:08 -0700628 impl_read = r->surface;
629 }
630
Mathias Agopian518ec112011-05-13 16:21:08 -0700631
Mathias Agopianfb87e542012-01-30 18:20:52 -0800632 EGLBoolean result = const_cast<egl_display_t*>(dp)->makeCurrent(c, cur_c,
633 draw, read, ctx,
634 impl_draw, impl_read, impl_ctx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700635
636 if (result == EGL_TRUE) {
Mathias Agopianfb87e542012-01-30 18:20:52 -0800637 if (c) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700638 setGLHooksThreadSpecific(c->cnx->hooks[c->version]);
639 egl_tls_t::setContext(ctx);
Siva Velusamy0469dd62011-11-30 15:05:37 -0800640#if EGL_TRACE
641 if (gEGLDebugLevel > 0)
Siva Velusamy93a826f2011-12-14 12:19:56 -0800642 GLTrace_eglMakeCurrent(c->version, c->cnx->hooks[c->version], ctx);
Siva Velusamy0469dd62011-11-30 15:05:37 -0800643#endif
Mathias Agopian518ec112011-05-13 16:21:08 -0700644 _c.acquire();
645 _r.acquire();
646 _d.acquire();
Mathias Agopian518ec112011-05-13 16:21:08 -0700647 } else {
648 setGLHooksThreadSpecific(&gHooksNoContext);
649 egl_tls_t::setContext(EGL_NO_CONTEXT);
650 }
Mathias Agopian5fecea72011-08-25 18:38:24 -0700651 } else {
Steve Blocke6f43dd2012-01-06 19:20:56 +0000652 // this will ALOGE the error
Mathias Agopian5fecea72011-08-25 18:38:24 -0700653 result = setError(c->cnx->egl.eglGetError(), EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700654 }
655 return result;
656}
657
658
659EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx,
660 EGLint attribute, EGLint *value)
661{
662 clearError();
663
664 egl_display_t const * const dp = validate_display(dpy);
665 if (!dp) return EGL_FALSE;
666
Mathias Agopianf0480de2011-11-13 20:50:07 -0800667 ContextRef _c(dp, ctx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700668 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
669
Mathias Agopian518ec112011-05-13 16:21:08 -0700670 egl_context_t * const c = get_context(ctx);
671
672 EGLBoolean result(EGL_TRUE);
673 if (attribute == EGL_CONFIG_ID) {
674 *value = dp->configs[intptr_t(c->config)].configId;
675 } else {
676 // We need to remap EGL_CONFIG_IDs
677 result = c->cnx->egl.eglQueryContext(
Mathias Agopianada798b2012-02-13 17:09:30 -0800678 dp->disp.dpy, c->context, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -0700679 }
680
681 return result;
682}
683
684EGLContext eglGetCurrentContext(void)
685{
686 // could be called before eglInitialize(), but we wouldn't have a context
687 // then, and this function would correctly return EGL_NO_CONTEXT.
688
689 clearError();
690
691 EGLContext ctx = getContext();
692 return ctx;
693}
694
695EGLSurface eglGetCurrentSurface(EGLint readdraw)
696{
697 // could be called before eglInitialize(), but we wouldn't have a context
698 // then, and this function would correctly return EGL_NO_SURFACE.
699
700 clearError();
701
702 EGLContext ctx = getContext();
703 if (ctx) {
704 egl_context_t const * const c = get_context(ctx);
705 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
706 switch (readdraw) {
707 case EGL_READ: return c->read;
708 case EGL_DRAW: return c->draw;
709 default: return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
710 }
711 }
712 return EGL_NO_SURFACE;
713}
714
715EGLDisplay eglGetCurrentDisplay(void)
716{
717 // could be called before eglInitialize(), but we wouldn't have a context
718 // then, and this function would correctly return EGL_NO_DISPLAY.
719
720 clearError();
721
722 EGLContext ctx = getContext();
723 if (ctx) {
724 egl_context_t const * const c = get_context(ctx);
725 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
726 return c->dpy;
727 }
728 return EGL_NO_DISPLAY;
729}
730
731EGLBoolean eglWaitGL(void)
732{
Mathias Agopian518ec112011-05-13 16:21:08 -0700733 clearError();
734
Mathias Agopianada798b2012-02-13 17:09:30 -0800735 egl_connection_t* const cnx = &gEGLImpl;
736 if (!cnx->dso)
737 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
738
739 return cnx->egl.eglWaitGL();
Mathias Agopian518ec112011-05-13 16:21:08 -0700740}
741
742EGLBoolean eglWaitNative(EGLint engine)
743{
Mathias Agopian518ec112011-05-13 16:21:08 -0700744 clearError();
745
Mathias Agopianada798b2012-02-13 17:09:30 -0800746 egl_connection_t* const cnx = &gEGLImpl;
747 if (!cnx->dso)
748 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
749
750 return cnx->egl.eglWaitNative(engine);
Mathias Agopian518ec112011-05-13 16:21:08 -0700751}
752
753EGLint eglGetError(void)
754{
Mathias Agopianada798b2012-02-13 17:09:30 -0800755 EGLint err = EGL_SUCCESS;
756 egl_connection_t* const cnx = &gEGLImpl;
757 if (cnx->dso) {
758 err = cnx->egl.eglGetError();
Mathias Agopian518ec112011-05-13 16:21:08 -0700759 }
Mathias Agopianada798b2012-02-13 17:09:30 -0800760 if (err == EGL_SUCCESS) {
761 err = egl_tls_t::getError();
762 }
763 return err;
Mathias Agopian518ec112011-05-13 16:21:08 -0700764}
765
766// Note: Similar implementations of these functions also exist in
767// gl2.cpp and gl.cpp, and are used by applications that call the
768// exported entry points directly.
769typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) (GLenum target, GLeglImageOES image);
770typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC) (GLenum target, GLeglImageOES image);
771
772static PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES_impl = NULL;
773static PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC glEGLImageTargetRenderbufferStorageOES_impl = NULL;
774
775static void glEGLImageTargetTexture2DOES_wrapper(GLenum target, GLeglImageOES image)
776{
777 GLeglImageOES implImage =
778 (GLeglImageOES)egl_get_image_for_current_context((EGLImageKHR)image);
779 glEGLImageTargetTexture2DOES_impl(target, implImage);
780}
781
782static void glEGLImageTargetRenderbufferStorageOES_wrapper(GLenum target, GLeglImageOES image)
783{
784 GLeglImageOES implImage =
785 (GLeglImageOES)egl_get_image_for_current_context((EGLImageKHR)image);
786 glEGLImageTargetRenderbufferStorageOES_impl(target, implImage);
787}
788
789__eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
790{
791 // eglGetProcAddress() could be the very first function called
792 // in which case we must make sure we've initialized ourselves, this
793 // happens the first time egl_get_display() is called.
794
795 clearError();
796
797 if (egl_init_drivers() == EGL_FALSE) {
798 setError(EGL_BAD_PARAMETER, NULL);
799 return NULL;
800 }
801
Jamie Gennisaca51c02011-11-03 17:42:43 -0700802 // The EGL_ANDROID_blob_cache extension should not be exposed to
803 // applications. It is used internally by the Android EGL layer.
Jamie Gennisc42fcf02011-11-09 15:35:34 -0800804 if (!strcmp(procname, "eglSetBlobCacheFuncsANDROID")) {
Jamie Gennisaca51c02011-11-03 17:42:43 -0700805 return NULL;
806 }
807
Mathias Agopian518ec112011-05-13 16:21:08 -0700808 __eglMustCastToProperFunctionPointerType addr;
809 addr = findProcAddress(procname, sExtentionMap, NELEM(sExtentionMap));
810 if (addr) return addr;
811
Jamie Gennisaca51c02011-11-03 17:42:43 -0700812
Mathias Agopian518ec112011-05-13 16:21:08 -0700813 // this protects accesses to sGLExtentionMap and sGLExtentionSlot
814 pthread_mutex_lock(&sExtensionMapMutex);
815
816 /*
817 * Since eglGetProcAddress() is not associated to anything, it needs
818 * to return a function pointer that "works" regardless of what
819 * the current context is.
820 *
821 * For this reason, we return a "forwarder", a small stub that takes
822 * care of calling the function associated with the context
823 * currently bound.
824 *
825 * We first look for extensions we've already resolved, if we're seeing
826 * this extension for the first time, we go through all our
827 * implementations and call eglGetProcAddress() and record the
828 * result in the appropriate implementation hooks and return the
829 * address of the forwarder corresponding to that hook set.
830 *
831 */
832
833 const String8 name(procname);
834 addr = sGLExtentionMap.valueFor(name);
835 const int slot = sGLExtentionSlot;
836
Steve Blocke6f43dd2012-01-06 19:20:56 +0000837 ALOGE_IF(slot >= MAX_NUMBER_OF_GL_EXTENSIONS,
Mathias Agopian518ec112011-05-13 16:21:08 -0700838 "no more slots for eglGetProcAddress(\"%s\")",
839 procname);
840
Siva Velusamy0469dd62011-11-30 15:05:37 -0800841#if EGL_TRACE
842 gl_hooks_t *debugHooks = GLTrace_getGLHooks();
843#endif
844
Mathias Agopian518ec112011-05-13 16:21:08 -0700845 if (!addr && (slot < MAX_NUMBER_OF_GL_EXTENSIONS)) {
846 bool found = false;
Mathias Agopianada798b2012-02-13 17:09:30 -0800847
848 egl_connection_t* const cnx = &gEGLImpl;
849 if (cnx->dso && cnx->egl.eglGetProcAddress) {
850 found = true;
851 // Extensions are independent of the bound context
852 cnx->hooks[GLESv1_INDEX]->ext.extensions[slot] =
853 cnx->hooks[GLESv2_INDEX]->ext.extensions[slot] =
Mathias Agopian518ec112011-05-13 16:21:08 -0700854#if EGL_TRACE
Mathias Agopianada798b2012-02-13 17:09:30 -0800855 debugHooks->ext.extensions[slot] =
856 gHooksTrace.ext.extensions[slot] =
Mathias Agopian518ec112011-05-13 16:21:08 -0700857#endif
Mathias Agopianada798b2012-02-13 17:09:30 -0800858 cnx->egl.eglGetProcAddress(procname);
Mathias Agopian518ec112011-05-13 16:21:08 -0700859 }
Mathias Agopianada798b2012-02-13 17:09:30 -0800860
Mathias Agopian518ec112011-05-13 16:21:08 -0700861 if (found) {
862 addr = gExtensionForwarders[slot];
863
864 if (!strcmp(procname, "glEGLImageTargetTexture2DOES")) {
865 glEGLImageTargetTexture2DOES_impl = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)addr;
866 addr = (__eglMustCastToProperFunctionPointerType)glEGLImageTargetTexture2DOES_wrapper;
867 }
868 if (!strcmp(procname, "glEGLImageTargetRenderbufferStorageOES")) {
869 glEGLImageTargetRenderbufferStorageOES_impl = (PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC)addr;
870 addr = (__eglMustCastToProperFunctionPointerType)glEGLImageTargetRenderbufferStorageOES_wrapper;
871 }
872
873 sGLExtentionMap.add(name, addr);
874 sGLExtentionSlot++;
875 }
876 }
877
878 pthread_mutex_unlock(&sExtensionMapMutex);
879 return addr;
880}
881
882EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw)
883{
Mathias Agopian518ec112011-05-13 16:21:08 -0700884 clearError();
885
886 egl_display_t const * const dp = validate_display(dpy);
887 if (!dp) return EGL_FALSE;
888
Mathias Agopianf0480de2011-11-13 20:50:07 -0800889 SurfaceRef _s(dp, draw);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700890 if (!_s.get())
891 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700892
Siva Velusamy0469dd62011-11-30 15:05:37 -0800893#if EGL_TRACE
894 if (gEGLDebugLevel > 0)
895 GLTrace_eglSwapBuffers(dpy, draw);
896#endif
897
Mathias Agopian518ec112011-05-13 16:21:08 -0700898 egl_surface_t const * const s = get_surface(draw);
Mathias Agopianada798b2012-02-13 17:09:30 -0800899 return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface);
Mathias Agopian518ec112011-05-13 16:21:08 -0700900}
901
902EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface,
903 NativePixmapType target)
904{
905 clearError();
906
907 egl_display_t const * const dp = validate_display(dpy);
908 if (!dp) return EGL_FALSE;
909
Mathias Agopianf0480de2011-11-13 20:50:07 -0800910 SurfaceRef _s(dp, surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700911 if (!_s.get())
912 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700913
Mathias Agopian518ec112011-05-13 16:21:08 -0700914 egl_surface_t const * const s = get_surface(surface);
Mathias Agopianada798b2012-02-13 17:09:30 -0800915 return s->cnx->egl.eglCopyBuffers(dp->disp.dpy, s->surface, target);
Mathias Agopian518ec112011-05-13 16:21:08 -0700916}
917
918const char* eglQueryString(EGLDisplay dpy, EGLint name)
919{
920 clearError();
921
922 egl_display_t const * const dp = validate_display(dpy);
923 if (!dp) return (const char *) NULL;
924
925 switch (name) {
926 case EGL_VENDOR:
Mathias Agopian4b9511c2011-11-13 23:52:47 -0800927 return dp->getVendorString();
Mathias Agopian518ec112011-05-13 16:21:08 -0700928 case EGL_VERSION:
Mathias Agopian4b9511c2011-11-13 23:52:47 -0800929 return dp->getVersionString();
Mathias Agopian518ec112011-05-13 16:21:08 -0700930 case EGL_EXTENSIONS:
Mathias Agopian4b9511c2011-11-13 23:52:47 -0800931 return dp->getExtensionString();
Mathias Agopian518ec112011-05-13 16:21:08 -0700932 case EGL_CLIENT_APIS:
Mathias Agopian4b9511c2011-11-13 23:52:47 -0800933 return dp->getClientApiString();
Mathias Agopianada798b2012-02-13 17:09:30 -0800934 case EGL_VERSION_HW_ANDROID:
935 return dp->disp.queryString.version;
Mathias Agopian518ec112011-05-13 16:21:08 -0700936 }
937 return setError(EGL_BAD_PARAMETER, (const char *)0);
938}
939
940
941// ----------------------------------------------------------------------------
942// EGL 1.1
943// ----------------------------------------------------------------------------
944
945EGLBoolean eglSurfaceAttrib(
946 EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
947{
948 clearError();
949
950 egl_display_t const * const dp = validate_display(dpy);
951 if (!dp) return EGL_FALSE;
952
Mathias Agopianf0480de2011-11-13 20:50:07 -0800953 SurfaceRef _s(dp, surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700954 if (!_s.get())
955 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700956
Mathias Agopian518ec112011-05-13 16:21:08 -0700957 egl_surface_t const * const s = get_surface(surface);
958 if (s->cnx->egl.eglSurfaceAttrib) {
959 return s->cnx->egl.eglSurfaceAttrib(
Mathias Agopianada798b2012-02-13 17:09:30 -0800960 dp->disp.dpy, s->surface, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -0700961 }
962 return setError(EGL_BAD_SURFACE, EGL_FALSE);
963}
964
965EGLBoolean eglBindTexImage(
966 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
967{
968 clearError();
969
970 egl_display_t const * const dp = validate_display(dpy);
971 if (!dp) return EGL_FALSE;
972
Mathias Agopianf0480de2011-11-13 20:50:07 -0800973 SurfaceRef _s(dp, surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700974 if (!_s.get())
975 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700976
Mathias Agopian518ec112011-05-13 16:21:08 -0700977 egl_surface_t const * const s = get_surface(surface);
978 if (s->cnx->egl.eglBindTexImage) {
979 return s->cnx->egl.eglBindTexImage(
Mathias Agopianada798b2012-02-13 17:09:30 -0800980 dp->disp.dpy, s->surface, buffer);
Mathias Agopian518ec112011-05-13 16:21:08 -0700981 }
982 return setError(EGL_BAD_SURFACE, EGL_FALSE);
983}
984
985EGLBoolean eglReleaseTexImage(
986 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
987{
988 clearError();
989
990 egl_display_t const * const dp = validate_display(dpy);
991 if (!dp) return EGL_FALSE;
992
Mathias Agopianf0480de2011-11-13 20:50:07 -0800993 SurfaceRef _s(dp, surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700994 if (!_s.get())
995 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700996
Mathias Agopian518ec112011-05-13 16:21:08 -0700997 egl_surface_t const * const s = get_surface(surface);
998 if (s->cnx->egl.eglReleaseTexImage) {
999 return s->cnx->egl.eglReleaseTexImage(
Mathias Agopianada798b2012-02-13 17:09:30 -08001000 dp->disp.dpy, s->surface, buffer);
Mathias Agopian518ec112011-05-13 16:21:08 -07001001 }
1002 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1003}
1004
1005EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
1006{
1007 clearError();
1008
1009 egl_display_t const * const dp = validate_display(dpy);
1010 if (!dp) return EGL_FALSE;
1011
1012 EGLBoolean res = EGL_TRUE;
Mathias Agopianada798b2012-02-13 17:09:30 -08001013 egl_connection_t* const cnx = &gEGLImpl;
1014 if (cnx->dso && cnx->egl.eglSwapInterval) {
1015 res = cnx->egl.eglSwapInterval(dp->disp.dpy, interval);
Mathias Agopian518ec112011-05-13 16:21:08 -07001016 }
Mathias Agopianada798b2012-02-13 17:09:30 -08001017
Mathias Agopian518ec112011-05-13 16:21:08 -07001018 return res;
1019}
1020
1021
1022// ----------------------------------------------------------------------------
1023// EGL 1.2
1024// ----------------------------------------------------------------------------
1025
1026EGLBoolean eglWaitClient(void)
1027{
1028 clearError();
1029
Mathias Agopianada798b2012-02-13 17:09:30 -08001030 egl_connection_t* const cnx = &gEGLImpl;
1031 if (!cnx->dso)
1032 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1033
1034 EGLBoolean res;
1035 if (cnx->egl.eglWaitClient) {
1036 res = cnx->egl.eglWaitClient();
1037 } else {
1038 res = cnx->egl.eglWaitGL();
Mathias Agopian518ec112011-05-13 16:21:08 -07001039 }
1040 return res;
1041}
1042
1043EGLBoolean eglBindAPI(EGLenum api)
1044{
1045 clearError();
1046
1047 if (egl_init_drivers() == EGL_FALSE) {
1048 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1049 }
1050
1051 // bind this API on all EGLs
1052 EGLBoolean res = EGL_TRUE;
Mathias Agopianada798b2012-02-13 17:09:30 -08001053 egl_connection_t* const cnx = &gEGLImpl;
1054 if (cnx->dso && cnx->egl.eglBindAPI) {
1055 res = cnx->egl.eglBindAPI(api);
Mathias Agopian518ec112011-05-13 16:21:08 -07001056 }
1057 return res;
1058}
1059
1060EGLenum eglQueryAPI(void)
1061{
1062 clearError();
1063
1064 if (egl_init_drivers() == EGL_FALSE) {
1065 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1066 }
1067
Mathias Agopianada798b2012-02-13 17:09:30 -08001068 egl_connection_t* const cnx = &gEGLImpl;
1069 if (cnx->dso && cnx->egl.eglQueryAPI) {
1070 return cnx->egl.eglQueryAPI();
Mathias Agopian518ec112011-05-13 16:21:08 -07001071 }
Mathias Agopianada798b2012-02-13 17:09:30 -08001072
Mathias Agopian518ec112011-05-13 16:21:08 -07001073 // or, it can only be OpenGL ES
1074 return EGL_OPENGL_ES_API;
1075}
1076
1077EGLBoolean eglReleaseThread(void)
1078{
1079 clearError();
1080
1081 // If there is context bound to the thread, release it
Mathias Agopianfb87e542012-01-30 18:20:52 -08001082 egl_display_t::loseCurrent(get_context(getContext()));
Mathias Agopian518ec112011-05-13 16:21:08 -07001083
Mathias Agopianada798b2012-02-13 17:09:30 -08001084 egl_connection_t* const cnx = &gEGLImpl;
1085 if (cnx->dso && cnx->egl.eglReleaseThread) {
1086 cnx->egl.eglReleaseThread();
Mathias Agopian518ec112011-05-13 16:21:08 -07001087 }
Mathias Agopianada798b2012-02-13 17:09:30 -08001088
Mathias Agopian518ec112011-05-13 16:21:08 -07001089 egl_tls_t::clearTLS();
Siva Velusamy0469dd62011-11-30 15:05:37 -08001090#if EGL_TRACE
1091 if (gEGLDebugLevel > 0)
1092 GLTrace_eglReleaseThread();
1093#endif
Mathias Agopian518ec112011-05-13 16:21:08 -07001094 return EGL_TRUE;
1095}
1096
1097EGLSurface eglCreatePbufferFromClientBuffer(
1098 EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer,
1099 EGLConfig config, const EGLint *attrib_list)
1100{
1101 clearError();
1102
1103 egl_display_t const* dp = 0;
1104 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
1105 if (!cnx) return EGL_FALSE;
1106 if (cnx->egl.eglCreatePbufferFromClientBuffer) {
1107 return cnx->egl.eglCreatePbufferFromClientBuffer(
Mathias Agopianada798b2012-02-13 17:09:30 -08001108 dp->disp.dpy,
Mathias Agopian518ec112011-05-13 16:21:08 -07001109 buftype, buffer,
1110 dp->configs[intptr_t(config)].config, attrib_list);
1111 }
1112 return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE);
1113}
1114
1115// ----------------------------------------------------------------------------
1116// EGL_EGLEXT_VERSION 3
1117// ----------------------------------------------------------------------------
1118
1119EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface,
1120 const EGLint *attrib_list)
1121{
1122 clearError();
1123
1124 egl_display_t const * const dp = validate_display(dpy);
1125 if (!dp) return EGL_FALSE;
1126
Mathias Agopianf0480de2011-11-13 20:50:07 -08001127 SurfaceRef _s(dp, surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001128 if (!_s.get())
1129 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001130
1131 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian518ec112011-05-13 16:21:08 -07001132 if (s->cnx->egl.eglLockSurfaceKHR) {
1133 return s->cnx->egl.eglLockSurfaceKHR(
Mathias Agopianada798b2012-02-13 17:09:30 -08001134 dp->disp.dpy, s->surface, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001135 }
1136 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1137}
1138
1139EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface)
1140{
1141 clearError();
1142
1143 egl_display_t const * const dp = validate_display(dpy);
1144 if (!dp) return EGL_FALSE;
1145
Mathias Agopianf0480de2011-11-13 20:50:07 -08001146 SurfaceRef _s(dp, surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001147 if (!_s.get())
1148 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001149
1150 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian518ec112011-05-13 16:21:08 -07001151 if (s->cnx->egl.eglUnlockSurfaceKHR) {
Mathias Agopianada798b2012-02-13 17:09:30 -08001152 return s->cnx->egl.eglUnlockSurfaceKHR(dp->disp.dpy, s->surface);
Mathias Agopian518ec112011-05-13 16:21:08 -07001153 }
1154 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1155}
1156
1157EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
1158 EGLClientBuffer buffer, const EGLint *attrib_list)
1159{
1160 clearError();
1161
1162 egl_display_t const * const dp = validate_display(dpy);
1163 if (!dp) return EGL_NO_IMAGE_KHR;
1164
1165 if (ctx != EGL_NO_CONTEXT) {
Mathias Agopianf0480de2011-11-13 20:50:07 -08001166 ContextRef _c(dp, ctx);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001167 if (!_c.get())
1168 return setError(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
Mathias Agopian518ec112011-05-13 16:21:08 -07001169 egl_context_t * const c = get_context(ctx);
1170 // since we have an EGLContext, we know which implementation to use
1171 EGLImageKHR image = c->cnx->egl.eglCreateImageKHR(
Mathias Agopianada798b2012-02-13 17:09:30 -08001172 dp->disp.dpy, c->context, target, buffer, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001173 if (image == EGL_NO_IMAGE_KHR)
1174 return image;
1175
1176 egl_image_t* result = new egl_image_t(dpy, ctx);
Mathias Agopianada798b2012-02-13 17:09:30 -08001177 result->image = image;
Mathias Agopian518ec112011-05-13 16:21:08 -07001178 return (EGLImageKHR)result;
1179 } else {
1180 // EGL_NO_CONTEXT is a valid parameter
1181
1182 /* Since we don't have a way to know which implementation to call,
1183 * we're calling all of them. If at least one of the implementation
1184 * succeeded, this is a success.
1185 */
1186
1187 EGLint currentError = eglGetError();
1188
Mathias Agopianada798b2012-02-13 17:09:30 -08001189 EGLImageKHR implImage = EGL_NO_IMAGE_KHR;
1190 egl_connection_t* const cnx = &gEGLImpl;
1191 if (cnx->dso && cnx->egl.eglCreateImageKHR) {
1192 implImage = cnx->egl.eglCreateImageKHR(
1193 dp->disp.dpy, ctx, target, buffer, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001194 }
1195
Mathias Agopianada798b2012-02-13 17:09:30 -08001196 if (implImage == EGL_NO_IMAGE_KHR) {
Mathias Agopian518ec112011-05-13 16:21:08 -07001197 // failure, if there was an error when we entered this function,
1198 // the error flag must not be updated.
1199 // Otherwise, the error is whatever happened in the implementation
1200 // that faulted.
1201 if (currentError != EGL_SUCCESS) {
1202 setError(currentError, EGL_NO_IMAGE_KHR);
1203 }
1204 return EGL_NO_IMAGE_KHR;
1205 } else {
1206 // In case of success, we need to clear all error flags
1207 // (especially those caused by the implementation that didn't
Mathias Agopianada798b2012-02-13 17:09:30 -08001208 // succeed).
Mathias Agopian518ec112011-05-13 16:21:08 -07001209 eglGetError();
1210 }
1211
1212 egl_image_t* result = new egl_image_t(dpy, ctx);
Mathias Agopianada798b2012-02-13 17:09:30 -08001213 result->image = implImage;
Mathias Agopian518ec112011-05-13 16:21:08 -07001214 return (EGLImageKHR)result;
1215 }
1216}
1217
1218EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
1219{
1220 clearError();
1221
1222 egl_display_t const * const dp = validate_display(dpy);
1223 if (!dp) return EGL_FALSE;
1224
Mathias Agopianf0480de2011-11-13 20:50:07 -08001225 ImageRef _i(dp, img);
Mathias Agopian518ec112011-05-13 16:21:08 -07001226 if (!_i.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1227
1228 egl_image_t* image = get_image(img);
1229 bool success = false;
Mathias Agopianada798b2012-02-13 17:09:30 -08001230
1231 egl_connection_t* const cnx = &gEGLImpl;
1232 if (image->image != EGL_NO_IMAGE_KHR) {
1233 if (cnx->dso && cnx->egl.eglDestroyImageKHR) {
1234 if (cnx->egl.eglDestroyImageKHR(
1235 dp->disp.dpy, image->image)) {
1236 success = true;
Mathias Agopian518ec112011-05-13 16:21:08 -07001237 }
1238 }
1239 }
Mathias Agopianada798b2012-02-13 17:09:30 -08001240
Mathias Agopian518ec112011-05-13 16:21:08 -07001241 if (!success)
1242 return EGL_FALSE;
1243
1244 _i.terminate();
1245
1246 return EGL_TRUE;
1247}
1248
1249// ----------------------------------------------------------------------------
1250// EGL_EGLEXT_VERSION 5
1251// ----------------------------------------------------------------------------
1252
1253
1254EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
1255{
1256 clearError();
1257
1258 egl_display_t const * const dp = validate_display(dpy);
1259 if (!dp) return EGL_NO_SYNC_KHR;
1260
1261 EGLContext ctx = eglGetCurrentContext();
Mathias Agopianf0480de2011-11-13 20:50:07 -08001262 ContextRef _c(dp, ctx);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001263 if (!_c.get())
1264 return setError(EGL_BAD_CONTEXT, EGL_NO_SYNC_KHR);
1265
Mathias Agopian518ec112011-05-13 16:21:08 -07001266 egl_context_t * const c = get_context(ctx);
1267 EGLSyncKHR result = EGL_NO_SYNC_KHR;
1268 if (c->cnx->egl.eglCreateSyncKHR) {
1269 EGLSyncKHR sync = c->cnx->egl.eglCreateSyncKHR(
Mathias Agopianada798b2012-02-13 17:09:30 -08001270 dp->disp.dpy, type, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001271 if (sync == EGL_NO_SYNC_KHR)
1272 return sync;
1273 result = (egl_sync_t*)new egl_sync_t(dpy, ctx, sync);
1274 }
1275 return (EGLSyncKHR)result;
1276}
1277
1278EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
1279{
1280 clearError();
1281
1282 egl_display_t const * const dp = validate_display(dpy);
1283 if (!dp) return EGL_FALSE;
1284
Mathias Agopianf0480de2011-11-13 20:50:07 -08001285 SyncRef _s(dp, sync);
Mathias Agopian518ec112011-05-13 16:21:08 -07001286 if (!_s.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1287 egl_sync_t* syncObject = get_sync(sync);
1288
1289 EGLContext ctx = syncObject->context;
Mathias Agopianf0480de2011-11-13 20:50:07 -08001290 ContextRef _c(dp, ctx);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001291 if (!_c.get())
1292 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001293
1294 EGLBoolean result = EGL_FALSE;
1295 egl_context_t * const c = get_context(ctx);
1296 if (c->cnx->egl.eglDestroySyncKHR) {
1297 result = c->cnx->egl.eglDestroySyncKHR(
Mathias Agopianada798b2012-02-13 17:09:30 -08001298 dp->disp.dpy, syncObject->sync);
Mathias Agopian518ec112011-05-13 16:21:08 -07001299 if (result)
1300 _s.terminate();
1301 }
1302 return result;
1303}
1304
1305EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout)
1306{
1307 clearError();
1308
1309 egl_display_t const * const dp = validate_display(dpy);
1310 if (!dp) return EGL_FALSE;
1311
Mathias Agopianf0480de2011-11-13 20:50:07 -08001312 SyncRef _s(dp, sync);
Mathias Agopian518ec112011-05-13 16:21:08 -07001313 if (!_s.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1314 egl_sync_t* syncObject = get_sync(sync);
1315
1316 EGLContext ctx = syncObject->context;
Mathias Agopianf0480de2011-11-13 20:50:07 -08001317 ContextRef _c(dp, ctx);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001318 if (!_c.get())
1319 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001320
1321 egl_context_t * const c = get_context(ctx);
Mathias Agopian518ec112011-05-13 16:21:08 -07001322 if (c->cnx->egl.eglClientWaitSyncKHR) {
1323 return c->cnx->egl.eglClientWaitSyncKHR(
Mathias Agopianada798b2012-02-13 17:09:30 -08001324 dp->disp.dpy, syncObject->sync, flags, timeout);
Mathias Agopian518ec112011-05-13 16:21:08 -07001325 }
1326
1327 return EGL_FALSE;
1328}
1329
1330EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value)
1331{
1332 clearError();
1333
1334 egl_display_t const * const dp = validate_display(dpy);
1335 if (!dp) return EGL_FALSE;
1336
Mathias Agopianf0480de2011-11-13 20:50:07 -08001337 SyncRef _s(dp, sync);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001338 if (!_s.get())
1339 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001340
Mathias Agopian5b287a62011-05-16 18:58:55 -07001341 egl_sync_t* syncObject = get_sync(sync);
Mathias Agopian518ec112011-05-13 16:21:08 -07001342 EGLContext ctx = syncObject->context;
Mathias Agopianf0480de2011-11-13 20:50:07 -08001343 ContextRef _c(dp, ctx);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001344 if (!_c.get())
1345 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001346
1347 egl_context_t * const c = get_context(ctx);
Mathias Agopian518ec112011-05-13 16:21:08 -07001348 if (c->cnx->egl.eglGetSyncAttribKHR) {
1349 return c->cnx->egl.eglGetSyncAttribKHR(
Mathias Agopianada798b2012-02-13 17:09:30 -08001350 dp->disp.dpy, syncObject->sync, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -07001351 }
1352
1353 return EGL_FALSE;
1354}
1355
1356// ----------------------------------------------------------------------------
1357// ANDROID extensions
1358// ----------------------------------------------------------------------------
1359
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001360/* ANDROID extensions entry-point go here */
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001361
1362// ----------------------------------------------------------------------------
1363// NVIDIA extensions
1364// ----------------------------------------------------------------------------
1365EGLuint64NV eglGetSystemTimeFrequencyNV()
1366{
1367 clearError();
1368
1369 if (egl_init_drivers() == EGL_FALSE) {
1370 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1371 }
1372
1373 EGLuint64NV ret = 0;
Mathias Agopianada798b2012-02-13 17:09:30 -08001374 egl_connection_t* const cnx = &gEGLImpl;
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001375
Mathias Agopianada798b2012-02-13 17:09:30 -08001376 if (cnx->dso && cnx->egl.eglGetSystemTimeFrequencyNV) {
1377 return cnx->egl.eglGetSystemTimeFrequencyNV();
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001378 }
1379
Mathias Agopian0e8bbee2011-10-05 19:15:05 -07001380 return setErrorQuiet(EGL_BAD_DISPLAY, 0);
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001381}
1382
1383EGLuint64NV eglGetSystemTimeNV()
1384{
1385 clearError();
1386
1387 if (egl_init_drivers() == EGL_FALSE) {
1388 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1389 }
1390
1391 EGLuint64NV ret = 0;
Mathias Agopianada798b2012-02-13 17:09:30 -08001392 egl_connection_t* const cnx = &gEGLImpl;
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001393
Mathias Agopianada798b2012-02-13 17:09:30 -08001394 if (cnx->dso && cnx->egl.eglGetSystemTimeNV) {
1395 return cnx->egl.eglGetSystemTimeNV();
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001396 }
1397
Mathias Agopian0e8bbee2011-10-05 19:15:05 -07001398 return setErrorQuiet(EGL_BAD_DISPLAY, 0);
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001399}