blob: bb2783dc26bcc14beab04def4c956c280f3d87f3 [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
Mathias Agopian518ec112011-05-13 16:21:08 -070092namespace android {
93extern void setGLHooksThreadSpecific(gl_hooks_t const *value);
94extern EGLBoolean egl_init_drivers();
95extern const __eglMustCastToProperFunctionPointerType gExtensionForwarders[MAX_NUMBER_OF_GL_EXTENSIONS];
96extern int gEGLDebugLevel;
97extern gl_hooks_t gHooksTrace;
Mathias Agopian518ec112011-05-13 16:21:08 -070098} // namespace android;
99
100// ----------------------------------------------------------------------------
101
102static inline void clearError() { egl_tls_t::clearError(); }
103static inline EGLContext getContext() { return egl_tls_t::getContext(); }
104
105// ----------------------------------------------------------------------------
106
107EGLDisplay eglGetDisplay(EGLNativeDisplayType display)
108{
109 clearError();
110
111 uint32_t index = uint32_t(display);
112 if (index >= NUM_DISPLAYS) {
113 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
114 }
115
116 if (egl_init_drivers() == EGL_FALSE) {
117 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
118 }
119
120 EGLDisplay dpy = egl_display_t::getFromNativeDisplay(display);
121 return dpy;
122}
123
124// ----------------------------------------------------------------------------
125// Initialization
126// ----------------------------------------------------------------------------
127
128EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
129{
130 clearError();
131
132 egl_display_t * const dp = get_display(dpy);
133 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
134
135 EGLBoolean res = dp->initialize(major, minor);
136
137 return res;
138}
139
140EGLBoolean eglTerminate(EGLDisplay dpy)
141{
142 // NOTE: don't unload the drivers b/c some APIs can be called
143 // after eglTerminate() has been called. eglTerminate() only
144 // terminates an EGLDisplay, not a EGL itself.
145
146 clearError();
147
148 egl_display_t* const dp = get_display(dpy);
149 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
150
151 EGLBoolean res = dp->terminate();
152
153 return res;
154}
155
156// ----------------------------------------------------------------------------
157// configuration
158// ----------------------------------------------------------------------------
159
160EGLBoolean eglGetConfigs( EGLDisplay dpy,
161 EGLConfig *configs,
162 EGLint config_size, EGLint *num_config)
163{
164 clearError();
165
166 egl_display_t const * const dp = validate_display(dpy);
167 if (!dp) return EGL_FALSE;
168
Mathias Agopian7773c432012-02-13 20:06:08 -0800169 if (num_config==0) {
170 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700171 }
172
Mathias Agopian7773c432012-02-13 20:06:08 -0800173 EGLBoolean res = EGL_FALSE;
174 *num_config = 0;
175
176 egl_connection_t* const cnx = &gEGLImpl;
177 if (cnx->dso) {
178 res = cnx->egl.eglGetConfigs(
179 dp->disp.dpy, configs, config_size, num_config);
Mathias Agopian518ec112011-05-13 16:21:08 -0700180 }
Mathias Agopian7773c432012-02-13 20:06:08 -0800181
182 return res;
Mathias Agopian518ec112011-05-13 16:21:08 -0700183}
184
185EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list,
186 EGLConfig *configs, EGLint config_size,
187 EGLint *num_config)
188{
189 clearError();
190
191 egl_display_t const * const dp = validate_display(dpy);
192 if (!dp) return EGL_FALSE;
193
194 if (num_config==0) {
195 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
196 }
197
Mathias Agopian518ec112011-05-13 16:21:08 -0700198 EGLBoolean res = EGL_FALSE;
199 *num_config = 0;
200
Mathias Agopianada798b2012-02-13 17:09:30 -0800201 egl_connection_t* const cnx = &gEGLImpl;
202 if (cnx->dso) {
Mathias Agopian7773c432012-02-13 20:06:08 -0800203 res = cnx->egl.eglChooseConfig(
204 dp->disp.dpy, attrib_list, configs, config_size, num_config);
Mathias Agopian518ec112011-05-13 16:21:08 -0700205 }
206 return res;
207}
208
209EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
210 EGLint attribute, EGLint *value)
211{
212 clearError();
213
214 egl_display_t const* dp = 0;
215 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
216 if (!cnx) return EGL_FALSE;
217
Mathias Agopian518ec112011-05-13 16:21:08 -0700218 return cnx->egl.eglGetConfigAttrib(
Mathias Agopian7773c432012-02-13 20:06:08 -0800219 dp->disp.dpy, config, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -0700220}
221
222// ----------------------------------------------------------------------------
223// surfaces
224// ----------------------------------------------------------------------------
225
226EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config,
227 NativeWindowType window,
228 const EGLint *attrib_list)
229{
230 clearError();
231
232 egl_display_t const* dp = 0;
233 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
234 if (cnx) {
Mathias Agopianada798b2012-02-13 17:09:30 -0800235 EGLDisplay iDpy = dp->disp.dpy;
Mathias Agopian518ec112011-05-13 16:21:08 -0700236 EGLint format;
237
Mathias Agopian81a63352011-07-29 17:55:48 -0700238 if (native_window_api_connect(window, NATIVE_WINDOW_API_EGL) != OK) {
Steve Blocke6f43dd2012-01-06 19:20:56 +0000239 ALOGE("EGLNativeWindowType %p already connected to another API",
Mathias Agopian81a63352011-07-29 17:55:48 -0700240 window);
241 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
242 }
243
Mathias Agopian518ec112011-05-13 16:21:08 -0700244 // set the native window's buffers format to match this config
245 if (cnx->egl.eglGetConfigAttrib(iDpy,
Mathias Agopian7773c432012-02-13 20:06:08 -0800246 config, EGL_NATIVE_VISUAL_ID, &format)) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700247 if (format != 0) {
Jamie Gennisbee205f2011-07-01 13:12:07 -0700248 int err = native_window_set_buffers_format(window, format);
249 if (err != 0) {
Steve Blocke6f43dd2012-01-06 19:20:56 +0000250 ALOGE("error setting native window pixel format: %s (%d)",
Jamie Gennisbee205f2011-07-01 13:12:07 -0700251 strerror(-err), err);
Mathias Agopian81a63352011-07-29 17:55:48 -0700252 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
Jamie Gennisbee205f2011-07-01 13:12:07 -0700253 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
254 }
Mathias Agopian518ec112011-05-13 16:21:08 -0700255 }
256 }
257
Jamie Gennis59769462011-11-19 18:04:43 -0800258 // the EGL spec requires that a new EGLSurface default to swap interval
259 // 1, so explicitly set that on the window here.
260 ANativeWindow* anw = reinterpret_cast<ANativeWindow*>(window);
261 anw->setSwapInterval(anw, 1);
262
Mathias Agopian518ec112011-05-13 16:21:08 -0700263 EGLSurface surface = cnx->egl.eglCreateWindowSurface(
Mathias Agopian7773c432012-02-13 20:06:08 -0800264 iDpy, config, window, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700265 if (surface != EGL_NO_SURFACE) {
Mathias Agopianada798b2012-02-13 17:09:30 -0800266 egl_surface_t* s = new egl_surface_t(dpy, config, window, surface, cnx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700267 return s;
268 }
Mathias Agopian81a63352011-07-29 17:55:48 -0700269
270 // EGLSurface creation failed
271 native_window_set_buffers_format(window, 0);
272 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
Mathias Agopian518ec112011-05-13 16:21:08 -0700273 }
274 return EGL_NO_SURFACE;
275}
276
277EGLSurface eglCreatePixmapSurface( EGLDisplay dpy, EGLConfig config,
278 NativePixmapType pixmap,
279 const EGLint *attrib_list)
280{
281 clearError();
282
283 egl_display_t const* dp = 0;
284 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
285 if (cnx) {
286 EGLSurface surface = cnx->egl.eglCreatePixmapSurface(
Mathias Agopian7773c432012-02-13 20:06:08 -0800287 dp->disp.dpy, config, pixmap, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700288 if (surface != EGL_NO_SURFACE) {
Mathias Agopianada798b2012-02-13 17:09:30 -0800289 egl_surface_t* s = new egl_surface_t(dpy, config, NULL, surface, cnx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700290 return s;
291 }
292 }
293 return EGL_NO_SURFACE;
294}
295
296EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config,
297 const EGLint *attrib_list)
298{
299 clearError();
300
301 egl_display_t const* dp = 0;
302 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
303 if (cnx) {
304 EGLSurface surface = cnx->egl.eglCreatePbufferSurface(
Mathias Agopian7773c432012-02-13 20:06:08 -0800305 dp->disp.dpy, config, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700306 if (surface != EGL_NO_SURFACE) {
Mathias Agopianada798b2012-02-13 17:09:30 -0800307 egl_surface_t* s = new egl_surface_t(dpy, config, NULL, surface, cnx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700308 return s;
309 }
310 }
311 return EGL_NO_SURFACE;
312}
313
314EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
315{
316 clearError();
317
318 egl_display_t const * const dp = validate_display(dpy);
319 if (!dp) return EGL_FALSE;
320
Mathias Agopianf0480de2011-11-13 20:50:07 -0800321 SurfaceRef _s(dp, surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700322 if (!_s.get())
323 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700324
325 egl_surface_t * const s = get_surface(surface);
Mathias Agopianada798b2012-02-13 17:09:30 -0800326 EGLBoolean result = s->cnx->egl.eglDestroySurface(dp->disp.dpy, s->surface);
Mathias Agopian518ec112011-05-13 16:21:08 -0700327 if (result == EGL_TRUE) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700328 _s.terminate();
329 }
330 return result;
331}
332
333EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface surface,
334 EGLint attribute, EGLint *value)
335{
336 clearError();
337
338 egl_display_t const * const dp = validate_display(dpy);
339 if (!dp) return EGL_FALSE;
340
Mathias Agopianf0480de2011-11-13 20:50:07 -0800341 SurfaceRef _s(dp, surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700342 if (!_s.get())
343 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700344
Mathias Agopian518ec112011-05-13 16:21:08 -0700345 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian7773c432012-02-13 20:06:08 -0800346 return s->cnx->egl.eglQuerySurface(
347 dp->disp.dpy, s->surface, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -0700348}
349
Jamie Gennise8696a42012-01-15 18:54:57 -0800350void EGLAPI eglBeginFrame(EGLDisplay dpy, EGLSurface surface) {
351 clearError();
352
353 egl_display_t const * const dp = validate_display(dpy);
354 if (!dp) {
355 return;
356 }
357
358 SurfaceRef _s(dp, surface);
359 if (!_s.get()) {
360 setError(EGL_BAD_SURFACE, EGL_FALSE);
361 return;
362 }
363
364 int64_t timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
365
366 egl_surface_t const * const s = get_surface(surface);
367 native_window_set_buffers_timestamp(s->win.get(), timestamp);
368}
369
Mathias Agopian518ec112011-05-13 16:21:08 -0700370// ----------------------------------------------------------------------------
371// Contexts
372// ----------------------------------------------------------------------------
373
374EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config,
375 EGLContext share_list, const EGLint *attrib_list)
376{
377 clearError();
378
379 egl_display_t const* dp = 0;
380 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
381 if (cnx) {
382 if (share_list != EGL_NO_CONTEXT) {
383 egl_context_t* const c = get_context(share_list);
384 share_list = c->context;
385 }
386 EGLContext context = cnx->egl.eglCreateContext(
Mathias Agopian7773c432012-02-13 20:06:08 -0800387 dp->disp.dpy, config, share_list, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700388 if (context != EGL_NO_CONTEXT) {
389 // figure out if it's a GLESv1 or GLESv2
390 int version = 0;
391 if (attrib_list) {
392 while (*attrib_list != EGL_NONE) {
393 GLint attr = *attrib_list++;
394 GLint value = *attrib_list++;
395 if (attr == EGL_CONTEXT_CLIENT_VERSION) {
396 if (value == 1) {
Mathias Agopian7773c432012-02-13 20:06:08 -0800397 version = egl_connection_t::GLESv1_INDEX;
Mathias Agopian518ec112011-05-13 16:21:08 -0700398 } else if (value == 2) {
Mathias Agopian7773c432012-02-13 20:06:08 -0800399 version = egl_connection_t::GLESv2_INDEX;
Mathias Agopian518ec112011-05-13 16:21:08 -0700400 }
401 }
402 };
403 }
Mathias Agopianada798b2012-02-13 17:09:30 -0800404 egl_context_t* c = new egl_context_t(dpy, context, config, cnx, version);
Siva Velusamy0469dd62011-11-30 15:05:37 -0800405#if EGL_TRACE
406 if (gEGLDebugLevel > 0)
407 GLTrace_eglCreateContext(version, c);
408#endif
Mathias Agopian518ec112011-05-13 16:21:08 -0700409 return c;
410 }
411 }
412 return EGL_NO_CONTEXT;
413}
414
415EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
416{
417 clearError();
418
419 egl_display_t const * const dp = validate_display(dpy);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700420 if (!dp)
421 return EGL_FALSE;
Mathias Agopian518ec112011-05-13 16:21:08 -0700422
Mathias Agopianf0480de2011-11-13 20:50:07 -0800423 ContextRef _c(dp, ctx);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700424 if (!_c.get())
425 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700426
Mathias Agopian518ec112011-05-13 16:21:08 -0700427 egl_context_t * const c = get_context(ctx);
Mathias Agopianada798b2012-02-13 17:09:30 -0800428 EGLBoolean result = c->cnx->egl.eglDestroyContext(dp->disp.dpy, c->context);
Mathias Agopian518ec112011-05-13 16:21:08 -0700429 if (result == EGL_TRUE) {
430 _c.terminate();
431 }
432 return result;
433}
434
Mathias Agopian518ec112011-05-13 16:21:08 -0700435EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw,
436 EGLSurface read, EGLContext ctx)
437{
438 clearError();
439
440 egl_display_t const * const dp = get_display(dpy);
441 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
442
Mathias Agopian5b287a62011-05-16 18:58:55 -0700443 // If ctx is not EGL_NO_CONTEXT, read is not EGL_NO_SURFACE, or draw is not
444 // EGL_NO_SURFACE, then an EGL_NOT_INITIALIZED error is generated if dpy is
445 // a valid but uninitialized display.
Mathias Agopian518ec112011-05-13 16:21:08 -0700446 if ( (ctx != EGL_NO_CONTEXT) || (read != EGL_NO_SURFACE) ||
447 (draw != EGL_NO_SURFACE) ) {
448 if (!dp->isReady()) return setError(EGL_NOT_INITIALIZED, EGL_FALSE);
449 }
450
451 // get a reference to the object passed in
Mathias Agopianf0480de2011-11-13 20:50:07 -0800452 ContextRef _c(dp, ctx);
453 SurfaceRef _d(dp, draw);
454 SurfaceRef _r(dp, read);
Mathias Agopian518ec112011-05-13 16:21:08 -0700455
456 // validate the context (if not EGL_NO_CONTEXT)
Mathias Agopian5b287a62011-05-16 18:58:55 -0700457 if ((ctx != EGL_NO_CONTEXT) && !_c.get()) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700458 // EGL_NO_CONTEXT is valid
459 return EGL_FALSE;
460 }
461
462 // these are the underlying implementation's object
463 EGLContext impl_ctx = EGL_NO_CONTEXT;
464 EGLSurface impl_draw = EGL_NO_SURFACE;
465 EGLSurface impl_read = EGL_NO_SURFACE;
466
467 // these are our objects structs passed in
468 egl_context_t * c = NULL;
469 egl_surface_t const * d = NULL;
470 egl_surface_t const * r = NULL;
471
472 // these are the current objects structs
473 egl_context_t * cur_c = get_context(getContext());
474
475 if (ctx != EGL_NO_CONTEXT) {
476 c = get_context(ctx);
477 impl_ctx = c->context;
478 } else {
479 // no context given, use the implementation of the current context
480 if (cur_c == NULL) {
481 // no current context
482 if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE) {
483 // calling eglMakeCurrent( ..., !=0, !=0, EGL_NO_CONTEXT);
484 return setError(EGL_BAD_MATCH, EGL_FALSE);
485 }
486 // not an error, there is just no current context.
487 return EGL_TRUE;
488 }
489 }
490
491 // retrieve the underlying implementation's draw EGLSurface
492 if (draw != EGL_NO_SURFACE) {
493 d = get_surface(draw);
Mathias Agopian518ec112011-05-13 16:21:08 -0700494 impl_draw = d->surface;
495 }
496
497 // retrieve the underlying implementation's read EGLSurface
498 if (read != EGL_NO_SURFACE) {
499 r = get_surface(read);
Mathias Agopian518ec112011-05-13 16:21:08 -0700500 impl_read = r->surface;
501 }
502
Mathias Agopian518ec112011-05-13 16:21:08 -0700503
Mathias Agopianfb87e542012-01-30 18:20:52 -0800504 EGLBoolean result = const_cast<egl_display_t*>(dp)->makeCurrent(c, cur_c,
505 draw, read, ctx,
506 impl_draw, impl_read, impl_ctx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700507
508 if (result == EGL_TRUE) {
Mathias Agopianfb87e542012-01-30 18:20:52 -0800509 if (c) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700510 setGLHooksThreadSpecific(c->cnx->hooks[c->version]);
511 egl_tls_t::setContext(ctx);
Siva Velusamy0469dd62011-11-30 15:05:37 -0800512#if EGL_TRACE
513 if (gEGLDebugLevel > 0)
Siva Velusamy93a826f2011-12-14 12:19:56 -0800514 GLTrace_eglMakeCurrent(c->version, c->cnx->hooks[c->version], ctx);
Siva Velusamy0469dd62011-11-30 15:05:37 -0800515#endif
Mathias Agopian518ec112011-05-13 16:21:08 -0700516 _c.acquire();
517 _r.acquire();
518 _d.acquire();
Mathias Agopian518ec112011-05-13 16:21:08 -0700519 } else {
520 setGLHooksThreadSpecific(&gHooksNoContext);
521 egl_tls_t::setContext(EGL_NO_CONTEXT);
522 }
Mathias Agopian5fecea72011-08-25 18:38:24 -0700523 } else {
Steve Blocke6f43dd2012-01-06 19:20:56 +0000524 // this will ALOGE the error
Mathias Agopian5fecea72011-08-25 18:38:24 -0700525 result = setError(c->cnx->egl.eglGetError(), EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700526 }
527 return result;
528}
529
530
531EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx,
532 EGLint attribute, EGLint *value)
533{
534 clearError();
535
536 egl_display_t const * const dp = validate_display(dpy);
537 if (!dp) return EGL_FALSE;
538
Mathias Agopianf0480de2011-11-13 20:50:07 -0800539 ContextRef _c(dp, ctx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700540 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
541
Mathias Agopian518ec112011-05-13 16:21:08 -0700542 egl_context_t * const c = get_context(ctx);
Mathias Agopian7773c432012-02-13 20:06:08 -0800543 return c->cnx->egl.eglQueryContext(
544 dp->disp.dpy, c->context, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -0700545
Mathias Agopian518ec112011-05-13 16:21:08 -0700546}
547
548EGLContext eglGetCurrentContext(void)
549{
550 // could be called before eglInitialize(), but we wouldn't have a context
551 // then, and this function would correctly return EGL_NO_CONTEXT.
552
553 clearError();
554
555 EGLContext ctx = getContext();
556 return ctx;
557}
558
559EGLSurface eglGetCurrentSurface(EGLint readdraw)
560{
561 // could be called before eglInitialize(), but we wouldn't have a context
562 // then, and this function would correctly return EGL_NO_SURFACE.
563
564 clearError();
565
566 EGLContext ctx = getContext();
567 if (ctx) {
568 egl_context_t const * const c = get_context(ctx);
569 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
570 switch (readdraw) {
571 case EGL_READ: return c->read;
572 case EGL_DRAW: return c->draw;
573 default: return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
574 }
575 }
576 return EGL_NO_SURFACE;
577}
578
579EGLDisplay eglGetCurrentDisplay(void)
580{
581 // could be called before eglInitialize(), but we wouldn't have a context
582 // then, and this function would correctly return EGL_NO_DISPLAY.
583
584 clearError();
585
586 EGLContext ctx = getContext();
587 if (ctx) {
588 egl_context_t const * const c = get_context(ctx);
589 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
590 return c->dpy;
591 }
592 return EGL_NO_DISPLAY;
593}
594
595EGLBoolean eglWaitGL(void)
596{
Mathias Agopian518ec112011-05-13 16:21:08 -0700597 clearError();
598
Mathias Agopianada798b2012-02-13 17:09:30 -0800599 egl_connection_t* const cnx = &gEGLImpl;
600 if (!cnx->dso)
601 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
602
603 return cnx->egl.eglWaitGL();
Mathias Agopian518ec112011-05-13 16:21:08 -0700604}
605
606EGLBoolean eglWaitNative(EGLint engine)
607{
Mathias Agopian518ec112011-05-13 16:21:08 -0700608 clearError();
609
Mathias Agopianada798b2012-02-13 17:09:30 -0800610 egl_connection_t* const cnx = &gEGLImpl;
611 if (!cnx->dso)
612 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
613
614 return cnx->egl.eglWaitNative(engine);
Mathias Agopian518ec112011-05-13 16:21:08 -0700615}
616
617EGLint eglGetError(void)
618{
Mathias Agopianada798b2012-02-13 17:09:30 -0800619 EGLint err = EGL_SUCCESS;
620 egl_connection_t* const cnx = &gEGLImpl;
621 if (cnx->dso) {
622 err = cnx->egl.eglGetError();
Mathias Agopian518ec112011-05-13 16:21:08 -0700623 }
Mathias Agopianada798b2012-02-13 17:09:30 -0800624 if (err == EGL_SUCCESS) {
625 err = egl_tls_t::getError();
626 }
627 return err;
Mathias Agopian518ec112011-05-13 16:21:08 -0700628}
629
630// Note: Similar implementations of these functions also exist in
631// gl2.cpp and gl.cpp, and are used by applications that call the
632// exported entry points directly.
633typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) (GLenum target, GLeglImageOES image);
634typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC) (GLenum target, GLeglImageOES image);
635
636static PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES_impl = NULL;
637static PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC glEGLImageTargetRenderbufferStorageOES_impl = NULL;
638
639static void glEGLImageTargetTexture2DOES_wrapper(GLenum target, GLeglImageOES image)
640{
641 GLeglImageOES implImage =
642 (GLeglImageOES)egl_get_image_for_current_context((EGLImageKHR)image);
643 glEGLImageTargetTexture2DOES_impl(target, implImage);
644}
645
646static void glEGLImageTargetRenderbufferStorageOES_wrapper(GLenum target, GLeglImageOES image)
647{
648 GLeglImageOES implImage =
649 (GLeglImageOES)egl_get_image_for_current_context((EGLImageKHR)image);
650 glEGLImageTargetRenderbufferStorageOES_impl(target, implImage);
651}
652
653__eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
654{
655 // eglGetProcAddress() could be the very first function called
656 // in which case we must make sure we've initialized ourselves, this
657 // happens the first time egl_get_display() is called.
658
659 clearError();
660
661 if (egl_init_drivers() == EGL_FALSE) {
662 setError(EGL_BAD_PARAMETER, NULL);
663 return NULL;
664 }
665
Jamie Gennisaca51c02011-11-03 17:42:43 -0700666 // The EGL_ANDROID_blob_cache extension should not be exposed to
667 // applications. It is used internally by the Android EGL layer.
Jamie Gennisc42fcf02011-11-09 15:35:34 -0800668 if (!strcmp(procname, "eglSetBlobCacheFuncsANDROID")) {
Jamie Gennisaca51c02011-11-03 17:42:43 -0700669 return NULL;
670 }
671
Mathias Agopian518ec112011-05-13 16:21:08 -0700672 __eglMustCastToProperFunctionPointerType addr;
673 addr = findProcAddress(procname, sExtentionMap, NELEM(sExtentionMap));
674 if (addr) return addr;
675
Jamie Gennisaca51c02011-11-03 17:42:43 -0700676
Mathias Agopian518ec112011-05-13 16:21:08 -0700677 // this protects accesses to sGLExtentionMap and sGLExtentionSlot
678 pthread_mutex_lock(&sExtensionMapMutex);
679
680 /*
681 * Since eglGetProcAddress() is not associated to anything, it needs
682 * to return a function pointer that "works" regardless of what
683 * the current context is.
684 *
685 * For this reason, we return a "forwarder", a small stub that takes
686 * care of calling the function associated with the context
687 * currently bound.
688 *
689 * We first look for extensions we've already resolved, if we're seeing
690 * this extension for the first time, we go through all our
691 * implementations and call eglGetProcAddress() and record the
692 * result in the appropriate implementation hooks and return the
693 * address of the forwarder corresponding to that hook set.
694 *
695 */
696
697 const String8 name(procname);
698 addr = sGLExtentionMap.valueFor(name);
699 const int slot = sGLExtentionSlot;
700
Steve Blocke6f43dd2012-01-06 19:20:56 +0000701 ALOGE_IF(slot >= MAX_NUMBER_OF_GL_EXTENSIONS,
Mathias Agopian518ec112011-05-13 16:21:08 -0700702 "no more slots for eglGetProcAddress(\"%s\")",
703 procname);
704
Siva Velusamy0469dd62011-11-30 15:05:37 -0800705#if EGL_TRACE
706 gl_hooks_t *debugHooks = GLTrace_getGLHooks();
707#endif
708
Mathias Agopian518ec112011-05-13 16:21:08 -0700709 if (!addr && (slot < MAX_NUMBER_OF_GL_EXTENSIONS)) {
710 bool found = false;
Mathias Agopianada798b2012-02-13 17:09:30 -0800711
712 egl_connection_t* const cnx = &gEGLImpl;
713 if (cnx->dso && cnx->egl.eglGetProcAddress) {
714 found = true;
715 // Extensions are independent of the bound context
Mathias Agopian7773c432012-02-13 20:06:08 -0800716 cnx->hooks[egl_connection_t::GLESv1_INDEX]->ext.extensions[slot] =
717 cnx->hooks[egl_connection_t::GLESv2_INDEX]->ext.extensions[slot] =
Mathias Agopian518ec112011-05-13 16:21:08 -0700718#if EGL_TRACE
Mathias Agopianada798b2012-02-13 17:09:30 -0800719 debugHooks->ext.extensions[slot] =
720 gHooksTrace.ext.extensions[slot] =
Mathias Agopian518ec112011-05-13 16:21:08 -0700721#endif
Mathias Agopianada798b2012-02-13 17:09:30 -0800722 cnx->egl.eglGetProcAddress(procname);
Mathias Agopian518ec112011-05-13 16:21:08 -0700723 }
Mathias Agopianada798b2012-02-13 17:09:30 -0800724
Mathias Agopian518ec112011-05-13 16:21:08 -0700725 if (found) {
726 addr = gExtensionForwarders[slot];
727
728 if (!strcmp(procname, "glEGLImageTargetTexture2DOES")) {
729 glEGLImageTargetTexture2DOES_impl = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)addr;
730 addr = (__eglMustCastToProperFunctionPointerType)glEGLImageTargetTexture2DOES_wrapper;
731 }
732 if (!strcmp(procname, "glEGLImageTargetRenderbufferStorageOES")) {
733 glEGLImageTargetRenderbufferStorageOES_impl = (PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC)addr;
734 addr = (__eglMustCastToProperFunctionPointerType)glEGLImageTargetRenderbufferStorageOES_wrapper;
735 }
736
737 sGLExtentionMap.add(name, addr);
738 sGLExtentionSlot++;
739 }
740 }
741
742 pthread_mutex_unlock(&sExtensionMapMutex);
743 return addr;
744}
745
746EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw)
747{
Mathias Agopian518ec112011-05-13 16:21:08 -0700748 clearError();
749
750 egl_display_t const * const dp = validate_display(dpy);
751 if (!dp) return EGL_FALSE;
752
Mathias Agopianf0480de2011-11-13 20:50:07 -0800753 SurfaceRef _s(dp, draw);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700754 if (!_s.get())
755 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700756
Siva Velusamy0469dd62011-11-30 15:05:37 -0800757#if EGL_TRACE
758 if (gEGLDebugLevel > 0)
759 GLTrace_eglSwapBuffers(dpy, draw);
760#endif
761
Mathias Agopian518ec112011-05-13 16:21:08 -0700762 egl_surface_t const * const s = get_surface(draw);
Mathias Agopianada798b2012-02-13 17:09:30 -0800763 return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface);
Mathias Agopian518ec112011-05-13 16:21:08 -0700764}
765
766EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface,
767 NativePixmapType target)
768{
769 clearError();
770
771 egl_display_t const * const dp = validate_display(dpy);
772 if (!dp) return EGL_FALSE;
773
Mathias Agopianf0480de2011-11-13 20:50:07 -0800774 SurfaceRef _s(dp, surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700775 if (!_s.get())
776 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700777
Mathias Agopian518ec112011-05-13 16:21:08 -0700778 egl_surface_t const * const s = get_surface(surface);
Mathias Agopianada798b2012-02-13 17:09:30 -0800779 return s->cnx->egl.eglCopyBuffers(dp->disp.dpy, s->surface, target);
Mathias Agopian518ec112011-05-13 16:21:08 -0700780}
781
782const char* eglQueryString(EGLDisplay dpy, EGLint name)
783{
784 clearError();
785
786 egl_display_t const * const dp = validate_display(dpy);
787 if (!dp) return (const char *) NULL;
788
789 switch (name) {
790 case EGL_VENDOR:
Mathias Agopian4b9511c2011-11-13 23:52:47 -0800791 return dp->getVendorString();
Mathias Agopian518ec112011-05-13 16:21:08 -0700792 case EGL_VERSION:
Mathias Agopian4b9511c2011-11-13 23:52:47 -0800793 return dp->getVersionString();
Mathias Agopian518ec112011-05-13 16:21:08 -0700794 case EGL_EXTENSIONS:
Mathias Agopian4b9511c2011-11-13 23:52:47 -0800795 return dp->getExtensionString();
Mathias Agopian518ec112011-05-13 16:21:08 -0700796 case EGL_CLIENT_APIS:
Mathias Agopian4b9511c2011-11-13 23:52:47 -0800797 return dp->getClientApiString();
Mathias Agopianada798b2012-02-13 17:09:30 -0800798 case EGL_VERSION_HW_ANDROID:
799 return dp->disp.queryString.version;
Mathias Agopian518ec112011-05-13 16:21:08 -0700800 }
801 return setError(EGL_BAD_PARAMETER, (const char *)0);
802}
803
804
805// ----------------------------------------------------------------------------
806// EGL 1.1
807// ----------------------------------------------------------------------------
808
809EGLBoolean eglSurfaceAttrib(
810 EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
811{
812 clearError();
813
814 egl_display_t const * const dp = validate_display(dpy);
815 if (!dp) return EGL_FALSE;
816
Mathias Agopianf0480de2011-11-13 20:50:07 -0800817 SurfaceRef _s(dp, surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700818 if (!_s.get())
819 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700820
Mathias Agopian518ec112011-05-13 16:21:08 -0700821 egl_surface_t const * const s = get_surface(surface);
822 if (s->cnx->egl.eglSurfaceAttrib) {
823 return s->cnx->egl.eglSurfaceAttrib(
Mathias Agopianada798b2012-02-13 17:09:30 -0800824 dp->disp.dpy, s->surface, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -0700825 }
826 return setError(EGL_BAD_SURFACE, EGL_FALSE);
827}
828
829EGLBoolean eglBindTexImage(
830 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
831{
832 clearError();
833
834 egl_display_t const * const dp = validate_display(dpy);
835 if (!dp) return EGL_FALSE;
836
Mathias Agopianf0480de2011-11-13 20:50:07 -0800837 SurfaceRef _s(dp, surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700838 if (!_s.get())
839 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700840
Mathias Agopian518ec112011-05-13 16:21:08 -0700841 egl_surface_t const * const s = get_surface(surface);
842 if (s->cnx->egl.eglBindTexImage) {
843 return s->cnx->egl.eglBindTexImage(
Mathias Agopianada798b2012-02-13 17:09:30 -0800844 dp->disp.dpy, s->surface, buffer);
Mathias Agopian518ec112011-05-13 16:21:08 -0700845 }
846 return setError(EGL_BAD_SURFACE, EGL_FALSE);
847}
848
849EGLBoolean eglReleaseTexImage(
850 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
851{
852 clearError();
853
854 egl_display_t const * const dp = validate_display(dpy);
855 if (!dp) return EGL_FALSE;
856
Mathias Agopianf0480de2011-11-13 20:50:07 -0800857 SurfaceRef _s(dp, surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700858 if (!_s.get())
859 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700860
Mathias Agopian518ec112011-05-13 16:21:08 -0700861 egl_surface_t const * const s = get_surface(surface);
862 if (s->cnx->egl.eglReleaseTexImage) {
863 return s->cnx->egl.eglReleaseTexImage(
Mathias Agopianada798b2012-02-13 17:09:30 -0800864 dp->disp.dpy, s->surface, buffer);
Mathias Agopian518ec112011-05-13 16:21:08 -0700865 }
866 return setError(EGL_BAD_SURFACE, EGL_FALSE);
867}
868
869EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
870{
871 clearError();
872
873 egl_display_t const * const dp = validate_display(dpy);
874 if (!dp) return EGL_FALSE;
875
876 EGLBoolean res = EGL_TRUE;
Mathias Agopianada798b2012-02-13 17:09:30 -0800877 egl_connection_t* const cnx = &gEGLImpl;
878 if (cnx->dso && cnx->egl.eglSwapInterval) {
879 res = cnx->egl.eglSwapInterval(dp->disp.dpy, interval);
Mathias Agopian518ec112011-05-13 16:21:08 -0700880 }
Mathias Agopianada798b2012-02-13 17:09:30 -0800881
Mathias Agopian518ec112011-05-13 16:21:08 -0700882 return res;
883}
884
885
886// ----------------------------------------------------------------------------
887// EGL 1.2
888// ----------------------------------------------------------------------------
889
890EGLBoolean eglWaitClient(void)
891{
892 clearError();
893
Mathias Agopianada798b2012-02-13 17:09:30 -0800894 egl_connection_t* const cnx = &gEGLImpl;
895 if (!cnx->dso)
896 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
897
898 EGLBoolean res;
899 if (cnx->egl.eglWaitClient) {
900 res = cnx->egl.eglWaitClient();
901 } else {
902 res = cnx->egl.eglWaitGL();
Mathias Agopian518ec112011-05-13 16:21:08 -0700903 }
904 return res;
905}
906
907EGLBoolean eglBindAPI(EGLenum api)
908{
909 clearError();
910
911 if (egl_init_drivers() == EGL_FALSE) {
912 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
913 }
914
915 // bind this API on all EGLs
916 EGLBoolean res = EGL_TRUE;
Mathias Agopianada798b2012-02-13 17:09:30 -0800917 egl_connection_t* const cnx = &gEGLImpl;
918 if (cnx->dso && cnx->egl.eglBindAPI) {
919 res = cnx->egl.eglBindAPI(api);
Mathias Agopian518ec112011-05-13 16:21:08 -0700920 }
921 return res;
922}
923
924EGLenum eglQueryAPI(void)
925{
926 clearError();
927
928 if (egl_init_drivers() == EGL_FALSE) {
929 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
930 }
931
Mathias Agopianada798b2012-02-13 17:09:30 -0800932 egl_connection_t* const cnx = &gEGLImpl;
933 if (cnx->dso && cnx->egl.eglQueryAPI) {
934 return cnx->egl.eglQueryAPI();
Mathias Agopian518ec112011-05-13 16:21:08 -0700935 }
Mathias Agopianada798b2012-02-13 17:09:30 -0800936
Mathias Agopian518ec112011-05-13 16:21:08 -0700937 // or, it can only be OpenGL ES
938 return EGL_OPENGL_ES_API;
939}
940
941EGLBoolean eglReleaseThread(void)
942{
943 clearError();
944
945 // If there is context bound to the thread, release it
Mathias Agopianfb87e542012-01-30 18:20:52 -0800946 egl_display_t::loseCurrent(get_context(getContext()));
Mathias Agopian518ec112011-05-13 16:21:08 -0700947
Mathias Agopianada798b2012-02-13 17:09:30 -0800948 egl_connection_t* const cnx = &gEGLImpl;
949 if (cnx->dso && cnx->egl.eglReleaseThread) {
950 cnx->egl.eglReleaseThread();
Mathias Agopian518ec112011-05-13 16:21:08 -0700951 }
Mathias Agopianada798b2012-02-13 17:09:30 -0800952
Mathias Agopian518ec112011-05-13 16:21:08 -0700953 egl_tls_t::clearTLS();
Siva Velusamy0469dd62011-11-30 15:05:37 -0800954#if EGL_TRACE
955 if (gEGLDebugLevel > 0)
956 GLTrace_eglReleaseThread();
957#endif
Mathias Agopian518ec112011-05-13 16:21:08 -0700958 return EGL_TRUE;
959}
960
961EGLSurface eglCreatePbufferFromClientBuffer(
962 EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer,
963 EGLConfig config, const EGLint *attrib_list)
964{
965 clearError();
966
967 egl_display_t const* dp = 0;
968 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
969 if (!cnx) return EGL_FALSE;
970 if (cnx->egl.eglCreatePbufferFromClientBuffer) {
971 return cnx->egl.eglCreatePbufferFromClientBuffer(
Mathias Agopian7773c432012-02-13 20:06:08 -0800972 dp->disp.dpy, buftype, buffer, config, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700973 }
974 return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE);
975}
976
977// ----------------------------------------------------------------------------
978// EGL_EGLEXT_VERSION 3
979// ----------------------------------------------------------------------------
980
981EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface,
982 const EGLint *attrib_list)
983{
984 clearError();
985
986 egl_display_t const * const dp = validate_display(dpy);
987 if (!dp) return EGL_FALSE;
988
Mathias Agopianf0480de2011-11-13 20:50:07 -0800989 SurfaceRef _s(dp, surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700990 if (!_s.get())
991 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700992
993 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian518ec112011-05-13 16:21:08 -0700994 if (s->cnx->egl.eglLockSurfaceKHR) {
995 return s->cnx->egl.eglLockSurfaceKHR(
Mathias Agopianada798b2012-02-13 17:09:30 -0800996 dp->disp.dpy, s->surface, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700997 }
998 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
999}
1000
1001EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface)
1002{
1003 clearError();
1004
1005 egl_display_t const * const dp = validate_display(dpy);
1006 if (!dp) return EGL_FALSE;
1007
Mathias Agopianf0480de2011-11-13 20:50:07 -08001008 SurfaceRef _s(dp, surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001009 if (!_s.get())
1010 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001011
1012 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian518ec112011-05-13 16:21:08 -07001013 if (s->cnx->egl.eglUnlockSurfaceKHR) {
Mathias Agopianada798b2012-02-13 17:09:30 -08001014 return s->cnx->egl.eglUnlockSurfaceKHR(dp->disp.dpy, s->surface);
Mathias Agopian518ec112011-05-13 16:21:08 -07001015 }
1016 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1017}
1018
1019EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
1020 EGLClientBuffer buffer, const EGLint *attrib_list)
1021{
1022 clearError();
1023
1024 egl_display_t const * const dp = validate_display(dpy);
1025 if (!dp) return EGL_NO_IMAGE_KHR;
1026
1027 if (ctx != EGL_NO_CONTEXT) {
Mathias Agopianf0480de2011-11-13 20:50:07 -08001028 ContextRef _c(dp, ctx);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001029 if (!_c.get())
1030 return setError(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
Mathias Agopian518ec112011-05-13 16:21:08 -07001031 egl_context_t * const c = get_context(ctx);
1032 // since we have an EGLContext, we know which implementation to use
1033 EGLImageKHR image = c->cnx->egl.eglCreateImageKHR(
Mathias Agopianada798b2012-02-13 17:09:30 -08001034 dp->disp.dpy, c->context, target, buffer, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001035 if (image == EGL_NO_IMAGE_KHR)
1036 return image;
1037
1038 egl_image_t* result = new egl_image_t(dpy, ctx);
Mathias Agopianada798b2012-02-13 17:09:30 -08001039 result->image = image;
Mathias Agopian518ec112011-05-13 16:21:08 -07001040 return (EGLImageKHR)result;
1041 } else {
1042 // EGL_NO_CONTEXT is a valid parameter
1043
1044 /* Since we don't have a way to know which implementation to call,
1045 * we're calling all of them. If at least one of the implementation
1046 * succeeded, this is a success.
1047 */
1048
1049 EGLint currentError = eglGetError();
1050
Mathias Agopianada798b2012-02-13 17:09:30 -08001051 EGLImageKHR implImage = EGL_NO_IMAGE_KHR;
1052 egl_connection_t* const cnx = &gEGLImpl;
1053 if (cnx->dso && cnx->egl.eglCreateImageKHR) {
1054 implImage = cnx->egl.eglCreateImageKHR(
1055 dp->disp.dpy, ctx, target, buffer, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001056 }
1057
Mathias Agopianada798b2012-02-13 17:09:30 -08001058 if (implImage == EGL_NO_IMAGE_KHR) {
Mathias Agopian518ec112011-05-13 16:21:08 -07001059 // failure, if there was an error when we entered this function,
1060 // the error flag must not be updated.
1061 // Otherwise, the error is whatever happened in the implementation
1062 // that faulted.
1063 if (currentError != EGL_SUCCESS) {
1064 setError(currentError, EGL_NO_IMAGE_KHR);
1065 }
1066 return EGL_NO_IMAGE_KHR;
1067 } else {
1068 // In case of success, we need to clear all error flags
1069 // (especially those caused by the implementation that didn't
Mathias Agopianada798b2012-02-13 17:09:30 -08001070 // succeed).
Mathias Agopian518ec112011-05-13 16:21:08 -07001071 eglGetError();
1072 }
1073
1074 egl_image_t* result = new egl_image_t(dpy, ctx);
Mathias Agopianada798b2012-02-13 17:09:30 -08001075 result->image = implImage;
Mathias Agopian518ec112011-05-13 16:21:08 -07001076 return (EGLImageKHR)result;
1077 }
1078}
1079
1080EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
1081{
1082 clearError();
1083
1084 egl_display_t const * const dp = validate_display(dpy);
1085 if (!dp) return EGL_FALSE;
1086
Mathias Agopianf0480de2011-11-13 20:50:07 -08001087 ImageRef _i(dp, img);
Mathias Agopian518ec112011-05-13 16:21:08 -07001088 if (!_i.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1089
1090 egl_image_t* image = get_image(img);
1091 bool success = false;
Mathias Agopianada798b2012-02-13 17:09:30 -08001092
1093 egl_connection_t* const cnx = &gEGLImpl;
1094 if (image->image != EGL_NO_IMAGE_KHR) {
1095 if (cnx->dso && cnx->egl.eglDestroyImageKHR) {
1096 if (cnx->egl.eglDestroyImageKHR(
1097 dp->disp.dpy, image->image)) {
1098 success = true;
Mathias Agopian518ec112011-05-13 16:21:08 -07001099 }
1100 }
1101 }
Mathias Agopianada798b2012-02-13 17:09:30 -08001102
Mathias Agopian518ec112011-05-13 16:21:08 -07001103 if (!success)
1104 return EGL_FALSE;
1105
1106 _i.terminate();
1107
1108 return EGL_TRUE;
1109}
1110
1111// ----------------------------------------------------------------------------
1112// EGL_EGLEXT_VERSION 5
1113// ----------------------------------------------------------------------------
1114
1115
1116EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
1117{
1118 clearError();
1119
1120 egl_display_t const * const dp = validate_display(dpy);
1121 if (!dp) return EGL_NO_SYNC_KHR;
1122
1123 EGLContext ctx = eglGetCurrentContext();
Mathias Agopianf0480de2011-11-13 20:50:07 -08001124 ContextRef _c(dp, ctx);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001125 if (!_c.get())
1126 return setError(EGL_BAD_CONTEXT, EGL_NO_SYNC_KHR);
1127
Mathias Agopian518ec112011-05-13 16:21:08 -07001128 egl_context_t * const c = get_context(ctx);
1129 EGLSyncKHR result = EGL_NO_SYNC_KHR;
1130 if (c->cnx->egl.eglCreateSyncKHR) {
1131 EGLSyncKHR sync = c->cnx->egl.eglCreateSyncKHR(
Mathias Agopianada798b2012-02-13 17:09:30 -08001132 dp->disp.dpy, type, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001133 if (sync == EGL_NO_SYNC_KHR)
1134 return sync;
1135 result = (egl_sync_t*)new egl_sync_t(dpy, ctx, sync);
1136 }
1137 return (EGLSyncKHR)result;
1138}
1139
1140EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
1141{
1142 clearError();
1143
1144 egl_display_t const * const dp = validate_display(dpy);
1145 if (!dp) return EGL_FALSE;
1146
Mathias Agopianf0480de2011-11-13 20:50:07 -08001147 SyncRef _s(dp, sync);
Mathias Agopian518ec112011-05-13 16:21:08 -07001148 if (!_s.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1149 egl_sync_t* syncObject = get_sync(sync);
1150
1151 EGLContext ctx = syncObject->context;
Mathias Agopianf0480de2011-11-13 20:50:07 -08001152 ContextRef _c(dp, ctx);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001153 if (!_c.get())
1154 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001155
1156 EGLBoolean result = EGL_FALSE;
1157 egl_context_t * const c = get_context(ctx);
1158 if (c->cnx->egl.eglDestroySyncKHR) {
1159 result = c->cnx->egl.eglDestroySyncKHR(
Mathias Agopianada798b2012-02-13 17:09:30 -08001160 dp->disp.dpy, syncObject->sync);
Mathias Agopian518ec112011-05-13 16:21:08 -07001161 if (result)
1162 _s.terminate();
1163 }
1164 return result;
1165}
1166
1167EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout)
1168{
1169 clearError();
1170
1171 egl_display_t const * const dp = validate_display(dpy);
1172 if (!dp) return EGL_FALSE;
1173
Mathias Agopianf0480de2011-11-13 20:50:07 -08001174 SyncRef _s(dp, sync);
Mathias Agopian518ec112011-05-13 16:21:08 -07001175 if (!_s.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1176 egl_sync_t* syncObject = get_sync(sync);
1177
1178 EGLContext ctx = syncObject->context;
Mathias Agopianf0480de2011-11-13 20:50:07 -08001179 ContextRef _c(dp, ctx);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001180 if (!_c.get())
1181 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001182
1183 egl_context_t * const c = get_context(ctx);
Mathias Agopian518ec112011-05-13 16:21:08 -07001184 if (c->cnx->egl.eglClientWaitSyncKHR) {
1185 return c->cnx->egl.eglClientWaitSyncKHR(
Mathias Agopianada798b2012-02-13 17:09:30 -08001186 dp->disp.dpy, syncObject->sync, flags, timeout);
Mathias Agopian518ec112011-05-13 16:21:08 -07001187 }
1188
1189 return EGL_FALSE;
1190}
1191
1192EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value)
1193{
1194 clearError();
1195
1196 egl_display_t const * const dp = validate_display(dpy);
1197 if (!dp) return EGL_FALSE;
1198
Mathias Agopianf0480de2011-11-13 20:50:07 -08001199 SyncRef _s(dp, sync);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001200 if (!_s.get())
1201 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001202
Mathias Agopian5b287a62011-05-16 18:58:55 -07001203 egl_sync_t* syncObject = get_sync(sync);
Mathias Agopian518ec112011-05-13 16:21:08 -07001204 EGLContext ctx = syncObject->context;
Mathias Agopianf0480de2011-11-13 20:50:07 -08001205 ContextRef _c(dp, ctx);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001206 if (!_c.get())
1207 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001208
1209 egl_context_t * const c = get_context(ctx);
Mathias Agopian518ec112011-05-13 16:21:08 -07001210 if (c->cnx->egl.eglGetSyncAttribKHR) {
1211 return c->cnx->egl.eglGetSyncAttribKHR(
Mathias Agopianada798b2012-02-13 17:09:30 -08001212 dp->disp.dpy, syncObject->sync, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -07001213 }
1214
1215 return EGL_FALSE;
1216}
1217
1218// ----------------------------------------------------------------------------
1219// ANDROID extensions
1220// ----------------------------------------------------------------------------
1221
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001222/* ANDROID extensions entry-point go here */
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001223
1224// ----------------------------------------------------------------------------
1225// NVIDIA extensions
1226// ----------------------------------------------------------------------------
1227EGLuint64NV eglGetSystemTimeFrequencyNV()
1228{
1229 clearError();
1230
1231 if (egl_init_drivers() == EGL_FALSE) {
1232 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1233 }
1234
1235 EGLuint64NV ret = 0;
Mathias Agopianada798b2012-02-13 17:09:30 -08001236 egl_connection_t* const cnx = &gEGLImpl;
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001237
Mathias Agopianada798b2012-02-13 17:09:30 -08001238 if (cnx->dso && cnx->egl.eglGetSystemTimeFrequencyNV) {
1239 return cnx->egl.eglGetSystemTimeFrequencyNV();
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001240 }
1241
Mathias Agopian0e8bbee2011-10-05 19:15:05 -07001242 return setErrorQuiet(EGL_BAD_DISPLAY, 0);
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001243}
1244
1245EGLuint64NV eglGetSystemTimeNV()
1246{
1247 clearError();
1248
1249 if (egl_init_drivers() == EGL_FALSE) {
1250 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1251 }
1252
1253 EGLuint64NV ret = 0;
Mathias Agopianada798b2012-02-13 17:09:30 -08001254 egl_connection_t* const cnx = &gEGLImpl;
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001255
Mathias Agopianada798b2012-02-13 17:09:30 -08001256 if (cnx->dso && cnx->egl.eglGetSystemTimeNV) {
1257 return cnx->egl.eglGetSystemTimeNV();
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001258 }
1259
Mathias Agopian0e8bbee2011-10-05 19:15:05 -07001260 return setErrorQuiet(EGL_BAD_DISPLAY, 0);
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001261}